/* //////////////////////////////////////////////////////////////////////////////////////
* check
*/
static tb_bool_t check_memset_u8(tb_byte_t* dst, tb_uint8_t src, tb_size_t size)
{
tb_uint8_t* p = (tb_uint8_t*)dst;
tb_uint8_t* e = p + size;
while (p < e)
{
if (*p != src) return tb_false;
p++;
}
return tb_true;
}
static tb_bool_t check_memset_u16(tb_byte_t* dst, tb_uint16_t src, tb_size_t size)
{
tb_uint16_t* p = (tb_uint16_t*)dst;
tb_uint16_t* e = p + size;
while (p < e)
{
if (*p != src) return tb_false;
p++;
}
return tb_true;
}
static tb_bool_t check_memset_u24(tb_byte_t* dst, tb_uint32_t src, tb_size_t size)
{
tb_byte_t* p = (tb_byte_t*)dst;
tb_byte_t* e = p + (size * 3);
while (p < e)
{
if ((*((tb_uint32_t*)p) & 0xffffff) != (src & 0xffffff)) return tb_false;
p += 3;
}
return tb_true;
}
static tb_bool_t check_memset_u32(tb_byte_t* dst, tb_uint32_t src, tb_size_t size)
{
tb_uint32_t* p = (tb_uint32_t*)dst;
tb_uint32_t* e = p + size;
while (p < e)
{
if (*p != src) return tb_false;
p++;
}
return tb_true;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_memory_memops_main(tb_int_t argc, tb_char_t** argv)
{
// init
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_hong_t dt = 0;
tb_size_t size = 15 * 1024 * 1024;
tb_byte_t* data = tb_malloc_bytes(size);
tb_size_t size2 = 15 * 1024 * 1024;
tb_byte_t* data2 = tb_malloc_bytes(size2);
// test: u8 x 1024
memset(data, 0, size);
dt = tb_mclock();
for (i = 0; i < 1000000; i++) tb_memset(data, 0xbe, 1024 + 3);
dt = tb_mclock() - dt;
tb_printf("memset[1k]: %lld ms\n", dt);
if (!check_memset_u8(data, 0xbe, 1024 + 3)) tb_printf("check failed\n");
// test: u8 x 1024 * 1024
memset(data, 0, size);
dt = tb_mclock();
for (i = 0; i < 1000; i++) tb_memset(data, 0xbe, 1024 * 1024 + 3);
dt = tb_mclock() - dt;
tb_printf("memset[1m]: %lld ms\n", dt);
if (!check_memset_u8(data, 0xbe, 1024 * 1024 + 3)) tb_printf("check failed\n");
// test: u8 x 1024
memset(data2, 0, size2);
dt = tb_mclock();
for (i = 0; i < 1000000; i++) tb_memcpy(data2, data, 1024 + 3);
dt = tb_mclock() - dt;
tb_printf("memcpy[1k]: %lld ms\n", dt);
if (!check_memset_u8(data2, 0xbe, 1024 + 3)) tb_printf("check failed\n");
// test: u8 x 1024 * 1024
memset(data2, 0, size2);
dt = tb_mclock();
for (i = 0; i < 1000; i++) tb_memcpy(data2, data, 1024 * 1024 + 3);
dt = tb_mclock() - dt;
tb_printf("memcpy[1m]: %lld ms\n", dt);
if (!check_memset_u8(data2, 0xbe, 1024 * 1024 + 3)) tb_printf("check failed\n");
// test: u8 x 1024
dt = tb_mclock();
for (i = 0; i < 1000000; i++) tb_memmov(data + 1024 + 3, data, 1024 + 3);
dt = tb_mclock() - dt;
tb_printf("memmov[1k]: %lld ms\n", dt);
if (!check_memset_u8(data + 1024 + 3, 0xbe, 1024 + 3)) tb_printf("check failed\n");
// test: u8 x 1024 * 1024
dt = tb_mclock();
for (i = 0; i < 1000; i++) tb_memmov(data + 1024 * 1024 + 3, data, 1024 * 1024 + 3);
dt = tb_mclock() - dt;
tb_printf("memmov[1m]: %lld ms\n", dt);
if (!check_memset_u8(data + 1024 * 1024 + 3, 0xbe, 1024 * 1024 + 3)) tb_printf("check failed\n");
// test: u16 x 1024
memset(data, 0, size);
dt = tb_mclock();
for (i = 0; i < 1000000; i++) tb_memset_u16(data, 0xbeef, 1024 + 3);
dt = tb_mclock() - dt;
tb_printf("memset_u16[1k]: %lld ms\n", dt);
if (!check_memset_u16(data, 0xbeef, 1024 + 3)) tb_printf("check failed\n");
// test: u16 x 1024 * 1024
memset(data, 0, size);
dt = tb_mclock();
for (i = 0; i < 1000; i++) tb_memset_u16(data, 0xbeef, 1024 * 1024 + 3);
dt = tb_mclock() - dt;
tb_printf("memset_u16[1m]: %lld ms\n", dt);
if (!check_memset_u16(data, 0xbeef, 1024 * 1024 + 3)) tb_printf("check failed\n");
// test: u24 x 1024
memset(data, 0, size);
dt = tb_mclock();
for (i = 0; i < 1000000; i++) tb_memset_u24(data, 0xbeefaa, 1024 + 3);
dt = tb_mclock() - dt;
tb_printf("memset_u24[1k]: %lld ms\n", dt);
if (!check_memset_u24(data, 0xbeefaa, 1024 + 3)) tb_printf("check failed\n");
// test: u24 x 1024 * 1024
memset(data, 0, size);
dt = tb_mclock();
for (i = 0; i < 1000; i++) tb_memset_u24(data, 0xbeefaa, 1024 * 1024 + 3);
dt = tb_mclock() - dt;
tb_printf("memset_u24[1m]: %lld ms\n", dt);
if (!check_memset_u24(data, 0xbeefaa, 1024 * 1024 + 3)) tb_printf("check failed\n");
// test: u32 x 1024
memset(data, 0, size);
dt = tb_mclock();
for (i = 0; i < 1000000; i++) tb_memset_u32(data, 0xbeefbeaf, 1024 + 3);
dt = tb_mclock() - dt;
tb_printf("memset_u32[1k]: %lld ms\n", dt);
if (!check_memset_u32(data, 0xbeefbeaf, 1024 + 3)) tb_printf("check failed\n");
// test: u32 x 1024 * 1024
memset(data, 0, size);
dt = tb_mclock();
for (i = 0; i < 1000; i++) tb_memset_u32(data, 0xbeefbeaf, 1024 * 1024 + 3);
dt = tb_mclock() - dt;
tb_printf("memset_u32[1m]: %lld ms\n", dt);
if (!check_memset_u32(data, 0xbeefbeaf, 1024 * 1024 + 3)) tb_printf("check failed\n");
return 0;
}
tbox-1.7.6/src/demo/memory/queue_buffer.c 0000664 0000000 0000000 00000001274 14671175054 0020363 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_memory_queue_buffer_main(tb_int_t argc, tb_char_t** argv)
{
tb_char_t d[1024];
tb_queue_buffer_t b;
tb_queue_buffer_init(&b, 1024);
tb_queue_buffer_writ(&b, (tb_byte_t const*)"hello", 5);
tb_queue_buffer_writ(&b, (tb_byte_t const*)" ", 1);
tb_queue_buffer_writ(&b, (tb_byte_t const*)"world", 6);
tb_queue_buffer_read(&b, (tb_byte_t*)d, 1024);
tb_trace_i("%s", d);
tb_queue_buffer_exit(&b);
return 0;
}
tbox-1.7.6/src/demo/memory/small_allocator.c 0000664 0000000 0000000 00000014753 14671175054 0021064 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* demo
*/
tb_void_t tb_demo_small_allocator_leak(tb_noarg_t);
tb_void_t tb_demo_small_allocator_leak()
{
// done
tb_allocator_ref_t small_allocator = tb_null;
do
{
// init small allocator
small_allocator = tb_small_allocator_init(tb_null);
tb_assert_and_check_break(small_allocator);
// make data0
tb_pointer_t data0 = tb_allocator_malloc(small_allocator, 10);
tb_assert_and_check_break(data0);
// make data1
tb_pointer_t data1 = tb_allocator_malloc(small_allocator, 10);
tb_assert_and_check_break(data1);
#ifdef __tb_debug__
// dump small_allocator
tb_allocator_dump(small_allocator);
#endif
} while (0);
// exit small allocator
if (small_allocator) tb_allocator_exit(small_allocator);
small_allocator = tb_null;
}
tb_void_t tb_demo_small_allocator_free2(tb_noarg_t);
tb_void_t tb_demo_small_allocator_free2()
{
// done
tb_allocator_ref_t small_allocator = tb_null;
do
{
// init small allocator
small_allocator = tb_small_allocator_init(tb_null);
tb_assert_and_check_break(small_allocator);
// make data
tb_pointer_t data = tb_allocator_malloc(small_allocator, 10);
tb_assert_and_check_break(data);
// exit data
tb_allocator_free(small_allocator, data);
tb_allocator_free(small_allocator, data);
#ifdef __tb_debug__
// dump small_allocator
tb_allocator_dump(small_allocator);
#endif
} while (0);
// exit small allocator
if (small_allocator) tb_allocator_exit(small_allocator);
small_allocator = tb_null;
}
tb_void_t tb_demo_small_allocator_underflow(tb_noarg_t);
tb_void_t tb_demo_small_allocator_underflow()
{
// done
tb_allocator_ref_t small_allocator = tb_null;
do
{
// init small allocator
small_allocator = tb_small_allocator_init(tb_null);
tb_assert_and_check_break(small_allocator);
// make data
tb_pointer_t data = tb_allocator_malloc(small_allocator, 10);
tb_assert_and_check_break(data);
// done underflow
tb_memset(data, 0, 10 + 1);
// exit data
tb_allocator_free(small_allocator, data);
#ifdef __tb_debug__
// dump small_allocator
tb_allocator_dump(small_allocator);
#endif
} while (0);
// exit small allocator
if (small_allocator) tb_allocator_exit(small_allocator);
small_allocator = tb_null;
}
tb_void_t tb_demo_small_allocator_underflow2(tb_noarg_t);
tb_void_t tb_demo_small_allocator_underflow2()
{
// done
tb_allocator_ref_t small_allocator = tb_null;
do
{
// init small allocator
small_allocator = tb_small_allocator_init(tb_null);
tb_assert_and_check_break(small_allocator);
// make data
tb_pointer_t data = tb_allocator_malloc(small_allocator, 10);
tb_assert_and_check_break(data);
// done underflow
tb_memset(data, 0, 10 + 1);
// make data2
data = tb_allocator_malloc(small_allocator, 10);
tb_assert_and_check_break(data);
#ifdef __tb_debug__
// dump small_allocator
tb_allocator_dump(small_allocator);
#endif
} while (0);
// exit small allocator
if (small_allocator) tb_allocator_exit(small_allocator);
small_allocator = tb_null;
}
tb_void_t tb_demo_small_allocator_perf(tb_noarg_t);
tb_void_t tb_demo_small_allocator_perf()
{
// done
tb_allocator_ref_t small_allocator = tb_null;
tb_allocator_ref_t large_allocator = tb_null;
do
{
// init small allocator
small_allocator = tb_small_allocator_init(tb_null);
tb_assert_and_check_break(small_allocator);
// init large allocator
large_allocator = tb_large_allocator_init(tb_null, 0);
tb_assert_and_check_break(large_allocator);
// make data list
tb_size_t maxn = 100000;
tb_pointer_t* list = (tb_pointer_t*)tb_allocator_large_nalloc0(large_allocator, maxn, sizeof(tb_pointer_t), tb_null);
tb_assert_and_check_break(list);
// done
__tb_volatile__ tb_size_t indx = 0;
__tb_volatile__ tb_hong_t time = tb_mclock();
__tb_volatile__ tb_size_t rand = 0xbeaf;
for (indx = 0; indx < maxn; indx++)
{
// make data
list[indx] = tb_allocator_malloc0(small_allocator, (rand & 3071) + 1);
tb_assert_and_check_break(list[indx]);
// make rand
rand = (rand * 10807 + 1) & 0xffffffff;
// re-make data
if (!(indx & 31))
{
list[indx] = tb_allocator_ralloc(small_allocator, list[indx], (rand & 3071) + 1);
tb_assert_and_check_break(list[indx]);
}
// free data
__tb_volatile__ tb_size_t size = rand & 15;
if (size > 5 && indx)
{
size -= 5;
while (size--)
{
// the free index
tb_size_t free_indx = rand % indx;
// free it
if (list[free_indx]) tb_allocator_free(small_allocator, list[free_indx]);
list[free_indx] = tb_null;
}
}
}
time = tb_mclock() - time;
#ifdef __tb_debug__
// dump small_allocator
tb_allocator_dump(small_allocator);
#endif
// trace
tb_trace_i("time: %lld ms", time);
// clear small_allocator
tb_allocator_clear(small_allocator);
// exit list
tb_allocator_large_free(large_allocator, list);
} while (0);
// exit small allocator
if (small_allocator) tb_allocator_exit(small_allocator);
small_allocator = tb_null;
// exit large allocator
if (large_allocator) tb_allocator_exit(large_allocator);
large_allocator = tb_null;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_memory_small_allocator_main(tb_int_t argc, tb_char_t** argv)
{
#if 1
tb_demo_small_allocator_perf();
#endif
#if 0
tb_demo_small_allocator_leak();
#endif
#if 0
tb_demo_small_allocator_free2();
#endif
#if 0
tb_demo_small_allocator_underflow();
#endif
#if 0
tb_demo_small_allocator_underflow2();
#endif
return 0;
}
tbox-1.7.6/src/demo/memory/static_buffer.c 0000664 0000000 0000000 00000001170 14671175054 0020521 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_memory_static_buffer_main(tb_int_t argc, tb_char_t** argv)
{
tb_byte_t data[1024];
tb_static_buffer_t b;
tb_static_buffer_init(&b, data, 1024);
tb_static_buffer_memncpy(&b, (tb_byte_t const*)"hello ", 6);
tb_static_buffer_memncat(&b, (tb_byte_t const*)"world", 6);
tb_trace_i("%s", tb_static_buffer_data(&b));
tb_static_buffer_exit(&b);
return 0;
}
tbox-1.7.6/src/demo/memory/string_pool.c 0000664 0000000 0000000 00000001764 14671175054 0020251 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_memory_string_pool_main(tb_int_t argc, tb_char_t** argv)
{
#if 0
// hello
tb_char_t const* hello = tb_string_pool_insert(tb_string_pool(), "hello world");
tb_trace_i("hello: %s", hello);
// performance
tb_char_t s[256] = {0};
tb_hong_t t = tb_mclock();
__tb_volatile__ tb_size_t n = 1000000;
while (n--)
{
tb_int_t r = tb_snprintf(s, 256, "%u", tb_random_range(0, 10000));
s[r] = '\0';
#if 1
tb_string_pool_insert(tb_string_pool(), s);
if (!(n & 15)) tb_string_pool_remove(tb_string_pool(), s);
#else
tb_free(tb_strdup(s));
#endif
}
t = tb_mclock() - t;
tb_trace_i("time: %lld", t);
// del hello
tb_string_pool_remove(tb_string_pool(), hello);
#endif
return 0;
}
tbox-1.7.6/src/demo/micro.c 0000664 0000000 0000000 00000006311 14671175054 0015504 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the main item
#define TB_DEMO_MAIN_ITEM(name) { #name, tb_demo_##name##_main }
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the demo type
typedef struct __tb_demo_t
{
// the demo name
tb_char_t const* name;
// the demo main
tb_int_t (*main)(tb_int_t argc, tb_char_t** argv);
}tb_demo_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
// the demos
static tb_demo_t g_demo[] =
{
// libc
TB_DEMO_MAIN_ITEM(libc_stdlib)
// utils
, TB_DEMO_MAIN_ITEM(utils_bits)
// other
, TB_DEMO_MAIN_ITEM(other_test)
// platform
, TB_DEMO_MAIN_ITEM(platform_addrinfo)
// container
, TB_DEMO_MAIN_ITEM(container_list_entry)
, TB_DEMO_MAIN_ITEM(container_single_list_entry)
#ifdef TB_CONFIG_MODULE_HAVE_COROUTINE
// stackless coroutine
, TB_DEMO_MAIN_ITEM(lo_coroutine_nest)
, TB_DEMO_MAIN_ITEM(lo_coroutine_lock)
, TB_DEMO_MAIN_ITEM(lo_coroutine_sleep)
, TB_DEMO_MAIN_ITEM(lo_coroutine_switch)
, TB_DEMO_MAIN_ITEM(lo_coroutine_echo_server)
, TB_DEMO_MAIN_ITEM(lo_coroutine_echo_client)
, TB_DEMO_MAIN_ITEM(lo_coroutine_file_server)
, TB_DEMO_MAIN_ITEM(lo_coroutine_file_client)
, TB_DEMO_MAIN_ITEM(lo_coroutine_http_server)
#endif
};
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t main(tb_int_t argc, tb_char_t** argv)
{
// init tbox
#if (defined(__tb_valgrind__) && defined(TB_CONFIG_VALGRIND_HAVE_VALGRIND_STACK_REGISTER)) \
|| defined(__tb_sanitize_address__) || defined(__tb_sanitize_thread__)
if (!tb_init(tb_null, tb_native_allocator())) return -1;
#else
if (!tb_init(tb_null, tb_static_allocator((tb_byte_t*)malloc(1024 * 1024), 1024 * 1024))) return -1;
#endif
// find the main func from the first argument
tb_int_t ok = 0;
tb_char_t const* name = tb_null;
if (argc > 1 && argv[1])
{
tb_size_t i = 0;
tb_size_t n = tb_arrayn(g_demo);
for (i = 0; i < n; i++)
{
// find it?
if (g_demo[i].name && !tb_stricmp(g_demo[i].name, argv[1]))
{
// save name
name = g_demo[i].name;
// done main
ok = g_demo[i].main(argc - 1, argv + 1);
break;
}
}
}
// no this demo? help it
if (!name)
{
tb_trace_i("======================================================================");
tb_trace_i("Usages: xmake r demo [testname] arguments ...");
tb_trace_i("");
tb_trace_i(".e.g");
tb_trace_i(" xmake r demo stream http://www.xxxxx.com /tmp/a");
tb_trace_i("");
// walk name
tb_size_t i = 0;
tb_size_t n = tb_arrayn(g_demo);
for (i = 0; i < n; i++) tb_trace_i("testname: %s", g_demo[i].name);
}
// exit tbox
tb_exit();
// ok?
return ok;
}
tbox-1.7.6/src/demo/micro.lua 0000664 0000000 0000000 00000001716 14671175054 0016047 0 ustar 00root root 0000000 0000000
-- add target
target("demo")
-- add the dependent target
add_deps("tbox")
-- make as a binary
set_kind("binary")
-- add defines
add_defines("__tb_prefix__=\"demo\"")
-- add the source file
add_files("micro.c")
add_files("libc/stdlib.c")
add_files("utils/bits.c")
add_files("other/test.c")
add_files("platform/addrinfo.c")
add_files("container/list_entry.c")
add_files("container/single_list_entry.c")
-- add the source files for coroutine
if has_config("coroutine") then
add_files("coroutine/stackless/*.c|process.c")
end
-- enable xp compatibility mode
if is_plat("windows") then
if is_arch("x86") then
add_ldflags("/subsystem:console,5.01")
else
add_ldflags("/subsystem:console,5.02")
end
end
-- link mingw/libgcc
if is_plat("mingw", "msys", "cygwin") then
add_ldflags("-static-libgcc", {force = true})
end
tbox-1.7.6/src/demo/network/ 0000775 0000000 0000000 00000000000 14671175054 0015717 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/demo/network/cookies.c 0000664 0000000 0000000 00000005662 14671175054 0017530 0 ustar 00root root 0000000 0000000 #include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_network_cookies_main(tb_int_t argc, tb_char_t** argv)
{
// set cookies
tb_cookies_set(tb_cookies(), "www.baidu.com", "/", tb_false, "HttpOnly;Secure");
tb_cookies_set(tb_cookies(), tb_null, tb_null, tb_false, "BAIDUID=0; max-age=946080000; expires=Sat, 06-Apr-41 03:21:53 GMT; domain=.baidu.com; path=/");
tb_cookies_set(tb_cookies(), tb_null, tb_null, tb_true, "FG=1; max-age=946080000; expires=Sat, 06-Apr-2017 03:21:53 GMT; domain=.baidu.com; path=/; version=1");
tb_cookies_set(tb_cookies(), tb_null, tb_null, tb_false, "BAIDUID=2; max-age=946080000; expires=Sat, 06-Apr-2016 03:21:53 GMT; domain=.baidu.com; path=/style; version=1");
tb_cookies_set(tb_cookies(), tb_null, tb_null, tb_false, "BG=3; expires=Wednesday, 09-Nov-99 23:12:40 GMT; domain=.space.baidu.com; path=/");
tb_cookies_set(tb_cookies(), tb_null, tb_null, tb_false, "BAIDSID=4; expires=Wednesday, 09-Nov-99 23:12:40 GMT; domain=.baidu.com; path=/style/foo");
tb_cookies_set(tb_cookies(), tb_null, tb_null, tb_false, "pvid=3317093836; path=/; domain=qq.com; expires=Sun, 18 Jan 2038 00:00:00 GMT;");
tb_cookies_set(tb_cookies(), tb_null, tb_null, tb_false, "clientuin=; EXPIRES=Fri, 02-Jan-1970 00:00:00 GMT; PATH=/; DOMAIN=qq.com;");
tb_cookies_set_from_url(tb_cookies(), "http://mail.163.com:2000/WorldClient.dll?View=Main", "User=wangrq; Expires=Tue, 19-Apr-2015 07:10:56 GMT; path=/");
tb_cookies_set_from_url(tb_cookies(), "http://mail.163.com:2000/WorldClient.dll?View=Main", "Session=Yz9eJRh6QijR; path=/");
tb_cookies_set_from_url(tb_cookies(), "http://mail.163.com:2000/WorldClient.dll?View=Main", "Lang=zh; Expires=Tue, 19-Apr-2015 07:10:56 GMT; path=/");
tb_cookies_set_from_url(tb_cookies(), "http://mail.163.com:2000/WorldClient.dll?View=Main", "Theme=Standard; Expires=Tue, 19-Apr-2015 07:10:56 GMT; path=/");
// get cookies
tb_string_t value;
tb_string_init(&value);
tb_trace_i("%s", tb_cookies_get_from_url(tb_cookies(), "http://www.space.baidu.com/style/foo/login.css", &value));
tb_trace_i("%s", tb_cookies_get_from_url(tb_cookies(), "http://www.baidu.com/style/foo/login.css", &value));
tb_trace_i("%s", tb_cookies_get_from_url(tb_cookies(), "http://www.baidu.com/style", &value));
tb_trace_i("%s", tb_cookies_get_from_url(tb_cookies(), "http://www.baidu.com", &value));
tb_trace_i("%s", tb_cookies_get_from_url(tb_cookies(), "https://www.baidu.com/", &value));
tb_trace_i("%s", tb_cookies_get_from_url(tb_cookies(), "http://pingfore.qq.com/pingd?dm=qzone.qq.com&url=login/qzone_n&tt=-&rdm=-&rurl=-&pvid=7466815060&scr=-&scl=-&lang=-&java=1&cc=-&pf=-&tz=-8&ct=-&vs=3.3&emu=0.20486706611700356", &value));
tb_trace_i("%s", tb_cookies_get_from_url(tb_cookies(), "http://mail.163.com:2000/?Session=LZBMQVW&View=Menu", &value));
tb_string_exit(&value);
return 0;
}
tbox-1.7.6/src/demo/network/dns.c 0000664 0000000 0000000 00000021574 14671175054 0016660 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define TB_DNS_TEST_INVALID_HOST (0)
#define TB_DNS_TEST_MORE_HOST (0)
#define TB_DNS_TEST_HOST_SOME (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* test
*/
static tb_void_t tb_dns_test_done(tb_char_t const* name)
{
tb_ipaddr_t addr;
tb_hong_t time = tb_mclock();
if (tb_dns_looker_done(name, &addr))
{
time = tb_mclock() - time;
tb_trace_i("lookup: %s => %{ipaddr}, %lld ms", name, &addr, time);
}
else tb_trace_i("lookup: %s failed", name);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_network_dns_main(tb_int_t argc, tb_char_t** argv)
{
// test the invalid host
#if TB_DNS_TEST_INVALID_HOST
// add not dns host
tb_dns_server_add("127.0.0.1");
// add not ipv4 host
tb_dns_server_add("localhost");
#endif
// test the more host
#if TB_DNS_TEST_MORE_HOST
tb_dns_server_add("2001:470:20::2");
tb_dns_server_add("fec0:0:0:ffff::1%1");
tb_dns_server_add("205.252.144.228");
tb_dns_server_add("208.151.69.65");
tb_dns_server_add("202.181.202.140");
tb_dns_server_add("202.181.224.2");
tb_dns_server_add("202.175.3.8");
tb_dns_server_add("202.175.3.3");
tb_dns_server_add("168.95.192.1");
tb_dns_server_add("168.95.1.1");
tb_dns_server_add("208.67.222.222");
tb_dns_server_add("205.171.2.65");
tb_dns_server_add("193.0.14.129");
tb_dns_server_add("202.12.27.33");
tb_dns_server_add("202.216.228.18");
tb_dns_server_add("209.166.160.132");
tb_dns_server_add("208.96.10.221");
tb_dns_server_add("61.144.56.101");
tb_dns_server_add("202.101.98.55");
tb_dns_server_add("202.96.128.166");
tb_dns_server_add("202.96.209.134");
tb_dns_server_add("221.12.65.228");
#endif
// sort
tb_dns_server_sort();
// dump
#ifdef __tb_debug__
tb_dns_server_dump();
#endif
#if TB_DNS_TEST_HOST_SOME
tb_hong_t time = tb_mclock();
tb_dns_test_done("www.tboox.org");
tb_dns_test_done("www.tboox.net");
tb_dns_test_done("www.baidu.com");
tb_dns_test_done("www.google.com");
tb_dns_test_done("www.google.com.hk");
tb_dns_test_done("www.csdn.net");
tb_dns_test_done("www.qq.com");
tb_dns_test_done("www.youku.com");
tb_dns_test_done("www.ibm.com");
tb_dns_test_done("www.sina.com.cn");
tb_dns_test_done("www.hao123.com");
tb_dns_test_done("www.sohu.com");
tb_dns_test_done("www.weibo.com");
tb_dns_test_done("www.126.com");
tb_dns_test_done("www.163.com");
tb_dns_test_done("www.taobao.com");
tb_dns_test_done("www.microsoft.com");
tb_dns_test_done("www.qiyi.com");
tb_dns_test_done("www.xunlei.com");
tb_dns_test_done("www.360buy.com");
tb_dns_test_done("www.tudou.com");
tb_dns_test_done("www.pps.tv");
tb_dns_test_done("www.yahoo.com");
tb_dns_test_done("www.zol.com.cn");
tb_dns_test_done("www.download.com");
tb_dns_test_done("www.webkit.org");
tb_dns_test_done("www.douban.com");
tb_dns_test_done("www.github.com");
tb_dns_test_done("www.videolan.org");
tb_dns_test_done("www.net.cn");
tb_dns_test_done("www.yahoo.com");
tb_dns_test_done("www.sina.com.cn");
tb_dns_test_done("www.hao123.com");
tb_dns_test_done("www.sohu.com");
tb_dns_test_done("www.weibo.com");
tb_dns_test_done("www.126.com");
tb_dns_test_done("www.163.com");
tb_dns_test_done("www.taobao.com");
tb_dns_test_done("www.microsoft.com");
tb_dns_test_done("www.qiyi.com");
tb_dns_test_done("www.xunlei.com");
tb_dns_test_done("www.360buy.com");
tb_dns_test_done("www.tudou.com");
tb_dns_test_done("www.pps.tv");
tb_dns_test_done("www.yahoo.com");
tb_dns_test_done("www.zol.com.cn");
tb_dns_test_done("www.download.com");
tb_dns_test_done("www.webkit.org");
tb_dns_test_done("www.huaxiazi.com");
tb_dns_test_done("www.facebook.com");
tb_dns_test_done("www.youtube.com");
tb_dns_test_done("www.bing.com");
tb_dns_test_done("www.baidu.com");
tb_dns_test_done("www.tianya.com");
tb_dns_test_done("www.adobe.com");
tb_dns_test_done("web2.qq.com");
tb_dns_test_done("www.bluehost.com");
tb_dns_test_done("www.pediy.com");
tb_dns_test_done("www.wordpress.com");
tb_dns_test_done("www.gitorious.org");
tb_dns_test_done("t.qq.com");
tb_dns_test_done("www.wordpress.com");
tb_dns_test_done("www.mop.com");
tb_dns_test_done("www.56.com");
tb_dns_test_done("www.joy.com.cn");
tb_dns_test_done("www.xxxxx.com");
tb_dns_test_done("www.wordpress.com");
tb_dns_test_done("developer.android.com");
tb_dns_test_done("developer.apple.com");
tb_dns_test_done("www.arm.com");
tb_dns_test_done("www.nginx.com");
tb_dns_test_done("www.ted.com");
tb_dns_test_done("www.tboox.org");
tb_dns_test_done("www.tboox.net");
tb_dns_test_done("www.baidu.com");
tb_dns_test_done("www.google.com");
tb_dns_test_done("www.google.com.hk");
tb_dns_test_done("www.csdn.net");
tb_dns_test_done("www.qq.com");
tb_dns_test_done("www.youku.com");
tb_dns_test_done("www.ibm.com");
tb_dns_test_done("www.sina.com.cn");
tb_dns_test_done("www.hao123.com");
tb_dns_test_done("www.sohu.com");
tb_dns_test_done("www.weibo.com");
tb_dns_test_done("www.126.com");
tb_dns_test_done("www.163.com");
tb_dns_test_done("www.taobao.com");
tb_dns_test_done("www.microsoft.com");
tb_dns_test_done("www.qiyi.com");
tb_dns_test_done("www.xunlei.com");
tb_dns_test_done("www.360buy.com");
tb_dns_test_done("www.tudou.com");
tb_dns_test_done("www.pps.tv");
tb_dns_test_done("www.yahoo.com");
tb_dns_test_done("www.zol.com.cn");
tb_dns_test_done("www.download.com");
tb_dns_test_done("www.webkit.org");
tb_dns_test_done("www.douban.com");
tb_dns_test_done("www.github.com");
tb_dns_test_done("www.videolan.org");
tb_dns_test_done("www.net.cn");
tb_dns_test_done("www.yahoo.com");
tb_dns_test_done("www.sina.com.cn");
tb_dns_test_done("www.hao123.com");
tb_dns_test_done("www.sohu.com");
tb_dns_test_done("www.weibo.com");
tb_dns_test_done("www.126.com");
tb_dns_test_done("www.163.com");
tb_dns_test_done("www.taobao.com");
tb_dns_test_done("www.microsoft.com");
tb_dns_test_done("www.qiyi.com");
tb_dns_test_done("www.xunlei.com");
tb_dns_test_done("www.360buy.com");
tb_dns_test_done("www.tudou.com");
tb_dns_test_done("www.pps.tv");
tb_dns_test_done("www.yahoo.com");
tb_dns_test_done("www.zol.com.cn");
tb_dns_test_done("www.download.com");
tb_dns_test_done("www.webkit.org");
tb_dns_test_done("www.huaxiazi.com");
tb_dns_test_done("www.facebook.com");
tb_dns_test_done("www.youtube.com");
tb_dns_test_done("www.bing.com");
tb_dns_test_done("www.baidu.com");
tb_dns_test_done("www.tianya.com");
tb_dns_test_done("www.adobe.com");
tb_dns_test_done("web2.qq.com");
tb_dns_test_done("www.bluehost.com");
tb_dns_test_done("www.pediy.com");
tb_dns_test_done("www.wordpress.com");
tb_dns_test_done("www.gitorious.org");
tb_dns_test_done("t.qq.com");
tb_dns_test_done("www.wordpress.com");
tb_dns_test_done("www.mop.com");
tb_dns_test_done("www.56.com");
tb_dns_test_done("www.joy.com.cn");
tb_dns_test_done("www.xxxxx.com");
tb_dns_test_done("www.wordpress.com");
tb_dns_test_done("developer.android.com");
tb_dns_test_done("developer.apple.com");
tb_dns_test_done("www.arm.com");
tb_dns_test_done("www.nginx.com");
tb_dns_test_done("www.ted.com");
tb_dns_test_done("www.mcu-memory.com");
tb_dns_test_done("mail.126.com");
tb_dns_test_done("mail.163.com");
tb_dns_test_done("mail.google.com");
tb_dns_test_done("mail.qq.com");
tb_dns_test_done("mail.sina.com");
tb_dns_test_done("mail.sohu.com");
tb_dns_test_done("mail.qq.com");
tb_dns_test_done("www.renren.com");
tb_dns_test_done("www.cepark.com");
tb_dns_test_done("www.ifttt.com");
tb_dns_test_done("www.china-pub.com");
tb_dns_test_done("www.amazon.com");
tb_dns_test_done("www.amazon.cn");
tb_dns_test_done("www.2688.com");
tb_dns_test_done("www.mtime.com");
tb_dns_test_done("hi.baidu.com");
tb_dns_test_done("repo.or.cz");
tb_dns_test_done("www.ifeng.com");
tb_dns_test_done("www.sourceforge.com");
tb_dns_test_done("www.wikipedia.org");
tb_dns_test_done("baike.baidu.com");
tb_dns_test_done("www.ted.com");
tb_dns_test_done("www.ted.com");
tb_dns_test_done("www.ted.com");
time = tb_mclock() - time;
tb_trace_i("[demo]: done %lld ms", time);
#else
tb_dns_test_done(argv[1]);
#endif
return 0;
}
tbox-1.7.6/src/demo/network/http.c 0000664 0000000 0000000 00000007033 14671175054 0017045 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_bool_t tb_http_demo_head_func(tb_char_t const* line, tb_cpointer_t priv)
{
// check
tb_assert_and_check_return_val(line, tb_false);
// trace
tb_trace_i("head: %s", line);
// ok
return tb_true;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_network_http_main(tb_int_t argc, tb_char_t** argv)
{
// done
tb_http_ref_t http = tb_null;
do
{
// init http
http = tb_http_init();
tb_assert_and_check_break(http);
// init cookies
if (!tb_http_ctrl(http, TB_HTTP_OPTION_SET_COOKIES, tb_cookies())) break;
// init head func
if (!tb_http_ctrl(http, TB_HTTP_OPTION_SET_HEAD_FUNC, tb_http_demo_head_func)) break;
// init url
if (!tb_http_ctrl(http, TB_HTTP_OPTION_SET_URL, argv[1])) break;
// init head
// if (!tb_http_ctrl(http, TB_HTTP_OPTION_SET_HEAD, "Connection", "keep-alive")) break;
// init post
if (argv[2])
{
// init post url
if (!tb_http_ctrl(http, TB_HTTP_OPTION_SET_POST_URL, argv[2])) break;
// init method
if (!tb_http_ctrl(http, TB_HTTP_OPTION_SET_METHOD, TB_HTTP_METHOD_POST)) break;
}
// init timeout
tb_size_t timeout = 0;
// if (!tb_http_ctrl(http, TB_HTTP_OPTION_SET_TIMEOUT, 10000)) break;
if (!tb_http_ctrl(http, TB_HTTP_OPTION_GET_TIMEOUT, &timeout)) break;
// init redirect maxn
// if (!tb_http_ctrl(http, TB_HTTP_OPTION_SET_REDIRECT, 0)) break;
// open http
tb_hong_t t = tb_mclock();
if (!tb_http_open(http)) break;
t = tb_mclock() - t;
tb_trace_i("open: %llu ms", t);
// read data
tb_byte_t data[8192];
tb_size_t read = 0;
tb_hize_t size = tb_http_status(http)->content_size;
do
{
// read data
tb_long_t real = tb_http_read(http, data, 8192);
tb_trace_i("read: %d", real);
if (real > 0)
{
// dump data
tb_char_t const* p = (tb_char_t const*)data;
tb_char_t const* e = (tb_char_t const*)data + real;
tb_char_t b[8192 + 1];
while (p < e && *p)
{
tb_char_t* q = b;
tb_char_t const* d = b + 4096;
for (; q < d && p < e && *p; p++, q++) *q = *p;
*q = '\0';
tb_printf("%s", b);
}
tb_printf("\n");
// save read
read += real;
}
else if (!real)
{
// wait
tb_trace_i("wait");
tb_long_t e = tb_http_wait(http, TB_SOCKET_EVENT_RECV, timeout);
tb_assert_and_check_break(e >= 0);
// timeout?
tb_check_break(e);
// has read?
tb_assert_and_check_break(e & TB_SOCKET_EVENT_RECV);
}
else break;
// is end?
if (size && read >= size) break;
} while (1);
} while (0);
// exit http
if (http) tb_http_exit(http);
// end
return 0;
}
tbox-1.7.6/src/demo/network/hwaddr.c 0000664 0000000 0000000 00000000774 14671175054 0017344 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_network_hwaddr_main(tb_int_t argc, tb_char_t** argv)
{
// done
tb_hwaddr_t addr;
tb_hwaddr_clear(&addr);
if (tb_hwaddr_cstr_set(&addr, argv[1]))
{
// trace
tb_trace_i("%s => %{hwaddr}", argv[1], &addr);
}
return 0;
}
tbox-1.7.6/src/demo/network/impl/ 0000775 0000000 0000000 00000000000 14671175054 0016660 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/demo/network/impl/date.c 0000664 0000000 0000000 00000002250 14671175054 0017740 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../../demo.h"
#include "../../../tbox/network/impl/http/date.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* test
*/
static tb_void_t tb_demo_test_date(tb_char_t const* cstr)
{
tb_tm_t date = {0};
if (tb_gmtime(tb_http_date_from_cstr(cstr, tb_strlen(cstr)), &date))
{
tb_trace_i("%s => %04ld-%02ld-%02ld %02ld:%02ld:%02ld GMT, week: %d"
, cstr
, date.year
, date.month
, date.mday
, date.hour
, date.minute
, date.second
, date.week);
}
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_network_impl_date_main(tb_int_t argc, tb_char_t** argv)
{
tb_demo_test_date("Sun, 06 Nov 1994 08:49:37 GMT");
tb_demo_test_date("Sun Nov 6 08:49:37 1994");
tb_demo_test_date("Sun, 06-Nov-1994 08:49:37 GMT");
tb_demo_test_date("Mon, 19 May 2014 07:21:56 GMT");
tb_demo_test_date("Thu, 31-Dec-37 23:55:55 GMT");
return 0;
}
tbox-1.7.6/src/demo/network/ipaddr.c 0000664 0000000 0000000 00000001026 14671175054 0017325 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_network_ipaddr_main(tb_int_t argc, tb_char_t** argv)
{
// done
tb_ipaddr_t addr;
tb_ipaddr_clear(&addr);
if (tb_ipaddr_ip_cstr_set(&addr, argv[1], TB_IPADDR_FAMILY_NONE))
{
// trace
tb_trace_i("%s => %{ipaddr}", argv[1], &addr);
}
return 0;
}
tbox-1.7.6/src/demo/network/ipv4.c 0000664 0000000 0000000 00000000744 14671175054 0016752 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_network_ipv4_main(tb_int_t argc, tb_char_t** argv)
{
// done
tb_ipv4_t ipv4;
if (tb_ipv4_cstr_set(&ipv4, argv[1]))
{
// trace
tb_trace_i("%s => %{ipv4}", argv[1], &ipv4);
}
// end
return 0;
}
tbox-1.7.6/src/demo/network/ipv6.c 0000664 0000000 0000000 00000000744 14671175054 0016754 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_network_ipv6_main(tb_int_t argc, tb_char_t** argv)
{
// done
tb_ipv6_t ipv6;
if (tb_ipv6_cstr_set(&ipv6, argv[1]))
{
// trace
tb_trace_i("%s => %{ipv6}", argv[1], &ipv6);
}
// end
return 0;
}
tbox-1.7.6/src/demo/network/ping.c 0000664 0000000 0000000 00000014574 14671175054 0017033 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define TB_ICMP_ECHOREPLY (0)
#define TB_ICMP_ECHOREQ (8)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
#include "tbox/prefix/packed.h"
// the ip header type - rfc791
typedef struct __tb_ip_header_t
{
// version and ihl
tb_uint8_t vihl;
// type of service
tb_uint8_t tos;
// total length of the packet
tb_uint16_t total_len;
// unique identifier
tb_uint16_t id;
// flags and fragment offset
tb_uint16_t frag_and_flags;
// time to live
tb_uint8_t ttl;
// the protocol, tcp, udp, ..
tb_uint8_t proto;
// the checksum
tb_uint16_t checksum;
// the source ipaddr
tb_uint32_t source_ip;
// the dest ipaddr
tb_uint32_t dest_ip;
} __tb_packed__ tb_ip_header_t;
// the icmp header type - rfc792
typedef struct __tb_icmp_header_t
{
// icmp type
tb_uint8_t type;
// type sub code
tb_uint8_t code;
// checksum
tb_uint16_t checksum;
// identifier
tb_uint16_t id;
// sequence numner
tb_uint16_t seq;
// data
tb_byte_t data[1];
} __tb_packed__ tb_icmp_header_t;
// the icmp echo request type
typedef struct __tb_icmp_echo_request_t
{
// the icmp header
tb_icmp_header_t icmp;
// the request time
tb_uint64_t time;
} __tb_packed__ tb_icmp_echo_request_t;
// the icmp echo reply type
typedef struct __tb_icmp_echo_reply_t
{
// the ip header
tb_ip_header_t ip;
// the echo request
tb_icmp_echo_request_t request;
} __tb_packed__ tb_icmp_echo_reply_t;
#include "tbox/prefix/packed.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_uint16_t tb_calculate_checksum(tb_byte_t const* data, tb_long_t size)
{
// calculate sum
tb_uint32_t sum = 0;
tb_long_t nleft = size;
tb_byte_t const* p = data;
while (nleft > 1)
{
sum += tb_bits_get_u16_le(p);
nleft -= 2;
p += 2;
}
// calculate answer
tb_uint16_t answer = 0;
if (nleft == 1)
{
*(tb_byte_t *)(&answer) = *p;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return answer;
}
static tb_bool_t tb_ping_send(tb_socket_ref_t sock, tb_ipaddr_ref_t addr, tb_uint16_t seq)
{
// init echo
tb_icmp_echo_request_t echo;
tb_uint64_t time = tb_mclock();
echo.icmp.type = TB_ICMP_ECHOREQ;
echo.icmp.code = 0;
tb_bits_set_u16_le((tb_byte_t*)&echo.icmp.checksum, 0);
tb_bits_set_u16_le((tb_byte_t*)&echo.icmp.id, 0xbeaf);
tb_bits_set_u16_le((tb_byte_t*)&echo.icmp.seq, seq);
tb_bits_set_u64_le((tb_byte_t*)&echo.time, time);
tb_uint16_t checksum = tb_calculate_checksum((tb_byte_t const*)&echo, sizeof(echo));
tb_bits_set_u16_le((tb_byte_t*)&echo.icmp.checksum, checksum);
// send echo
tb_long_t send = 0;
tb_long_t size = sizeof(echo);
tb_bool_t wait = tb_false;
tb_byte_t const* data = (tb_byte_t const*)&echo;
while (send < size)
{
tb_long_t real = tb_socket_usend(sock, addr, data + send, size - send);
if (real > 0)
{
send += real;
wait = tb_false;
}
else if (!real && !wait)
{
wait = tb_true;
real = tb_socket_wait(sock, TB_SOCKET_EVENT_SEND, -1);
tb_assert_and_check_break(real > 0);
}
else break;
}
// ok?
return send == size;
}
static tb_bool_t tb_ping_recv(tb_socket_ref_t sock, tb_uint16_t seq)
{
// recv echo
tb_icmp_echo_reply_t echo;
tb_long_t recv = 0;
tb_long_t size = sizeof(echo);
tb_bool_t wait = tb_false;
tb_byte_t* data = (tb_byte_t*)&echo;
while (recv < size)
{
tb_long_t real = tb_socket_urecv(sock, tb_null, data + recv, size - recv);
if (real > 0)
{
recv += real;
wait = tb_false;
}
else if (!real && !wait)
{
wait = tb_true;
real = tb_socket_wait(sock, TB_SOCKET_EVENT_RECV, -1);
tb_assert_and_check_break(real > 0);
}
else break;
}
tb_assert_and_check_return_val(recv == size, tb_false);
// check protocol (icmp)
tb_assert_and_check_return_val(echo.ip.proto == 1, tb_false);
// check icmp type
tb_assert_and_check_return_val(echo.request.icmp.type == TB_ICMP_ECHOREPLY, tb_false);
// check id
tb_assert_and_check_return_val(tb_bits_get_u16_le((tb_byte_t const*)&echo.request.icmp.id) == 0xbeaf, tb_false);
// get source ip address
tb_ipv4_t source_ip;
source_ip.u32 = tb_bits_get_u32_le((tb_byte_t const*)&echo.ip.source_ip);
// trace
tb_uint64_t time = tb_bits_get_u64_le((tb_byte_t const*)&echo.request.time);
tb_trace_i("%ld bytes from %{ipv4}: icmp_seq=%d ttl=%d time=%ld ms", size, &source_ip, seq, echo.ip.ttl, tb_mclock() - (tb_hong_t)time);
// ok
return tb_true;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_network_ping_main(tb_int_t argc, tb_char_t** argv)
{
// check
tb_assert_and_check_return_val(argc == 2 && argv[1], -1);
// init addr
tb_ipaddr_t addr;
if (!tb_dns_looker_done(argv[1], &addr)) return -1;
// init socket
tb_socket_ref_t sock = tb_socket_init(TB_SOCKET_TYPE_ICMP, TB_IPADDR_FAMILY_IPV4);
if (sock)
{
// trace
tb_trace_i("PING %s (%{ipv4}): %d data bytes", argv[1], tb_ipaddr_ipv4(&addr), sizeof(tb_icmp_echo_request_t));
// send ping
tb_uint16_t i = 0;
tb_uint16_t n = 10;
while (i < n && tb_ping_send(sock, &addr, i))
{
// recv ping
if (!tb_ping_recv(sock, i)) break;
i++;
// wait some time
tb_sleep(1);
}
// exit socket
tb_socket_exit(sock);
}
return 0;
}
tbox-1.7.6/src/demo/network/unix_echo_client.c 0000664 0000000 0000000 00000004030 14671175054 0021377 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// timeout
#define TB_DEMO_TIMEOUT (-1)
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_network_unix_echo_client_main(tb_int_t argc, tb_char_t** argv)
{
// check
tb_assert_and_check_return_val(argc == 2, -1);
// done
tb_socket_ref_t sock = tb_null;
do
{
// init socket
sock = tb_socket_init(TB_SOCKET_TYPE_TCP, TB_IPADDR_FAMILY_UNIX);
tb_assert_and_check_break(sock);
tb_bool_t is_abstract = argv[1][0] == '@';
tb_char_t* path = is_abstract? argv[1] + 1 : argv[1];
// init address
tb_ipaddr_t addr;
tb_ipaddr_unix_set_cstr(&addr, path, is_abstract);
// trace
tb_trace_i("connecting(%p): %{ipaddr} %s..", sock, &addr, is_abstract? "(abstract)" : "");
// connect socket
tb_long_t ok;
while (!(ok = tb_socket_connect(sock, &addr)))
{
// wait it
if (tb_socket_wait(sock, TB_SOCKET_EVENT_CONN, TB_DEMO_TIMEOUT) <= 0) break;
}
// connect ok?
tb_check_break(ok > 0);
// loop
tb_byte_t data[8192] = {0};
tb_long_t count = 10000;
while (count--)
{
// send data
if (tb_socket_bsend(sock, (tb_byte_t const*)"hello world..", 13))
{
// recv data
if (!tb_socket_brecv(sock, data, 13))
{
// error
tb_trace_e("send error!");
break;
}
}
else break;
}
// trace
tb_trace_d("send(%p): %s %s", sock, data, count <= 0? "ok" : "failed");
} while (0);
// exit socket
if (sock) tb_socket_exit(sock);
sock = tb_null;
return 0;
} tbox-1.7.6/src/demo/network/unix_echo_server.c 0000664 0000000 0000000 00000004710 14671175054 0021434 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// timeout
#define TB_DEMO_TIMEOUT (-1)
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_network_unix_echo_server_main(tb_int_t argc, tb_char_t** argv)
{
// check
tb_assert_and_check_return_val(argc == 2, -1);
// get path
tb_bool_t is_abstract = argv[1][0] == '@';
tb_char_t* path = is_abstract? argv[1] + 1 : argv[1];
// done
tb_socket_ref_t sock = tb_null;
do
{
// init socket
sock = tb_socket_init(TB_SOCKET_TYPE_TCP, TB_IPADDR_FAMILY_UNIX);
tb_assert_and_check_break(sock);
if (!is_abstract)
{
// clear old socket
tb_file_remove(path);
}
// bind socket
tb_ipaddr_t addr;
tb_ipaddr_unix_set_cstr(&addr, path, is_abstract);
if (!tb_socket_bind(sock, &addr)) break;
// listen socket
if (!tb_socket_listen(sock, 1000)) break;
// trace
tb_trace_i("listening %{ipaddr} %s..", &addr, is_abstract? "(abstract)" : "");
// accept client sockets
tb_socket_ref_t client = tb_null;
while (1)
{
// accept and start client connection
if ((client = tb_socket_accept(sock, tb_null)))
{
// loop
tb_byte_t data[8192] = {0};
tb_size_t size = 13;
while (1)
{
// recv data
if (tb_socket_brecv(client, data, size))
{
// send data
if (!tb_socket_bsend(client, data, size))
{
// error
tb_trace_e("send error!");
break;
}
}
else break;
}
// trace
tb_trace_d("echo: %s", data);
// exit socket
tb_socket_exit(client);
}
else if (tb_socket_wait(sock, TB_SOCKET_EVENT_ACPT, -1) <= 0) break;
}
} while(0);
// exit socket
if (sock) tb_socket_exit(sock);
sock = tb_null;
return 0;
}
tbox-1.7.6/src/demo/network/unixaddr.c 0000664 0000000 0000000 00000001012 14671175054 0017673 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_network_unixaddr_main(tb_int_t argc, tb_char_t** argv)
{
// done
tb_unixaddr_t unixaddr;
if (tb_unixaddr_cstr_set(&unixaddr, argv[1], tb_false))
{
// trace
tb_trace_i("%s => %{unixaddr}", argv[1], &unixaddr);
}
// end
return 0;
}
tbox-1.7.6/src/demo/network/url.c 0000664 0000000 0000000 00000010435 14671175054 0016670 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* test
*/
static tb_void_t tb_url_test_set(tb_char_t const* url)
{
tb_url_t u;
tb_url_init(&u);
if (tb_url_cstr_set(&u, url))
{
tb_trace_i("=================================================");
tb_trace_i("irl: %s", url);
tb_trace_i("orl: %s", tb_url_cstr(&u));
tb_trace_i("poto: %s", tb_url_protocol_cstr(&u));
tb_trace_i("port: %u", tb_url_port(&u));
tb_trace_i("host: %s", tb_url_host(&u));
tb_trace_i("path: %s", tb_url_path(&u));
tb_trace_i("args: %s", tb_url_args(&u));
}
else tb_trace_i("invalid url: %s", url);
tb_url_exit(&u);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_network_url_main(tb_int_t argc, tb_char_t** argv)
{
tb_url_test_set("data://VGhlIFRyZWFzdXJlIEJveCBMaWJyYXJ5Cgo=");
tb_url_test_set("file:///home/ruki/file.txt");
tb_url_test_set("sock://localhost:8080");
tb_url_test_set("sock://localhost:8080/ruki/file.txt");
tb_url_test_set("rtsp://localhost:8080");
tb_url_test_set("rtsp://localhost:8080/ruki/file.txt");
tb_url_test_set("http://localhost");
tb_url_test_set("http://localhost:80");
tb_url_test_set("http://localhost:8080");
tb_url_test_set("http://localhost/ruki/file.txt");
tb_url_test_set("http://localhost:8080/ruki/file.txt");
tb_url_test_set("http://[::1]:8080/ruki/file.txt");
tb_url_test_set("http://[fe80::7a31:c1ff:fecf:e8ae%en0]:8080/ruki/file.txt");
tb_url_test_set("http://[fe80::7a31:c1ff:fecf:e8ae%7]:8080/ruki/file.txt");
tb_url_test_set("socks://localhost:8080");
tb_url_test_set("socks://localhost:8080/ruki/file.txt");
tb_url_test_set("https://localhost");
tb_url_test_set("https://localhost:80");
tb_url_test_set("https://localhost:8080");
tb_url_test_set("https://localhost/ruki/file.txt");
tb_url_test_set("https://localhost:443/ruki/file.txt");
tb_url_test_set("https://localhost:8080/ruki/file.txt");
tb_url_test_set("https://localhost:8080/ruki/file.txt/#/hello");
tb_url_test_set("https://github.githubassets.com/#start-of-content");
tb_url_test_set("file:///home/ruki/file.txt?");
tb_url_test_set("sock://localhost:8080?udp=");
tb_url_test_set("sock://localhost:8080/ruki/file.txt?proto=tcp");
tb_url_test_set("http://localhost?=");
tb_url_test_set("http://127.0.0.1:8080?ssl=true");
tb_url_test_set("http://localhost/ruki/file.txt?arg0=11111&arg1=222222");
tb_url_test_set("http://localhost:8080/ruki/file.txt?xxxx&sds");
tb_url_test_set("http://vcode.baidu.com/genimage?00140254475301668D95A071A0C29E7F10FD51CA7F1548CF49B02D47F821146A1F7A4154B649D30D2E4FE5B24AD645EAA0D957938A0E838D854084A77B3589F7E0E6784E9919C2178A5978F8CA51E878E1DB3B84C7D2BE5E4BC145811FEC7DBE6E17DB25931A00F0A31E45A7C476FF8209BD9DDD6824D89D8E0EC7260FE53F4B412FC67D161DE6FEFC3F884E079170A1A8085629B84AED10352DCAA946D80EDCBB04A664936CAB0DDC585110D11D2747C27260EF6CD44648");
tb_url_test_set("http://中文.中文");
tb_url_test_set("FILE:///HOME/RUKI/FILE.TXT?");
tb_url_test_set("SOCK://LOCALHOST:8080?UDP=");
tb_url_test_set("SOCK://LOCALHOST:8080/RUKI/FILE.TXT?PROTO=TCP");
tb_url_test_set("HTTP://LOCALHOST?=");
tb_url_test_set("HTTP://127.0.0.1:8080?SSL=TRUE");
tb_url_test_set("HTTP://LOCALHOST/RUKI/FILE.TXT?ARG0=11111&ARG1=222222");
tb_url_test_set("HTTP://LOCALHOST:8080/RUKI/FILE.TXT?XXXX&SDS");
tb_url_test_set("sql://localhost/?type=mysql&user=xxxx&pwd=xxxx");
tb_url_test_set("sql://localhost:3306/?type=mysql&user=xxxx&pwd=xxxx&database=xxxx");
tb_url_test_set("Sql:///home/file.sqlite3?type=sqlite3");
tb_url_test_set("C:/HOME/RUKI/FILE.TXT");
tb_url_test_set("d:/home/ruki/file.txt");
tb_url_test_set("d:\\home\\ruki\\file.txt");
tb_url_test_set("/home/ruki/file.txt");
tb_url_test_set("ruki/file.txt");
tb_url_test_set("./ruki/file.txt");
tb_url_test_set("../ruki/file.txt");
tb_url_test_set("../../ruki/file.txt");
tb_url_test_set("..\\..\\ruki\\file.txt");
tb_url_test_set("../../ruki/../file.txt");
return 0;
}
tbox-1.7.6/src/demo/network/whois.c 0000664 0000000 0000000 00000026476 14671175054 0017233 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define TB_WHOIS_TEST_HOST_WALK (1)
/* //////////////////////////////////////////////////////////////////////////////////////
* test
*/
#if !TB_WHOIS_TEST_HOST_WALK
static tb_void_t tb_whois_test_done(tb_char_t const* name)
{
// init
// tb_stream_ref_t stream = tb_stream_init_from_url("sock://whois.internic.net:43");
tb_stream_ref_t stream = tb_stream_init_from_url("sock://199.7.51.74:43");
// tb_stream_ref_t stream = tb_stream_init_from_url("sock://whois.cnnic.net.cn:43");
tb_assert_and_check_return(stream);
// timeout
tb_stream_ctrl(stream, TB_STREAM_CTRL_SET_TIMEOUT, 1000);
// data
tb_char_t data[251] = {0};
// open
if (tb_stream_open(stream))
{
tb_stream_printf(stream, "%s \r\n", name);
tb_stream_sync(stream, tb_true);
tb_stream_bread(stream, data, 250);
tb_trace_i("%s", data);
}
// exit
tb_stream_exit(stream);
}
#else
static tb_bool_t tb_whois_test_no_match_com(tb_char_t const* name)
{
// init
// tb_stream_ref_t stream = tb_stream_init_from_url("sock://whois.internic.net:43");
tb_stream_ref_t stream = tb_stream_init_from_url("sock://199.7.51.74:43");
tb_assert_and_check_return_val(stream, tb_false);
// timeout
tb_stream_ctrl(stream, TB_STREAM_CTRL_SET_TIMEOUT, 1000);
// data
tb_char_t data[251] = {0};
// open
if (tb_stream_open(stream))
{
tb_stream_printf(stream, "%s \r\n", name);
tb_stream_sync(stream, tb_true);
tb_stream_bread(stream, (tb_byte_t*)data, 250);
if (tb_strstr(data + 150, "No match")) return tb_true;
}
// exit
tb_stream_exit(stream);
return tb_false;
}
static tb_bool_t tb_whois_test_no_match_cn(tb_char_t const* name)
{
// init
// tb_stream_ref_t stream = tb_stream_init_from_url("sock://whois.cnnic.net.cn:43");
tb_stream_ref_t stream = tb_stream_init_from_url("sock://218.241.97.14:43");
tb_assert_and_check_return_val(stream, tb_false);
// timeout
tb_stream_ctrl(stream, TB_STREAM_CTRL_SET_TIMEOUT, 1000);
// data
tb_char_t data[21] = {0};
// open
if (tb_stream_open(stream))
{
tb_stream_printf(stream, "%s \r\n", name);
tb_stream_sync(stream, tb_true);
tb_stream_bread(stream, (tb_byte_t*)data, 20);
if (tb_strstr(data, "no matching")) return tb_true;
}
// exit
tb_stream_exit(stream);
return tb_false;
}
static tb_void_t tb_whois_test_walk_2()
{
// table
tb_char_t const* t = "abcdefghijklmnopqrstuvwxyz";
tb_char_t p[] = {'w', 'w', 'w', '.', 'x', 'x', '.', 'c', 'o', 'm', '\0'};
// walk
tb_size_t i = 0;
tb_size_t j = 0;
tb_size_t b = 0;
for (i = 26; i < 27 * 26; i++)
{
j = i;
b = j % 26; j /= 26; p[5] = t[b];
b = j % 26; p[4] = t[b];
tb_trace_i("%s: %s", p, tb_whois_test_no_match_com(&p[4])? "ok" : "no");
}
}
static tb_void_t tb_whois_test_walk_3()
{
// table
tb_char_t const* t = "abcdefghijklmnopqrstuvwxyz";
tb_char_t p[] = {'w', 'w', 'w', '.', 'x', 'x', 'x', '.', 'c', 'o', 'm', '\0'};
// walk
tb_size_t i = 0;
tb_size_t j = 0;
tb_size_t b = 0;
for (i = 26 * 26; i < 27 * 26 * 26; i++)
{
j = i;
b = j % 26; j /= 26; p[6] = t[b];
b = j % 26; j /= 26; p[5] = t[b];
b = j % 26; p[4] = t[b];
tb_trace_i("%s: %s", p, tb_whois_test_no_match_com(&p[4])? "ok" : "no");
}
}
static tb_void_t tb_whois_test_walk_4()
{
// table
tb_char_t const* t = "abcdefghijklmnopqrstuvwxyz";
tb_char_t p[] = {'w', 'w', 'w', '.', 'x', 'x', 'x', 'x', '.', 'c', 'o', 'm', '\0'};
// walk
tb_size_t i = 0;
tb_size_t j = 0;
tb_size_t b = 0;
for (i = 26 * 26 * 26; i < 27 * 26 * 26 * 26; i++)
{
j = i;
b = j % 26; j /= 26; p[7] = t[b];
b = j % 26; j /= 26; p[6] = t[b];
b = j % 26; j /= 26; p[5] = t[b];
b = j % 26; p[4] = t[b];
tb_trace_i("%s: %s", p, tb_whois_test_no_match_com(&p[4])? "ok" : "no");
}
}
static tb_void_t tb_whois_test_walk_5()
{
// table
tb_char_t const* t = "abcdefghijklmnopqrstuvwxyz";
tb_char_t p[] = {'w', 'w', 'w', '.', 'x', 'x', 'x', 'x', 'x', '.', 'c', 'o', 'm', '\0'};
// walk
tb_size_t i = 0;
tb_size_t j = 0;
tb_size_t b = 0;
for (i = 26 * 26 * 26 * 26; i < 27 * 26 * 26 * 26 * 26; i++)
{
j = i;
b = j % 26; j /= 26; p[8] = t[b];
b = j % 26; j /= 26; p[7] = t[b];
b = j % 26; j /= 26; p[6] = t[b];
b = j % 26; j /= 26; p[5] = t[b];
b = j % 26; p[4] = t[b];
tb_trace_i("%s: %s", p, tb_whois_test_no_match_com(&p[4])? "ok" : "no");
}
}
static tb_void_t tb_whois_test_walk_6()
{
// table
tb_char_t const* t = "abcdefghijklmnopqrstuvwxyz";
tb_char_t p[] = {'w', 'w', 'w', '.', 'x', 'x', 'x', 'x', 'x', 'x', '.', 'c', 'o', 'm', '\0'};
// walk
tb_size_t i = 0;
tb_size_t j = 0;
tb_size_t b = 0;
for (i = 26 * 26 * 26 * 26 * 26; i < 27 * 26 * 26 * 26 * 26 * 26; i++)
{
j = i;
b = j % 26; j /= 26; p[9] = t[b];
b = j % 26; j /= 26; p[8] = t[b];
b = j % 26; j /= 26; p[7] = t[b];
b = j % 26; j /= 26; p[6] = t[b];
b = j % 26; j /= 26; p[5] = t[b];
b = j % 26; p[4] = t[b];
tb_trace_i("%s: %s", p, tb_whois_test_no_match_com(&p[4])? "ok" : "no");
}
}
static tb_bool_t tb_whois_test_walk_ping_2(tb_char_t const* file)
{
// init stream
tb_stream_ref_t stream = tb_stream_init_from_url(file);
tb_assert_and_check_return_val(stream, tb_false);
// init ping
tb_char_t* ping = tb_malloc0_cstr(1000 * 16);
tb_assert_and_check_return_val(stream, tb_false);
// open
tb_size_t n = 0;
if (tb_stream_open(stream))
{
while (tb_stream_bread_line(stream, &ping[n * 16], 15) > 0)
n++;
}
// exit stream
tb_stream_exit(stream);
// walk
tb_size_t i = 0;
tb_size_t j = 0;
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
tb_char_t p[41] = {0};
tb_snprintf(p, 40, "%s%s.cn", &ping[i * 16], &ping[j * 16]);
tb_trace_i("%s: %s", p, tb_whois_test_no_match_cn(p)? "ok" : "no");
}
}
// exit ping
tb_free(ping);
return tb_true;
}
static tb_bool_t tb_whois_test_walk_ping_3(tb_char_t const* file)
{
// init stream
tb_stream_ref_t stream = tb_stream_init_from_url(file);
tb_assert_and_check_return_val(stream, tb_false);
// init ping
tb_char_t* ping = tb_malloc0_cstr(1000 * 16);
tb_assert_and_check_return_val(stream, tb_false);
// open
tb_size_t n = 0;
if (tb_stream_open(stream))
{
while (tb_stream_bread_line(stream, &ping[n * 16], 15) > 0)
n++;
}
// exit stream
tb_stream_exit(stream);
// walk
tb_size_t i = 0;
tb_size_t j = 0;
tb_size_t k = 0;
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
for (k = 0; k < n; k++)
{
tb_char_t p[61] = {0};
tb_snprintf(p, 60, "%s%s%s.cn", &ping[i * 16], &ping[j * 16], &ping[k * 16]);
tb_trace_i("%s: %s", p, tb_whois_test_no_match_cn(p)? "ok" : "no");
}
}
}
// exit ping
tb_free(ping);
return tb_true;
}
static tb_void_t tb_whois_test_walk_num_1()
{
// table
tb_char_t const* t = "0123456789";
tb_char_t p[] = {'w', 'w', 'w', '.', 'x', '.', 'c', 'o', 'm', '\0'};
// walk
tb_size_t i = 0;
tb_size_t j = 0;
tb_size_t b = 0;
for (i = 0; i < 10; i++)
{
j = i;
b = j % 10; p[4] = t[b];
tb_trace_i("%s: %s", p, tb_whois_test_no_match_com(&p[4])? "ok" : "no");
}
}
static tb_void_t tb_whois_test_walk_num_2()
{
// table
tb_char_t const* t = "0123456789";
tb_char_t p[] = {'w', 'w', 'w', '.', 'x', 'x', '.', 'c', 'o', 'm', '\0'};
// walk
tb_size_t i = 0;
tb_size_t j = 0;
tb_size_t b = 0;
for (i = 10; i < 100; i++)
{
j = i;
b = j % 10; j /= 10; p[5] = t[b];
b = j % 10; p[4] = t[b];
tb_trace_i("%s: %s", p, tb_whois_test_no_match_com(&p[4])? "ok" : "no");
}
}
static tb_void_t tb_whois_test_walk_num_3()
{
// table
tb_char_t const* t = "0123456789";
tb_char_t p[] = {'w', 'w', 'w', '.', 'x', 'x', 'x', '.', 'c', 'o', 'm', '\0'};
// walk
tb_size_t i = 0;
tb_size_t j = 0;
tb_size_t b = 0;
for (i = 100; i < 1000; i++)
{
j = i;
b = j % 10; j /= 10; p[6] = t[b];
b = j % 10; j /= 10; p[5] = t[b];
b = j % 10; p[4] = t[b];
tb_trace_i("%s: %s", p, tb_whois_test_no_match_com(&p[4])? "ok" : "no");
}
}
static tb_void_t tb_whois_test_walk_num_4()
{
// table
tb_char_t const* t = "0123456789";
tb_char_t p[] = {'w', 'w', 'w', '.', 'x', 'x', 'x', 'x', '.', 'c', 'o', 'm', '\0'};
// walk
tb_size_t i = 0;
tb_size_t j = 0;
tb_size_t b = 0;
for (i = 1000; i < 10000; i++)
{
j = i;
b = j % 10; j /= 10; p[7] = t[b];
b = j % 10; j /= 10; p[6] = t[b];
b = j % 10; j /= 10; p[5] = t[b];
b = j % 10; p[4] = t[b];
tb_trace_i("%s: %s", p, tb_whois_test_no_match_com(&p[4])? "ok" : "no");
}
}
static tb_void_t tb_whois_test_walk_num_5()
{
// table
tb_char_t const* t = "0123456789";
tb_char_t p[] = {'w', 'w', 'w', '.', 'x', 'x', 'x', 'x', 'x', '.', 'c', 'o', 'm', '\0'};
// walk
tb_size_t i = 0;
tb_size_t j = 0;
tb_size_t b = 0;
for (i = 10000; i < 100000; i++)
{
j = i;
b = j % 10; j /= 10; p[8] = t[b];
b = j % 10; j /= 10; p[7] = t[b];
b = j % 10; j /= 10; p[6] = t[b];
b = j % 10; j /= 10; p[5] = t[b];
b = j % 10; p[4] = t[b];
tb_trace_i("%s: %s", p, tb_whois_test_no_match_com(&p[4])? "ok" : "no");
}
}
static tb_void_t tb_whois_test_walk_num_6()
{
// table
tb_char_t const* t = "0123456789";
tb_char_t p[] = {'w', 'w', 'w', '.', 'x', 'x', 'x', 'x', 'x', 'x', '.', 'c', 'o', 'm', '\0'};
// walk
tb_size_t i = 0;
tb_size_t j = 0;
tb_size_t b = 0;
for (i = 100000; i < 1000000; i++)
{
j = i;
b = j % 10; j /= 10; p[9] = t[b];
b = j % 10; j /= 10; p[8] = t[b];
b = j % 10; j /= 10; p[7] = t[b];
b = j % 10; j /= 10; p[6] = t[b];
b = j % 10; j /= 10; p[5] = t[b];
b = j % 10; p[4] = t[b];
tb_trace_i("%s: %s", p, tb_whois_test_no_match_com(&p[4])? "ok" : "no");
}
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_network_whois_main(tb_int_t argc, tb_char_t** argv)
{
#if TB_WHOIS_TEST_HOST_WALK
tb_whois_test_walk_2();
tb_whois_test_walk_3();
tb_whois_test_walk_4();
tb_whois_test_walk_5();
tb_whois_test_walk_6();
tb_whois_test_walk_num_1();
tb_whois_test_walk_num_2();
tb_whois_test_walk_num_3();
tb_whois_test_walk_num_4();
tb_whois_test_walk_num_5();
tb_whois_test_walk_num_6();
tb_whois_test_walk_ping_2(argv[1]);
tb_whois_test_walk_ping_3(argv[1]);
#else
tb_whois_test_done(argv[1]);
#endif
return 0;
}
tbox-1.7.6/src/demo/object/ 0000775 0000000 0000000 00000000000 14671175054 0015474 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/demo/object/bin.c 0000664 0000000 0000000 00000000774 14671175054 0016420 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_object_bin_main(tb_int_t argc, tb_char_t** argv)
{
tb_object_ref_t object = tb_object_read_from_url(argv[1]);
if (object)
{
tb_object_writ_to_url(object, argv[2], TB_OBJECT_FORMAT_BIN);
tb_object_exit(object);
}
return 0;
}
tbox-1.7.6/src/demo/object/bplist.c 0000664 0000000 0000000 00000001122 14671175054 0017131 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_object_bplist_main(tb_int_t argc, tb_char_t** argv)
{
// read object
tb_object_ref_t object = tb_object_read_from_url(argv[1]);
// writ
if (object)
{
// writ object
tb_object_writ_to_url(object, argv[2], TB_OBJECT_FORMAT_BPLIST);
// exit object
tb_object_exit(object);
}
return 0;
}
tbox-1.7.6/src/demo/object/dump.c 0000664 0000000 0000000 00000001257 14671175054 0016612 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_object_dump_main(tb_int_t argc, tb_char_t** argv)
{
// read
tb_object_ref_t root = tb_object_read_from_url(argv[1]);
if (root)
{
// seek?
tb_object_ref_t object = root;
if (argv[2]) object = tb_object_seek(root, argv[2], tb_true);
// dump object
if (object) tb_object_dump(object, TB_OBJECT_FORMAT_JSON);
// exit object
tb_object_exit(root);
}
return 0;
}
tbox-1.7.6/src/demo/object/jcat.c 0000664 0000000 0000000 00000007431 14671175054 0016566 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
static tb_option_item_t g_options[] =
{
{ 'f'
, "filter"
, TB_OPTION_MODE_KEY_VAL
, TB_OPTION_TYPE_CSTR
, "the json filter\n"
".e.g\n"
"\n"
"file:\n"
"{\n"
" \"string\": \"hello world!\"\n"
", \"com.xxx.xxx\": \"hello world\"\n"
", \"integer\": 31415926\n"
", \"array\":\n"
" [\n"
" \"hello world!\"\n"
" , 31415926\n"
" , 3.1415926\n"
" , false\n"
" , true\n"
" , { \"string\": \"hello world!\" }\n"
" ]\n"
", \"macro\": \"$.array[2]\"\n"
", \"macro2\": \"$.com\\\\.xxx\\\\.xxx\"\n"
", \"macro3\": \"$.macro\"\n"
", \"macro4\": \"$.array\"\n"
"}\n"
"\n"
"filter:\n"
" 1. \".string\" : hello world!\n"
" 2. \".array[1]\" : 31415926\n"
" 3. \".array[5].string\" : hello world!\n"
" 4. \".com\\.xxx\\.xxx\" : hello world\n"
" 5. \".macro\" : 3.1415926\n"
" 6. \".macro2\" : hello world\n"
" 7. \".macro3\" : 3.1415926\n"
" 8. \".macro4[0]\" : \"hello world!\"\n"
}
, {'h', "help", TB_OPTION_MODE_KEY, TB_OPTION_TYPE_BOOL, "display this help and exit"}
, {'-', "file", TB_OPTION_MODE_VAL, TB_OPTION_TYPE_CSTR, "the json file" }
};
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_object_jcat_main(tb_int_t argc, tb_char_t** argv)
{
// init option
tb_option_ref_t option = tb_option_init("jcat", "cat the json file", g_options);
if (option)
{
// done option
if (tb_option_done(option, argc - 1, &argv[1]))
{
// done file
if (tb_option_find(option, "file"))
{
// load object
tb_object_ref_t root = tb_object_read_from_url(tb_option_item_cstr(option, "file"));
if (root)
{
// done filter
tb_object_ref_t object = root;
if (tb_option_find(option, "filter"))
object = tb_object_seek(root, tb_option_item_cstr(option, "filter"), tb_true);
// dump object
if (object)
{
// done
tb_char_t info[8192] = {0};
tb_long_t size = tb_object_writ_to_data(object, (tb_byte_t*)info, sizeof(info), TB_OBJECT_FORMAT_JSON | TB_OBJECT_FORMAT_DEFLATE);
if (size > 0)
{
// strip string: ""
tb_char_t* show = info;
if (info[0] == '\"' && info[size - 1] == '\"')
{
show++;
info[size - 1] = '\0';
}
// trace
tb_printf("%s\n", show);
}
}
// exit object
tb_object_exit(root);
}
}
else tb_option_help(option);
}
else tb_option_help(option);
// exit option
tb_option_exit(option);
}
// ok
return 0;
}
tbox-1.7.6/src/demo/object/json.c 0000664 0000000 0000000 00000000776 14671175054 0016623 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_object_json_main(tb_int_t argc, tb_char_t** argv)
{
tb_object_ref_t object = tb_object_read_from_url(argv[1]);
if (object)
{
tb_object_writ_to_url(object, argv[2], TB_OBJECT_FORMAT_JSON);
tb_object_exit(object);
}
return 0;
}
tbox-1.7.6/src/demo/object/writer.c 0000664 0000000 0000000 00000003301 14671175054 0017151 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_object_writer_main(tb_int_t argc, tb_char_t** argv)
{
/* init a dictionary object
*
* {"key1": "hello", "key2" :"world", "key3": 12345, "key4": true, "key5": ["1", "2", []]}
*/
tb_object_ref_t dict = tb_oc_dictionary_init(0, tb_false);
if (dict)
{
// key1 => hello
tb_oc_dictionary_insert(dict, "key1", tb_oc_string_init_from_cstr("hello"));
// key2 => world
tb_oc_dictionary_insert(dict, "key2", tb_oc_string_init_from_cstr("world"));
// key3 => 12345
tb_oc_dictionary_insert(dict, "key3", tb_oc_number_init_from_sint32(12345));
// key4 => true
tb_oc_dictionary_insert(dict, "key4", tb_oc_boolean_true());
// key5 => ["1", "2"]
tb_object_ref_t array = tb_oc_array_init(0, tb_false);
if (array)
{
tb_oc_array_append(array, tb_oc_string_init_from_cstr("1"));
tb_oc_array_append(array, tb_oc_string_init_from_cstr("2"));
tb_oc_array_append(array, tb_oc_array_init(0, tb_false));
tb_oc_dictionary_insert(dict, "key5", array);
}
// key6 => "hello world"\n
tb_oc_dictionary_insert(dict, "key6", tb_oc_string_init_from_cstr("hello\nworld\tusa\"china\\india"));
// write dictionary to json file
tb_object_writ_to_url(dict, argv[1], TB_OBJECT_FORMAT_JSON/* | TB_OBJECT_FORMAT_DEFLATE*/);
// exit dictionary
tb_object_exit(dict);
}
return 0;
}
tbox-1.7.6/src/demo/object/xml.c 0000664 0000000 0000000 00000000774 14671175054 0016450 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_object_xml_main(tb_int_t argc, tb_char_t** argv)
{
tb_object_ref_t object = tb_object_read_from_url(argv[1]);
if (object)
{
tb_object_writ_to_url(object, argv[2], TB_OBJECT_FORMAT_XML);
tb_object_exit(object);
}
return 0;
}
tbox-1.7.6/src/demo/object/xplist.c 0000664 0000000 0000000 00000001122 14671175054 0017157 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_object_xplist_main(tb_int_t argc, tb_char_t** argv)
{
// read object
tb_object_ref_t object = tb_object_read_from_url(argv[1]);
// writ
if (object)
{
// writ object
tb_object_writ_to_url(object, argv[2], TB_OBJECT_FORMAT_XPLIST);
// exit object
tb_object_exit(object);
}
return 0;
}
tbox-1.7.6/src/demo/other/ 0000775 0000000 0000000 00000000000 14671175054 0015347 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/demo/other/charset.c 0000664 0000000 0000000 00000003117 14671175054 0017146 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_other_charset_main(tb_int_t argc, tb_char_t** argv)
{
// check
tb_assert_and_check_return_val(argc == 5, 0);
// init stream
tb_stream_ref_t istream = tb_stream_init_from_url(argv[1]);
tb_stream_ref_t ostream = tb_stream_init_from_file(argv[2], TB_FILE_MODE_WO | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC);
if (istream && ostream && tb_stream_open(istream) && tb_stream_open(ostream))
{
// init data & size
tb_hong_t isize = tb_stream_size(istream);
if (isize > 0)
{
tb_long_t osize = (tb_long_t)(isize << 2);
tb_byte_t* idata = tb_malloc_bytes((tb_size_t)isize);
tb_byte_t* odata = tb_malloc_bytes((tb_size_t)osize);
if (idata && odata && tb_stream_bread(istream, idata, (tb_size_t)isize))
{
// conv
osize = tb_charset_conv_data(tb_charset_type(argv[3]), tb_charset_type(argv[4]), idata, (tb_size_t)isize, odata, osize);
tb_trace_i("conv: %ld bytes", osize);
// save
if (osize > 0) tb_stream_bwrit(ostream, odata, osize);
}
// exit data
if (idata) tb_free(idata);
if (odata) tb_free(odata);
}
// exit stream
tb_stream_exit(istream);
tb_stream_exit(ostream);
}
return 0;
}
tbox-1.7.6/src/demo/other/test.c 0000664 0000000 0000000 00000000472 14671175054 0016475 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_other_test_main(tb_int_t argc, tb_char_t** argv)
{
return 0;
}
tbox-1.7.6/src/demo/other/test.cpp 0000664 0000000 0000000 00000000476 14671175054 0017041 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_other_test_cpp_main(tb_int_t argc, tb_char_t** argv)
{
return 0;
}
tbox-1.7.6/src/demo/platform/ 0000775 0000000 0000000 00000000000 14671175054 0016052 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/demo/platform/addrinfo.c 0000664 0000000 0000000 00000002043 14671175054 0020003 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_demo_addrinfo_test(tb_char_t const* name)
{
// get the default address (ipv4)
tb_ipaddr_t addr = {0};
tb_char_t host[256];
if (tb_addrinfo_addr(name, &addr))
tb_trace_i("%s: %{ipaddr} => %s", name, &addr, tb_addrinfo_name(&addr, host, sizeof(host)));
// get the ipv6 address by the hint info
tb_ipaddr_clear(&addr);
tb_ipaddr_family_set(&addr, TB_IPADDR_FAMILY_IPV6);
if (tb_addrinfo_addr(name, &addr))
tb_trace_i("%s: %{ipaddr} => %s", name, &addr, tb_addrinfo_name(&addr, host, sizeof(host)));
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_addrinfo_main(tb_int_t argc, tb_char_t** argv)
{
// test address
tb_demo_addrinfo_test(argv[1]);
return 0;
}
tbox-1.7.6/src/demo/platform/atomic.c 0000664 0000000 0000000 00000013323 14671175054 0017474 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_test_atomic_get()
{
tb_trace_i("atomic_get(): test ..");
tb_atomic_t a;
tb_atomic_init(&a, 0);
tb_assert_and_check_return(tb_atomic_get(&a) == 0);
tb_atomic_init(&a, 1);
tb_assert_and_check_return(tb_atomic_get(&a) == 1);
tb_atomic_init(&a, 1000);
tb_assert_and_check_return(tb_atomic_get(&a) == 1000);
tb_trace_i("atomic_get(): test ok!");
}
static tb_void_t tb_test_atomic_fetch_and_set()
{
tb_trace_i("atomic_fetch_and_set(): test ..");
tb_atomic_t a;
tb_atomic_init(&a, 0);
tb_assert_and_check_return(tb_atomic_fetch_and_set(&a, 1) == 0);
tb_assert_and_check_return(tb_atomic_fetch_and_set(&a, 2) == 1);
tb_assert_and_check_return(tb_atomic_fetch_and_set(&a, 1000) == 2);
tb_trace_i("atomic_fetch_and_set(): test ok!");
}
static tb_void_t tb_test_atomic_fetch_and_cmpset()
{
tb_trace_i("atomic_fetch_and_cmpset(): test ..");
tb_atomic_t a;
tb_atomic_init(&a, 0);
tb_assert_and_check_return(tb_atomic_fetch_and_cmpset(&a, 0, 1) == 0);
tb_assert_and_check_return(tb_atomic_fetch_and_cmpset(&a, 1, 2) == 1);
tb_assert_and_check_return(tb_atomic_fetch_and_cmpset(&a, 10, 1000) == 2);
tb_assert_and_check_return(tb_atomic_fetch_and_cmpset(&a, 10, 1000) == 2);
tb_trace_i("atomic_fetch_and_cmpset(): test ok!");
}
static tb_void_t tb_test_atomic_compare_and_swap()
{
tb_trace_i("atomic_compare_and_swap(): test ..");
tb_atomic_t a;
tb_atomic_init(&a, 0);
tb_long_t p = 0;
tb_assert_and_check_return(tb_atomic_compare_and_swap(&a, &p, 1) && p == 0);
p = 1;
tb_assert_and_check_return(tb_atomic_compare_and_swap(&a, &p, 2) && p == 1);
p = 10;
tb_assert_and_check_return(!tb_atomic_compare_and_swap(&a, &p, 1000) && p == 2);
tb_trace_i("atomic_compare_and_swap(): test ok!");
}
static tb_void_t tb_test_atomic_fetch_and_add()
{
tb_trace_i("atomic_fetch_and_add(): test ..");
tb_atomic_t a;
tb_atomic_init(&a, 0);
tb_assert_and_check_return(tb_atomic_fetch_and_add(&a, 1) == 0);
tb_assert_and_check_return(tb_atomic_fetch_and_add(&a, 2) == 1);
tb_assert_and_check_return(tb_atomic_fetch_and_add(&a, 1000) == 3);
tb_assert_and_check_return(tb_atomic_fetch_and_add(&a, 1000) == 1003);
tb_trace_i("atomic_fetch_and_add(): test ok!");
}
static tb_void_t tb_test_atomic_fetch_and_sub()
{
tb_trace_i("atomic_fetch_and_sub(): test ..");
tb_atomic_t a;
tb_atomic_init(&a, 0);
tb_assert_and_check_return(tb_atomic_fetch_and_sub(&a, 1) == 0);
tb_assert_and_check_return(tb_atomic_fetch_and_sub(&a, 2) == -1);
tb_assert_and_check_return(tb_atomic_fetch_and_sub(&a, 1000) == -3);
tb_assert_and_check_return(tb_atomic_fetch_and_sub(&a, 1000) == -1003);
tb_trace_i("atomic_fetch_and_sub(): test ok!");
}
static tb_void_t tb_test_atomic_fetch_and_and()
{
tb_trace_i("atomic_fetch_and_and(): test ..");
tb_atomic_t a;
tb_atomic_init(&a, 1);
tb_assert_and_check_return(tb_atomic_fetch_and_and(&a, 1) == 1);
tb_assert_and_check_return(tb_atomic_fetch_and_and(&a, 2) == 1);
tb_assert_and_check_return(tb_atomic_fetch_and_and(&a, 0xff) == 0);
tb_assert_and_check_return(tb_atomic_fetch_and_and(&a, 1000) == 0);
tb_trace_i("atomic_fetch_and_and(): test ok!");
}
static tb_void_t tb_test_atomic_fetch_and_xor()
{
tb_trace_i("atomic_fetch_and_xor(): test ..");
tb_atomic_t a;
tb_atomic_init(&a, 1);
tb_assert_and_check_return(tb_atomic_fetch_and_xor(&a, 1) == 1);
tb_assert_and_check_return(tb_atomic_fetch_and_xor(&a, 2) == 0);
tb_assert_and_check_return(tb_atomic_fetch_and_xor(&a, 3) == 2);
tb_assert_and_check_return(tb_atomic_fetch_and_xor(&a, 1000) == 1);
tb_trace_i("atomic_fetch_and_xor(): test ok!");
}
static tb_void_t tb_test_atomic_fetch_and_or()
{
tb_trace_i("atomic_fetch_and_or(): test ..");
tb_atomic_t a;
tb_atomic_init(&a, 1);
tb_assert_and_check_return(tb_atomic_fetch_and_or(&a, 1) == 1);
tb_assert_and_check_return(tb_atomic_fetch_and_or(&a, 2) == 1);
tb_assert_and_check_return(tb_atomic_fetch_and_or(&a, 3) == 3);
tb_assert_and_check_return(tb_atomic_fetch_and_or(&a, 1000) == 3);
tb_trace_i("atomic_fetch_and_or(): test ok!");
}
static tb_void_t tb_test_atomic_flag_test_and_set()
{
tb_trace_i("atomic_flag_test_and_set(): test ..");
tb_atomic_flag_t a = TB_ATOMIC_FLAG_INIT;
tb_assert_and_check_return(!tb_atomic_flag_test(&a));
tb_assert_and_check_return(!tb_atomic_flag_test_and_set(&a));
tb_assert_and_check_return(tb_atomic_flag_test_and_set(&a));
tb_atomic_flag_clear(&a);
tb_assert_and_check_return(!tb_atomic_flag_test_and_set(&a));
tb_assert_and_check_return(tb_atomic_flag_test_and_set(&a));
tb_assert_and_check_return(tb_atomic_flag_test(&a));
tb_trace_i("atomic_flag_test_and_set(): test ok!");
}
static tb_void_t tb_test_memory_barrier()
{
tb_trace_i("memory_barrier(): test ..");
tb_memory_barrier();
tb_trace_i("memory_barrier(): test ok!");
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_atomic_main(tb_int_t argc, tb_char_t** argv)
{
tb_test_atomic_get();
tb_test_atomic_compare_and_swap();
tb_test_atomic_fetch_and_set();
tb_test_atomic_fetch_and_cmpset();
tb_test_atomic_fetch_and_add();
tb_test_atomic_fetch_and_sub();
tb_test_atomic_fetch_and_and();
tb_test_atomic_fetch_and_xor();
tb_test_atomic_fetch_and_or();
tb_test_atomic_flag_test_and_set();
tb_test_memory_barrier();
return 0;
}
tbox-1.7.6/src/demo/platform/atomic32.c 0000664 0000000 0000000 00000012064 14671175054 0017642 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_test_atomic32_get()
{
tb_trace_i("atomic32_get(): test ..");
tb_atomic32_t a;
tb_atomic32_init(&a, 0);
tb_assert_and_check_return(tb_atomic32_get(&a) == 0);
tb_atomic32_init(&a, 1);
tb_assert_and_check_return(tb_atomic32_get(&a) == 1);
tb_atomic32_init(&a, 1000);
tb_assert_and_check_return(tb_atomic32_get(&a) == 1000);
tb_trace_i("atomic32_get(): test ok!");
}
static tb_void_t tb_test_atomic32_fetch_and_set()
{
tb_trace_i("atomic32_fetch_and_set(): test ..");
tb_atomic32_t a;
tb_atomic32_init(&a, 0);
tb_assert_and_check_return(tb_atomic32_fetch_and_set(&a, 1) == 0);
tb_assert_and_check_return(tb_atomic32_fetch_and_set(&a, 2) == 1);
tb_assert_and_check_return(tb_atomic32_fetch_and_set(&a, 1000) == 2);
tb_trace_i("atomic32_fetch_and_set(): test ok!");
}
static tb_void_t tb_test_atomic32_fetch_and_cmpset()
{
tb_trace_i("atomic32_fetch_and_cmpset(): test ..");
tb_atomic32_t a;
tb_atomic32_init(&a, 0);
tb_assert_and_check_return(tb_atomic32_fetch_and_cmpset(&a, 0, 1) == 0);
tb_assert_and_check_return(tb_atomic32_fetch_and_cmpset(&a, 1, 2) == 1);
tb_assert_and_check_return(tb_atomic32_fetch_and_cmpset(&a, 10, 1000) == 2);
tb_assert_and_check_return(tb_atomic32_fetch_and_cmpset(&a, 10, 1000) == 2);
tb_trace_i("atomic32_fetch_and_cmpset(): test ok!");
}
static tb_void_t tb_test_atomic32_compare_and_swap()
{
tb_trace_i("atomic32_compare_and_swap(): test ..");
tb_atomic32_t a;
tb_atomic32_init(&a, 0);
tb_int32_t p = 0;
tb_assert_and_check_return(tb_atomic32_compare_and_swap(&a, &p, 1) && p == 0);
p = 1;
tb_assert_and_check_return(tb_atomic32_compare_and_swap(&a, &p, 2) && p == 1);
p = 10;
tb_assert_and_check_return(!tb_atomic32_compare_and_swap(&a, &p, 1000) && p == 2);
tb_trace_i("atomic32_compare_and_swap(): test ok!");
}
static tb_void_t tb_test_atomic32_fetch_and_add()
{
tb_trace_i("atomic32_fetch_and_add(): test ..");
tb_atomic32_t a;
tb_atomic32_init(&a, 0);
tb_assert_and_check_return(tb_atomic32_fetch_and_add(&a, 1) == 0);
tb_assert_and_check_return(tb_atomic32_fetch_and_add(&a, 2) == 1);
tb_assert_and_check_return(tb_atomic32_fetch_and_add(&a, 1000) == 3);
tb_assert_and_check_return(tb_atomic32_fetch_and_add(&a, 1000) == 1003);
tb_trace_i("atomic32_fetch_and_add(): test ok!");
}
static tb_void_t tb_test_atomic32_fetch_and_sub()
{
tb_trace_i("atomic32_fetch_and_sub(): test ..");
tb_atomic32_t a;
tb_atomic32_init(&a, 0);
tb_assert_and_check_return(tb_atomic32_fetch_and_sub(&a, 1) == 0);
tb_assert_and_check_return(tb_atomic32_fetch_and_sub(&a, 2) == -1);
tb_assert_and_check_return(tb_atomic32_fetch_and_sub(&a, 1000) == -3);
tb_assert_and_check_return(tb_atomic32_fetch_and_sub(&a, 1000) == -1003);
tb_trace_i("atomic32_fetch_and_sub(): test ok!");
}
static tb_void_t tb_test_atomic32_fetch_and_and()
{
tb_trace_i("atomic32_fetch_and_and(): test ..");
tb_atomic32_t a;
tb_atomic32_init(&a, 1);
tb_assert_and_check_return(tb_atomic32_fetch_and_and(&a, 1) == 1);
tb_assert_and_check_return(tb_atomic32_fetch_and_and(&a, 2) == 1);
tb_assert_and_check_return(tb_atomic32_fetch_and_and(&a, 0xff) == 0);
tb_assert_and_check_return(tb_atomic32_fetch_and_and(&a, 1000) == 0);
tb_trace_i("atomic32_fetch_and_and(): test ok!");
}
static tb_void_t tb_test_atomic32_fetch_and_xor()
{
tb_trace_i("atomic32_fetch_and_xor(): test ..");
tb_atomic32_t a;
tb_atomic32_init(&a, 1);
tb_assert_and_check_return(tb_atomic32_fetch_and_xor(&a, 1) == 1);
tb_assert_and_check_return(tb_atomic32_fetch_and_xor(&a, 2) == 0);
tb_assert_and_check_return(tb_atomic32_fetch_and_xor(&a, 3) == 2);
tb_assert_and_check_return(tb_atomic32_fetch_and_xor(&a, 1000) == 1);
tb_trace_i("atomic32_fetch_and_xor(): test ok!");
}
static tb_void_t tb_test_atomic32_fetch_and_or()
{
tb_trace_i("atomic32_fetch_and_or(): test ..");
tb_atomic32_t a;
tb_atomic32_init(&a, 1);
tb_assert_and_check_return(tb_atomic32_fetch_and_or(&a, 1) == 1);
tb_assert_and_check_return(tb_atomic32_fetch_and_or(&a, 2) == 1);
tb_assert_and_check_return(tb_atomic32_fetch_and_or(&a, 3) == 3);
tb_assert_and_check_return(tb_atomic32_fetch_and_or(&a, 1000) == 3);
tb_trace_i("atomic32_fetch_and_or(): test ok!");
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_atomic32_main(tb_int_t argc, tb_char_t** argv)
{
tb_test_atomic32_get();
tb_test_atomic32_compare_and_swap();
tb_test_atomic32_fetch_and_set();
tb_test_atomic32_fetch_and_cmpset();
tb_test_atomic32_fetch_and_add();
tb_test_atomic32_fetch_and_sub();
tb_test_atomic32_fetch_and_and();
tb_test_atomic32_fetch_and_xor();
tb_test_atomic32_fetch_and_or();
return 0;
}
tbox-1.7.6/src/demo/platform/atomic64.c 0000664 0000000 0000000 00000013305 14671175054 0017646 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_test_atomic64_get()
{
tb_trace_i("atomic64_get(): test ..");
tb_atomic64_t a;
tb_atomic64_init(&a, 0);
tb_assert_and_check_return(tb_atomic64_get(&a) == 0);
tb_atomic64_init(&a, 1);
tb_assert_and_check_return(tb_atomic64_get(&a) == 1);
tb_atomic64_init(&a, 1000);
tb_assert_and_check_return(tb_atomic64_get(&a) == 1000);
tb_atomic64_init(&a, 0xFFFFFFFFFFFFFFFFULL);
tb_assert_and_check_return(tb_atomic64_get(&a) == 0xFFFFFFFFFFFFFFFFULL);
tb_trace_i("atomic64_get(): test ok!");
}
static tb_void_t tb_test_atomic64_fetch_and_set()
{
tb_trace_i("atomic64_fetch_and_set(): test ..");
tb_atomic64_t a;
tb_atomic64_init(&a, 0);
tb_assert_and_check_return(tb_atomic64_fetch_and_set(&a, 1) == 0);
tb_assert_and_check_return(tb_atomic64_fetch_and_set(&a, 2) == 1);
tb_assert_and_check_return(tb_atomic64_fetch_and_set(&a, 0xFFFFFFFFFFFFFFFFULL) == 2);
tb_assert_and_check_return(tb_atomic64_fetch_and_set(&a, 0xFFFFFFFFFFFFFFFFULL) == 0xFFFFFFFFFFFFFFFFULL);
tb_trace_i("atomic64_fetch_and_set(): test ok!");
}
static tb_void_t tb_test_atomic64_fetch_and_cmpset()
{
tb_trace_i("atomic64_fetch_and_cmpset(): test ..");
tb_atomic64_t a;
tb_atomic64_init(&a, 0);
tb_assert_and_check_return(tb_atomic64_fetch_and_cmpset(&a, 0, 1) == 0);
tb_assert_and_check_return(tb_atomic64_fetch_and_cmpset(&a, 1, 2) == 1);
tb_assert_and_check_return(tb_atomic64_fetch_and_cmpset(&a, 10, 1000) == 2);
tb_assert_and_check_return(tb_atomic64_fetch_and_cmpset(&a, 2, 0xFFFFFFFFFFFFFFFFULL) == 2);
tb_assert_and_check_return(tb_atomic64_fetch_and_cmpset(&a, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL) == 0xFFFFFFFFFFFFFFFFULL);
tb_trace_i("atomic64_fetch_and_cmpset(): test ok!");
}
static tb_void_t tb_test_atomic64_compare_and_swap()
{
tb_trace_i("atomic64_compare_and_swap(): test ..");
tb_atomic64_t a;
tb_atomic64_init(&a, 0);
tb_int64_t p = 0;
tb_assert_and_check_return(tb_atomic64_compare_and_swap(&a, &p, 1) && p == 0);
p = 1;
tb_assert_and_check_return(tb_atomic64_compare_and_swap(&a, &p, 2) && p == 1);
p = 10;
tb_assert_and_check_return(!tb_atomic64_compare_and_swap(&a, &p, 1000) && p == 2);
p = 2;
tb_assert_and_check_return(tb_atomic64_compare_and_swap(&a, &p, 0xFFFFFFFFFFFFFFFFULL) && p == 2);
p = 2;
tb_assert_and_check_return(!tb_atomic64_compare_and_swap(&a, &p, 0xFFFFFFFFFFFFFFFFULL) && p == 0xFFFFFFFFFFFFFFFFULL);
tb_trace_i("atomic64_compare_and_swap(): test ok!");
}
static tb_void_t tb_test_atomic64_fetch_and_add()
{
tb_trace_i("atomic64_fetch_and_add(): test ..");
tb_atomic64_t a;
tb_atomic64_init(&a, 0);
tb_assert_and_check_return(tb_atomic64_fetch_and_add(&a, 1) == 0);
tb_assert_and_check_return(tb_atomic64_fetch_and_add(&a, 2) == 1);
tb_assert_and_check_return(tb_atomic64_fetch_and_add(&a, 1000) == 3);
tb_assert_and_check_return(tb_atomic64_fetch_and_add(&a, 1000) == 1003);
tb_trace_i("atomic64_fetch_and_add(): test ok!");
}
static tb_void_t tb_test_atomic64_fetch_and_sub()
{
tb_trace_i("atomic64_fetch_and_sub(): test ..");
tb_atomic64_t a;
tb_atomic64_init(&a, 0);
tb_assert_and_check_return(tb_atomic64_fetch_and_sub(&a, 1) == 0);
tb_assert_and_check_return(tb_atomic64_fetch_and_sub(&a, 2) == -1);
tb_assert_and_check_return(tb_atomic64_fetch_and_sub(&a, 1000) == -3);
tb_assert_and_check_return(tb_atomic64_fetch_and_sub(&a, 1000) == -1003);
tb_trace_i("atomic64_fetch_and_sub(): test ok!");
}
static tb_void_t tb_test_atomic64_fetch_and_and()
{
tb_trace_i("atomic64_fetch_and_and(): test ..");
tb_atomic64_t a;
tb_atomic64_init(&a, 1);
tb_assert_and_check_return(tb_atomic64_fetch_and_and(&a, 1) == 1);
tb_assert_and_check_return(tb_atomic64_fetch_and_and(&a, 2) == 1);
tb_assert_and_check_return(tb_atomic64_fetch_and_and(&a, 0xff) == 0);
tb_assert_and_check_return(tb_atomic64_fetch_and_and(&a, 1000) == 0);
tb_trace_i("atomic64_fetch_and_and(): test ok!");
}
static tb_void_t tb_test_atomic64_fetch_and_xor()
{
tb_trace_i("atomic64_fetch_and_xor(): test ..");
tb_atomic64_t a;
tb_atomic64_init(&a, 1);
tb_assert_and_check_return(tb_atomic64_fetch_and_xor(&a, 1) == 1);
tb_assert_and_check_return(tb_atomic64_fetch_and_xor(&a, 2) == 0);
tb_assert_and_check_return(tb_atomic64_fetch_and_xor(&a, 3) == 2);
tb_assert_and_check_return(tb_atomic64_fetch_and_xor(&a, 1000) == 1);
tb_trace_i("atomic64_fetch_and_xor(): test ok!");
}
static tb_void_t tb_test_atomic64_fetch_and_or()
{
tb_trace_i("atomic64_fetch_and_or(): test ..");
tb_atomic64_t a;
tb_atomic64_init(&a, 1);
tb_assert_and_check_return(tb_atomic64_fetch_and_or(&a, 1) == 1);
tb_assert_and_check_return(tb_atomic64_fetch_and_or(&a, 2) == 1);
tb_assert_and_check_return(tb_atomic64_fetch_and_or(&a, 3) == 3);
tb_assert_and_check_return(tb_atomic64_fetch_and_or(&a, 1000) == 3);
tb_trace_i("atomic64_fetch_and_or(): test ok!");
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_atomic64_main(tb_int_t argc, tb_char_t** argv)
{
tb_test_atomic64_get();
tb_test_atomic64_compare_and_swap();
tb_test_atomic64_fetch_and_set();
tb_test_atomic64_fetch_and_cmpset();
tb_test_atomic64_fetch_and_add();
tb_test_atomic64_fetch_and_sub();
tb_test_atomic64_fetch_and_and();
tb_test_atomic64_fetch_and_xor();
tb_test_atomic64_fetch_and_or();
return 0;
}
tbox-1.7.6/src/demo/platform/backtrace.c 0000664 0000000 0000000 00000001441 14671175054 0020135 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* test
*/
tb_void_t tb_demo_test3(tb_noarg_t);
tb_void_t tb_demo_test3()
{
tb_backtrace_dump("\t", tb_null, 10);
}
static tb_void_t tb_demo_test2()
{
tb_demo_test3();
}
tb_void_t tb_demo_test(tb_size_t size);
tb_void_t tb_demo_test(tb_size_t size)
{
if (size) tb_demo_test(size - 1);
else tb_demo_test2();
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_backtrace_main(tb_int_t argc, tb_char_t** argv)
{
// done
tb_demo_test(argv[1]? tb_atoi(argv[1]) : 10);
return 0;
}
tbox-1.7.6/src/demo/platform/cache_time.c 0000664 0000000 0000000 00000001106 14671175054 0020275 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_cache_time_main(tb_int_t argc, tb_char_t** argv)
{
tb_trace_i("%lld %lld", tb_cache_time_spak(), tb_cache_time_mclock());
tb_sleep(1);
tb_trace_i("%lld %lld", tb_cache_time_spak(), tb_cache_time_mclock());
tb_sleep(1);
tb_trace_i("%lld %lld", tb_cache_time_spak(), tb_cache_time_mclock());
return 0;
}
tbox-1.7.6/src/demo/platform/context.c 0000664 0000000 0000000 00000010275 14671175054 0017707 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the switch count
#define COUNT (10000000)
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_demo_platform_context_test_func1(tb_context_from_t from)
{
// check
tb_context_ref_t* contexts = (tb_context_ref_t*)from.priv;
tb_assert_and_check_return(contexts);
// save main context
contexts[0] = from.context;
// jump to context2
from.context = contexts[2];
// loop
tb_size_t count = 10;
while (count--)
{
// trace
tb_trace_i("func1: %lu", count);
// switch to the func2
from = tb_context_jump(from.context, contexts);
}
// switch to the main function
tb_context_jump(contexts[0], tb_null);
}
static tb_void_t tb_demo_platform_context_test_func2(tb_context_from_t from)
{
// check
tb_context_ref_t* contexts = (tb_context_ref_t*)from.priv;
tb_assert_and_check_return(contexts);
// loop
tb_size_t count = 10;
while (count--)
{
// trace
tb_trace_i("func2: %lu", count);
// switch to the func1
from = tb_context_jump(from.context, contexts);
}
// switch to the main function
tb_context_jump(contexts[0], tb_null);
}
static tb_context_from_t test()
{
tb_context_from_t from = {0};
return from;
}
static tb_void_t tb_demo_platform_context_test()
{
// the stacks
static tb_context_ref_t contexts[3];
static tb_byte_t stacks1[8192];
static tb_byte_t stacks2[8192];
test();
// make context1
contexts[1] = tb_context_make(stacks1, sizeof(stacks1), tb_demo_platform_context_test_func1);
// make context2
contexts[2] = tb_context_make(stacks2, sizeof(stacks2), tb_demo_platform_context_test_func2);
// trace
tb_trace_i("test: enter");
// switch to func1
tb_context_jump(contexts[1], contexts);
// trace
tb_trace_i("test: leave");
}
static tb_void_t tb_demo_platform_context_perf_func1(tb_context_from_t from)
{
// check
tb_context_ref_t* contexts = (tb_context_ref_t*)from.priv;
tb_assert_and_check_return(contexts);
// save main context
contexts[0] = from.context;
// jump to context2
from.context = contexts[2];
// loop
__tb_volatile__ tb_size_t count = COUNT >> 1;
while (count--)
{
// switch to the func2
from = tb_context_jump(from.context, contexts);
}
// switch to the main function
tb_context_jump(contexts[0], tb_null);
}
static tb_void_t tb_demo_platform_context_perf_func2(tb_context_from_t from)
{
// check
tb_context_ref_t* contexts = (tb_context_ref_t*)from.priv;
tb_assert_and_check_return(contexts);
// loop
__tb_volatile__ tb_size_t count = COUNT >> 1;
while (count--)
{
// switch to the func1
from = tb_context_jump(from.context, contexts);
}
// switch to the main function
tb_context_jump(contexts[0], tb_null);
}
static tb_void_t tb_demo_platform_context_perf()
{
// the stacks
static tb_context_ref_t contexts[3];
static tb_byte_t stacks1[8192];
static tb_byte_t stacks2[8192];
// make context1
contexts[1] = tb_context_make(stacks1, sizeof(stacks1), tb_demo_platform_context_perf_func1);
// make context2
contexts[2] = tb_context_make(stacks2, sizeof(stacks2), tb_demo_platform_context_perf_func2);
// init start time
tb_hong_t startime = tb_mclock();
// switch to func1
tb_context_jump(contexts[1], contexts);
// computing time
tb_hong_t duration = tb_mclock() - startime;
// trace
tb_trace_i("perf: %d switches in %lld ms, %lld switches per second", COUNT, duration, (((tb_hong_t)1000 * COUNT) / duration));
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_context_main(tb_int_t argc, tb_char_t** argv)
{
tb_demo_platform_context_test();
tb_demo_platform_context_perf();
return 0;
}
tbox-1.7.6/src/demo/platform/directory.c 0000664 0000000 0000000 00000004116 14671175054 0020224 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* ////////////////////////////////////////////////////////////////////////////////////////////////////
* callback
*/
#if 0
static tb_long_t tb_directory_walk_func(tb_char_t const* path, tb_file_info_t const* info, tb_cpointer_t priv)
{
// check
tb_assert_and_check_return_val(path && info, TB_DIRECTORY_WALK_CODE_END);
// the modified time
tb_tm_t mtime = {0};
tb_localtime(info->mtime, &mtime);
// trace
tb_trace_i( "path[%c]: %s, size: %llu, mtime: %04ld-%02ld-%02ld %02ld:%02ld:%02ld"
, info->type == TB_FILE_TYPE_DIRECTORY? 'd' : 'f'
, path
, info->size
, mtime.year
, mtime.month
, mtime.mday
, mtime.hour
, mtime.minute
, mtime.second);
return TB_DIRECTORY_WALK_CODE_CONTINUE;
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_directory_main(tb_int_t argc, tb_char_t** argv)
{
#if 0
// home
tb_char_t home[TB_PATH_MAXN] = {0};
if (tb_directory_home(home, sizeof(home))) tb_trace_i("home: %s", home);
// current
tb_char_t current[TB_PATH_MAXN] = {0};
if (tb_directory_current(current, sizeof(current))) tb_trace_i("current: %s", current);
// temporary
tb_char_t temporary[TB_PATH_MAXN] = {0};
if (tb_directory_temporary(temporary, sizeof(temporary))) tb_trace_i("temporary: %s", temporary);
#elif 0
// current
tb_char_t current[TB_PATH_MAXN] = {0};
if (tb_directory_current(current, sizeof(current))) tb_trace_i("current: %s", current);
// current
tb_directory_walk(argv[1]? argv[1] : current, -1, tb_true, tb_directory_walk_func, tb_null);
#elif 0
tb_directory_remove(argv[1]);
#elif 1
tb_directory_copy(argv[1], argv[2], TB_FILE_COPY_LINK);
#elif 0
tb_directory_create(argv[1]);
#else
tb_directory_walk(argv[1], 1, tb_true, tb_directory_walk_func, tb_null);
#endif
return 0;
}
tbox-1.7.6/src/demo/platform/environment.c 0000664 0000000 0000000 00000002436 14671175054 0020567 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_environment_main(tb_int_t argc, tb_char_t** argv)
{
// init environment
tb_environment_ref_t environment = tb_environment_init();
if (environment)
{
// load variable
if (tb_environment_load(environment, argv[1]))
{
// dump it
#ifdef __tb_debug__
tb_environment_dump(environment, argv[1]);
#endif
}
// save variable?
if (argc > 2)
{
tb_size_t i = 0;
for (i = 2; i < argc && argv[i]; i++)
{
// set value
tb_environment_insert(environment, argv[i], tb_false);
}
// save variable
tb_environment_save(environment, argv[1]);
// load variable
if (tb_environment_load(environment, argv[1]))
{
// dump it
#ifdef __tb_debug__
tb_environment_dump(environment, argv[1]);
#endif
}
}
// exit environment
tb_environment_exit(environment);
}
return 0;
}
tbox-1.7.6/src/demo/platform/event.c 0000664 0000000 0000000 00000010776 14671175054 0017352 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
typedef struct __tb_demo_loop_t
{
// the event
tb_event_ref_t event;
// the loop
tb_thread_ref_t loop;
// the index
tb_size_t index;
// is stoped?
tb_atomic_flag_t bstoped;
}tb_demo_loop_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* thread
*/
static tb_char_t const* tb_demo_gets(tb_char_t* line, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(line && maxn, tb_null);
// done
tb_char_t* p = line;
tb_char_t* e = line + maxn;
while (p < e)
{
// get character
tb_char_t ch = tb_getchar(); if (ch == '\r') tb_getchar();
tb_check_break(ch != '\r' && ch != '\n');
// append digit
if (tb_isdigit(ch)) *p++ = ch;
else
{
// trace
tb_trace_e("invalid character: %x, please input digit!", ch);
}
}
// end
if (p < e) *p = '\0';
// ok?
return line;
}
static tb_int_t tb_demo_loop(tb_cpointer_t priv)
{
// check
tb_demo_loop_t* loop = (tb_demo_loop_t*)priv;
// done
do
{
// check
tb_assert_and_check_break(loop);
// trace
tb_trace_i("[thread: %lu]: init", loop->index);
// loop
while (!tb_atomic_flag_test(&loop->bstoped))
{
// wait
tb_long_t wait = tb_event_wait(loop->event, -1);
tb_assert_and_check_break(wait >= 0);
// timeout?
tb_check_continue(wait);
// trace
tb_trace_i("[event: %lu]: wait: ok", loop->index);
}
} while (0);
// trace
tb_trace_i("[thread: %lu]: exit", loop? loop->index : 0);
// end
return 0;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_event_main(tb_int_t argc, tb_char_t** argv)
{
// init loop
tb_demo_loop_t loop[10];
tb_size_t i = 0;
tb_size_t n = tb_arrayn(loop);
for (i = 0; i < n; i++)
{
// init event
loop[i].event = tb_event_init();
tb_assert_and_check_break(loop[i].event);
// post event
tb_event_post(loop[i].event);
// init index
loop[i].index = i;
// init stoped
tb_atomic_flag_clear_explicit(&loop[i].bstoped, TB_ATOMIC_RELAXED);
// init loop
loop[i].loop = tb_thread_init(tb_null, tb_demo_loop, loop + i, 0);
tb_assert_and_check_break(loop[i].loop);
}
// check
tb_assert_and_check_return_val(i == n, 0);
// wait some time
tb_msleep(100);
// post
tb_char_t line[256];
tb_bool_t stop = tb_false;
while (!stop)
{
// get line
tb_char_t const* p = tb_demo_gets(line, sizeof(line));
tb_assert_and_check_break(p);
// trace
tb_trace_i("post: %s", p);
// done
while (*p && !stop)
{
tb_char_t ch = *p++;
switch (ch)
{
case 'q':
stop = tb_true;
break;
default:
{
if (ch >= '0' && ch <= '9')
{
// the index
tb_size_t index = ch - '0';
tb_assert_and_check_break(index < n && index == loop[index].index);
// post event
if (loop[index].event) tb_event_post(loop[index].event);
}
}
break;
}
}
}
// post loop
for (i = 0; i < n; i++)
{
// quit thread
tb_atomic_flag_test_and_set(&loop[i].bstoped);
// post event
if (loop[i].event) tb_event_post(loop[i].event);
}
// exit loop
for (i = 0; i < n; i++)
{
// exit loop
if (loop[i].loop)
{
// wait it
if (!tb_thread_wait(loop[i].loop, 5000, tb_null))
{
// trace
tb_trace_e("wait loop[%lu]: timeout", i);
}
// exit it
tb_thread_exit(loop[i].loop);
}
// exit event
if (loop[i].event) tb_event_exit(loop[i].event);
}
// exit
tb_trace_i("exit");
return 0;
}
tbox-1.7.6/src/demo/platform/exception.c 0000664 0000000 0000000 00000005240 14671175054 0020215 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* test
*/
static tb_int_t tb_demo_exception_test(tb_cpointer_t priv)
{
// self
__tb_volatile__ tb_size_t self = tb_thread_self();
// trace
tb_trace_i("thread[%lu]: init", self);
// try0
// tb_size_t i = 0; // FIXME: maybe restored after exception, will leak memory if i is handle
__tb_volatile__ tb_size_t i = 0;
__tb_try
{
tb_trace_i("thread[%lu]: try0: b: %lu", self, i++);
__tb_try
{
tb_trace_i("thread[%lu]: try1: b: %lu", self, i++);
__tb_try
{
// trace
// FIXME: debug: if i is been stored in the stack, it will be modified after exception
// FIXME: relase: if i is been stored in the register, it will be restored after exception
tb_trace_i("thread[%lu]: try2: b: %lu", self, i++);
// abort
// tb_memset(&i, 0, 8192); // FIXME
// *((__tb_volatile__ tb_size_t*)0) = 0;
tb_abort();
// __tb_volatile__ tb_pointer_t p = tb_malloc0(10); tb_memset(p, 0, 8192);
// trace
tb_trace_i("thread[%lu]: try2: e: %lu", self, i++);
}
__tb_except(0)
{
tb_trace_i("thread[%lu]: except2: %lu", self, i++);
}
__tb_end
tb_trace_i("thread[%lu]: try1: e: %lu", self, i++);
}
__tb_except(1)
{
tb_trace_i("thread[%lu]: except1: %lu", self, i++);
tb_backtrace_dump("\t\t", tb_null, 10);
}
__tb_end
tb_trace_i("thread[%lu]: try0: e: %lu", self, i);
// abort
tb_abort();
// end
tb_trace_i("thread[%lu]: end0: e: %lu", self, i);
}
__tb_except(1)
{
tb_trace_i("thread[%lu]: except0: %lu", self, i++);
tb_backtrace_dump("\t", tb_null, 10);
}
__tb_end
// trace
tb_trace_i("thread[%lu]: exit: %lu", self, i);
return 0;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_exception_main(tb_int_t argc, tb_char_t** argv)
{
// done
tb_thread_init(tb_null, tb_demo_exception_test, tb_null, 0);
tb_thread_init(tb_null, tb_demo_exception_test, tb_null, 0);
tb_thread_init(tb_null, tb_demo_exception_test, tb_null, 0);
tb_thread_init(tb_null, tb_demo_exception_test, tb_null, 0);
// wait
tb_getchar();
return 0;
}
tbox-1.7.6/src/demo/platform/file.c 0000664 0000000 0000000 00000015042 14671175054 0017137 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_file_main(tb_int_t argc, tb_char_t** argv)
{
#if 0
// init file
// tb_file_ref_t file = tb_file_init(argv[1], TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC);
tb_file_ref_t file = tb_file_init(argv[1], TB_FILE_MODE_DIRECT | TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC);
if (file)
{
// done
tb_size_t align = TB_FILE_DIRECT_ASIZE;
tb_size_t writ = 0;
tb_size_t size = 512 * 1024 * 1024;
tb_size_t maxn = 8096;
// tb_size_t maxn = (1 << 17);
tb_byte_t* data = tb_malloc(maxn + align);
tb_hong_t time = tb_mclock();
if (data)
{
// align
tb_byte_t* buff = (tb_byte_t*)tb_align((tb_hize_t)data, align);
// writ file
while (writ < size)
{
tb_long_t real = tb_file_writ(file, buff, tb_min(maxn, size - writ));
// tb_trace_i("real: %ld, size: %lu", real, tb_min(maxn, size - writ));
if (real > 0) writ += real;
else if (!real) ;
else break;
}
// exit data
tb_free(data);
}
// sync
tb_file_sync(file);
// ok
if (writ == size)
{
// trace
time = tb_mclock() - time;
tb_trace_i("writ: %lld s", time / 1000);
time = tb_mclock();
}
// exit file
tb_file_exit(file);
}
#elif 0
// init file
tb_file_ref_t file = tb_file_init(argv[1], TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC);
if (file)
{
// done
tb_size_t writ = 0;
tb_size_t size = 512 * 1024 * 1024;
tb_size_t maxn = 8096;
tb_iovec_t list[4];
tb_hong_t time = tb_mclock();
tb_byte_t* data = tb_malloc(maxn << 2);
// init iovec
list[0].data = tb_malloc(maxn);
list[1].data = tb_malloc(maxn);
list[2].data = tb_malloc(maxn);
list[3].data = tb_malloc(maxn);
list[0].size = maxn;
list[1].size = maxn;
list[2].size = maxn;
list[3].size = maxn;
// writ file
while (writ < size)
{
// size
tb_memcpy(data, list[0].data, list[0].size);
tb_memcpy(data + maxn, list[1].data, list[1].size);
tb_memcpy(data + maxn + maxn, list[2].data, list[2].size);
tb_memcpy(data + maxn + maxn + maxn, list[3].data, list[3].size);
// writ
tb_long_t real = tb_file_writ(file, data, tb_min((size - writ), (maxn << 2)));
if (real > 0) writ += real;
else if (!real) ;
else break;
}
// exit data
tb_free(list[0].data);
tb_free(list[1].data);
tb_free(list[2].data);
tb_free(list[3].data);
tb_free(data);
// sync
tb_file_sync(file);
// ok
if (writ == size)
{
// trace
time = tb_mclock() - time;
tb_trace_i("writ: %lld s", time / 1000);
time = tb_mclock();
}
// exit file
tb_file_exit(file);
}
#elif 0
// init file
tb_file_ref_t file = tb_file_init(argv[1], TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC);
if (file)
{
// done
tb_size_t writ = 0;
tb_size_t size = 512 * 1024 * 1024;
tb_size_t maxn = 8096;
tb_iovec_t list[4];
tb_hong_t time = tb_mclock();
// init iovec
list[0].data = tb_malloc(maxn);
list[1].data = tb_malloc(maxn);
list[2].data = tb_malloc(maxn);
list[3].data = tb_malloc(maxn);
list[0].size = maxn;
list[1].size = maxn;
list[2].size = maxn;
list[3].size = maxn;
// writ file
while (writ < size)
{
// size
tb_size_t left = size - writ;
if (left < (maxn << 2))
{
list[0].size = left >= maxn? maxn : left; left -= list[0].size;
list[1].size = left >= maxn? maxn : left; left -= list[1].size;
list[2].size = left >= maxn? maxn : left; left -= list[2].size;
list[3].size = left >= maxn? maxn : left; left -= list[3].size;
}
// writ
tb_long_t real = tb_file_writv(file, list, 4);
if (real > 0) writ += real;
else if (!real) ;
else break;
}
// exit data
tb_free(list[0].data);
tb_free(list[1].data);
tb_free(list[2].data);
tb_free(list[3].data);
// sync
tb_file_sync(file);
// ok
if (writ == size)
{
// trace
time = tb_mclock() - time;
tb_trace_i("writ: %lld s", time / 1000);
time = tb_mclock();
}
// exit file
tb_file_exit(file);
}
#elif 0
tb_file_ref_t ifile = tb_file_init(argv[1], TB_FILE_MODE_RW);
tb_file_ref_t ofile = tb_file_init(argv[2], TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC);
if (ifile && ofile)
{
tb_hize_t writ = 0;
tb_hize_t size = tb_file_size(ifile);
while (writ < size)
{
tb_long_t real = tb_file_writf(ofile, ifile, writ, size - writ);
if (real > 0) writ += real;
else break;
}
}
// exit file
if (ifile) tb_file_exit(ifile);
if (ofile) tb_file_exit(ofile);
#elif 1
tb_bool_t ok = tb_file_rename(argv[1], argv[2]);
tb_trace_i("rename: %s => %s %s", argv[1], argv[2], ok? "ok" : "failed");
#elif 1
tb_long_t ok = tb_file_fscase(argv[1]);
tb_trace_i("fscase: %s => %d", argv[1], ok);
#elif 0
tb_bool_t ok = tb_file_copy(argv[1], argv[2], TB_FILE_COPY_LINK);
tb_trace_i("copy: %s => %s %s", argv[1], argv[2], ok? "ok" : "failed");
#elif 0
tb_file_info_t info;
tb_hong_t time = tb_time();
if (tb_file_touch(argv[1], time, time) && tb_file_info(argv[1], &info))
tb_trace_i("touch: %s, atime: %lld mtime: %lld, time: %lld", argv[1], info.atime, info.mtime, time);
#elif 0
tb_bool_t ok = tb_file_link(argv[1], argv[2]);
tb_trace_i("link: %s => %s %s", argv[1], argv[2], ok? "ok" : "failed");
#else
// remove
tb_file_remove(argv[1]);
#endif
return 0;
}
tbox-1.7.6/src/demo/platform/filelock.c 0000664 0000000 0000000 00000001754 14671175054 0020015 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_filelock_main(tb_int_t argc, tb_char_t** argv)
{
tb_filelock_ref_t lock = tb_filelock_init_from_path(argv[1], tb_file_info(argv[1], tb_null)? TB_FILE_MODE_RO : TB_FILE_MODE_RW | TB_FILE_MODE_CREAT);
if (lock)
{
// trace
tb_trace_i("filelock: enter ..");
// enter lock
if (tb_filelock_enter(lock, (argv[2] && !tb_strcmp(argv[2], "sh"))? TB_FILELOCK_MODE_SH : TB_FILELOCK_MODE_EX))
{
// trace
tb_trace_i("filelock: enter ok");
// wait ..
tb_getchar();
// leave lock
tb_filelock_leave(lock);
// trace
tb_trace_i("filelock: leave ok");
}
tb_filelock_exit(lock);
}
return 0;
}
tbox-1.7.6/src/demo/platform/fwatcher.c 0000664 0000000 0000000 00000003323 14671175054 0020022 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_bool_t g_stop = tb_false;
static tb_fwatcher_ref_t g_fwatcher = tb_null;
static tb_int_t tb_demo_watcher(tb_cpointer_t priv)
{
tb_char_t const* path = (tb_char_t const*)priv;
tb_fwatcher_ref_t fwatcher = tb_fwatcher_init();
if (fwatcher)
{
g_fwatcher = fwatcher;
tb_trace_i("watching %s", path);
if (tb_fwatcher_add(fwatcher, path, tb_true))
{
tb_bool_t eof = tb_false;
tb_fwatcher_event_t event;
while (!eof && !g_stop && tb_fwatcher_wait(fwatcher, &event, -1) >= 0)
{
tb_char_t const* status = event.event == TB_FWATCHER_EVENT_CREATE? "created" :
(event.event == TB_FWATCHER_EVENT_MODIFY? "modified" : "deleted");
tb_trace_i("watch: %s %s", event.filepath, status);
if (tb_strstr(event.filepath, "eof"))
eof = tb_true;
}
}
tb_fwatcher_exit(fwatcher);
}
g_fwatcher = tb_null;
return 0;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_fwatcher_main(tb_int_t argc, tb_char_t** argv)
{
tb_thread_ref_t thread = tb_thread_init(tb_null, tb_demo_watcher, argv[1], 0);
if (thread)
{
tb_getchar();
g_stop = tb_true;
if (g_fwatcher) tb_fwatcher_spak(g_fwatcher);
tb_thread_wait(thread, -1, tb_null);
tb_thread_exit(thread);
}
return 0;
}
tbox-1.7.6/src/demo/platform/hostname.c 0000664 0000000 0000000 00000000677 14671175054 0020046 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_hostname_main(tb_int_t argc, tb_char_t** argv)
{
tb_char_t name[256] = {0};
if (tb_hostname(name, sizeof(name)))
{
tb_trace_i("hostname: %s", name);
}
return 0;
}
tbox-1.7.6/src/demo/platform/ifaddrs.c 0000664 0000000 0000000 00000002104 14671175054 0017627 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_ifaddrs_main(tb_int_t argc, tb_char_t** argv)
{
#ifdef __tb_debug__
// dump ifaddrs
tb_ifaddrs_dump(tb_ifaddrs());
#endif
// dump hwaddr
tb_hwaddr_t hwaddr;
if (tb_ifaddrs_hwaddr(tb_ifaddrs(), argv[1], tb_false, &hwaddr))
{
// trace
tb_trace_i("name: %s, hwaddr: %{hwaddr}", argv[1], &hwaddr);
}
// dump ipaddr4
tb_ipaddr_t ipaddr4;
if (tb_ifaddrs_ipaddr(tb_ifaddrs(), argv[1], tb_false, TB_IPADDR_FAMILY_IPV4, &ipaddr4))
{
// trace
tb_trace_i("name: %s, ipaddr4: %{ipaddr}", argv[1], &ipaddr4);
}
// dump ipaddr6
tb_ipaddr_t ipaddr6;
if (tb_ifaddrs_ipaddr(tb_ifaddrs(), argv[1], tb_false, TB_IPADDR_FAMILY_IPV6, &ipaddr6))
{
// trace
tb_trace_i("name: %s, ipaddr6: %{ipaddr}", argv[1], &ipaddr6);
}
return 0;
}
tbox-1.7.6/src/demo/platform/lock.c 0000664 0000000 0000000 00000010456 14671175054 0017154 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the loop maxn
#define TB_TEST_LOOP_MAXN (20)
// the lock type
#define TB_TEST_LOCK_MUTEX
//#define TB_TEST_LOCK_SPINLOCK
//#define TB_TEST_LOCK_ATOMIC
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
static __tb_volatile__ tb_atomic32_t g_value = 0;
/* //////////////////////////////////////////////////////////////////////////////////////
* loop
*/
static tb_int_t tb_test_mutx_loop(tb_cpointer_t priv)
{
// check
tb_uint32_t self = (tb_uint32_t)tb_thread_self(); tb_used(&self);
// get lock
#if defined(TB_TEST_LOCK_MUTEX)
tb_mutex_ref_t lock = (tb_mutex_ref_t)priv;
#elif defined(TB_TEST_LOCK_SPINLOCK)
tb_spinlock_ref_t lock = (tb_spinlock_ref_t)priv;
#endif
// get cpu core index
static tb_size_t cpuidx = 0;
tb_size_t cpu = cpuidx;
cpuidx = (cpuidx + 1) % tb_cpu_count();
// set thread affinity
tb_cpuset_t cpuset;
TB_CPUSET_ZERO(&cpuset);
TB_CPUSET_SET(cpu, &cpuset);
if (!tb_thread_setaffinity(tb_null, &cpuset))
{
tb_trace_e("thread[%x]: set cpu core(%zu) failed!", self, cpu);
}
// get cpu core again
TB_CPUSET_ZERO(&cpuset);
if (tb_thread_getaffinity(tb_null, &cpuset))
{
tb_size_t i;
for (i = 0; i < TB_CPUSET_SIZE; i++)
{
if (TB_CPUSET_ISSET(i, &cpuset))
{
tb_trace_d("thread[%x]: init cpu core(%zu), cpu: %zu", self, i, cpu);
break;
}
}
}
// loop
__tb_volatile__ tb_size_t n = 100000;
while (n--)
{
#if defined(TB_TEST_LOCK_MUTEX)
{
// enter
tb_mutex_enter(lock);
// value++
__tb_volatile__ tb_size_t n = 100;
while (n--) g_value++;
// leave
tb_mutex_leave(lock);
}
#elif defined(TB_TEST_LOCK_SPINLOCK)
{
// enter
tb_spinlock_enter(lock);
// value++
__tb_volatile__ tb_size_t n = 100;
while (n--) g_value++;
// leave
tb_spinlock_leave(lock);
}
#elif defined(TB_TEST_LOCK_ATOMIC)
tb_atomic32_fetch_and_add_explicit(&g_value, 1, TB_ATOMIC_RELAXED);
#else
// value++
__tb_volatile__ tb_size_t n = 100;
while (n--) g_value++;
#endif
}
tb_trace_d("thread[%x]: exit cpu core(%zu)", self, cpu);
return 0;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_lock_main(tb_int_t argc, tb_char_t** argv)
{
// init lock
#if defined(TB_TEST_LOCK_MUTEX)
tb_mutex_ref_t lock = tb_mutex_init();
tb_lock_profiler_register(tb_lock_profiler(), (tb_pointer_t)lock, "demo_mutex");
#elif defined(TB_TEST_LOCK_SPINLOCK)
tb_spinlock_t lock = TB_SPINLOCK_INIT;
tb_lock_profiler_register(tb_lock_profiler(), (tb_pointer_t)&lock, "demo_spinlock");
#endif
// init time
tb_hong_t time = tb_mclock();
// init loop
tb_size_t i = 0;
tb_size_t n = argv[1]? tb_atoi(argv[1]) : TB_TEST_LOOP_MAXN;
tb_thread_ref_t loop[TB_TEST_LOOP_MAXN] = {0};
for (i = 0; i < n; i++)
{
#if defined(TB_TEST_LOCK_MUTEX)
loop[i] = tb_thread_init(tb_null, tb_test_mutx_loop, lock, 0);
#elif defined(TB_TEST_LOCK_SPINLOCK)
loop[i] = tb_thread_init(tb_null, tb_test_mutx_loop, (tb_pointer_t)&lock, 0);
#else
loop[i] = tb_thread_init(tb_null, tb_test_mutx_loop, tb_null, 0);
#endif
tb_assert_and_check_break(loop[i]);
}
// exit thread
for (i = 0; i < TB_TEST_LOOP_MAXN; i++)
{
// kill thread
if (loop[i])
{
tb_thread_wait(loop[i], -1, tb_null);
tb_thread_exit(loop[i]);
loop[i] = tb_null;
}
// exit lock
#if defined(TB_TEST_LOCK_MUTEX)
if (lock) tb_mutex_exit(lock);
lock = tb_null;
#elif defined(TB_TEST_LOCK_SPINLOCK)
tb_spinlock_exit(&lock);
#endif
}
// exit time
time = tb_mclock() - time;
// trace
tb_trace_i("time: %lld ms", time);
return 0;
}
tbox-1.7.6/src/demo/platform/ltimer.c 0000664 0000000 0000000 00000004732 14671175054 0017520 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* func
*/
static tb_void_t tb_demo_ltimer_task_func(tb_bool_t killed, tb_cpointer_t priv)
{
// get the time
tb_timeval_t tv = {0};
if (tb_gettimeofday(&tv, tb_null))
{
// the time value
tb_hong_t val = ((tb_hong_t)tv.tv_sec * 1000 + tv.tv_usec / 1000);
// trace
tb_trace_i("task[%s]: %lld ms, killed: %d", (tb_char_t const*)priv, val, killed);
}
}
static tb_int_t tb_demo_ltimer_loop(tb_cpointer_t priv)
{
// the timer
tb_ltimer_ref_t timer = (tb_ltimer_ref_t)priv;
// wait
if (timer) tb_ltimer_loop(timer);
// exit it
return 0;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_ltimer_main(tb_int_t argc, tb_char_t** argv)
{
// init timer
// tb_ltimer_ref_t timer = tb_ltimer_init(3, TB_LTIMER_TICK_S, tb_true);
tb_ltimer_ref_t timer = tb_ltimer_init(3, TB_LTIMER_TICK_S, tb_false);
// tb_ltimer_ref_t timer = tb_ltimer_init(3, TB_LTIMER_TICK_100MS, tb_false);
// tb_ltimer_ref_t timer = tb_ltimer_init(3, TB_LTIMER_TICK_M, tb_false);
if (timer)
{
// the limit and delay
tb_size_t limit = tb_ltimer_limit(timer);
tb_size_t delay = tb_ltimer_delay(timer);
// trace
tb_trace_i("limit: %lu, delay: %lu", limit, delay);
// add task: every
tb_ltimer_task_post(timer, 1 * delay, tb_true, tb_demo_ltimer_task_func, "every");
// add task: one
tb_ltimer_task_ref_t one = tb_ltimer_task_init(timer, 10 * delay, tb_false, tb_demo_ltimer_task_func, "one");
// add task: after
tb_ltimer_task_ref_t after = tb_ltimer_task_init_after(timer, 10 * delay, 5 * delay, tb_true, tb_demo_ltimer_task_func, "after");
// init loop
tb_thread_init(tb_null, tb_demo_ltimer_loop, timer, 0);
// wait some time
tb_getchar();
// kil the task
if (one) tb_ltimer_task_kill(timer, one);
if (after) tb_ltimer_task_kill(timer, after);
// wait some time
tb_getchar();
// del the task
if (one) tb_ltimer_task_exit(timer, one);
if (after) tb_ltimer_task_exit(timer, after);
// exit timer
tb_ltimer_exit(timer);
}
return 0;
}
tbox-1.7.6/src/demo/platform/named_pipe.c 0000664 0000000 0000000 00000003743 14671175054 0020326 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define TB_DEMO_PIPE_NAME "hello"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_named_pipe_main(tb_int_t argc, tb_char_t** argv)
{
// init buffer
tb_size_t length = 100 * 1024 * 1024;
tb_byte_t* buffer = (tb_byte_t*)tb_malloc(length);
tb_assert_and_check_return_val(buffer, -1);
// is server?
tb_bool_t is_server = argc > 1 && !tb_strcmp(argv[1], "server");
if (is_server)
{
tb_pipe_file_ref_t pipe = tb_pipe_file_init(TB_DEMO_PIPE_NAME, TB_PIPE_MODE_WO, 0);
if (pipe)
{
// trace
tb_trace_i("connect pipe ..");
// connect pipe first
tb_long_t connected = -1;
while (!(connected = tb_pipe_file_connect(pipe)))
{
tb_long_t wait = tb_pipe_file_wait(pipe, TB_PIPE_EVENT_CONN, -1);
tb_assert_and_check_break(wait > 0);
}
if (connected > 0)
{
// trace
tb_trace_i("write data to pipe ..");
// write data to pipe
tb_bool_t ok = tb_pipe_file_bwrit(pipe, buffer, length);
tb_trace_i("write ok: %d", ok);
}
tb_pipe_file_exit(pipe);
}
}
else
{
tb_pipe_file_ref_t pipe = tb_pipe_file_init(TB_DEMO_PIPE_NAME, TB_PIPE_MODE_RO, 0);
if (pipe)
{
// trace
tb_trace_i("read data to pipe ..");
// read data from pipe
tb_bool_t ok = tb_pipe_file_bread(pipe, buffer, length);
tb_trace_i("read ok: %d", ok);
tb_pipe_file_exit(pipe);
}
}
// exit buffer
tb_free(buffer);
return 0;
}
tbox-1.7.6/src/demo/platform/path.c 0000664 0000000 0000000 00000017363 14671175054 0017164 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_CONFIG_OS_WINDOWS
# define tb_compare_path tb_stricmp
#else
# define tb_compare_path tb_strcmp
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_void_t tb_demo_path_test_directory(tb_char_t const* path, tb_char_t const* excepted)
{
tb_char_t data[TB_PATH_MAXN] = {0};
tb_char_t const* result = tb_path_directory(path, data, sizeof(data));
if (result && excepted && !tb_compare_path(result, excepted))
tb_trace_i("directory(%s): %s passed!", path, result);
else if (!result && !excepted)
tb_trace_i("directory(%s): null passed!", path);
else tb_trace_i("directory(%s): %s != %s", path, result, excepted);
}
static tb_void_t tb_demo_path_test_absolute_to(tb_char_t const* root, tb_char_t const* path, tb_char_t const* excepted)
{
tb_char_t data[TB_PATH_MAXN] = {0};
tb_char_t const* result = tb_path_absolute_to(root, path, data, sizeof(data));
if (result && excepted && !tb_compare_path(result, excepted))
tb_trace_i("absolute_to(%s, %s): %s passed!", root, path, result);
else if (!result && !excepted)
tb_trace_i("absolute_to(%s, %s): null passed!", root, path);
else tb_trace_i("absolute_to(%s, %s): %s != %s", root, path, result, excepted);
}
static tb_void_t tb_demo_path_test_relative_to(tb_char_t const* root, tb_char_t const* path, tb_char_t const* excepted)
{
tb_char_t data[TB_PATH_MAXN] = {0};
tb_char_t const* result = tb_path_relative_to(root, path, data, sizeof(data));
if (result && excepted && !tb_compare_path(result, excepted))
tb_trace_i("relative_to(%s, %s): %s passed!", root, path, result);
else if (!result && !excepted)
tb_trace_i("relative_to(%s, %s): null passed!", root, path);
else tb_trace_i("relative_to(%s, %s): %s != %s", root, path, result, excepted);
}
static tb_void_t tb_demo_path_test_translate(tb_bool_t reduce_dot2, tb_char_t const* path, tb_char_t const* excepted)
{
tb_char_t data[TB_PATH_MAXN] = {0};
tb_strcpy(data, path);
tb_size_t size = tb_path_translate(data, 0, sizeof(data), reduce_dot2);
if (excepted && size && !tb_compare_path(data, excepted))
tb_trace_i("translate(%s): %s passed!", path, data);
else if (!size && !excepted)
tb_trace_i("translate(%s): null passed!", path);
else tb_trace_i("translate(%s): %s != %s", path, data, excepted);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_path_main(tb_int_t argc, tb_char_t** argv)
{
tb_demo_path_test_directory("", tb_null);
tb_demo_path_test_directory(".", tb_null);
tb_demo_path_test_directory("foo", ".");
#ifdef TB_CONFIG_OS_WINDOWS
tb_demo_path_test_directory("c:", tb_null);
tb_demo_path_test_directory("c:\\", tb_null);
tb_demo_path_test_directory("c:\\xxx", "c:");
tb_demo_path_test_directory("c:\\xxx\\yyy", "c:\\xxx");
#else
tb_demo_path_test_directory("/tmp", "/");
tb_demo_path_test_directory("/tmp/", "/");
tb_demo_path_test_directory("/tmp/xxx", "/tmp");
tb_demo_path_test_directory("/tmp/xxx/", "/tmp");
tb_demo_path_test_directory("/", tb_null);
#endif
tb_trace_i("");
tb_demo_path_test_absolute_to("", "", tb_null);
tb_demo_path_test_absolute_to(".", ".", ".");
#ifdef TB_CONFIG_OS_WINDOWS
tb_demo_path_test_absolute_to("c:", "foo", "c:\\foo");
tb_demo_path_test_absolute_to("c:\\", "foo", "c:\\foo");
tb_demo_path_test_absolute_to("c:\\tmp", "foo", "c:\\tmp\\foo");
tb_demo_path_test_absolute_to("c:\\tmp\\", "foo", "c:\\tmp\\foo");
tb_demo_path_test_absolute_to("\\\\.\\tmp\\", "foo", "\\\\.\\tmp\\foo");
tb_demo_path_test_absolute_to("\\\\wsl.localhost\\tmp\\", "foo", "\\\\wsl.localhost\\tmp\\foo");
tb_demo_path_test_absolute_to("\\tmp\\", "foo", "\\tmp\\foo");
#else
tb_demo_path_test_absolute_to("/", "", tb_null);
tb_demo_path_test_absolute_to("/", "/", "/");
tb_demo_path_test_absolute_to("/", ".", "/");
tb_demo_path_test_absolute_to("/tmp/", "foo", "/tmp/foo");
tb_demo_path_test_absolute_to("/tmp", "foo", "/tmp/foo");
#endif
tb_trace_i("");
tb_demo_path_test_relative_to("", "", tb_null);
tb_demo_path_test_relative_to(".", ".", ".");
#ifdef TB_CONFIG_OS_WINDOWS
tb_demo_path_test_relative_to("c:\\", "c:", ".");
tb_demo_path_test_relative_to("c:\\foo", "c:\\foo", ".");
tb_demo_path_test_relative_to("c:\\", "c:\\foo", "foo");
tb_demo_path_test_relative_to("c:\\tmp", "c:\\tmp\\foo", "foo");
tb_demo_path_test_relative_to("c:\\tmp\\", "c:\\tmp\\foo", "foo");
#else
tb_demo_path_test_relative_to("/", "", tb_null);
tb_demo_path_test_relative_to("/", "/", ".");
tb_demo_path_test_relative_to("/tmp/", "/tmp/foo", "foo");
tb_demo_path_test_relative_to("/tmp", "/tmp/foo", "foo");
#endif
tb_trace_i("");
tb_demo_path_test_translate(tb_false, "", tb_null);
tb_demo_path_test_translate(tb_false, ".", ".");
tb_demo_path_test_translate(tb_false, "..", "..");
tb_demo_path_test_translate(tb_true, "././.", ".");
tb_demo_path_test_translate(tb_true, "../foo/..", "..");
tb_demo_path_test_translate(tb_true, "../foo/bar/../..", "..");
#ifdef TB_CONFIG_OS_WINDOWS
tb_demo_path_test_translate(tb_false, "c:", "c:");
tb_demo_path_test_translate(tb_false, "c:\\", "c:");
tb_demo_path_test_translate(tb_false, "c:\\foo\\\\\\", "c:\\foo");
tb_demo_path_test_translate(tb_false, "c:\\foo\\..\\..", "c:\\foo\\..\\..");
tb_demo_path_test_translate(tb_true, "c:\\foo\\.\\.\\", "c:\\foo");
tb_demo_path_test_translate(tb_true, "c:\\foo\\bar\\.\\..\\xyz", "c:\\foo\\xyz");
tb_demo_path_test_translate(tb_true, "c:\\foo\\..\\..", "c:");
tb_demo_path_test_translate(tb_true, "../..", "..\\..");
tb_demo_path_test_translate(tb_true, "../foo/bar/..", "..\\foo");
tb_demo_path_test_translate(tb_true, "../foo/bar/../../..", "..\\..");
tb_demo_path_test_translate(tb_false, "c:\\temp\\test-file.txt", "c:\\temp\\test-file.txt");
tb_demo_path_test_translate(tb_false, "\\\\127.0.0.1\\c$\\temp\\test-file.txt", "\\\\127.0.0.1\\c$\\temp\\test-file.txt");
tb_demo_path_test_translate(tb_false, "\\\\.\\c:\\temp\\test-file.txt", "\\\\.\\c:\\temp\\test-file.txt");
tb_demo_path_test_translate(tb_false, "\\\\?\\c:\\temp\\test-file.txt", "\\\\?\\c:\\temp\\test-file.txt");
tb_demo_path_test_translate(tb_false, "\\\\.\\UNC\\LOCALHOST\\c$\\temp\\test-file.txt", "\\\\.\\UNC\\LOCALHOST\\c$\\temp\\test-file.txt");
tb_demo_path_test_translate(tb_false, "\\\\127.0.0.1\\c$\\temp\\test-file.txt", "\\\\127.0.0.1\\c$\\temp\\test-file.txt");
tb_demo_path_test_translate(tb_false, "\\temp\\test-file.txt", "\\temp\\test-file.txt");
#else
tb_demo_path_test_translate(tb_false, "/", "/");
tb_demo_path_test_translate(tb_false, "////", "/");
tb_demo_path_test_translate(tb_false, "/foo//////", "/foo");
tb_demo_path_test_translate(tb_false, "/foo/../..", "/foo/../..");
tb_demo_path_test_translate(tb_false, "/foo/../../", "/foo/../..");
tb_demo_path_test_translate(tb_true, "/foo/././", "/foo");
tb_demo_path_test_translate(tb_true, "/./././", "/");
tb_demo_path_test_translate(tb_true, "/foo/bar/.//..//xyz", "/foo/xyz");
tb_demo_path_test_translate(tb_true, "/foo/../..", "/");
tb_demo_path_test_translate(tb_true, "/foo/bar../..", "/foo");
tb_demo_path_test_translate(tb_true, "../..", "../..");
tb_demo_path_test_translate(tb_true, "../foo/bar/..", "../foo");
tb_demo_path_test_translate(tb_true, "../foo/bar/../../..", "../..");
#endif
return 0;
}
tbox-1.7.6/src/demo/platform/pipe_pair.c 0000664 0000000 0000000 00000003147 14671175054 0020173 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define BUFSIZE (8192 << 1)
#define COUNT (10000)
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_int_t tb_demo_pipe_pair_read(tb_cpointer_t priv)
{
tb_pipe_file_ref_t file = (tb_pipe_file_ref_t)priv;
tb_byte_t data[BUFSIZE];
tb_size_t count = 0;
while (1)
{
count++;
if (!tb_pipe_file_bread(file, data, sizeof(data))) break;
tb_trace_i("read %lu", count);
}
tb_pipe_file_exit(file);
return 0;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_pipe_pair_main(tb_int_t argc, tb_char_t** argv)
{
// test the anonymous pipe
tb_pipe_file_ref_t file[2] = {};
if (tb_pipe_file_init_pair(file, tb_null, 8192))
{
// start the read thread
tb_thread_ref_t thread = tb_thread_init(tb_null, tb_demo_pipe_pair_read, file[0], 0);
// write data to pipe
tb_byte_t data[BUFSIZE];
tb_size_t count = COUNT;
while (count--)
{
tb_trace_i("write ..");
if (!tb_pipe_file_bwrit(file[1], data, sizeof(data))) break;
}
// exit pipe files
tb_pipe_file_exit(file[1]);
// exit thread
tb_thread_wait(thread, -1, tb_null);
tb_thread_exit(thread);
}
return 0;
}
tbox-1.7.6/src/demo/platform/poller_client.c 0000664 0000000 0000000 00000010627 14671175054 0021057 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// port
#define TB_DEMO_PORT (9090)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the client type
typedef struct __tb_demo_client_t
{
// the socket
tb_socket_ref_t sock;
// the recv size
tb_hize_t size;
// the recv data
tb_byte_t data[8192];
// wait event
tb_bool_t wait;
}tb_demo_client_t, *tb_demo_client_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_demo_session_exit(tb_demo_client_ref_t client, tb_poller_ref_t poller)
{
if (client)
{
// trace
tb_trace_d("[%p]: recv %llu", client->sock, client->size);
// remove socket from poller
tb_poller_remove_sock(poller, client->sock);
// exit socket
if (client->sock) tb_socket_exit(client->sock);
client->sock = tb_null;
// exit client
tb_free(client);
}
}
static tb_long_t tb_demo_session_recv(tb_demo_client_ref_t client)
{
while (1)
{
tb_long_t real = tb_socket_recv(client->sock, client->data, sizeof(client->data));
if (real > 0)
{
client->size += real;
client->wait = tb_false;
}
else if (!real && !client->wait)
{
client->wait = tb_true;
break;
}
else return -1;
}
return 0;
}
static tb_void_t tb_demo_session_start(tb_poller_ref_t poller, tb_socket_ref_t sock)
{
// trace
tb_trace_d("[%p]: recving ..", sock);
// init client
tb_demo_client_ref_t client = tb_malloc0_type(tb_demo_client_t);
if (client)
{
client->sock = sock;
client->wait = tb_false;
if (!tb_demo_session_recv(client))
{
tb_size_t events = TB_POLLER_EVENT_RECV;
if (tb_poller_support(poller, TB_POLLER_EVENT_CLEAR))
events |= TB_POLLER_EVENT_CLEAR;
tb_poller_insert_sock(poller, sock, events, client);
}
else tb_demo_session_exit(client, poller);
}
}
static tb_void_t tb_demo_poller_connect(tb_poller_ref_t poller, tb_ipaddr_ref_t addr)
{
tb_socket_ref_t sock = tb_socket_init(TB_SOCKET_TYPE_TCP, TB_IPADDR_FAMILY_IPV4);
if (sock)
{
tb_long_t ok = tb_socket_connect(sock, addr);
if (ok > 0) tb_demo_session_start(poller, sock);
else if (!ok) tb_poller_insert_sock(poller, sock, TB_POLLER_EVENT_CONN | TB_POLLER_EVENT_ONESHOT, tb_null);
else tb_socket_exit(sock);
}
}
static tb_void_t tb_demo_poller_event(tb_poller_ref_t poller, tb_poller_object_ref_t object, tb_long_t events, tb_cpointer_t priv)
{
switch (events)
{
case TB_POLLER_EVENT_CONN:
tb_demo_session_start(poller, object->ref.sock);
break;
case TB_POLLER_EVENT_RECV | TB_POLLER_EVENT_EOF:
case TB_POLLER_EVENT_RECV:
{
tb_demo_client_ref_t client = (tb_demo_client_ref_t)priv;
if (tb_demo_session_recv(client) || (events & TB_POLLER_EVENT_EOF))
tb_demo_session_exit(client, poller);
}
break;
default:
break;
}
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_poller_client_main(tb_int_t argc, tb_char_t** argv)
{
// check
tb_assert_and_check_return_val(argc == 2 && argv[1], -1);
// the client count
tb_size_t count = tb_atoi(argv[1]);
// start file client
tb_poller_ref_t poller = tb_null;
do
{
// init poller
poller = tb_poller_init(tb_null);
tb_assert_and_check_break(poller);
// attach poller to the current thread
tb_poller_attach(poller);
// init address
tb_ipaddr_t addr;
tb_ipaddr_set(&addr, "127.0.0.1", TB_DEMO_PORT, TB_IPADDR_FAMILY_IPV4);
// attempt to connect clients
while (count--) tb_demo_poller_connect(poller, &addr);
// wait events
while (tb_poller_wait(poller, tb_demo_poller_event, -1) >= 0) ;
} while (0);
// exit poller
if (poller) tb_poller_exit(poller);
poller = tb_null;
return 0;
}
tbox-1.7.6/src/demo/platform/poller_fwatcher.c 0000664 0000000 0000000 00000004115 14671175054 0021377 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_demo_poller_event(tb_poller_ref_t poller, tb_poller_object_ref_t object, tb_long_t events, tb_cpointer_t priv)
{
// check
tb_assert_and_check_return(poller && object);
// fwatcher?
if (object->type == TB_POLLER_OBJECT_FWATCHER)
{
tb_fwatcher_event_t* event = (tb_fwatcher_event_t*)events;
if (event)
{
tb_char_t const* status = event->event == TB_FWATCHER_EVENT_CREATE? "created" :
(event->event == TB_FWATCHER_EVENT_MODIFY? "modified" : "deleted");
tb_trace_i("watch: %s %s", event->filepath, status);
if (tb_strstr(event->filepath, "eof"))
tb_poller_kill(poller);
}
}
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_poller_fwatcher_main(tb_int_t argc, tb_char_t** argv)
{
tb_poller_ref_t poller = tb_null;
do
{
// init poller
poller = tb_poller_init(tb_null);
tb_assert_and_check_break(poller);
// attach poller to the current thread
tb_poller_attach(poller);
// init fwatcher
tb_fwatcher_ref_t fwatcher = tb_fwatcher_init();
tb_assert_and_check_break(fwatcher);
// add watch directory
tb_fwatcher_add(fwatcher, argv[1], tb_true);
// insert fwatcher
tb_poller_object_t object;
object.type = TB_POLLER_OBJECT_FWATCHER;
object.ref.fwatcher = fwatcher;
tb_poller_insert(poller, &object, 0, tb_null);
// wait events
while (tb_poller_wait(poller, tb_demo_poller_event, -1) >= 0) ;
// exit fwatcher
tb_fwatcher_exit(fwatcher);
// end
tb_trace_i("finished");
} while (0);
// exit poller
if (poller) tb_poller_exit(poller);
poller = tb_null;
return 0;
}
tbox-1.7.6/src/demo/platform/poller_pipe.c 0000664 0000000 0000000 00000010143 14671175054 0020527 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the client type
typedef struct __tb_demo_client_t
{
// the pipe file
tb_pipe_file_ref_t pipe;
// the read size
tb_hize_t size;
// the read data
tb_byte_t data[8192];
// wait event
tb_bool_t wait;
}tb_demo_client_t, *tb_demo_client_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_demo_session_exit(tb_demo_client_ref_t client, tb_poller_ref_t poller)
{
if (client)
{
// remove pipe from poller
tb_poller_remove_pipe(poller, client->pipe);
// exit pipe file
if (client->pipe) tb_pipe_file_exit(client->pipe);
client->pipe = tb_null;
// exit client
tb_free(client);
}
}
static tb_long_t tb_demo_session_read(tb_demo_client_ref_t client)
{
while (1)
{
tb_long_t real = tb_pipe_file_read(client->pipe, client->data, sizeof(client->data));
if (real > 0)
{
client->size += real;
client->wait = tb_false;
}
else if (!real && !client->wait)
{
client->wait = tb_true;
break;
}
else return -1;
}
tb_trace_d("[%p]: read %llu", client->pipe, client->size);
return 0;
}
static tb_int_t tb_demo_session_writ(tb_cpointer_t priv)
{
tb_pipe_file_ref_t pipe = (tb_pipe_file_ref_t)priv;
tb_byte_t data[8192 * 16];
tb_size_t count = 100;
tb_hize_t total = 0;
while (count--)
{
total += sizeof(data);
tb_trace_d("[%p]: write %llu", pipe, total);
if (!tb_pipe_file_bwrit(pipe, data, sizeof(data))) break;
tb_usleep(50000);
}
tb_used(&total);
return 0;
}
static tb_void_t tb_demo_session_start(tb_poller_ref_t poller, tb_pipe_file_ref_t pipe)
{
// trace
tb_trace_d("[%p]: recving ..", pipe);
// init client
tb_demo_client_ref_t client = tb_malloc0_type(tb_demo_client_t);
if (client)
{
client->pipe = pipe;
client->wait = tb_false;
if (!tb_demo_session_read(client))
{
tb_size_t events = TB_POLLER_EVENT_RECV;
if (tb_poller_support(poller, TB_POLLER_EVENT_CLEAR))
events |= TB_POLLER_EVENT_CLEAR;
tb_poller_insert_pipe(poller, pipe, events, client);
}
else tb_demo_session_exit(client, poller);
}
}
static tb_void_t tb_demo_poller_open(tb_poller_ref_t poller)
{
tb_pipe_file_ref_t pair[2];
if (tb_pipe_file_init_pair(pair, tb_null, 4096))
{
tb_demo_session_start(poller, pair[0]);
tb_thread_init(tb_null, tb_demo_session_writ, pair[1], 0);
}
}
static tb_void_t tb_demo_poller_event(tb_poller_ref_t poller, tb_poller_object_ref_t object, tb_long_t events, tb_cpointer_t priv)
{
switch (events)
{
case TB_POLLER_EVENT_RECV | TB_POLLER_EVENT_EOF:
case TB_POLLER_EVENT_RECV:
{
tb_demo_client_ref_t client = (tb_demo_client_ref_t)priv;
if (tb_demo_session_read(client) || (events & TB_POLLER_EVENT_EOF))
tb_demo_session_exit(client, poller);
}
break;
default:
break;
}
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_poller_pipe_main(tb_int_t argc, tb_char_t** argv)
{
// start file client
tb_poller_ref_t poller = tb_null;
do
{
// init poller
poller = tb_poller_init(tb_null);
tb_assert_and_check_break(poller);
// attach poller to the current thread
tb_poller_attach(poller);
// attempt to open clients
tb_demo_poller_open(poller);
// wait events
while (tb_poller_wait(poller, tb_demo_poller_event, -1) >= 0) ;
} while (0);
// exit poller
if (poller) tb_poller_exit(poller);
poller = tb_null;
return 0;
}
tbox-1.7.6/src/demo/platform/poller_process.c 0000664 0000000 0000000 00000012706 14671175054 0021257 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define COUNT (50)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the client type
typedef struct __tb_demo_client_t
{
// the pipe file
tb_pipe_file_ref_t pipe[2];
// the read size
tb_hize_t size;
// the read data
tb_byte_t data[8192];
// wait event
tb_bool_t wait;
}tb_demo_client_t, *tb_demo_client_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_demo_session_exit(tb_demo_client_ref_t client, tb_poller_ref_t poller)
{
if (client)
{
// remove pipe from poller
tb_poller_remove_pipe(poller, client->pipe[0]);
// exit pipe file
if (client->pipe[0]) tb_pipe_file_exit(client->pipe[0]);
if (client->pipe[1]) tb_pipe_file_exit(client->pipe[1]);
client->pipe[0] = tb_null;
client->pipe[1] = tb_null;
// exit client
tb_free(client);
}
}
static tb_long_t tb_demo_session_read(tb_demo_client_ref_t client)
{
// closed?
tb_check_return_val(client && client->pipe[0], -1);
while (1)
{
tb_long_t real = tb_pipe_file_read(client->pipe[0], client->data, sizeof(client->data));
if (real > 0)
{
client->size += real;
client->wait = tb_false;
}
else if (!real && !client->wait)
{
client->wait = tb_true;
break;
}
else return -1;
}
tb_trace_d("[%p]: read %llu", client->pipe[0], client->size);
return 0;
}
static tb_demo_client_ref_t tb_demo_session_start(tb_poller_ref_t poller, tb_pipe_file_ref_t pipe[2])
{
// trace
tb_trace_d("[%p]: recving ..", pipe);
// init client
tb_demo_client_ref_t client = tb_malloc0_type(tb_demo_client_t);
if (client)
{
client->pipe[0] = pipe[0];
client->pipe[1] = pipe[1];
client->wait = tb_false;
if (!tb_demo_session_read(client))
{
tb_size_t events = TB_POLLER_EVENT_RECV;
if (tb_poller_support(poller, TB_POLLER_EVENT_CLEAR))
events |= TB_POLLER_EVENT_CLEAR;
tb_poller_insert_pipe(poller, pipe[0], events, client);
return client;
}
else tb_demo_session_exit(client, poller);
}
return tb_null;
}
static tb_void_t tb_demo_poller_event(tb_poller_ref_t poller, tb_poller_object_ref_t object, tb_long_t events, tb_cpointer_t priv)
{
// check
tb_assert_and_check_return(poller && object);
// process?
tb_demo_client_ref_t client = (tb_demo_client_ref_t)priv;
if (object->type == TB_POLLER_OBJECT_PROC)
{
// update count
static tb_size_t count = 0;
count++;
// trace
tb_trace_i("process(%p): exited, status: %ld, count: %lu", object->ref.proc, events, count);
// exit process
tb_process_exit(object->ref.proc);
// finished?
if (count == COUNT)
tb_poller_kill(poller);
}
else
{
switch (events)
{
case TB_POLLER_EVENT_RECV | TB_POLLER_EVENT_EOF:
case TB_POLLER_EVENT_RECV:
tb_demo_session_read(client);
break;
default:
break;
}
}
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_poller_process_main(tb_int_t argc, tb_char_t** argv)
{
// check
tb_assert_and_check_return_val(argc >= 2, -1);
// start file client
tb_poller_ref_t poller = tb_null;
do
{
// init poller
poller = tb_poller_init(tb_null);
tb_assert_and_check_break(poller);
// attach poller to the current thread
tb_poller_attach(poller);
// start processes
tb_size_t count = COUNT;
tb_demo_client_ref_t clients[COUNT];
while (count--)
{
tb_pipe_file_ref_t pipe[2] = {0};
if (tb_pipe_file_init_pair(pipe, tb_null, 4096))
{
tb_process_attr_t attr = {0};
attr.out.pipe = pipe[1];
attr.outtype = TB_PROCESS_REDIRECT_TYPE_PIPE;
tb_process_ref_t process = tb_process_init(argv[1], (tb_char_t const**)(argv + 1), &attr);
if (process)
{
clients[count] = tb_demo_session_start(poller, pipe);
if (clients[count])
{
tb_poller_object_t object;
object.type = TB_POLLER_OBJECT_PROC;
object.ref.proc = process;
tb_poller_insert(poller, &object, 0, clients[count]);
}
}
}
}
// wait events
while (tb_poller_wait(poller, tb_demo_poller_event, -1) >= 0) ;
// exit clients
count = COUNT;
while (count--)
{
if (clients[count]) tb_demo_session_exit(clients[count], poller);
clients[count] = 0;
}
// end
tb_trace_i("finished");
} while (0);
// exit poller
if (poller) tb_poller_exit(poller);
poller = tb_null;
return 0;
}
tbox-1.7.6/src/demo/platform/poller_server.c 0000664 0000000 0000000 00000013127 14671175054 0021105 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// port
#define TB_DEMO_PORT (9090)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the client type
typedef struct __tb_demo_client_t
{
// the socket
tb_socket_ref_t sock;
// the file
tb_file_ref_t file;
// the file size
tb_hize_t size;
// the file offset
tb_hize_t offset;
// wait event
tb_bool_t wait;
}tb_demo_client_t, *tb_demo_client_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
// the file path
static tb_char_t g_filepath[TB_PATH_MAXN];
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_demo_session_exit(tb_demo_client_ref_t client, tb_poller_ref_t poller)
{
if (client)
{
// trace
tb_trace_d("[%p]: send %llu", client->sock, client->offset);
// remove socket from poller
tb_poller_remove_sock(poller, client->sock);
// exit file
if (client->file) tb_file_exit(client->file);
client->file = tb_null;
// exit socket
if (client->sock) tb_socket_exit(client->sock);
client->sock = tb_null;
// exit client
tb_free(client);
}
}
static tb_long_t tb_demo_session_send(tb_demo_client_ref_t client)
{
tb_hize_t offset = client->offset;
tb_hize_t size = client->size;
while (offset < size)
{
tb_hong_t real = tb_socket_sendf(client->sock, client->file, offset, size - offset);
if (real > 0)
{
offset += real;
client->wait = tb_false;
}
else if (!real && !client->wait)
{
client->wait = tb_true;
break;
}
else return -1;
}
client->offset = offset;
return offset < size? 0 : 1;
}
static tb_void_t tb_demo_session_start(tb_poller_ref_t poller, tb_socket_ref_t sock)
{
// trace
tb_trace_d("[%p]: sending %s ..", sock, g_filepath);
// init file
tb_file_ref_t file = tb_file_init(g_filepath, TB_FILE_MODE_RO);
tb_assert_and_check_return(file);
// init client
tb_demo_client_ref_t client = tb_malloc0_type(tb_demo_client_t);
if (client)
{
client->file = file;
client->sock = sock;
client->size = tb_file_size(file);
client->offset = 0;
client->wait = tb_false;
// send file data to client
if (!tb_demo_session_send(client))
{
tb_size_t events = TB_POLLER_EVENT_SEND;
if (tb_poller_support(poller, TB_POLLER_EVENT_CLEAR))
events |= TB_POLLER_EVENT_CLEAR;
tb_poller_insert_sock(poller, sock, events, client);
}
else tb_demo_session_exit(client, poller);
}
}
static tb_void_t tb_demo_poller_accept(tb_poller_ref_t poller, tb_socket_ref_t sock)
{
tb_socket_ref_t client = tb_null;
while ((client = tb_socket_accept(sock, tb_null)))
tb_demo_session_start(poller, client);
}
static tb_void_t tb_demo_poller_event(tb_poller_ref_t poller, tb_poller_object_ref_t object, tb_long_t events, tb_cpointer_t priv)
{
switch (events)
{
case TB_POLLER_EVENT_ACPT:
tb_demo_poller_accept(poller, object->ref.sock);
break;
case TB_POLLER_EVENT_SEND:
{
tb_demo_client_ref_t client = (tb_demo_client_ref_t)priv;
if (tb_demo_session_send(client))
tb_demo_session_exit(client, poller);
}
break;
default:
break;
}
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_poller_server_main(tb_int_t argc, tb_char_t** argv)
{
// check
tb_assert_and_check_return_val(argc == 2 && argv[1], -1);
// the file path
tb_char_t const* filepath = argv[1];
tb_assert_and_check_return_val(filepath, -1);
// save the file path
tb_strlcpy(g_filepath, filepath, sizeof(g_filepath));
// start file server
tb_socket_ref_t sock = tb_null;
tb_poller_ref_t poller = tb_null;
do
{
// init poller
poller = tb_poller_init(tb_null);
tb_assert_and_check_break(poller);
// attach poller to the current thread
tb_poller_attach(poller);
// init socket
sock = tb_socket_init(TB_SOCKET_TYPE_TCP, TB_IPADDR_FAMILY_IPV4);
tb_assert_and_check_break(sock);
// bind socket
tb_ipaddr_t addr;
tb_ipaddr_set(&addr, tb_null, TB_DEMO_PORT, TB_IPADDR_FAMILY_IPV4);
if (!tb_socket_bind(sock, &addr)) break;
// listen socket
if (!tb_socket_listen(sock, 1000)) break;
// trace
tb_trace_i("listening ..");
// attempt to accept clients
tb_demo_poller_accept(poller, sock);
// start to wait accept events
tb_size_t events = TB_POLLER_EVENT_ACPT;
if (tb_poller_support(poller, TB_POLLER_EVENT_CLEAR))
events |= TB_POLLER_EVENT_CLEAR;
tb_poller_insert_sock(poller, sock, events, tb_null);
// wait events
while (tb_poller_wait(poller, tb_demo_poller_event, -1) >= 0) ;
} while (0);
// exit socket
if (sock) tb_socket_exit(sock);
sock = tb_null;
// exit poller
if (poller) tb_poller_exit(poller);
poller = tb_null;
return 0;
}
tbox-1.7.6/src/demo/platform/process.c 0000664 0000000 0000000 00000011711 14671175054 0017675 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_void_t tb_demo_process_test_run(tb_char_t** argv)
{
tb_long_t ok = tb_process_run(argv[1], (tb_char_t const**)(argv + 1), tb_null);
tb_trace_i("run: %s: %ld", argv[1], ok);
}
static tb_void_t tb_demo_process_test_pipe(tb_char_t** argv)
{
// init pipe files
tb_pipe_file_ref_t file[2] = {0};
if (tb_pipe_file_init_pair(file, tb_null, 0))
{
// init process
tb_process_attr_t attr = {0};
attr.out.pipe = file[1];
attr.outtype = TB_PROCESS_REDIRECT_TYPE_PIPE;
attr.err.pipe = file[1];
attr.errtype = TB_PROCESS_REDIRECT_TYPE_PIPE;
tb_process_ref_t process = tb_process_init(argv[1], (tb_char_t const**)(argv + 1), &attr);
if (process)
{
// read pipe data
tb_size_t read = 0;
tb_byte_t data[8192];
tb_size_t size = sizeof(data);
tb_bool_t wait = tb_false;
while (read < size)
{
tb_long_t real = tb_pipe_file_read(file[0], data + read, size - read);
if (real > 0)
{
read += real;
wait = tb_false;
}
else if (!real && !wait)
{
// wait pipe
tb_long_t ok = tb_pipe_file_wait(file[0], TB_PIPE_EVENT_READ, 1000);
tb_check_break(ok > 0);
wait = tb_true;
}
else break;
}
// dump data
if (read) tb_dump_data(data, read);
// wait process
tb_long_t status = 0;
tb_process_wait(process, &status, -1);
// trace
tb_trace_i("run: %s, status: %ld", argv[1], status);
// exit process
tb_process_exit(process);
}
// exit pipe files
tb_pipe_file_exit(file[0]);
tb_pipe_file_exit(file[1]);
}
}
static tb_void_t tb_demo_process_test_waitlist(tb_char_t** argv)
{
// init processes
tb_size_t count1 = 0;
tb_process_ref_t processes1[5] = {0};
tb_process_ref_t processes2[5] = {0};
tb_process_attr_t attr = {0};
for (; count1 < 4; count1++)
{
attr.priv = tb_u2p(count1);
processes1[count1] = tb_process_init(argv[1], (tb_char_t const**)(argv + 1), &attr);
tb_assert_and_check_break(processes1[count1]);
}
// ok?
while (count1)
{
// trace
tb_trace_i("waiting: %ld", count1);
// wait processes
tb_long_t infosize = -1;
tb_process_waitinfo_t infolist[4] = {{0}};
if ((infosize = tb_process_waitlist(processes1, infolist, tb_arrayn(infolist), -1)) > 0)
{
tb_size_t i = 0;
for (i = 0; i < infosize; i++)
{
// trace
tb_trace_i("process(%d:%p) exited: %d, priv: %p", infolist[i].index, infolist[i].process, infolist[i].status, tb_process_priv(infolist[i].process));
// exit process
if (infolist[i].process) tb_process_exit(infolist[i].process);
// remove this process
processes1[infolist[i].index] = tb_null;
}
// update processes
tb_size_t count2 = 0;
for (i = 0; i < count1; i++)
{
if (processes1[i]) processes2[count2++] = processes1[i];
}
tb_memcpy(processes1, processes2, count2 * sizeof(tb_process_ref_t));
processes1[count2] = tb_null;
count1 = count2;
}
}
}
static tb_void_t tb_demo_process_test_exit(tb_char_t** argv, tb_bool_t detach)
{
tb_size_t i = 0;
tb_process_attr_t attr = {0};
if (detach) attr.flags |= TB_PROCESS_FLAG_DETACH;
for (i = 0; i < 10; i++)
tb_process_init(argv[1], (tb_char_t const**)(argv + 1), &attr);
// we attempt to enter or do ctrl+c and see process list in process monitor
tb_getchar();
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_process_main(tb_int_t argc, tb_char_t** argv)
{
#if 0
tb_demo_process_test_run(argv);
#else
tb_used(tb_demo_process_test_run);
#endif
#if 0
tb_demo_process_test_pipe(argv);
#else
tb_used(tb_demo_process_test_pipe);
#endif
#if 0
tb_demo_process_test_waitlist(argv);
#else
tb_used(tb_demo_process_test_waitlist);
#endif
#if 1
// we can run `xxx.bat` or `xxx.sh` shell command to test it
// @see https://github.com/xmake-io/xmake/issues/719
tb_demo_process_test_exit(argv, tb_false);
// tb_demo_process_test_exit(argv, tb_true);
#else
tb_used(tb_demo_process_test_exit);
#endif
return 0;
}
tbox-1.7.6/src/demo/platform/sched.c 0000664 0000000 0000000 00000002526 14671175054 0017311 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_sched_main(tb_int_t argc, tb_char_t** argv)
{
// get cpu count
tb_size_t cpu_count = tb_cpu_count();
tb_trace_i("cpu count: %lu", cpu_count);
// get the previous cpu core
tb_cpuset_t cpuset;
TB_CPUSET_ZERO(&cpuset);
if (tb_sched_getaffinity(0, &cpuset))
{
tb_size_t i;
for (i = 0; i < cpu_count; i++)
{
if (TB_CPUSET_ISSET(i, &cpuset))
tb_trace_i("get previous cpu core: %d", i);
}
}
// trace
tb_int_t cpu = argv[1]? tb_atoi(argv[1]) : 0;
tb_trace_i("set cpu core: %d", cpu);
// set cpu affinity to the given cpu core
TB_CPUSET_ZERO(&cpuset);
TB_CPUSET_SET(cpu, &cpuset);
if (tb_sched_setaffinity(0, &cpuset))
{
TB_CPUSET_ZERO(&cpuset);
if (tb_sched_getaffinity(0, &cpuset))
{
tb_size_t i;
for (i = 0; i < cpu_count; i++)
{
if (TB_CPUSET_ISSET(i, &cpuset))
tb_trace_i("get cpu core: %d", i);
}
}
}
else tb_trace_i("set cpu core failed!");
return 0;
}
tbox-1.7.6/src/demo/platform/semaphore.c 0000664 0000000 0000000 00000011054 14671175054 0020202 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
typedef struct __tb_demo_loop_t
{
// the semaphore
tb_semaphore_ref_t semaphore;
// the loop
tb_thread_ref_t loop;
// the index
tb_size_t index;
// is stoped?
tb_atomic_t bstoped;
}tb_demo_loop_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* thread
*/
static tb_char_t const* tb_demo_gets(tb_char_t* line, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(line && maxn, tb_null);
// done
tb_char_t* p = line;
tb_char_t* e = line + maxn;
while (p < e)
{
// get character
tb_char_t ch = tb_getchar(); if (ch == '\r') tb_getchar();
tb_check_break(ch != '\r' && ch != '\n');
// append digit
if (tb_isdigit(ch)) *p++ = ch;
else
{
// trace
tb_trace_e("invalid character: %x, please input digit!", ch);
}
}
// end
if (p < e) *p = '\0';
// ok?
return line;
}
static tb_int_t tb_demo_loop(tb_cpointer_t priv)
{
// check
tb_demo_loop_t* loop = (tb_demo_loop_t*)priv;
// done
do
{
// check
tb_assert_and_check_break(loop);
// trace
tb_trace_i("[thread: %lu]: init", loop->index);
// loop
while (!tb_atomic_get(&loop->bstoped))
{
// wait
tb_long_t wait = tb_semaphore_wait(loop->semaphore, -1);
tb_assert_and_check_break(wait >= 0);
// timeout?
tb_check_continue(wait);
// trace
tb_trace_i("[semaphore: %lu]: wait: ok", loop->index);
}
} while (0);
// trace
tb_trace_i("[thread: %lu]: exit", loop? loop->index : 0);
// end
return 0;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_semaphore_main(tb_int_t argc, tb_char_t** argv)
{
// init loop
tb_demo_loop_t loop[10];
tb_size_t i = 0;
tb_size_t n = tb_arrayn(loop);
for (i = 0; i < n; i++)
{
// init semaphore
loop[i].semaphore = tb_semaphore_init(0);
tb_assert_and_check_break(loop[i].semaphore);
// post semaphore
tb_semaphore_post(loop[i].semaphore, 1);
// init index
loop[i].index = i;
// init stoped
loop[i].bstoped = 0;
// init loop
loop[i].loop = tb_thread_init(tb_null, tb_demo_loop, loop + i, 0);
tb_assert_and_check_break(loop[i].loop);
}
// check
tb_assert_and_check_return_val(i == n, 0);
// wait some time
tb_msleep(100);
// post
tb_char_t line[256];
tb_bool_t stop = tb_false;
while (!stop)
{
// get line
tb_char_t const* p = tb_demo_gets(line, sizeof(line));
tb_assert_and_check_break(p);
// trace
tb_trace_i("post: %s", p);
// done
while (*p && !stop)
{
tb_char_t ch = *p++;
switch (ch)
{
case 'q':
stop = tb_true;
break;
default:
{
if (ch >= '0' && ch <= '9')
{
// the index
tb_size_t index = ch - '0';
tb_assert_and_check_break(index < n && index == loop[index].index);
// post semaphore
if (loop[index].semaphore) tb_semaphore_post(loop[index].semaphore, 1);
}
}
break;
}
}
}
// post loop
for (i = 0; i < n; i++)
{
// quit thread
tb_atomic_set(&loop[i].bstoped, 1);
// post semaphore
if (loop[i].semaphore) tb_semaphore_post(loop[i].semaphore, 1);
}
// exit loop
for (i = 0; i < n; i++)
{
// exit loop
if (loop[i].loop)
{
// wait it
if (!tb_thread_wait(loop[i].loop, 5000, tb_null))
{
// trace
tb_trace_e("wait loop[%lu]: timeout", i);
}
// exit it
tb_thread_exit(loop[i].loop);
}
// exit semaphore
if (loop[i].semaphore) tb_semaphore_exit(loop[i].semaphore);
}
// exit
tb_trace_i("exit");
return 0;
}
tbox-1.7.6/src/demo/platform/stdfile.c 0000664 0000000 0000000 00000005302 14671175054 0017650 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_test_writ()
{
tb_trace_i("=================== test stdfile writ ===================");
tb_stdfile_writ(tb_stdfile_output(), (tb_byte_t const*)"hello world!\n", tb_strlen("hello world!\n"));
}
static tb_void_t tb_test_read()
{
tb_trace_i("=================== test stdfile read ===================");
tb_byte_t data[4096] = {0};
if (tb_stdfile_read(tb_stdfile_input(), data, 3))
tb_trace_i("%s", data);
tb_trace_i("------");
// ignore left characters
tb_char_t ch;
while (tb_stdfile_getc(tb_stdfile_input(), &ch) && ch != '\n') ;
}
static tb_void_t tb_test_puts()
{
tb_trace_i("=================== test stdfile puts ===================");
tb_stdfile_puts(tb_stdfile_output(), "hello world!\n");
}
static tb_void_t tb_test_gets()
{
tb_trace_i("=================== test stdfile gets ===================");
tb_char_t data[4096] = {0};
if (tb_stdfile_gets(tb_stdfile_input(), data, sizeof(data)))
tb_trace_i("%s", data);
tb_trace_i("------");
}
static tb_void_t tb_test_putc()
{
tb_trace_i("=================== test stdfile putc ===================");
tb_char_t const* s = "hello world!\n";
tb_size_t n = tb_strlen("hello world!\n");
tb_size_t i = 0;
for (i = 0; i < n; i++)
tb_stdfile_putc(tb_stdfile_output(), s[i]);
}
static tb_void_t tb_test_getc()
{
tb_trace_i("=================== test stdfile getc ===================");
tb_char_t ch;
tb_int_t i = 0;
tb_char_t s[4096] = {0};
while (tb_stdfile_getc(tb_stdfile_input(), &ch) && ch != '\n')
s[i++] = (tb_char_t)ch;
s[i] = '\0';
tb_trace_i("%s", s);
tb_trace_i("------");
}
static tb_void_t tb_test_peek()
{
tb_trace_i("=================== test stdfile peek ===================");
tb_char_t ch;
tb_int_t i = 0;
tb_char_t s[4096] = {0};
while (tb_stdfile_getc(tb_stdfile_input(), &ch) && ch != '\n')
{
tb_char_t ch2;
if (tb_stdfile_peek(tb_stdfile_input(), &ch2))
tb_trace_i("peek: %c", ch2);
s[i++] = (tb_char_t)ch;
}
s[i] = '\0';
tb_trace_i("%s", s);
tb_trace_i("------");
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_stdfile_main(tb_int_t argc, tb_char_t** argv)
{
tb_test_writ();
tb_test_putc();
tb_test_puts();
tb_test_read();
tb_test_getc();
tb_test_gets();
tb_test_peek();
return 0;
}
tbox-1.7.6/src/demo/platform/thread.c 0000664 0000000 0000000 00000005466 14671175054 0017500 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_int_t tb_demo_thread_func(tb_cpointer_t priv)
{
// self
tb_size_t self = tb_thread_self();
// trace
tb_trace_i("thread[%lx: %zu]: init", self, priv);
// wait some time
tb_sleep(1);
// get cpu core
tb_cpuset_t cpuset;
TB_CPUSET_ZERO(&cpuset);
if (tb_thread_getaffinity(tb_null, &cpuset))
{
tb_size_t i;
for (i = 0; i < TB_CPUSET_SIZE; i++)
{
if (TB_CPUSET_ISSET(i, &cpuset))
tb_trace_i("thread[%lx: %zu]: get cpu core: %d", self, priv, i);
}
}
// reset thread affinity
tb_size_t cpu = tb_min(1, tb_cpu_count() - 1);
TB_CPUSET_ZERO(&cpuset);
TB_CPUSET_SET(cpu, &cpuset);
if (!tb_thread_setaffinity(tb_null, &cpuset))
{
tb_trace_e("thread[%lx: %zu]: set cpu core(%zu) failed!", self, priv, 1);
}
// get cpu core again
TB_CPUSET_ZERO(&cpuset);
if (tb_thread_getaffinity(tb_null, &cpuset))
{
tb_size_t i;
for (i = 0; i < TB_CPUSET_SIZE; i++)
{
if (TB_CPUSET_ISSET(i, &cpuset))
tb_trace_i("thread[%lx: %zu]: get cpu core again: %d", self, priv, i);
}
}
// exit
tb_thread_return(-1);
// trace
tb_trace_i("thread[%lx: %zu]: exit", self, priv);
// ok
return 0;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_thread_main(tb_int_t argc, tb_char_t** argv)
{
// get cpu count
tb_size_t cpu_count = tb_cpu_count();
tb_trace_i("cpu count: %lu", cpu_count);
// init threads
tb_size_t i = 0;
tb_cpuset_t cpuset;
tb_thread_ref_t threads[64] = {0};
for (i = 0; i < cpu_count; i++)
{
// init thread
threads[i] = tb_thread_init(tb_null, tb_demo_thread_func, tb_u2p(i), 0);
tb_assert_and_check_break(threads[i]);
// set thread affinity
TB_CPUSET_ZERO(&cpuset);
TB_CPUSET_SET(i, &cpuset);
if (!tb_thread_setaffinity(threads[i], &cpuset))
{
tb_trace_e("set cpu core(%zu) failed for thread(%zu)", i, i);
}
}
// wait threads
for (i = 0; i < cpu_count; i++)
{
tb_thread_ref_t thread = threads[i];
if (thread)
{
// wait thread
tb_int_t retval = 0;
if (tb_thread_wait(thread, -1, &retval) > 0)
{
// trace
tb_trace_i("wait: %zu ok, retval: %d", i, retval);
}
// exit thread
tb_thread_exit(thread);
}
}
return 0;
}
tbox-1.7.6/src/demo/platform/thread_local.c 0000664 0000000 0000000 00000004403 14671175054 0020640 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_demo_thread_local_free(tb_cpointer_t priv)
{
tb_trace_i("thread[%lx]: free: %p", tb_thread_self(), priv);
}
static tb_int_t tb_demo_thread_local_test(tb_cpointer_t priv)
{
// self
tb_size_t self = tb_thread_self();
// trace
tb_trace_i("thread[%lx]: init", self);
// init the thread local, only once
static tb_thread_local_t s_local = TB_THREAD_LOCAL_INIT;
if (!tb_thread_local_init(&s_local, tb_demo_thread_local_free)) return -1;
// init start time
tb_hong_t time = tb_mclock();
// done
__tb_volatile__ tb_size_t count = 10000000;
while (count--)
{
// attempt to get local variable
tb_size_t local;
if (!(local = (tb_size_t)tb_thread_local_get(&s_local)))
{
// init local variable
if (tb_thread_local_set(&s_local, (tb_cpointer_t)self))
local = self;
}
// check
if (local != self)
{
// trace
tb_trace_i("thread[%lx]: invalid value: %lx", self, local);
}
}
// compile the interval time
time = tb_mclock() - time;
// trace
tb_trace_i("thread[%lx]: exit: %lld ms", self, time);
// ok
return 0;
}
static tb_int_t tb_demo_thread_local_stub(tb_cpointer_t priv)
{
// self
tb_size_t self = tb_thread_self();
// trace
tb_trace_i("thread[%lx]: init", self);
// trace
tb_trace_i("thread[%lx]: exit", self);
// ok
return 0;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_thread_local_main(tb_int_t argc, tb_char_t** argv)
{
tb_thread_init(tb_null, tb_demo_thread_local_test, tb_null, 0);
tb_thread_init(tb_null, tb_demo_thread_local_test, tb_null, 0);
tb_thread_init(tb_null, tb_demo_thread_local_test, tb_null, 0);
tb_thread_init(tb_null, tb_demo_thread_local_test, tb_null, 0);
tb_thread_init(tb_null, tb_demo_thread_local_stub, tb_null, 0);
// wait
tb_getchar();
return 0;
}
tbox-1.7.6/src/demo/platform/thread_pool.c 0000664 0000000 0000000 00000004155 14671175054 0020523 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* test
*/
static tb_void_t tb_demo_task_time_done(tb_thread_pool_worker_ref_t worker, tb_cpointer_t priv)
{
// trace
tb_trace_i("done: %u ms", tb_p2u32(priv));
// wait some time
tb_msleep(tb_p2u32(priv));
}
static tb_void_t tb_demo_task_time_exit(tb_thread_pool_worker_ref_t worker, tb_cpointer_t priv)
{
// trace
tb_trace_i("exit: %u ms", tb_p2u32(priv));
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_thread_pool_main(tb_int_t argc, tb_char_t** argv)
{
#if 0
// post task: 60s
tb_thread_pool_task_post(tb_thread_pool(), "60000ms", tb_demo_task_time_done, tb_null, (tb_cpointer_t)60000, tb_false);
// post task: 10s
tb_thread_pool_task_post(tb_thread_pool(), "10000ms", tb_demo_task_time_done, tb_null, (tb_cpointer_t)10000, tb_false);
// post task: 1s
tb_thread_pool_task_post(tb_thread_pool(), "1000ms", tb_demo_task_time_done, tb_demo_task_time_exit, (tb_cpointer_t)1000, tb_false);
// wait some time
tb_getchar();
#else
// done
tb_size_t count = tb_random_range(1, 16);
tb_size_t total = count;
while (count-- && total < 1000)
{
// the time
tb_size_t time = tb_random_range(0, 500);
// trace
tb_trace_i("post: %lu ms, total: %lu", time, total);
// post task: time ms
tb_thread_pool_task_post(tb_thread_pool(), tb_null, tb_demo_task_time_done, tb_demo_task_time_exit, (tb_pointer_t)time, !(time & 15)? tb_true : tb_false);
// finished? wait some time and update count
if (!count)
{
// wait some time
tb_msleep(100);
// update count
count = tb_random_range(1, 16);
total += count;
}
}
// wait all
tb_thread_pool_task_wait_all(tb_thread_pool(), -1);
#endif
// trace
tb_trace_i("end");
return 0;
}
tbox-1.7.6/src/demo/platform/timer.c 0000664 0000000 0000000 00000003011 14671175054 0017331 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* func
*/
static tb_void_t tb_demo_timer_task_func(tb_bool_t killed, tb_cpointer_t priv)
{
// get the time
tb_timeval_t tv = {0};
if (tb_gettimeofday(&tv, tb_null))
{
// the time value
tb_hong_t val = ((tb_hong_t)tv.tv_sec * 1000 + tv.tv_usec / 1000);
// trace
tb_trace_i("task[%s]: %lld ms, killed: %d", (tb_char_t const*)priv, val, killed);
}
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_timer_main(tb_int_t argc, tb_char_t** argv)
{
// add task: every
tb_timer_task_post(tb_timer(), 1000, tb_true, tb_demo_timer_task_func, "every");
// add task: one
tb_timer_task_ref_t one = tb_timer_task_init(tb_timer(), 10000, tb_false, tb_demo_timer_task_func, "one");
// add task: after
tb_timer_task_ref_t after = tb_timer_task_init_after(tb_timer(), 10000, 5000, tb_true, tb_demo_timer_task_func, "after");
// wait some time
tb_getchar();
// kil the task
if (one) tb_timer_task_kill(tb_timer(), one);
if (after) tb_timer_task_kill(tb_timer(), after);
// wait some time
tb_getchar();
// del the task
if (one) tb_timer_task_exit(tb_timer(), one);
if (after) tb_timer_task_exit(tb_timer(), after);
// ok
return 0;
}
tbox-1.7.6/src/demo/platform/utils.c 0000664 0000000 0000000 00000000675 14671175054 0017366 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_platform_utils_main(tb_int_t argc, tb_char_t** argv)
{
// hostname
tb_char_t hostname[4096] = {0};
if (tb_hostname(hostname, 4096)) tb_trace_i("hostname: %s", hostname);
return 0;
}
tbox-1.7.6/src/demo/regex/ 0000775 0000000 0000000 00000000000 14671175054 0015340 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/demo/regex/regex.c 0000664 0000000 0000000 00000006626 14671175054 0016630 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* test
*/
static tb_void_t tb_demo_regex_test_match_simple(tb_char_t const* pattern, tb_char_t const* content)
{
// trace
tb_trace_i("match_simple: %s, %s", content, pattern);
// done
tb_vector_ref_t results = tb_regex_match_done_simple(pattern, 0, content);
if (results)
{
// show results
tb_for_all_if (tb_regex_match_ref_t, entry, results, entry)
{
// trace
tb_trace_i("[%lu, %lu]: %s", entry->start, entry->size, entry->cstr);
}
// exit results
tb_vector_exit(results);
}
// trace
tb_trace_i("");
}
static tb_void_t tb_demo_regex_test_replace_simple(tb_char_t const* pattern, tb_char_t const* content, tb_char_t const* replacement)
{
// trace
tb_trace_i("replace_simple: %s, %s to %s", content, pattern, replacement);
// done
tb_char_t const* results = tb_regex_replace_done_simple(pattern, 0, content, replacement);
if (results)
{
// trace
tb_trace_i(": %s", results);
// exit results
tb_free(results);
}
}
static tb_void_t tb_demo_regex_test_match_global(tb_char_t const* pattern, tb_char_t const* content)
{
// trace
tb_trace_i("match_global: %s, %s", content, pattern);
// init regex
tb_regex_ref_t regex = tb_regex_init(pattern, 0);
if (regex)
{
// done
tb_long_t start = 0;
tb_size_t length = 0;
tb_vector_ref_t results = tb_null;
while ((start = tb_regex_match_cstr(regex, content, start + length, &length, &results)) >= 0 && results)
{
// trace
tb_trace_i("[%lu, %lu]: ", start, length);
// show results
tb_for_all_if (tb_regex_match_ref_t, entry, results, entry)
{
// trace
tb_trace_i(" [%lu, %lu]: %s", entry->start, entry->size, entry->cstr);
}
}
// exit regex
tb_regex_exit(regex);
}
// trace
tb_trace_i("");
}
static tb_void_t tb_demo_regex_test_replace_global(tb_char_t const* pattern, tb_char_t const* content, tb_char_t const* replacement)
{
// trace
tb_trace_i("replace_global: %s, %s to %s", content, pattern, replacement);
// done
tb_char_t const* results = tb_regex_replace_done_simple(pattern, TB_REGEX_MODE_GLOBAL, content, replacement);
if (results)
{
// trace
tb_trace_i(": %s", results);
// exit results
tb_free(results);
}
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_regex_main(tb_int_t argc, tb_char_t** argv)
{
// test arguments
if (argv[1] && argv[2]) tb_demo_regex_test_match_global(argv[1], argv[2]);
// test match
tb_demo_regex_test_match_simple("\\w+", "hello world");
tb_demo_regex_test_match_global("\\w+", "hello world");
tb_demo_regex_test_match_simple("(\\w+)\\s+?(\\w+)", "hello world");
tb_demo_regex_test_match_global("(\\w+)\\s+?(\\w+)", "hello world");
// test replace
tb_demo_regex_test_replace_simple("\\w+", "hello world", "hi");
tb_demo_regex_test_replace_global("\\w+", "hello world", "hi");
// ok
return 0;
}
tbox-1.7.6/src/demo/stream/ 0000775 0000000 0000000 00000000000 14671175054 0015521 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/demo/stream/stream.c 0000664 0000000 0000000 00000036441 14671175054 0017170 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
typedef struct __tb_demo_context_t
{
// verbose
tb_bool_t verbose;
}tb_demo_context_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* func
*/
#ifdef TB_CONFIG_MODULE_HAVE_OBJECT
static tb_bool_t tb_demo_http_post_func(tb_size_t state, tb_hize_t offset, tb_hong_t size, tb_hize_t save, tb_size_t rate, tb_cpointer_t priv)
{
// percent
tb_size_t percent = 0;
if (size > 0) percent = (tb_size_t)((offset * 100) / size);
else if (state == TB_STATE_CLOSED) percent = 100;
// trace
tb_trace_i("post: %llu, rate: %lu bytes/s, percent: %lu%%, state: %s", save, rate, percent, tb_state_cstr(state));
// ok
return tb_true;
}
static tb_bool_t tb_demo_stream_head_func(tb_char_t const* line, tb_cpointer_t priv)
{
tb_printf("response: %s\n", line);
return tb_true;
}
static tb_bool_t tb_demo_stream_save_func(tb_size_t state, tb_hize_t offset, tb_hong_t size, tb_hize_t save, tb_size_t rate, tb_cpointer_t priv)
{
// check
tb_demo_context_t* context = (tb_demo_context_t*)priv;
tb_assert_and_check_return_val(context, tb_false);
// print verbose info
if (context->verbose)
{
// percent
tb_size_t percent = 0;
if (size > 0) percent = (tb_size_t)((offset * 100) / size);
else if (state == TB_STATE_CLOSED) percent = 100;
// trace
tb_printf("save: %llu bytes, rate: %lu bytes/s, percent: %lu%%, state: %s\n", save, rate, percent, tb_state_cstr(state));
}
// ok
return tb_true;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
static tb_option_item_t g_options[] =
{
{'-', "gzip", TB_OPTION_MODE_KEY, TB_OPTION_TYPE_BOOL, "enable gzip" }
, {'-', "no-verbose", TB_OPTION_MODE_KEY, TB_OPTION_TYPE_BOOL, "disable verbose info" }
, {'d', "debug", TB_OPTION_MODE_KEY, TB_OPTION_TYPE_BOOL, "enable debug info" }
, {'k', "keep-alive", TB_OPTION_MODE_KEY, TB_OPTION_TYPE_BOOL, "keep alive" }
, {'h', "header", TB_OPTION_MODE_KEY_VAL, TB_OPTION_TYPE_CSTR, "the custem http header" }
, {'-', "post-data", TB_OPTION_MODE_KEY_VAL, TB_OPTION_TYPE_CSTR, "set the post data" }
, {'-', "post-file", TB_OPTION_MODE_KEY_VAL, TB_OPTION_TYPE_CSTR, "set the post file" }
, {'-', "range", TB_OPTION_MODE_KEY_VAL, TB_OPTION_TYPE_CSTR, "set the range" }
, {'-', "timeout", TB_OPTION_MODE_KEY_VAL, TB_OPTION_TYPE_INTEGER, "set the timeout" }
, {'-', "limitrate", TB_OPTION_MODE_KEY_VAL, TB_OPTION_TYPE_INTEGER, "set the limitrate" }
, {'h', "help", TB_OPTION_MODE_KEY, TB_OPTION_TYPE_BOOL, "display this help and exit"}
, {'-', "url", TB_OPTION_MODE_VAL, TB_OPTION_TYPE_CSTR, "the url" }
, {'-', tb_null, TB_OPTION_MODE_MORE, TB_OPTION_TYPE_NONE, tb_null }
};
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_stream_main(tb_int_t argc, tb_char_t** argv)
{
// done
tb_option_ref_t option = tb_null;
tb_stream_ref_t istream = tb_null;
tb_stream_ref_t ostream = tb_null;
tb_stream_ref_t pstream = tb_null;
do
{
// init option
option = tb_option_init("stream", "the stream demo", g_options);
tb_assert_and_check_break(option);
// done option
if (tb_option_done(option, argc - 1, &argv[1]))
{
// debug & verbose
tb_bool_t debug = tb_option_find(option, "debug");
tb_bool_t verbose = tb_option_find(option, "no-verbose")? tb_false : tb_true;
// done url
if (tb_option_find(option, "url"))
{
// init istream
istream = tb_stream_init_from_url(tb_option_item_cstr(option, "url"));
tb_assert_and_check_break(istream);
// ctrl http
if (tb_stream_type(istream) == TB_STREAM_TYPE_HTTP)
{
// enable gzip?
if (tb_option_find(option, "gzip"))
{
// auto unzip
if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_AUTO_UNZIP, 1)) break;
// need gzip
if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_HEAD, "Accept-Encoding", "gzip,deflate")) break;
}
// enable debug?
if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_HEAD_FUNC, debug? tb_demo_stream_head_func : tb_null)) break;
// custem header?
if (tb_option_find(option, "header"))
{
// init
tb_string_t key;
tb_string_t val;
tb_string_init(&key);
tb_string_init(&val);
// done
tb_bool_t k = tb_true;
tb_char_t const* p = tb_option_item_cstr(option, "header");
while (*p)
{
// is key?
if (k)
{
if (*p != ':' && !tb_isspace(*p)) tb_string_chrcat(&key, *p++);
else if (*p == ':')
{
// skip ':'
p++;
// skip space
while (*p && tb_isspace(*p)) p++;
// is val now
k = tb_false;
}
else p++;
}
// is val?
else
{
if (*p != ';') tb_string_chrcat(&val, *p++);
else
{
// skip ';'
p++;
// skip space
while (*p && tb_isspace(*p)) p++;
// set header
if (tb_string_size(&key) && tb_string_size(&val))
{
if (debug) tb_printf("header: %s: %s\n", tb_string_cstr(&key), tb_string_cstr(&val));
if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_HEAD, tb_string_cstr(&key), tb_string_cstr(&val))) break;
}
// is key now
k = tb_true;
// clear key & val
tb_string_clear(&key);
tb_string_clear(&val);
}
}
}
// set header
if (tb_string_size(&key) && tb_string_size(&val))
{
if (debug) tb_printf("header: %s: %s\n", tb_string_cstr(&key), tb_string_cstr(&val));
if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_HEAD, tb_string_cstr(&key), tb_string_cstr(&val))) break;
}
// exit
tb_string_exit(&key);
tb_string_exit(&val);
}
// keep alive?
if (tb_option_find(option, "keep-alive"))
{
if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_HEAD, "Connection", "keep-alive")) break;
}
// post-data?
if (tb_option_find(option, "post-data"))
{
tb_char_t const* post_data = tb_option_item_cstr(option, "post-data");
tb_hize_t post_size = tb_strlen(post_data);
if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_METHOD, TB_HTTP_METHOD_POST)) break;
if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_POST_DATA, post_data, post_size)) break;
if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_POST_FUNC, tb_demo_http_post_func)) break;
if (debug) tb_printf("post: %llu\n", post_size);
}
// post-file?
else if (tb_option_find(option, "post-file"))
{
tb_char_t const* url = tb_option_item_cstr(option, "post-file");
if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_METHOD, TB_HTTP_METHOD_POST)) break;
if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_POST_URL, url)) break;
if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_POST_FUNC, tb_demo_http_post_func)) break;
if (debug) tb_printf("post: %s\n", url);
}
}
// set range
if (tb_option_find(option, "range"))
{
tb_char_t const* p = tb_option_item_cstr(option, "range");
if (p)
{
// the bof
tb_hize_t eof = 0;
tb_hize_t bof = tb_atoll(p);
while (*p && tb_isdigit(*p)) p++;
if (*p == '-')
{
p++;
eof = tb_atoll(p);
}
if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_RANGE, bof, eof)) break;
}
}
// set timeout
if (tb_option_find(option, "timeout"))
{
tb_size_t timeout = tb_option_item_uint32(option, "timeout");
if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_SET_TIMEOUT, timeout)) break;
}
// print verbose info
if (verbose) tb_printf("open: %s: ..\n", tb_option_item_cstr(option, "url"));
// open istream
if (!tb_stream_open(istream))
{
// print verbose info
if (verbose) tb_printf("open: %s\n", tb_state_cstr(tb_stream_state(istream)));
break;
}
// print verbose info
if (verbose) tb_printf("open: ok\n");
// init ostream
if (tb_option_find(option, "more0"))
{
// the path
tb_char_t const* path = tb_option_item_cstr(option, "more0");
// init
ostream = tb_stream_init_from_file(path, TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC);
// print verbose info
if (verbose) tb_printf("save: %s\n", path);
}
else
{
// the name
tb_char_t const* name = tb_strrchr(tb_option_item_cstr(option, "url"), '/');
if (!name) name = tb_strrchr(tb_option_item_cstr(option, "url"), '\\');
if (!name) name = "/stream.file";
// the path
tb_char_t path[TB_PATH_MAXN] = {0};
if (tb_directory_current(path, TB_PATH_MAXN))
tb_strcat(path, name);
else break;
// init file
ostream = tb_stream_init_from_file(path, TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC);
// print verbose info
if (verbose) tb_printf("save: %s\n", path);
}
tb_assert_and_check_break(ostream);
// the limit rate
tb_size_t limitrate = 0;
if (tb_option_find(option, "limitrate"))
limitrate = tb_option_item_uint32(option, "limitrate");
// save it
tb_hong_t save = 0;
tb_demo_context_t context = {0};
context.verbose = verbose;
if ((save = tb_transfer(istream, ostream, limitrate, tb_demo_stream_save_func, &context)) < 0) break;
}
else tb_option_help(option);
}
else tb_option_help(option);
} while (0);
// exit pstream
if (pstream) tb_stream_exit(pstream);
pstream = tb_null;
// exit istream
if (istream) tb_stream_exit(istream);
istream = tb_null;
// exit ostream
if (ostream) tb_stream_exit(ostream);
ostream = tb_null;
// exit option
if (option) tb_option_exit(option);
option = tb_null;
return 0;
}
#else
tb_int_t tb_demo_stream_main(tb_int_t argc, tb_char_t** argv)
{
// done
tb_stream_ref_t istream = tb_null;
tb_stream_ref_t ostream = tb_null;
do
{
// init istream
istream = tb_stream_init_from_url(argv[1]);
tb_assert_and_check_break(istream);
// init ostream
ostream = tb_stream_init_from_file(argv[2], TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC);
// open istream
if (!tb_stream_open(istream)) break;
// open ostream
if (!tb_stream_open(ostream)) break;
// writ data
tb_byte_t data[TB_STREAM_BLOCK_MAXN];
tb_hize_t writ = 0;
tb_hize_t left = tb_stream_left(istream);
do
{
// read data
tb_long_t real = tb_stream_read(istream, data, TB_STREAM_BLOCK_MAXN);
if (real > 0)
{
// writ data
if (!tb_stream_bwrit(ostream, data, real)) break;
// save writ
writ += real;
}
else if (!real)
{
// wait
tb_long_t wait = tb_stream_wait(istream, TB_STREAM_WAIT_READ, tb_stream_timeout(istream));
tb_assert_and_check_break(wait >= 0);
// timeout?
tb_check_break(wait);
// has writ?
tb_assert_and_check_break(wait & TB_STREAM_WAIT_READ);
}
else break;
// is end?
if (writ >= left) break;
} while(1);
} while (0);
// exit istream
if (istream) tb_stream_exit(istream);
istream = tb_null;
// exit ostream
if (ostream) tb_stream_exit(ostream);
ostream = tb_null;
return 0;
}
#endif
tbox-1.7.6/src/demo/stream/stream/ 0000775 0000000 0000000 00000000000 14671175054 0017014 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/demo/stream/stream/cache.c 0000664 0000000 0000000 00000002415 14671175054 0020225 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_stream_cache_main(tb_int_t argc, tb_char_t** argv)
{
// init istream
tb_stream_ref_t istream = tb_stream_init_from_url(argv[1]);
// init ostream
tb_stream_ref_t ostream = tb_stream_init_from_file(argv[2], TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC);
// filter istream or ostream?
tb_stream_ref_t iostream = istream;
// tb_stream_ref_t iostream = ostream;
// init fstream
tb_stream_ref_t fstream = tb_stream_init_filter_from_cache(iostream, 0);
// done
if (istream && ostream && fstream)
{
// save it
tb_hong_t save = 0;
if (iostream == istream) save = tb_transfer(fstream, ostream, 0, tb_null, tb_null);
else save = tb_transfer(istream, fstream, 0, tb_null, tb_null);
// trace
tb_trace_i("save: %lld bytes, size: %lld bytes", save, tb_stream_size(istream));
}
// exit fstream
tb_stream_exit(fstream);
// exit istream
tb_stream_exit(istream);
// exit ostream
tb_stream_exit(ostream);
return 0;
}
tbox-1.7.6/src/demo/stream/stream/charset.c 0000664 0000000 0000000 00000002714 14671175054 0020615 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
#ifdef TB_CONFIG_MODULE_HAVE_CHARSET
tb_int_t tb_demo_stream_charset_main(tb_int_t argc, tb_char_t** argv)
{
// init istream
tb_stream_ref_t istream = tb_stream_init_from_url(argv[1]);
// init ostream
tb_stream_ref_t ostream = tb_stream_init_from_file(argv[2], TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC);
// filter istream or ostream?
tb_stream_ref_t iostream = istream;
// tb_stream_ref_t iostream = ostream;
// init fstream
tb_stream_ref_t fstream = tb_stream_init_filter_from_charset(iostream, tb_charset_type(argv[3]), tb_charset_type(argv[4]));
// done
if (istream && ostream && fstream)
{
// save it
tb_hong_t save = 0;
if (iostream == istream) save = tb_transfer(fstream, ostream, 0, tb_null, tb_null);
else save = tb_transfer(istream, fstream, 0, tb_null, tb_null);
// trace
tb_trace_i("save: %lld bytes, size: %lld bytes", save, tb_stream_size(istream));
}
// exit fstream
tb_stream_exit(fstream);
// exit istream
tb_stream_exit(istream);
// exit ostream
tb_stream_exit(ostream);
return 0;
}
#else
tb_int_t tb_demo_stream_charset_main(tb_int_t argc, tb_char_t** argv)
{
return 0;
}
#endif
tbox-1.7.6/src/demo/stream/stream/null.c 0000664 0000000 0000000 00000002410 14671175054 0020127 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_stream_null_main(tb_int_t argc, tb_char_t** argv)
{
// init istream
tb_stream_ref_t istream = tb_stream_init_from_url(argv[1]);
// init ostream
tb_stream_ref_t ostream = tb_stream_init_from_file(argv[2], TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC);
// filter istream or ostream?
tb_stream_ref_t iostream = istream;
// tb_stream_ref_t iostream = ostream;
// init fstream
tb_stream_ref_t fstream = tb_stream_init_filter_from_null(iostream);
// done
if (istream && ostream && fstream)
{
// save it
tb_hong_t save = 0;
if (iostream == istream) save = tb_transfer(fstream, ostream, 0, tb_null, tb_null);
else save = tb_transfer(istream, fstream, 0, tb_null, tb_null);
// trace
tb_trace_i("save: %lld bytes, size: %lld bytes", save, tb_stream_size(istream));
}
// exit fstream
tb_stream_exit(fstream);
// exit istream
tb_stream_exit(istream);
// exit ostream
tb_stream_exit(ostream);
return 0;
}
tbox-1.7.6/src/demo/stream/stream/zip.c 0000664 0000000 0000000 00000004314 14671175054 0017764 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
#ifdef TB_CONFIG_MODULE_HAVE_ZIP
tb_int_t tb_demo_stream_zip_main(tb_int_t argc, tb_char_t** argv)
{
// init istream
tb_stream_ref_t istream = tb_stream_init_from_url(argv[1]);
// init ostream
tb_stream_ref_t ostream = tb_stream_init_from_file(argv[2], TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC);
// filter istream or ostream?
tb_stream_ref_t iostream = istream;
// tb_stream_ref_t iostream = ostream;
// init fstream
// tb_stream_ref_t fstream = tb_stream_init_filter_from_zip(iostream, TB_ZIP_ALGO_RLC, TB_ZIP_ACTION_INFLATE);
// tb_stream_ref_t fstream = tb_stream_init_filter_from_zip(iostream, TB_ZIP_ALGO_RLC, TB_ZIP_ACTION_DEFLATE);
// tb_stream_ref_t fstream = tb_stream_init_filter_from_zip(iostream, TB_ZIP_ALGO_ZLIB, TB_ZIP_ACTION_INFLATE);
// tb_stream_ref_t fstream = tb_stream_init_filter_from_zip(iostream, TB_ZIP_ALGO_ZLIB, TB_ZIP_ACTION_DEFLATE);
// tb_stream_ref_t fstream = tb_stream_init_filter_from_zip(iostream, TB_ZIP_ALGO_GZIP, TB_ZIP_ACTION_INFLATE);
tb_stream_ref_t fstream = tb_stream_init_filter_from_zip(iostream, TB_ZIP_ALGO_GZIP, TB_ZIP_ACTION_DEFLATE);
// tb_stream_ref_t fstream = tb_stream_init_filter_from_zip(iostream, TB_ZIP_ALGO_ZLIBRAW, TB_ZIP_ACTION_INFLATE);
// tb_stream_ref_t fstream = tb_stream_init_filter_from_zip(iostream, TB_ZIP_ALGO_ZLIBRAW, TB_ZIP_ACTION_DEFLATE);
// done
if (istream && ostream && fstream)
{
// save it
tb_hong_t save = 0;
if (iostream == istream) save = tb_transfer(fstream, ostream, 0, tb_null, tb_null);
else save = tb_transfer(istream, fstream, 0, tb_null, tb_null);
// trace
tb_trace_i("save: %lld bytes, size: %lld bytes", save, tb_stream_size(istream));
}
// exit fstream
tb_stream_exit(fstream);
// exit istream
tb_stream_exit(istream);
// exit ostream
tb_stream_exit(ostream);
return 0;
}
#else
tb_int_t tb_demo_stream_zip_main(tb_int_t argc, tb_char_t** argv)
{
return 0;
}
#endif
tbox-1.7.6/src/demo/string/ 0000775 0000000 0000000 00000000000 14671175054 0015534 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/demo/string/static_string.c 0000664 0000000 0000000 00000001172 14671175054 0020556 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_string_static_string_main(tb_int_t argc, tb_char_t** argv)
{
tb_static_string_t s;
tb_char_t b[4096];
tb_static_string_init(&s, b, 4096);
tb_static_string_cstrcpy(&s, "hello");
tb_static_string_chrcat(&s, ' ');
tb_static_string_cstrfcat(&s, "%s", "world");
tb_trace_i("%s", tb_static_string_cstr(&s));
tb_static_string_exit(&s);
return 0;
}
tbox-1.7.6/src/demo/string/string.c 0000664 0000000 0000000 00000001165 14671175054 0017211 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_string_string_main(tb_int_t argc, tb_char_t** argv)
{
tb_string_t s;
tb_string_init(&s);
tb_string_cstrcpy(&s, "hello");
tb_string_chrcat(&s, ' ');
tb_string_cstrfcat(&s, "%s", "world");
tb_string_chrcat(&s, ' ');
tb_string_chrncat(&s, 'x', 5);
tb_trace_i("%d: %s", tb_string_size(&s), tb_string_cstr(&s));
tb_string_exit(&s);
return 0;
}
tbox-1.7.6/src/demo/utils/ 0000775 0000000 0000000 00000000000 14671175054 0015366 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/demo/utils/base32.c 0000664 0000000 0000000 00000001045 14671175054 0016611 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_utils_base32_main(tb_int_t argc, tb_char_t** argv)
{
tb_char_t ob[4096];
//tb_size_t on = tb_base32_encode(argv[1], tb_strlen(argv[1]), ob, 4096);
tb_size_t on = tb_base32_decode((tb_byte_t const*)argv[1], tb_strlen(argv[1]), ob, 4096);
tb_printf("%s: %lu\n", ob, on);
return 0;
}
tbox-1.7.6/src/demo/utils/base64.c 0000664 0000000 0000000 00000001061 14671175054 0016614 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_utils_base64_main(tb_int_t argc, tb_char_t** argv)
{
tb_char_t ob[4096] = {0};
tb_size_t on = tb_base64_encode((tb_byte_t*)argv[1], tb_strlen(argv[1]), ob, 4096);
//tb_size_t on = tb_base64_decode((tb_byte_t*)argv[1], tb_strlen(argv[1]), ob, 4096);
tb_printf("%s: %lu\n", ob, on);
return 0;
}
tbox-1.7.6/src/demo/utils/bits.c 0000664 0000000 0000000 00000107606 14671175054 0016505 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* test
*/
static tb_void_t tb_test_bits_swap_u16()
{
__tb_volatile__ tb_uint16_t x = 0x1234;
__tb_volatile__ tb_size_t n = 100000001;
__tb_volatile__ tb_hong_t dt = tb_mclock();
while (n--) x = tb_bits_swap_u16(x);
dt = tb_mclock() - dt;
tb_trace_i("[bitops]: swap_u16: %x => %x, %llu ms", 0x1234, x, dt);
}
static tb_void_t tb_test_bits_swap_u32()
{
__tb_volatile__ tb_uint32_t x = 0x12345678;
__tb_volatile__ tb_size_t n = 100000001;
__tb_volatile__ tb_hong_t dt = tb_mclock();
while (n--) x = tb_bits_swap_u32(x);
dt = tb_mclock() - dt;
tb_trace_i("[bitops]: swap_u32: %x => %x, %llu ms", 0x12345678, x, dt);
}
static tb_void_t tb_test_bits_swap_u64()
{
__tb_volatile__ tb_hize_t x = 0x12345678;
__tb_volatile__ tb_size_t n = 100000001;
__tb_volatile__ tb_hong_t dt = tb_mclock();
while (n--) x = tb_bits_swap_u64(x);
dt = tb_mclock() - dt;
tb_trace_i("[bitops]: swap_u64: %x => %llx, %llu ms", 0x12345678, x, dt);
}
static tb_void_t tb_test_bits_ubits32(tb_uint32_t x)
{
__tb_volatile__ tb_size_t b = 0;
__tb_volatile__ tb_size_t n = 0;
__tb_volatile__ tb_hong_t ts = 0;
__tb_volatile__ tb_hong_t tg = 0;
for (b = 0; b < 8; ++b)
{
tb_trace_i("[bitops]: ubits32 b: %d x: %x", b, x);
for (n = 0; n <= 32; ++n)
{
tb_byte_t p[256] = {0};
__tb_volatile__ tb_size_t n1 = 100000;
__tb_volatile__ tb_size_t n2 = 100000;
__tb_volatile__ tb_uint32_t y = 0;
__tb_volatile__ tb_hong_t t1, t2;
__tb_volatile__ tb_uint32_t xx = n < 32? (x & ((tb_uint32_t)(1 << n) - 1)) : x;
t1 = tb_mclock();
while (n1--) tb_bits_set_ubits32(p, b, x, n);
t1 = tb_mclock() - t1;
ts += t1;
t2 = tb_mclock();
while (n2--) y = tb_bits_get_ubits32(p, b, n);
t2 = tb_mclock() - t2;
tg += t1;
if (xx != y)
{
tb_trace_i("[bitops]: ubits32 set: b: %x, n: %x, x: %x, %llu ms", b, n, xx, t1);
tb_trace_i("[bitops]: ubits32 get: b: %x, n: %x, y: %x, %llu ms", b, n, y, t2);
}
}
}
tb_trace_i("[bitops]: ubits32 set: %llu ms, get: %llu ms", ts, tg);
}
static tb_void_t tb_test_bits_sbits32(tb_sint32_t x)
{
__tb_volatile__ tb_size_t b = 0;
__tb_volatile__ tb_size_t n = 0;
__tb_volatile__ tb_hong_t ts = 0;
__tb_volatile__ tb_hong_t tg = 0;
for (b = 0; b < 8; ++b)
{
tb_trace_i("[bitops]: sbits32 b: %d x: %d", b, x);
for (n = 2; n <= 32; ++n)
{
tb_byte_t p[256] = {0};
__tb_volatile__ tb_size_t n1 = 100000;
__tb_volatile__ tb_size_t n2 = 100000;
__tb_volatile__ tb_sint32_t y = 0;
__tb_volatile__ tb_hong_t t1, t2;
__tb_volatile__ tb_sint32_t xx = ((x >> 31) << (n - 1)) | (x & ((tb_uint32_t)(1 << (n - 1)) - 1));
t1 = tb_mclock();
while (n1--) tb_bits_set_sbits32(p, b, x, n);
t1 = tb_mclock() - t1;
ts += t1;
t2 = tb_mclock();
while (n2--) y = tb_bits_get_sbits32(p, b, n);
t2 = tb_mclock() - t2;
tg += t1;
if (xx != y)
{
tb_trace_i("[bitops]: sbits32 set: b: %d, n: %u, x: %d, %llu ms", b, n, xx, t1);
tb_trace_i("[bitops]: sbits32 get: b: %u, n: %u, y: %d, %llu ms", b, n, y, t2);
}
}
}
tb_trace_i("[bitops]: sbits32 set: %llu ms, get: %llu ms", ts, tg);
}
static tb_void_t tb_test_bits_u32_be(tb_uint32_t x)
{
tb_byte_t p[8] = {0};
__tb_volatile__ tb_uint32_t y = 0;
__tb_volatile__ tb_size_t n1 = 100000;
__tb_volatile__ tb_size_t n2 = 100000;
__tb_volatile__ tb_hong_t ts = 0;
__tb_volatile__ tb_hong_t tg = 0;
__tb_volatile__ tb_hong_t t1, t2;
t1 = tb_mclock();
while (n1--) tb_bits_set_u32_be(p, x);
t1 = tb_mclock() - t1;
ts += t1;
t2 = tb_mclock();
while (n2--) y = tb_bits_get_u32_be(p);
t2 = tb_mclock() - t2;
tg += t1;
tb_trace_i("[bitops]: u32_be set: x: %x, %llu ms, get: y: %x, %llu ms", x, ts, y, tg);
}
static tb_void_t tb_test_bits_u32_le(tb_uint32_t x)
{
tb_byte_t p[8] = {0};
__tb_volatile__ tb_uint32_t y = 0;
__tb_volatile__ tb_size_t n1 = 100000;
__tb_volatile__ tb_size_t n2 = 100000;
__tb_volatile__ tb_hong_t ts = 0;
__tb_volatile__ tb_hong_t tg = 0;
__tb_volatile__ tb_hong_t t1, t2;
t1 = tb_mclock();
while (n1--) tb_bits_set_u32_le(p, x);
t1 = tb_mclock() - t1;
ts += t1;
t2 = tb_mclock();
while (n2--) y = tb_bits_get_u32_le(p);
t2 = tb_mclock() - t2;
tg += t1;
tb_trace_i("[bitops]: u32_le set: x: %x, %llu ms, get: y: %x, %llu ms", x, ts, y, tg);
}
static tb_void_t tb_test_bits_u24_be(tb_uint32_t x)
{
tb_byte_t p[8] = {0};
__tb_volatile__ tb_uint32_t y = 0;
__tb_volatile__ tb_size_t n1 = 100000;
__tb_volatile__ tb_size_t n2 = 100000;
__tb_volatile__ tb_hong_t ts = 0;
__tb_volatile__ tb_hong_t tg = 0;
__tb_volatile__ tb_hong_t t1, t2;
t1 = tb_mclock();
while (n1--) tb_bits_set_u24_be(p, x);
t1 = tb_mclock() - t1;
ts += t1;
t2 = tb_mclock();
while (n2--) y = tb_bits_get_u24_be(p);
t2 = tb_mclock() - t2;
tg += t1;
tb_trace_i("[bitops]: u24_be set: x: %x, %llu ms, get: y: %x, %llu ms", x, ts, y, tg);
}
static tb_void_t tb_test_bits_u24_le(tb_uint32_t x)
{
tb_byte_t p[8] = {0};
__tb_volatile__ tb_uint32_t y = 0;
__tb_volatile__ tb_size_t n1 = 100000;
__tb_volatile__ tb_size_t n2 = 100000;
__tb_volatile__ tb_hong_t ts = 0;
__tb_volatile__ tb_hong_t tg = 0;
__tb_volatile__ tb_hong_t t1, t2;
t1 = tb_mclock();
while (n1--) tb_bits_set_u24_le(p, x);
t1 = tb_mclock() - t1;
ts += t1;
t2 = tb_mclock();
while (n2--) y = tb_bits_get_u24_le(p);
t2 = tb_mclock() - t2;
tg += t1;
tb_trace_i("[bitops]: u24_le set: x: %x, %llu ms, get: y: %x, %llu ms", x, ts, y, tg);
}
static tb_void_t tb_test_bits_u16_be(tb_uint16_t x)
{
tb_byte_t p[8] = {0};
__tb_volatile__ tb_uint16_t y = 0;
__tb_volatile__ tb_size_t n1 = 100000;
__tb_volatile__ tb_size_t n2 = 100000;
__tb_volatile__ tb_hong_t ts = 0;
__tb_volatile__ tb_hong_t tg = 0;
__tb_volatile__ tb_hong_t t1, t2;
t1 = tb_mclock();
while (n1--) tb_bits_set_u16_be(p, x);
t1 = tb_mclock() - t1;
ts += t1;
t2 = tb_mclock();
while (n2--) y = tb_bits_get_u16_be(p);
t2 = tb_mclock() - t2;
tg += t1;
tb_trace_i("[bitops]: u16_be set: x: %x, %llu ms, get: y: %x, %llu ms", x, ts, y, tg);
}
static tb_void_t tb_test_bits_u16_le(tb_uint16_t x)
{
tb_byte_t p[8] = {0};
__tb_volatile__ tb_uint16_t y = 0;
__tb_volatile__ tb_size_t n1 = 100000;
__tb_volatile__ tb_size_t n2 = 100000;
__tb_volatile__ tb_hong_t ts = 0;
__tb_volatile__ tb_hong_t tg = 0;
__tb_volatile__ tb_hong_t t1, t2;
t1 = tb_mclock();
while (n1--) tb_bits_set_u16_le(p, x);
t1 = tb_mclock() - t1;
ts += t1;
t2 = tb_mclock();
while (n2--) y = tb_bits_get_u16_le(p);
t2 = tb_mclock() - t2;
tg += t1;
tb_trace_i("[bitops]: u16_le set: x: %x, %llu ms, get: y: %x, %llu ms", x, ts, y, tg);
}
static tb_void_t tb_test_bits_s32_be(tb_sint32_t x)
{
tb_byte_t p[8] = {0};
__tb_volatile__ tb_sint32_t y = 0;
__tb_volatile__ tb_size_t n1 = 100000;
__tb_volatile__ tb_size_t n2 = 100000;
__tb_volatile__ tb_hong_t ts = 0;
__tb_volatile__ tb_hong_t tg = 0;
__tb_volatile__ tb_hong_t t1, t2;
t1 = tb_mclock();
while (n1--) tb_bits_set_s32_be(p, x);
t1 = tb_mclock() - t1;
ts += t1;
t2 = tb_mclock();
while (n2--) y = tb_bits_get_s32_be(p);
t2 = tb_mclock() - t2;
tg += t1;
tb_trace_i("[bitops]: s32_be set: x: %d, %llu ms, get: y: %d, %llu ms", x, ts, y, tg);
}
static tb_void_t tb_test_bits_s32_le(tb_sint32_t x)
{
tb_byte_t p[8] = {0};
__tb_volatile__ tb_sint32_t y = 0;
__tb_volatile__ tb_size_t n1 = 100000;
__tb_volatile__ tb_size_t n2 = 100000;
__tb_volatile__ tb_hong_t ts = 0;
__tb_volatile__ tb_hong_t tg = 0;
__tb_volatile__ tb_hong_t t1, t2;
t1 = tb_mclock();
while (n1--) tb_bits_set_s32_le(p, x);
t1 = tb_mclock() - t1;
ts += t1;
t2 = tb_mclock();
while (n2--) y = tb_bits_get_s32_le(p);
t2 = tb_mclock() - t2;
tg += t1;
tb_trace_i("[bitops]: s32_le set: x: %d, %llu ms, get: y: %d, %llu ms", x, ts, y, tg);
}
static tb_void_t tb_test_bits_s24_be(tb_sint32_t x)
{
tb_byte_t p[8] = {0};
__tb_volatile__ tb_sint32_t y = 0;
__tb_volatile__ tb_size_t n1 = 100000;
__tb_volatile__ tb_size_t n2 = 100000;
__tb_volatile__ tb_hong_t ts = 0;
__tb_volatile__ tb_hong_t tg = 0;
__tb_volatile__ tb_hong_t t1, t2;
t1 = tb_mclock();
while (n1--) tb_bits_set_s24_be(p, x);
t1 = tb_mclock() - t1;
ts += t1;
t2 = tb_mclock();
while (n2--) y = tb_bits_get_s24_be(p);
t2 = tb_mclock() - t2;
tg += t1;
tb_trace_i("[bitops]: s24_be set: x: %d, %llu ms, get: y: %d, %llu ms", x, ts, y, tg);
}
static tb_void_t tb_test_bits_s24_le(tb_sint32_t x)
{
tb_byte_t p[8] = {0};
__tb_volatile__ tb_sint32_t y = 0;
__tb_volatile__ tb_size_t n1 = 100000;
__tb_volatile__ tb_size_t n2 = 100000;
__tb_volatile__ tb_hong_t ts = 0;
__tb_volatile__ tb_hong_t tg = 0;
__tb_volatile__ tb_hong_t t1, t2;
t1 = tb_mclock();
while (n1--) tb_bits_set_s24_le(p, x);
t1 = tb_mclock() - t1;
ts += t1;
t2 = tb_mclock();
while (n2--) y = tb_bits_get_s24_le(p);
t2 = tb_mclock() - t2;
tg += t1;
tb_trace_i("[bitops]: s24_le set: x: %d, %llu ms, get: y: %d, %llu ms", x, ts, y, tg);
}
static tb_void_t tb_test_bits_s16_be(tb_sint16_t x)
{
tb_byte_t p[8] = {0};
__tb_volatile__ tb_sint16_t y = 0;
__tb_volatile__ tb_size_t n1 = 100000;
__tb_volatile__ tb_size_t n2 = 100000;
__tb_volatile__ tb_hong_t ts = 0;
__tb_volatile__ tb_hong_t tg = 0;
__tb_volatile__ tb_hong_t t1, t2;
t1 = tb_mclock();
while (n1--) tb_bits_set_s16_be(p, x);
t1 = tb_mclock() - t1;
ts += t1;
t2 = tb_mclock();
while (n2--) y = tb_bits_get_s16_be(p);
t2 = tb_mclock() - t2;
tg += t1;
tb_trace_i("[bitops]: s16_be set: x: %d, %llu ms, get: y: %d, %llu ms", x, ts, y, tg);
}
static tb_void_t tb_test_bits_s16_le(tb_sint16_t x)
{
tb_byte_t p[8] = {0};
__tb_volatile__ tb_sint16_t y = 0;
__tb_volatile__ tb_size_t n1 = 100000;
__tb_volatile__ tb_size_t n2 = 100000;
__tb_volatile__ tb_hong_t ts = 0;
__tb_volatile__ tb_hong_t tg = 0;
__tb_volatile__ tb_hong_t t1, t2;
t1 = tb_mclock();
while (n1--) tb_bits_set_s16_le(p, x);
t1 = tb_mclock() - t1;
ts += t1;
t2 = tb_mclock();
while (n2--) y = tb_bits_get_s16_le(p);
t2 = tb_mclock() - t2;
tg += t1;
tb_trace_i("[bitops]: s16_le set: x: %d, %llu ms, get: y: %d, %llu ms", x, ts, y, tg);
}
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
static tb_void_t tb_test_bits_double_bbe(tb_double_t x)
{
tb_byte_t p[8] = {0};
__tb_volatile__ tb_double_t y = 0;
__tb_volatile__ tb_size_t n1 = 100000;
__tb_volatile__ tb_size_t n2 = 100000;
__tb_volatile__ tb_hong_t ts = 0;
__tb_volatile__ tb_hong_t tg = 0;
__tb_volatile__ tb_hong_t t1, t2;
t1 = tb_mclock();
while (n1--) tb_bits_set_double_bbe(p, x);
t1 = tb_mclock() - t1;
ts += t1;
t2 = tb_mclock();
while (n2--) y = tb_bits_get_double_bbe(p);
t2 = tb_mclock() - t2;
tg += t1;
tb_trace_i("[bitops]: double_bbe set: x: %lf, %llu ms, get: y: %lf, %llu ms", x, ts, y, tg);
}
static tb_void_t tb_test_bits_double_ble(tb_double_t x)
{
tb_byte_t p[8] = {0};
__tb_volatile__ tb_double_t y = 0;
__tb_volatile__ tb_size_t n1 = 100000;
__tb_volatile__ tb_size_t n2 = 100000;
__tb_volatile__ tb_hong_t ts = 0;
__tb_volatile__ tb_hong_t tg = 0;
__tb_volatile__ tb_hong_t t1, t2;
t1 = tb_mclock();
while (n1--) tb_bits_set_double_ble(p, x);
t1 = tb_mclock() - t1;
ts += t1;
t2 = tb_mclock();
while (n2--) y = tb_bits_get_double_ble(p);
t2 = tb_mclock() - t2;
tg += t1;
tb_trace_i("[bitops]: double_ble set: x: %lf, %llu ms, get: y: %lf, %llu ms", x, ts, y, tg);
}
static tb_void_t tb_test_bits_double_lbe(tb_double_t x)
{
tb_byte_t p[8] = {0};
__tb_volatile__ tb_double_t y = 0;
__tb_volatile__ tb_size_t n1 = 100000;
__tb_volatile__ tb_size_t n2 = 100000;
__tb_volatile__ tb_hong_t ts = 0;
__tb_volatile__ tb_hong_t tg = 0;
__tb_volatile__ tb_hong_t t1, t2;
t1 = tb_mclock();
while (n1--) tb_bits_set_double_lbe(p, x);
t1 = tb_mclock() - t1;
ts += t1;
t2 = tb_mclock();
while (n2--) y = tb_bits_get_double_lbe(p);
t2 = tb_mclock() - t2;
tg += t1;
tb_trace_i("[bitops]: double_lbe set: x: %lf, %llu ms, get: y: %lf, %llu ms", x, ts, y, tg);
}
static tb_void_t tb_test_bits_double_lle(tb_double_t x)
{
tb_byte_t p[8] = {0};
__tb_volatile__ tb_double_t y = 0;
__tb_volatile__ tb_size_t n1 = 100000;
__tb_volatile__ tb_size_t n2 = 100000;
__tb_volatile__ tb_hong_t ts = 0;
__tb_volatile__ tb_hong_t tg = 0;
__tb_volatile__ tb_hong_t t1, t2;
t1 = tb_mclock();
while (n1--) tb_bits_set_double_lle(p, x);
t1 = tb_mclock() - t1;
ts += t1;
t2 = tb_mclock();
while (n2--) y = tb_bits_get_double_lle(p);
t2 = tb_mclock() - t2;
tg += t1;
tb_trace_i("[bitops]: double_lle set: x: %lf, %llu ms, get: y: %lf, %llu ms", x, ts, y, tg);
}
static tb_void_t tb_test_bits_float_be(tb_float_t x)
{
tb_byte_t p[8] = {0};
__tb_volatile__ tb_float_t y = 0;
__tb_volatile__ tb_size_t n1 = 100000;
__tb_volatile__ tb_size_t n2 = 100000;
__tb_volatile__ tb_hong_t ts = 0;
__tb_volatile__ tb_hong_t tg = 0;
__tb_volatile__ tb_hong_t t1, t2;
t1 = tb_mclock();
while (n1--) tb_bits_set_float_be(p, x);
t1 = tb_mclock() - t1;
ts += t1;
t2 = tb_mclock();
while (n2--) y = tb_bits_get_float_be(p);
t2 = tb_mclock() - t2;
tg += t1;
tb_trace_i("[bitops]: float_be set: x: %f, %llu ms, get: y: %f, %llu ms", x, ts, y, tg);
}
static tb_void_t tb_test_bits_float_le(tb_float_t x)
{
tb_byte_t p[8] = {0};
__tb_volatile__ tb_float_t y = 0;
__tb_volatile__ tb_size_t n1 = 100000;
__tb_volatile__ tb_size_t n2 = 100000;
__tb_volatile__ tb_hong_t ts = 0;
__tb_volatile__ tb_hong_t tg = 0;
__tb_volatile__ tb_hong_t t1, t2;
t1 = tb_mclock();
while (n1--) tb_bits_set_float_le(p, x);
t1 = tb_mclock() - t1;
ts += t1;
t2 = tb_mclock();
while (n2--) y = tb_bits_get_float_le(p);
t2 = tb_mclock() - t2;
tg += t1;
tb_trace_i("[bitops]: float_le set: x: %f, %llu ms, get: y: %f, %llu ms", x, ts, y, tg);
}
#endif
static tb_void_t tb_test_bits_cl0_u32_be(tb_uint32_t x)
{
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 100000;
__tb_volatile__ tb_hong_t t = tb_mclock();
while (n--) i = tb_bits_cl0_u32_be(x);
t = tb_mclock() - t;
tb_trace_i("[bitops]: u32_be: cl0: %032lb => %lu, %lld ms", x, i, t);
}
static tb_void_t tb_test_bits_cl0_u32_le(tb_uint32_t x)
{
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 100000;
__tb_volatile__ tb_hong_t t = tb_mclock();
while (n--) i = tb_bits_cl0_u32_le(x);
t = tb_mclock() - t;
tb_trace_i("[bitops]: u32_le: cl0: %032lb => %lu, %lld ms", x, i, t);
}
static tb_void_t tb_test_bits_cl0_u64_be(tb_uint64_t x)
{
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 100000;
__tb_volatile__ tb_hong_t t = tb_mclock();
while (n--) i = tb_bits_cl0_u64_be(x);
t = tb_mclock() - t;
tb_trace_i("[bitops]: u64_be: cl0: %064llb => %lu, %lld ms", x, i, t);
}
static tb_void_t tb_test_bits_cl0_u64_le(tb_uint64_t x)
{
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 100000;
__tb_volatile__ tb_hong_t t = tb_mclock();
while (n--) i = tb_bits_cl0_u64_le(x);
t = tb_mclock() - t;
tb_trace_i("[bitops]: u64_le: cl0: %064llb => %lu, %lld ms", x, i, t);
}
static tb_void_t tb_test_bits_cl1_u32_be(tb_uint32_t x)
{
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 100000;
__tb_volatile__ tb_hong_t t = tb_mclock();
while (n--) i = tb_bits_cl1_u32_be(x);
t = tb_mclock() - t;
tb_trace_i("[bitops]: u32_be: cl1: %032lb => %lu, %lld ms", x, i, t);
}
static tb_void_t tb_test_bits_cl1_u32_le(tb_uint32_t x)
{
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 100000;
__tb_volatile__ tb_hong_t t = tb_mclock();
while (n--) i = tb_bits_cl1_u32_le(x);
t = tb_mclock() - t;
tb_trace_i("[bitops]: u32_le: cl1: %032lb => %lu, %lld ms", x, i, t);
}
static tb_void_t tb_test_bits_cl1_u64_be(tb_uint64_t x)
{
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 100000;
__tb_volatile__ tb_hong_t t = tb_mclock();
while (n--) i = tb_bits_cl1_u64_be(x);
t = tb_mclock() - t;
tb_trace_i("[bitops]: u64_be: cl1: %064llb => %lu, %lld ms", x, i, t);
}
static tb_void_t tb_test_bits_cl1_u64_le(tb_uint64_t x)
{
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 100000;
__tb_volatile__ tb_hong_t t = tb_mclock();
while (n--) i = tb_bits_cl1_u64_le(x);
t = tb_mclock() - t;
tb_trace_i("[bitops]: u64_le: cl1: %064llb => %lu, %lld ms", x, i, t);
}
static tb_void_t tb_test_bits_cb0_u32(tb_uint32_t x)
{
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 100000;
__tb_volatile__ tb_hong_t t = tb_mclock();
while (n--) i = tb_bits_cb0_u32(x);
t = tb_mclock() - t;
tb_trace_i("[bitops]: u32: cb0: %032lb => %lu, %lld ms", x, i, t);
}
static tb_void_t tb_test_bits_cb0_u64(tb_uint64_t x)
{
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 100000;
__tb_volatile__ tb_hong_t t = tb_mclock();
while (n--) i = tb_bits_cb0_u64(x);
t = tb_mclock() - t;
tb_trace_i("[bitops]: u64: cb0: %064llb => %lu, %lld ms", x, i, t);
}
static tb_void_t tb_test_bits_cb1_u32(tb_uint32_t x)
{
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 100000;
__tb_volatile__ tb_hong_t t = tb_mclock();
while (n--) i = tb_bits_cb1_u32(x);
t = tb_mclock() - t;
tb_trace_i("[bitops]: u32: cb1: %032lb => %lu, %lld ms", x, i, t);
}
static tb_void_t tb_test_bits_cb1_u64(tb_uint64_t x)
{
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 100000;
__tb_volatile__ tb_hong_t t = tb_mclock();
while (n--) i = tb_bits_cb1_u64(x);
t = tb_mclock() - t;
tb_trace_i("[bitops]: u64: cb1: %064llb => %lu, %lld ms", x, i, t);
}
static tb_void_t tb_test_bits_fb0_u32_be(tb_uint32_t x)
{
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 100000;
__tb_volatile__ tb_hong_t t = tb_mclock();
while (n--) i = tb_bits_fb0_u32_be(x);
t = tb_mclock() - t;
tb_trace_i("[bitops]: u32_be: fb0: %032lb => %lu, %lld ms", x, i, t);
}
static tb_void_t tb_test_bits_fb0_u32_le(tb_uint32_t x)
{
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 100000;
__tb_volatile__ tb_hong_t t = tb_mclock();
while (n--) i = tb_bits_fb0_u32_le(x);
t = tb_mclock() - t;
tb_trace_i("[bitops]: u32_le: fb0: %032lb => %lu, %lld ms", x, i, t);
}
static tb_void_t tb_test_bits_fb0_u64_be(tb_uint64_t x)
{
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 100000;
__tb_volatile__ tb_hong_t t = tb_mclock();
while (n--) i = tb_bits_fb0_u64_be(x);
t = tb_mclock() - t;
tb_trace_i("[bitops]: u64_be: fb0: %064llb => %lu, %lld ms", x, i, t);
}
static tb_void_t tb_test_bits_fb0_u64_le(tb_uint64_t x)
{
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 100000;
__tb_volatile__ tb_hong_t t = tb_mclock();
while (n--) i = tb_bits_fb0_u64_le(x);
t = tb_mclock() - t;
tb_trace_i("[bitops]: u64_le: fb0: %064llb => %lu, %lld ms", x, i, t);
}
static tb_void_t tb_test_bits_fb1_u32_be(tb_uint32_t x)
{
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 100000;
__tb_volatile__ tb_hong_t t = tb_mclock();
while (n--) i = tb_bits_fb1_u32_be(x);
t = tb_mclock() - t;
tb_trace_i("[bitops]: u32_be: fb1: %032lb => %lu, %lld ms", x, i, t);
}
static tb_void_t tb_test_bits_fb1_u32_le(tb_uint32_t x)
{
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 100000;
__tb_volatile__ tb_hong_t t = tb_mclock();
while (n--) i = tb_bits_fb1_u32_le(x);
t = tb_mclock() - t;
tb_trace_i("[bitops]: u32_le: fb1: %032lb => %lu, %lld ms", x, i, t);
}
static tb_void_t tb_test_bits_fb1_u64_be(tb_uint64_t x)
{
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 100000;
__tb_volatile__ tb_hong_t t = tb_mclock();
while (n--) i = tb_bits_fb1_u64_be(x);
t = tb_mclock() - t;
tb_trace_i("[bitops]: u64_be: fb1: %064llb => %lu, %lld ms", x, i, t);
}
static tb_void_t tb_test_bits_fb1_u64_le(tb_uint64_t x)
{
__tb_volatile__ tb_size_t i = 0;
__tb_volatile__ tb_size_t n = 100000;
__tb_volatile__ tb_hong_t t = tb_mclock();
while (n--) i = tb_bits_fb1_u64_le(x);
t = tb_mclock() - t;
tb_trace_i("[bitops]: u64_le: fb1: %064llb => %lu, %lld ms", x, i, t);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_utils_bits_main(tb_int_t argc, tb_char_t** argv)
{
#if 1
tb_test_bits_swap_u16();
tb_test_bits_swap_u32();
tb_test_bits_swap_u64();
#endif
#if 1
tb_trace_i("");
tb_test_bits_ubits32(0x87654321);
tb_test_bits_ubits32(0x12345678);
tb_trace_i("");
tb_test_bits_sbits32(0x87654321);
tb_test_bits_sbits32(0x12345678);
tb_trace_i("");
tb_test_bits_sbits32(-300);
tb_test_bits_sbits32(300);
tb_trace_i("");
tb_test_bits_u32_be(0x87654321);
tb_test_bits_u32_be(0x12345678);
tb_test_bits_u32_le(0x87654321);
tb_test_bits_u32_le(0x12345678);
tb_trace_i("");
tb_test_bits_u24_be(0x654321);
tb_test_bits_u24_be(0x345678);
tb_test_bits_u24_le(0x654321);
tb_test_bits_u24_le(0x345678);
tb_trace_i("");
tb_test_bits_u16_be(0x4321);
tb_test_bits_u16_be(0x5678);
tb_test_bits_u16_le(0x4321);
tb_test_bits_u16_le(0x5678);
tb_trace_i("");
tb_test_bits_s32_be(0x8765F321);
tb_test_bits_s32_be(0x1234F678);
tb_test_bits_s32_le(0x8765F321);
tb_test_bits_s32_le(0x1234F678);
tb_trace_i("");
tb_test_bits_s24_be(123456);
tb_test_bits_s24_be(-123456);
tb_test_bits_s24_le(123456);
tb_test_bits_s24_le(-123456);
tb_trace_i("");
tb_test_bits_s16_be(4321);
tb_test_bits_s16_be(-4321);
tb_test_bits_s16_le(4321);
tb_test_bits_s16_le(-4321);
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
tb_trace_i("");
tb_test_bits_double_bbe(3.1415926);
tb_test_bits_double_ble(3.1415926);
tb_test_bits_double_lbe(3.1415926);
tb_test_bits_double_lle(3.1415926);
tb_trace_i("");
tb_test_bits_float_be(3.1415926f);
tb_test_bits_float_le(3.1415926f);
tb_test_bits_float_be(3.1415926f);
tb_test_bits_float_le(3.1415926f);
#endif
#endif
#if 1
tb_trace_i("");
tb_test_bits_cl0_u32_be(0);
tb_test_bits_cl0_u32_be(1);
tb_test_bits_cl0_u32_be(2);
tb_test_bits_cl0_u32_be(8);
tb_test_bits_cl0_u32_be(123);
tb_test_bits_cl0_u32_be(123456);
tb_test_bits_cl0_u32_be(800000);
tb_test_bits_cl0_u32_be(31415926);
tb_test_bits_cl0_u32_be(0xffffffff);
tb_test_bits_cl0_u32_be(0xfffffff0);
tb_test_bits_cl0_u32_be(0x0fffffff);
tb_test_bits_cl0_u32_be(0xfff00fff);
tb_test_bits_cl0_u32_be(0x0ffffff0);
tb_test_bits_cl0_u32_be(0x0000000f);
tb_test_bits_cl0_u32_be(0xf0000000);
tb_trace_i("");
tb_test_bits_cl0_u32_le(0);
tb_test_bits_cl0_u32_le(1);
tb_test_bits_cl0_u32_le(2);
tb_test_bits_cl0_u32_le(8);
tb_test_bits_cl0_u32_le(123);
tb_test_bits_cl0_u32_le(123456);
tb_test_bits_cl0_u32_le(800000);
tb_test_bits_cl0_u32_le(31415926);
tb_test_bits_cl0_u32_le(0xffffffff);
tb_test_bits_cl0_u32_le(0xfffffff0);
tb_test_bits_cl0_u32_le(0x0fffffff);
tb_test_bits_cl0_u32_le(0xfff00fff);
tb_test_bits_cl0_u32_le(0x0ffffff0);
tb_test_bits_cl0_u32_le(0x0000000f);
tb_test_bits_cl0_u32_le(0xf0000000);
tb_trace_i("");
tb_test_bits_cl0_u64_be(0);
tb_test_bits_cl0_u64_be(1);
tb_test_bits_cl0_u64_be(2);
tb_test_bits_cl0_u64_be(8);
tb_test_bits_cl0_u64_be(123);
tb_test_bits_cl0_u64_be(123456);
tb_test_bits_cl0_u64_be(800000);
tb_test_bits_cl0_u64_be(31415926);
tb_test_bits_cl0_u64_be(0xffffffffffffffffull);
tb_test_bits_cl0_u64_be(0xfffffffffffffff0ull);
tb_test_bits_cl0_u64_be(0x0fffffffffffffffull);
tb_test_bits_cl0_u64_be(0xfff00ffffff00fffull);
tb_test_bits_cl0_u64_be(0x0ffffff00ffffff0ull);
tb_test_bits_cl0_u64_be(0x000000000000000full);
tb_test_bits_cl0_u64_be(0xf000000000000000ull);
tb_trace_i("");
tb_test_bits_cl0_u64_le(0);
tb_test_bits_cl0_u64_le(1);
tb_test_bits_cl0_u64_le(2);
tb_test_bits_cl0_u64_le(8);
tb_test_bits_cl0_u64_le(123);
tb_test_bits_cl0_u64_le(123456);
tb_test_bits_cl0_u64_le(800000);
tb_test_bits_cl0_u64_le(31415926);
tb_test_bits_cl0_u64_le(0xffffffffffffffffull);
tb_test_bits_cl0_u64_le(0xfffffffffffffff0ull);
tb_test_bits_cl0_u64_le(0x0fffffffffffffffull);
tb_test_bits_cl0_u64_le(0xfff00ffffff00fffull);
tb_test_bits_cl0_u64_le(0x0ffffff00ffffff0ull);
tb_test_bits_cl0_u64_le(0x000000000000000full);
tb_test_bits_cl0_u64_le(0xf000000000000000ull);
#endif
#if 1
tb_trace_i("");
tb_test_bits_cl1_u32_be(0);
tb_test_bits_cl1_u32_be(1);
tb_test_bits_cl1_u32_be(2);
tb_test_bits_cl1_u32_be(8);
tb_test_bits_cl1_u32_be(123);
tb_test_bits_cl1_u32_be(123456);
tb_test_bits_cl1_u32_be(800000);
tb_test_bits_cl1_u32_be(31415926);
tb_test_bits_cl1_u32_be(0xffffffff);
tb_test_bits_cl1_u32_be(0xfffffff0);
tb_test_bits_cl1_u32_be(0x0fffffff);
tb_test_bits_cl1_u32_be(0xfff00fff);
tb_test_bits_cl1_u32_be(0x0ffffff0);
tb_test_bits_cl1_u32_be(0x0000000f);
tb_test_bits_cl1_u32_be(0xf0000000);
tb_trace_i("");
tb_test_bits_cl1_u32_le(0);
tb_test_bits_cl1_u32_le(1);
tb_test_bits_cl1_u32_le(2);
tb_test_bits_cl1_u32_le(8);
tb_test_bits_cl1_u32_le(123);
tb_test_bits_cl1_u32_le(123456);
tb_test_bits_cl1_u32_le(800000);
tb_test_bits_cl1_u32_le(31415926);
tb_test_bits_cl1_u32_le(0xffffffff);
tb_test_bits_cl1_u32_le(0xfffffff0);
tb_test_bits_cl1_u32_le(0x0fffffff);
tb_test_bits_cl1_u32_le(0xfff00fff);
tb_test_bits_cl1_u32_le(0x0ffffff0);
tb_test_bits_cl1_u32_le(0x0000000f);
tb_test_bits_cl1_u32_le(0xf0000000);
tb_trace_i("");
tb_test_bits_cl1_u64_be(0);
tb_test_bits_cl1_u64_be(1);
tb_test_bits_cl1_u64_be(2);
tb_test_bits_cl1_u64_be(8);
tb_test_bits_cl1_u64_be(123);
tb_test_bits_cl1_u64_be(123456);
tb_test_bits_cl1_u64_be(800000);
tb_test_bits_cl1_u64_be(31415926);
tb_test_bits_cl1_u64_be(0xffffffffffffffffull);
tb_test_bits_cl1_u64_be(0xfffffffffffffff0ull);
tb_test_bits_cl1_u64_be(0x0fffffffffffffffull);
tb_test_bits_cl1_u64_be(0xfff00ffffff00fffull);
tb_test_bits_cl1_u64_be(0x0ffffff00ffffff0ull);
tb_test_bits_cl1_u64_be(0x000000000000000full);
tb_test_bits_cl1_u64_be(0xf000000000000000ull);
tb_trace_i("");
tb_test_bits_cl1_u64_le(0);
tb_test_bits_cl1_u64_le(1);
tb_test_bits_cl1_u64_le(2);
tb_test_bits_cl1_u64_le(8);
tb_test_bits_cl1_u64_le(123);
tb_test_bits_cl1_u64_le(123456);
tb_test_bits_cl1_u64_le(800000);
tb_test_bits_cl1_u64_le(31415926);
tb_test_bits_cl1_u64_le(0xffffffffffffffffull);
tb_test_bits_cl1_u64_le(0xfffffffffffffff0ull);
tb_test_bits_cl1_u64_le(0x0fffffffffffffffull);
tb_test_bits_cl1_u64_le(0xfff00ffffff00fffull);
tb_test_bits_cl1_u64_le(0x0ffffff00ffffff0ull);
tb_test_bits_cl1_u64_le(0x000000000000000full);
tb_test_bits_cl1_u64_le(0xf000000000000000ull);
#endif
#if 1
tb_trace_i("");
tb_test_bits_cb0_u32(0);
tb_test_bits_cb0_u32(1);
tb_test_bits_cb0_u32(2);
tb_test_bits_cb0_u32(8);
tb_test_bits_cb0_u32(123);
tb_test_bits_cb0_u32(123456);
tb_test_bits_cb0_u32(800000);
tb_test_bits_cb0_u32(31415926);
tb_test_bits_cb0_u32(0xffffffff);
tb_test_bits_cb0_u32(0xfffffff0);
tb_test_bits_cb0_u32(0x0fffffff);
tb_test_bits_cb0_u32(0xfff00fff);
tb_test_bits_cb0_u32(0x0ffffff0);
tb_test_bits_cb0_u32(0x0000000f);
tb_test_bits_cb0_u32(0xf0000000);
tb_trace_i("");
tb_test_bits_cb0_u64(0);
tb_test_bits_cb0_u64(1);
tb_test_bits_cb0_u64(2);
tb_test_bits_cb0_u64(8);
tb_test_bits_cb0_u64(123);
tb_test_bits_cb0_u64(123456);
tb_test_bits_cb0_u64(800000);
tb_test_bits_cb0_u64(31415926);
tb_test_bits_cb0_u64(0xffffffffffffffffull);
tb_test_bits_cb0_u64(0xfffffffffffffff0ull);
tb_test_bits_cb0_u64(0x0fffffffffffffffull);
tb_test_bits_cb0_u64(0xfff00ffffff00fffull);
tb_test_bits_cb0_u64(0x0ffffff00ffffff0ull);
tb_test_bits_cb0_u64(0x000000000000000full);
tb_test_bits_cb0_u64(0xf000000000000000ull);
#endif
#if 1
tb_trace_i("");
tb_test_bits_cb1_u32(0);
tb_test_bits_cb1_u32(1);
tb_test_bits_cb1_u32(2);
tb_test_bits_cb1_u32(8);
tb_test_bits_cb1_u32(123);
tb_test_bits_cb1_u32(123456);
tb_test_bits_cb1_u32(800000);
tb_test_bits_cb1_u32(31415926);
tb_test_bits_cb1_u32(0xffffffff);
tb_test_bits_cb1_u32(0xfffffff0);
tb_test_bits_cb1_u32(0x0fffffff);
tb_test_bits_cb1_u32(0xfff00fff);
tb_test_bits_cb1_u32(0x0ffffff0);
tb_test_bits_cb1_u32(0x0000000f);
tb_test_bits_cb1_u32(0xf0000000);
tb_trace_i("");
tb_test_bits_cb1_u64(0);
tb_test_bits_cb1_u64(1);
tb_test_bits_cb1_u64(2);
tb_test_bits_cb1_u64(8);
tb_test_bits_cb1_u64(123);
tb_test_bits_cb1_u64(123456);
tb_test_bits_cb1_u64(800000);
tb_test_bits_cb1_u64(31415926);
tb_test_bits_cb1_u64(0xffffffffffffffffull);
tb_test_bits_cb1_u64(0xfffffffffffffff0ull);
tb_test_bits_cb1_u64(0x0fffffffffffffffull);
tb_test_bits_cb1_u64(0xfff00ffffff00fffull);
tb_test_bits_cb1_u64(0x0ffffff00ffffff0ull);
tb_test_bits_cb1_u64(0x000000000000000full);
tb_test_bits_cb1_u64(0xf000000000000000ull);
#endif
#if 1
tb_trace_i("");
tb_test_bits_fb0_u32_be(0);
tb_test_bits_fb0_u32_be(1);
tb_test_bits_fb0_u32_be(2);
tb_test_bits_fb0_u32_be(8);
tb_test_bits_fb0_u32_be(123);
tb_test_bits_fb0_u32_be(123456);
tb_test_bits_fb0_u32_be(800000);
tb_test_bits_fb0_u32_be(31415926);
tb_test_bits_fb0_u32_be(0xffffffff);
tb_test_bits_fb0_u32_be(0xfffffff0);
tb_test_bits_fb0_u32_be(0x0fffffff);
tb_test_bits_fb0_u32_be(0xfff00fff);
tb_test_bits_fb0_u32_be(0x0ffffff0);
tb_test_bits_fb0_u32_be(0x0000000f);
tb_test_bits_fb0_u32_be(0xf0000000);
tb_trace_i("");
tb_test_bits_fb0_u32_le(0);
tb_test_bits_fb0_u32_le(1);
tb_test_bits_fb0_u32_le(2);
tb_test_bits_fb0_u32_le(8);
tb_test_bits_fb0_u32_le(123);
tb_test_bits_fb0_u32_le(123456);
tb_test_bits_fb0_u32_le(800000);
tb_test_bits_fb0_u32_le(31415926);
tb_test_bits_fb0_u32_le(0xffffffff);
tb_test_bits_fb0_u32_le(0xfffffff0);
tb_test_bits_fb0_u32_le(0x0fffffff);
tb_test_bits_fb0_u32_le(0xfff00fff);
tb_test_bits_fb0_u32_le(0x0ffffff0);
tb_test_bits_fb0_u32_le(0x0000000f);
tb_test_bits_fb0_u32_le(0xf0000000);
tb_trace_i("");
tb_test_bits_fb0_u64_be(0);
tb_test_bits_fb0_u64_be(1);
tb_test_bits_fb0_u64_be(2);
tb_test_bits_fb0_u64_be(8);
tb_test_bits_fb0_u64_be(123);
tb_test_bits_fb0_u64_be(123456);
tb_test_bits_fb0_u64_be(800000);
tb_test_bits_fb0_u64_be(31415926);
tb_test_bits_fb0_u64_be(0xffffffffffffffffull);
tb_test_bits_fb0_u64_be(0xfffffffffffffff0ull);
tb_test_bits_fb0_u64_be(0x0fffffffffffffffull);
tb_test_bits_fb0_u64_be(0xfff00ffffff00fffull);
tb_test_bits_fb0_u64_be(0x0ffffff00ffffff0ull);
tb_test_bits_fb0_u64_be(0x000000000000000full);
tb_test_bits_fb0_u64_be(0xf000000000000000ull);
tb_trace_i("");
tb_test_bits_fb0_u64_le(0);
tb_test_bits_fb0_u64_le(1);
tb_test_bits_fb0_u64_le(2);
tb_test_bits_fb0_u64_le(8);
tb_test_bits_fb0_u64_le(123);
tb_test_bits_fb0_u64_le(123456);
tb_test_bits_fb0_u64_le(800000);
tb_test_bits_fb0_u64_le(31415926);
tb_test_bits_fb0_u64_le(0xffffffffffffffffull);
tb_test_bits_fb0_u64_le(0xfffffffffffffff0ull);
tb_test_bits_fb0_u64_le(0x0fffffffffffffffull);
tb_test_bits_fb0_u64_le(0xfff00ffffff00fffull);
tb_test_bits_fb0_u64_le(0x0ffffff00ffffff0ull);
tb_test_bits_fb0_u64_le(0x000000000000000full);
tb_test_bits_fb0_u64_le(0xf000000000000000ull);
#endif
#if 1
tb_trace_i("");
tb_test_bits_fb1_u32_be(0);
tb_test_bits_fb1_u32_be(1);
tb_test_bits_fb1_u32_be(2);
tb_test_bits_fb1_u32_be(8);
tb_test_bits_fb1_u32_be(123);
tb_test_bits_fb1_u32_be(123456);
tb_test_bits_fb1_u32_be(800000);
tb_test_bits_fb1_u32_be(31415926);
tb_test_bits_fb1_u32_be(0xffffffff);
tb_test_bits_fb1_u32_be(0xfffffff0);
tb_test_bits_fb1_u32_be(0x0fffffff);
tb_test_bits_fb1_u32_be(0xfff00fff);
tb_test_bits_fb1_u32_be(0x0ffffff0);
tb_test_bits_fb1_u32_be(0x0000000f);
tb_test_bits_fb1_u32_be(0xf0000000);
tb_trace_i("");
tb_test_bits_fb1_u32_le(0);
tb_test_bits_fb1_u32_le(1);
tb_test_bits_fb1_u32_le(2);
tb_test_bits_fb1_u32_le(8);
tb_test_bits_fb1_u32_le(123);
tb_test_bits_fb1_u32_le(123456);
tb_test_bits_fb1_u32_le(800000);
tb_test_bits_fb1_u32_le(31415926);
tb_test_bits_fb1_u32_le(0xffffffff);
tb_test_bits_fb1_u32_le(0xfffffff0);
tb_test_bits_fb1_u32_le(0x0fffffff);
tb_test_bits_fb1_u32_le(0xfff00fff);
tb_test_bits_fb1_u32_le(0x0ffffff0);
tb_test_bits_fb1_u32_le(0x0000000f);
tb_test_bits_fb1_u32_le(0xf0000000);
tb_trace_i("");
tb_test_bits_fb1_u64_be(0);
tb_test_bits_fb1_u64_be(1);
tb_test_bits_fb1_u64_be(2);
tb_test_bits_fb1_u64_be(8);
tb_test_bits_fb1_u64_be(123);
tb_test_bits_fb1_u64_be(123456);
tb_test_bits_fb1_u64_be(800000);
tb_test_bits_fb1_u64_be(31415926);
tb_test_bits_fb1_u64_be(0xffffffffffffffffull);
tb_test_bits_fb1_u64_be(0xfffffffffffffff0ull);
tb_test_bits_fb1_u64_be(0x0fffffffffffffffull);
tb_test_bits_fb1_u64_be(0xfff00ffffff00fffull);
tb_test_bits_fb1_u64_be(0x0ffffff00ffffff0ull);
tb_test_bits_fb1_u64_be(0x000000000000000full);
tb_test_bits_fb1_u64_be(0xf000000000000000ull);
tb_trace_i("");
tb_test_bits_fb1_u64_le(0);
tb_test_bits_fb1_u64_le(1);
tb_test_bits_fb1_u64_le(2);
tb_test_bits_fb1_u64_le(8);
tb_test_bits_fb1_u64_le(123);
tb_test_bits_fb1_u64_le(123456);
tb_test_bits_fb1_u64_le(800000);
tb_test_bits_fb1_u64_le(31415926);
tb_test_bits_fb1_u64_le(0xffffffffffffffffull);
tb_test_bits_fb1_u64_le(0xfffffffffffffff0ull);
tb_test_bits_fb1_u64_le(0x0fffffffffffffffull);
tb_test_bits_fb1_u64_le(0xfff00ffffff00fffull);
tb_test_bits_fb1_u64_le(0x0ffffff00ffffff0ull);
tb_test_bits_fb1_u64_le(0x000000000000000full);
tb_test_bits_fb1_u64_le(0xf000000000000000ull);
#endif
return 0;
}
tbox-1.7.6/src/demo/utils/dump.c 0000664 0000000 0000000 00000000607 14671175054 0016502 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_utils_dump_main(tb_int_t argc, tb_char_t** argv)
{
// dump
tb_dump_data((tb_byte_t const*)argv[1], tb_strlen(argv[1]));
return 0;
}
tbox-1.7.6/src/demo/utils/option.c 0000664 0000000 0000000 00000010505 14671175054 0017043 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
static tb_option_item_t g_options[] =
{
{ '-'
, "demo"
, TB_OPTION_MODE_VAL
, TB_OPTION_TYPE_CSTR
, "the demo:\n"
" demo0: the demo test0\n"
" demo1: the demo test1\n"
" demo2: the demo test2\n"
" demo3: the demo test3\n"
}
, {'-', "lower", TB_OPTION_MODE_KEY, TB_OPTION_TYPE_BOOL, "display lower string"}
, {'-', "upper", TB_OPTION_MODE_KEY, TB_OPTION_TYPE_BOOL, "display upper string"}
, {'i', "integer", TB_OPTION_MODE_KEY_VAL, TB_OPTION_TYPE_INTEGER, "display integer value"}
, {'f', "float", TB_OPTION_MODE_KEY_VAL, TB_OPTION_TYPE_FLOAT, "display float value"}
, {'b', "boolean", TB_OPTION_MODE_KEY_VAL, TB_OPTION_TYPE_BOOL, "display boolean value"}
, {'s', "string", TB_OPTION_MODE_KEY_VAL, TB_OPTION_TYPE_CSTR, "display string value"}
, {'h', "help", TB_OPTION_MODE_KEY, TB_OPTION_TYPE_BOOL, "display this help and exit"}
, {'v', "version", TB_OPTION_MODE_KEY, TB_OPTION_TYPE_BOOL, "output version information and exit"}
, {'-', "file0", TB_OPTION_MODE_VAL, TB_OPTION_TYPE_CSTR, "the file0 path"}
, {'-', "file1", TB_OPTION_MODE_VAL, TB_OPTION_TYPE_CSTR, "the file1 path"}
, {'-', tb_null, TB_OPTION_MODE_MORE, TB_OPTION_TYPE_NONE, tb_null}
};
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_utils_option_main(tb_int_t argc, tb_char_t** argv)
{
// init option
tb_option_ref_t option = tb_option_init("option", "the option command test demo", g_options);
if (option)
{
// done option
if (tb_option_done(option, argc - 1, &argv[1]))
{
// done dump
tb_option_dump(option);
// done help
if (tb_option_find(option, "help"))
tb_option_help(option);
#ifdef TB_CONFIG_INFO_HAVE_VERSION
// done version
else if (tb_option_find(option, "version"))
{
tb_version_t const* version = tb_version();
if (version) tb_trace_i("version: tbox-v%u.%u.%u.%llu", version->major, version->minor, version->alter, version->build);
}
#endif
else
{
// done integer
if (tb_option_find(option, "i"))
tb_trace_i("integer: %lld", tb_option_item_sint64(option, "i"));
// done string
if (tb_option_find(option, "s"))
tb_trace_i("string: %s", tb_option_item_cstr(option, "s"));
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
// done float
if (tb_option_find(option, "f"))
tb_trace_i("float: %f", tb_option_item_float(option, "f"));
#endif
// done boolean
if (tb_option_find(option, "b"))
tb_trace_i("boolean: %s", tb_option_item_bool(option, "b")? "y" : "n");
// done demo
if (tb_option_find(option, "demo"))
tb_trace_i("demo: %s", tb_option_item_cstr(option, "demo"));
// done file0
if (tb_option_find(option, "file0"))
tb_trace_i("file0: %s", tb_option_item_cstr(option, "file0"));
// done file1
if (tb_option_find(option, "file1"))
tb_trace_i("file1: %s", tb_option_item_cstr(option, "file1"));
// done more
tb_size_t more = 0;
while (1)
{
tb_char_t name[64] = {0};
tb_snprintf(name, 63, "more%lu", more++);
if (tb_option_find(option, name))
tb_trace_i("%s: %s", name, tb_option_item_cstr(option, name));
else break;
}
}
}
else tb_option_help(option);
// exit option
tb_option_exit(option);
}
return 0;
}
tbox-1.7.6/src/demo/utils/url.c 0000664 0000000 0000000 00000001011 14671175054 0016325 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_utils_url_main(tb_int_t argc, tb_char_t** argv)
{
tb_char_t ob[4096];
//tb_size_t on = tb_url_encode(argv[1], tb_strlen(argv[1]), ob, 4096);
tb_size_t on = tb_url_decode(argv[1], tb_strlen(argv[1]), ob, 4096);
tb_trace_i("%s: %lu", ob, on);
return 0;
}
tbox-1.7.6/src/demo/xmake.lua 0000664 0000000 0000000 00000004660 14671175054 0016044 0 ustar 00root root 0000000 0000000
-- add target
target("demo")
-- add the dependent target
add_deps("tbox")
-- make as a binary
set_kind("binary")
-- add defines
add_defines("__tb_prefix__=\"demo\"")
-- add the source files
add_files("demo.c")
add_files("libc/*.c")
add_files("libm/integer.c")
add_files("math/random.c")
add_files("utils/*.c|option.c")
add_files("other/*.c|charset.c", "other/*.cpp")
add_files("string/*.c")
add_files("memory/**.c")
add_files("platform/*.c|exception.c|context.c")
add_files("container/*.c")
add_files("algorithm/*.c")
add_files("stream/stream.c")
add_files("stream/stream/*.c")
add_files("network/**.c")
-- add the source files for the hash module
if has_config("hash") then
add_files("hash/*.c")
end
-- add the source files for the float type
if has_config("float") then
add_files("math/fixed.c")
add_files("libm/float.c")
add_files("libm/double.c")
end
-- add the source files for the coroutine module
if has_config("coroutine") then
add_files("coroutine/**.c")
add_files("platform/context.c")
end
-- add the source files for the exception module
if has_config("exception") then
add_files("platform/exception.c")
end
-- add the source files for the xml module
if has_config("xml") then
add_files("xml/*.c")
end
-- add the source files for the regex module
if has_config("regex") then
add_files("regex/*.c")
end
-- add the source files for the object module
if has_config("object") then
add_files("utils/option.c")
add_files("object/*.c")
end
-- enable utf8?
add_options("force-utf8")
-- add the source files for the charset module
if has_config("charset") then add_files("other/charset.c") end
-- add the source files for the database module
if has_config("database") then add_files("database/sql.c") end
-- enable xp compatibility mode
if is_plat("windows") then
if is_arch("x86") then
add_ldflags("/subsystem:console,5.01")
else
add_ldflags("/subsystem:console,5.02")
end
end
-- link mingw/libgcc
if is_plat("mingw", "msys", "cygwin") then
add_ldflags("-static-libgcc", {force = true})
end
-- link backtrace/execinfo for bsd
if is_plat("bsd") then
add_syslinks("execinfo")
end
tbox-1.7.6/src/demo/xmake.sh 0000775 0000000 0000000 00000006421 14671175054 0015675 0 ustar 00root root 0000000 0000000 #!/bin/sh
target "demo"
add_deps "tbox"
set_kind "binary"
add_defines "__tb_prefix__=\"demo\""
# add the source files
add_files "demo.c"
add_files "libc/*.c"
add_files "libm/integer.c"
add_files "math/random.c"
add_files "utils/base32.c"
add_files "utils/base64.c"
add_files "utils/bits.c"
add_files "utils/dump.c"
add_files "utils/url.c"
add_files "other/test.c"
add_files "other/test.cpp"
add_files "string/*.c"
add_files "memory/**.c"
add_files "platform/addrinfo.c"
add_files "platform/atomic.c"
add_files "platform/atomic32.c"
add_files "platform/atomic64.c"
add_files "platform/backtrace.c"
add_files "platform/cache_time.c"
add_files "platform/directory.c"
add_files "platform/environment.c"
add_files "platform/event.c"
add_files "platform/file.c"
add_files "platform/filelock.c"
add_files "platform/fwatcher.c"
add_files "platform/hostname.c"
add_files "platform/ifaddrs.c"
add_files "platform/lock.c"
add_files "platform/ltimer.c"
add_files "platform/named_pipe.c"
add_files "platform/path.c"
add_files "platform/pipe_pair.c"
add_files "platform/poller_client.c"
add_files "platform/poller_fwatcher.c"
add_files "platform/poller_pipe.c"
add_files "platform/poller_process.c"
add_files "platform/poller_server.c"
add_files "platform/process.c"
add_files "platform/sched.c"
add_files "platform/semaphore.c"
add_files "platform/stdfile.c"
add_files "platform/thread.c"
add_files "platform/thread_local.c"
add_files "platform/thread_pool.c"
add_files "platform/timer.c"
add_files "platform/utils.c"
add_files "container/*.c"
add_files "algorithm/*.c"
add_files "stream/stream.c"
add_files "stream/stream/*.c"
add_files "network/**.c"
# add the source files for the hash module
if has_config "hash"; then
add_files "hash/*.c"
fi
# add the source files for the float type
if has_config "float"; then
add_files "math/fixed.c"
add_files "libm/float.c"
add_files "libm/double.c"
fi
# add the source files for the coroutine module
if has_config "coroutine"; then
add_files "coroutine/**.c"
add_files "platform/context.c"
fi
# add the source files for the exception module
if has_config "exception"; then
add_files "platform/exception.c"
fi
# add the source files for the xml module
if has_config "xml"; then
add_files "xml/*.c"
fi
# add the source files for the regex module
if has_config "regex"; then
add_files "regex/*.c"
fi
# add the source files for the object module
if has_config "object"; then
add_files "utils/option.c"
add_files "object/*.c"
fi
# add the source files for the charset module
if has_config "charset"; then
add_files "other/charset.c"
fi
# add the source files for the database module
if has_config "database"; then
add_files "database/sql.c"
fi
# link mingw/libgcc
if is_plat "mingw" "msys" "cygwin"; then
add_ldflags "-static-libgcc"
fi
# link backtrace/execinfo for bsd
if is_plat "freebsd" "bsd"; then
add_syslinks "execinfo"
fi
tbox-1.7.6/src/demo/xml/ 0000775 0000000 0000000 00000000000 14671175054 0015026 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/demo/xml/document.c 0000664 0000000 0000000 00000002350 14671175054 0017010 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_xml_document_main(tb_int_t argc, tb_char_t** argv)
{
// init reader and writer
tb_xml_reader_ref_t reader = tb_xml_reader_init();
tb_xml_writer_ref_t writer = tb_xml_writer_init();
if (reader && writer)
{
// open reader and writer
if ( tb_xml_reader_open(reader, tb_stream_init_from_url(argv[1]), tb_true)
&& tb_xml_writer_open(writer, tb_true, tb_stream_init_from_url(argv[2]), tb_true))
{
// goto
tb_bool_t ok = tb_true;
if (argv[3]) ok = tb_xml_reader_goto(reader, argv[3]);
// load & save
tb_xml_node_ref_t root = tb_null;
if (ok) tb_xml_writer_save(writer, root = tb_xml_reader_load(reader));
// exit root
if (root) tb_xml_node_exit(root);
}
}
// exit reader
if (reader) tb_xml_reader_exit(reader);
reader = tb_null;
// exit writer
if (writer) tb_xml_writer_exit(writer);
writer = tb_null;
return 0;
}
tbox-1.7.6/src/demo/xml/reader.c 0000664 0000000 0000000 00000010732 14671175054 0016437 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_xml_reader_main(tb_int_t argc, tb_char_t** argv)
{
// init reader
tb_xml_reader_ref_t reader = tb_xml_reader_init();
if (reader)
{
// open reader
if (tb_xml_reader_open(reader, tb_stream_init_from_url(argv[1]), tb_true))
{
// goto
tb_bool_t ok = tb_true;
if (argv[2]) ok = tb_xml_reader_goto(reader, argv[2]);
// walk
tb_size_t event = TB_XML_READER_EVENT_NONE;
while (ok && (event = tb_xml_reader_next(reader)))
{
switch (event)
{
case TB_XML_READER_EVENT_DOCUMENT:
{
tb_printf("\n"
, tb_xml_reader_version(reader), tb_xml_reader_charset(reader));
}
break;
case TB_XML_READER_EVENT_DOCUMENT_TYPE:
{
tb_printf("\n");
}
break;
case TB_XML_READER_EVENT_ELEMENT_EMPTY:
{
tb_char_t const* name = tb_xml_reader_element(reader);
tb_xml_node_ref_t attr = tb_xml_reader_attributes(reader);
tb_size_t t = tb_xml_reader_level(reader);
while (t--) tb_printf("\t");
if (!attr) tb_printf("<%s/>\n", name);
else
{
tb_printf("<%s", name);
for (; attr; attr = attr->next)
tb_printf(" %s = \"%s\"", tb_string_cstr(&attr->name), tb_string_cstr(&attr->data));
tb_printf("/>\n");
}
}
break;
case TB_XML_READER_EVENT_ELEMENT_BEG:
{
tb_char_t const* name = tb_xml_reader_element(reader);
tb_xml_node_ref_t attr = tb_xml_reader_attributes(reader);
tb_size_t t = tb_xml_reader_level(reader) - 1;
while (t--) tb_printf("\t");
if (!attr) tb_printf("<%s>\n", name);
else
{
tb_printf("<%s", name);
for (; attr; attr = attr->next)
tb_printf(" %s = \"%s\"", tb_string_cstr(&attr->name), tb_string_cstr(&attr->data));
tb_printf(">\n");
}
}
break;
case TB_XML_READER_EVENT_ELEMENT_END:
{
tb_size_t t = tb_xml_reader_level(reader);
while (t--) tb_printf("\t");
tb_printf("%s>\n", tb_xml_reader_element(reader));
}
break;
case TB_XML_READER_EVENT_TEXT:
{
tb_size_t t = tb_xml_reader_level(reader);
while (t--) tb_printf("\t");
tb_printf("%s", tb_xml_reader_text(reader));
tb_printf("\n");
}
break;
case TB_XML_READER_EVENT_CDATA:
{
tb_size_t t = tb_xml_reader_level(reader);
while (t--) tb_printf("\t");
tb_printf("", tb_xml_reader_cdata(reader));
tb_printf("\n");
}
break;
case TB_XML_READER_EVENT_COMMENT:
{
tb_size_t t = tb_xml_reader_level(reader);
while (t--) tb_printf("\t");
tb_printf("", tb_xml_reader_comment(reader));
tb_printf("\n");
}
break;
default:
break;
}
}
}
// exit reader
tb_xml_reader_exit(reader);
}
return 0;
}
tbox-1.7.6/src/demo/xml/writer.c 0000664 0000000 0000000 00000004226 14671175054 0016512 0 ustar 00root root 0000000 0000000 /* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../demo.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* main
*/
tb_int_t tb_demo_xml_writer_main(tb_int_t argc, tb_char_t** argv)
{
// init writer
tb_xml_writer_ref_t writer = tb_xml_writer_init();
if (writer)
{
// open writer
if (tb_xml_writer_open(writer, tb_true, tb_stream_init_from_url(argv[1]), tb_true))
{
tb_xml_writer_document(writer, "1.0", "utf-8");
tb_xml_writer_comment(writer, "comments ...");
tb_xml_writer_attributes_format(writer, "name", "hello %s", "world");
tb_xml_writer_element_enter(writer, "labels");
tb_xml_writer_attributes_long(writer, "id", 1);
tb_xml_writer_attributes_cstr(writer, "label", "1");
tb_xml_writer_element_enter(writer, "label_1");
tb_xml_writer_text(writer, "characters");
tb_xml_writer_element_leave(writer);
tb_xml_writer_attributes_long(writer, "id", 2);
tb_xml_writer_attributes_bool(writer, "bool", tb_true);
tb_xml_writer_element_enter(writer, "label_2");
tb_xml_writer_text(writer, "characters");
tb_xml_writer_element_leave(writer);
tb_xml_writer_attributes_long(writer, "id", 3);
tb_xml_writer_attributes_format(writer, "label", "%d", 3);
tb_xml_writer_element_enter(writer, "label_3");
tb_xml_writer_text(writer, "characters");
tb_xml_writer_attributes_long(writer, "id", -4);
tb_xml_writer_attributes_bool(writer, "bool", tb_false);
tb_xml_writer_element_empty(writer, "label_4");
tb_xml_writer_element_empty(writer, "label_5");
tb_xml_writer_element_leave(writer);
tb_xml_writer_cdata(writer, "datas");
tb_xml_writer_element_leave(writer);
}
// exit writer
tb_xml_writer_exit(writer);
}
return 0;
}
tbox-1.7.6/src/tbox/ 0000775 0000000 0000000 00000000000 14671175054 0014256 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/algorithm/ 0000775 0000000 0000000 00000000000 14671175054 0016244 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/algorithm/algorithm.h 0000664 0000000 0000000 00000002660 14671175054 0020407 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file algorithm.h
* @defgroup algorithm
*
*/
#ifndef TB_ALGORITHM_H
#define TB_ALGORITHM_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "predicate.h"
#include "distance.h"
#include "for.h"
#include "for_if.h"
#include "rfor.h"
#include "rfor_if.h"
#include "sort.h"
#include "heap_sort.h"
#include "quick_sort.h"
#include "insert_sort.h"
#include "bubble_sort.h"
#include "find.h"
#include "find_if.h"
#include "rfind.h"
#include "rfind_if.h"
#include "binary_find.h"
#include "binary_find_if.h"
#include "walk.h"
#include "rwalk.h"
#include "count.h"
#include "count_if.h"
#include "remove.h"
#include "remove_if.h"
#include "remove_first.h"
#include "remove_first_if.h"
#endif
tbox-1.7.6/src/tbox/algorithm/binary_find.c 0000664 0000000 0000000 00000002474 14671175054 0020703 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file binary_find.c
* @ingroup algorithm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "binary_find.h"
#include "binary_find_if.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_binary_find(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_cpointer_t item)
{
return tb_binary_find_if(iterator, head, tail, tb_iterator_comp, item);
}
tb_size_t tb_binary_find_all(tb_iterator_ref_t iterator, tb_cpointer_t item)
{
return tb_binary_find_all_if(iterator, tb_iterator_comp, item);
}
tbox-1.7.6/src/tbox/algorithm/binary_find.h 0000664 0000000 0000000 00000003646 14671175054 0020712 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file binary_find.h
* @ingroup algorithm
*
*/
#ifndef TB_ALGORITHM_BINARY_FIND_H
#define TB_ALGORITHM_BINARY_FIND_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! binary find item
*
* @param iterator the iterator
* @param head the iterator head
* @param tail the iterator tail
* @param item the found item
*
* @return the iterator itor, return tb_iterator_tail(iterator) if not found
*/
tb_size_t tb_binary_find(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_cpointer_t item);
/*!binary find item for all
*
* @param iterator the iterator
* @param item the found item
*
* @return the iterator itor, return tb_iterator_tail(iterator) if not found
*/
tb_size_t tb_binary_find_all(tb_iterator_ref_t iterator, tb_cpointer_t item);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/algorithm/binary_find_if.c 0000664 0000000 0000000 00000003635 14671175054 0021361 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file binary_find_if.c
* @ingroup algorithm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "binary_find_if.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_binary_find_if(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp, tb_cpointer_t priv)
{
// check
tb_assert_and_check_return_val(comp && iterator && (tb_iterator_mode(iterator) & TB_ITERATOR_MODE_RACCESS), tb_iterator_tail(iterator));
// null?
tb_check_return_val(head != tail, tb_iterator_tail(iterator));
// find
tb_size_t l = head;
tb_size_t r = tail;
tb_size_t m = (l + r) >> 1;
tb_long_t c = -1;
while (l < r)
{
c = comp(iterator, tb_iterator_item(iterator, m), priv);
if (c > 0) r = m;
else if (c < 0) l = m + 1;
else break;
m = (l + r) >> 1;
}
// ok?
return !c? m : tb_iterator_tail(iterator);
}
tb_size_t tb_binary_find_all_if(tb_iterator_ref_t iterator, tb_iterator_comp_t comp, tb_cpointer_t priv)
{
return tb_binary_find_if(iterator, tb_iterator_head(iterator), tb_iterator_tail(iterator), comp, priv);
}
tbox-1.7.6/src/tbox/algorithm/binary_find_if.h 0000664 0000000 0000000 00000004144 14671175054 0021362 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file binary_find_if.h
* @ingroup algorithm
*
*/
#ifndef TB_ALGORITHM_BINARY_FIND_IF_H
#define TB_ALGORITHM_BINARY_FIND_IF_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! binary find item if !comp(item, priv)
*
* @param iterator the iterator
* @param head the iterator head
* @param tail the iterator tail
* @param comp the comparer func
* @param priv the comparer data
*
* @return the iterator itor, return tb_iterator_tail(iterator) if not found
*/
tb_size_t tb_binary_find_if(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp, tb_cpointer_t priv);
/*! binary find item for all if !comp(item, priv)
*
* @param iterator the iterator
* @param comp the comparer func
* @param priv the comparer data
*
* @return the iterator itor, return tb_iterator_tail(iterator) if not found
*/
tb_size_t tb_binary_find_all_if(tb_iterator_ref_t iterator, tb_iterator_comp_t comp, tb_cpointer_t priv);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/algorithm/bubble_sort.c 0000664 0000000 0000000 00000005265 14671175054 0020722 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file bubble_sort.c
* @ingroup algorithm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "bubble_sort.h"
#include "../libc/libc.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_void_t tb_bubble_sort(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp)
{
// check
tb_assert_and_check_return(iterator && (tb_iterator_mode(iterator) & TB_ITERATOR_MODE_FORWARD));
tb_check_return(head != tail);
// get flag
tb_size_t step = tb_iterator_step(iterator);
tb_size_t flag = tb_iterator_flag(iterator);
if (!flag && step > sizeof(tb_pointer_t))
flag |= TB_ITERATOR_FLAG_ITEM_REF;
// init temp item
tb_pointer_t temp = flag & TB_ITERATOR_FLAG_ITEM_REF? tb_malloc(step) : tb_null;
tb_assert_and_check_return(step <= sizeof(tb_pointer_t) || temp);
// the comparer
if (!comp) comp = tb_iterator_comp;
// bubble_sort
tb_size_t itor1, itor2;
for (itor1 = head; itor1 != tail; itor1 = tb_iterator_next(iterator, itor1))
{
for (itor2 = itor1, itor2 = tb_iterator_next(iterator, itor2); itor2 != tail; itor2 = tb_iterator_next(iterator, itor2))
{
if (comp(iterator, tb_iterator_item(iterator, itor2), tb_iterator_item(iterator, itor1)) < 0)
{
if (flag & TB_ITERATOR_FLAG_ITEM_REF)
tb_memcpy(temp, tb_iterator_item(iterator, itor1), step);
else temp = tb_iterator_item(iterator, itor1);
tb_iterator_copy(iterator, itor1, tb_iterator_item(iterator, itor2));
tb_iterator_copy(iterator, itor2, temp);
}
}
}
// free temp item
if (temp && (flag & TB_ITERATOR_FLAG_ITEM_REF)) tb_free(temp);
}
tb_void_t tb_bubble_sort_all(tb_iterator_ref_t iterator, tb_iterator_comp_t comp)
{
tb_bubble_sort(iterator, tb_iterator_head(iterator), tb_iterator_tail(iterator), comp);
}
tbox-1.7.6/src/tbox/algorithm/bubble_sort.h 0000664 0000000 0000000 00000003405 14671175054 0020721 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file bubble_sort.h
* @ingroup algorithm
*
*/
#ifndef TB_ALGORITHM_BUBBLE_SORT_H
#define TB_ALGORITHM_BUBBLE_SORT_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the bubble sorter, O(n^2)
*
* @param iterator the iterator
* @param head the iterator head
* @param tail the iterator tail
* @param comp the comparer
*/
tb_void_t tb_bubble_sort(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp);
/*! the bubble sorter for all
*
* @param iterator the iterator
* @param comp the comparer
*/
tb_void_t tb_bubble_sort_all(tb_iterator_ref_t iterator, tb_iterator_comp_t comp);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/algorithm/count.c 0000664 0000000 0000000 00000002424 14671175054 0017542 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file count.c
* @ingroup algorithm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "count.h"
#include "count_if.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_count(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_cpointer_t value)
{
return tb_count_if(iterator, head, tail, tb_predicate_eq, value);
}
tb_size_t tb_count_all(tb_iterator_ref_t iterator, tb_cpointer_t value)
{
return tb_count_all_if(iterator, tb_predicate_eq, value);
}
tbox-1.7.6/src/tbox/algorithm/count.h 0000664 0000000 0000000 00000003463 14671175054 0017553 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file count.h
* @ingroup algorithm
*
*/
#ifndef TB_ALGORITHM_COUNT_H
#define TB_ALGORITHM_COUNT_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! count items
*
* @param iterator the iterator
* @param head the iterator head
* @param tail the iterator tail
* @param value the value of the predicate
*
* @return the real count
*/
tb_size_t tb_count(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_cpointer_t value);
/*! count items for all
*
* @param iterator the iterator
* @param value the value of the predicate
*
* @return the real count
*/
tb_size_t tb_count_all(tb_iterator_ref_t iterator, tb_cpointer_t value);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/algorithm/count_if.c 0000664 0000000 0000000 00000003226 14671175054 0020221 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file count_if.c
* @ingroup algorithm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "count_if.h"
#include "for.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_count_if(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_predicate_ref_t pred, tb_cpointer_t value)
{
// check
tb_assert_and_check_return_val(pred && iterator && (tb_iterator_mode(iterator) & TB_ITERATOR_MODE_FORWARD), 0);
// null?
tb_check_return_val(head != tail, 0);
// count
tb_size_t count = 0;
tb_for (tb_pointer_t, item, head, tail, iterator)
if (pred(iterator, item, value)) count++;
// ok?
return count;
}
tb_size_t tb_count_all_if(tb_iterator_ref_t iterator, tb_predicate_ref_t pred, tb_cpointer_t value)
{
return tb_count_if(iterator, tb_iterator_head(iterator), tb_iterator_tail(iterator), pred, value);
}
tbox-1.7.6/src/tbox/algorithm/count_if.h 0000664 0000000 0000000 00000003771 14671175054 0020233 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file count_if.h
* @ingroup algorithm
*
*/
#ifndef TB_ALGORITHM_COUNT_IF_H
#define TB_ALGORITHM_COUNT_IF_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "predicate.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! count items if pred(item, value)
*
* @param iterator the iterator
* @param head the iterator head
* @param tail the iterator tail
* @param pred the predicate
* @param value the value of the predicate
*
* @return the real count
*/
tb_size_t tb_count_if(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_predicate_ref_t pred, tb_cpointer_t value);
/*! count items for all if pred(item, value)
*
* @param iterator the iterator
* @param pred the predicate
* @param value the value of the predicate
*
* @return the real count
*/
tb_size_t tb_count_all_if(tb_iterator_ref_t iterator, tb_predicate_ref_t pred, tb_cpointer_t value);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/algorithm/distance.c 0000664 0000000 0000000 00000004740 14671175054 0020207 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file distance.c
* @ingroup algorithm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "distance.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_distance(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail)
{
// check
tb_assert_and_check_return_val(iterator, 0);
// zero distance?
tb_check_return_val(head != tail, 0);
// the iterator mode
tb_size_t mode = tb_iterator_mode(iterator);
// random access iterator?
tb_size_t distance = 0;
if (mode & TB_ITERATOR_MODE_RACCESS)
{
// compute it fastly
distance = tail - head;
}
// forward iterator?
else if (mode & TB_ITERATOR_MODE_FORWARD)
{
// whole container?
if (tb_iterator_head(iterator) == head && tb_iterator_tail(iterator) == tail)
distance = tb_iterator_size(iterator);
else
{
// done
tb_size_t itor = head;
for (; itor != tail; itor = tb_iterator_next(iterator, itor)) distance++;
}
}
// reverse iterator?
else if (mode & TB_ITERATOR_MODE_REVERSE)
{
// whole container?
if (tb_iterator_head(iterator) == head && tb_iterator_tail(iterator) == tail)
distance = tb_iterator_size(iterator);
else
{
// done
tb_size_t itor = tail;
do
{
// update the distance
distance++;
// the previous
itor = tb_iterator_prev(iterator, itor);
} while (itor != head);
}
}
// unknown mode?
else
{
// abort
tb_assert(0);
}
// ok?
return distance;
}
tbox-1.7.6/src/tbox/algorithm/distance.h 0000664 0000000 0000000 00000003047 14671175054 0020213 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file distance.h
* @ingroup algorithm
*
*/
#ifndef TB_ALGORITHM_DISTANCE_H
#define TB_ALGORITHM_DISTANCE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! compute distance from head to tail
*
* @param iterator the iterator
* @param head the iterator head
* @param tail the iterator tail
*
* @return the distance
*/
tb_size_t tb_distance(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/algorithm/find.c 0000664 0000000 0000000 00000002415 14671175054 0017332 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file find.c
* @ingroup algorithm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "find.h"
#include "find_if.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_find(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_cpointer_t value)
{
return tb_find_if(iterator, head, tail, tb_predicate_eq, value);
}
tb_size_t tb_find_all(tb_iterator_ref_t iterator, tb_cpointer_t value)
{
return tb_find_all_if(iterator, tb_predicate_eq, value);
}
tbox-1.7.6/src/tbox/algorithm/find.h 0000664 0000000 0000000 00000003622 14671175054 0017340 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file find.h
* @ingroup algorithm
*
*/
#ifndef TB_ALGORITHM_FIND_H
#define TB_ALGORITHM_FIND_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the finder
*
* @param iterator the iterator
* @param head the iterator head
* @param tail the iterator tail
* @param value the value of the predicate
*
* @return the iterator itor, return tb_iterator_tail(iterator) if not found
*/
tb_size_t tb_find(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_cpointer_t value);
/*! the finder for all
*
* @param iterator the iterator
* @param value the value of the predicate
*
* @return the iterator itor, return tb_iterator_tail(iterator) if not found
*/
tb_size_t tb_find_all(tb_iterator_ref_t iterator, tb_cpointer_t value);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/algorithm/find_if.c 0000664 0000000 0000000 00000003443 14671175054 0020012 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file find_if.c
* @ingroup algorithm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "find_if.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_find_if(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_predicate_ref_t pred, tb_cpointer_t value)
{
// check
tb_assert_and_check_return_val(pred && iterator && (tb_iterator_mode(iterator) & TB_ITERATOR_MODE_FORWARD), tb_iterator_tail(iterator));
// null?
tb_check_return_val(head != tail, tb_iterator_tail(iterator));
// find
tb_size_t itor = head;
tb_bool_t find = tb_false;
for (; itor != tail; itor = tb_iterator_next(iterator, itor))
if ((find = pred(iterator, tb_iterator_item(iterator, itor), value))) break;
// ok?
return find? itor : tb_iterator_tail(iterator);
}
tb_size_t tb_find_all_if(tb_iterator_ref_t iterator, tb_predicate_ref_t pred, tb_cpointer_t value)
{
return tb_find_if(iterator, tb_iterator_head(iterator), tb_iterator_tail(iterator), pred, value);
}
tbox-1.7.6/src/tbox/algorithm/find_if.h 0000664 0000000 0000000 00000004126 14671175054 0020016 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file find_if.h
* @ingroup algorithm
*
*/
#ifndef TB_ALGORITHM_FIND_IF_H
#define TB_ALGORITHM_FIND_IF_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "predicate.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! find item if pred(item, value)
*
* @param iterator the iterator
* @param head the iterator head
* @param tail the iterator tail
* @param pred the predicate
* @param value the value of the predicate
*
* @return the iterator itor, return tb_iterator_tail(iterator) if not found
*/
tb_size_t tb_find_if(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_predicate_ref_t pred, tb_cpointer_t value);
/*! find item for all if pred(item, value)
*
* @param iterator the iterator
* @param pred the predicate
* @param value the value of the predicate
*
* @return the iterator itor, return tb_iterator_tail(iterator) if not found
*/
tb_size_t tb_find_all_if(tb_iterator_ref_t iterator, tb_predicate_ref_t pred, tb_cpointer_t value);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/algorithm/for.h 0000664 0000000 0000000 00000005674 14671175054 0017217 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file for.h
* @ingroup algorithm
*
*/
#ifndef TB_ALGORITHM_FOR_H
#define TB_ALGORITHM_FOR_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/*! for items using iterator
*
* @code
* tb_for(tb_char_t*, item, tb_iterator_head(iterator), tb_iterator_tail(iterator), iterator)
* {
* tb_trace_d("item: %s", item);
* }
*
* tb_for(tb_size_t, item, tb_iterator_head(iterator), tb_iterator_tail(iterator), iterator)
* {
* tb_trace_d("item: %lu", item);
* }
*
* tb_for(tb_hash_map_item_ref_t, item, tb_iterator_head(iterator), tb_iterator_tail(iterator), iterator)
* {
* if (item) tb_trace_d("item: %p => %p", item->name, item->data);
* }
* @endcode
*/
#define tb_for(type, item, head, tail, iterator) \
/* iterator */ \
tb_iterator_ref_t item##_iterator = (tb_iterator_ref_t)iterator; \
tb_assert(!item##_iterator || (tb_iterator_mode(item##_iterator) & (TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_RACCESS))); \
/* init */ \
type item; \
tb_size_t item##_itor = head; \
tb_size_t item##_head = head; \
tb_size_t item##_tail = tail; \
/* walk */ \
if (item##_iterator && item##_head != item##_tail) \
for ( ; \
item##_itor != item##_tail && ((item = (type)tb_iterator_item(item##_iterator, item##_itor)), 1); \
item##_itor = tb_iterator_next(item##_iterator, item##_itor))
/*! for all items using iterator
*
* @code
*
* tb_for_all(tb_char_t*, item, iterator)
* {
* tb_trace_d("item: %s", item);
* }
*
* tb_for_all(tb_size_t, item, iterator)
* {
* tb_trace_d("item: %lu", item);
* }
*
* tb_for_all(tb_hash_map_item_ref_t, item, iterator)
* {
* if (item) tb_trace_d("item: %p => %p", item->name, item->data);
* }
* @endcode
*/
#define tb_for_all(type, item, iterator) \
tb_iterator_ref_t item##_iterator_all = (tb_iterator_ref_t)iterator; \
tb_for(type, item, tb_iterator_head(item##_iterator_all), tb_iterator_tail(item##_iterator_all), item##_iterator_all)
#endif
tbox-1.7.6/src/tbox/algorithm/for_if.h 0000664 0000000 0000000 00000006140 14671175054 0017662 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file for_if.h
* @ingroup algorithm
*
*/
#ifndef TB_ALGORITHM_FOR_IF_H
#define TB_ALGORITHM_FOR_IF_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/*! for items using iterator if the condition ok
*
* @code
* tb_for_if(tb_char_t*, item, tb_iterator_head(iterator), tb_iterator_tail(iterator), iterator, item)
* {
* tb_trace_d("item: %s", item);
* }
*
* tb_for_if(tb_size_t, item, tb_iterator_head(iterator), tb_iterator_tail(iterator), iterator, item > 10)
* {
* tb_trace_d("item: %lu", item);
* }
*
* tb_for_if(tb_hash_map_item_ref_t, item, tb_iterator_head(iterator), tb_iterator_tail(iterator), iterator, item != tb_null)
* {
* tb_trace_d("item: %p => %p", item->name, item->data);
* }
* @endcode
*/
#define tb_for_if(type, item, head, tail, iterator, cond) \
/* iterator */ \
tb_iterator_ref_t item##_iterator = (tb_iterator_ref_t)iterator; \
tb_assert(!item##_iterator || (tb_iterator_mode(item##_iterator) & (TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_RACCESS))); \
/* init */ \
type item; \
tb_size_t item##_itor = head; \
tb_size_t item##_head = head; \
tb_size_t item##_tail = tail; \
/* walk */ \
if (item##_iterator && item##_head != item##_tail) \
for ( ; \
item##_itor != item##_tail && ((item = (type)tb_iterator_item(item##_iterator, item##_itor)), 1); \
item##_itor = tb_iterator_next(item##_iterator, item##_itor)) if ((cond))
/*! for all items using iterator if the condition ok
*
* @code
*
* tb_for_all_if(tb_char_t*, item, iterator, item)
* {
* tb_trace_d("item: %s", item);
* }
*
* tb_for_all_if(tb_size_t, item, iterator, item > 10)
* {
* tb_trace_d("item: %lu", item);
* }
*
* tb_for_all_if(tb_hash_map_item_ref_t, item, iterator, item != tb_null)
* {
* if (item) tb_trace_d("item: %p => %p", item->name, item->data);
* }
* @endcode
*/
#define tb_for_all_if(type, item, iterator, cond) \
tb_iterator_ref_t item##_iterator_all = (tb_iterator_ref_t)iterator; \
tb_for_if(type, item, tb_iterator_head(item##_iterator_all), tb_iterator_tail(item##_iterator_all), item##_iterator_all, cond)
#endif
tbox-1.7.6/src/tbox/algorithm/heap_sort.c 0000664 0000000 0000000 00000040541 14671175054 0020400 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file heap_sort.c
* @ingroup algorithm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "heap_sort.h"
#include "../libc/libc.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* head
*/
#ifdef __tb_debug__
static __tb_inline__ tb_bool_t tb_heap_check(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp)
{
// the comparer
if (!comp) comp = tb_iterator_comp;
// walk
if (head != tail)
{
tb_size_t root;
for (root = head; ++head != tail; ++root)
{
// root < left?
if (tb_iterator_comp(iterator, tb_iterator_item(iterator, root), tb_iterator_item(iterator, head)) < 0) return tb_false;
// end?
else if (++head == tail) break;
// root < right?
else if (tb_iterator_comp(iterator, tb_iterator_item(iterator, root), tb_iterator_item(iterator, head)) < 0) return tb_false;
}
}
// ok
return tb_true;
}
#endif
/*!push heap
*
*
* hole: bottom => top
* init:
* 16(top)
* -------------------------
* | |
* 14 10
* -------------- -------------
* | | | |
* 8(parent) 7 9 3
* ---------
* | |
* 2 (hole) <= 11(val)
* after:
* 16(top)
* -------------------------
* | |
* 14(parent) 10
* -------------- -------------
* | | | |
* 11(hole) 7 9 3
* ---------
* | |
* 2 8
*
*/
#if 0
static __tb_inline__ tb_void_t tb_heap_push(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t hole, tb_size_t top, tb_cpointer_t item, tb_iterator_comp_t comp)
{
// check
tb_assert_and_check_return(comp);
// (hole - 1) / 2: the parent node of the hole
// finds the final hole
tb_size_t parent = 0;
tb_cpointer_t parent_item = tb_null;
for (parent = (hole - 1) >> 1; hole > top && (comp(iterator, (parent_item = tb_iterator_item(iterator, head + parent)), item) < 0); parent = (hole - 1) >> 1)
{
// move item: parent => hole
// tb_iterator_copy(iterator, head + parent, item);
tb_iterator_copy(iterator, head + hole, parent_item);
// move node: hole => parent
hole = parent;
}
// copy item
tb_iterator_copy(iterator, head + hole, item);
}
#endif
/*! adjust heap
*
*
* init:
* 16(head)
* -------------------------
* | |
* (hole) 10
* -------------- -------------
* | | | |
* 8(larger) 7 9 3
* --------- ----
* | | |
* 2 4 1(tail - 1)
*
* after:
* 16(head)
* -------------------------
* | |
* 8 10
* -------------- -------------
* | | | |
* (hole) 7 9 3
* --------- ----
* | | |
* 2 (larger)4 1(tail - 1)
*
* after:
* 16(head)
* -------------------------
* | |
* 8 10
* -------------- -------------
* | | | |
* 4 7 9 3
* --------- ----
* | | |
* 2 (hole) 1(tail - 1)
*
*
*/
static __tb_inline__ tb_void_t tb_heap_adjust(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t hole, tb_size_t tail, tb_cpointer_t item, tb_iterator_comp_t comp)
{
// the comparer
if (!comp) comp = tb_iterator_comp;
#if 0
// save top position
tb_size_t top = hole;
// 2 * hole + 2: the right child node of hole
tb_size_t child = (hole << 1) + 2;
for (; child < tail; child = (child << 1) + 2)
{
// the larger child node
if (comp(iterator, tb_iterator_item(iterator, head + child), tb_iterator_item(iterator, head + child - 1)) < 0) child--;
// the larger child node => hole
tb_iterator_copy(iterator, head + hole, tb_iterator_item(iterator, head + child));
// move the hole down to it's larger child node
hole = child;
}
// no right child node?
if (child == tail)
{
// the last child => hole
tb_iterator_copy(iterator, head + hole, tb_iterator_item(iterator, head + tail - 1));
// move hole down to tail
hole = tail - 1;
}
// push item into the hole
tb_heap_push(iterator, head, hole, top, item, comp);
#else
// walk, 2 * hole + 1: the left child node of hole
tb_size_t child = (hole << 1) + 1;
tb_cpointer_t child_item = tb_null;
tb_cpointer_t child_item_r = tb_null;
for (; child < tail; child = (child << 1) + 1)
{
// the larger child node
child_item = tb_iterator_item(iterator, head + child);
if (child + 1 < tail && comp(iterator, child_item, (child_item_r = tb_iterator_item(iterator, head + child + 1))) < 0)
{
child++;
child_item = child_item_r;
}
// end?
if (comp(iterator, child_item, item) < 0) break;
// the larger child node => hole
tb_iterator_copy(iterator, head + hole, child_item);
// move the hole down to it's larger child node
hole = child;
}
// copy item
tb_iterator_copy(iterator, head + hole, item);
#endif
}
/*!make heap
*
*
* heap: 16 14 10 8 7 9 3 2 4 1
*
* 16(head)
* -------------------------
* | |
* 14 10
* -------------- -------------
* | | | |
* 8 (tail / 2 - 1)7 9 3
* --------- ----
* | | |
* 2 4 1(tail - 1)
*
*/
static __tb_inline__ tb_void_t tb_heap_make(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp)
{
// get flag
tb_size_t step = tb_iterator_step(iterator);
tb_size_t flag = tb_iterator_flag(iterator);
if (!flag && step > sizeof(tb_pointer_t))
flag |= TB_ITERATOR_FLAG_ITEM_REF;
// init
tb_pointer_t temp = flag & TB_ITERATOR_FLAG_ITEM_REF? tb_malloc(step) : tb_null;
tb_assert_and_check_return(step <= sizeof(tb_pointer_t) || temp);
// make
tb_size_t hole;
tb_size_t bottom = tail - head;
for (hole = (bottom >> 1); hole > 0; )
{
--hole;
// save hole
if (flag & TB_ITERATOR_FLAG_ITEM_REF)
tb_memcpy(temp, tb_iterator_item(iterator, head + hole), step);
else temp = tb_iterator_item(iterator, head + hole);
// reheap top half, bottom to top
tb_heap_adjust(iterator, head, hole, bottom, temp, comp);
}
// free temp item
if (temp && (flag & TB_ITERATOR_FLAG_ITEM_REF)) tb_free(temp);
// check
tb_assert(tb_heap_check(iterator, head, tail, comp));
}
/*!pop the top of heap to last and reheap
*
*
* 16(head)
* ----------------|--------
* | | |
* 14 | 10
* -------------- | -------------
* | | | | |
* 8 7 | 9 3
* --------- ---- |
* | | | |
* 2 4 1(last)<-----
* (hole)
*
*/
static __tb_inline__ tb_void_t tb_heap_pop0(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_cpointer_t item, tb_iterator_comp_t comp)
{
// top => last
tb_iterator_copy(iterator, tail - 1, tb_iterator_item(iterator, head));
// reheap it
tb_heap_adjust(iterator, head, 0, tail - head - 1, item, comp);
// check
// tb_assert(tb_heap_check(iterator, head, tail - head - 1, comp));
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
/*!the heap sort
*
*
* init:
*
* 16(head)
* -------------------------
* | |
* 4 10
* -------------- -------------
* | | | |
* 14 7 9 3
* --------- ----
* | | |
* 2 8 1(last - 1)
*
* make_heap:
*
* 16(head)
* -------------------------
* | |
* 14 10
* -------------- -------------
* | | | |
* 8 7 9 3
* --------- ----
* | | |
* 2 4 1(last - 1)
* pop_heap:
*
* 16(head)--------------------------
* ------------------------- |
* | | |
* 4 10 |
* -------------- ------------- |
* | | | | |
* 14 7 9 3 |
* --------- ---- |
* | | | |
* 2 8 1(last - 1) <------------------------------
*
* (hole)(head)
* -------------------------
* | |
* 4 10
* -------------- -------------
* | | | | (val = 1)
* 14 7 9 3
* --------- ----
* | | |
* 2 8 16(last - 1)
*
* adjust_heap:
* 14(head)
* -------------------------
* | |
* 8 10
* -------------- -------------
* | | | | (val = 1)
* 4 7 9 3
* ---------
* | |
* 2 (hole)(last - 1) 16
*
*
* push_heap:
* 14(head)
* -------------------------
* | |
* 8 10
* -------------- -------------
* | | | | (val = 1)
* 4 7 9 3 |
* --------- |
* | | /-----------------------------------------------
* 2 (hole)(last - 1) 16
*
* 14(head)
* -------------------------
* | |
* 8 10
* -------------- -------------
* | | | | (val = 1)
* 4 7 9 3
* ---------
* | |
* 2 1(last - 1) 16
*
* pop_heap adjust_heap push_heap ...
*
* final_heap:
* 1(head)
*
*
* 2 3
*
*
* 4 7 8 9
*
*
* 10 14 16
*
* result: 1 2 3 4 7 8 9 10 14 16
*
*/
tb_void_t tb_heap_sort(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp)
{
// check
tb_assert_and_check_return(iterator && (tb_iterator_mode(iterator) & TB_ITERATOR_MODE_RACCESS));
tb_check_return(head != tail);
// make
tb_heap_make(iterator, head, tail, comp);
// get flag
tb_size_t step = tb_iterator_step(iterator);
tb_size_t flag = tb_iterator_flag(iterator);
if (!flag && step > sizeof(tb_pointer_t))
flag |= TB_ITERATOR_FLAG_ITEM_REF;
// init last item
tb_pointer_t last = flag & TB_ITERATOR_FLAG_ITEM_REF? tb_malloc(step) : tb_null;
tb_assert_and_check_return(step <= sizeof(tb_pointer_t) || last);
// pop0 ...
for (; tail > head + 1; tail--)
{
// save last
if (flag & TB_ITERATOR_FLAG_ITEM_REF)
tb_memcpy(last, tb_iterator_item(iterator, tail - 1), step);
else last = tb_iterator_item(iterator, tail - 1);
// pop0
tb_heap_pop0(iterator, head, tail, last, comp);
}
// free
if (last && (flag & TB_ITERATOR_FLAG_ITEM_REF)) tb_free(last);
}
tb_void_t tb_heap_sort_all(tb_iterator_ref_t iterator, tb_iterator_comp_t comp)
{
tb_heap_sort(iterator, tb_iterator_head(iterator), tb_iterator_tail(iterator), comp);
}
tbox-1.7.6/src/tbox/algorithm/heap_sort.h 0000664 0000000 0000000 00000003373 14671175054 0020407 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file heap_sort.h
* @ingroup algorithm
*
*/
#ifndef TB_ALGORITHM_HEAP_SORT_H
#define TB_ALGORITHM_HEAP_SORT_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the heap sorter, O(nlog(n))
*
* @param iterator the iterator
* @param head the iterator head
* @param tail the iterator tail
* @param comp the comparer
*/
tb_void_t tb_heap_sort(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp);
/*! the heap sorter for all
*
* @param iterator the iterator
* @param comp the comparer
*/
tb_void_t tb_heap_sort_all(tb_iterator_ref_t iterator, tb_iterator_comp_t comp);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/algorithm/insert_sort.c 0000664 0000000 0000000 00000007514 14671175054 0020772 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file insert_sort.c
* @ingroup algorithm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "insert_sort.h"
#include "../libc/libc.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
/*!the insertion sort
*
*
* old: 5 2 6 2 8 6 1
*
* (hole)
* step1: ((5)) 2 6 2 8 6 1
* (next) <=
*
* (hole)
* step2: ((2)) (5) 6 2 8 6 1
* (next) <=
*
* (hole)
* step3: 2 5 ((6)) 2 8 6 1
* (next) <=
*
* (hole)
* step4: 2 ((2)) (5) (6) 8 6 1
* (next) <=
*
* (hole)
* step5: 2 2 5 6 ((8)) 6 1
* (next) <=
*
* (hole)
* step6: 2 2 5 6 ((6)) (8) 1
* (next) <=
*
* (hole)
* step7: ((1)) (2) (2) (5) (6) (6) (8)
* (next)
*
*/
tb_void_t tb_insert_sort(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp)
{
// check
tb_assert_and_check_return(iterator);
tb_assert_and_check_return((tb_iterator_mode(iterator) & TB_ITERATOR_MODE_FORWARD));
tb_assert_and_check_return((tb_iterator_mode(iterator) & TB_ITERATOR_MODE_REVERSE));
tb_check_return(head != tail);
// get flag
tb_size_t step = tb_iterator_step(iterator);
tb_size_t flag = tb_iterator_flag(iterator);
if (!flag && step > sizeof(tb_pointer_t))
flag |= TB_ITERATOR_FLAG_ITEM_REF;
// init temp item
tb_pointer_t temp = flag & TB_ITERATOR_FLAG_ITEM_REF? tb_malloc(step) : tb_null;
tb_assert_and_check_return(step <= sizeof(tb_pointer_t) || temp);
// the comparer
if (!comp) comp = tb_iterator_comp;
// sort
tb_size_t last, next;
for (next = tb_iterator_next(iterator, head); next != tail; next = tb_iterator_next(iterator, next))
{
// save next
if (flag & TB_ITERATOR_FLAG_ITEM_REF)
tb_memcpy(temp, tb_iterator_item(iterator, next), step);
else temp = tb_iterator_item(iterator, next);
// look for hole and move elements[hole, next - 1] => [hole + 1, next]
for (last = next; last != head && (last = tb_iterator_prev(iterator, last), comp(iterator, temp, tb_iterator_item(iterator, last)) < 0); next = last)
tb_iterator_copy(iterator, next, tb_iterator_item(iterator, last));
// item => hole
tb_iterator_copy(iterator, next, temp);
}
// free temp item
if (temp && (flag & TB_ITERATOR_FLAG_ITEM_REF)) tb_free(temp);
}
tb_void_t tb_insert_sort_all(tb_iterator_ref_t iterator, tb_iterator_comp_t comp)
{
tb_insert_sort(iterator, tb_iterator_head(iterator), tb_iterator_tail(iterator), comp);
}
tbox-1.7.6/src/tbox/algorithm/insert_sort.h 0000664 0000000 0000000 00000003405 14671175054 0020772 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file insert_sort.h
* @ingroup algorithm
*
*/
#ifndef TB_ALGORITHM_INSERT_SORT_H
#define TB_ALGORITHM_INSERT_SORT_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the insert sorter, O(n^2)
*
* @param iterator the iterator
* @param head the iterator head
* @param tail the iterator tail
* @param comp the comparer
*/
tb_void_t tb_insert_sort(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp);
/*! the insert sorter for all
*
* @param iterator the iterator
* @param comp the comparer
*/
tb_void_t tb_insert_sort_all(tb_iterator_ref_t iterator, tb_iterator_comp_t comp);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/algorithm/predicate.c 0000664 0000000 0000000 00000004001 14671175054 0020343 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file predicate.c
* @ingroup algorithm
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "predicate.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_predicate_eq(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value)
{
// check
tb_assert(iterator);
// item == value?
return !tb_iterator_comp(iterator, item, value);
}
tb_bool_t tb_predicate_le(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value)
{
// check
tb_assert(iterator);
// item < value?
return tb_iterator_comp(iterator, item, value) < 0;
}
tb_bool_t tb_predicate_be(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value)
{
// check
tb_assert(iterator);
// item > value?
return tb_iterator_comp(iterator, item, value) > 0;
}
tb_bool_t tb_predicate_leq(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value)
{
// check
tb_assert(iterator);
// item <= value?
return tb_iterator_comp(iterator, item, value) <= 0;
}
tb_bool_t tb_predicate_beq(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value)
{
// check
tb_assert(iterator);
// item >= value?
return tb_iterator_comp(iterator, item, value) >= 0;
}
tbox-1.7.6/src/tbox/algorithm/predicate.h 0000664 0000000 0000000 00000007124 14671175054 0020361 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file predicate.h
* @ingroup algorithm
*/
#ifndef TB_ALGORITHM_PREDICATE_H
#define TB_ALGORITHM_PREDICATE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/*! the predicate ref type
*
* @param iterator the iterator
* @param item the inner item of the container
* @param value the outer value
*
* @return tb_true or tb_false
*/
typedef tb_bool_t (*tb_predicate_ref_t)(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value);
/*! the predicate break ref type
*
* @param iterator the iterator
* @param item the inner item of the container
* @param value the outer value
* @param is_break is break now?
*
* @return tb_true or tb_false
*/
typedef tb_bool_t (*tb_predicate_break_ref_t)(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value, tb_bool_t* is_break);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the predicate: if (item == value)?
*
* @param iterator the iterator
* @param item the inner item of the container
* @param value the outer value
*
* @return tb_true or tb_false
*/
tb_bool_t tb_predicate_eq(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value);
/*! the predicate: if (item < value)?
*
* @param iterator the iterator
* @param item the inner item of the container
* @param value the outer value
*
* @return tb_true or tb_false
*/
tb_bool_t tb_predicate_le(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value);
/*! the predicate: if (item > value)?
*
* @param iterator the iterator
* @param item the inner item of the container
* @param value the outer value
*
* @return tb_true or tb_false
*/
tb_bool_t tb_predicate_be(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value);
/*! the predicate: if (item <= value)?
*
* @param iterator the iterator
* @param item the inner item of the container
* @param value the outer value
*
* @return tb_true or tb_false
*/
tb_bool_t tb_predicate_leq(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value);
/*! the predicate: if (item >= value)?
*
* @param iterator the iterator
* @param item the inner item of the container
* @param value the outer value
*
* @return tb_true or tb_false
*/
tb_bool_t tb_predicate_beq(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/algorithm/prefix.h 0000664 0000000 0000000 00000001701 14671175054 0017711 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
* @ingroup algorithm
*
*/
#ifndef TB_ALGORITHM_PREFIX_H
#define TB_ALGORITHM_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#include "../container/container.h"
#endif
tbox-1.7.6/src/tbox/algorithm/quick_sort.c 0000664 0000000 0000000 00000005650 14671175054 0020601 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file quick_sort.c
* @ingroup algorithm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "quick_sort.h"
#include "../libc/libc.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_void_t tb_quick_sort(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp)
{
// check
tb_assert_and_check_return(iterator && (tb_iterator_mode(iterator) & TB_ITERATOR_MODE_RACCESS));
tb_check_return(head != tail);
// get flag
tb_size_t step = tb_iterator_step(iterator);
tb_size_t flag = tb_iterator_flag(iterator);
if (!flag && step > sizeof(tb_pointer_t))
flag |= TB_ITERATOR_FLAG_ITEM_REF;
// init key item
tb_pointer_t key = (flag & TB_ITERATOR_FLAG_ITEM_REF)? tb_malloc(step) : tb_null;
tb_assert_and_check_return(step <= sizeof(tb_pointer_t) || key);
// the comparer
if (!comp) comp = tb_iterator_comp;
// hole => key
if (flag & TB_ITERATOR_FLAG_ITEM_REF)
tb_memcpy(key, tb_iterator_item(iterator, head), step);
else key = tb_iterator_item(iterator, head);
// quick_sort
tb_size_t l = head;
tb_size_t r = tail - 1;
while (r > l)
{
// find: <=
for (; r != l; r--)
if (comp(iterator, tb_iterator_item(iterator, r), key) < 0) break;
if (r != l)
{
tb_iterator_copy(iterator, l, tb_iterator_item(iterator, r));
l++;
}
// find: =>
for (; l != r; l++)
if (comp(iterator, tb_iterator_item(iterator, l), key) > 0) break;
if (l != r)
{
tb_iterator_copy(iterator, r, tb_iterator_item(iterator, l));
r--;
}
}
// key => hole
tb_iterator_copy(iterator, l, key);
// quick_sort [head, hole - 1]
tb_quick_sort(iterator, head, l, comp);
// quick_sort [hole + 1, tail]
tb_quick_sort(iterator, ++l, tail, comp);
// free key item
if (key && (flag & TB_ITERATOR_FLAG_ITEM_REF)) tb_free(key);
}
tb_void_t tb_quick_sort_all(tb_iterator_ref_t iterator, tb_iterator_comp_t comp)
{
tb_quick_sort(iterator, tb_iterator_head(iterator), tb_iterator_tail(iterator), comp);
}
tbox-1.7.6/src/tbox/algorithm/quick_sort.h 0000664 0000000 0000000 00000003402 14671175054 0020577 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file quick_sort.h
* @ingroup algorithm
*
*/
#ifndef TB_ALGORITHM_QUICK_SORT_H
#define TB_ALGORITHM_QUICK_SORT_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the quick sorter, O(nlog(n))
*
* @param iterator the iterator
* @param head the iterator head
* @param tail the iterator tail
* @param comp the comparer
*/
tb_void_t tb_quick_sort(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp);
/*! the quick sorter for all
*
* @param iterator the iterator
* @param comp the comparer
*/
tb_void_t tb_quick_sort_all(tb_iterator_ref_t iterator, tb_iterator_comp_t comp);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/algorithm/remove.c 0000664 0000000 0000000 00000002155 14671175054 0017710 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file remove.c
* @ingroup algorithm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "remove.h"
#include "remove_if.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_void_t tb_remove(tb_iterator_ref_t iterator, tb_cpointer_t value)
{
// remove it
tb_remove_if(iterator, tb_predicate_eq, value);
}
tbox-1.7.6/src/tbox/algorithm/remove.h 0000664 0000000 0000000 00000002675 14671175054 0017724 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file remove.h
* @ingroup algorithm
*
*/
#ifndef TB_ALGORITHM_REMOVE_H
#define TB_ALGORITHM_REMOVE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! remove items
*
* @param iterator the iterator
* @param value the value of the predicate
*/
tb_void_t tb_remove(tb_iterator_ref_t iterator, tb_cpointer_t value);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/algorithm/remove_first.c 0000664 0000000 0000000 00000002213 14671175054 0021112 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file remove_first.c
* @ingroup algorithm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "remove_first.h"
#include "remove_first_if.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_void_t tb_remove_first(tb_iterator_ref_t iterator, tb_cpointer_t value)
{
// remove it
tb_remove_first_if(iterator, tb_predicate_eq, value);
}
tbox-1.7.6/src/tbox/algorithm/remove_first.h 0000664 0000000 0000000 00000002736 14671175054 0021131 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file remove_first.h
* @ingroup algorithm
*
*/
#ifndef TB_ALGORITHM_REMOVE_FIRST_H
#define TB_ALGORITHM_REMOVE_FIRST_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! remove the first item
*
* @param iterator the iterator
* @param value the value of the predicate
*/
tb_void_t tb_remove_first(tb_iterator_ref_t iterator, tb_cpointer_t value);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/algorithm/remove_first_if.c 0000664 0000000 0000000 00000003341 14671175054 0021573 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file remove_first_if.c
* @ingroup algorithm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "remove_first_if.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_void_t tb_remove_first_if(tb_iterator_ref_t iterator, tb_predicate_ref_t pred, tb_cpointer_t value)
{
// check
tb_assert_and_check_return(iterator && pred);
// the iterator mode
tb_size_t mode = tb_iterator_mode(iterator);
tb_assert_and_check_return((mode & TB_ITERATOR_MODE_FORWARD));
tb_assert_and_check_return(!(mode & TB_ITERATOR_MODE_READONLY));
// done
tb_size_t itor = tb_iterator_head(iterator);
while (itor != tb_iterator_tail(iterator))
{
// done predicate
if (pred(iterator, tb_iterator_item(iterator, itor), value))
{
// remove it
tb_iterator_remove(iterator, itor);
break;
}
// next
itor = tb_iterator_next(iterator, itor);
}
}
tbox-1.7.6/src/tbox/algorithm/remove_first_if.h 0000664 0000000 0000000 00000003121 14671175054 0021574 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file remove_first_if.h
* @ingroup algorithm
*
*/
#ifndef TB_ALGORITHM_REMOVE_FIRST_IF_H
#define TB_ALGORITHM_REMOVE_FIRST_IF_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "predicate.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! remove the first item if pred(item, value)
*
* @param iterator the iterator
* @param pred the predicate
* @param value the value of the predicate
*/
tb_void_t tb_remove_first_if(tb_iterator_ref_t iterator, tb_predicate_ref_t pred, tb_cpointer_t value);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/algorithm/remove_if.c 0000664 0000000 0000000 00000010734 14671175054 0020370 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file remove_if.c
* @ingroup algorithm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "remove_if.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_bool_t tb_remove_if_pred(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value, tb_bool_t* pbreak)
{
// check
tb_value_ref_t tuple = (tb_value_ref_t)value;
tb_assert(tuple && tuple[0].cptr);
// the pred
return ((tb_predicate_ref_t)tuple[0].cptr)(iterator, item, tuple[1].cptr);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_void_t tb_remove_if(tb_iterator_ref_t iterator, tb_predicate_ref_t pred, tb_cpointer_t value)
{
// init tuple
tb_value_t tuple[2];
tuple[0].cptr = pred;
tuple[1].cptr = value;
// remove it
tb_remove_if_until(iterator, tb_remove_if_pred, tuple);
}
tb_void_t tb_remove_if_until(tb_iterator_ref_t iterator, tb_predicate_break_ref_t pred, tb_cpointer_t value)
{
// check
tb_assert_and_check_return(iterator && pred);
// the iterator mode
tb_size_t mode = tb_iterator_mode(iterator);
tb_assert_and_check_return((mode & TB_ITERATOR_MODE_FORWARD));
tb_assert_and_check_return(!(mode & TB_ITERATOR_MODE_READONLY));
// done
tb_size_t next;
tb_size_t size = 0;
tb_bool_t ok = tb_false;
tb_bool_t need = tb_false;
tb_bool_t is_break = tb_false;
tb_size_t prev = tb_iterator_tail(iterator);
tb_size_t itor = tb_iterator_head(iterator);
tb_size_t base = tb_iterator_tail(iterator);
tb_bool_t bmutable = (mode & TB_ITERATOR_MODE_MUTABLE)? tb_true : tb_false;
while (itor != tb_iterator_tail(iterator))
{
// save next
next = tb_iterator_next(iterator, itor);
// done predicate
ok = pred(iterator, tb_iterator_item(iterator, itor), value, &is_break);
// remove it?
if (ok)
{
// is the first removed item?
if (!need)
{
// save the removed range base
base = prev;
// need remove items
need = tb_true;
}
// update size
size++;
}
// the removed range have been passed or stop or end?
if (!ok || next == tb_iterator_tail(iterator))
{
// need remove items?
if (need)
{
// check
tb_assert(size);
// the previous tail
tb_size_t prev_tail = tb_iterator_tail(iterator);
// remove items
tb_iterator_nremove(iterator, base, ok? next : itor, size);
// reset state
need = tb_false;
size = 0;
// is the mutable iterator?
if (bmutable)
{
// update itor
prev = base;
// the body items are removed?
if (base != prev_tail) itor = tb_iterator_next(iterator, base);
// the head items are removed?
else itor = tb_iterator_head(iterator);
// the last item be not removed? skip the last walked item
if (!ok)
{
prev = itor;
itor = tb_iterator_next(iterator, itor);
}
// break?
tb_check_break(!is_break);
// continue?
continue ;
}
}
// break?
tb_check_break(!is_break);
}
// next
prev = itor;
itor = next;
}
}
tbox-1.7.6/src/tbox/algorithm/remove_if.h 0000664 0000000 0000000 00000003570 14671175054 0020375 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file remove_if.h
* @ingroup algorithm
*
*/
#ifndef TB_ALGORITHM_REMOVE_IF_H
#define TB_ALGORITHM_REMOVE_IF_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "predicate.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! remove items if pred(item, value)
*
* @param iterator the iterator
* @param pred the predicate
* @param value the value of the predicate
*/
tb_void_t tb_remove_if(tb_iterator_ref_t iterator, tb_predicate_ref_t pred, tb_cpointer_t value);
/*! remove items if pred(item, value, &is_break) until is_break == tb_true
*
* @param iterator the iterator
* @param pred the predicate with break
* @param value the value of the predicate
*/
tb_void_t tb_remove_if_until(tb_iterator_ref_t iterator, tb_predicate_break_ref_t pred, tb_cpointer_t value);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/algorithm/rfind.c 0000664 0000000 0000000 00000002424 14671175054 0017514 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file rfind.c
* @ingroup algorithm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "rfind.h"
#include "rfind_if.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_rfind(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_cpointer_t value)
{
return tb_rfind_if(iterator, head, tail, tb_predicate_eq, value);
}
tb_size_t tb_rfind_all(tb_iterator_ref_t iterator, tb_cpointer_t value)
{
return tb_rfind_all_if(iterator, tb_predicate_eq, value);
}
tbox-1.7.6/src/tbox/algorithm/rfind.h 0000664 0000000 0000000 00000003645 14671175054 0017527 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file rfind.h
* @ingroup algorithm
*
*/
#ifndef TB_ALGORITHM_RFIND_H
#define TB_ALGORITHM_RFIND_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! reverse find item
*
* @param iterator the iterator
* @param head the iterator head
* @param tail the iterator tail
* @param value the value of the predicate
*
* @return the iterator itor, return tb_iterator_tail(iterator) if not found
*/
tb_size_t tb_rfind(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_cpointer_t value);
/*! reverse find item for all
*
* @param iterator the iterator
* @param value the value of the predicate
*
* @return the iterator itor, return tb_iterator_tail(iterator) if not found
*/
tb_size_t tb_rfind_all(tb_iterator_ref_t iterator, tb_cpointer_t value);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/algorithm/rfind_if.c 0000664 0000000 0000000 00000003557 14671175054 0020202 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file rfind_if.c
* @ingroup algorithm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "rfind_if.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_rfind_if(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_predicate_ref_t pred, tb_cpointer_t value)
{
// check
tb_assert_and_check_return_val(pred && iterator && (tb_iterator_mode(iterator) & TB_ITERATOR_MODE_REVERSE), tb_iterator_tail(iterator));
// null?
tb_check_return_val(head != tail, tb_iterator_tail(iterator));
// find
tb_size_t itor = tail;
tb_bool_t find = tb_false;
do
{
// the previous item
itor = tb_iterator_prev(iterator, itor);
// comp
if ((find = pred(iterator, tb_iterator_item(iterator, itor), value))) break;
} while (itor != head);
// ok?
return find? itor : tb_iterator_tail(iterator);
}
tb_size_t tb_rfind_all_if(tb_iterator_ref_t iterator, tb_predicate_ref_t pred, tb_cpointer_t value)
{
return tb_rfind_if(iterator, tb_iterator_head(iterator), tb_iterator_tail(iterator), pred, value);
}
tbox-1.7.6/src/tbox/algorithm/rfind_if.h 0000664 0000000 0000000 00000004153 14671175054 0020200 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file rfind_if.h
* @ingroup algorithm
*
*/
#ifndef TB_ALGORITHM_RFIND_IF_H
#define TB_ALGORITHM_RFIND_IF_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "predicate.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! reverse find item if pred(item, value)
*
* @param iterator the iterator
* @param head the iterator head
* @param tail the iterator tail
* @param pred the predicate
* @param value the value of the predicate
*
* @return the iterator itor, return tb_iterator_tail(iterator) if not found
*/
tb_size_t tb_rfind_if(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_predicate_ref_t pred, tb_cpointer_t value);
/*! reverse find item for all if pred(item, value)
*
* @param iterator the iterator
* @param pred the predicate
* @param value the value of the predicate
*
* @return the iterator itor, return tb_iterator_tail(iterator) if not found
*/
tb_size_t tb_rfind_all_if(tb_iterator_ref_t iterator, tb_predicate_ref_t pred, tb_cpointer_t value);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/algorithm/rfor.h 0000664 0000000 0000000 00000006154 14671175054 0017373 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file rfor.h
* @ingroup algorithm
*
*/
#ifndef TB_ALGORITHM_RFOR_H
#define TB_ALGORITHM_RFOR_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/*! for items using iterator
*
* @code
* tb_rfor(tb_char_t*, item, tb_iterator_head(iterator), tb_iterator_tail(iterator), iterator)
* {
* tb_trace_d("item: %s", item);
* }
*
* tb_rfor(tb_size_t, item, tb_iterator_head(iterator), tb_iterator_tail(iterator), iterator)
* {
* tb_trace_d("item: %lu", item);
* }
*
* tb_rfor(tb_hash_map_item_ref_t, item, tb_iterator_head(iterator), tb_iterator_tail(iterator), iterator)
* {
* if (item) tb_trace_d("item: %p => %p", item->name, item->data);
* }
* @endcode
*/
#define tb_rfor(type, item, head, tail, iterator) \
/* iterator */ \
tb_iterator_ref_t item##_iterator = (tb_iterator_ref_t)iterator; \
tb_assert(!item##_iterator || (tb_iterator_mode(item##_iterator) & (TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_RACCESS))); \
/* init */ \
type item; \
tb_size_t item##_itor; \
tb_size_t item##_head = head; \
tb_size_t item##_tail = tail; \
/* walk */ \
if (item##_iterator && item##_head != item##_tail) \
for ( item##_itor = tb_iterator_prev(item##_iterator, item##_tail); \
item##_itor != item##_tail && ((item = (type)tb_iterator_item(item##_iterator, item##_itor)), item##_itor = item##_itor != item##_head? item##_itor : item##_tail, 1); \
item##_itor = item##_itor != item##_tail? tb_iterator_prev(item##_iterator, item##_itor) : item##_tail)
/*! for all items using iterator
*
* @code
*
* tb_rfor_all(tb_char_t*, item, iterator)
* {
* tb_trace_d("item: %s", item);
* }
*
* tb_rfor_all(tb_size_t, item, iterator)
* {
* tb_trace_d("item: %lu", item);
* }
*
* tb_rfor_all(tb_hash_map_item_ref_t, item, iterator)
* {
* if (item) tb_trace_d("item: %p => %p", item->name, item->data);
* }
* @endcode
*/
#define tb_rfor_all(type, item, iterator) \
tb_iterator_ref_t item##_iterator_all = (tb_iterator_ref_t)iterator; \
tb_rfor(type, item, tb_iterator_head(item##_iterator_all), tb_iterator_tail(item##_iterator_all), item##_iterator_all)
#endif
tbox-1.7.6/src/tbox/algorithm/rfor_if.h 0000664 0000000 0000000 00000006325 14671175054 0020051 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file rfor_if.h
* @ingroup algorithm
*
*/
#ifndef TB_ALGORITHM_RFOR_IF_H
#define TB_ALGORITHM_RFOR_IF_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/*! for items using iterator
*
* @code
* tb_rfor_if(tb_char_t*, item, tb_iterator_head(iterator), tb_iterator_tail(iterator), iterator, item)
* {
* tb_trace_d("item: %s", item);
* }
*
* tb_rfor_if(tb_size_t, item, tb_iterator_head(iterator), tb_iterator_tail(iterator), iterator, item > 10)
* {
* tb_trace_d("item: %lu", item);
* }
*
* tb_rfor_if(tb_hash_map_item_ref_t, item, tb_iterator_head(iterator), tb_iterator_tail(iterator), iterator, item != tb_null)
* {
* tb_trace_d("item: %p => %p", item->name, item->data);
* }
* @endcode
*/
#define tb_rfor_if(type, item, head, tail, iterator, cond) \
/* iterator */ \
tb_iterator_ref_t item##_iterator = (tb_iterator_ref_t)iterator; \
tb_assert(!item##_iterator || (tb_iterator_mode(item##_iterator) & (TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_RACCESS))); \
/* init */ \
type item; \
tb_size_t item##_itor; \
tb_size_t item##_head = head; \
tb_size_t item##_tail = tail; \
/* walk */ \
if (item##_iterator && item##_head != item##_tail) \
for ( item##_itor = tb_iterator_prev(item##_iterator, item##_tail); \
item##_itor != item##_tail && ((item = (type)tb_iterator_item(item##_iterator, item##_itor)), item##_itor = item##_itor != item##_head? item##_itor : item##_tail, 1); \
item##_itor = item##_itor != item##_tail? tb_iterator_prev(item##_iterator, item##_itor) : item##_tail) if ((cond))
/*! for all items using iterator
*
* @code
*
* tb_rfor_all(tb_char_t*, item, iterator, item)
* {
* tb_trace_d("item: %s", item);
* }
*
* tb_rfor_all(tb_size_t, item, iterator, itme > 10)
* {
* tb_trace_d("item: %lu", item);
* }
*
* tb_rfor_all(tb_hash_map_item_ref_t, item, iterator, item != tb_null)
* {
* tb_trace_d("item: %p => %p", item->name, item->data);
* }
* @endcode
*/
#define tb_rfor_all_if(type, item, iterator, cond) \
tb_iterator_ref_t item##_iterator_all = (tb_iterator_ref_t)iterator; \
tb_rfor_if(type, item, tb_iterator_head(item##_iterator_all), tb_iterator_tail(item##_iterator_all), item##_iterator_all, cond)
#endif
tbox-1.7.6/src/tbox/algorithm/rwalk.c 0000664 0000000 0000000 00000003276 14671175054 0017540 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file rwalk.c
* @ingroup algorithm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "rwalk.h"
#include "rfor.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_rwalk(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_rwalk_func_t func, tb_cpointer_t priv)
{
// check
tb_assert_and_check_return_val(iterator && (tb_iterator_mode(iterator) & TB_ITERATOR_MODE_REVERSE) && func, 0);
// null?
tb_check_return_val(head != tail, 0);
// rwalk
tb_size_t count = 0;
tb_rfor (tb_pointer_t, item, head, tail, iterator)
{
// done
if (!func(iterator, item, priv)) break;
// count++
count++;
}
// ok?
return count;
}
tb_size_t tb_rwalk_all(tb_iterator_ref_t iterator, tb_rwalk_func_t func, tb_cpointer_t priv)
{
return tb_rwalk(iterator, tb_iterator_head(iterator), tb_iterator_tail(iterator), func, priv);
}
tbox-1.7.6/src/tbox/algorithm/rwalk.h 0000664 0000000 0000000 00000004234 14671175054 0017540 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file rwalk.h
* @ingroup algorithm
*
*/
#ifndef TB_ALGORITHM_RWALK_H
#define TB_ALGORITHM_RWALK_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the reverse walk func type
typedef tb_bool_t (*tb_rwalk_func_t)(tb_iterator_ref_t iterator, tb_pointer_t item, tb_cpointer_t priv);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the reverse walker
*
* @param iterator the iterator
* @param head the iterator head
* @param tail the iterator tail
* @param func the walker func
* @param priv the func private data
*
* @return the item count
*/
tb_size_t tb_rwalk(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_rwalk_func_t func, tb_cpointer_t priv);
/*! the reverse walker for all
*
* @param iterator the iterator
* @param func the walker func
* @param priv the func private data
*
* @return the item count
*/
tb_size_t tb_rwalk_all(tb_iterator_ref_t iterator, tb_rwalk_func_t func, tb_cpointer_t priv);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/algorithm/sort.c 0000664 0000000 0000000 00000004207 14671175054 0017402 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file sort.c
* @ingroup algorithm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "sort.h"
#include "distance.h"
#include "heap_sort.h"
#include "quick_sort.h"
#include "insert_sort.h"
#include "bubble_sort.h"
#include "../libc/libc.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_void_t tb_sort(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp)
{
// check
tb_assert_and_check_return(iterator);
// no elements?
tb_check_return(head != tail);
// readonly?
tb_assert_and_check_return(!(tb_iterator_mode(iterator) & TB_ITERATOR_MODE_READONLY));
#ifdef TB_CONFIG_MICRO_ENABLE
// random access iterator?
tb_assert_and_check_return(tb_iterator_mode(iterator) & TB_ITERATOR_MODE_RACCESS);
// sort it
tb_quick_sort(iterator, head, tail, comp);
#else
// random access iterator?
if (tb_iterator_mode(iterator) & TB_ITERATOR_MODE_RACCESS)
{
if (tb_distance(iterator, head, tail) > 100000) tb_heap_sort(iterator, head, tail, comp);
else tb_quick_sort(iterator, head, tail, comp); //!< @note the recursive stack size is limit
}
else tb_insert_sort(iterator, head, tail, comp);
#endif
}
tb_void_t tb_sort_all(tb_iterator_ref_t iterator, tb_iterator_comp_t comp)
{
tb_sort(iterator, tb_iterator_head(iterator), tb_iterator_tail(iterator), comp);
}
tbox-1.7.6/src/tbox/algorithm/sort.h 0000664 0000000 0000000 00000003314 14671175054 0017405 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file sort.h
* @ingroup algorithm
*
*/
#ifndef TB_ALGORITHM_SORT_H
#define TB_ALGORITHM_SORT_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the sorter
*
* @param iterator the iterator
* @param head the iterator head
* @param tail the iterator tail
* @param comp the comparer
*/
tb_void_t tb_sort(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_iterator_comp_t comp);
/*! the sorter for all
*
* @param iterator the iterator
* @param comp the comparer
*/
tb_void_t tb_sort_all(tb_iterator_ref_t iterator, tb_iterator_comp_t comp);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/algorithm/walk.c 0000664 0000000 0000000 00000003264 14671175054 0017353 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file walk.c
* @ingroup algorithm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "walk.h"
#include "for.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_walk(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_walk_func_t func, tb_cpointer_t priv)
{
// check
tb_assert_and_check_return_val(iterator && (tb_iterator_mode(iterator) & TB_ITERATOR_MODE_FORWARD) && func, 0);
// null?
tb_check_return_val(head != tail, 0);
// walk
tb_size_t count = 0;
tb_for (tb_pointer_t, item, head, tail, iterator)
{
// done
if (!func(iterator, item, priv)) break;
// count++
count++;
}
// ok?
return count;
}
tb_size_t tb_walk_all(tb_iterator_ref_t iterator, tb_walk_func_t func, tb_cpointer_t priv)
{
return tb_walk(iterator, tb_iterator_head(iterator), tb_iterator_tail(iterator), func, priv);
}
tbox-1.7.6/src/tbox/algorithm/walk.h 0000664 0000000 0000000 00000004174 14671175054 0017361 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file walk.h
* @ingroup algorithm
*
*/
#ifndef TB_ALGORITHM_WALK_H
#define TB_ALGORITHM_WALK_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the walk func type
typedef tb_bool_t (*tb_walk_func_t)(tb_iterator_ref_t iterator, tb_pointer_t item, tb_cpointer_t priv);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the walker
*
* @param iterator the iterator
* @param head the iterator head
* @param tail the iterator tail
* @param func the walker func
* @param priv the func private data
*
* @return the item count
*/
tb_size_t tb_walk(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_walk_func_t func, tb_cpointer_t priv);
/*! the walker for all
*
* @param iterator the iterator
* @param func the walker func
* @param priv the func private data
*
* @return the item count
*/
tb_size_t tb_walk_all(tb_iterator_ref_t iterator, tb_walk_func_t func, tb_cpointer_t priv);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/charset/ 0000775 0000000 0000000 00000000000 14671175054 0015707 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/charset/ascii.c 0000664 0000000 0000000 00000002764 14671175054 0017154 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file ascii.c
* @ingroup charset
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../stream/stream.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_long_t tb_charset_ascii_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch);
tb_long_t tb_charset_ascii_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch)
{
*ch = tb_static_stream_read_u8(sstream);
return 1;
}
tb_long_t tb_charset_ascii_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch);
tb_long_t tb_charset_ascii_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch)
{
if (ch <= 0xff) tb_static_stream_writ_u8(sstream, (tb_uint8_t)ch);
return 1;
}
tbox-1.7.6/src/tbox/charset/charset.c 0000664 0000000 0000000 00000020507 14671175054 0017510 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file charset.c
* @ingroup charset
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "charset.h"
#include "../algorithm/algorithm.h"
#include "../platform/impl/charset.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* declaration
*/
// ascii
tb_long_t tb_charset_ascii_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch);
tb_long_t tb_charset_ascii_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch);
// utf8
tb_long_t tb_charset_utf8_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch);
tb_long_t tb_charset_utf8_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch);
// utf16
tb_long_t tb_charset_utf16_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch);
tb_long_t tb_charset_utf16_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch);
// utf32
tb_long_t tb_charset_utf32_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch);
tb_long_t tb_charset_utf32_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch);
// ucs2
tb_long_t tb_charset_ucs2_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch);
tb_long_t tb_charset_ucs2_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch);
// ucs4
tb_long_t tb_charset_ucs4_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch);
tb_long_t tb_charset_ucs4_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch);
// gb2312
tb_long_t tb_charset_gb2312_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch);
tb_long_t tb_charset_gb2312_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch);
// iso8859
tb_long_t tb_charset_iso8859_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch);
tb_long_t tb_charset_iso8859_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch);
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
// the charsets, @note: type & name is sorted
static tb_charset_t g_charsets[] =
{
{TB_CHARSET_TYPE_ASCII, "ascii", tb_charset_ascii_get, tb_charset_ascii_set }
, {TB_CHARSET_TYPE_GB2312, "gb2312", tb_charset_gb2312_get, tb_charset_gb2312_set }
, {TB_CHARSET_TYPE_GBK, "gbk", tb_charset_gb2312_get, tb_charset_gb2312_set }
, {TB_CHARSET_TYPE_ISO8859, "iso8859", tb_charset_iso8859_get, tb_charset_iso8859_set }
, {TB_CHARSET_TYPE_UCS2, "ucs3", tb_charset_ucs2_get, tb_charset_ucs2_set }
, {TB_CHARSET_TYPE_UCS4, "ucs4", tb_charset_ucs4_get, tb_charset_ucs4_set }
, {TB_CHARSET_TYPE_UTF16, "utf16", tb_charset_utf16_get, tb_charset_utf16_set }
, {TB_CHARSET_TYPE_UTF32, "utf32", tb_charset_utf32_get, tb_charset_utf32_set }
, {TB_CHARSET_TYPE_UTF8, "utf8", tb_charset_utf8_get, tb_charset_utf8_set }
};
/* //////////////////////////////////////////////////////////////////////////////////////
* finder
*/
static tb_long_t tb_charset_comp_by_name(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t name)
{
// check
tb_assert(item);
// comp
return tb_stricmp(((tb_charset_ref_t)item)->name, (tb_char_t const*)name);
}
static tb_long_t tb_charset_comp_by_type(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t type)
{
// check
tb_assert(item && type);
// comp
return (tb_long_t)((tb_charset_ref_t)item)->type - (tb_long_t)type;
}
static tb_charset_ref_t tb_charset_find_by_name(tb_char_t const* name)
{
// make iterator
tb_array_iterator_t array_iterator;
tb_iterator_ref_t iterator = tb_array_iterator_init_mem(&array_iterator, g_charsets, tb_arrayn(g_charsets), sizeof(tb_charset_t));
tb_assert_and_check_return_val(iterator, tb_null);
// find it by the binary search
tb_size_t itor = tb_binary_find_all_if(iterator, tb_charset_comp_by_name, name);
// ok?
if (itor != tb_iterator_tail(iterator))
return (tb_charset_ref_t)tb_iterator_item(iterator, itor);
else return tb_null;
}
static tb_charset_ref_t tb_charset_find_by_type(tb_size_t type)
{
// make iterator
tb_array_iterator_t array_iterator;
tb_iterator_ref_t iterator = tb_array_iterator_init_mem(&array_iterator, g_charsets, tb_arrayn(g_charsets), sizeof(tb_charset_t));
tb_assert_and_check_return_val(iterator, tb_null);
// find it by the binary search
tb_size_t itor = tb_binary_find_all_if(iterator, tb_charset_comp_by_type, (tb_cpointer_t)TB_CHARSET_TYPE(type));
// ok?
if (itor != tb_iterator_tail(iterator))
return (tb_charset_ref_t)tb_iterator_item(iterator, itor);
else return tb_null;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_char_t const* tb_charset_name(tb_size_t type)
{
// find
tb_charset_ref_t charset = tb_charset_find_by_type(type);
tb_assert_and_check_return_val(charset, tb_null);
// type
return charset->name;
}
tb_size_t tb_charset_type(tb_char_t const* name)
{
// find
tb_charset_ref_t charset = tb_charset_find_by_name(name);
tb_assert_and_check_return_val(charset, TB_CHARSET_TYPE_NONE);
// type
return charset->type;
}
tb_charset_ref_t tb_charset_find(tb_size_t type)
{
return tb_charset_find_by_type(type);
}
tb_long_t tb_charset_conv_bst(tb_size_t ftype, tb_size_t ttype, tb_static_stream_ref_t fst, tb_static_stream_ref_t tst)
{
// check
tb_assert_and_check_return_val(TB_CHARSET_TYPE_OK(ftype) && TB_CHARSET_TYPE_OK(ttype) && fst && tst, -1);
tb_assert_and_check_return_val(tb_static_stream_valid(fst) && tb_static_stream_valid(tst), -1);
// attempt to convert charset using the platform implementation
tb_long_t ok = tb_charset_conv_impl(ftype, ttype, fst, tst);
tb_check_return_val(ok < 0, ok);
// init the charset
tb_charset_ref_t fr = tb_charset_find_by_type(ftype);
tb_charset_ref_t to = tb_charset_find_by_type(ttype);
tb_assert_and_check_return_val(fr && to && fr->get && fr->set, -1);
// no data?
tb_check_return_val(tb_static_stream_left(fst), 0);
// big endian?
tb_bool_t fbe = !(ftype & TB_CHARSET_TYPE_LE)? tb_true : tb_false;
tb_bool_t tbe = !(ttype & TB_CHARSET_TYPE_LE)? tb_true : tb_false;
// walk
tb_uint32_t ch;
tb_byte_t const* tp = tb_static_stream_pos(tst);
while (tb_static_stream_left(fst) && tb_static_stream_left(tst))
{
// get ucs4 character
tb_long_t ok = 0;
if ((ok = fr->get(fst, fbe, &ch)) > 0)
{
// set ucs4 character
if (to->set(tst, tbe, ch) < 0) break;
}
else if (ok < 0) break;
}
// ok?
return tb_static_stream_pos(tst) - tp;
}
tb_long_t tb_charset_conv_cstr(tb_size_t ftype, tb_size_t ttype, tb_char_t const* cstr, tb_byte_t* data, tb_size_t size)
{
// check
tb_assert_and_check_return_val(TB_CHARSET_TYPE_OK(ftype) && TB_CHARSET_TYPE_OK(ttype) && cstr && data && size, -1);
// conv
return tb_charset_conv_data(ftype, ttype, (tb_byte_t const*)cstr, tb_strlen(cstr), data, size);
}
tb_long_t tb_charset_conv_data(tb_size_t ftype, tb_size_t ttype, tb_byte_t const* idata, tb_size_t isize, tb_byte_t* odata, tb_size_t osize)
{
// check
tb_assert_and_check_return_val(TB_CHARSET_TYPE_OK(ftype) && TB_CHARSET_TYPE_OK(ttype) && idata && odata && osize, -1);
tb_check_return_val(isize, 0);
// init static stream
tb_static_stream_t ist;
tb_static_stream_t ost;
tb_static_stream_init(&ist, (tb_byte_t*)idata, isize);
tb_static_stream_init(&ost, odata, osize);
// conv
return tb_charset_conv_bst(ftype, ttype, &ist, &ost);
}
tbox-1.7.6/src/tbox/charset/charset.h 0000664 0000000 0000000 00000012145 14671175054 0017514 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file charset.h
* @defgroup charset
* @ingroup charset
*
*/
#ifndef TB_CHARSET_H
#define TB_CHARSET_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../stream/stream.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the endian for the charset type
#define TB_CHARSET_TYPE_LE (0x0100)
#define TB_CHARSET_TYPE_BE (0x0000)
#define TB_CHARSET_TYPE_ME (0x0100)
#ifdef TB_WORDS_BIGENDIAN
# define TB_CHARSET_TYPE_NE (TB_CHARSET_TYPE_BE)
#else
# define TB_CHARSET_TYPE_NE (TB_CHARSET_TYPE_LE)
#endif
// type
#define TB_CHARSET_TYPE(type) (((type) & ~TB_CHARSET_TYPE_ME))
// ok?
#define TB_CHARSET_TYPE_OK(type) (TB_CHARSET_TYPE(type) != TB_CHARSET_TYPE_NONE)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/*! the charset type enum
*
* @note default: big endian
*/
typedef enum __tb_charset_type_e
{
TB_CHARSET_TYPE_NONE = 0x00
, TB_CHARSET_TYPE_ASCII = 0x01
, TB_CHARSET_TYPE_GB2312 = 0x02
, TB_CHARSET_TYPE_GBK = 0x03
, TB_CHARSET_TYPE_ISO8859 = 0x04
, TB_CHARSET_TYPE_UCS2 = 0x05
, TB_CHARSET_TYPE_UCS4 = 0x06
, TB_CHARSET_TYPE_UTF16 = 0x07
, TB_CHARSET_TYPE_UTF32 = 0x08
, TB_CHARSET_TYPE_UTF8 = 0x09
, TB_CHARSET_TYPE_ANSI = 0x10
#ifdef TB_CONFIG_OS_WINDOWS
, TB_CHARSET_TYPE_COCP = 0x11 //!< console output cp
#endif
}tb_charset_type_e;
/// the charset type
typedef struct __tb_charset_t
{
/// the charset type
tb_size_t type;
/// the charset name
tb_char_t const* name;
/*! get ucs4 character
*
* return: -1, 0 or 1
*
* -1: failed, break it
* 0: no character, skip and continue it
* 1: ok, continue it
*/
tb_long_t (*get)(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch);
/*! set ucs4 character
*
* return: -1, 0 or 1
*
* -1: failed, break it
* 0: no character, skip and continue it
* 1: ok, continue it
*/
tb_long_t (*set)(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch);
}tb_charset_t;
/// the charset ref type
typedef tb_charset_t* tb_charset_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the charset name
*
* @param type the charset type
*
* @return the charset name
*/
tb_char_t const* tb_charset_name(tb_size_t type);
/*! the charset type
*
* @param name the charset name
*
* @return the charset type
*/
tb_size_t tb_charset_type(tb_char_t const* name);
/*! find the charset
*
* @param type the charset type
*
* @return the charset pointer
*/
tb_charset_ref_t tb_charset_find(tb_size_t type);
/*! convert charset from static stream
*
* @param ftype the from charset
* @param ttype the to charset
* @param fst the from stream
* @param tst the to stream
*
* @return the converted bytes for output or -1
*/
tb_long_t tb_charset_conv_bst(tb_size_t ftype, tb_size_t ttype, tb_static_stream_ref_t fst, tb_static_stream_ref_t tst);
/*! convert charset from cstr
*
* @param ftype the from charset
* @param ttype the to charset
* @param cstr the cstr
* @param data the data
* @param size the size
*
* @return the converted bytes for output or -1
*/
tb_long_t tb_charset_conv_cstr(tb_size_t ftype, tb_size_t ttype, tb_char_t const* cstr, tb_byte_t* data, tb_size_t size);
/*! convert charset from data
*
* @param ftype the from charset
* @param ttype the to charset
* @param idata the idata
* @param isize the isize
* @param odata the odata
* @param osize the osize
*
* @return the converted bytes for output or -1
*/
tb_long_t tb_charset_conv_data(tb_size_t ftype, tb_size_t ttype, tb_byte_t const* idata, tb_size_t isize, tb_byte_t* odata, tb_size_t osize);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/charset/gb2312.c 0000664 0000000 0000000 00000006775 14671175054 0016772 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file gb2312.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../stream/stream.h"
#include "gb2312.g"
/* //////////////////////////////////////////////////////////////////////////////////////
* helper
*/
static tb_uint32_t tb_charset_gb2312_from_ucs4(tb_uint32_t ch)
{
// is ascii?
if (ch <= 0x7f) return ch;
// find the gb2312 character
tb_long_t left = 0;
tb_long_t right = (g_charset_ucs4_to_gb2312_table_size / sizeof(g_charset_ucs4_to_gb2312_table_data[0])) - 1;
while (left <= right)
{
// the middle character
tb_long_t mid = (left + right) >> 1;
tb_uint16_t mid_ucs4 = g_charset_ucs4_to_gb2312_table_data[mid][0];
// find it?
if (mid_ucs4 == ch)
return g_charset_ucs4_to_gb2312_table_data[mid][1];
if (ch > mid_ucs4) left = mid + 1;
else right = mid - 1;
}
return 0;
}
static tb_uint32_t tb_charset_gb2312_to_ucs4(tb_uint32_t ch)
{
// is ascii?
if (ch <= 0x7f) return ch;
// is gb2312?
if (ch >= 0xa1a1 && ch <= 0xf7fe)
return g_charset_gb2312_to_ucs4_table_data[ch - 0xa1a1];
else return 0;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_long_t tb_charset_gb2312_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch);
tb_long_t tb_charset_gb2312_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch)
{
// init
tb_byte_t const* p = tb_static_stream_pos(sstream);
tb_size_t n = tb_static_stream_left(sstream);
if (*p <= 0x7f)
{
// not enough? break it
tb_check_return_val(n, -1);
// get character
*ch = tb_static_stream_read_u8(sstream);
}
else
{
// not enough? break it
tb_check_return_val(n > 1, -1);
// get character
*ch = tb_charset_gb2312_to_ucs4(be? tb_static_stream_read_u16_be(sstream) : tb_static_stream_read_u16_le(sstream));
}
// ok
return 1;
}
tb_long_t tb_charset_gb2312_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch);
tb_long_t tb_charset_gb2312_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch)
{
// init
tb_size_t n = tb_static_stream_left(sstream);
// character
ch = tb_charset_gb2312_from_ucs4(ch);
if (ch <= 0x7f)
{
// not enough? break it
tb_check_return_val(n, -1);
// set character
tb_static_stream_writ_u8(sstream, ch & 0xff);
}
else
{
// not enough? break it
tb_check_return_val(n > 1, 0);
// set character
if (be) tb_static_stream_writ_u16_be(sstream, ch & 0xffff);
else tb_static_stream_writ_u16_le(sstream, ch & 0xffff);
}
// ok
return 1;
}
tbox-1.7.6/src/tbox/charset/gb2312.g 0000664 0000000 0000000 00001714456 14671175054 0017001 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-2020, TBOOX Open Source Group.
*
* @author ruki
* @file gb2312.g
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#ifdef TB_COMPILER_IS_MSVC
# pragma warning(disable: 4819)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
static tb_uint16_t g_charset_gb2312_to_ucs4_table_data[] =
{
0x3000
, 0x3001
, 0x3002
, 0x30fb
, 0x02c9
, 0x02c7
, 0x00a8
, 0x3003
, 0x3005
, 0x2015
, 0xff5e
, 0x2016
, 0x2026
, 0x2018
, 0x2019
, 0x201c
, 0x201d
, 0x3014
, 0x3015
, 0x3008
, 0x3009
, 0x300a
, 0x300b
, 0x300c
, 0x300d
, 0x300e
, 0x300f
, 0x3016
, 0x3017
, 0x3010
, 0x3011
, 0x00b1
, 0x00d7
, 0x00f7
, 0x2236
, 0x2227
, 0x2228
, 0x2211
, 0x220f
, 0x222a
, 0x2229
, 0x2208
, 0x2237
, 0x221a
, 0x22a5
, 0x2225
, 0x2220
, 0x2312
, 0x2299
, 0x222b
, 0x222e
, 0x2261
, 0x224c
, 0x2248
, 0x223d
, 0x221d
, 0x2260
, 0x226e
, 0x226f
, 0x2264
, 0x2265
, 0x221e
, 0x2235
, 0x2234
, 0x2642
, 0x2640
, 0x00b0
, 0x2032
, 0x2033
, 0x2103
, 0xff04
, 0x00a4
, 0xffe0
, 0xffe1
, 0x2030
, 0x00a7
, 0x2116
, 0x2606
, 0x2605
, 0x25cb
, 0x25cf
, 0x25ce
, 0x25c7
, 0x25c6
, 0x25a1
, 0x25a0
, 0x25b3
, 0x25b2
, 0x203b
, 0x2192
, 0x2190
, 0x2191
, 0x2193
, 0x3013
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x2488
, 0x2489
, 0x248a
, 0x248b
, 0x248c
, 0x248d
, 0x248e
, 0x248f
, 0x2490
, 0x2491
, 0x2492
, 0x2493
, 0x2494
, 0x2495
, 0x2496
, 0x2497
, 0x2498
, 0x2499
, 0x249a
, 0x249b
, 0x2474
, 0x2475
, 0x2476
, 0x2477
, 0x2478
, 0x2479
, 0x247a
, 0x247b
, 0x247c
, 0x247d
, 0x247e
, 0x247f
, 0x2480
, 0x2481
, 0x2482
, 0x2483
, 0x2484
, 0x2485
, 0x2486
, 0x2487
, 0x2460
, 0x2461
, 0x2462
, 0x2463
, 0x2464
, 0x2465
, 0x2466
, 0x2467
, 0x2468
, 0x2469
, 0x0000
, 0x0000
, 0x3220
, 0x3221
, 0x3222
, 0x3223
, 0x3224
, 0x3225
, 0x3226
, 0x3227
, 0x3228
, 0x3229
, 0x0000
, 0x0000
, 0x2160
, 0x2161
, 0x2162
, 0x2163
, 0x2164
, 0x2165
, 0x2166
, 0x2167
, 0x2168
, 0x2169
, 0x216a
, 0x216b
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0xff01
, 0xff02
, 0xff03
, 0xffe5
, 0xff05
, 0xff06
, 0xff07
, 0xff08
, 0xff09
, 0xff0a
, 0xff0b
, 0xff0c
, 0xff0d
, 0xff0e
, 0xff0f
, 0xff10
, 0xff11
, 0xff12
, 0xff13
, 0xff14
, 0xff15
, 0xff16
, 0xff17
, 0xff18
, 0xff19
, 0xff1a
, 0xff1b
, 0xff1c
, 0xff1d
, 0xff1e
, 0xff1f
, 0xff20
, 0xff21
, 0xff22
, 0xff23
, 0xff24
, 0xff25
, 0xff26
, 0xff27
, 0xff28
, 0xff29
, 0xff2a
, 0xff2b
, 0xff2c
, 0xff2d
, 0xff2e
, 0xff2f
, 0xff30
, 0xff31
, 0xff32
, 0xff33
, 0xff34
, 0xff35
, 0xff36
, 0xff37
, 0xff38
, 0xff39
, 0xff3a
, 0xff3b
, 0xff3c
, 0xff3d
, 0xff3e
, 0xff3f
, 0xff40
, 0xff41
, 0xff42
, 0xff43
, 0xff44
, 0xff45
, 0xff46
, 0xff47
, 0xff48
, 0xff49
, 0xff4a
, 0xff4b
, 0xff4c
, 0xff4d
, 0xff4e
, 0xff4f
, 0xff50
, 0xff51
, 0xff52
, 0xff53
, 0xff54
, 0xff55
, 0xff56
, 0xff57
, 0xff58
, 0xff59
, 0xff5a
, 0xff5b
, 0xff5c
, 0xff5d
, 0xffe3
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x3041
, 0x3042
, 0x3043
, 0x3044
, 0x3045
, 0x3046
, 0x3047
, 0x3048
, 0x3049
, 0x304a
, 0x304b
, 0x304c
, 0x304d
, 0x304e
, 0x304f
, 0x3050
, 0x3051
, 0x3052
, 0x3053
, 0x3054
, 0x3055
, 0x3056
, 0x3057
, 0x3058
, 0x3059
, 0x305a
, 0x305b
, 0x305c
, 0x305d
, 0x305e
, 0x305f
, 0x3060
, 0x3061
, 0x3062
, 0x3063
, 0x3064
, 0x3065
, 0x3066
, 0x3067
, 0x3068
, 0x3069
, 0x306a
, 0x306b
, 0x306c
, 0x306d
, 0x306e
, 0x306f
, 0x3070
, 0x3071
, 0x3072
, 0x3073
, 0x3074
, 0x3075
, 0x3076
, 0x3077
, 0x3078
, 0x3079
, 0x307a
, 0x307b
, 0x307c
, 0x307d
, 0x307e
, 0x307f
, 0x3080
, 0x3081
, 0x3082
, 0x3083
, 0x3084
, 0x3085
, 0x3086
, 0x3087
, 0x3088
, 0x3089
, 0x308a
, 0x308b
, 0x308c
, 0x308d
, 0x308e
, 0x308f
, 0x3090
, 0x3091
, 0x3092
, 0x3093
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x30a1
, 0x30a2
, 0x30a3
, 0x30a4
, 0x30a5
, 0x30a6
, 0x30a7
, 0x30a8
, 0x30a9
, 0x30aa
, 0x30ab
, 0x30ac
, 0x30ad
, 0x30ae
, 0x30af
, 0x30b0
, 0x30b1
, 0x30b2
, 0x30b3
, 0x30b4
, 0x30b5
, 0x30b6
, 0x30b7
, 0x30b8
, 0x30b9
, 0x30ba
, 0x30bb
, 0x30bc
, 0x30bd
, 0x30be
, 0x30bf
, 0x30c0
, 0x30c1
, 0x30c2
, 0x30c3
, 0x30c4
, 0x30c5
, 0x30c6
, 0x30c7
, 0x30c8
, 0x30c9
, 0x30ca
, 0x30cb
, 0x30cc
, 0x30cd
, 0x30ce
, 0x30cf
, 0x30d0
, 0x30d1
, 0x30d2
, 0x30d3
, 0x30d4
, 0x30d5
, 0x30d6
, 0x30d7
, 0x30d8
, 0x30d9
, 0x30da
, 0x30db
, 0x30dc
, 0x30dd
, 0x30de
, 0x30df
, 0x30e0
, 0x30e1
, 0x30e2
, 0x30e3
, 0x30e4
, 0x30e5
, 0x30e6
, 0x30e7
, 0x30e8
, 0x30e9
, 0x30ea
, 0x30eb
, 0x30ec
, 0x30ed
, 0x30ee
, 0x30ef
, 0x30f0
, 0x30f1
, 0x30f2
, 0x30f3
, 0x30f4
, 0x30f5
, 0x30f6
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0391
, 0x0392
, 0x0393
, 0x0394
, 0x0395
, 0x0396
, 0x0397
, 0x0398
, 0x0399
, 0x039a
, 0x039b
, 0x039c
, 0x039d
, 0x039e
, 0x039f
, 0x03a0
, 0x03a1
, 0x03a3
, 0x03a4
, 0x03a5
, 0x03a6
, 0x03a7
, 0x03a8
, 0x03a9
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x03b1
, 0x03b2
, 0x03b3
, 0x03b4
, 0x03b5
, 0x03b6
, 0x03b7
, 0x03b8
, 0x03b9
, 0x03ba
, 0x03bb
, 0x03bc
, 0x03bd
, 0x03be
, 0x03bf
, 0x03c0
, 0x03c1
, 0x03c3
, 0x03c4
, 0x03c5
, 0x03c6
, 0x03c7
, 0x03c8
, 0x03c9
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0410
, 0x0411
, 0x0412
, 0x0413
, 0x0414
, 0x0415
, 0x0401
, 0x0416
, 0x0417
, 0x0418
, 0x0419
, 0x041a
, 0x041b
, 0x041c
, 0x041d
, 0x041e
, 0x041f
, 0x0420
, 0x0421
, 0x0422
, 0x0423
, 0x0424
, 0x0425
, 0x0426
, 0x0427
, 0x0428
, 0x0429
, 0x042a
, 0x042b
, 0x042c
, 0x042d
, 0x042e
, 0x042f
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0430
, 0x0431
, 0x0432
, 0x0433
, 0x0434
, 0x0435
, 0x0451
, 0x0436
, 0x0437
, 0x0438
, 0x0439
, 0x043a
, 0x043b
, 0x043c
, 0x043d
, 0x043e
, 0x043f
, 0x0440
, 0x0441
, 0x0442
, 0x0443
, 0x0444
, 0x0445
, 0x0446
, 0x0447
, 0x0448
, 0x0449
, 0x044a
, 0x044b
, 0x044c
, 0x044d
, 0x044e
, 0x044f
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0101
, 0x00e1
, 0x01ce
, 0x00e0
, 0x0113
, 0x00e9
, 0x011b
, 0x00e8
, 0x012b
, 0x00ed
, 0x01d0
, 0x00ec
, 0x014d
, 0x00f3
, 0x01d2
, 0x00f2
, 0x016b
, 0x00fa
, 0x01d4
, 0x00f9
, 0x01d6
, 0x01d8
, 0x01da
, 0x01dc
, 0x00fc
, 0x00ea
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x3105
, 0x3106
, 0x3107
, 0x3108
, 0x3109
, 0x310a
, 0x310b
, 0x310c
, 0x310d
, 0x310e
, 0x310f
, 0x3110
, 0x3111
, 0x3112
, 0x3113
, 0x3114
, 0x3115
, 0x3116
, 0x3117
, 0x3118
, 0x3119
, 0x311a
, 0x311b
, 0x311c
, 0x311d
, 0x311e
, 0x311f
, 0x3120
, 0x3121
, 0x3122
, 0x3123
, 0x3124
, 0x3125
, 0x3126
, 0x3127
, 0x3128
, 0x3129
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x2500
, 0x2501
, 0x2502
, 0x2503
, 0x2504
, 0x2505
, 0x2506
, 0x2507
, 0x2508
, 0x2509
, 0x250a
, 0x250b
, 0x250c
, 0x250d
, 0x250e
, 0x250f
, 0x2510
, 0x2511
, 0x2512
, 0x2513
, 0x2514
, 0x2515
, 0x2516
, 0x2517
, 0x2518
, 0x2519
, 0x251a
, 0x251b
, 0x251c
, 0x251d
, 0x251e
, 0x251f
, 0x2520
, 0x2521
, 0x2522
, 0x2523
, 0x2524
, 0x2525
, 0x2526
, 0x2527
, 0x2528
, 0x2529
, 0x252a
, 0x252b
, 0x252c
, 0x252d
, 0x252e
, 0x252f
, 0x2530
, 0x2531
, 0x2532
, 0x2533
, 0x2534
, 0x2535
, 0x2536
, 0x2537
, 0x2538
, 0x2539
, 0x253a
, 0x253b
, 0x253c
, 0x253d
, 0x253e
, 0x253f
, 0x2540
, 0x2541
, 0x2542
, 0x2543
, 0x2544
, 0x2545
, 0x2546
, 0x2547
, 0x2548
, 0x2549
, 0x254a
, 0x254b
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x554a
, 0x963f
, 0x57c3
, 0x6328
, 0x54ce
, 0x5509
, 0x54c0
, 0x7691
, 0x764c
, 0x853c
, 0x77ee
, 0x827e
, 0x788d
, 0x7231
, 0x9698
, 0x978d
, 0x6c28
, 0x5b89
, 0x4ffa
, 0x6309
, 0x6697
, 0x5cb8
, 0x80fa
, 0x6848
, 0x80ae
, 0x6602
, 0x76ce
, 0x51f9
, 0x6556
, 0x71ac
, 0x7ff1
, 0x8884
, 0x50b2
, 0x5965
, 0x61ca
, 0x6fb3
, 0x82ad
, 0x634c
, 0x6252
, 0x53ed
, 0x5427
, 0x7b06
, 0x516b
, 0x75a4
, 0x5df4
, 0x62d4
, 0x8dcb
, 0x9776
, 0x628a
, 0x8019
, 0x575d
, 0x9738
, 0x7f62
, 0x7238
, 0x767d
, 0x67cf
, 0x767e
, 0x6446
, 0x4f70
, 0x8d25
, 0x62dc
, 0x7a17
, 0x6591
, 0x73ed
, 0x642c
, 0x6273
, 0x822c
, 0x9881
, 0x677f
, 0x7248
, 0x626e
, 0x62cc
, 0x4f34
, 0x74e3
, 0x534a
, 0x529e
, 0x7eca
, 0x90a6
, 0x5e2e
, 0x6886
, 0x699c
, 0x8180
, 0x7ed1
, 0x68d2
, 0x78c5
, 0x868c
, 0x9551
, 0x508d
, 0x8c24
, 0x82de
, 0x80de
, 0x5305
, 0x8912
, 0x5265
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x8584
, 0x96f9
, 0x4fdd
, 0x5821
, 0x9971
, 0x5b9d
, 0x62b1
, 0x62a5
, 0x66b4
, 0x8c79
, 0x9c8d
, 0x7206
, 0x676f
, 0x7891
, 0x60b2
, 0x5351
, 0x5317
, 0x8f88
, 0x80cc
, 0x8d1d
, 0x94a1
, 0x500d
, 0x72c8
, 0x5907
, 0x60eb
, 0x7119
, 0x88ab
, 0x5954
, 0x82ef
, 0x672c
, 0x7b28
, 0x5d29
, 0x7ef7
, 0x752d
, 0x6cf5
, 0x8e66
, 0x8ff8
, 0x903c
, 0x9f3b
, 0x6bd4
, 0x9119
, 0x7b14
, 0x5f7c
, 0x78a7
, 0x84d6
, 0x853d
, 0x6bd5
, 0x6bd9
, 0x6bd6
, 0x5e01
, 0x5e87
, 0x75f9
, 0x95ed
, 0x655d
, 0x5f0a
, 0x5fc5
, 0x8f9f
, 0x58c1
, 0x81c2
, 0x907f
, 0x965b
, 0x97ad
, 0x8fb9
, 0x7f16
, 0x8d2c
, 0x6241
, 0x4fbf
, 0x53d8
, 0x535e
, 0x8fa8
, 0x8fa9
, 0x8fab
, 0x904d
, 0x6807
, 0x5f6a
, 0x8198
, 0x8868
, 0x9cd6
, 0x618b
, 0x522b
, 0x762a
, 0x5f6c
, 0x658c
, 0x6fd2
, 0x6ee8
, 0x5bbe
, 0x6448
, 0x5175
, 0x51b0
, 0x67c4
, 0x4e19
, 0x79c9
, 0x997c
, 0x70b3
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x75c5
, 0x5e76
, 0x73bb
, 0x83e0
, 0x64ad
, 0x62e8
, 0x94b5
, 0x6ce2
, 0x535a
, 0x52c3
, 0x640f
, 0x94c2
, 0x7b94
, 0x4f2f
, 0x5e1b
, 0x8236
, 0x8116
, 0x818a
, 0x6e24
, 0x6cca
, 0x9a73
, 0x6355
, 0x535c
, 0x54fa
, 0x8865
, 0x57e0
, 0x4e0d
, 0x5e03
, 0x6b65
, 0x7c3f
, 0x90e8
, 0x6016
, 0x64e6
, 0x731c
, 0x88c1
, 0x6750
, 0x624d
, 0x8d22
, 0x776c
, 0x8e29
, 0x91c7
, 0x5f69
, 0x83dc
, 0x8521
, 0x9910
, 0x53c2
, 0x8695
, 0x6b8b
, 0x60ed
, 0x60e8
, 0x707f
, 0x82cd
, 0x8231
, 0x4ed3
, 0x6ca7
, 0x85cf
, 0x64cd
, 0x7cd9
, 0x69fd
, 0x66f9
, 0x8349
, 0x5395
, 0x7b56
, 0x4fa7
, 0x518c
, 0x6d4b
, 0x5c42
, 0x8e6d
, 0x63d2
, 0x53c9
, 0x832c
, 0x8336
, 0x67e5
, 0x78b4
, 0x643d
, 0x5bdf
, 0x5c94
, 0x5dee
, 0x8be7
, 0x62c6
, 0x67f4
, 0x8c7a
, 0x6400
, 0x63ba
, 0x8749
, 0x998b
, 0x8c17
, 0x7f20
, 0x94f2
, 0x4ea7
, 0x9610
, 0x98a4
, 0x660c
, 0x7316
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x573a
, 0x5c1d
, 0x5e38
, 0x957f
, 0x507f
, 0x80a0
, 0x5382
, 0x655e
, 0x7545
, 0x5531
, 0x5021
, 0x8d85
, 0x6284
, 0x949e
, 0x671d
, 0x5632
, 0x6f6e
, 0x5de2
, 0x5435
, 0x7092
, 0x8f66
, 0x626f
, 0x64a4
, 0x63a3
, 0x5f7b
, 0x6f88
, 0x90f4
, 0x81e3
, 0x8fb0
, 0x5c18
, 0x6668
, 0x5ff1
, 0x6c89
, 0x9648
, 0x8d81
, 0x886c
, 0x6491
, 0x79f0
, 0x57ce
, 0x6a59
, 0x6210
, 0x5448
, 0x4e58
, 0x7a0b
, 0x60e9
, 0x6f84
, 0x8bda
, 0x627f
, 0x901e
, 0x9a8b
, 0x79e4
, 0x5403
, 0x75f4
, 0x6301
, 0x5319
, 0x6c60
, 0x8fdf
, 0x5f1b
, 0x9a70
, 0x803b
, 0x9f7f
, 0x4f88
, 0x5c3a
, 0x8d64
, 0x7fc5
, 0x65a5
, 0x70bd
, 0x5145
, 0x51b2
, 0x866b
, 0x5d07
, 0x5ba0
, 0x62bd
, 0x916c
, 0x7574
, 0x8e0c
, 0x7a20
, 0x6101
, 0x7b79
, 0x4ec7
, 0x7ef8
, 0x7785
, 0x4e11
, 0x81ed
, 0x521d
, 0x51fa
, 0x6a71
, 0x53a8
, 0x8e87
, 0x9504
, 0x96cf
, 0x6ec1
, 0x9664
, 0x695a
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x7840
, 0x50a8
, 0x77d7
, 0x6410
, 0x89e6
, 0x5904
, 0x63e3
, 0x5ddd
, 0x7a7f
, 0x693d
, 0x4f20
, 0x8239
, 0x5598
, 0x4e32
, 0x75ae
, 0x7a97
, 0x5e62
, 0x5e8a
, 0x95ef
, 0x521b
, 0x5439
, 0x708a
, 0x6376
, 0x9524
, 0x5782
, 0x6625
, 0x693f
, 0x9187
, 0x5507
, 0x6df3
, 0x7eaf
, 0x8822
, 0x6233
, 0x7ef0
, 0x75b5
, 0x8328
, 0x78c1
, 0x96cc
, 0x8f9e
, 0x6148
, 0x74f7
, 0x8bcd
, 0x6b64
, 0x523a
, 0x8d50
, 0x6b21
, 0x806a
, 0x8471
, 0x56f1
, 0x5306
, 0x4ece
, 0x4e1b
, 0x51d1
, 0x7c97
, 0x918b
, 0x7c07
, 0x4fc3
, 0x8e7f
, 0x7be1
, 0x7a9c
, 0x6467
, 0x5d14
, 0x50ac
, 0x8106
, 0x7601
, 0x7cb9
, 0x6dec
, 0x7fe0
, 0x6751
, 0x5b58
, 0x5bf8
, 0x78cb
, 0x64ae
, 0x6413
, 0x63aa
, 0x632b
, 0x9519
, 0x642d
, 0x8fbe
, 0x7b54
, 0x7629
, 0x6253
, 0x5927
, 0x5446
, 0x6b79
, 0x50a3
, 0x6234
, 0x5e26
, 0x6b86
, 0x4ee3
, 0x8d37
, 0x888b
, 0x5f85
, 0x902e
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x6020
, 0x803d
, 0x62c5
, 0x4e39
, 0x5355
, 0x90f8
, 0x63b8
, 0x80c6
, 0x65e6
, 0x6c2e
, 0x4f46
, 0x60ee
, 0x6de1
, 0x8bde
, 0x5f39
, 0x86cb
, 0x5f53
, 0x6321
, 0x515a
, 0x8361
, 0x6863
, 0x5200
, 0x6363
, 0x8e48
, 0x5012
, 0x5c9b
, 0x7977
, 0x5bfc
, 0x5230
, 0x7a3b
, 0x60bc
, 0x9053
, 0x76d7
, 0x5fb7
, 0x5f97
, 0x7684
, 0x8e6c
, 0x706f
, 0x767b
, 0x7b49
, 0x77aa
, 0x51f3
, 0x9093
, 0x5824
, 0x4f4e
, 0x6ef4
, 0x8fea
, 0x654c
, 0x7b1b
, 0x72c4
, 0x6da4
, 0x7fdf
, 0x5ae1
, 0x62b5
, 0x5e95
, 0x5730
, 0x8482
, 0x7b2c
, 0x5e1d
, 0x5f1f
, 0x9012
, 0x7f14
, 0x98a0
, 0x6382
, 0x6ec7
, 0x7898
, 0x70b9
, 0x5178
, 0x975b
, 0x57ab
, 0x7535
, 0x4f43
, 0x7538
, 0x5e97
, 0x60e6
, 0x5960
, 0x6dc0
, 0x6bbf
, 0x7889
, 0x53fc
, 0x96d5
, 0x51cb
, 0x5201
, 0x6389
, 0x540a
, 0x9493
, 0x8c03
, 0x8dcc
, 0x7239
, 0x789f
, 0x8776
, 0x8fed
, 0x8c0d
, 0x53e0
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x4e01
, 0x76ef
, 0x53ee
, 0x9489
, 0x9876
, 0x9f0e
, 0x952d
, 0x5b9a
, 0x8ba2
, 0x4e22
, 0x4e1c
, 0x51ac
, 0x8463
, 0x61c2
, 0x52a8
, 0x680b
, 0x4f97
, 0x606b
, 0x51bb
, 0x6d1e
, 0x515c
, 0x6296
, 0x6597
, 0x9661
, 0x8c46
, 0x9017
, 0x75d8
, 0x90fd
, 0x7763
, 0x6bd2
, 0x728a
, 0x72ec
, 0x8bfb
, 0x5835
, 0x7779
, 0x8d4c
, 0x675c
, 0x9540
, 0x809a
, 0x5ea6
, 0x6e21
, 0x5992
, 0x7aef
, 0x77ed
, 0x953b
, 0x6bb5
, 0x65ad
, 0x7f0e
, 0x5806
, 0x5151
, 0x961f
, 0x5bf9
, 0x58a9
, 0x5428
, 0x8e72
, 0x6566
, 0x987f
, 0x56e4
, 0x949d
, 0x76fe
, 0x9041
, 0x6387
, 0x54c6
, 0x591a
, 0x593a
, 0x579b
, 0x8eb2
, 0x6735
, 0x8dfa
, 0x8235
, 0x5241
, 0x60f0
, 0x5815
, 0x86fe
, 0x5ce8
, 0x9e45
, 0x4fc4
, 0x989d
, 0x8bb9
, 0x5a25
, 0x6076
, 0x5384
, 0x627c
, 0x904f
, 0x9102
, 0x997f
, 0x6069
, 0x800c
, 0x513f
, 0x8033
, 0x5c14
, 0x9975
, 0x6d31
, 0x4e8c
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x8d30
, 0x53d1
, 0x7f5a
, 0x7b4f
, 0x4f10
, 0x4e4f
, 0x9600
, 0x6cd5
, 0x73d0
, 0x85e9
, 0x5e06
, 0x756a
, 0x7ffb
, 0x6a0a
, 0x77fe
, 0x9492
, 0x7e41
, 0x51e1
, 0x70e6
, 0x53cd
, 0x8fd4
, 0x8303
, 0x8d29
, 0x72af
, 0x996d
, 0x6cdb
, 0x574a
, 0x82b3
, 0x65b9
, 0x80aa
, 0x623f
, 0x9632
, 0x59a8
, 0x4eff
, 0x8bbf
, 0x7eba
, 0x653e
, 0x83f2
, 0x975e
, 0x5561
, 0x98de
, 0x80a5
, 0x532a
, 0x8bfd
, 0x5420
, 0x80ba
, 0x5e9f
, 0x6cb8
, 0x8d39
, 0x82ac
, 0x915a
, 0x5429
, 0x6c1b
, 0x5206
, 0x7eb7
, 0x575f
, 0x711a
, 0x6c7e
, 0x7c89
, 0x594b
, 0x4efd
, 0x5fff
, 0x6124
, 0x7caa
, 0x4e30
, 0x5c01
, 0x67ab
, 0x8702
, 0x5cf0
, 0x950b
, 0x98ce
, 0x75af
, 0x70fd
, 0x9022
, 0x51af
, 0x7f1d
, 0x8bbd
, 0x5949
, 0x51e4
, 0x4f5b
, 0x5426
, 0x592b
, 0x6577
, 0x80a4
, 0x5b75
, 0x6276
, 0x62c2
, 0x8f90
, 0x5e45
, 0x6c1f
, 0x7b26
, 0x4f0f
, 0x4fd8
, 0x670d
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x6d6e
, 0x6daa
, 0x798f
, 0x88b1
, 0x5f17
, 0x752b
, 0x629a
, 0x8f85
, 0x4fef
, 0x91dc
, 0x65a7
, 0x812f
, 0x8151
, 0x5e9c
, 0x8150
, 0x8d74
, 0x526f
, 0x8986
, 0x8d4b
, 0x590d
, 0x5085
, 0x4ed8
, 0x961c
, 0x7236
, 0x8179
, 0x8d1f
, 0x5bcc
, 0x8ba3
, 0x9644
, 0x5987
, 0x7f1a
, 0x5490
, 0x5676
, 0x560e
, 0x8be5
, 0x6539
, 0x6982
, 0x9499
, 0x76d6
, 0x6e89
, 0x5e72
, 0x7518
, 0x6746
, 0x67d1
, 0x7aff
, 0x809d
, 0x8d76
, 0x611f
, 0x79c6
, 0x6562
, 0x8d63
, 0x5188
, 0x521a
, 0x94a2
, 0x7f38
, 0x809b
, 0x7eb2
, 0x5c97
, 0x6e2f
, 0x6760
, 0x7bd9
, 0x768b
, 0x9ad8
, 0x818f
, 0x7f94
, 0x7cd5
, 0x641e
, 0x9550
, 0x7a3f
, 0x544a
, 0x54e5
, 0x6b4c
, 0x6401
, 0x6208
, 0x9e3d
, 0x80f3
, 0x7599
, 0x5272
, 0x9769
, 0x845b
, 0x683c
, 0x86e4
, 0x9601
, 0x9694
, 0x94ec
, 0x4e2a
, 0x5404
, 0x7ed9
, 0x6839
, 0x8ddf
, 0x8015
, 0x66f4
, 0x5e9a
, 0x7fb9
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x57c2
, 0x803f
, 0x6897
, 0x5de5
, 0x653b
, 0x529f
, 0x606d
, 0x9f9a
, 0x4f9b
, 0x8eac
, 0x516c
, 0x5bab
, 0x5f13
, 0x5de9
, 0x6c5e
, 0x62f1
, 0x8d21
, 0x5171
, 0x94a9
, 0x52fe
, 0x6c9f
, 0x82df
, 0x72d7
, 0x57a2
, 0x6784
, 0x8d2d
, 0x591f
, 0x8f9c
, 0x83c7
, 0x5495
, 0x7b8d
, 0x4f30
, 0x6cbd
, 0x5b64
, 0x59d1
, 0x9f13
, 0x53e4
, 0x86ca
, 0x9aa8
, 0x8c37
, 0x80a1
, 0x6545
, 0x987e
, 0x56fa
, 0x96c7
, 0x522e
, 0x74dc
, 0x5250
, 0x5be1
, 0x6302
, 0x8902
, 0x4e56
, 0x62d0
, 0x602a
, 0x68fa
, 0x5173
, 0x5b98
, 0x51a0
, 0x89c2
, 0x7ba1
, 0x9986
, 0x7f50
, 0x60ef
, 0x704c
, 0x8d2f
, 0x5149
, 0x5e7f
, 0x901b
, 0x7470
, 0x89c4
, 0x572d
, 0x7845
, 0x5f52
, 0x9f9f
, 0x95fa
, 0x8f68
, 0x9b3c
, 0x8be1
, 0x7678
, 0x6842
, 0x67dc
, 0x8dea
, 0x8d35
, 0x523d
, 0x8f8a
, 0x6eda
, 0x68cd
, 0x9505
, 0x90ed
, 0x56fd
, 0x679c
, 0x88f9
, 0x8fc7
, 0x54c8
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x9ab8
, 0x5b69
, 0x6d77
, 0x6c26
, 0x4ea5
, 0x5bb3
, 0x9a87
, 0x9163
, 0x61a8
, 0x90af
, 0x97e9
, 0x542b
, 0x6db5
, 0x5bd2
, 0x51fd
, 0x558a
, 0x7f55
, 0x7ff0
, 0x64bc
, 0x634d
, 0x65f1
, 0x61be
, 0x608d
, 0x710a
, 0x6c57
, 0x6c49
, 0x592f
, 0x676d
, 0x822a
, 0x58d5
, 0x568e
, 0x8c6a
, 0x6beb
, 0x90dd
, 0x597d
, 0x8017
, 0x53f7
, 0x6d69
, 0x5475
, 0x559d
, 0x8377
, 0x83cf
, 0x6838
, 0x79be
, 0x548c
, 0x4f55
, 0x5408
, 0x76d2
, 0x8c89
, 0x9602
, 0x6cb3
, 0x6db8
, 0x8d6b
, 0x8910
, 0x9e64
, 0x8d3a
, 0x563f
, 0x9ed1
, 0x75d5
, 0x5f88
, 0x72e0
, 0x6068
, 0x54fc
, 0x4ea8
, 0x6a2a
, 0x8861
, 0x6052
, 0x8f70
, 0x54c4
, 0x70d8
, 0x8679
, 0x9e3f
, 0x6d2a
, 0x5b8f
, 0x5f18
, 0x7ea2
, 0x5589
, 0x4faf
, 0x7334
, 0x543c
, 0x539a
, 0x5019
, 0x540e
, 0x547c
, 0x4e4e
, 0x5ffd
, 0x745a
, 0x58f6
, 0x846b
, 0x80e1
, 0x8774
, 0x72d0
, 0x7cca
, 0x6e56
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x5f27
, 0x864e
, 0x552c
, 0x62a4
, 0x4e92
, 0x6caa
, 0x6237
, 0x82b1
, 0x54d7
, 0x534e
, 0x733e
, 0x6ed1
, 0x753b
, 0x5212
, 0x5316
, 0x8bdd
, 0x69d0
, 0x5f8a
, 0x6000
, 0x6dee
, 0x574f
, 0x6b22
, 0x73af
, 0x6853
, 0x8fd8
, 0x7f13
, 0x6362
, 0x60a3
, 0x5524
, 0x75ea
, 0x8c62
, 0x7115
, 0x6da3
, 0x5ba6
, 0x5e7b
, 0x8352
, 0x614c
, 0x9ec4
, 0x78fa
, 0x8757
, 0x7c27
, 0x7687
, 0x51f0
, 0x60f6
, 0x714c
, 0x6643
, 0x5e4c
, 0x604d
, 0x8c0e
, 0x7070
, 0x6325
, 0x8f89
, 0x5fbd
, 0x6062
, 0x86d4
, 0x56de
, 0x6bc1
, 0x6094
, 0x6167
, 0x5349
, 0x60e0
, 0x6666
, 0x8d3f
, 0x79fd
, 0x4f1a
, 0x70e9
, 0x6c47
, 0x8bb3
, 0x8bf2
, 0x7ed8
, 0x8364
, 0x660f
, 0x5a5a
, 0x9b42
, 0x6d51
, 0x6df7
, 0x8c41
, 0x6d3b
, 0x4f19
, 0x706b
, 0x83b7
, 0x6216
, 0x60d1
, 0x970d
, 0x8d27
, 0x7978
, 0x51fb
, 0x573e
, 0x57fa
, 0x673a
, 0x7578
, 0x7a3d
, 0x79ef
, 0x7b95
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x808c
, 0x9965
, 0x8ff9
, 0x6fc0
, 0x8ba5
, 0x9e21
, 0x59ec
, 0x7ee9
, 0x7f09
, 0x5409
, 0x6781
, 0x68d8
, 0x8f91
, 0x7c4d
, 0x96c6
, 0x53ca
, 0x6025
, 0x75be
, 0x6c72
, 0x5373
, 0x5ac9
, 0x7ea7
, 0x6324
, 0x51e0
, 0x810a
, 0x5df1
, 0x84df
, 0x6280
, 0x5180
, 0x5b63
, 0x4f0e
, 0x796d
, 0x5242
, 0x60b8
, 0x6d4e
, 0x5bc4
, 0x5bc2
, 0x8ba1
, 0x8bb0
, 0x65e2
, 0x5fcc
, 0x9645
, 0x5993
, 0x7ee7
, 0x7eaa
, 0x5609
, 0x67b7
, 0x5939
, 0x4f73
, 0x5bb6
, 0x52a0
, 0x835a
, 0x988a
, 0x8d3e
, 0x7532
, 0x94be
, 0x5047
, 0x7a3c
, 0x4ef7
, 0x67b6
, 0x9a7e
, 0x5ac1
, 0x6b7c
, 0x76d1
, 0x575a
, 0x5c16
, 0x7b3a
, 0x95f4
, 0x714e
, 0x517c
, 0x80a9
, 0x8270
, 0x5978
, 0x7f04
, 0x8327
, 0x68c0
, 0x67ec
, 0x78b1
, 0x7877
, 0x62e3
, 0x6361
, 0x7b80
, 0x4fed
, 0x526a
, 0x51cf
, 0x8350
, 0x69db
, 0x9274
, 0x8df5
, 0x8d31
, 0x89c1
, 0x952e
, 0x7bad
, 0x4ef6
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x5065
, 0x8230
, 0x5251
, 0x996f
, 0x6e10
, 0x6e85
, 0x6da7
, 0x5efa
, 0x50f5
, 0x59dc
, 0x5c06
, 0x6d46
, 0x6c5f
, 0x7586
, 0x848b
, 0x6868
, 0x5956
, 0x8bb2
, 0x5320
, 0x9171
, 0x964d
, 0x8549
, 0x6912
, 0x7901
, 0x7126
, 0x80f6
, 0x4ea4
, 0x90ca
, 0x6d47
, 0x9a84
, 0x5a07
, 0x56bc
, 0x6405
, 0x94f0
, 0x77eb
, 0x4fa5
, 0x811a
, 0x72e1
, 0x89d2
, 0x997a
, 0x7f34
, 0x7ede
, 0x527f
, 0x6559
, 0x9175
, 0x8f7f
, 0x8f83
, 0x53eb
, 0x7a96
, 0x63ed
, 0x63a5
, 0x7686
, 0x79f8
, 0x8857
, 0x9636
, 0x622a
, 0x52ab
, 0x8282
, 0x6854
, 0x6770
, 0x6377
, 0x776b
, 0x7aed
, 0x6d01
, 0x7ed3
, 0x89e3
, 0x59d0
, 0x6212
, 0x85c9
, 0x82a5
, 0x754c
, 0x501f
, 0x4ecb
, 0x75a5
, 0x8beb
, 0x5c4a
, 0x5dfe
, 0x7b4b
, 0x65a4
, 0x91d1
, 0x4eca
, 0x6d25
, 0x895f
, 0x7d27
, 0x9526
, 0x4ec5
, 0x8c28
, 0x8fdb
, 0x9773
, 0x664b
, 0x7981
, 0x8fd1
, 0x70ec
, 0x6d78
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x5c3d
, 0x52b2
, 0x8346
, 0x5162
, 0x830e
, 0x775b
, 0x6676
, 0x9cb8
, 0x4eac
, 0x60ca
, 0x7cbe
, 0x7cb3
, 0x7ecf
, 0x4e95
, 0x8b66
, 0x666f
, 0x9888
, 0x9759
, 0x5883
, 0x656c
, 0x955c
, 0x5f84
, 0x75c9
, 0x9756
, 0x7adf
, 0x7ade
, 0x51c0
, 0x70af
, 0x7a98
, 0x63ea
, 0x7a76
, 0x7ea0
, 0x7396
, 0x97ed
, 0x4e45
, 0x7078
, 0x4e5d
, 0x9152
, 0x53a9
, 0x6551
, 0x65e7
, 0x81fc
, 0x8205
, 0x548e
, 0x5c31
, 0x759a
, 0x97a0
, 0x62d8
, 0x72d9
, 0x75bd
, 0x5c45
, 0x9a79
, 0x83ca
, 0x5c40
, 0x5480
, 0x77e9
, 0x4e3e
, 0x6cae
, 0x805a
, 0x62d2
, 0x636e
, 0x5de8
, 0x5177
, 0x8ddd
, 0x8e1e
, 0x952f
, 0x4ff1
, 0x53e5
, 0x60e7
, 0x70ac
, 0x5267
, 0x6350
, 0x9e43
, 0x5a1f
, 0x5026
, 0x7737
, 0x5377
, 0x7ee2
, 0x6485
, 0x652b
, 0x6289
, 0x6398
, 0x5014
, 0x7235
, 0x89c9
, 0x51b3
, 0x8bc0
, 0x7edd
, 0x5747
, 0x83cc
, 0x94a7
, 0x519b
, 0x541b
, 0x5cfb
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x4fca
, 0x7ae3
, 0x6d5a
, 0x90e1
, 0x9a8f
, 0x5580
, 0x5496
, 0x5361
, 0x54af
, 0x5f00
, 0x63e9
, 0x6977
, 0x51ef
, 0x6168
, 0x520a
, 0x582a
, 0x52d8
, 0x574e
, 0x780d
, 0x770b
, 0x5eb7
, 0x6177
, 0x7ce0
, 0x625b
, 0x6297
, 0x4ea2
, 0x7095
, 0x8003
, 0x62f7
, 0x70e4
, 0x9760
, 0x5777
, 0x82db
, 0x67ef
, 0x68f5
, 0x78d5
, 0x9897
, 0x79d1
, 0x58f3
, 0x54b3
, 0x53ef
, 0x6e34
, 0x514b
, 0x523b
, 0x5ba2
, 0x8bfe
, 0x80af
, 0x5543
, 0x57a6
, 0x6073
, 0x5751
, 0x542d
, 0x7a7a
, 0x6050
, 0x5b54
, 0x63a7
, 0x62a0
, 0x53e3
, 0x6263
, 0x5bc7
, 0x67af
, 0x54ed
, 0x7a9f
, 0x82e6
, 0x9177
, 0x5e93
, 0x88e4
, 0x5938
, 0x57ae
, 0x630e
, 0x8de8
, 0x80ef
, 0x5757
, 0x7b77
, 0x4fa9
, 0x5feb
, 0x5bbd
, 0x6b3e
, 0x5321
, 0x7b50
, 0x72c2
, 0x6846
, 0x77ff
, 0x7736
, 0x65f7
, 0x51b5
, 0x4e8f
, 0x76d4
, 0x5cbf
, 0x7aa5
, 0x8475
, 0x594e
, 0x9b41
, 0x5080
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x9988
, 0x6127
, 0x6e83
, 0x5764
, 0x6606
, 0x6346
, 0x56f0
, 0x62ec
, 0x6269
, 0x5ed3
, 0x9614
, 0x5783
, 0x62c9
, 0x5587
, 0x8721
, 0x814a
, 0x8fa3
, 0x5566
, 0x83b1
, 0x6765
, 0x8d56
, 0x84dd
, 0x5a6a
, 0x680f
, 0x62e6
, 0x7bee
, 0x9611
, 0x5170
, 0x6f9c
, 0x8c30
, 0x63fd
, 0x89c8
, 0x61d2
, 0x7f06
, 0x70c2
, 0x6ee5
, 0x7405
, 0x6994
, 0x72fc
, 0x5eca
, 0x90ce
, 0x6717
, 0x6d6a
, 0x635e
, 0x52b3
, 0x7262
, 0x8001
, 0x4f6c
, 0x59e5
, 0x916a
, 0x70d9
, 0x6d9d
, 0x52d2
, 0x4e50
, 0x96f7
, 0x956d
, 0x857e
, 0x78ca
, 0x7d2f
, 0x5121
, 0x5792
, 0x64c2
, 0x808b
, 0x7c7b
, 0x6cea
, 0x68f1
, 0x695e
, 0x51b7
, 0x5398
, 0x68a8
, 0x7281
, 0x9ece
, 0x7bf1
, 0x72f8
, 0x79bb
, 0x6f13
, 0x7406
, 0x674e
, 0x91cc
, 0x9ca4
, 0x793c
, 0x8389
, 0x8354
, 0x540f
, 0x6817
, 0x4e3d
, 0x5389
, 0x52b1
, 0x783e
, 0x5386
, 0x5229
, 0x5088
, 0x4f8b
, 0x4fd0
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x75e2
, 0x7acb
, 0x7c92
, 0x6ca5
, 0x96b6
, 0x529b
, 0x7483
, 0x54e9
, 0x4fe9
, 0x8054
, 0x83b2
, 0x8fde
, 0x9570
, 0x5ec9
, 0x601c
, 0x6d9f
, 0x5e18
, 0x655b
, 0x8138
, 0x94fe
, 0x604b
, 0x70bc
, 0x7ec3
, 0x7cae
, 0x51c9
, 0x6881
, 0x7cb1
, 0x826f
, 0x4e24
, 0x8f86
, 0x91cf
, 0x667e
, 0x4eae
, 0x8c05
, 0x64a9
, 0x804a
, 0x50da
, 0x7597
, 0x71ce
, 0x5be5
, 0x8fbd
, 0x6f66
, 0x4e86
, 0x6482
, 0x9563
, 0x5ed6
, 0x6599
, 0x5217
, 0x88c2
, 0x70c8
, 0x52a3
, 0x730e
, 0x7433
, 0x6797
, 0x78f7
, 0x9716
, 0x4e34
, 0x90bb
, 0x9cde
, 0x6dcb
, 0x51db
, 0x8d41
, 0x541d
, 0x62ce
, 0x73b2
, 0x83f1
, 0x96f6
, 0x9f84
, 0x94c3
, 0x4f36
, 0x7f9a
, 0x51cc
, 0x7075
, 0x9675
, 0x5cad
, 0x9886
, 0x53e6
, 0x4ee4
, 0x6e9c
, 0x7409
, 0x69b4
, 0x786b
, 0x998f
, 0x7559
, 0x5218
, 0x7624
, 0x6d41
, 0x67f3
, 0x516d
, 0x9f99
, 0x804b
, 0x5499
, 0x7b3c
, 0x7abf
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x9686
, 0x5784
, 0x62e2
, 0x9647
, 0x697c
, 0x5a04
, 0x6402
, 0x7bd3
, 0x6f0f
, 0x964b
, 0x82a6
, 0x5362
, 0x9885
, 0x5e90
, 0x7089
, 0x63b3
, 0x5364
, 0x864f
, 0x9c81
, 0x9e93
, 0x788c
, 0x9732
, 0x8def
, 0x8d42
, 0x9e7f
, 0x6f5e
, 0x7984
, 0x5f55
, 0x9646
, 0x622e
, 0x9a74
, 0x5415
, 0x94dd
, 0x4fa3
, 0x65c5
, 0x5c65
, 0x5c61
, 0x7f15
, 0x8651
, 0x6c2f
, 0x5f8b
, 0x7387
, 0x6ee4
, 0x7eff
, 0x5ce6
, 0x631b
, 0x5b6a
, 0x6ee6
, 0x5375
, 0x4e71
, 0x63a0
, 0x7565
, 0x62a1
, 0x8f6e
, 0x4f26
, 0x4ed1
, 0x6ca6
, 0x7eb6
, 0x8bba
, 0x841d
, 0x87ba
, 0x7f57
, 0x903b
, 0x9523
, 0x7ba9
, 0x9aa1
, 0x88f8
, 0x843d
, 0x6d1b
, 0x9a86
, 0x7edc
, 0x5988
, 0x9ebb
, 0x739b
, 0x7801
, 0x8682
, 0x9a6c
, 0x9a82
, 0x561b
, 0x5417
, 0x57cb
, 0x4e70
, 0x9ea6
, 0x5356
, 0x8fc8
, 0x8109
, 0x7792
, 0x9992
, 0x86ee
, 0x6ee1
, 0x8513
, 0x66fc
, 0x6162
, 0x6f2b
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x8c29
, 0x8292
, 0x832b
, 0x76f2
, 0x6c13
, 0x5fd9
, 0x83bd
, 0x732b
, 0x8305
, 0x951a
, 0x6bdb
, 0x77db
, 0x94c6
, 0x536f
, 0x8302
, 0x5192
, 0x5e3d
, 0x8c8c
, 0x8d38
, 0x4e48
, 0x73ab
, 0x679a
, 0x6885
, 0x9176
, 0x9709
, 0x7164
, 0x6ca1
, 0x7709
, 0x5a92
, 0x9541
, 0x6bcf
, 0x7f8e
, 0x6627
, 0x5bd0
, 0x59b9
, 0x5a9a
, 0x95e8
, 0x95f7
, 0x4eec
, 0x840c
, 0x8499
, 0x6aac
, 0x76df
, 0x9530
, 0x731b
, 0x68a6
, 0x5b5f
, 0x772f
, 0x919a
, 0x9761
, 0x7cdc
, 0x8ff7
, 0x8c1c
, 0x5f25
, 0x7c73
, 0x79d8
, 0x89c5
, 0x6ccc
, 0x871c
, 0x5bc6
, 0x5e42
, 0x68c9
, 0x7720
, 0x7ef5
, 0x5195
, 0x514d
, 0x52c9
, 0x5a29
, 0x7f05
, 0x9762
, 0x82d7
, 0x63cf
, 0x7784
, 0x85d0
, 0x79d2
, 0x6e3a
, 0x5e99
, 0x5999
, 0x8511
, 0x706d
, 0x6c11
, 0x62bf
, 0x76bf
, 0x654f
, 0x60af
, 0x95fd
, 0x660e
, 0x879f
, 0x9e23
, 0x94ed
, 0x540d
, 0x547d
, 0x8c2c
, 0x6478
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x6479
, 0x8611
, 0x6a21
, 0x819c
, 0x78e8
, 0x6469
, 0x9b54
, 0x62b9
, 0x672b
, 0x83ab
, 0x58a8
, 0x9ed8
, 0x6cab
, 0x6f20
, 0x5bde
, 0x964c
, 0x8c0b
, 0x725f
, 0x67d0
, 0x62c7
, 0x7261
, 0x4ea9
, 0x59c6
, 0x6bcd
, 0x5893
, 0x66ae
, 0x5e55
, 0x52df
, 0x6155
, 0x6728
, 0x76ee
, 0x7766
, 0x7267
, 0x7a46
, 0x62ff
, 0x54ea
, 0x5450
, 0x94a0
, 0x90a3
, 0x5a1c
, 0x7eb3
, 0x6c16
, 0x4e43
, 0x5976
, 0x8010
, 0x5948
, 0x5357
, 0x7537
, 0x96be
, 0x56ca
, 0x6320
, 0x8111
, 0x607c
, 0x95f9
, 0x6dd6
, 0x5462
, 0x9981
, 0x5185
, 0x5ae9
, 0x80fd
, 0x59ae
, 0x9713
, 0x502a
, 0x6ce5
, 0x5c3c
, 0x62df
, 0x4f60
, 0x533f
, 0x817b
, 0x9006
, 0x6eba
, 0x852b
, 0x62c8
, 0x5e74
, 0x78be
, 0x64b5
, 0x637b
, 0x5ff5
, 0x5a18
, 0x917f
, 0x9e1f
, 0x5c3f
, 0x634f
, 0x8042
, 0x5b7d
, 0x556e
, 0x954a
, 0x954d
, 0x6d85
, 0x60a8
, 0x67e0
, 0x72de
, 0x51dd
, 0x5b81
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x62e7
, 0x6cde
, 0x725b
, 0x626d
, 0x94ae
, 0x7ebd
, 0x8113
, 0x6d53
, 0x519c
, 0x5f04
, 0x5974
, 0x52aa
, 0x6012
, 0x5973
, 0x6696
, 0x8650
, 0x759f
, 0x632a
, 0x61e6
, 0x7cef
, 0x8bfa
, 0x54e6
, 0x6b27
, 0x9e25
, 0x6bb4
, 0x85d5
, 0x5455
, 0x5076
, 0x6ca4
, 0x556a
, 0x8db4
, 0x722c
, 0x5e15
, 0x6015
, 0x7436
, 0x62cd
, 0x6392
, 0x724c
, 0x5f98
, 0x6e43
, 0x6d3e
, 0x6500
, 0x6f58
, 0x76d8
, 0x78d0
, 0x76fc
, 0x7554
, 0x5224
, 0x53db
, 0x4e53
, 0x5e9e
, 0x65c1
, 0x802a
, 0x80d6
, 0x629b
, 0x5486
, 0x5228
, 0x70ae
, 0x888d
, 0x8dd1
, 0x6ce1
, 0x5478
, 0x80da
, 0x57f9
, 0x88f4
, 0x8d54
, 0x966a
, 0x914d
, 0x4f69
, 0x6c9b
, 0x55b7
, 0x76c6
, 0x7830
, 0x62a8
, 0x70f9
, 0x6f8e
, 0x5f6d
, 0x84ec
, 0x68da
, 0x787c
, 0x7bf7
, 0x81a8
, 0x670b
, 0x9e4f
, 0x6367
, 0x78b0
, 0x576f
, 0x7812
, 0x9739
, 0x6279
, 0x62ab
, 0x5288
, 0x7435
, 0x6bd7
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x5564
, 0x813e
, 0x75b2
, 0x76ae
, 0x5339
, 0x75de
, 0x50fb
, 0x5c41
, 0x8b6c
, 0x7bc7
, 0x504f
, 0x7247
, 0x9a97
, 0x98d8
, 0x6f02
, 0x74e2
, 0x7968
, 0x6487
, 0x77a5
, 0x62fc
, 0x9891
, 0x8d2b
, 0x54c1
, 0x8058
, 0x4e52
, 0x576a
, 0x82f9
, 0x840d
, 0x5e73
, 0x51ed
, 0x74f6
, 0x8bc4
, 0x5c4f
, 0x5761
, 0x6cfc
, 0x9887
, 0x5a46
, 0x7834
, 0x9b44
, 0x8feb
, 0x7c95
, 0x5256
, 0x6251
, 0x94fa
, 0x4ec6
, 0x8386
, 0x8461
, 0x83e9
, 0x84b2
, 0x57d4
, 0x6734
, 0x5703
, 0x666e
, 0x6d66
, 0x8c31
, 0x66dd
, 0x7011
, 0x671f
, 0x6b3a
, 0x6816
, 0x621a
, 0x59bb
, 0x4e03
, 0x51c4
, 0x6f06
, 0x67d2
, 0x6c8f
, 0x5176
, 0x68cb
, 0x5947
, 0x6b67
, 0x7566
, 0x5d0e
, 0x8110
, 0x9f50
, 0x65d7
, 0x7948
, 0x7941
, 0x9a91
, 0x8d77
, 0x5c82
, 0x4e5e
, 0x4f01
, 0x542f
, 0x5951
, 0x780c
, 0x5668
, 0x6c14
, 0x8fc4
, 0x5f03
, 0x6c7d
, 0x6ce3
, 0x8bab
, 0x6390
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x6070
, 0x6d3d
, 0x7275
, 0x6266
, 0x948e
, 0x94c5
, 0x5343
, 0x8fc1
, 0x7b7e
, 0x4edf
, 0x8c26
, 0x4e7e
, 0x9ed4
, 0x94b1
, 0x94b3
, 0x524d
, 0x6f5c
, 0x9063
, 0x6d45
, 0x8c34
, 0x5811
, 0x5d4c
, 0x6b20
, 0x6b49
, 0x67aa
, 0x545b
, 0x8154
, 0x7f8c
, 0x5899
, 0x8537
, 0x5f3a
, 0x62a2
, 0x6a47
, 0x9539
, 0x6572
, 0x6084
, 0x6865
, 0x77a7
, 0x4e54
, 0x4fa8
, 0x5de7
, 0x9798
, 0x64ac
, 0x7fd8
, 0x5ced
, 0x4fcf
, 0x7a8d
, 0x5207
, 0x8304
, 0x4e14
, 0x602f
, 0x7a83
, 0x94a6
, 0x4fb5
, 0x4eb2
, 0x79e6
, 0x7434
, 0x52e4
, 0x82b9
, 0x64d2
, 0x79bd
, 0x5bdd
, 0x6c81
, 0x9752
, 0x8f7b
, 0x6c22
, 0x503e
, 0x537f
, 0x6e05
, 0x64ce
, 0x6674
, 0x6c30
, 0x60c5
, 0x9877
, 0x8bf7
, 0x5e86
, 0x743c
, 0x7a77
, 0x79cb
, 0x4e18
, 0x90b1
, 0x7403
, 0x6c42
, 0x56da
, 0x914b
, 0x6cc5
, 0x8d8b
, 0x533a
, 0x86c6
, 0x66f2
, 0x8eaf
, 0x5c48
, 0x9a71
, 0x6e20
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x53d6
, 0x5a36
, 0x9f8b
, 0x8da3
, 0x53bb
, 0x5708
, 0x98a7
, 0x6743
, 0x919b
, 0x6cc9
, 0x5168
, 0x75ca
, 0x62f3
, 0x72ac
, 0x5238
, 0x529d
, 0x7f3a
, 0x7094
, 0x7638
, 0x5374
, 0x9e4a
, 0x69b7
, 0x786e
, 0x96c0
, 0x88d9
, 0x7fa4
, 0x7136
, 0x71c3
, 0x5189
, 0x67d3
, 0x74e4
, 0x58e4
, 0x6518
, 0x56b7
, 0x8ba9
, 0x9976
, 0x6270
, 0x7ed5
, 0x60f9
, 0x70ed
, 0x58ec
, 0x4ec1
, 0x4eba
, 0x5fcd
, 0x97e7
, 0x4efb
, 0x8ba4
, 0x5203
, 0x598a
, 0x7eab
, 0x6254
, 0x4ecd
, 0x65e5
, 0x620e
, 0x8338
, 0x84c9
, 0x8363
, 0x878d
, 0x7194
, 0x6eb6
, 0x5bb9
, 0x7ed2
, 0x5197
, 0x63c9
, 0x67d4
, 0x8089
, 0x8339
, 0x8815
, 0x5112
, 0x5b7a
, 0x5982
, 0x8fb1
, 0x4e73
, 0x6c5d
, 0x5165
, 0x8925
, 0x8f6f
, 0x962e
, 0x854a
, 0x745e
, 0x9510
, 0x95f0
, 0x6da6
, 0x82e5
, 0x5f31
, 0x6492
, 0x6d12
, 0x8428
, 0x816e
, 0x9cc3
, 0x585e
, 0x8d5b
, 0x4e09
, 0x53c1
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x4f1e
, 0x6563
, 0x6851
, 0x55d3
, 0x4e27
, 0x6414
, 0x9a9a
, 0x626b
, 0x5ac2
, 0x745f
, 0x8272
, 0x6da9
, 0x68ee
, 0x50e7
, 0x838e
, 0x7802
, 0x6740
, 0x5239
, 0x6c99
, 0x7eb1
, 0x50bb
, 0x5565
, 0x715e
, 0x7b5b
, 0x6652
, 0x73ca
, 0x82eb
, 0x6749
, 0x5c71
, 0x5220
, 0x717d
, 0x886b
, 0x95ea
, 0x9655
, 0x64c5
, 0x8d61
, 0x81b3
, 0x5584
, 0x6c55
, 0x6247
, 0x7f2e
, 0x5892
, 0x4f24
, 0x5546
, 0x8d4f
, 0x664c
, 0x4e0a
, 0x5c1a
, 0x88f3
, 0x68a2
, 0x634e
, 0x7a0d
, 0x70e7
, 0x828d
, 0x52fa
, 0x97f6
, 0x5c11
, 0x54e8
, 0x90b5
, 0x7ecd
, 0x5962
, 0x8d4a
, 0x86c7
, 0x820c
, 0x820d
, 0x8d66
, 0x6444
, 0x5c04
, 0x6151
, 0x6d89
, 0x793e
, 0x8bbe
, 0x7837
, 0x7533
, 0x547b
, 0x4f38
, 0x8eab
, 0x6df1
, 0x5a20
, 0x7ec5
, 0x795e
, 0x6c88
, 0x5ba1
, 0x5a76
, 0x751a
, 0x80be
, 0x614e
, 0x6e17
, 0x58f0
, 0x751f
, 0x7525
, 0x7272
, 0x5347
, 0x7ef3
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x7701
, 0x76db
, 0x5269
, 0x80dc
, 0x5723
, 0x5e08
, 0x5931
, 0x72ee
, 0x65bd
, 0x6e7f
, 0x8bd7
, 0x5c38
, 0x8671
, 0x5341
, 0x77f3
, 0x62fe
, 0x65f6
, 0x4ec0
, 0x98df
, 0x8680
, 0x5b9e
, 0x8bc6
, 0x53f2
, 0x77e2
, 0x4f7f
, 0x5c4e
, 0x9a76
, 0x59cb
, 0x5f0f
, 0x793a
, 0x58eb
, 0x4e16
, 0x67ff
, 0x4e8b
, 0x62ed
, 0x8a93
, 0x901d
, 0x52bf
, 0x662f
, 0x55dc
, 0x566c
, 0x9002
, 0x4ed5
, 0x4f8d
, 0x91ca
, 0x9970
, 0x6c0f
, 0x5e02
, 0x6043
, 0x5ba4
, 0x89c6
, 0x8bd5
, 0x6536
, 0x624b
, 0x9996
, 0x5b88
, 0x5bff
, 0x6388
, 0x552e
, 0x53d7
, 0x7626
, 0x517d
, 0x852c
, 0x67a2
, 0x68b3
, 0x6b8a
, 0x6292
, 0x8f93
, 0x53d4
, 0x8212
, 0x6dd1
, 0x758f
, 0x4e66
, 0x8d4e
, 0x5b70
, 0x719f
, 0x85af
, 0x6691
, 0x66d9
, 0x7f72
, 0x8700
, 0x9ecd
, 0x9f20
, 0x5c5e
, 0x672f
, 0x8ff0
, 0x6811
, 0x675f
, 0x620d
, 0x7ad6
, 0x5885
, 0x5eb6
, 0x6570
, 0x6f31
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x6055
, 0x5237
, 0x800d
, 0x6454
, 0x8870
, 0x7529
, 0x5e05
, 0x6813
, 0x62f4
, 0x971c
, 0x53cc
, 0x723d
, 0x8c01
, 0x6c34
, 0x7761
, 0x7a0e
, 0x542e
, 0x77ac
, 0x987a
, 0x821c
, 0x8bf4
, 0x7855
, 0x6714
, 0x70c1
, 0x65af
, 0x6495
, 0x5636
, 0x601d
, 0x79c1
, 0x53f8
, 0x4e1d
, 0x6b7b
, 0x8086
, 0x5bfa
, 0x55e3
, 0x56db
, 0x4f3a
, 0x4f3c
, 0x9972
, 0x5df3
, 0x677e
, 0x8038
, 0x6002
, 0x9882
, 0x9001
, 0x5b8b
, 0x8bbc
, 0x8bf5
, 0x641c
, 0x8258
, 0x64de
, 0x55fd
, 0x82cf
, 0x9165
, 0x4fd7
, 0x7d20
, 0x901f
, 0x7c9f
, 0x50f3
, 0x5851
, 0x6eaf
, 0x5bbf
, 0x8bc9
, 0x8083
, 0x9178
, 0x849c
, 0x7b97
, 0x867d
, 0x968b
, 0x968f
, 0x7ee5
, 0x9ad3
, 0x788e
, 0x5c81
, 0x7a57
, 0x9042
, 0x96a7
, 0x795f
, 0x5b59
, 0x635f
, 0x7b0b
, 0x84d1
, 0x68ad
, 0x5506
, 0x7f29
, 0x7410
, 0x7d22
, 0x9501
, 0x6240
, 0x584c
, 0x4ed6
, 0x5b83
, 0x5979
, 0x5854
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x736d
, 0x631e
, 0x8e4b
, 0x8e0f
, 0x80ce
, 0x82d4
, 0x62ac
, 0x53f0
, 0x6cf0
, 0x915e
, 0x592a
, 0x6001
, 0x6c70
, 0x574d
, 0x644a
, 0x8d2a
, 0x762b
, 0x6ee9
, 0x575b
, 0x6a80
, 0x75f0
, 0x6f6d
, 0x8c2d
, 0x8c08
, 0x5766
, 0x6bef
, 0x8892
, 0x78b3
, 0x63a2
, 0x53f9
, 0x70ad
, 0x6c64
, 0x5858
, 0x642a
, 0x5802
, 0x68e0
, 0x819b
, 0x5510
, 0x7cd6
, 0x5018
, 0x8eba
, 0x6dcc
, 0x8d9f
, 0x70eb
, 0x638f
, 0x6d9b
, 0x6ed4
, 0x7ee6
, 0x8404
, 0x6843
, 0x9003
, 0x6dd8
, 0x9676
, 0x8ba8
, 0x5957
, 0x7279
, 0x85e4
, 0x817e
, 0x75bc
, 0x8a8a
, 0x68af
, 0x5254
, 0x8e22
, 0x9511
, 0x63d0
, 0x9898
, 0x8e44
, 0x557c
, 0x4f53
, 0x66ff
, 0x568f
, 0x60d5
, 0x6d95
, 0x5243
, 0x5c49
, 0x5929
, 0x6dfb
, 0x586b
, 0x7530
, 0x751c
, 0x606c
, 0x8214
, 0x8146
, 0x6311
, 0x6761
, 0x8fe2
, 0x773a
, 0x8df3
, 0x8d34
, 0x94c1
, 0x5e16
, 0x5385
, 0x542c
, 0x70c3
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x6c40
, 0x5ef7
, 0x505c
, 0x4ead
, 0x5ead
, 0x633a
, 0x8247
, 0x901a
, 0x6850
, 0x916e
, 0x77b3
, 0x540c
, 0x94dc
, 0x5f64
, 0x7ae5
, 0x6876
, 0x6345
, 0x7b52
, 0x7edf
, 0x75db
, 0x5077
, 0x6295
, 0x5934
, 0x900f
, 0x51f8
, 0x79c3
, 0x7a81
, 0x56fe
, 0x5f92
, 0x9014
, 0x6d82
, 0x5c60
, 0x571f
, 0x5410
, 0x5154
, 0x6e4d
, 0x56e2
, 0x63a8
, 0x9893
, 0x817f
, 0x8715
, 0x892a
, 0x9000
, 0x541e
, 0x5c6f
, 0x81c0
, 0x62d6
, 0x6258
, 0x8131
, 0x9e35
, 0x9640
, 0x9a6e
, 0x9a7c
, 0x692d
, 0x59a5
, 0x62d3
, 0x553e
, 0x6316
, 0x54c7
, 0x86d9
, 0x6d3c
, 0x5a03
, 0x74e6
, 0x889c
, 0x6b6a
, 0x5916
, 0x8c4c
, 0x5f2f
, 0x6e7e
, 0x73a9
, 0x987d
, 0x4e38
, 0x70f7
, 0x5b8c
, 0x7897
, 0x633d
, 0x665a
, 0x7696
, 0x60cb
, 0x5b9b
, 0x5a49
, 0x4e07
, 0x8155
, 0x6c6a
, 0x738b
, 0x4ea1
, 0x6789
, 0x7f51
, 0x5f80
, 0x65fa
, 0x671b
, 0x5fd8
, 0x5984
, 0x5a01
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x5dcd
, 0x5fae
, 0x5371
, 0x97e6
, 0x8fdd
, 0x6845
, 0x56f4
, 0x552f
, 0x60df
, 0x4e3a
, 0x6f4d
, 0x7ef4
, 0x82c7
, 0x840e
, 0x59d4
, 0x4f1f
, 0x4f2a
, 0x5c3e
, 0x7eac
, 0x672a
, 0x851a
, 0x5473
, 0x754f
, 0x80c3
, 0x5582
, 0x9b4f
, 0x4f4d
, 0x6e2d
, 0x8c13
, 0x5c09
, 0x6170
, 0x536b
, 0x761f
, 0x6e29
, 0x868a
, 0x6587
, 0x95fb
, 0x7eb9
, 0x543b
, 0x7a33
, 0x7d0a
, 0x95ee
, 0x55e1
, 0x7fc1
, 0x74ee
, 0x631d
, 0x8717
, 0x6da1
, 0x7a9d
, 0x6211
, 0x65a1
, 0x5367
, 0x63e1
, 0x6c83
, 0x5deb
, 0x545c
, 0x94a8
, 0x4e4c
, 0x6c61
, 0x8bec
, 0x5c4b
, 0x65e0
, 0x829c
, 0x68a7
, 0x543e
, 0x5434
, 0x6bcb
, 0x6b66
, 0x4e94
, 0x6342
, 0x5348
, 0x821e
, 0x4f0d
, 0x4fae
, 0x575e
, 0x620a
, 0x96fe
, 0x6664
, 0x7269
, 0x52ff
, 0x52a1
, 0x609f
, 0x8bef
, 0x6614
, 0x7199
, 0x6790
, 0x897f
, 0x7852
, 0x77fd
, 0x6670
, 0x563b
, 0x5438
, 0x9521
, 0x727a
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x7a00
, 0x606f
, 0x5e0c
, 0x6089
, 0x819d
, 0x5915
, 0x60dc
, 0x7184
, 0x70ef
, 0x6eaa
, 0x6c50
, 0x7280
, 0x6a84
, 0x88ad
, 0x5e2d
, 0x4e60
, 0x5ab3
, 0x559c
, 0x94e3
, 0x6d17
, 0x7cfb
, 0x9699
, 0x620f
, 0x7ec6
, 0x778e
, 0x867e
, 0x5323
, 0x971e
, 0x8f96
, 0x6687
, 0x5ce1
, 0x4fa0
, 0x72ed
, 0x4e0b
, 0x53a6
, 0x590f
, 0x5413
, 0x6380
, 0x9528
, 0x5148
, 0x4ed9
, 0x9c9c
, 0x7ea4
, 0x54b8
, 0x8d24
, 0x8854
, 0x8237
, 0x95f2
, 0x6d8e
, 0x5f26
, 0x5acc
, 0x663e
, 0x9669
, 0x73b0
, 0x732e
, 0x53bf
, 0x817a
, 0x9985
, 0x7fa1
, 0x5baa
, 0x9677
, 0x9650
, 0x7ebf
, 0x76f8
, 0x53a2
, 0x9576
, 0x9999
, 0x7bb1
, 0x8944
, 0x6e58
, 0x4e61
, 0x7fd4
, 0x7965
, 0x8be6
, 0x60f3
, 0x54cd
, 0x4eab
, 0x9879
, 0x5df7
, 0x6a61
, 0x50cf
, 0x5411
, 0x8c61
, 0x8427
, 0x785d
, 0x9704
, 0x524a
, 0x54ee
, 0x56a3
, 0x9500
, 0x6d88
, 0x5bb5
, 0x6dc6
, 0x6653
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x5c0f
, 0x5b5d
, 0x6821
, 0x8096
, 0x5578
, 0x7b11
, 0x6548
, 0x6954
, 0x4e9b
, 0x6b47
, 0x874e
, 0x978b
, 0x534f
, 0x631f
, 0x643a
, 0x90aa
, 0x659c
, 0x80c1
, 0x8c10
, 0x5199
, 0x68b0
, 0x5378
, 0x87f9
, 0x61c8
, 0x6cc4
, 0x6cfb
, 0x8c22
, 0x5c51
, 0x85aa
, 0x82af
, 0x950c
, 0x6b23
, 0x8f9b
, 0x65b0
, 0x5ffb
, 0x5fc3
, 0x4fe1
, 0x8845
, 0x661f
, 0x8165
, 0x7329
, 0x60fa
, 0x5174
, 0x5211
, 0x578b
, 0x5f62
, 0x90a2
, 0x884c
, 0x9192
, 0x5e78
, 0x674f
, 0x6027
, 0x59d3
, 0x5144
, 0x51f6
, 0x80f8
, 0x5308
, 0x6c79
, 0x96c4
, 0x718a
, 0x4f11
, 0x4fee
, 0x7f9e
, 0x673d
, 0x55c5
, 0x9508
, 0x79c0
, 0x8896
, 0x7ee3
, 0x589f
, 0x620c
, 0x9700
, 0x865a
, 0x5618
, 0x987b
, 0x5f90
, 0x8bb8
, 0x84c4
, 0x9157
, 0x53d9
, 0x65ed
, 0x5e8f
, 0x755c
, 0x6064
, 0x7d6e
, 0x5a7f
, 0x7eea
, 0x7eed
, 0x8f69
, 0x55a7
, 0x5ba3
, 0x60ac
, 0x65cb
, 0x7384
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x9009
, 0x7663
, 0x7729
, 0x7eda
, 0x9774
, 0x859b
, 0x5b66
, 0x7a74
, 0x96ea
, 0x8840
, 0x52cb
, 0x718f
, 0x5faa
, 0x65ec
, 0x8be2
, 0x5bfb
, 0x9a6f
, 0x5de1
, 0x6b89
, 0x6c5b
, 0x8bad
, 0x8baf
, 0x900a
, 0x8fc5
, 0x538b
, 0x62bc
, 0x9e26
, 0x9e2d
, 0x5440
, 0x4e2b
, 0x82bd
, 0x7259
, 0x869c
, 0x5d16
, 0x8859
, 0x6daf
, 0x96c5
, 0x54d1
, 0x4e9a
, 0x8bb6
, 0x7109
, 0x54bd
, 0x9609
, 0x70df
, 0x6df9
, 0x76d0
, 0x4e25
, 0x7814
, 0x8712
, 0x5ca9
, 0x5ef6
, 0x8a00
, 0x989c
, 0x960e
, 0x708e
, 0x6cbf
, 0x5944
, 0x63a9
, 0x773c
, 0x884d
, 0x6f14
, 0x8273
, 0x5830
, 0x71d5
, 0x538c
, 0x781a
, 0x96c1
, 0x5501
, 0x5f66
, 0x7130
, 0x5bb4
, 0x8c1a
, 0x9a8c
, 0x6b83
, 0x592e
, 0x9e2f
, 0x79e7
, 0x6768
, 0x626c
, 0x4f6f
, 0x75a1
, 0x7f8a
, 0x6d0b
, 0x9633
, 0x6c27
, 0x4ef0
, 0x75d2
, 0x517b
, 0x6837
, 0x6f3e
, 0x9080
, 0x8170
, 0x5996
, 0x7476
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x6447
, 0x5c27
, 0x9065
, 0x7a91
, 0x8c23
, 0x59da
, 0x54ac
, 0x8200
, 0x836f
, 0x8981
, 0x8000
, 0x6930
, 0x564e
, 0x8036
, 0x7237
, 0x91ce
, 0x51b6
, 0x4e5f
, 0x9875
, 0x6396
, 0x4e1a
, 0x53f6
, 0x66f3
, 0x814b
, 0x591c
, 0x6db2
, 0x4e00
, 0x58f9
, 0x533b
, 0x63d6
, 0x94f1
, 0x4f9d
, 0x4f0a
, 0x8863
, 0x9890
, 0x5937
, 0x9057
, 0x79fb
, 0x4eea
, 0x80f0
, 0x7591
, 0x6c82
, 0x5b9c
, 0x59e8
, 0x5f5d
, 0x6905
, 0x8681
, 0x501a
, 0x5df2
, 0x4e59
, 0x77e3
, 0x4ee5
, 0x827a
, 0x6291
, 0x6613
, 0x9091
, 0x5c79
, 0x4ebf
, 0x5f79
, 0x81c6
, 0x9038
, 0x8084
, 0x75ab
, 0x4ea6
, 0x88d4
, 0x610f
, 0x6bc5
, 0x5fc6
, 0x4e49
, 0x76ca
, 0x6ea2
, 0x8be3
, 0x8bae
, 0x8c0a
, 0x8bd1
, 0x5f02
, 0x7ffc
, 0x7fcc
, 0x7ece
, 0x8335
, 0x836b
, 0x56e0
, 0x6bb7
, 0x97f3
, 0x9634
, 0x59fb
, 0x541f
, 0x94f6
, 0x6deb
, 0x5bc5
, 0x996e
, 0x5c39
, 0x5f15
, 0x9690
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x5370
, 0x82f1
, 0x6a31
, 0x5a74
, 0x9e70
, 0x5e94
, 0x7f28
, 0x83b9
, 0x8424
, 0x8425
, 0x8367
, 0x8747
, 0x8fce
, 0x8d62
, 0x76c8
, 0x5f71
, 0x9896
, 0x786c
, 0x6620
, 0x54df
, 0x62e5
, 0x4f63
, 0x81c3
, 0x75c8
, 0x5eb8
, 0x96cd
, 0x8e0a
, 0x86f9
, 0x548f
, 0x6cf3
, 0x6d8c
, 0x6c38
, 0x607f
, 0x52c7
, 0x7528
, 0x5e7d
, 0x4f18
, 0x60a0
, 0x5fe7
, 0x5c24
, 0x7531
, 0x90ae
, 0x94c0
, 0x72b9
, 0x6cb9
, 0x6e38
, 0x9149
, 0x6709
, 0x53cb
, 0x53f3
, 0x4f51
, 0x91c9
, 0x8bf1
, 0x53c8
, 0x5e7c
, 0x8fc2
, 0x6de4
, 0x4e8e
, 0x76c2
, 0x6986
, 0x865e
, 0x611a
, 0x8206
, 0x4f59
, 0x4fde
, 0x903e
, 0x9c7c
, 0x6109
, 0x6e1d
, 0x6e14
, 0x9685
, 0x4e88
, 0x5a31
, 0x96e8
, 0x4e0e
, 0x5c7f
, 0x79b9
, 0x5b87
, 0x8bed
, 0x7fbd
, 0x7389
, 0x57df
, 0x828b
, 0x90c1
, 0x5401
, 0x9047
, 0x55bb
, 0x5cea
, 0x5fa1
, 0x6108
, 0x6b32
, 0x72f1
, 0x80b2
, 0x8a89
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x6d74
, 0x5bd3
, 0x88d5
, 0x9884
, 0x8c6b
, 0x9a6d
, 0x9e33
, 0x6e0a
, 0x51a4
, 0x5143
, 0x57a3
, 0x8881
, 0x539f
, 0x63f4
, 0x8f95
, 0x56ed
, 0x5458
, 0x5706
, 0x733f
, 0x6e90
, 0x7f18
, 0x8fdc
, 0x82d1
, 0x613f
, 0x6028
, 0x9662
, 0x66f0
, 0x7ea6
, 0x8d8a
, 0x8dc3
, 0x94a5
, 0x5cb3
, 0x7ca4
, 0x6708
, 0x60a6
, 0x9605
, 0x8018
, 0x4e91
, 0x90e7
, 0x5300
, 0x9668
, 0x5141
, 0x8fd0
, 0x8574
, 0x915d
, 0x6655
, 0x97f5
, 0x5b55
, 0x531d
, 0x7838
, 0x6742
, 0x683d
, 0x54c9
, 0x707e
, 0x5bb0
, 0x8f7d
, 0x518d
, 0x5728
, 0x54b1
, 0x6512
, 0x6682
, 0x8d5e
, 0x8d43
, 0x810f
, 0x846c
, 0x906d
, 0x7cdf
, 0x51ff
, 0x85fb
, 0x67a3
, 0x65e9
, 0x6fa1
, 0x86a4
, 0x8e81
, 0x566a
, 0x9020
, 0x7682
, 0x7076
, 0x71e5
, 0x8d23
, 0x62e9
, 0x5219
, 0x6cfd
, 0x8d3c
, 0x600e
, 0x589e
, 0x618e
, 0x66fe
, 0x8d60
, 0x624e
, 0x55b3
, 0x6e23
, 0x672d
, 0x8f67
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x94e1
, 0x95f8
, 0x7728
, 0x6805
, 0x69a8
, 0x548b
, 0x4e4d
, 0x70b8
, 0x8bc8
, 0x6458
, 0x658b
, 0x5b85
, 0x7a84
, 0x503a
, 0x5be8
, 0x77bb
, 0x6be1
, 0x8a79
, 0x7c98
, 0x6cbe
, 0x76cf
, 0x65a9
, 0x8f97
, 0x5d2d
, 0x5c55
, 0x8638
, 0x6808
, 0x5360
, 0x6218
, 0x7ad9
, 0x6e5b
, 0x7efd
, 0x6a1f
, 0x7ae0
, 0x5f70
, 0x6f33
, 0x5f20
, 0x638c
, 0x6da8
, 0x6756
, 0x4e08
, 0x5e10
, 0x8d26
, 0x4ed7
, 0x80c0
, 0x7634
, 0x969c
, 0x62db
, 0x662d
, 0x627e
, 0x6cbc
, 0x8d75
, 0x7167
, 0x7f69
, 0x5146
, 0x8087
, 0x53ec
, 0x906e
, 0x6298
, 0x54f2
, 0x86f0
, 0x8f99
, 0x8005
, 0x9517
, 0x8517
, 0x8fd9
, 0x6d59
, 0x73cd
, 0x659f
, 0x771f
, 0x7504
, 0x7827
, 0x81fb
, 0x8d1e
, 0x9488
, 0x4fa6
, 0x6795
, 0x75b9
, 0x8bca
, 0x9707
, 0x632f
, 0x9547
, 0x9635
, 0x84b8
, 0x6323
, 0x7741
, 0x5f81
, 0x72f0
, 0x4e89
, 0x6014
, 0x6574
, 0x62ef
, 0x6b63
, 0x653f
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x5e27
, 0x75c7
, 0x90d1
, 0x8bc1
, 0x829d
, 0x679d
, 0x652f
, 0x5431
, 0x8718
, 0x77e5
, 0x80a2
, 0x8102
, 0x6c41
, 0x4e4b
, 0x7ec7
, 0x804c
, 0x76f4
, 0x690d
, 0x6b96
, 0x6267
, 0x503c
, 0x4f84
, 0x5740
, 0x6307
, 0x6b62
, 0x8dbe
, 0x53ea
, 0x65e8
, 0x7eb8
, 0x5fd7
, 0x631a
, 0x63b7
, 0x81f3
, 0x81f4
, 0x7f6e
, 0x5e1c
, 0x5cd9
, 0x5236
, 0x667a
, 0x79e9
, 0x7a1a
, 0x8d28
, 0x7099
, 0x75d4
, 0x6ede
, 0x6cbb
, 0x7a92
, 0x4e2d
, 0x76c5
, 0x5fe0
, 0x949f
, 0x8877
, 0x7ec8
, 0x79cd
, 0x80bf
, 0x91cd
, 0x4ef2
, 0x4f17
, 0x821f
, 0x5468
, 0x5dde
, 0x6d32
, 0x8bcc
, 0x7ca5
, 0x8f74
, 0x8098
, 0x5e1a
, 0x5492
, 0x76b1
, 0x5b99
, 0x663c
, 0x9aa4
, 0x73e0
, 0x682a
, 0x86db
, 0x6731
, 0x732a
, 0x8bf8
, 0x8bdb
, 0x9010
, 0x7af9
, 0x70db
, 0x716e
, 0x62c4
, 0x77a9
, 0x5631
, 0x4e3b
, 0x8457
, 0x67f1
, 0x52a9
, 0x86c0
, 0x8d2e
, 0x94f8
, 0x7b51
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x4f4f
, 0x6ce8
, 0x795d
, 0x9a7b
, 0x6293
, 0x722a
, 0x62fd
, 0x4e13
, 0x7816
, 0x8f6c
, 0x64b0
, 0x8d5a
, 0x7bc6
, 0x6869
, 0x5e84
, 0x88c5
, 0x5986
, 0x649e
, 0x58ee
, 0x72b6
, 0x690e
, 0x9525
, 0x8ffd
, 0x8d58
, 0x5760
, 0x7f00
, 0x8c06
, 0x51c6
, 0x6349
, 0x62d9
, 0x5353
, 0x684c
, 0x7422
, 0x8301
, 0x914c
, 0x5544
, 0x7740
, 0x707c
, 0x6d4a
, 0x5179
, 0x54a8
, 0x8d44
, 0x59ff
, 0x6ecb
, 0x6dc4
, 0x5b5c
, 0x7d2b
, 0x4ed4
, 0x7c7d
, 0x6ed3
, 0x5b50
, 0x81ea
, 0x6e0d
, 0x5b57
, 0x9b03
, 0x68d5
, 0x8e2a
, 0x5b97
, 0x7efc
, 0x603b
, 0x7eb5
, 0x90b9
, 0x8d70
, 0x594f
, 0x63cd
, 0x79df
, 0x8db3
, 0x5352
, 0x65cf
, 0x7956
, 0x8bc5
, 0x963b
, 0x7ec4
, 0x94bb
, 0x7e82
, 0x5634
, 0x9189
, 0x6700
, 0x7f6a
, 0x5c0a
, 0x9075
, 0x6628
, 0x5de6
, 0x4f50
, 0x67de
, 0x505a
, 0x4f5c
, 0x5750
, 0x5ea7
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x4e8d
, 0x4e0c
, 0x5140
, 0x4e10
, 0x5eff
, 0x5345
, 0x4e15
, 0x4e98
, 0x4e1e
, 0x9b32
, 0x5b6c
, 0x5669
, 0x4e28
, 0x79ba
, 0x4e3f
, 0x5315
, 0x4e47
, 0x592d
, 0x723b
, 0x536e
, 0x6c10
, 0x56df
, 0x80e4
, 0x9997
, 0x6bd3
, 0x777e
, 0x9f17
, 0x4e36
, 0x4e9f
, 0x9f10
, 0x4e5c
, 0x4e69
, 0x4e93
, 0x8288
, 0x5b5b
, 0x556c
, 0x560f
, 0x4ec4
, 0x538d
, 0x539d
, 0x53a3
, 0x53a5
, 0x53ae
, 0x9765
, 0x8d5d
, 0x531a
, 0x53f5
, 0x5326
, 0x532e
, 0x533e
, 0x8d5c
, 0x5366
, 0x5363
, 0x5202
, 0x5208
, 0x520e
, 0x522d
, 0x5233
, 0x523f
, 0x5240
, 0x524c
, 0x525e
, 0x5261
, 0x525c
, 0x84af
, 0x527d
, 0x5282
, 0x5281
, 0x5290
, 0x5293
, 0x5182
, 0x7f54
, 0x4ebb
, 0x4ec3
, 0x4ec9
, 0x4ec2
, 0x4ee8
, 0x4ee1
, 0x4eeb
, 0x4ede
, 0x4f1b
, 0x4ef3
, 0x4f22
, 0x4f64
, 0x4ef5
, 0x4f25
, 0x4f27
, 0x4f09
, 0x4f2b
, 0x4f5e
, 0x4f67
, 0x6538
, 0x4f5a
, 0x4f5d
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x4f5f
, 0x4f57
, 0x4f32
, 0x4f3d
, 0x4f76
, 0x4f74
, 0x4f91
, 0x4f89
, 0x4f83
, 0x4f8f
, 0x4f7e
, 0x4f7b
, 0x4faa
, 0x4f7c
, 0x4fac
, 0x4f94
, 0x4fe6
, 0x4fe8
, 0x4fea
, 0x4fc5
, 0x4fda
, 0x4fe3
, 0x4fdc
, 0x4fd1
, 0x4fdf
, 0x4ff8
, 0x5029
, 0x504c
, 0x4ff3
, 0x502c
, 0x500f
, 0x502e
, 0x502d
, 0x4ffe
, 0x501c
, 0x500c
, 0x5025
, 0x5028
, 0x507e
, 0x5043
, 0x5055
, 0x5048
, 0x504e
, 0x506c
, 0x507b
, 0x50a5
, 0x50a7
, 0x50a9
, 0x50ba
, 0x50d6
, 0x5106
, 0x50ed
, 0x50ec
, 0x50e6
, 0x50ee
, 0x5107
, 0x510b
, 0x4edd
, 0x6c3d
, 0x4f58
, 0x4f65
, 0x4fce
, 0x9fa0
, 0x6c46
, 0x7c74
, 0x516e
, 0x5dfd
, 0x9ec9
, 0x9998
, 0x5181
, 0x5914
, 0x52f9
, 0x530d
, 0x8a07
, 0x5310
, 0x51eb
, 0x5919
, 0x5155
, 0x4ea0
, 0x5156
, 0x4eb3
, 0x886e
, 0x88a4
, 0x4eb5
, 0x8114
, 0x88d2
, 0x7980
, 0x5b34
, 0x8803
, 0x7fb8
, 0x51ab
, 0x51b1
, 0x51bd
, 0x51bc
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x51c7
, 0x5196
, 0x51a2
, 0x51a5
, 0x8ba0
, 0x8ba6
, 0x8ba7
, 0x8baa
, 0x8bb4
, 0x8bb5
, 0x8bb7
, 0x8bc2
, 0x8bc3
, 0x8bcb
, 0x8bcf
, 0x8bce
, 0x8bd2
, 0x8bd3
, 0x8bd4
, 0x8bd6
, 0x8bd8
, 0x8bd9
, 0x8bdc
, 0x8bdf
, 0x8be0
, 0x8be4
, 0x8be8
, 0x8be9
, 0x8bee
, 0x8bf0
, 0x8bf3
, 0x8bf6
, 0x8bf9
, 0x8bfc
, 0x8bff
, 0x8c00
, 0x8c02
, 0x8c04
, 0x8c07
, 0x8c0c
, 0x8c0f
, 0x8c11
, 0x8c12
, 0x8c14
, 0x8c15
, 0x8c16
, 0x8c19
, 0x8c1b
, 0x8c18
, 0x8c1d
, 0x8c1f
, 0x8c20
, 0x8c21
, 0x8c25
, 0x8c27
, 0x8c2a
, 0x8c2b
, 0x8c2e
, 0x8c2f
, 0x8c32
, 0x8c33
, 0x8c35
, 0x8c36
, 0x5369
, 0x537a
, 0x961d
, 0x9622
, 0x9621
, 0x9631
, 0x962a
, 0x963d
, 0x963c
, 0x9642
, 0x9649
, 0x9654
, 0x965f
, 0x9667
, 0x966c
, 0x9672
, 0x9674
, 0x9688
, 0x968d
, 0x9697
, 0x96b0
, 0x9097
, 0x909b
, 0x909d
, 0x9099
, 0x90ac
, 0x90a1
, 0x90b4
, 0x90b3
, 0x90b6
, 0x90ba
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x90b8
, 0x90b0
, 0x90cf
, 0x90c5
, 0x90be
, 0x90d0
, 0x90c4
, 0x90c7
, 0x90d3
, 0x90e6
, 0x90e2
, 0x90dc
, 0x90d7
, 0x90db
, 0x90eb
, 0x90ef
, 0x90fe
, 0x9104
, 0x9122
, 0x911e
, 0x9123
, 0x9131
, 0x912f
, 0x9139
, 0x9143
, 0x9146
, 0x520d
, 0x5942
, 0x52a2
, 0x52ac
, 0x52ad
, 0x52be
, 0x54ff
, 0x52d0
, 0x52d6
, 0x52f0
, 0x53df
, 0x71ee
, 0x77cd
, 0x5ef4
, 0x51f5
, 0x51fc
, 0x9b2f
, 0x53b6
, 0x5f01
, 0x755a
, 0x5def
, 0x574c
, 0x57a9
, 0x57a1
, 0x587e
, 0x58bc
, 0x58c5
, 0x58d1
, 0x5729
, 0x572c
, 0x572a
, 0x5733
, 0x5739
, 0x572e
, 0x572f
, 0x575c
, 0x573b
, 0x5742
, 0x5769
, 0x5785
, 0x576b
, 0x5786
, 0x577c
, 0x577b
, 0x5768
, 0x576d
, 0x5776
, 0x5773
, 0x57ad
, 0x57a4
, 0x578c
, 0x57b2
, 0x57cf
, 0x57a7
, 0x57b4
, 0x5793
, 0x57a0
, 0x57d5
, 0x57d8
, 0x57da
, 0x57d9
, 0x57d2
, 0x57b8
, 0x57f4
, 0x57ef
, 0x57f8
, 0x57e4
, 0x57dd
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x580b
, 0x580d
, 0x57fd
, 0x57ed
, 0x5800
, 0x581e
, 0x5819
, 0x5844
, 0x5820
, 0x5865
, 0x586c
, 0x5881
, 0x5889
, 0x589a
, 0x5880
, 0x99a8
, 0x9f19
, 0x61ff
, 0x8279
, 0x827d
, 0x827f
, 0x828f
, 0x828a
, 0x82a8
, 0x8284
, 0x828e
, 0x8291
, 0x8297
, 0x8299
, 0x82ab
, 0x82b8
, 0x82be
, 0x82b0
, 0x82c8
, 0x82ca
, 0x82e3
, 0x8298
, 0x82b7
, 0x82ae
, 0x82cb
, 0x82cc
, 0x82c1
, 0x82a9
, 0x82b4
, 0x82a1
, 0x82aa
, 0x829f
, 0x82c4
, 0x82ce
, 0x82a4
, 0x82e1
, 0x8309
, 0x82f7
, 0x82e4
, 0x830f
, 0x8307
, 0x82dc
, 0x82f4
, 0x82d2
, 0x82d8
, 0x830c
, 0x82fb
, 0x82d3
, 0x8311
, 0x831a
, 0x8306
, 0x8314
, 0x8315
, 0x82e0
, 0x82d5
, 0x831c
, 0x8351
, 0x835b
, 0x835c
, 0x8308
, 0x8392
, 0x833c
, 0x8334
, 0x8331
, 0x839b
, 0x835e
, 0x832f
, 0x834f
, 0x8347
, 0x8343
, 0x835f
, 0x8340
, 0x8317
, 0x8360
, 0x832d
, 0x833a
, 0x8333
, 0x8366
, 0x8365
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x8368
, 0x831b
, 0x8369
, 0x836c
, 0x836a
, 0x836d
, 0x836e
, 0x83b0
, 0x8378
, 0x83b3
, 0x83b4
, 0x83a0
, 0x83aa
, 0x8393
, 0x839c
, 0x8385
, 0x837c
, 0x83b6
, 0x83a9
, 0x837d
, 0x83b8
, 0x837b
, 0x8398
, 0x839e
, 0x83a8
, 0x83ba
, 0x83bc
, 0x83c1
, 0x8401
, 0x83e5
, 0x83d8
, 0x5807
, 0x8418
, 0x840b
, 0x83dd
, 0x83fd
, 0x83d6
, 0x841c
, 0x8438
, 0x8411
, 0x8406
, 0x83d4
, 0x83df
, 0x840f
, 0x8403
, 0x83f8
, 0x83f9
, 0x83ea
, 0x83c5
, 0x83c0
, 0x8426
, 0x83f0
, 0x83e1
, 0x845c
, 0x8451
, 0x845a
, 0x8459
, 0x8473
, 0x8487
, 0x8488
, 0x847a
, 0x8489
, 0x8478
, 0x843c
, 0x8446
, 0x8469
, 0x8476
, 0x848c
, 0x848e
, 0x8431
, 0x846d
, 0x84c1
, 0x84cd
, 0x84d0
, 0x84e6
, 0x84bd
, 0x84d3
, 0x84ca
, 0x84bf
, 0x84ba
, 0x84e0
, 0x84a1
, 0x84b9
, 0x84b4
, 0x8497
, 0x84e5
, 0x84e3
, 0x850c
, 0x750d
, 0x8538
, 0x84f0
, 0x8539
, 0x851f
, 0x853a
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x8556
, 0x853b
, 0x84ff
, 0x84fc
, 0x8559
, 0x8548
, 0x8568
, 0x8564
, 0x855e
, 0x857a
, 0x77a2
, 0x8543
, 0x8572
, 0x857b
, 0x85a4
, 0x85a8
, 0x8587
, 0x858f
, 0x8579
, 0x85ae
, 0x859c
, 0x8585
, 0x85b9
, 0x85b7
, 0x85b0
, 0x85d3
, 0x85c1
, 0x85dc
, 0x85ff
, 0x8627
, 0x8605
, 0x8629
, 0x8616
, 0x863c
, 0x5efe
, 0x5f08
, 0x593c
, 0x5941
, 0x8037
, 0x5955
, 0x595a
, 0x5958
, 0x530f
, 0x5c22
, 0x5c25
, 0x5c2c
, 0x5c34
, 0x624c
, 0x626a
, 0x629f
, 0x62bb
, 0x62ca
, 0x62da
, 0x62d7
, 0x62ee
, 0x6322
, 0x62f6
, 0x6339
, 0x634b
, 0x6343
, 0x63ad
, 0x63f6
, 0x6371
, 0x637a
, 0x638e
, 0x63b4
, 0x636d
, 0x63ac
, 0x638a
, 0x6369
, 0x63ae
, 0x63bc
, 0x63f2
, 0x63f8
, 0x63e0
, 0x63ff
, 0x63c4
, 0x63de
, 0x63ce
, 0x6452
, 0x63c6
, 0x63be
, 0x6445
, 0x6441
, 0x640b
, 0x641b
, 0x6420
, 0x640c
, 0x6426
, 0x6421
, 0x645e
, 0x6484
, 0x646d
, 0x6496
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x647a
, 0x64b7
, 0x64b8
, 0x6499
, 0x64ba
, 0x64c0
, 0x64d0
, 0x64d7
, 0x64e4
, 0x64e2
, 0x6509
, 0x6525
, 0x652e
, 0x5f0b
, 0x5fd2
, 0x7519
, 0x5f11
, 0x535f
, 0x53f1
, 0x53fd
, 0x53e9
, 0x53e8
, 0x53fb
, 0x5412
, 0x5416
, 0x5406
, 0x544b
, 0x5452
, 0x5453
, 0x5454
, 0x5456
, 0x5443
, 0x5421
, 0x5457
, 0x5459
, 0x5423
, 0x5432
, 0x5482
, 0x5494
, 0x5477
, 0x5471
, 0x5464
, 0x549a
, 0x549b
, 0x5484
, 0x5476
, 0x5466
, 0x549d
, 0x54d0
, 0x54ad
, 0x54c2
, 0x54b4
, 0x54d2
, 0x54a7
, 0x54a6
, 0x54d3
, 0x54d4
, 0x5472
, 0x54a3
, 0x54d5
, 0x54bb
, 0x54bf
, 0x54cc
, 0x54d9
, 0x54da
, 0x54dc
, 0x54a9
, 0x54aa
, 0x54a4
, 0x54dd
, 0x54cf
, 0x54de
, 0x551b
, 0x54e7
, 0x5520
, 0x54fd
, 0x5514
, 0x54f3
, 0x5522
, 0x5523
, 0x550f
, 0x5511
, 0x5527
, 0x552a
, 0x5567
, 0x558f
, 0x55b5
, 0x5549
, 0x556d
, 0x5541
, 0x5555
, 0x553f
, 0x5550
, 0x553c
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x5537
, 0x5556
, 0x5575
, 0x5576
, 0x5577
, 0x5533
, 0x5530
, 0x555c
, 0x558b
, 0x55d2
, 0x5583
, 0x55b1
, 0x55b9
, 0x5588
, 0x5581
, 0x559f
, 0x557e
, 0x55d6
, 0x5591
, 0x557b
, 0x55df
, 0x55bd
, 0x55be
, 0x5594
, 0x5599
, 0x55ea
, 0x55f7
, 0x55c9
, 0x561f
, 0x55d1
, 0x55eb
, 0x55ec
, 0x55d4
, 0x55e6
, 0x55dd
, 0x55c4
, 0x55ef
, 0x55e5
, 0x55f2
, 0x55f3
, 0x55cc
, 0x55cd
, 0x55e8
, 0x55f5
, 0x55e4
, 0x8f94
, 0x561e
, 0x5608
, 0x560c
, 0x5601
, 0x5624
, 0x5623
, 0x55fe
, 0x5600
, 0x5627
, 0x562d
, 0x5658
, 0x5639
, 0x5657
, 0x562c
, 0x564d
, 0x5662
, 0x5659
, 0x565c
, 0x564c
, 0x5654
, 0x5686
, 0x5664
, 0x5671
, 0x566b
, 0x567b
, 0x567c
, 0x5685
, 0x5693
, 0x56af
, 0x56d4
, 0x56d7
, 0x56dd
, 0x56e1
, 0x56f5
, 0x56eb
, 0x56f9
, 0x56ff
, 0x5704
, 0x570a
, 0x5709
, 0x571c
, 0x5e0f
, 0x5e19
, 0x5e14
, 0x5e11
, 0x5e31
, 0x5e3b
, 0x5e3c
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x5e37
, 0x5e44
, 0x5e54
, 0x5e5b
, 0x5e5e
, 0x5e61
, 0x5c8c
, 0x5c7a
, 0x5c8d
, 0x5c90
, 0x5c96
, 0x5c88
, 0x5c98
, 0x5c99
, 0x5c91
, 0x5c9a
, 0x5c9c
, 0x5cb5
, 0x5ca2
, 0x5cbd
, 0x5cac
, 0x5cab
, 0x5cb1
, 0x5ca3
, 0x5cc1
, 0x5cb7
, 0x5cc4
, 0x5cd2
, 0x5ce4
, 0x5ccb
, 0x5ce5
, 0x5d02
, 0x5d03
, 0x5d27
, 0x5d26
, 0x5d2e
, 0x5d24
, 0x5d1e
, 0x5d06
, 0x5d1b
, 0x5d58
, 0x5d3e
, 0x5d34
, 0x5d3d
, 0x5d6c
, 0x5d5b
, 0x5d6f
, 0x5d5d
, 0x5d6b
, 0x5d4b
, 0x5d4a
, 0x5d69
, 0x5d74
, 0x5d82
, 0x5d99
, 0x5d9d
, 0x8c73
, 0x5db7
, 0x5dc5
, 0x5f73
, 0x5f77
, 0x5f82
, 0x5f87
, 0x5f89
, 0x5f8c
, 0x5f95
, 0x5f99
, 0x5f9c
, 0x5fa8
, 0x5fad
, 0x5fb5
, 0x5fbc
, 0x8862
, 0x5f61
, 0x72ad
, 0x72b0
, 0x72b4
, 0x72b7
, 0x72b8
, 0x72c3
, 0x72c1
, 0x72ce
, 0x72cd
, 0x72d2
, 0x72e8
, 0x72ef
, 0x72e9
, 0x72f2
, 0x72f4
, 0x72f7
, 0x7301
, 0x72f3
, 0x7303
, 0x72fa
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x72fb
, 0x7317
, 0x7313
, 0x7321
, 0x730a
, 0x731e
, 0x731d
, 0x7315
, 0x7322
, 0x7339
, 0x7325
, 0x732c
, 0x7338
, 0x7331
, 0x7350
, 0x734d
, 0x7357
, 0x7360
, 0x736c
, 0x736f
, 0x737e
, 0x821b
, 0x5925
, 0x98e7
, 0x5924
, 0x5902
, 0x9963
, 0x9967
, 0x9968
, 0x9969
, 0x996a
, 0x996b
, 0x996c
, 0x9974
, 0x9977
, 0x997d
, 0x9980
, 0x9984
, 0x9987
, 0x998a
, 0x998d
, 0x9990
, 0x9991
, 0x9993
, 0x9994
, 0x9995
, 0x5e80
, 0x5e91
, 0x5e8b
, 0x5e96
, 0x5ea5
, 0x5ea0
, 0x5eb9
, 0x5eb5
, 0x5ebe
, 0x5eb3
, 0x8d53
, 0x5ed2
, 0x5ed1
, 0x5edb
, 0x5ee8
, 0x5eea
, 0x81ba
, 0x5fc4
, 0x5fc9
, 0x5fd6
, 0x5fcf
, 0x6003
, 0x5fee
, 0x6004
, 0x5fe1
, 0x5fe4
, 0x5ffe
, 0x6005
, 0x6006
, 0x5fea
, 0x5fed
, 0x5ff8
, 0x6019
, 0x6035
, 0x6026
, 0x601b
, 0x600f
, 0x600d
, 0x6029
, 0x602b
, 0x600a
, 0x603f
, 0x6021
, 0x6078
, 0x6079
, 0x607b
, 0x607a
, 0x6042
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x606a
, 0x607d
, 0x6096
, 0x609a
, 0x60ad
, 0x609d
, 0x6083
, 0x6092
, 0x608c
, 0x609b
, 0x60ec
, 0x60bb
, 0x60b1
, 0x60dd
, 0x60d8
, 0x60c6
, 0x60da
, 0x60b4
, 0x6120
, 0x6126
, 0x6115
, 0x6123
, 0x60f4
, 0x6100
, 0x610e
, 0x612b
, 0x614a
, 0x6175
, 0x61ac
, 0x6194
, 0x61a7
, 0x61b7
, 0x61d4
, 0x61f5
, 0x5fdd
, 0x96b3
, 0x95e9
, 0x95eb
, 0x95f1
, 0x95f3
, 0x95f5
, 0x95f6
, 0x95fc
, 0x95fe
, 0x9603
, 0x9604
, 0x9606
, 0x9608
, 0x960a
, 0x960b
, 0x960c
, 0x960d
, 0x960f
, 0x9612
, 0x9615
, 0x9616
, 0x9617
, 0x9619
, 0x961a
, 0x4e2c
, 0x723f
, 0x6215
, 0x6c35
, 0x6c54
, 0x6c5c
, 0x6c4a
, 0x6ca3
, 0x6c85
, 0x6c90
, 0x6c94
, 0x6c8c
, 0x6c68
, 0x6c69
, 0x6c74
, 0x6c76
, 0x6c86
, 0x6ca9
, 0x6cd0
, 0x6cd4
, 0x6cad
, 0x6cf7
, 0x6cf8
, 0x6cf1
, 0x6cd7
, 0x6cb2
, 0x6ce0
, 0x6cd6
, 0x6cfa
, 0x6ceb
, 0x6cee
, 0x6cb1
, 0x6cd3
, 0x6cef
, 0x6cfe
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x6d39
, 0x6d27
, 0x6d0c
, 0x6d43
, 0x6d48
, 0x6d07
, 0x6d04
, 0x6d19
, 0x6d0e
, 0x6d2b
, 0x6d4d
, 0x6d2e
, 0x6d35
, 0x6d1a
, 0x6d4f
, 0x6d52
, 0x6d54
, 0x6d33
, 0x6d91
, 0x6d6f
, 0x6d9e
, 0x6da0
, 0x6d5e
, 0x6d93
, 0x6d94
, 0x6d5c
, 0x6d60
, 0x6d7c
, 0x6d63
, 0x6e1a
, 0x6dc7
, 0x6dc5
, 0x6dde
, 0x6e0e
, 0x6dbf
, 0x6de0
, 0x6e11
, 0x6de6
, 0x6ddd
, 0x6dd9
, 0x6e16
, 0x6dab
, 0x6e0c
, 0x6dae
, 0x6e2b
, 0x6e6e
, 0x6e4e
, 0x6e6b
, 0x6eb2
, 0x6e5f
, 0x6e86
, 0x6e53
, 0x6e54
, 0x6e32
, 0x6e25
, 0x6e44
, 0x6edf
, 0x6eb1
, 0x6e98
, 0x6ee0
, 0x6f2d
, 0x6ee2
, 0x6ea5
, 0x6ea7
, 0x6ebd
, 0x6ebb
, 0x6eb7
, 0x6ed7
, 0x6eb4
, 0x6ecf
, 0x6e8f
, 0x6ec2
, 0x6e9f
, 0x6f62
, 0x6f46
, 0x6f47
, 0x6f24
, 0x6f15
, 0x6ef9
, 0x6f2f
, 0x6f36
, 0x6f4b
, 0x6f74
, 0x6f2a
, 0x6f09
, 0x6f29
, 0x6f89
, 0x6f8d
, 0x6f8c
, 0x6f78
, 0x6f72
, 0x6f7c
, 0x6f7a
, 0x6fd1
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x6fc9
, 0x6fa7
, 0x6fb9
, 0x6fb6
, 0x6fc2
, 0x6fe1
, 0x6fee
, 0x6fde
, 0x6fe0
, 0x6fef
, 0x701a
, 0x7023
, 0x701b
, 0x7039
, 0x7035
, 0x704f
, 0x705e
, 0x5b80
, 0x5b84
, 0x5b95
, 0x5b93
, 0x5ba5
, 0x5bb8
, 0x752f
, 0x9a9e
, 0x6434
, 0x5be4
, 0x5bee
, 0x8930
, 0x5bf0
, 0x8e47
, 0x8b07
, 0x8fb6
, 0x8fd3
, 0x8fd5
, 0x8fe5
, 0x8fee
, 0x8fe4
, 0x8fe9
, 0x8fe6
, 0x8ff3
, 0x8fe8
, 0x9005
, 0x9004
, 0x900b
, 0x9026
, 0x9011
, 0x900d
, 0x9016
, 0x9021
, 0x9035
, 0x9036
, 0x902d
, 0x902f
, 0x9044
, 0x9051
, 0x9052
, 0x9050
, 0x9068
, 0x9058
, 0x9062
, 0x905b
, 0x66b9
, 0x9074
, 0x907d
, 0x9082
, 0x9088
, 0x9083
, 0x908b
, 0x5f50
, 0x5f57
, 0x5f56
, 0x5f58
, 0x5c3b
, 0x54ab
, 0x5c50
, 0x5c59
, 0x5b71
, 0x5c63
, 0x5c66
, 0x7fbc
, 0x5f2a
, 0x5f29
, 0x5f2d
, 0x8274
, 0x5f3c
, 0x9b3b
, 0x5c6e
, 0x5981
, 0x5983
, 0x598d
, 0x59a9
, 0x59aa
, 0x59a3
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x5997
, 0x59ca
, 0x59ab
, 0x599e
, 0x59a4
, 0x59d2
, 0x59b2
, 0x59af
, 0x59d7
, 0x59be
, 0x5a05
, 0x5a06
, 0x59dd
, 0x5a08
, 0x59e3
, 0x59d8
, 0x59f9
, 0x5a0c
, 0x5a09
, 0x5a32
, 0x5a34
, 0x5a11
, 0x5a23
, 0x5a13
, 0x5a40
, 0x5a67
, 0x5a4a
, 0x5a55
, 0x5a3c
, 0x5a62
, 0x5a75
, 0x80ec
, 0x5aaa
, 0x5a9b
, 0x5a77
, 0x5a7a
, 0x5abe
, 0x5aeb
, 0x5ab2
, 0x5ad2
, 0x5ad4
, 0x5ab8
, 0x5ae0
, 0x5ae3
, 0x5af1
, 0x5ad6
, 0x5ae6
, 0x5ad8
, 0x5adc
, 0x5b09
, 0x5b17
, 0x5b16
, 0x5b32
, 0x5b37
, 0x5b40
, 0x5c15
, 0x5c1c
, 0x5b5a
, 0x5b65
, 0x5b73
, 0x5b51
, 0x5b53
, 0x5b62
, 0x9a75
, 0x9a77
, 0x9a78
, 0x9a7a
, 0x9a7f
, 0x9a7d
, 0x9a80
, 0x9a81
, 0x9a85
, 0x9a88
, 0x9a8a
, 0x9a90
, 0x9a92
, 0x9a93
, 0x9a96
, 0x9a98
, 0x9a9b
, 0x9a9c
, 0x9a9d
, 0x9a9f
, 0x9aa0
, 0x9aa2
, 0x9aa3
, 0x9aa5
, 0x9aa7
, 0x7e9f
, 0x7ea1
, 0x7ea3
, 0x7ea5
, 0x7ea8
, 0x7ea9
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x7ead
, 0x7eb0
, 0x7ebe
, 0x7ec0
, 0x7ec1
, 0x7ec2
, 0x7ec9
, 0x7ecb
, 0x7ecc
, 0x7ed0
, 0x7ed4
, 0x7ed7
, 0x7edb
, 0x7ee0
, 0x7ee1
, 0x7ee8
, 0x7eeb
, 0x7eee
, 0x7eef
, 0x7ef1
, 0x7ef2
, 0x7f0d
, 0x7ef6
, 0x7efa
, 0x7efb
, 0x7efe
, 0x7f01
, 0x7f02
, 0x7f03
, 0x7f07
, 0x7f08
, 0x7f0b
, 0x7f0c
, 0x7f0f
, 0x7f11
, 0x7f12
, 0x7f17
, 0x7f19
, 0x7f1c
, 0x7f1b
, 0x7f1f
, 0x7f21
, 0x7f22
, 0x7f23
, 0x7f24
, 0x7f25
, 0x7f26
, 0x7f27
, 0x7f2a
, 0x7f2b
, 0x7f2c
, 0x7f2d
, 0x7f2f
, 0x7f30
, 0x7f31
, 0x7f32
, 0x7f33
, 0x7f35
, 0x5e7a
, 0x757f
, 0x5ddb
, 0x753e
, 0x9095
, 0x738e
, 0x7391
, 0x73ae
, 0x73a2
, 0x739f
, 0x73cf
, 0x73c2
, 0x73d1
, 0x73b7
, 0x73b3
, 0x73c0
, 0x73c9
, 0x73c8
, 0x73e5
, 0x73d9
, 0x987c
, 0x740a
, 0x73e9
, 0x73e7
, 0x73de
, 0x73ba
, 0x73f2
, 0x740f
, 0x742a
, 0x745b
, 0x7426
, 0x7425
, 0x7428
, 0x7430
, 0x742e
, 0x742c
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x741b
, 0x741a
, 0x7441
, 0x745c
, 0x7457
, 0x7455
, 0x7459
, 0x7477
, 0x746d
, 0x747e
, 0x749c
, 0x748e
, 0x7480
, 0x7481
, 0x7487
, 0x748b
, 0x749e
, 0x74a8
, 0x74a9
, 0x7490
, 0x74a7
, 0x74d2
, 0x74ba
, 0x97ea
, 0x97eb
, 0x97ec
, 0x674c
, 0x6753
, 0x675e
, 0x6748
, 0x6769
, 0x67a5
, 0x6787
, 0x676a
, 0x6773
, 0x6798
, 0x67a7
, 0x6775
, 0x67a8
, 0x679e
, 0x67ad
, 0x678b
, 0x6777
, 0x677c
, 0x67f0
, 0x6809
, 0x67d8
, 0x680a
, 0x67e9
, 0x67b0
, 0x680c
, 0x67d9
, 0x67b5
, 0x67da
, 0x67b3
, 0x67dd
, 0x6800
, 0x67c3
, 0x67b8
, 0x67e2
, 0x680e
, 0x67c1
, 0x67fd
, 0x6832
, 0x6833
, 0x6860
, 0x6861
, 0x684e
, 0x6862
, 0x6844
, 0x6864
, 0x6883
, 0x681d
, 0x6855
, 0x6866
, 0x6841
, 0x6867
, 0x6840
, 0x683e
, 0x684a
, 0x6849
, 0x6829
, 0x68b5
, 0x688f
, 0x6874
, 0x6877
, 0x6893
, 0x686b
, 0x68c2
, 0x696e
, 0x68fc
, 0x691f
, 0x6920
, 0x68f9
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x6924
, 0x68f0
, 0x690b
, 0x6901
, 0x6957
, 0x68e3
, 0x6910
, 0x6971
, 0x6939
, 0x6960
, 0x6942
, 0x695d
, 0x6984
, 0x696b
, 0x6980
, 0x6998
, 0x6978
, 0x6934
, 0x69cc
, 0x6987
, 0x6988
, 0x69ce
, 0x6989
, 0x6966
, 0x6963
, 0x6979
, 0x699b
, 0x69a7
, 0x69bb
, 0x69ab
, 0x69ad
, 0x69d4
, 0x69b1
, 0x69c1
, 0x69ca
, 0x69df
, 0x6995
, 0x69e0
, 0x698d
, 0x69ff
, 0x6a2f
, 0x69ed
, 0x6a17
, 0x6a18
, 0x6a65
, 0x69f2
, 0x6a44
, 0x6a3e
, 0x6aa0
, 0x6a50
, 0x6a5b
, 0x6a35
, 0x6a8e
, 0x6a79
, 0x6a3d
, 0x6a28
, 0x6a58
, 0x6a7c
, 0x6a91
, 0x6a90
, 0x6aa9
, 0x6a97
, 0x6aab
, 0x7337
, 0x7352
, 0x6b81
, 0x6b82
, 0x6b87
, 0x6b84
, 0x6b92
, 0x6b93
, 0x6b8d
, 0x6b9a
, 0x6b9b
, 0x6ba1
, 0x6baa
, 0x8f6b
, 0x8f6d
, 0x8f71
, 0x8f72
, 0x8f73
, 0x8f75
, 0x8f76
, 0x8f78
, 0x8f77
, 0x8f79
, 0x8f7a
, 0x8f7c
, 0x8f7e
, 0x8f81
, 0x8f82
, 0x8f84
, 0x8f87
, 0x8f8b
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x8f8d
, 0x8f8e
, 0x8f8f
, 0x8f98
, 0x8f9a
, 0x8ece
, 0x620b
, 0x6217
, 0x621b
, 0x621f
, 0x6222
, 0x6221
, 0x6225
, 0x6224
, 0x622c
, 0x81e7
, 0x74ef
, 0x74f4
, 0x74ff
, 0x750f
, 0x7511
, 0x7513
, 0x6534
, 0x65ee
, 0x65ef
, 0x65f0
, 0x660a
, 0x6619
, 0x6772
, 0x6603
, 0x6615
, 0x6600
, 0x7085
, 0x66f7
, 0x661d
, 0x6634
, 0x6631
, 0x6636
, 0x6635
, 0x8006
, 0x665f
, 0x6654
, 0x6641
, 0x664f
, 0x6656
, 0x6661
, 0x6657
, 0x6677
, 0x6684
, 0x668c
, 0x66a7
, 0x669d
, 0x66be
, 0x66db
, 0x66dc
, 0x66e6
, 0x66e9
, 0x8d32
, 0x8d33
, 0x8d36
, 0x8d3b
, 0x8d3d
, 0x8d40
, 0x8d45
, 0x8d46
, 0x8d48
, 0x8d49
, 0x8d47
, 0x8d4d
, 0x8d55
, 0x8d59
, 0x89c7
, 0x89ca
, 0x89cb
, 0x89cc
, 0x89ce
, 0x89cf
, 0x89d0
, 0x89d1
, 0x726e
, 0x729f
, 0x725d
, 0x7266
, 0x726f
, 0x727e
, 0x727f
, 0x7284
, 0x728b
, 0x728d
, 0x728f
, 0x7292
, 0x6308
, 0x6332
, 0x63b0
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x643f
, 0x64d8
, 0x8004
, 0x6bea
, 0x6bf3
, 0x6bfd
, 0x6bf5
, 0x6bf9
, 0x6c05
, 0x6c07
, 0x6c06
, 0x6c0d
, 0x6c15
, 0x6c18
, 0x6c19
, 0x6c1a
, 0x6c21
, 0x6c29
, 0x6c24
, 0x6c2a
, 0x6c32
, 0x6535
, 0x6555
, 0x656b
, 0x724d
, 0x7252
, 0x7256
, 0x7230
, 0x8662
, 0x5216
, 0x809f
, 0x809c
, 0x8093
, 0x80bc
, 0x670a
, 0x80bd
, 0x80b1
, 0x80ab
, 0x80ad
, 0x80b4
, 0x80b7
, 0x80e7
, 0x80e8
, 0x80e9
, 0x80ea
, 0x80db
, 0x80c2
, 0x80c4
, 0x80d9
, 0x80cd
, 0x80d7
, 0x6710
, 0x80dd
, 0x80eb
, 0x80f1
, 0x80f4
, 0x80ed
, 0x810d
, 0x810e
, 0x80f2
, 0x80fc
, 0x6715
, 0x8112
, 0x8c5a
, 0x8136
, 0x811e
, 0x812c
, 0x8118
, 0x8132
, 0x8148
, 0x814c
, 0x8153
, 0x8174
, 0x8159
, 0x815a
, 0x8171
, 0x8160
, 0x8169
, 0x817c
, 0x817d
, 0x816d
, 0x8167
, 0x584d
, 0x5ab5
, 0x8188
, 0x8182
, 0x8191
, 0x6ed5
, 0x81a3
, 0x81aa
, 0x81cc
, 0x6726
, 0x81ca
, 0x81bb
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x81c1
, 0x81a6
, 0x6b24
, 0x6b37
, 0x6b39
, 0x6b43
, 0x6b46
, 0x6b59
, 0x98d1
, 0x98d2
, 0x98d3
, 0x98d5
, 0x98d9
, 0x98da
, 0x6bb3
, 0x5f40
, 0x6bc2
, 0x89f3
, 0x6590
, 0x9f51
, 0x6593
, 0x65bc
, 0x65c6
, 0x65c4
, 0x65c3
, 0x65cc
, 0x65ce
, 0x65d2
, 0x65d6
, 0x7080
, 0x709c
, 0x7096
, 0x709d
, 0x70bb
, 0x70c0
, 0x70b7
, 0x70ab
, 0x70b1
, 0x70e8
, 0x70ca
, 0x7110
, 0x7113
, 0x7116
, 0x712f
, 0x7131
, 0x7173
, 0x715c
, 0x7168
, 0x7145
, 0x7172
, 0x714a
, 0x7178
, 0x717a
, 0x7198
, 0x71b3
, 0x71b5
, 0x71a8
, 0x71a0
, 0x71e0
, 0x71d4
, 0x71e7
, 0x71f9
, 0x721d
, 0x7228
, 0x706c
, 0x7118
, 0x7166
, 0x71b9
, 0x623e
, 0x623d
, 0x6243
, 0x6248
, 0x6249
, 0x793b
, 0x7940
, 0x7946
, 0x7949
, 0x795b
, 0x795c
, 0x7953
, 0x795a
, 0x7962
, 0x7957
, 0x7960
, 0x796f
, 0x7967
, 0x797a
, 0x7985
, 0x798a
, 0x799a
, 0x79a7
, 0x79b3
, 0x5fd1
, 0x5fd0
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x603c
, 0x605d
, 0x605a
, 0x6067
, 0x6041
, 0x6059
, 0x6063
, 0x60ab
, 0x6106
, 0x610d
, 0x615d
, 0x61a9
, 0x619d
, 0x61cb
, 0x61d1
, 0x6206
, 0x8080
, 0x807f
, 0x6c93
, 0x6cf6
, 0x6dfc
, 0x77f6
, 0x77f8
, 0x7800
, 0x7809
, 0x7817
, 0x7818
, 0x7811
, 0x65ab
, 0x782d
, 0x781c
, 0x781d
, 0x7839
, 0x783a
, 0x783b
, 0x781f
, 0x783c
, 0x7825
, 0x782c
, 0x7823
, 0x7829
, 0x784e
, 0x786d
, 0x7856
, 0x7857
, 0x7826
, 0x7850
, 0x7847
, 0x784c
, 0x786a
, 0x789b
, 0x7893
, 0x789a
, 0x7887
, 0x789c
, 0x78a1
, 0x78a3
, 0x78b2
, 0x78b9
, 0x78a5
, 0x78d4
, 0x78d9
, 0x78c9
, 0x78ec
, 0x78f2
, 0x7905
, 0x78f4
, 0x7913
, 0x7924
, 0x791e
, 0x7934
, 0x9f9b
, 0x9ef9
, 0x9efb
, 0x9efc
, 0x76f1
, 0x7704
, 0x770d
, 0x76f9
, 0x7707
, 0x7708
, 0x771a
, 0x7722
, 0x7719
, 0x772d
, 0x7726
, 0x7735
, 0x7738
, 0x7750
, 0x7751
, 0x7747
, 0x7743
, 0x775a
, 0x7768
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x7762
, 0x7765
, 0x777f
, 0x778d
, 0x777d
, 0x7780
, 0x778c
, 0x7791
, 0x779f
, 0x77a0
, 0x77b0
, 0x77b5
, 0x77bd
, 0x753a
, 0x7540
, 0x754e
, 0x754b
, 0x7548
, 0x755b
, 0x7572
, 0x7579
, 0x7583
, 0x7f58
, 0x7f61
, 0x7f5f
, 0x8a48
, 0x7f68
, 0x7f74
, 0x7f71
, 0x7f79
, 0x7f81
, 0x7f7e
, 0x76cd
, 0x76e5
, 0x8832
, 0x9485
, 0x9486
, 0x9487
, 0x948b
, 0x948a
, 0x948c
, 0x948d
, 0x948f
, 0x9490
, 0x9494
, 0x9497
, 0x9495
, 0x949a
, 0x949b
, 0x949c
, 0x94a3
, 0x94a4
, 0x94ab
, 0x94aa
, 0x94ad
, 0x94ac
, 0x94af
, 0x94b0
, 0x94b2
, 0x94b4
, 0x94b6
, 0x94b7
, 0x94b8
, 0x94b9
, 0x94ba
, 0x94bc
, 0x94bd
, 0x94bf
, 0x94c4
, 0x94c8
, 0x94c9
, 0x94ca
, 0x94cb
, 0x94cc
, 0x94cd
, 0x94ce
, 0x94d0
, 0x94d1
, 0x94d2
, 0x94d5
, 0x94d6
, 0x94d7
, 0x94d9
, 0x94d8
, 0x94db
, 0x94de
, 0x94df
, 0x94e0
, 0x94e2
, 0x94e4
, 0x94e5
, 0x94e7
, 0x94e8
, 0x94ea
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x94e9
, 0x94eb
, 0x94ee
, 0x94ef
, 0x94f3
, 0x94f4
, 0x94f5
, 0x94f7
, 0x94f9
, 0x94fc
, 0x94fd
, 0x94ff
, 0x9503
, 0x9502
, 0x9506
, 0x9507
, 0x9509
, 0x950a
, 0x950d
, 0x950e
, 0x950f
, 0x9512
, 0x9513
, 0x9514
, 0x9515
, 0x9516
, 0x9518
, 0x951b
, 0x951d
, 0x951e
, 0x951f
, 0x9522
, 0x952a
, 0x952b
, 0x9529
, 0x952c
, 0x9531
, 0x9532
, 0x9534
, 0x9536
, 0x9537
, 0x9538
, 0x953c
, 0x953e
, 0x953f
, 0x9542
, 0x9535
, 0x9544
, 0x9545
, 0x9546
, 0x9549
, 0x954c
, 0x954e
, 0x954f
, 0x9552
, 0x9553
, 0x9554
, 0x9556
, 0x9557
, 0x9558
, 0x9559
, 0x955b
, 0x955e
, 0x955f
, 0x955d
, 0x9561
, 0x9562
, 0x9564
, 0x9565
, 0x9566
, 0x9567
, 0x9568
, 0x9569
, 0x956a
, 0x956b
, 0x956c
, 0x956f
, 0x9571
, 0x9572
, 0x9573
, 0x953a
, 0x77e7
, 0x77ec
, 0x96c9
, 0x79d5
, 0x79ed
, 0x79e3
, 0x79eb
, 0x7a06
, 0x5d47
, 0x7a03
, 0x7a02
, 0x7a1e
, 0x7a14
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x7a39
, 0x7a37
, 0x7a51
, 0x9ecf
, 0x99a5
, 0x7a70
, 0x7688
, 0x768e
, 0x7693
, 0x7699
, 0x76a4
, 0x74de
, 0x74e0
, 0x752c
, 0x9e20
, 0x9e22
, 0x9e28
, 0x9e29
, 0x9e2a
, 0x9e2b
, 0x9e2c
, 0x9e32
, 0x9e31
, 0x9e36
, 0x9e38
, 0x9e37
, 0x9e39
, 0x9e3a
, 0x9e3e
, 0x9e41
, 0x9e42
, 0x9e44
, 0x9e46
, 0x9e47
, 0x9e48
, 0x9e49
, 0x9e4b
, 0x9e4c
, 0x9e4e
, 0x9e51
, 0x9e55
, 0x9e57
, 0x9e5a
, 0x9e5b
, 0x9e5c
, 0x9e5e
, 0x9e63
, 0x9e66
, 0x9e67
, 0x9e68
, 0x9e69
, 0x9e6a
, 0x9e6b
, 0x9e6c
, 0x9e71
, 0x9e6d
, 0x9e73
, 0x7592
, 0x7594
, 0x7596
, 0x75a0
, 0x759d
, 0x75ac
, 0x75a3
, 0x75b3
, 0x75b4
, 0x75b8
, 0x75c4
, 0x75b1
, 0x75b0
, 0x75c3
, 0x75c2
, 0x75d6
, 0x75cd
, 0x75e3
, 0x75e8
, 0x75e6
, 0x75e4
, 0x75eb
, 0x75e7
, 0x7603
, 0x75f1
, 0x75fc
, 0x75ff
, 0x7610
, 0x7600
, 0x7605
, 0x760c
, 0x7617
, 0x760a
, 0x7625
, 0x7618
, 0x7615
, 0x7619
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x761b
, 0x763c
, 0x7622
, 0x7620
, 0x7640
, 0x762d
, 0x7630
, 0x763f
, 0x7635
, 0x7643
, 0x763e
, 0x7633
, 0x764d
, 0x765e
, 0x7654
, 0x765c
, 0x7656
, 0x766b
, 0x766f
, 0x7fca
, 0x7ae6
, 0x7a78
, 0x7a79
, 0x7a80
, 0x7a86
, 0x7a88
, 0x7a95
, 0x7aa6
, 0x7aa0
, 0x7aac
, 0x7aa8
, 0x7aad
, 0x7ab3
, 0x8864
, 0x8869
, 0x8872
, 0x887d
, 0x887f
, 0x8882
, 0x88a2
, 0x88c6
, 0x88b7
, 0x88bc
, 0x88c9
, 0x88e2
, 0x88ce
, 0x88e3
, 0x88e5
, 0x88f1
, 0x891a
, 0x88fc
, 0x88e8
, 0x88fe
, 0x88f0
, 0x8921
, 0x8919
, 0x8913
, 0x891b
, 0x890a
, 0x8934
, 0x892b
, 0x8936
, 0x8941
, 0x8966
, 0x897b
, 0x758b
, 0x80e5
, 0x76b2
, 0x76b4
, 0x77dc
, 0x8012
, 0x8014
, 0x8016
, 0x801c
, 0x8020
, 0x8022
, 0x8025
, 0x8026
, 0x8027
, 0x8029
, 0x8028
, 0x8031
, 0x800b
, 0x8035
, 0x8043
, 0x8046
, 0x804d
, 0x8052
, 0x8069
, 0x8071
, 0x8983
, 0x9878
, 0x9880
, 0x9883
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x9889
, 0x988c
, 0x988d
, 0x988f
, 0x9894
, 0x989a
, 0x989b
, 0x989e
, 0x989f
, 0x98a1
, 0x98a2
, 0x98a5
, 0x98a6
, 0x864d
, 0x8654
, 0x866c
, 0x866e
, 0x867f
, 0x867a
, 0x867c
, 0x867b
, 0x86a8
, 0x868d
, 0x868b
, 0x86ac
, 0x869d
, 0x86a7
, 0x86a3
, 0x86aa
, 0x8693
, 0x86a9
, 0x86b6
, 0x86c4
, 0x86b5
, 0x86ce
, 0x86b0
, 0x86ba
, 0x86b1
, 0x86af
, 0x86c9
, 0x86cf
, 0x86b4
, 0x86e9
, 0x86f1
, 0x86f2
, 0x86ed
, 0x86f3
, 0x86d0
, 0x8713
, 0x86de
, 0x86f4
, 0x86df
, 0x86d8
, 0x86d1
, 0x8703
, 0x8707
, 0x86f8
, 0x8708
, 0x870a
, 0x870d
, 0x8709
, 0x8723
, 0x873b
, 0x871e
, 0x8725
, 0x872e
, 0x871a
, 0x873e
, 0x8748
, 0x8734
, 0x8731
, 0x8729
, 0x8737
, 0x873f
, 0x8782
, 0x8722
, 0x877d
, 0x877e
, 0x877b
, 0x8760
, 0x8770
, 0x874c
, 0x876e
, 0x878b
, 0x8753
, 0x8763
, 0x877c
, 0x8764
, 0x8759
, 0x8765
, 0x8793
, 0x87af
, 0x87a8
, 0x87d2
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x87c6
, 0x8788
, 0x8785
, 0x87ad
, 0x8797
, 0x8783
, 0x87ab
, 0x87e5
, 0x87ac
, 0x87b5
, 0x87b3
, 0x87cb
, 0x87d3
, 0x87bd
, 0x87d1
, 0x87c0
, 0x87ca
, 0x87db
, 0x87ea
, 0x87e0
, 0x87ee
, 0x8816
, 0x8813
, 0x87fe
, 0x880a
, 0x881b
, 0x8821
, 0x8839
, 0x883c
, 0x7f36
, 0x7f42
, 0x7f44
, 0x7f45
, 0x8210
, 0x7afa
, 0x7afd
, 0x7b08
, 0x7b03
, 0x7b04
, 0x7b15
, 0x7b0a
, 0x7b2b
, 0x7b0f
, 0x7b47
, 0x7b38
, 0x7b2a
, 0x7b19
, 0x7b2e
, 0x7b31
, 0x7b20
, 0x7b25
, 0x7b24
, 0x7b33
, 0x7b3e
, 0x7b1e
, 0x7b58
, 0x7b5a
, 0x7b45
, 0x7b75
, 0x7b4c
, 0x7b5d
, 0x7b60
, 0x7b6e
, 0x7b7b
, 0x7b62
, 0x7b72
, 0x7b71
, 0x7b90
, 0x7ba6
, 0x7ba7
, 0x7bb8
, 0x7bac
, 0x7b9d
, 0x7ba8
, 0x7b85
, 0x7baa
, 0x7b9c
, 0x7ba2
, 0x7bab
, 0x7bb4
, 0x7bd1
, 0x7bc1
, 0x7bcc
, 0x7bdd
, 0x7bda
, 0x7be5
, 0x7be6
, 0x7bea
, 0x7c0c
, 0x7bfe
, 0x7bfc
, 0x7c0f
, 0x7c16
, 0x7c0b
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x7c1f
, 0x7c2a
, 0x7c26
, 0x7c38
, 0x7c41
, 0x7c40
, 0x81fe
, 0x8201
, 0x8202
, 0x8204
, 0x81ec
, 0x8844
, 0x8221
, 0x8222
, 0x8223
, 0x822d
, 0x822f
, 0x8228
, 0x822b
, 0x8238
, 0x823b
, 0x8233
, 0x8234
, 0x823e
, 0x8244
, 0x8249
, 0x824b
, 0x824f
, 0x825a
, 0x825f
, 0x8268
, 0x887e
, 0x8885
, 0x8888
, 0x88d8
, 0x88df
, 0x895e
, 0x7f9d
, 0x7f9f
, 0x7fa7
, 0x7faf
, 0x7fb0
, 0x7fb2
, 0x7c7c
, 0x6549
, 0x7c91
, 0x7c9d
, 0x7c9c
, 0x7c9e
, 0x7ca2
, 0x7cb2
, 0x7cbc
, 0x7cbd
, 0x7cc1
, 0x7cc7
, 0x7ccc
, 0x7ccd
, 0x7cc8
, 0x7cc5
, 0x7cd7
, 0x7ce8
, 0x826e
, 0x66a8
, 0x7fbf
, 0x7fce
, 0x7fd5
, 0x7fe5
, 0x7fe1
, 0x7fe6
, 0x7fe9
, 0x7fee
, 0x7ff3
, 0x7cf8
, 0x7d77
, 0x7da6
, 0x7dae
, 0x7e47
, 0x7e9b
, 0x9eb8
, 0x9eb4
, 0x8d73
, 0x8d84
, 0x8d94
, 0x8d91
, 0x8db1
, 0x8d67
, 0x8d6d
, 0x8c47
, 0x8c49
, 0x914a
, 0x9150
, 0x914e
, 0x914f
, 0x9164
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x9162
, 0x9161
, 0x9170
, 0x9169
, 0x916f
, 0x917d
, 0x917e
, 0x9172
, 0x9174
, 0x9179
, 0x918c
, 0x9185
, 0x9190
, 0x918d
, 0x9191
, 0x91a2
, 0x91a3
, 0x91aa
, 0x91ad
, 0x91ae
, 0x91af
, 0x91b5
, 0x91b4
, 0x91ba
, 0x8c55
, 0x9e7e
, 0x8db8
, 0x8deb
, 0x8e05
, 0x8e59
, 0x8e69
, 0x8db5
, 0x8dbf
, 0x8dbc
, 0x8dba
, 0x8dc4
, 0x8dd6
, 0x8dd7
, 0x8dda
, 0x8dde
, 0x8dce
, 0x8dcf
, 0x8ddb
, 0x8dc6
, 0x8dec
, 0x8df7
, 0x8df8
, 0x8de3
, 0x8df9
, 0x8dfb
, 0x8de4
, 0x8e09
, 0x8dfd
, 0x8e14
, 0x8e1d
, 0x8e1f
, 0x8e2c
, 0x8e2e
, 0x8e23
, 0x8e2f
, 0x8e3a
, 0x8e40
, 0x8e39
, 0x8e35
, 0x8e3d
, 0x8e31
, 0x8e49
, 0x8e41
, 0x8e42
, 0x8e51
, 0x8e52
, 0x8e4a
, 0x8e70
, 0x8e76
, 0x8e7c
, 0x8e6f
, 0x8e74
, 0x8e85
, 0x8e8f
, 0x8e94
, 0x8e90
, 0x8e9c
, 0x8e9e
, 0x8c78
, 0x8c82
, 0x8c8a
, 0x8c85
, 0x8c98
, 0x8c94
, 0x659b
, 0x89d6
, 0x89de
, 0x89da
, 0x89dc
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x89e5
, 0x89eb
, 0x89ef
, 0x8a3e
, 0x8b26
, 0x9753
, 0x96e9
, 0x96f3
, 0x96ef
, 0x9706
, 0x9701
, 0x9708
, 0x970f
, 0x970e
, 0x972a
, 0x972d
, 0x9730
, 0x973e
, 0x9f80
, 0x9f83
, 0x9f85
, 0x9f86
, 0x9f87
, 0x9f88
, 0x9f89
, 0x9f8a
, 0x9f8c
, 0x9efe
, 0x9f0b
, 0x9f0d
, 0x96b9
, 0x96bc
, 0x96bd
, 0x96ce
, 0x96d2
, 0x77bf
, 0x96e0
, 0x928e
, 0x92ae
, 0x92c8
, 0x933e
, 0x936a
, 0x93ca
, 0x938f
, 0x943e
, 0x946b
, 0x9c7f
, 0x9c82
, 0x9c85
, 0x9c86
, 0x9c87
, 0x9c88
, 0x7a23
, 0x9c8b
, 0x9c8e
, 0x9c90
, 0x9c91
, 0x9c92
, 0x9c94
, 0x9c95
, 0x9c9a
, 0x9c9b
, 0x9c9e
, 0x9c9f
, 0x9ca0
, 0x9ca1
, 0x9ca2
, 0x9ca3
, 0x9ca5
, 0x9ca6
, 0x9ca7
, 0x9ca8
, 0x9ca9
, 0x9cab
, 0x9cad
, 0x9cae
, 0x9cb0
, 0x9cb1
, 0x9cb2
, 0x9cb3
, 0x9cb4
, 0x9cb5
, 0x9cb6
, 0x9cb7
, 0x9cba
, 0x9cbb
, 0x9cbc
, 0x9cbd
, 0x9cc4
, 0x9cc5
, 0x9cc6
, 0x9cc7
, 0x9cca
, 0x9ccb
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x0000
, 0x9ccc
, 0x9ccd
, 0x9cce
, 0x9ccf
, 0x9cd0
, 0x9cd3
, 0x9cd4
, 0x9cd5
, 0x9cd7
, 0x9cd8
, 0x9cd9
, 0x9cdc
, 0x9cdd
, 0x9cdf
, 0x9ce2
, 0x977c
, 0x9785
, 0x9791
, 0x9792
, 0x9794
, 0x97af
, 0x97ab
, 0x97a3
, 0x97b2
, 0x97b4
, 0x9ab1
, 0x9ab0
, 0x9ab7
, 0x9e58
, 0x9ab6
, 0x9aba
, 0x9abc
, 0x9ac1
, 0x9ac0
, 0x9ac5
, 0x9ac2
, 0x9acb
, 0x9acc
, 0x9ad1
, 0x9b45
, 0x9b43
, 0x9b47
, 0x9b49
, 0x9b48
, 0x9b4d
, 0x9b51
, 0x98e8
, 0x990d
, 0x992e
, 0x9955
, 0x9954
, 0x9adf
, 0x9ae1
, 0x9ae6
, 0x9aef
, 0x9aeb
, 0x9afb
, 0x9aed
, 0x9af9
, 0x9b08
, 0x9b0f
, 0x9b13
, 0x9b1f
, 0x9b23
, 0x9ebd
, 0x9ebe
, 0x7e3b
, 0x9e82
, 0x9e87
, 0x9e88
, 0x9e8b
, 0x9e92
, 0x93d6
, 0x9e9d
, 0x9e9f
, 0x9edb
, 0x9edc
, 0x9edd
, 0x9ee0
, 0x9edf
, 0x9ee2
, 0x9ee9
, 0x9ee7
, 0x9ee5
, 0x9eea
, 0x9eef
, 0x9f22
, 0x9f2c
, 0x9f2f
, 0x9f39
, 0x9f37
, 0x9f3d
, 0x9f3e
, 0x9f44
};
static tb_uint16_t g_charset_ucs4_to_gb2312_table_data[][2] =
{
// ucs4, gb2312
{0x00a4, 0xa1e8}, /* '¤' -> 164 */
{0x00a7, 0xa1ec}, /* '§' -> 167 */
{0x00a8, 0xa1a7}, /* '¨' -> 168 */
{0x00b0, 0xa1e3}, /* '°' -> 176 */
{0x00b1, 0xa1c0}, /* '±' -> 177 */
{0x00d7, 0xa1c1}, /* '×' -> 215 */
{0x00e0, 0xa8a4}, /* 'à' -> 224 */
{0x00e1, 0xa8a2}, /* 'á' -> 225 */
{0x00e8, 0xa8a8}, /* 'è' -> 232 */
{0x00e9, 0xa8a6}, /* 'é' -> 233 */
{0x00ea, 0xa8ba}, /* 'ê' -> 234 */
{0x00ec, 0xa8ac}, /* 'ì' -> 236 */
{0x00ed, 0xa8aa}, /* 'í' -> 237 */
{0x00f2, 0xa8b0}, /* 'ò' -> 242 */
{0x00f3, 0xa8ae}, /* 'ó' -> 243 */
{0x00f7, 0xa1c2}, /* '÷' -> 247 */
{0x00f9, 0xa8b4}, /* 'ù' -> 249 */
{0x00fa, 0xa8b2}, /* 'ú' -> 250 */
{0x00fc, 0xa8b9}, /* 'ü' -> 252 */
{0x0101, 0xa8a1}, /* 'ā' -> 257 */
{0x0113, 0xa8a5}, /* 'ē' -> 275 */
{0x011b, 0xa8a7}, /* 'ě' -> 283 */
{0x012b, 0xa8a9}, /* 'ī' -> 299 */
{0x014d, 0xa8ad}, /* 'ō' -> 333 */
{0x016b, 0xa8b1}, /* 'ū' -> 363 */
{0x01ce, 0xa8a3}, /* 'ǎ' -> 462 */
{0x01d0, 0xa8ab}, /* 'ǐ' -> 464 */
{0x01d2, 0xa8af}, /* 'ǒ' -> 466 */
{0x01d4, 0xa8b3}, /* 'ǔ' -> 468 */
{0x01d6, 0xa8b5}, /* 'ǖ' -> 470 */
{0x01d8, 0xa8b6}, /* 'ǘ' -> 472 */
{0x01da, 0xa8b7}, /* 'ǚ' -> 474 */
{0x01dc, 0xa8b8}, /* 'ǜ' -> 476 */
{0x02c7, 0xa1a6}, /* 'ˇ' -> 711 */
{0x02c9, 0xa1a5}, /* 'ˉ' -> 713 */
{0x0391, 0xa6a1}, /* 'α' -> 913 */
{0x0392, 0xa6a2}, /* 'β' -> 914 */
{0x0393, 0xa6a3}, /* 'γ' -> 915 */
{0x0394, 0xa6a4}, /* 'δ' -> 916 */
{0x0395, 0xa6a5}, /* 'ε' -> 917 */
{0x0396, 0xa6a6}, /* 'ζ' -> 918 */
{0x0397, 0xa6a7}, /* 'η' -> 919 */
{0x0398, 0xa6a8}, /* 'θ' -> 920 */
{0x0399, 0xa6a9}, /* 'ι' -> 921 */
{0x039a, 0xa6aa}, /* 'κ' -> 922 */
{0x039b, 0xa6ab}, /* 'λ' -> 923 */
{0x039c, 0xa6ac}, /* 'μ' -> 924 */
{0x039d, 0xa6ad}, /* 'ν' -> 925 */
{0x039e, 0xa6ae}, /* 'ξ' -> 926 */
{0x039f, 0xa6af}, /* 'ο' -> 927 */
{0x03a0, 0xa6b0}, /* 'π' -> 928 */
{0x03a1, 0xa6b1}, /* 'ρ' -> 929 */
{0x03a3, 0xa6b2}, /* 'σ' -> 931 */
{0x03a4, 0xa6b3}, /* 'τ' -> 932 */
{0x03a5, 0xa6b4}, /* 'υ' -> 933 */
{0x03a6, 0xa6b5}, /* 'φ' -> 934 */
{0x03a7, 0xa6b6}, /* 'χ' -> 935 */
{0x03a8, 0xa6b7}, /* 'ψ' -> 936 */
{0x03a9, 0xa6b8}, /* 'ω' -> 937 */
{0x03b1, 0xa6c1}, /* 'α' -> 945 */
{0x03b2, 0xa6c2}, /* 'β' -> 946 */
{0x03b3, 0xa6c3}, /* 'γ' -> 947 */
{0x03b4, 0xa6c4}, /* 'δ' -> 948 */
{0x03b5, 0xa6c5}, /* 'ε' -> 949 */
{0x03b6, 0xa6c6}, /* 'ζ' -> 950 */
{0x03b7, 0xa6c7}, /* 'η' -> 951 */
{0x03b8, 0xa6c8}, /* 'θ' -> 952 */
{0x03b9, 0xa6c9}, /* 'ι' -> 953 */
{0x03ba, 0xa6ca}, /* 'κ' -> 954 */
{0x03bb, 0xa6cb}, /* 'λ' -> 955 */
{0x03bc, 0xa6cc}, /* 'μ' -> 956 */
{0x03bd, 0xa6cd}, /* 'ν' -> 957 */
{0x03be, 0xa6ce}, /* 'ξ' -> 958 */
{0x03bf, 0xa6cf}, /* 'ο' -> 959 */
{0x03c0, 0xa6d0}, /* 'π' -> 960 */
{0x03c1, 0xa6d1}, /* 'ρ' -> 961 */
{0x03c3, 0xa6d2}, /* 'σ' -> 963 */
{0x03c4, 0xa6d3}, /* 'τ' -> 964 */
{0x03c5, 0xa6d4}, /* 'υ' -> 965 */
{0x03c6, 0xa6d5}, /* 'φ' -> 966 */
{0x03c7, 0xa6d6}, /* 'χ' -> 967 */
{0x03c8, 0xa6d7}, /* 'ψ' -> 968 */
{0x03c9, 0xa6d8}, /* 'ω' -> 969 */
{0x0401, 0xa7a7}, /* 'ё' -> 1025 */
{0x0410, 0xa7a1}, /* 'а' -> 1040 */
{0x0411, 0xa7a2}, /* 'б' -> 1041 */
{0x0412, 0xa7a3}, /* 'в' -> 1042 */
{0x0413, 0xa7a4}, /* 'г' -> 1043 */
{0x0414, 0xa7a5}, /* 'д' -> 1044 */
{0x0415, 0xa7a6}, /* 'е' -> 1045 */
{0x0416, 0xa7a8}, /* 'ж' -> 1046 */
{0x0417, 0xa7a9}, /* 'з' -> 1047 */
{0x0418, 0xa7aa}, /* 'и' -> 1048 */
{0x0419, 0xa7ab}, /* 'й' -> 1049 */
{0x041a, 0xa7ac}, /* 'к' -> 1050 */
{0x041b, 0xa7ad}, /* 'л' -> 1051 */
{0x041c, 0xa7ae}, /* 'м' -> 1052 */
{0x041d, 0xa7af}, /* 'н' -> 1053 */
{0x041e, 0xa7b0}, /* 'о' -> 1054 */
{0x041f, 0xa7b1}, /* 'п' -> 1055 */
{0x0420, 0xa7b2}, /* 'р' -> 1056 */
{0x0421, 0xa7b3}, /* 'с' -> 1057 */
{0x0422, 0xa7b4}, /* 'т' -> 1058 */
{0x0423, 0xa7b5}, /* 'у' -> 1059 */
{0x0424, 0xa7b6}, /* 'ф' -> 1060 */
{0x0425, 0xa7b7}, /* 'х' -> 1061 */
{0x0426, 0xa7b8}, /* 'ц' -> 1062 */
{0x0427, 0xa7b9}, /* 'ч' -> 1063 */
{0x0428, 0xa7ba}, /* 'ш' -> 1064 */
{0x0429, 0xa7bb}, /* 'щ' -> 1065 */
{0x042a, 0xa7bc}, /* 'ъ' -> 1066 */
{0x042b, 0xa7bd}, /* 'ы' -> 1067 */
{0x042c, 0xa7be}, /* 'ь' -> 1068 */
{0x042d, 0xa7bf}, /* 'э' -> 1069 */
{0x042e, 0xa7c0}, /* 'ю' -> 1070 */
{0x042f, 0xa7c1}, /* 'я' -> 1071 */
{0x0430, 0xa7d1}, /* 'а' -> 1072 */
{0x0431, 0xa7d2}, /* 'б' -> 1073 */
{0x0432, 0xa7d3}, /* 'в' -> 1074 */
{0x0433, 0xa7d4}, /* 'г' -> 1075 */
{0x0434, 0xa7d5}, /* 'д' -> 1076 */
{0x0435, 0xa7d6}, /* 'е' -> 1077 */
{0x0436, 0xa7d8}, /* 'ж' -> 1078 */
{0x0437, 0xa7d9}, /* 'з' -> 1079 */
{0x0438, 0xa7da}, /* 'и' -> 1080 */
{0x0439, 0xa7db}, /* 'й' -> 1081 */
{0x043a, 0xa7dc}, /* 'к' -> 1082 */
{0x043b, 0xa7dd}, /* 'л' -> 1083 */
{0x043c, 0xa7de}, /* 'м' -> 1084 */
{0x043d, 0xa7df}, /* 'н' -> 1085 */
{0x043e, 0xa7e0}, /* 'о' -> 1086 */
{0x043f, 0xa7e1}, /* 'п' -> 1087 */
{0x0440, 0xa7e2}, /* 'р' -> 1088 */
{0x0441, 0xa7e3}, /* 'с' -> 1089 */
{0x0442, 0xa7e4}, /* 'т' -> 1090 */
{0x0443, 0xa7e5}, /* 'у' -> 1091 */
{0x0444, 0xa7e6}, /* 'ф' -> 1092 */
{0x0445, 0xa7e7}, /* 'х' -> 1093 */
{0x0446, 0xa7e8}, /* 'ц' -> 1094 */
{0x0447, 0xa7e9}, /* 'ч' -> 1095 */
{0x0448, 0xa7ea}, /* 'ш' -> 1096 */
{0x0449, 0xa7eb}, /* 'щ' -> 1097 */
{0x044a, 0xa7ec}, /* 'ъ' -> 1098 */
{0x044b, 0xa7ed}, /* 'ы' -> 1099 */
{0x044c, 0xa7ee}, /* 'ь' -> 1100 */
{0x044d, 0xa7ef}, /* 'э' -> 1101 */
{0x044e, 0xa7f0}, /* 'ю' -> 1102 */
{0x044f, 0xa7f1}, /* 'я' -> 1103 */
{0x0451, 0xa7d7}, /* 'ё' -> 1105 */
{0x2015, 0xa1aa}, /* '―' -> 8213 */
{0x2016, 0xa1ac}, /* '‖' -> 8214 */
{0x2018, 0xa1ae}, /* '‘' -> 8216 */
{0x2019, 0xa1af}, /* '’' -> 8217 */
{0x201c, 0xa1b0}, /* '“' -> 8220 */
{0x201d, 0xa1b1}, /* '”' -> 8221 */
{0x2026, 0xa1ad}, /* '…' -> 8230 */
{0x2030, 0xa1eb}, /* '‰' -> 8240 */
{0x2032, 0xa1e4}, /* '′' -> 8242 */
{0x2033, 0xa1e5}, /* '″' -> 8243 */
{0x203b, 0xa1f9}, /* '※' -> 8251 */
{0x2103, 0xa1e6}, /* '℃' -> 8451 */
{0x2116, 0xa1ed}, /* '№' -> 8470 */
{0x2160, 0xa2f1}, /* 'ⅰ' -> 8544 */
{0x2161, 0xa2f2}, /* 'ⅱ' -> 8545 */
{0x2162, 0xa2f3}, /* 'ⅲ' -> 8546 */
{0x2163, 0xa2f4}, /* 'ⅳ' -> 8547 */
{0x2164, 0xa2f5}, /* 'ⅴ' -> 8548 */
{0x2165, 0xa2f6}, /* 'ⅵ' -> 8549 */
{0x2166, 0xa2f7}, /* 'ⅶ' -> 8550 */
{0x2167, 0xa2f8}, /* 'ⅷ' -> 8551 */
{0x2168, 0xa2f9}, /* 'ⅸ' -> 8552 */
{0x2169, 0xa2fa}, /* 'ⅹ' -> 8553 */
{0x216a, 0xa2fb}, /* 'ⅺ' -> 8554 */
{0x216b, 0xa2fc}, /* 'ⅻ' -> 8555 */
{0x2190, 0xa1fb}, /* '←' -> 8592 */
{0x2191, 0xa1fc}, /* '↑' -> 8593 */
{0x2192, 0xa1fa}, /* '→' -> 8594 */
{0x2193, 0xa1fd}, /* '↓' -> 8595 */
{0x2208, 0xa1ca}, /* '∈' -> 8712 */
{0x220f, 0xa1c7}, /* '∏' -> 8719 */
{0x2211, 0xa1c6}, /* '∑' -> 8721 */
{0x221a, 0xa1cc}, /* '√' -> 8730 */
{0x221d, 0xa1d8}, /* '∝' -> 8733 */
{0x221e, 0xa1de}, /* '∞' -> 8734 */
{0x2220, 0xa1cf}, /* '∠' -> 8736 */
{0x2225, 0xa1ce}, /* '∥' -> 8741 */
{0x2227, 0xa1c4}, /* '∧' -> 8743 */
{0x2228, 0xa1c5}, /* '∨' -> 8744 */
{0x2229, 0xa1c9}, /* '∩' -> 8745 */
{0x222a, 0xa1c8}, /* '∪' -> 8746 */
{0x222b, 0xa1d2}, /* '∫' -> 8747 */
{0x222e, 0xa1d3}, /* '∮' -> 8750 */
{0x2234, 0xa1e0}, /* '∴' -> 8756 */
{0x2235, 0xa1df}, /* '∵' -> 8757 */
{0x2236, 0xa1c3}, /* '∶' -> 8758 */
{0x2237, 0xa1cb}, /* '∷' -> 8759 */
{0x223d, 0xa1d7}, /* '∽' -> 8765 */
{0x2248, 0xa1d6}, /* '≈' -> 8776 */
{0x224c, 0xa1d5}, /* '≌' -> 8780 */
{0x2260, 0xa1d9}, /* '≠' -> 8800 */
{0x2261, 0xa1d4}, /* '≡' -> 8801 */
{0x2264, 0xa1dc}, /* '≤' -> 8804 */
{0x2265, 0xa1dd}, /* '≥' -> 8805 */
{0x226e, 0xa1da}, /* '≮' -> 8814 */
{0x226f, 0xa1db}, /* '≯' -> 8815 */
{0x2299, 0xa1d1}, /* '⊙' -> 8857 */
{0x22a5, 0xa1cd}, /* '⊥' -> 8869 */
{0x2312, 0xa1d0}, /* '⌒' -> 8978 */
{0x2460, 0xa2d9}, /* '①' -> 9312 */
{0x2461, 0xa2da}, /* '②' -> 9313 */
{0x2462, 0xa2db}, /* '③' -> 9314 */
{0x2463, 0xa2dc}, /* '④' -> 9315 */
{0x2464, 0xa2dd}, /* '⑤' -> 9316 */
{0x2465, 0xa2de}, /* '⑥' -> 9317 */
{0x2466, 0xa2df}, /* '⑦' -> 9318 */
{0x2467, 0xa2e0}, /* '⑧' -> 9319 */
{0x2468, 0xa2e1}, /* '⑨' -> 9320 */
{0x2469, 0xa2e2}, /* '⑩' -> 9321 */
{0x2474, 0xa2c5}, /* '⑴' -> 9332 */
{0x2475, 0xa2c6}, /* '⑵' -> 9333 */
{0x2476, 0xa2c7}, /* '⑶' -> 9334 */
{0x2477, 0xa2c8}, /* '⑷' -> 9335 */
{0x2478, 0xa2c9}, /* '⑸' -> 9336 */
{0x2479, 0xa2ca}, /* '⑹' -> 9337 */
{0x247a, 0xa2cb}, /* '⑺' -> 9338 */
{0x247b, 0xa2cc}, /* '⑻' -> 9339 */
{0x247c, 0xa2cd}, /* '⑼' -> 9340 */
{0x247d, 0xa2ce}, /* '⑽' -> 9341 */
{0x247e, 0xa2cf}, /* '⑾' -> 9342 */
{0x247f, 0xa2d0}, /* '⑿' -> 9343 */
{0x2480, 0xa2d1}, /* '⒀' -> 9344 */
{0x2481, 0xa2d2}, /* '⒁' -> 9345 */
{0x2482, 0xa2d3}, /* '⒂' -> 9346 */
{0x2483, 0xa2d4}, /* '⒃' -> 9347 */
{0x2484, 0xa2d5}, /* '⒄' -> 9348 */
{0x2485, 0xa2d6}, /* '⒅' -> 9349 */
{0x2486, 0xa2d7}, /* '⒆' -> 9350 */
{0x2487, 0xa2d8}, /* '⒇' -> 9351 */
{0x2488, 0xa2b1}, /* '⒈' -> 9352 */
{0x2489, 0xa2b2}, /* '⒉' -> 9353 */
{0x248a, 0xa2b3}, /* '⒊' -> 9354 */
{0x248b, 0xa2b4}, /* '⒋' -> 9355 */
{0x248c, 0xa2b5}, /* '⒌' -> 9356 */
{0x248d, 0xa2b6}, /* '⒍' -> 9357 */
{0x248e, 0xa2b7}, /* '⒎' -> 9358 */
{0x248f, 0xa2b8}, /* '⒏' -> 9359 */
{0x2490, 0xa2b9}, /* '⒐' -> 9360 */
{0x2491, 0xa2ba}, /* '⒑' -> 9361 */
{0x2492, 0xa2bb}, /* '⒒' -> 9362 */
{0x2493, 0xa2bc}, /* '⒓' -> 9363 */
{0x2494, 0xa2bd}, /* '⒔' -> 9364 */
{0x2495, 0xa2be}, /* '⒕' -> 9365 */
{0x2496, 0xa2bf}, /* '⒖' -> 9366 */
{0x2497, 0xa2c0}, /* '⒗' -> 9367 */
{0x2498, 0xa2c1}, /* '⒘' -> 9368 */
{0x2499, 0xa2c2}, /* '⒙' -> 9369 */
{0x249a, 0xa2c3}, /* '⒚' -> 9370 */
{0x249b, 0xa2c4}, /* '⒛' -> 9371 */
{0x2500, 0xa9a4}, /* '─' -> 9472 */
{0x2501, 0xa9a5}, /* '━' -> 9473 */
{0x2502, 0xa9a6}, /* '│' -> 9474 */
{0x2503, 0xa9a7}, /* '┃' -> 9475 */
{0x2504, 0xa9a8}, /* '┄' -> 9476 */
{0x2505, 0xa9a9}, /* '┅' -> 9477 */
{0x2506, 0xa9aa}, /* '┆' -> 9478 */
{0x2507, 0xa9ab}, /* '┇' -> 9479 */
{0x2508, 0xa9ac}, /* '┈' -> 9480 */
{0x2509, 0xa9ad}, /* '┉' -> 9481 */
{0x250a, 0xa9ae}, /* '┊' -> 9482 */
{0x250b, 0xa9af}, /* '┋' -> 9483 */
{0x250c, 0xa9b0}, /* '┌' -> 9484 */
{0x250d, 0xa9b1}, /* '┍' -> 9485 */
{0x250e, 0xa9b2}, /* '┎' -> 9486 */
{0x250f, 0xa9b3}, /* '┏' -> 9487 */
{0x2510, 0xa9b4}, /* '┐' -> 9488 */
{0x2511, 0xa9b5}, /* '┑' -> 9489 */
{0x2512, 0xa9b6}, /* '┒' -> 9490 */
{0x2513, 0xa9b7}, /* '┓' -> 9491 */
{0x2514, 0xa9b8}, /* '└' -> 9492 */
{0x2515, 0xa9b9}, /* '┕' -> 9493 */
{0x2516, 0xa9ba}, /* '┖' -> 9494 */
{0x2517, 0xa9bb}, /* '┗' -> 9495 */
{0x2518, 0xa9bc}, /* '┘' -> 9496 */
{0x2519, 0xa9bd}, /* '┙' -> 9497 */
{0x251a, 0xa9be}, /* '┚' -> 9498 */
{0x251b, 0xa9bf}, /* '┛' -> 9499 */
{0x251c, 0xa9c0}, /* '├' -> 9500 */
{0x251d, 0xa9c1}, /* '┝' -> 9501 */
{0x251e, 0xa9c2}, /* '┞' -> 9502 */
{0x251f, 0xa9c3}, /* '┟' -> 9503 */
{0x2520, 0xa9c4}, /* '┠' -> 9504 */
{0x2521, 0xa9c5}, /* '┡' -> 9505 */
{0x2522, 0xa9c6}, /* '┢' -> 9506 */
{0x2523, 0xa9c7}, /* '┣' -> 9507 */
{0x2524, 0xa9c8}, /* '┤' -> 9508 */
{0x2525, 0xa9c9}, /* '┥' -> 9509 */
{0x2526, 0xa9ca}, /* '┦' -> 9510 */
{0x2527, 0xa9cb}, /* '┧' -> 9511 */
{0x2528, 0xa9cc}, /* '┨' -> 9512 */
{0x2529, 0xa9cd}, /* '┩' -> 9513 */
{0x252a, 0xa9ce}, /* '┪' -> 9514 */
{0x252b, 0xa9cf}, /* '┫' -> 9515 */
{0x252c, 0xa9d0}, /* '┬' -> 9516 */
{0x252d, 0xa9d1}, /* '┭' -> 9517 */
{0x252e, 0xa9d2}, /* '┮' -> 9518 */
{0x252f, 0xa9d3}, /* '┯' -> 9519 */
{0x2530, 0xa9d4}, /* '┰' -> 9520 */
{0x2531, 0xa9d5}, /* '┱' -> 9521 */
{0x2532, 0xa9d6}, /* '┲' -> 9522 */
{0x2533, 0xa9d7}, /* '┳' -> 9523 */
{0x2534, 0xa9d8}, /* '┴' -> 9524 */
{0x2535, 0xa9d9}, /* '┵' -> 9525 */
{0x2536, 0xa9da}, /* '┶' -> 9526 */
{0x2537, 0xa9db}, /* '┷' -> 9527 */
{0x2538, 0xa9dc}, /* '┸' -> 9528 */
{0x2539, 0xa9dd}, /* '┹' -> 9529 */
{0x253a, 0xa9de}, /* '┺' -> 9530 */
{0x253b, 0xa9df}, /* '┻' -> 9531 */
{0x253c, 0xa9e0}, /* '┼' -> 9532 */
{0x253d, 0xa9e1}, /* '┽' -> 9533 */
{0x253e, 0xa9e2}, /* '┾' -> 9534 */
{0x253f, 0xa9e3}, /* '┿' -> 9535 */
{0x2540, 0xa9e4}, /* '╀' -> 9536 */
{0x2541, 0xa9e5}, /* '╁' -> 9537 */
{0x2542, 0xa9e6}, /* '╂' -> 9538 */
{0x2543, 0xa9e7}, /* '╃' -> 9539 */
{0x2544, 0xa9e8}, /* '╄' -> 9540 */
{0x2545, 0xa9e9}, /* '╅' -> 9541 */
{0x2546, 0xa9ea}, /* '╆' -> 9542 */
{0x2547, 0xa9eb}, /* '╇' -> 9543 */
{0x2548, 0xa9ec}, /* '╈' -> 9544 */
{0x2549, 0xa9ed}, /* '╉' -> 9545 */
{0x254a, 0xa9ee}, /* '╊' -> 9546 */
{0x254b, 0xa9ef}, /* '╋' -> 9547 */
{0x25a0, 0xa1f6}, /* '■' -> 9632 */
{0x25a1, 0xa1f5}, /* '□' -> 9633 */
{0x25b2, 0xa1f8}, /* '▲' -> 9650 */
{0x25b3, 0xa1f7}, /* '△' -> 9651 */
{0x25c6, 0xa1f4}, /* '◆' -> 9670 */
{0x25c7, 0xa1f3}, /* '◇' -> 9671 */
{0x25cb, 0xa1f0}, /* '○' -> 9675 */
{0x25ce, 0xa1f2}, /* '◎' -> 9678 */
{0x25cf, 0xa1f1}, /* '●' -> 9679 */
{0x2605, 0xa1ef}, /* '★' -> 9733 */
{0x2606, 0xa1ee}, /* '☆' -> 9734 */
{0x2640, 0xa1e2}, /* '♀' -> 9792 */
{0x2642, 0xa1e1}, /* '♂' -> 9794 */
{0x3000, 0xa1a1}, /* ' ' -> 12288 */
{0x3001, 0xa1a2}, /* '、' -> 12289 */
{0x3002, 0xa1a3}, /* '。' -> 12290 */
{0x3003, 0xa1a8}, /* '〃' -> 12291 */
{0x3005, 0xa1a9}, /* '々' -> 12293 */
{0x3008, 0xa1b4}, /* '〈' -> 12296 */
{0x3009, 0xa1b5}, /* '〉' -> 12297 */
{0x300a, 0xa1b6}, /* '《' -> 12298 */
{0x300b, 0xa1b7}, /* '》' -> 12299 */
{0x300c, 0xa1b8}, /* '「' -> 12300 */
{0x300d, 0xa1b9}, /* '」' -> 12301 */
{0x300e, 0xa1ba}, /* '『' -> 12302 */
{0x300f, 0xa1bb}, /* '』' -> 12303 */
{0x3010, 0xa1be}, /* '【' -> 12304 */
{0x3011, 0xa1bf}, /* '】' -> 12305 */
{0x3013, 0xa1fe}, /* '〓' -> 12307 */
{0x3014, 0xa1b2}, /* '〔' -> 12308 */
{0x3015, 0xa1b3}, /* '〕' -> 12309 */
{0x3016, 0xa1bc}, /* '〖' -> 12310 */
{0x3017, 0xa1bd}, /* '〗' -> 12311 */
{0x3041, 0xa4a1}, /* 'ぁ' -> 12353 */
{0x3042, 0xa4a2}, /* 'あ' -> 12354 */
{0x3043, 0xa4a3}, /* 'ぃ' -> 12355 */
{0x3044, 0xa4a4}, /* 'い' -> 12356 */
{0x3045, 0xa4a5}, /* 'ぅ' -> 12357 */
{0x3046, 0xa4a6}, /* 'う' -> 12358 */
{0x3047, 0xa4a7}, /* 'ぇ' -> 12359 */
{0x3048, 0xa4a8}, /* 'え' -> 12360 */
{0x3049, 0xa4a9}, /* 'ぉ' -> 12361 */
{0x304a, 0xa4aa}, /* 'お' -> 12362 */
{0x304b, 0xa4ab}, /* 'か' -> 12363 */
{0x304c, 0xa4ac}, /* 'が' -> 12364 */
{0x304d, 0xa4ad}, /* 'き' -> 12365 */
{0x304e, 0xa4ae}, /* 'ぎ' -> 12366 */
{0x304f, 0xa4af}, /* 'く' -> 12367 */
{0x3050, 0xa4b0}, /* 'ぐ' -> 12368 */
{0x3051, 0xa4b1}, /* 'け' -> 12369 */
{0x3052, 0xa4b2}, /* 'げ' -> 12370 */
{0x3053, 0xa4b3}, /* 'こ' -> 12371 */
{0x3054, 0xa4b4}, /* 'ご' -> 12372 */
{0x3055, 0xa4b5}, /* 'さ' -> 12373 */
{0x3056, 0xa4b6}, /* 'ざ' -> 12374 */
{0x3057, 0xa4b7}, /* 'し' -> 12375 */
{0x3058, 0xa4b8}, /* 'じ' -> 12376 */
{0x3059, 0xa4b9}, /* 'す' -> 12377 */
{0x305a, 0xa4ba}, /* 'ず' -> 12378 */
{0x305b, 0xa4bb}, /* 'せ' -> 12379 */
{0x305c, 0xa4bc}, /* 'ぜ' -> 12380 */
{0x305d, 0xa4bd}, /* 'そ' -> 12381 */
{0x305e, 0xa4be}, /* 'ぞ' -> 12382 */
{0x305f, 0xa4bf}, /* 'た' -> 12383 */
{0x3060, 0xa4c0}, /* 'だ' -> 12384 */
{0x3061, 0xa4c1}, /* 'ち' -> 12385 */
{0x3062, 0xa4c2}, /* 'ぢ' -> 12386 */
{0x3063, 0xa4c3}, /* 'っ' -> 12387 */
{0x3064, 0xa4c4}, /* 'つ' -> 12388 */
{0x3065, 0xa4c5}, /* 'づ' -> 12389 */
{0x3066, 0xa4c6}, /* 'て' -> 12390 */
{0x3067, 0xa4c7}, /* 'で' -> 12391 */
{0x3068, 0xa4c8}, /* 'と' -> 12392 */
{0x3069, 0xa4c9}, /* 'ど' -> 12393 */
{0x306a, 0xa4ca}, /* 'な' -> 12394 */
{0x306b, 0xa4cb}, /* 'に' -> 12395 */
{0x306c, 0xa4cc}, /* 'ぬ' -> 12396 */
{0x306d, 0xa4cd}, /* 'ね' -> 12397 */
{0x306e, 0xa4ce}, /* 'の' -> 12398 */
{0x306f, 0xa4cf}, /* 'は' -> 12399 */
{0x3070, 0xa4d0}, /* 'ば' -> 12400 */
{0x3071, 0xa4d1}, /* 'ぱ' -> 12401 */
{0x3072, 0xa4d2}, /* 'ひ' -> 12402 */
{0x3073, 0xa4d3}, /* 'び' -> 12403 */
{0x3074, 0xa4d4}, /* 'ぴ' -> 12404 */
{0x3075, 0xa4d5}, /* 'ふ' -> 12405 */
{0x3076, 0xa4d6}, /* 'ぶ' -> 12406 */
{0x3077, 0xa4d7}, /* 'ぷ' -> 12407 */
{0x3078, 0xa4d8}, /* 'へ' -> 12408 */
{0x3079, 0xa4d9}, /* 'べ' -> 12409 */
{0x307a, 0xa4da}, /* 'ぺ' -> 12410 */
{0x307b, 0xa4db}, /* 'ほ' -> 12411 */
{0x307c, 0xa4dc}, /* 'ぼ' -> 12412 */
{0x307d, 0xa4dd}, /* 'ぽ' -> 12413 */
{0x307e, 0xa4de}, /* 'ま' -> 12414 */
{0x307f, 0xa4df}, /* 'み' -> 12415 */
{0x3080, 0xa4e0}, /* 'む' -> 12416 */
{0x3081, 0xa4e1}, /* 'め' -> 12417 */
{0x3082, 0xa4e2}, /* 'も' -> 12418 */
{0x3083, 0xa4e3}, /* 'ゃ' -> 12419 */
{0x3084, 0xa4e4}, /* 'や' -> 12420 */
{0x3085, 0xa4e5}, /* 'ゅ' -> 12421 */
{0x3086, 0xa4e6}, /* 'ゆ' -> 12422 */
{0x3087, 0xa4e7}, /* 'ょ' -> 12423 */
{0x3088, 0xa4e8}, /* 'よ' -> 12424 */
{0x3089, 0xa4e9}, /* 'ら' -> 12425 */
{0x308a, 0xa4ea}, /* 'り' -> 12426 */
{0x308b, 0xa4eb}, /* 'る' -> 12427 */
{0x308c, 0xa4ec}, /* 'れ' -> 12428 */
{0x308d, 0xa4ed}, /* 'ろ' -> 12429 */
{0x308e, 0xa4ee}, /* 'ゎ' -> 12430 */
{0x308f, 0xa4ef}, /* 'わ' -> 12431 */
{0x3090, 0xa4f0}, /* 'ゐ' -> 12432 */
{0x3091, 0xa4f1}, /* 'ゑ' -> 12433 */
{0x3092, 0xa4f2}, /* 'を' -> 12434 */
{0x3093, 0xa4f3}, /* 'ん' -> 12435 */
{0x30a1, 0xa5a1}, /* 'ァ' -> 12449 */
{0x30a2, 0xa5a2}, /* 'ア' -> 12450 */
{0x30a3, 0xa5a3}, /* 'ィ' -> 12451 */
{0x30a4, 0xa5a4}, /* 'イ' -> 12452 */
{0x30a5, 0xa5a5}, /* 'ゥ' -> 12453 */
{0x30a6, 0xa5a6}, /* 'ウ' -> 12454 */
{0x30a7, 0xa5a7}, /* 'ェ' -> 12455 */
{0x30a8, 0xa5a8}, /* 'エ' -> 12456 */
{0x30a9, 0xa5a9}, /* 'ォ' -> 12457 */
{0x30aa, 0xa5aa}, /* 'オ' -> 12458 */
{0x30ab, 0xa5ab}, /* 'カ' -> 12459 */
{0x30ac, 0xa5ac}, /* 'ガ' -> 12460 */
{0x30ad, 0xa5ad}, /* 'キ' -> 12461 */
{0x30ae, 0xa5ae}, /* 'ギ' -> 12462 */
{0x30af, 0xa5af}, /* 'ク' -> 12463 */
{0x30b0, 0xa5b0}, /* 'グ' -> 12464 */
{0x30b1, 0xa5b1}, /* 'ケ' -> 12465 */
{0x30b2, 0xa5b2}, /* 'ゲ' -> 12466 */
{0x30b3, 0xa5b3}, /* 'コ' -> 12467 */
{0x30b4, 0xa5b4}, /* 'ゴ' -> 12468 */
{0x30b5, 0xa5b5}, /* 'サ' -> 12469 */
{0x30b6, 0xa5b6}, /* 'ザ' -> 12470 */
{0x30b7, 0xa5b7}, /* 'シ' -> 12471 */
{0x30b8, 0xa5b8}, /* 'ジ' -> 12472 */
{0x30b9, 0xa5b9}, /* 'ス' -> 12473 */
{0x30ba, 0xa5ba}, /* 'ズ' -> 12474 */
{0x30bb, 0xa5bb}, /* 'セ' -> 12475 */
{0x30bc, 0xa5bc}, /* 'ゼ' -> 12476 */
{0x30bd, 0xa5bd}, /* 'ソ' -> 12477 */
{0x30be, 0xa5be}, /* 'ゾ' -> 12478 */
{0x30bf, 0xa5bf}, /* 'タ' -> 12479 */
{0x30c0, 0xa5c0}, /* 'ダ' -> 12480 */
{0x30c1, 0xa5c1}, /* 'チ' -> 12481 */
{0x30c2, 0xa5c2}, /* 'ヂ' -> 12482 */
{0x30c3, 0xa5c3}, /* 'ッ' -> 12483 */
{0x30c4, 0xa5c4}, /* 'ツ' -> 12484 */
{0x30c5, 0xa5c5}, /* 'ヅ' -> 12485 */
{0x30c6, 0xa5c6}, /* 'テ' -> 12486 */
{0x30c7, 0xa5c7}, /* 'デ' -> 12487 */
{0x30c8, 0xa5c8}, /* 'ト' -> 12488 */
{0x30c9, 0xa5c9}, /* 'ド' -> 12489 */
{0x30ca, 0xa5ca}, /* 'ナ' -> 12490 */
{0x30cb, 0xa5cb}, /* 'ニ' -> 12491 */
{0x30cc, 0xa5cc}, /* 'ヌ' -> 12492 */
{0x30cd, 0xa5cd}, /* 'ネ' -> 12493 */
{0x30ce, 0xa5ce}, /* 'ノ' -> 12494 */
{0x30cf, 0xa5cf}, /* 'ハ' -> 12495 */
{0x30d0, 0xa5d0}, /* 'バ' -> 12496 */
{0x30d1, 0xa5d1}, /* 'パ' -> 12497 */
{0x30d2, 0xa5d2}, /* 'ヒ' -> 12498 */
{0x30d3, 0xa5d3}, /* 'ビ' -> 12499 */
{0x30d4, 0xa5d4}, /* 'ピ' -> 12500 */
{0x30d5, 0xa5d5}, /* 'フ' -> 12501 */
{0x30d6, 0xa5d6}, /* 'ブ' -> 12502 */
{0x30d7, 0xa5d7}, /* 'プ' -> 12503 */
{0x30d8, 0xa5d8}, /* 'ヘ' -> 12504 */
{0x30d9, 0xa5d9}, /* 'ベ' -> 12505 */
{0x30da, 0xa5da}, /* 'ペ' -> 12506 */
{0x30db, 0xa5db}, /* 'ホ' -> 12507 */
{0x30dc, 0xa5dc}, /* 'ボ' -> 12508 */
{0x30dd, 0xa5dd}, /* 'ポ' -> 12509 */
{0x30de, 0xa5de}, /* 'マ' -> 12510 */
{0x30df, 0xa5df}, /* 'ミ' -> 12511 */
{0x30e0, 0xa5e0}, /* 'ム' -> 12512 */
{0x30e1, 0xa5e1}, /* 'メ' -> 12513 */
{0x30e2, 0xa5e2}, /* 'モ' -> 12514 */
{0x30e3, 0xa5e3}, /* 'ャ' -> 12515 */
{0x30e4, 0xa5e4}, /* 'ヤ' -> 12516 */
{0x30e5, 0xa5e5}, /* 'ュ' -> 12517 */
{0x30e6, 0xa5e6}, /* 'ユ' -> 12518 */
{0x30e7, 0xa5e7}, /* 'ョ' -> 12519 */
{0x30e8, 0xa5e8}, /* 'ヨ' -> 12520 */
{0x30e9, 0xa5e9}, /* 'ラ' -> 12521 */
{0x30ea, 0xa5ea}, /* 'リ' -> 12522 */
{0x30eb, 0xa5eb}, /* 'ル' -> 12523 */
{0x30ec, 0xa5ec}, /* 'レ' -> 12524 */
{0x30ed, 0xa5ed}, /* 'ロ' -> 12525 */
{0x30ee, 0xa5ee}, /* 'ヮ' -> 12526 */
{0x30ef, 0xa5ef}, /* 'ワ' -> 12527 */
{0x30f0, 0xa5f0}, /* 'ヰ' -> 12528 */
{0x30f1, 0xa5f1}, /* 'ヱ' -> 12529 */
{0x30f2, 0xa5f2}, /* 'ヲ' -> 12530 */
{0x30f3, 0xa5f3}, /* 'ン' -> 12531 */
{0x30f4, 0xa5f4}, /* 'ヴ' -> 12532 */
{0x30f5, 0xa5f5}, /* 'ヵ' -> 12533 */
{0x30f6, 0xa5f6}, /* 'ヶ' -> 12534 */
{0x30fb, 0xa1a4}, /* '・' -> 12539 */
{0x3105, 0xa8c5}, /* 'ㄅ' -> 12549 */
{0x3106, 0xa8c6}, /* 'ㄆ' -> 12550 */
{0x3107, 0xa8c7}, /* 'ㄇ' -> 12551 */
{0x3108, 0xa8c8}, /* 'ㄈ' -> 12552 */
{0x3109, 0xa8c9}, /* 'ㄉ' -> 12553 */
{0x310a, 0xa8ca}, /* 'ㄊ' -> 12554 */
{0x310b, 0xa8cb}, /* 'ㄋ' -> 12555 */
{0x310c, 0xa8cc}, /* 'ㄌ' -> 12556 */
{0x310d, 0xa8cd}, /* 'ㄍ' -> 12557 */
{0x310e, 0xa8ce}, /* 'ㄎ' -> 12558 */
{0x310f, 0xa8cf}, /* 'ㄏ' -> 12559 */
{0x3110, 0xa8d0}, /* 'ㄐ' -> 12560 */
{0x3111, 0xa8d1}, /* 'ㄑ' -> 12561 */
{0x3112, 0xa8d2}, /* 'ㄒ' -> 12562 */
{0x3113, 0xa8d3}, /* 'ㄓ' -> 12563 */
{0x3114, 0xa8d4}, /* 'ㄔ' -> 12564 */
{0x3115, 0xa8d5}, /* 'ㄕ' -> 12565 */
{0x3116, 0xa8d6}, /* 'ㄖ' -> 12566 */
{0x3117, 0xa8d7}, /* 'ㄗ' -> 12567 */
{0x3118, 0xa8d8}, /* 'ㄘ' -> 12568 */
{0x3119, 0xa8d9}, /* 'ㄙ' -> 12569 */
{0x311a, 0xa8da}, /* 'ㄚ' -> 12570 */
{0x311b, 0xa8db}, /* 'ㄛ' -> 12571 */
{0x311c, 0xa8dc}, /* 'ㄜ' -> 12572 */
{0x311d, 0xa8dd}, /* 'ㄝ' -> 12573 */
{0x311e, 0xa8de}, /* 'ㄞ' -> 12574 */
{0x311f, 0xa8df}, /* 'ㄟ' -> 12575 */
{0x3120, 0xa8e0}, /* 'ㄠ' -> 12576 */
{0x3121, 0xa8e1}, /* 'ㄡ' -> 12577 */
{0x3122, 0xa8e2}, /* 'ㄢ' -> 12578 */
{0x3123, 0xa8e3}, /* 'ㄣ' -> 12579 */
{0x3124, 0xa8e4}, /* 'ㄤ' -> 12580 */
{0x3125, 0xa8e5}, /* 'ㄥ' -> 12581 */
{0x3126, 0xa8e6}, /* 'ㄦ' -> 12582 */
{0x3127, 0xa8e7}, /* 'ㄧ' -> 12583 */
{0x3128, 0xa8e8}, /* 'ㄨ' -> 12584 */
{0x3129, 0xa8e9}, /* 'ㄩ' -> 12585 */
{0x3220, 0xa2e5}, /* '㈠' -> 12832 */
{0x3221, 0xa2e6}, /* '㈡' -> 12833 */
{0x3222, 0xa2e7}, /* '㈢' -> 12834 */
{0x3223, 0xa2e8}, /* '㈣' -> 12835 */
{0x3224, 0xa2e9}, /* '㈤' -> 12836 */
{0x3225, 0xa2ea}, /* '㈥' -> 12837 */
{0x3226, 0xa2eb}, /* '㈦' -> 12838 */
{0x3227, 0xa2ec}, /* '㈧' -> 12839 */
{0x3228, 0xa2ed}, /* '㈨' -> 12840 */
{0x3229, 0xa2ee}, /* '㈩' -> 12841 */
{0x4e00, 0xd2bb}, /* '一' -> 19968 */
{0x4e01, 0xb6a1}, /* '丁' -> 19969 */
{0x4e03, 0xc6df}, /* '七' -> 19971 */
{0x4e07, 0xcdf2}, /* '万' -> 19975 */
{0x4e08, 0xd5c9}, /* '丈' -> 19976 */
{0x4e09, 0xc8fd}, /* '三' -> 19977 */
{0x4e0a, 0xc9cf}, /* '上' -> 19978 */
{0x4e0b, 0xcfc2}, /* '下' -> 19979 */
{0x4e0c, 0xd8a2}, /* '丌' -> 19980 */
{0x4e0d, 0xb2bb}, /* '不' -> 19981 */
{0x4e0e, 0xd3eb}, /* '与' -> 19982 */
{0x4e10, 0xd8a4}, /* '丐' -> 19984 */
{0x4e11, 0xb3f3}, /* '丑' -> 19985 */
{0x4e13, 0xd7a8}, /* '专' -> 19987 */
{0x4e14, 0xc7d2}, /* '且' -> 19988 */
{0x4e15, 0xd8a7}, /* '丕' -> 19989 */
{0x4e16, 0xcac0}, /* '世' -> 19990 */
{0x4e18, 0xc7f0}, /* '丘' -> 19992 */
{0x4e19, 0xb1fb}, /* '丙' -> 19993 */
{0x4e1a, 0xd2b5}, /* '业' -> 19994 */
{0x4e1b, 0xb4d4}, /* '丛' -> 19995 */
{0x4e1c, 0xb6ab}, /* '东' -> 19996 */
{0x4e1d, 0xcbbf}, /* '丝' -> 19997 */
{0x4e1e, 0xd8a9}, /* '丞' -> 19998 */
{0x4e22, 0xb6aa}, /* '丢' -> 20002 */
{0x4e24, 0xc1bd}, /* '两' -> 20004 */
{0x4e25, 0xd1cf}, /* '严' -> 20005 */
{0x4e27, 0xc9a5}, /* '丧' -> 20007 */
{0x4e28, 0xd8ad}, /* '丨' -> 20008 */
{0x4e2a, 0xb8f6}, /* '个' -> 20010 */
{0x4e2b, 0xd1be}, /* '丫' -> 20011 */
{0x4e2c, 0xe3dc}, /* '丬' -> 20012 */
{0x4e2d, 0xd6d0}, /* '中' -> 20013 */
{0x4e30, 0xb7e1}, /* '丰' -> 20016 */
{0x4e32, 0xb4ae}, /* '串' -> 20018 */
{0x4e34, 0xc1d9}, /* '临' -> 20020 */
{0x4e36, 0xd8bc}, /* '丶' -> 20022 */
{0x4e38, 0xcde8}, /* '丸' -> 20024 */
{0x4e39, 0xb5a4}, /* '丹' -> 20025 */
{0x4e3a, 0xceaa}, /* '为' -> 20026 */
{0x4e3b, 0xd6f7}, /* '主' -> 20027 */
{0x4e3d, 0xc0f6}, /* '丽' -> 20029 */
{0x4e3e, 0xbed9}, /* '举' -> 20030 */
{0x4e3f, 0xd8af}, /* '丿' -> 20031 */
{0x4e43, 0xc4cb}, /* '乃' -> 20035 */
{0x4e45, 0xbec3}, /* '久' -> 20037 */
{0x4e47, 0xd8b1}, /* '乇' -> 20039 */
{0x4e48, 0xc3b4}, /* '么' -> 20040 */
{0x4e49, 0xd2e5}, /* '义' -> 20041 */
{0x4e4b, 0xd6ae}, /* '之' -> 20043 */
{0x4e4c, 0xceda}, /* '乌' -> 20044 */
{0x4e4d, 0xd5a7}, /* '乍' -> 20045 */
{0x4e4e, 0xbaf5}, /* '乎' -> 20046 */
{0x4e4f, 0xb7a6}, /* '乏' -> 20047 */
{0x4e50, 0xc0d6}, /* '乐' -> 20048 */
{0x4e52, 0xc6b9}, /* '乒' -> 20050 */
{0x4e53, 0xc5d2}, /* '乓' -> 20051 */
{0x4e54, 0xc7c7}, /* '乔' -> 20052 */
{0x4e56, 0xb9d4}, /* '乖' -> 20054 */
{0x4e58, 0xb3cb}, /* '乘' -> 20056 */
{0x4e59, 0xd2d2}, /* '乙' -> 20057 */
{0x4e5c, 0xd8bf}, /* '乜' -> 20060 */
{0x4e5d, 0xbec5}, /* '九' -> 20061 */
{0x4e5e, 0xc6f2}, /* '乞' -> 20062 */
{0x4e5f, 0xd2b2}, /* '也' -> 20063 */
{0x4e60, 0xcfb0}, /* '习' -> 20064 */
{0x4e61, 0xcfe7}, /* '乡' -> 20065 */
{0x4e66, 0xcae9}, /* '书' -> 20070 */
{0x4e69, 0xd8c0}, /* '乩' -> 20073 */
{0x4e70, 0xc2f2}, /* '买' -> 20080 */
{0x4e71, 0xc2d2}, /* '乱' -> 20081 */
{0x4e73, 0xc8e9}, /* '乳' -> 20083 */
{0x4e7e, 0xc7ac}, /* '乾' -> 20094 */
{0x4e86, 0xc1cb}, /* '了' -> 20102 */
{0x4e88, 0xd3e8}, /* '予' -> 20104 */
{0x4e89, 0xd5f9}, /* '争' -> 20105 */
{0x4e8b, 0xcac2}, /* '事' -> 20107 */
{0x4e8c, 0xb6fe}, /* '二' -> 20108 */
{0x4e8d, 0xd8a1}, /* '亍' -> 20109 */
{0x4e8e, 0xd3da}, /* '于' -> 20110 */
{0x4e8f, 0xbff7}, /* '亏' -> 20111 */
{0x4e91, 0xd4c6}, /* '云' -> 20113 */
{0x4e92, 0xbba5}, /* '互' -> 20114 */
{0x4e93, 0xd8c1}, /* '亓' -> 20115 */
{0x4e94, 0xcee5}, /* '五' -> 20116 */
{0x4e95, 0xbeae}, /* '井' -> 20117 */
{0x4e98, 0xd8a8}, /* '亘' -> 20120 */
{0x4e9a, 0xd1c7}, /* '亚' -> 20122 */
{0x4e9b, 0xd0a9}, /* '些' -> 20123 */
{0x4e9f, 0xd8bd}, /* '亟' -> 20127 */
{0x4ea0, 0xd9ef}, /* '亠' -> 20128 */
{0x4ea1, 0xcdf6}, /* '亡' -> 20129 */
{0x4ea2, 0xbfba}, /* '亢' -> 20130 */
{0x4ea4, 0xbdbb}, /* '交' -> 20132 */
{0x4ea5, 0xbaa5}, /* '亥' -> 20133 */
{0x4ea6, 0xd2e0}, /* '亦' -> 20134 */
{0x4ea7, 0xb2fa}, /* '产' -> 20135 */
{0x4ea8, 0xbae0}, /* '亨' -> 20136 */
{0x4ea9, 0xc4b6}, /* '亩' -> 20137 */
{0x4eab, 0xcfed}, /* '享' -> 20139 */
{0x4eac, 0xbea9}, /* '京' -> 20140 */
{0x4ead, 0xcda4}, /* '亭' -> 20141 */
{0x4eae, 0xc1c1}, /* '亮' -> 20142 */
{0x4eb2, 0xc7d7}, /* '亲' -> 20146 */
{0x4eb3, 0xd9f1}, /* '亳' -> 20147 */
{0x4eb5, 0xd9f4}, /* '亵' -> 20149 */
{0x4eba, 0xc8cb}, /* '人' -> 20154 */
{0x4ebb, 0xd8e9}, /* '亻' -> 20155 */
{0x4ebf, 0xd2da}, /* '亿' -> 20159 */
{0x4ec0, 0xcab2}, /* '什' -> 20160 */
{0x4ec1, 0xc8ca}, /* '仁' -> 20161 */
{0x4ec2, 0xd8ec}, /* '仂' -> 20162 */
{0x4ec3, 0xd8ea}, /* '仃' -> 20163 */
{0x4ec4, 0xd8c6}, /* '仄' -> 20164 */
{0x4ec5, 0xbdf6}, /* '仅' -> 20165 */
{0x4ec6, 0xc6cd}, /* '仆' -> 20166 */
{0x4ec7, 0xb3f0}, /* '仇' -> 20167 */
{0x4ec9, 0xd8eb}, /* '仉' -> 20169 */
{0x4eca, 0xbdf1}, /* '今' -> 20170 */
{0x4ecb, 0xbde9}, /* '介' -> 20171 */
{0x4ecd, 0xc8d4}, /* '仍' -> 20173 */
{0x4ece, 0xb4d3}, /* '从' -> 20174 */
{0x4ed1, 0xc2d8}, /* '仑' -> 20177 */
{0x4ed3, 0xb2d6}, /* '仓' -> 20179 */
{0x4ed4, 0xd7d0}, /* '仔' -> 20180 */
{0x4ed5, 0xcacb}, /* '仕' -> 20181 */
{0x4ed6, 0xcbfb}, /* '他' -> 20182 */
{0x4ed7, 0xd5cc}, /* '仗' -> 20183 */
{0x4ed8, 0xb8b6}, /* '付' -> 20184 */
{0x4ed9, 0xcfc9}, /* '仙' -> 20185 */
{0x4edd, 0xd9da}, /* '仝' -> 20189 */
{0x4ede, 0xd8f0}, /* '仞' -> 20190 */
{0x4edf, 0xc7aa}, /* '仟' -> 20191 */
{0x4ee1, 0xd8ee}, /* '仡' -> 20193 */
{0x4ee3, 0xb4fa}, /* '代' -> 20195 */
{0x4ee4, 0xc1ee}, /* '令' -> 20196 */
{0x4ee5, 0xd2d4}, /* '以' -> 20197 */
{0x4ee8, 0xd8ed}, /* '仨' -> 20200 */
{0x4eea, 0xd2c7}, /* '仪' -> 20202 */
{0x4eeb, 0xd8ef}, /* '仫' -> 20203 */
{0x4eec, 0xc3c7}, /* '们' -> 20204 */
{0x4ef0, 0xd1f6}, /* '仰' -> 20208 */
{0x4ef2, 0xd6d9}, /* '仲' -> 20210 */
{0x4ef3, 0xd8f2}, /* '仳' -> 20211 */
{0x4ef5, 0xd8f5}, /* '仵' -> 20213 */
{0x4ef6, 0xbcfe}, /* '件' -> 20214 */
{0x4ef7, 0xbcdb}, /* '价' -> 20215 */
{0x4efb, 0xc8ce}, /* '任' -> 20219 */
{0x4efd, 0xb7dd}, /* '份' -> 20221 */
{0x4eff, 0xb7c2}, /* '仿' -> 20223 */
{0x4f01, 0xc6f3}, /* '企' -> 20225 */
{0x4f09, 0xd8f8}, /* '伉' -> 20233 */
{0x4f0a, 0xd2c1}, /* '伊' -> 20234 */
{0x4f0d, 0xcee9}, /* '伍' -> 20237 */
{0x4f0e, 0xbcbf}, /* '伎' -> 20238 */
{0x4f0f, 0xb7fc}, /* '伏' -> 20239 */
{0x4f10, 0xb7a5}, /* '伐' -> 20240 */
{0x4f11, 0xd0dd}, /* '休' -> 20241 */
{0x4f17, 0xd6da}, /* '众' -> 20247 */
{0x4f18, 0xd3c5}, /* '优' -> 20248 */
{0x4f19, 0xbbef}, /* '伙' -> 20249 */
{0x4f1a, 0xbbe1}, /* '会' -> 20250 */
{0x4f1b, 0xd8f1}, /* '伛' -> 20251 */
{0x4f1e, 0xc9a1}, /* '伞' -> 20254 */
{0x4f1f, 0xceb0}, /* '伟' -> 20255 */
{0x4f20, 0xb4ab}, /* '传' -> 20256 */
{0x4f22, 0xd8f3}, /* '伢' -> 20258 */
{0x4f24, 0xc9cb}, /* '伤' -> 20260 */
{0x4f25, 0xd8f6}, /* '伥' -> 20261 */
{0x4f26, 0xc2d7}, /* '伦' -> 20262 */
{0x4f27, 0xd8f7}, /* '伧' -> 20263 */
{0x4f2a, 0xceb1}, /* '伪' -> 20266 */
{0x4f2b, 0xd8f9}, /* '伫' -> 20267 */
{0x4f2f, 0xb2ae}, /* '伯' -> 20271 */
{0x4f30, 0xb9c0}, /* '估' -> 20272 */
{0x4f32, 0xd9a3}, /* '伲' -> 20274 */
{0x4f34, 0xb0e9}, /* '伴' -> 20276 */
{0x4f36, 0xc1e6}, /* '伶' -> 20278 */
{0x4f38, 0xc9ec}, /* '伸' -> 20280 */
{0x4f3a, 0xcbc5}, /* '伺' -> 20282 */
{0x4f3c, 0xcbc6}, /* '似' -> 20284 */
{0x4f3d, 0xd9a4}, /* '伽' -> 20285 */
{0x4f43, 0xb5e8}, /* '佃' -> 20291 */
{0x4f46, 0xb5ab}, /* '但' -> 20294 */
{0x4f4d, 0xcebb}, /* '位' -> 20301 */
{0x4f4e, 0xb5cd}, /* '低' -> 20302 */
{0x4f4f, 0xd7a1}, /* '住' -> 20303 */
{0x4f50, 0xd7f4}, /* '佐' -> 20304 */
{0x4f51, 0xd3d3}, /* '佑' -> 20305 */
{0x4f53, 0xcce5}, /* '体' -> 20307 */
{0x4f55, 0xbace}, /* '何' -> 20309 */
{0x4f57, 0xd9a2}, /* '佗' -> 20311 */
{0x4f58, 0xd9dc}, /* '佘' -> 20312 */
{0x4f59, 0xd3e0}, /* '余' -> 20313 */
{0x4f5a, 0xd8fd}, /* '佚' -> 20314 */
{0x4f5b, 0xb7f0}, /* '佛' -> 20315 */
{0x4f5c, 0xd7f7}, /* '作' -> 20316 */
{0x4f5d, 0xd8fe}, /* '佝' -> 20317 */
{0x4f5e, 0xd8fa}, /* '佞' -> 20318 */
{0x4f5f, 0xd9a1}, /* '佟' -> 20319 */
{0x4f60, 0xc4e3}, /* '你' -> 20320 */
{0x4f63, 0xd3b6}, /* '佣' -> 20323 */
{0x4f64, 0xd8f4}, /* '佤' -> 20324 */
{0x4f65, 0xd9dd}, /* '佥' -> 20325 */
{0x4f67, 0xd8fb}, /* '佧' -> 20327 */
{0x4f69, 0xc5e5}, /* '佩' -> 20329 */
{0x4f6c, 0xc0d0}, /* '佬' -> 20332 */
{0x4f6f, 0xd1f0}, /* '佯' -> 20335 */
{0x4f70, 0xb0db}, /* '佰' -> 20336 */
{0x4f73, 0xbcd1}, /* '佳' -> 20339 */
{0x4f74, 0xd9a6}, /* '佴' -> 20340 */
{0x4f76, 0xd9a5}, /* '佶' -> 20342 */
{0x4f7b, 0xd9ac}, /* '佻' -> 20347 */
{0x4f7c, 0xd9ae}, /* '佼' -> 20348 */
{0x4f7e, 0xd9ab}, /* '佾' -> 20350 */
{0x4f7f, 0xcab9}, /* '使' -> 20351 */
{0x4f83, 0xd9a9}, /* '侃' -> 20355 */
{0x4f84, 0xd6b6}, /* '侄' -> 20356 */
{0x4f88, 0xb3de}, /* '侈' -> 20360 */
{0x4f89, 0xd9a8}, /* '侉' -> 20361 */
{0x4f8b, 0xc0fd}, /* '例' -> 20363 */
{0x4f8d, 0xcacc}, /* '侍' -> 20365 */
{0x4f8f, 0xd9aa}, /* '侏' -> 20367 */
{0x4f91, 0xd9a7}, /* '侑' -> 20369 */
{0x4f94, 0xd9b0}, /* '侔' -> 20372 */
{0x4f97, 0xb6b1}, /* '侗' -> 20375 */
{0x4f9b, 0xb9a9}, /* '供' -> 20379 */
{0x4f9d, 0xd2c0}, /* '依' -> 20381 */
{0x4fa0, 0xcfc0}, /* '侠' -> 20384 */
{0x4fa3, 0xc2c2}, /* '侣' -> 20387 */
{0x4fa5, 0xbdc4}, /* '侥' -> 20389 */
{0x4fa6, 0xd5ec}, /* '侦' -> 20390 */
{0x4fa7, 0xb2e0}, /* '侧' -> 20391 */
{0x4fa8, 0xc7c8}, /* '侨' -> 20392 */
{0x4fa9, 0xbfeb}, /* '侩' -> 20393 */
{0x4faa, 0xd9ad}, /* '侪' -> 20394 */
{0x4fac, 0xd9af}, /* '侬' -> 20396 */
{0x4fae, 0xceea}, /* '侮' -> 20398 */
{0x4faf, 0xbaee}, /* '侯' -> 20399 */
{0x4fb5, 0xc7d6}, /* '侵' -> 20405 */
{0x4fbf, 0xb1e3}, /* '便' -> 20415 */
{0x4fc3, 0xb4d9}, /* '促' -> 20419 */
{0x4fc4, 0xb6ed}, /* '俄' -> 20420 */
{0x4fc5, 0xd9b4}, /* '俅' -> 20421 */
{0x4fca, 0xbfa1}, /* '俊' -> 20426 */
{0x4fce, 0xd9de}, /* '俎' -> 20430 */
{0x4fcf, 0xc7ce}, /* '俏' -> 20431 */
{0x4fd0, 0xc0fe}, /* '俐' -> 20432 */
{0x4fd1, 0xd9b8}, /* '俑' -> 20433 */
{0x4fd7, 0xcbd7}, /* '俗' -> 20439 */
{0x4fd8, 0xb7fd}, /* '俘' -> 20440 */
{0x4fda, 0xd9b5}, /* '俚' -> 20442 */
{0x4fdc, 0xd9b7}, /* '俜' -> 20444 */
{0x4fdd, 0xb1a3}, /* '保' -> 20445 */
{0x4fde, 0xd3e1}, /* '俞' -> 20446 */
{0x4fdf, 0xd9b9}, /* '俟' -> 20447 */
{0x4fe1, 0xd0c5}, /* '信' -> 20449 */
{0x4fe3, 0xd9b6}, /* '俣' -> 20451 */
{0x4fe6, 0xd9b1}, /* '俦' -> 20454 */
{0x4fe8, 0xd9b2}, /* '俨' -> 20456 */
{0x4fe9, 0xc1a9}, /* '俩' -> 20457 */
{0x4fea, 0xd9b3}, /* '俪' -> 20458 */
{0x4fed, 0xbcf3}, /* '俭' -> 20461 */
{0x4fee, 0xd0de}, /* '修' -> 20462 */
{0x4fef, 0xb8a9}, /* '俯' -> 20463 */
{0x4ff1, 0xbee3}, /* '俱' -> 20465 */
{0x4ff3, 0xd9bd}, /* '俳' -> 20467 */
{0x4ff8, 0xd9ba}, /* '俸' -> 20472 */
{0x4ffa, 0xb0b3}, /* '俺' -> 20474 */
{0x4ffe, 0xd9c2}, /* '俾' -> 20478 */
{0x500c, 0xd9c4}, /* '倌' -> 20492 */
{0x500d, 0xb1b6}, /* '倍' -> 20493 */
{0x500f, 0xd9bf}, /* '倏' -> 20495 */
{0x5012, 0xb5b9}, /* '倒' -> 20498 */
{0x5014, 0xbef3}, /* '倔' -> 20500 */
{0x5018, 0xccc8}, /* '倘' -> 20504 */
{0x5019, 0xbaf2}, /* '候' -> 20505 */
{0x501a, 0xd2d0}, /* '倚' -> 20506 */
{0x501c, 0xd9c3}, /* '倜' -> 20508 */
{0x501f, 0xbde8}, /* '借' -> 20511 */
{0x5021, 0xb3ab}, /* '倡' -> 20513 */
{0x5025, 0xd9c5}, /* '倥' -> 20517 */
{0x5026, 0xbeeb}, /* '倦' -> 20518 */
{0x5028, 0xd9c6}, /* '倨' -> 20520 */
{0x5029, 0xd9bb}, /* '倩' -> 20521 */
{0x502a, 0xc4df}, /* '倪' -> 20522 */
{0x502c, 0xd9be}, /* '倬' -> 20524 */
{0x502d, 0xd9c1}, /* '倭' -> 20525 */
{0x502e, 0xd9c0}, /* '倮' -> 20526 */
{0x503a, 0xd5ae}, /* '债' -> 20538 */
{0x503c, 0xd6b5}, /* '值' -> 20540 */
{0x503e, 0xc7e3}, /* '倾' -> 20542 */
{0x5043, 0xd9c8}, /* '偃' -> 20547 */
{0x5047, 0xbcd9}, /* '假' -> 20551 */
{0x5048, 0xd9ca}, /* '偈' -> 20552 */
{0x504c, 0xd9bc}, /* '偌' -> 20556 */
{0x504e, 0xd9cb}, /* '偎' -> 20558 */
{0x504f, 0xc6ab}, /* '偏' -> 20559 */
{0x5055, 0xd9c9}, /* '偕' -> 20565 */
{0x505a, 0xd7f6}, /* '做' -> 20570 */
{0x505c, 0xcda3}, /* '停' -> 20572 */
{0x5065, 0xbda1}, /* '健' -> 20581 */
{0x506c, 0xd9cc}, /* '偬' -> 20588 */
{0x5076, 0xc5bc}, /* '偶' -> 20598 */
{0x5077, 0xcdb5}, /* '偷' -> 20599 */
{0x507b, 0xd9cd}, /* '偻' -> 20603 */
{0x507e, 0xd9c7}, /* '偾' -> 20606 */
{0x507f, 0xb3a5}, /* '偿' -> 20607 */
{0x5080, 0xbffe}, /* '傀' -> 20608 */
{0x5085, 0xb8b5}, /* '傅' -> 20613 */
{0x5088, 0xc0fc}, /* '傈' -> 20616 */
{0x508d, 0xb0f8}, /* '傍' -> 20621 */
{0x50a3, 0xb4f6}, /* '傣' -> 20643 */
{0x50a5, 0xd9ce}, /* '傥' -> 20645 */
{0x50a7, 0xd9cf}, /* '傧' -> 20647 */
{0x50a8, 0xb4a2}, /* '储' -> 20648 */
{0x50a9, 0xd9d0}, /* '傩' -> 20649 */
{0x50ac, 0xb4df}, /* '催' -> 20652 */
{0x50b2, 0xb0c1}, /* '傲' -> 20658 */
{0x50ba, 0xd9d1}, /* '傺' -> 20666 */
{0x50bb, 0xc9b5}, /* '傻' -> 20667 */
{0x50cf, 0xcff1}, /* '像' -> 20687 */
{0x50d6, 0xd9d2}, /* '僖' -> 20694 */
{0x50da, 0xc1c5}, /* '僚' -> 20698 */
{0x50e6, 0xd9d6}, /* '僦' -> 20710 */
{0x50e7, 0xc9ae}, /* '僧' -> 20711 */
{0x50ec, 0xd9d5}, /* '僬' -> 20716 */
{0x50ed, 0xd9d4}, /* '僭' -> 20717 */
{0x50ee, 0xd9d7}, /* '僮' -> 20718 */
{0x50f3, 0xcbdb}, /* '僳' -> 20723 */
{0x50f5, 0xbda9}, /* '僵' -> 20725 */
{0x50fb, 0xc6a7}, /* '僻' -> 20731 */
{0x5106, 0xd9d3}, /* '儆' -> 20742 */
{0x5107, 0xd9d8}, /* '儇' -> 20743 */
{0x510b, 0xd9d9}, /* '儋' -> 20747 */
{0x5112, 0xc8e5}, /* '儒' -> 20754 */
{0x5121, 0xc0dc}, /* '儡' -> 20769 */
{0x513f, 0xb6f9}, /* '儿' -> 20799 */
{0x5140, 0xd8a3}, /* '兀' -> 20800 */
{0x5141, 0xd4ca}, /* '允' -> 20801 */
{0x5143, 0xd4aa}, /* '元' -> 20803 */
{0x5144, 0xd0d6}, /* '兄' -> 20804 */
{0x5145, 0xb3e4}, /* '充' -> 20805 */
{0x5146, 0xd5d7}, /* '兆' -> 20806 */
{0x5148, 0xcfc8}, /* '先' -> 20808 */
{0x5149, 0xb9e2}, /* '光' -> 20809 */
{0x514b, 0xbfcb}, /* '克' -> 20811 */
{0x514d, 0xc3e2}, /* '免' -> 20813 */
{0x5151, 0xb6d2}, /* '兑' -> 20817 */
{0x5154, 0xcdc3}, /* '兔' -> 20820 */
{0x5155, 0xd9ee}, /* '兕' -> 20821 */
{0x5156, 0xd9f0}, /* '兖' -> 20822 */
{0x515a, 0xb5b3}, /* '党' -> 20826 */
{0x515c, 0xb6b5}, /* '兜' -> 20828 */
{0x5162, 0xbea4}, /* '兢' -> 20834 */
{0x5165, 0xc8eb}, /* '入' -> 20837 */
{0x5168, 0xc8ab}, /* '全' -> 20840 */
{0x516b, 0xb0cb}, /* '八' -> 20843 */
{0x516c, 0xb9ab}, /* '公' -> 20844 */
{0x516d, 0xc1f9}, /* '六' -> 20845 */
{0x516e, 0xd9e2}, /* '兮' -> 20846 */
{0x5170, 0xc0bc}, /* '兰' -> 20848 */
{0x5171, 0xb9b2}, /* '共' -> 20849 */
{0x5173, 0xb9d8}, /* '关' -> 20851 */
{0x5174, 0xd0cb}, /* '兴' -> 20852 */
{0x5175, 0xb1f8}, /* '兵' -> 20853 */
{0x5176, 0xc6e4}, /* '其' -> 20854 */
{0x5177, 0xbedf}, /* '具' -> 20855 */
{0x5178, 0xb5e4}, /* '典' -> 20856 */
{0x5179, 0xd7c8}, /* '兹' -> 20857 */
{0x517b, 0xd1f8}, /* '养' -> 20859 */
{0x517c, 0xbce6}, /* '兼' -> 20860 */
{0x517d, 0xcade}, /* '兽' -> 20861 */
{0x5180, 0xbcbd}, /* '冀' -> 20864 */
{0x5181, 0xd9e6}, /* '冁' -> 20865 */
{0x5182, 0xd8e7}, /* '冂' -> 20866 */
{0x5185, 0xc4da}, /* '内' -> 20869 */
{0x5188, 0xb8d4}, /* '冈' -> 20872 */
{0x5189, 0xc8bd}, /* '冉' -> 20873 */
{0x518c, 0xb2e1}, /* '册' -> 20876 */
{0x518d, 0xd4d9}, /* '再' -> 20877 */
{0x5192, 0xc3b0}, /* '冒' -> 20882 */
{0x5195, 0xc3e1}, /* '冕' -> 20885 */
{0x5196, 0xdaa2}, /* '冖' -> 20886 */
{0x5197, 0xc8df}, /* '冗' -> 20887 */
{0x5199, 0xd0b4}, /* '写' -> 20889 */
{0x519b, 0xbefc}, /* '军' -> 20891 */
{0x519c, 0xc5a9}, /* '农' -> 20892 */
{0x51a0, 0xb9da}, /* '冠' -> 20896 */
{0x51a2, 0xdaa3}, /* '冢' -> 20898 */
{0x51a4, 0xd4a9}, /* '冤' -> 20900 */
{0x51a5, 0xdaa4}, /* '冥' -> 20901 */
{0x51ab, 0xd9fb}, /* '冫' -> 20907 */
{0x51ac, 0xb6ac}, /* '冬' -> 20908 */
{0x51af, 0xb7eb}, /* '冯' -> 20911 */
{0x51b0, 0xb1f9}, /* '冰' -> 20912 */
{0x51b1, 0xd9fc}, /* '冱' -> 20913 */
{0x51b2, 0xb3e5}, /* '冲' -> 20914 */
{0x51b3, 0xbef6}, /* '决' -> 20915 */
{0x51b5, 0xbff6}, /* '况' -> 20917 */
{0x51b6, 0xd2b1}, /* '冶' -> 20918 */
{0x51b7, 0xc0e4}, /* '冷' -> 20919 */
{0x51bb, 0xb6b3}, /* '冻' -> 20923 */
{0x51bc, 0xd9fe}, /* '冼' -> 20924 */
{0x51bd, 0xd9fd}, /* '冽' -> 20925 */
{0x51c0, 0xbebb}, /* '净' -> 20928 */
{0x51c4, 0xc6e0}, /* '凄' -> 20932 */
{0x51c6, 0xd7bc}, /* '准' -> 20934 */
{0x51c7, 0xdaa1}, /* '凇' -> 20935 */
{0x51c9, 0xc1b9}, /* '凉' -> 20937 */
{0x51cb, 0xb5f2}, /* '凋' -> 20939 */
{0x51cc, 0xc1e8}, /* '凌' -> 20940 */
{0x51cf, 0xbcf5}, /* '减' -> 20943 */
{0x51d1, 0xb4d5}, /* '凑' -> 20945 */
{0x51db, 0xc1dd}, /* '凛' -> 20955 */
{0x51dd, 0xc4fd}, /* '凝' -> 20957 */
{0x51e0, 0xbcb8}, /* '几' -> 20960 */
{0x51e1, 0xb7b2}, /* '凡' -> 20961 */
{0x51e4, 0xb7ef}, /* '凤' -> 20964 */
{0x51eb, 0xd9ec}, /* '凫' -> 20971 */
{0x51ed, 0xc6be}, /* '凭' -> 20973 */
{0x51ef, 0xbfad}, /* '凯' -> 20975 */
{0x51f0, 0xbbcb}, /* '凰' -> 20976 */
{0x51f3, 0xb5ca}, /* '凳' -> 20979 */
{0x51f5, 0xdbc9}, /* '凵' -> 20981 */
{0x51f6, 0xd0d7}, /* '凶' -> 20982 */
{0x51f8, 0xcdb9}, /* '凸' -> 20984 */
{0x51f9, 0xb0bc}, /* '凹' -> 20985 */
{0x51fa, 0xb3f6}, /* '出' -> 20986 */
{0x51fb, 0xbbf7}, /* '击' -> 20987 */
{0x51fc, 0xdbca}, /* '凼' -> 20988 */
{0x51fd, 0xbaaf}, /* '函' -> 20989 */
{0x51ff, 0xd4e4}, /* '凿' -> 20991 */
{0x5200, 0xb5b6}, /* '刀' -> 20992 */
{0x5201, 0xb5f3}, /* '刁' -> 20993 */
{0x5202, 0xd8d6}, /* '刂' -> 20994 */
{0x5203, 0xc8d0}, /* '刃' -> 20995 */
{0x5206, 0xb7d6}, /* '分' -> 20998 */
{0x5207, 0xc7d0}, /* '切' -> 20999 */
{0x5208, 0xd8d7}, /* '刈' -> 21000 */
{0x520a, 0xbfaf}, /* '刊' -> 21002 */
{0x520d, 0xdbbb}, /* '刍' -> 21005 */
{0x520e, 0xd8d8}, /* '刎' -> 21006 */
{0x5211, 0xd0cc}, /* '刑' -> 21009 */
{0x5212, 0xbbae}, /* '划' -> 21010 */
{0x5216, 0xebbe}, /* '刖' -> 21014 */
{0x5217, 0xc1d0}, /* '列' -> 21015 */
{0x5218, 0xc1f5}, /* '刘' -> 21016 */
{0x5219, 0xd4f2}, /* '则' -> 21017 */
{0x521a, 0xb8d5}, /* '刚' -> 21018 */
{0x521b, 0xb4b4}, /* '创' -> 21019 */
{0x521d, 0xb3f5}, /* '初' -> 21021 */
{0x5220, 0xc9be}, /* '删' -> 21024 */
{0x5224, 0xc5d0}, /* '判' -> 21028 */
{0x5228, 0xc5d9}, /* '刨' -> 21032 */
{0x5229, 0xc0fb}, /* '利' -> 21033 */
{0x522b, 0xb1f0}, /* '别' -> 21035 */
{0x522d, 0xd8d9}, /* '刭' -> 21037 */
{0x522e, 0xb9ce}, /* '刮' -> 21038 */
{0x5230, 0xb5bd}, /* '到' -> 21040 */
{0x5233, 0xd8da}, /* '刳' -> 21043 */
{0x5236, 0xd6c6}, /* '制' -> 21046 */
{0x5237, 0xcba2}, /* '刷' -> 21047 */
{0x5238, 0xc8af}, /* '券' -> 21048 */
{0x5239, 0xc9b2}, /* '刹' -> 21049 */
{0x523a, 0xb4cc}, /* '刺' -> 21050 */
{0x523b, 0xbfcc}, /* '刻' -> 21051 */
{0x523d, 0xb9f4}, /* '刽' -> 21053 */
{0x523f, 0xd8db}, /* '刿' -> 21055 */
{0x5240, 0xd8dc}, /* '剀' -> 21056 */
{0x5241, 0xb6e7}, /* '剁' -> 21057 */
{0x5242, 0xbcc1}, /* '剂' -> 21058 */
{0x5243, 0xccea}, /* '剃' -> 21059 */
{0x524a, 0xcff7}, /* '削' -> 21066 */
{0x524c, 0xd8dd}, /* '剌' -> 21068 */
{0x524d, 0xc7b0}, /* '前' -> 21069 */
{0x5250, 0xb9d0}, /* '剐' -> 21072 */
{0x5251, 0xbda3}, /* '剑' -> 21073 */
{0x5254, 0xccde}, /* '剔' -> 21076 */
{0x5256, 0xc6ca}, /* '剖' -> 21078 */
{0x525c, 0xd8e0}, /* '剜' -> 21084 */
{0x525e, 0xd8de}, /* '剞' -> 21086 */
{0x5261, 0xd8df}, /* '剡' -> 21089 */
{0x5265, 0xb0fe}, /* '剥' -> 21093 */
{0x5267, 0xbee7}, /* '剧' -> 21095 */
{0x5269, 0xcaa3}, /* '剩' -> 21097 */
{0x526a, 0xbcf4}, /* '剪' -> 21098 */
{0x526f, 0xb8b1}, /* '副' -> 21103 */
{0x5272, 0xb8ee}, /* '割' -> 21106 */
{0x527d, 0xd8e2}, /* '剽' -> 21117 */
{0x527f, 0xbdcb}, /* '剿' -> 21119 */
{0x5281, 0xd8e4}, /* '劁' -> 21121 */
{0x5282, 0xd8e3}, /* '劂' -> 21122 */
{0x5288, 0xc5fc}, /* '劈' -> 21128 */
{0x5290, 0xd8e5}, /* '劐' -> 21136 */
{0x5293, 0xd8e6}, /* '劓' -> 21139 */
{0x529b, 0xc1a6}, /* '力' -> 21147 */
{0x529d, 0xc8b0}, /* '劝' -> 21149 */
{0x529e, 0xb0ec}, /* '办' -> 21150 */
{0x529f, 0xb9a6}, /* '功' -> 21151 */
{0x52a0, 0xbcd3}, /* '加' -> 21152 */
{0x52a1, 0xcef1}, /* '务' -> 21153 */
{0x52a2, 0xdbbd}, /* '劢' -> 21154 */
{0x52a3, 0xc1d3}, /* '劣' -> 21155 */
{0x52a8, 0xb6af}, /* '动' -> 21160 */
{0x52a9, 0xd6fa}, /* '助' -> 21161 */
{0x52aa, 0xc5ac}, /* '努' -> 21162 */
{0x52ab, 0xbdd9}, /* '劫' -> 21163 */
{0x52ac, 0xdbbe}, /* '劬' -> 21164 */
{0x52ad, 0xdbbf}, /* '劭' -> 21165 */
{0x52b1, 0xc0f8}, /* '励' -> 21169 */
{0x52b2, 0xbea2}, /* '劲' -> 21170 */
{0x52b3, 0xc0cd}, /* '劳' -> 21171 */
{0x52be, 0xdbc0}, /* '劾' -> 21182 */
{0x52bf, 0xcac6}, /* '势' -> 21183 */
{0x52c3, 0xb2aa}, /* '勃' -> 21187 */
{0x52c7, 0xd3c2}, /* '勇' -> 21191 */
{0x52c9, 0xc3e3}, /* '勉' -> 21193 */
{0x52cb, 0xd1ab}, /* '勋' -> 21195 */
{0x52d0, 0xdbc2}, /* '勐' -> 21200 */
{0x52d2, 0xc0d5}, /* '勒' -> 21202 */
{0x52d6, 0xdbc3}, /* '勖' -> 21206 */
{0x52d8, 0xbfb1}, /* '勘' -> 21208 */
{0x52df, 0xc4bc}, /* '募' -> 21215 */
{0x52e4, 0xc7da}, /* '勤' -> 21220 */
{0x52f0, 0xdbc4}, /* '勰' -> 21232 */
{0x52f9, 0xd9e8}, /* '勹' -> 21241 */
{0x52fa, 0xc9d7}, /* '勺' -> 21242 */
{0x52fe, 0xb9b4}, /* '勾' -> 21246 */
{0x52ff, 0xcef0}, /* '勿' -> 21247 */
{0x5300, 0xd4c8}, /* '匀' -> 21248 */
{0x5305, 0xb0fc}, /* '包' -> 21253 */
{0x5306, 0xb4d2}, /* '匆' -> 21254 */
{0x5308, 0xd0d9}, /* '匈' -> 21256 */
{0x530d, 0xd9e9}, /* '匍' -> 21261 */
{0x530f, 0xdecb}, /* '匏' -> 21263 */
{0x5310, 0xd9eb}, /* '匐' -> 21264 */
{0x5315, 0xd8b0}, /* '匕' -> 21269 */
{0x5316, 0xbbaf}, /* '化' -> 21270 */
{0x5317, 0xb1b1}, /* '北' -> 21271 */
{0x5319, 0xb3d7}, /* '匙' -> 21273 */
{0x531a, 0xd8ce}, /* '匚' -> 21274 */
{0x531d, 0xd4d1}, /* '匝' -> 21277 */
{0x5320, 0xbdb3}, /* '匠' -> 21280 */
{0x5321, 0xbfef}, /* '匡' -> 21281 */
{0x5323, 0xcfbb}, /* '匣' -> 21283 */
{0x5326, 0xd8d0}, /* '匦' -> 21286 */
{0x532a, 0xb7cb}, /* '匪' -> 21290 */
{0x532e, 0xd8d1}, /* '匮' -> 21294 */
{0x5339, 0xc6a5}, /* '匹' -> 21305 */
{0x533a, 0xc7f8}, /* '区' -> 21306 */
{0x533b, 0xd2bd}, /* '医' -> 21307 */
{0x533e, 0xd8d2}, /* '匾' -> 21310 */
{0x533f, 0xc4e4}, /* '匿' -> 21311 */
{0x5341, 0xcaae}, /* '十' -> 21313 */
{0x5343, 0xc7a7}, /* '千' -> 21315 */
{0x5345, 0xd8a6}, /* '卅' -> 21317 */
{0x5347, 0xc9fd}, /* '升' -> 21319 */
{0x5348, 0xcee7}, /* '午' -> 21320 */
{0x5349, 0xbbdc}, /* '卉' -> 21321 */
{0x534a, 0xb0eb}, /* '半' -> 21322 */
{0x534e, 0xbbaa}, /* '华' -> 21326 */
{0x534f, 0xd0ad}, /* '协' -> 21327 */
{0x5351, 0xb1b0}, /* '卑' -> 21329 */
{0x5352, 0xd7e4}, /* '卒' -> 21330 */
{0x5353, 0xd7bf}, /* '卓' -> 21331 */
{0x5355, 0xb5a5}, /* '单' -> 21333 */
{0x5356, 0xc2f4}, /* '卖' -> 21334 */
{0x5357, 0xc4cf}, /* '南' -> 21335 */
{0x535a, 0xb2a9}, /* '博' -> 21338 */
{0x535c, 0xb2b7}, /* '卜' -> 21340 */
{0x535e, 0xb1e5}, /* '卞' -> 21342 */
{0x535f, 0xdfb2}, /* '卟' -> 21343 */
{0x5360, 0xd5bc}, /* '占' -> 21344 */
{0x5361, 0xbfa8}, /* '卡' -> 21345 */
{0x5362, 0xc2ac}, /* '卢' -> 21346 */
{0x5363, 0xd8d5}, /* '卣' -> 21347 */
{0x5364, 0xc2b1}, /* '卤' -> 21348 */
{0x5366, 0xd8d4}, /* '卦' -> 21350 */
{0x5367, 0xced4}, /* '卧' -> 21351 */
{0x5369, 0xdae0}, /* '卩' -> 21353 */
{0x536b, 0xcec0}, /* '卫' -> 21355 */
{0x536e, 0xd8b4}, /* '卮' -> 21358 */
{0x536f, 0xc3ae}, /* '卯' -> 21359 */
{0x5370, 0xd3a1}, /* '印' -> 21360 */
{0x5371, 0xcea3}, /* '危' -> 21361 */
{0x5373, 0xbcb4}, /* '即' -> 21363 */
{0x5374, 0xc8b4}, /* '却' -> 21364 */
{0x5375, 0xc2d1}, /* '卵' -> 21365 */
{0x5377, 0xbeed}, /* '卷' -> 21367 */
{0x5378, 0xd0b6}, /* '卸' -> 21368 */
{0x537a, 0xdae1}, /* '卺' -> 21370 */
{0x537f, 0xc7e4}, /* '卿' -> 21375 */
{0x5382, 0xb3a7}, /* '厂' -> 21378 */
{0x5384, 0xb6f2}, /* '厄' -> 21380 */
{0x5385, 0xccfc}, /* '厅' -> 21381 */
{0x5386, 0xc0fa}, /* '历' -> 21382 */
{0x5389, 0xc0f7}, /* '厉' -> 21385 */
{0x538b, 0xd1b9}, /* '压' -> 21387 */
{0x538c, 0xd1e1}, /* '厌' -> 21388 */
{0x538d, 0xd8c7}, /* '厍' -> 21389 */
{0x5395, 0xb2de}, /* '厕' -> 21397 */
{0x5398, 0xc0e5}, /* '厘' -> 21400 */
{0x539a, 0xbaf1}, /* '厚' -> 21402 */
{0x539d, 0xd8c8}, /* '厝' -> 21405 */
{0x539f, 0xd4ad}, /* '原' -> 21407 */
{0x53a2, 0xcfe1}, /* '厢' -> 21410 */
{0x53a3, 0xd8c9}, /* '厣' -> 21411 */
{0x53a5, 0xd8ca}, /* '厥' -> 21413 */
{0x53a6, 0xcfc3}, /* '厦' -> 21414 */
{0x53a8, 0xb3f8}, /* '厨' -> 21416 */
{0x53a9, 0xbec7}, /* '厩' -> 21417 */
{0x53ae, 0xd8cb}, /* '厮' -> 21422 */
{0x53b6, 0xdbcc}, /* '厶' -> 21430 */
{0x53bb, 0xc8a5}, /* '去' -> 21435 */
{0x53bf, 0xcfd8}, /* '县' -> 21439 */
{0x53c1, 0xc8fe}, /* '叁' -> 21441 */
{0x53c2, 0xb2ce}, /* '参' -> 21442 */
{0x53c8, 0xd3d6}, /* '又' -> 21448 */
{0x53c9, 0xb2e6}, /* '叉' -> 21449 */
{0x53ca, 0xbcb0}, /* '及' -> 21450 */
{0x53cb, 0xd3d1}, /* '友' -> 21451 */
{0x53cc, 0xcbab}, /* '双' -> 21452 */
{0x53cd, 0xb7b4}, /* '反' -> 21453 */
{0x53d1, 0xb7a2}, /* '发' -> 21457 */
{0x53d4, 0xcae5}, /* '叔' -> 21460 */
{0x53d6, 0xc8a1}, /* '取' -> 21462 */
{0x53d7, 0xcadc}, /* '受' -> 21463 */
{0x53d8, 0xb1e4}, /* '变' -> 21464 */
{0x53d9, 0xd0f0}, /* '叙' -> 21465 */
{0x53db, 0xc5d1}, /* '叛' -> 21467 */
{0x53df, 0xdbc5}, /* '叟' -> 21471 */
{0x53e0, 0xb5fe}, /* '叠' -> 21472 */
{0x53e3, 0xbfda}, /* '口' -> 21475 */
{0x53e4, 0xb9c5}, /* '古' -> 21476 */
{0x53e5, 0xbee4}, /* '句' -> 21477 */
{0x53e6, 0xc1ed}, /* '另' -> 21478 */
{0x53e8, 0xdfb6}, /* '叨' -> 21480 */
{0x53e9, 0xdfb5}, /* '叩' -> 21481 */
{0x53ea, 0xd6bb}, /* '只' -> 21482 */
{0x53eb, 0xbdd0}, /* '叫' -> 21483 */
{0x53ec, 0xd5d9}, /* '召' -> 21484 */
{0x53ed, 0xb0c8}, /* '叭' -> 21485 */
{0x53ee, 0xb6a3}, /* '叮' -> 21486 */
{0x53ef, 0xbfc9}, /* '可' -> 21487 */
{0x53f0, 0xcca8}, /* '台' -> 21488 */
{0x53f1, 0xdfb3}, /* '叱' -> 21489 */
{0x53f2, 0xcab7}, /* '史' -> 21490 */
{0x53f3, 0xd3d2}, /* '右' -> 21491 */
{0x53f5, 0xd8cf}, /* '叵' -> 21493 */
{0x53f6, 0xd2b6}, /* '叶' -> 21494 */
{0x53f7, 0xbac5}, /* '号' -> 21495 */
{0x53f8, 0xcbbe}, /* '司' -> 21496 */
{0x53f9, 0xccbe}, /* '叹' -> 21497 */
{0x53fb, 0xdfb7}, /* '叻' -> 21499 */
{0x53fc, 0xb5f0}, /* '叼' -> 21500 */
{0x53fd, 0xdfb4}, /* '叽' -> 21501 */
{0x5401, 0xd3f5}, /* '吁' -> 21505 */
{0x5403, 0xb3d4}, /* '吃' -> 21507 */
{0x5404, 0xb8f7}, /* '各' -> 21508 */
{0x5406, 0xdfba}, /* '吆' -> 21510 */
{0x5408, 0xbacf}, /* '合' -> 21512 */
{0x5409, 0xbcaa}, /* '吉' -> 21513 */
{0x540a, 0xb5f5}, /* '吊' -> 21514 */
{0x540c, 0xcdac}, /* '同' -> 21516 */
{0x540d, 0xc3fb}, /* '名' -> 21517 */
{0x540e, 0xbaf3}, /* '后' -> 21518 */
{0x540f, 0xc0f4}, /* '吏' -> 21519 */
{0x5410, 0xcdc2}, /* '吐' -> 21520 */
{0x5411, 0xcff2}, /* '向' -> 21521 */
{0x5412, 0xdfb8}, /* '吒' -> 21522 */
{0x5413, 0xcfc5}, /* '吓' -> 21523 */
{0x5415, 0xc2c0}, /* '吕' -> 21525 */
{0x5416, 0xdfb9}, /* '吖' -> 21526 */
{0x5417, 0xc2f0}, /* '吗' -> 21527 */
{0x541b, 0xbefd}, /* '君' -> 21531 */
{0x541d, 0xc1df}, /* '吝' -> 21533 */
{0x541e, 0xcdcc}, /* '吞' -> 21534 */
{0x541f, 0xd2f7}, /* '吟' -> 21535 */
{0x5420, 0xb7cd}, /* '吠' -> 21536 */
{0x5421, 0xdfc1}, /* '吡' -> 21537 */
{0x5423, 0xdfc4}, /* '吣' -> 21539 */
{0x5426, 0xb7f1}, /* '否' -> 21542 */
{0x5427, 0xb0c9}, /* '吧' -> 21543 */
{0x5428, 0xb6d6}, /* '吨' -> 21544 */
{0x5429, 0xb7d4}, /* '吩' -> 21545 */
{0x542b, 0xbaac}, /* '含' -> 21547 */
{0x542c, 0xccfd}, /* '听' -> 21548 */
{0x542d, 0xbfd4}, /* '吭' -> 21549 */
{0x542e, 0xcbb1}, /* '吮' -> 21550 */
{0x542f, 0xc6f4}, /* '启' -> 21551 */
{0x5431, 0xd6a8}, /* '吱' -> 21553 */
{0x5432, 0xdfc5}, /* '吲' -> 21554 */
{0x5434, 0xcee2}, /* '吴' -> 21556 */
{0x5435, 0xb3b3}, /* '吵' -> 21557 */
{0x5438, 0xcefc}, /* '吸' -> 21560 */
{0x5439, 0xb4b5}, /* '吹' -> 21561 */
{0x543b, 0xcec7}, /* '吻' -> 21563 */
{0x543c, 0xbaf0}, /* '吼' -> 21564 */
{0x543e, 0xcee1}, /* '吾' -> 21566 */
{0x5440, 0xd1bd}, /* '呀' -> 21568 */
{0x5443, 0xdfc0}, /* '呃' -> 21571 */
{0x5446, 0xb4f4}, /* '呆' -> 21574 */
{0x5448, 0xb3ca}, /* '呈' -> 21576 */
{0x544a, 0xb8e6}, /* '告' -> 21578 */
{0x544b, 0xdfbb}, /* '呋' -> 21579 */
{0x5450, 0xc4c5}, /* '呐' -> 21584 */
{0x5452, 0xdfbc}, /* '呒' -> 21586 */
{0x5453, 0xdfbd}, /* '呓' -> 21587 */
{0x5454, 0xdfbe}, /* '呔' -> 21588 */
{0x5455, 0xc5bb}, /* '呕' -> 21589 */
{0x5456, 0xdfbf}, /* '呖' -> 21590 */
{0x5457, 0xdfc2}, /* '呗' -> 21591 */
{0x5458, 0xd4b1}, /* '员' -> 21592 */
{0x5459, 0xdfc3}, /* '呙' -> 21593 */
{0x545b, 0xc7ba}, /* '呛' -> 21595 */
{0x545c, 0xced8}, /* '呜' -> 21596 */
{0x5462, 0xc4d8}, /* '呢' -> 21602 */
{0x5464, 0xdfca}, /* '呤' -> 21604 */
{0x5466, 0xdfcf}, /* '呦' -> 21606 */
{0x5468, 0xd6dc}, /* '周' -> 21608 */
{0x5471, 0xdfc9}, /* '呱' -> 21617 */
{0x5472, 0xdfda}, /* '呲' -> 21618 */
{0x5473, 0xceb6}, /* '味' -> 21619 */
{0x5475, 0xbac7}, /* '呵' -> 21621 */
{0x5476, 0xdfce}, /* '呶' -> 21622 */
{0x5477, 0xdfc8}, /* '呷' -> 21623 */
{0x5478, 0xc5de}, /* '呸' -> 21624 */
{0x547b, 0xc9eb}, /* '呻' -> 21627 */
{0x547c, 0xbaf4}, /* '呼' -> 21628 */
{0x547d, 0xc3fc}, /* '命' -> 21629 */
{0x5480, 0xbed7}, /* '咀' -> 21632 */
{0x5482, 0xdfc6}, /* '咂' -> 21634 */
{0x5484, 0xdfcd}, /* '咄' -> 21636 */
{0x5486, 0xc5d8}, /* '咆' -> 21638 */
{0x548b, 0xd5a6}, /* '咋' -> 21643 */
{0x548c, 0xbacd}, /* '和' -> 21644 */
{0x548e, 0xbecc}, /* '咎' -> 21646 */
{0x548f, 0xd3bd}, /* '咏' -> 21647 */
{0x5490, 0xb8c0}, /* '咐' -> 21648 */
{0x5492, 0xd6e4}, /* '咒' -> 21650 */
{0x5494, 0xdfc7}, /* '咔' -> 21652 */
{0x5495, 0xb9be}, /* '咕' -> 21653 */
{0x5496, 0xbfa7}, /* '咖' -> 21654 */
{0x5499, 0xc1fc}, /* '咙' -> 21657 */
{0x549a, 0xdfcb}, /* '咚' -> 21658 */
{0x549b, 0xdfcc}, /* '咛' -> 21659 */
{0x549d, 0xdfd0}, /* '咝' -> 21661 */
{0x54a3, 0xdfdb}, /* '咣' -> 21667 */
{0x54a4, 0xdfe5}, /* '咤' -> 21668 */
{0x54a6, 0xdfd7}, /* '咦' -> 21670 */
{0x54a7, 0xdfd6}, /* '咧' -> 21671 */
{0x54a8, 0xd7c9}, /* '咨' -> 21672 */
{0x54a9, 0xdfe3}, /* '咩' -> 21673 */
{0x54aa, 0xdfe4}, /* '咪' -> 21674 */
{0x54ab, 0xe5eb}, /* '咫' -> 21675 */
{0x54ac, 0xd2a7}, /* '咬' -> 21676 */
{0x54ad, 0xdfd2}, /* '咭' -> 21677 */
{0x54af, 0xbfa9}, /* '咯' -> 21679 */
{0x54b1, 0xd4db}, /* '咱' -> 21681 */
{0x54b3, 0xbfc8}, /* '咳' -> 21683 */
{0x54b4, 0xdfd4}, /* '咴' -> 21684 */
{0x54b8, 0xcfcc}, /* '咸' -> 21688 */
{0x54bb, 0xdfdd}, /* '咻' -> 21691 */
{0x54bd, 0xd1ca}, /* '咽' -> 21693 */
{0x54bf, 0xdfde}, /* '咿' -> 21695 */
{0x54c0, 0xb0a7}, /* '哀' -> 21696 */
{0x54c1, 0xc6b7}, /* '品' -> 21697 */
{0x54c2, 0xdfd3}, /* '哂' -> 21698 */
{0x54c4, 0xbae5}, /* '哄' -> 21700 */
{0x54c6, 0xb6df}, /* '哆' -> 21702 */
{0x54c7, 0xcddb}, /* '哇' -> 21703 */
{0x54c8, 0xb9fe}, /* '哈' -> 21704 */
{0x54c9, 0xd4d5}, /* '哉' -> 21705 */
{0x54cc, 0xdfdf}, /* '哌' -> 21708 */
{0x54cd, 0xcfec}, /* '响' -> 21709 */
{0x54ce, 0xb0a5}, /* '哎' -> 21710 */
{0x54cf, 0xdfe7}, /* '哏' -> 21711 */
{0x54d0, 0xdfd1}, /* '哐' -> 21712 */
{0x54d1, 0xd1c6}, /* '哑' -> 21713 */
{0x54d2, 0xdfd5}, /* '哒' -> 21714 */
{0x54d3, 0xdfd8}, /* '哓' -> 21715 */
{0x54d4, 0xdfd9}, /* '哔' -> 21716 */
{0x54d5, 0xdfdc}, /* '哕' -> 21717 */
{0x54d7, 0xbba9}, /* '哗' -> 21719 */
{0x54d9, 0xdfe0}, /* '哙' -> 21721 */
{0x54da, 0xdfe1}, /* '哚' -> 21722 */
{0x54dc, 0xdfe2}, /* '哜' -> 21724 */
{0x54dd, 0xdfe6}, /* '哝' -> 21725 */
{0x54de, 0xdfe8}, /* '哞' -> 21726 */
{0x54df, 0xd3b4}, /* '哟' -> 21727 */
{0x54e5, 0xb8e7}, /* '哥' -> 21733 */
{0x54e6, 0xc5b6}, /* '哦' -> 21734 */
{0x54e7, 0xdfea}, /* '哧' -> 21735 */
{0x54e8, 0xc9da}, /* '哨' -> 21736 */
{0x54e9, 0xc1a8}, /* '哩' -> 21737 */
{0x54ea, 0xc4c4}, /* '哪' -> 21738 */
{0x54ed, 0xbfde}, /* '哭' -> 21741 */
{0x54ee, 0xcff8}, /* '哮' -> 21742 */
{0x54f2, 0xd5dc}, /* '哲' -> 21746 */
{0x54f3, 0xdfee}, /* '哳' -> 21747 */
{0x54fa, 0xb2b8}, /* '哺' -> 21754 */
{0x54fc, 0xbadf}, /* '哼' -> 21756 */
{0x54fd, 0xdfec}, /* '哽' -> 21757 */
{0x54ff, 0xdbc1}, /* '哿' -> 21759 */
{0x5501, 0xd1e4}, /* '唁' -> 21761 */
{0x5506, 0xcbf4}, /* '唆' -> 21766 */
{0x5507, 0xb4bd}, /* '唇' -> 21767 */
{0x5509, 0xb0a6}, /* '唉' -> 21769 */
{0x550f, 0xdff1}, /* '唏' -> 21775 */
{0x5510, 0xccc6}, /* '唐' -> 21776 */
{0x5511, 0xdff2}, /* '唑' -> 21777 */
{0x5514, 0xdfed}, /* '唔' -> 21780 */
{0x551b, 0xdfe9}, /* '唛' -> 21787 */
{0x5520, 0xdfeb}, /* '唠' -> 21792 */
{0x5522, 0xdfef}, /* '唢' -> 21794 */
{0x5523, 0xdff0}, /* '唣' -> 21795 */
{0x5524, 0xbbbd}, /* '唤' -> 21796 */
{0x5527, 0xdff3}, /* '唧' -> 21799 */
{0x552a, 0xdff4}, /* '唪' -> 21802 */
{0x552c, 0xbba3}, /* '唬' -> 21804 */
{0x552e, 0xcadb}, /* '售' -> 21806 */
{0x552f, 0xcea8}, /* '唯' -> 21807 */
{0x5530, 0xe0a7}, /* '唰' -> 21808 */
{0x5531, 0xb3aa}, /* '唱' -> 21809 */
{0x5533, 0xe0a6}, /* '唳' -> 21811 */
{0x5537, 0xe0a1}, /* '唷' -> 21815 */
{0x553c, 0xdffe}, /* '唼' -> 21820 */
{0x553e, 0xcdd9}, /* '唾' -> 21822 */
{0x553f, 0xdffc}, /* '唿' -> 21823 */
{0x5541, 0xdffa}, /* '啁' -> 21825 */
{0x5543, 0xbfd0}, /* '啃' -> 21827 */
{0x5544, 0xd7c4}, /* '啄' -> 21828 */
{0x5546, 0xc9cc}, /* '商' -> 21830 */
{0x5549, 0xdff8}, /* '啉' -> 21833 */
{0x554a, 0xb0a1}, /* '啊' -> 21834 */
{0x5550, 0xdffd}, /* '啐' -> 21840 */
{0x5555, 0xdffb}, /* '啕' -> 21845 */
{0x5556, 0xe0a2}, /* '啖' -> 21846 */
{0x555c, 0xe0a8}, /* '啜' -> 21852 */
{0x5561, 0xb7c8}, /* '啡' -> 21857 */
{0x5564, 0xc6a1}, /* '啤' -> 21860 */
{0x5565, 0xc9b6}, /* '啥' -> 21861 */
{0x5566, 0xc0b2}, /* '啦' -> 21862 */
{0x5567, 0xdff5}, /* '啧' -> 21863 */
{0x556a, 0xc5be}, /* '啪' -> 21866 */
{0x556c, 0xd8c4}, /* '啬' -> 21868 */
{0x556d, 0xdff9}, /* '啭' -> 21869 */
{0x556e, 0xc4f6}, /* '啮' -> 21870 */
{0x5575, 0xe0a3}, /* '啵' -> 21877 */
{0x5576, 0xe0a4}, /* '啶' -> 21878 */
{0x5577, 0xe0a5}, /* '啷' -> 21879 */
{0x5578, 0xd0a5}, /* '啸' -> 21880 */
{0x557b, 0xe0b4}, /* '啻' -> 21883 */
{0x557c, 0xcce4}, /* '啼' -> 21884 */
{0x557e, 0xe0b1}, /* '啾' -> 21886 */
{0x5580, 0xbfa6}, /* '喀' -> 21888 */
{0x5581, 0xe0af}, /* '喁' -> 21889 */
{0x5582, 0xceb9}, /* '喂' -> 21890 */
{0x5583, 0xe0ab}, /* '喃' -> 21891 */
{0x5584, 0xc9c6}, /* '善' -> 21892 */
{0x5587, 0xc0ae}, /* '喇' -> 21895 */
{0x5588, 0xe0ae}, /* '喈' -> 21896 */
{0x5589, 0xbaed}, /* '喉' -> 21897 */
{0x558a, 0xbab0}, /* '喊' -> 21898 */
{0x558b, 0xe0a9}, /* '喋' -> 21899 */
{0x558f, 0xdff6}, /* '喏' -> 21903 */
{0x5591, 0xe0b3}, /* '喑' -> 21905 */
{0x5594, 0xe0b8}, /* '喔' -> 21908 */
{0x5598, 0xb4ad}, /* '喘' -> 21912 */
{0x5599, 0xe0b9}, /* '喙' -> 21913 */
{0x559c, 0xcfb2}, /* '喜' -> 21916 */
{0x559d, 0xbac8}, /* '喝' -> 21917 */
{0x559f, 0xe0b0}, /* '喟' -> 21919 */
{0x55a7, 0xd0fa}, /* '喧' -> 21927 */
{0x55b1, 0xe0ac}, /* '喱' -> 21937 */
{0x55b3, 0xd4fb}, /* '喳' -> 21939 */
{0x55b5, 0xdff7}, /* '喵' -> 21941 */
{0x55b7, 0xc5e7}, /* '喷' -> 21943 */
{0x55b9, 0xe0ad}, /* '喹' -> 21945 */
{0x55bb, 0xd3f7}, /* '喻' -> 21947 */
{0x55bd, 0xe0b6}, /* '喽' -> 21949 */
{0x55be, 0xe0b7}, /* '喾' -> 21950 */
{0x55c4, 0xe0c4}, /* '嗄' -> 21956 */
{0x55c5, 0xd0e1}, /* '嗅' -> 21957 */
{0x55c9, 0xe0bc}, /* '嗉' -> 21961 */
{0x55cc, 0xe0c9}, /* '嗌' -> 21964 */
{0x55cd, 0xe0ca}, /* '嗍' -> 21965 */
{0x55d1, 0xe0be}, /* '嗑' -> 21969 */
{0x55d2, 0xe0aa}, /* '嗒' -> 21970 */
{0x55d3, 0xc9a4}, /* '嗓' -> 21971 */
{0x55d4, 0xe0c1}, /* '嗔' -> 21972 */
{0x55d6, 0xe0b2}, /* '嗖' -> 21974 */
{0x55dc, 0xcac8}, /* '嗜' -> 21980 */
{0x55dd, 0xe0c3}, /* '嗝' -> 21981 */
{0x55df, 0xe0b5}, /* '嗟' -> 21983 */
{0x55e1, 0xcecb}, /* '嗡' -> 21985 */
{0x55e3, 0xcbc3}, /* '嗣' -> 21987 */
{0x55e4, 0xe0cd}, /* '嗤' -> 21988 */
{0x55e5, 0xe0c6}, /* '嗥' -> 21989 */
{0x55e6, 0xe0c2}, /* '嗦' -> 21990 */
{0x55e8, 0xe0cb}, /* '嗨' -> 21992 */
{0x55ea, 0xe0ba}, /* '嗪' -> 21994 */
{0x55eb, 0xe0bf}, /* '嗫' -> 21995 */
{0x55ec, 0xe0c0}, /* '嗬' -> 21996 */
{0x55ef, 0xe0c5}, /* '嗯' -> 21999 */
{0x55f2, 0xe0c7}, /* '嗲' -> 22002 */
{0x55f3, 0xe0c8}, /* '嗳' -> 22003 */
{0x55f5, 0xe0cc}, /* '嗵' -> 22005 */
{0x55f7, 0xe0bb}, /* '嗷' -> 22007 */
{0x55fd, 0xcbd4}, /* '嗽' -> 22013 */
{0x55fe, 0xe0d5}, /* '嗾' -> 22014 */
{0x5600, 0xe0d6}, /* '嘀' -> 22016 */
{0x5601, 0xe0d2}, /* '嘁' -> 22017 */
{0x5608, 0xe0d0}, /* '嘈' -> 22024 */
{0x5609, 0xbcce}, /* '嘉' -> 22025 */
{0x560c, 0xe0d1}, /* '嘌' -> 22028 */
{0x560e, 0xb8c2}, /* '嘎' -> 22030 */
{0x560f, 0xd8c5}, /* '嘏' -> 22031 */
{0x5618, 0xd0ea}, /* '嘘' -> 22040 */
{0x561b, 0xc2ef}, /* '嘛' -> 22043 */
{0x561e, 0xe0cf}, /* '嘞' -> 22046 */
{0x561f, 0xe0bd}, /* '嘟' -> 22047 */
{0x5623, 0xe0d4}, /* '嘣' -> 22051 */
{0x5624, 0xe0d3}, /* '嘤' -> 22052 */
{0x5627, 0xe0d7}, /* '嘧' -> 22055 */
{0x562c, 0xe0dc}, /* '嘬' -> 22060 */
{0x562d, 0xe0d8}, /* '嘭' -> 22061 */
{0x5631, 0xd6f6}, /* '嘱' -> 22065 */
{0x5632, 0xb3b0}, /* '嘲' -> 22066 */
{0x5634, 0xd7ec}, /* '嘴' -> 22068 */
{0x5636, 0xcbbb}, /* '嘶' -> 22070 */
{0x5639, 0xe0da}, /* '嘹' -> 22073 */
{0x563b, 0xcefb}, /* '嘻' -> 22075 */
{0x563f, 0xbad9}, /* '嘿' -> 22079 */
{0x564c, 0xe0e1}, /* '噌' -> 22092 */
{0x564d, 0xe0dd}, /* '噍' -> 22093 */
{0x564e, 0xd2ad}, /* '噎' -> 22094 */
{0x5654, 0xe0e2}, /* '噔' -> 22100 */
{0x5657, 0xe0db}, /* '噗' -> 22103 */
{0x5658, 0xe0d9}, /* '噘' -> 22104 */
{0x5659, 0xe0df}, /* '噙' -> 22105 */
{0x565c, 0xe0e0}, /* '噜' -> 22108 */
{0x5662, 0xe0de}, /* '噢' -> 22114 */
{0x5664, 0xe0e4}, /* '噤' -> 22116 */
{0x5668, 0xc6f7}, /* '器' -> 22120 */
{0x5669, 0xd8ac}, /* '噩' -> 22121 */
{0x566a, 0xd4eb}, /* '噪' -> 22122 */
{0x566b, 0xe0e6}, /* '噫' -> 22123 */
{0x566c, 0xcac9}, /* '噬' -> 22124 */
{0x5671, 0xe0e5}, /* '噱' -> 22129 */
{0x5676, 0xb8c1}, /* '噶' -> 22134 */
{0x567b, 0xe0e7}, /* '噻' -> 22139 */
{0x567c, 0xe0e8}, /* '噼' -> 22140 */
{0x5685, 0xe0e9}, /* '嚅' -> 22149 */
{0x5686, 0xe0e3}, /* '嚆' -> 22150 */
{0x568e, 0xbabf}, /* '嚎' -> 22158 */
{0x568f, 0xcce7}, /* '嚏' -> 22159 */
{0x5693, 0xe0ea}, /* '嚓' -> 22163 */
{0x56a3, 0xcff9}, /* '嚣' -> 22179 */
{0x56af, 0xe0eb}, /* '嚯' -> 22191 */
{0x56b7, 0xc8c2}, /* '嚷' -> 22199 */
{0x56bc, 0xbdc0}, /* '嚼' -> 22204 */
{0x56ca, 0xc4d2}, /* '囊' -> 22218 */
{0x56d4, 0xe0ec}, /* '囔' -> 22228 */
{0x56d7, 0xe0ed}, /* '囗' -> 22231 */
{0x56da, 0xc7f4}, /* '囚' -> 22234 */
{0x56db, 0xcbc4}, /* '四' -> 22235 */
{0x56dd, 0xe0ee}, /* '囝' -> 22237 */
{0x56de, 0xbbd8}, /* '回' -> 22238 */
{0x56df, 0xd8b6}, /* '囟' -> 22239 */
{0x56e0, 0xd2f2}, /* '因' -> 22240 */
{0x56e1, 0xe0ef}, /* '囡' -> 22241 */
{0x56e2, 0xcdc5}, /* '团' -> 22242 */
{0x56e4, 0xb6da}, /* '囤' -> 22244 */
{0x56eb, 0xe0f1}, /* '囫' -> 22251 */
{0x56ed, 0xd4b0}, /* '园' -> 22253 */
{0x56f0, 0xc0a7}, /* '困' -> 22256 */
{0x56f1, 0xb4d1}, /* '囱' -> 22257 */
{0x56f4, 0xcea7}, /* '围' -> 22260 */
{0x56f5, 0xe0f0}, /* '囵' -> 22261 */
{0x56f9, 0xe0f2}, /* '囹' -> 22265 */
{0x56fa, 0xb9cc}, /* '固' -> 22266 */
{0x56fd, 0xb9fa}, /* '国' -> 22269 */
{0x56fe, 0xcdbc}, /* '图' -> 22270 */
{0x56ff, 0xe0f3}, /* '囿' -> 22271 */
{0x5703, 0xc6d4}, /* '圃' -> 22275 */
{0x5704, 0xe0f4}, /* '圄' -> 22276 */
{0x5706, 0xd4b2}, /* '圆' -> 22278 */
{0x5708, 0xc8a6}, /* '圈' -> 22280 */
{0x5709, 0xe0f6}, /* '圉' -> 22281 */
{0x570a, 0xe0f5}, /* '圊' -> 22282 */
{0x571c, 0xe0f7}, /* '圜' -> 22300 */
{0x571f, 0xcdc1}, /* '土' -> 22303 */
{0x5723, 0xcaa5}, /* '圣' -> 22307 */
{0x5728, 0xd4da}, /* '在' -> 22312 */
{0x5729, 0xdbd7}, /* '圩' -> 22313 */
{0x572a, 0xdbd9}, /* '圪' -> 22314 */
{0x572c, 0xdbd8}, /* '圬' -> 22316 */
{0x572d, 0xb9e7}, /* '圭' -> 22317 */
{0x572e, 0xdbdc}, /* '圮' -> 22318 */
{0x572f, 0xdbdd}, /* '圯' -> 22319 */
{0x5730, 0xb5d8}, /* '地' -> 22320 */
{0x5733, 0xdbda}, /* '圳' -> 22323 */
{0x5739, 0xdbdb}, /* '圹' -> 22329 */
{0x573a, 0xb3a1}, /* '场' -> 22330 */
{0x573b, 0xdbdf}, /* '圻' -> 22331 */
{0x573e, 0xbbf8}, /* '圾' -> 22334 */
{0x5740, 0xd6b7}, /* '址' -> 22336 */
{0x5742, 0xdbe0}, /* '坂' -> 22338 */
{0x5747, 0xbef9}, /* '均' -> 22343 */
{0x574a, 0xb7bb}, /* '坊' -> 22346 */
{0x574c, 0xdbd0}, /* '坌' -> 22348 */
{0x574d, 0xccae}, /* '坍' -> 22349 */
{0x574e, 0xbfb2}, /* '坎' -> 22350 */
{0x574f, 0xbbb5}, /* '坏' -> 22351 */
{0x5750, 0xd7f8}, /* '坐' -> 22352 */
{0x5751, 0xbfd3}, /* '坑' -> 22353 */
{0x5757, 0xbfe9}, /* '块' -> 22359 */
{0x575a, 0xbce1}, /* '坚' -> 22362 */
{0x575b, 0xccb3}, /* '坛' -> 22363 */
{0x575c, 0xdbde}, /* '坜' -> 22364 */
{0x575d, 0xb0d3}, /* '坝' -> 22365 */
{0x575e, 0xceeb}, /* '坞' -> 22366 */
{0x575f, 0xb7d8}, /* '坟' -> 22367 */
{0x5760, 0xd7b9}, /* '坠' -> 22368 */
{0x5761, 0xc6c2}, /* '坡' -> 22369 */
{0x5764, 0xc0a4}, /* '坤' -> 22372 */
{0x5766, 0xccb9}, /* '坦' -> 22374 */
{0x5768, 0xdbe7}, /* '坨' -> 22376 */
{0x5769, 0xdbe1}, /* '坩' -> 22377 */
{0x576a, 0xc6ba}, /* '坪' -> 22378 */
{0x576b, 0xdbe3}, /* '坫' -> 22379 */
{0x576d, 0xdbe8}, /* '坭' -> 22381 */
{0x576f, 0xc5f7}, /* '坯' -> 22383 */
{0x5773, 0xdbea}, /* '坳' -> 22387 */
{0x5776, 0xdbe9}, /* '坶' -> 22390 */
{0x5777, 0xbfc0}, /* '坷' -> 22391 */
{0x577b, 0xdbe6}, /* '坻' -> 22395 */
{0x577c, 0xdbe5}, /* '坼' -> 22396 */
{0x5782, 0xb4b9}, /* '垂' -> 22402 */
{0x5783, 0xc0ac}, /* '垃' -> 22403 */
{0x5784, 0xc2a2}, /* '垄' -> 22404 */
{0x5785, 0xdbe2}, /* '垅' -> 22405 */
{0x5786, 0xdbe4}, /* '垆' -> 22406 */
{0x578b, 0xd0cd}, /* '型' -> 22411 */
{0x578c, 0xdbed}, /* '垌' -> 22412 */
{0x5792, 0xc0dd}, /* '垒' -> 22418 */
{0x5793, 0xdbf2}, /* '垓' -> 22419 */
{0x579b, 0xb6e2}, /* '垛' -> 22427 */
{0x57a0, 0xdbf3}, /* '垠' -> 22432 */
{0x57a1, 0xdbd2}, /* '垡' -> 22433 */
{0x57a2, 0xb9b8}, /* '垢' -> 22434 */
{0x57a3, 0xd4ab}, /* '垣' -> 22435 */
{0x57a4, 0xdbec}, /* '垤' -> 22436 */
{0x57a6, 0xbfd1}, /* '垦' -> 22438 */
{0x57a7, 0xdbf0}, /* '垧' -> 22439 */
{0x57a9, 0xdbd1}, /* '垩' -> 22441 */
{0x57ab, 0xb5e6}, /* '垫' -> 22443 */
{0x57ad, 0xdbeb}, /* '垭' -> 22445 */
{0x57ae, 0xbfe5}, /* '垮' -> 22446 */
{0x57b2, 0xdbee}, /* '垲' -> 22450 */
{0x57b4, 0xdbf1}, /* '垴' -> 22452 */
{0x57b8, 0xdbf9}, /* '垸' -> 22456 */
{0x57c2, 0xb9a1}, /* '埂' -> 22466 */
{0x57c3, 0xb0a3}, /* '埃' -> 22467 */
{0x57cb, 0xc2f1}, /* '埋' -> 22475 */
{0x57ce, 0xb3c7}, /* '城' -> 22478 */
{0x57cf, 0xdbef}, /* '埏' -> 22479 */
{0x57d2, 0xdbf8}, /* '埒' -> 22482 */
{0x57d4, 0xc6d2}, /* '埔' -> 22484 */
{0x57d5, 0xdbf4}, /* '埕' -> 22485 */
{0x57d8, 0xdbf5}, /* '埘' -> 22488 */
{0x57d9, 0xdbf7}, /* '埙' -> 22489 */
{0x57da, 0xdbf6}, /* '埚' -> 22490 */
{0x57dd, 0xdbfe}, /* '埝' -> 22493 */
{0x57df, 0xd3f2}, /* '域' -> 22495 */
{0x57e0, 0xb2ba}, /* '埠' -> 22496 */
{0x57e4, 0xdbfd}, /* '埤' -> 22500 */
{0x57ed, 0xdca4}, /* '埭' -> 22509 */
{0x57ef, 0xdbfb}, /* '埯' -> 22511 */
{0x57f4, 0xdbfa}, /* '埴' -> 22516 */
{0x57f8, 0xdbfc}, /* '埸' -> 22520 */
{0x57f9, 0xc5e0}, /* '培' -> 22521 */
{0x57fa, 0xbbf9}, /* '基' -> 22522 */
{0x57fd, 0xdca3}, /* '埽' -> 22525 */
{0x5800, 0xdca5}, /* '堀' -> 22528 */
{0x5802, 0xccc3}, /* '堂' -> 22530 */
{0x5806, 0xb6d1}, /* '堆' -> 22534 */
{0x5807, 0xddc0}, /* '堇' -> 22535 */
{0x580b, 0xdca1}, /* '堋' -> 22539 */
{0x580d, 0xdca2}, /* '堍' -> 22541 */
{0x5811, 0xc7b5}, /* '堑' -> 22545 */
{0x5815, 0xb6e9}, /* '堕' -> 22549 */
{0x5819, 0xdca7}, /* '堙' -> 22553 */
{0x581e, 0xdca6}, /* '堞' -> 22558 */
{0x5820, 0xdca9}, /* '堠' -> 22560 */
{0x5821, 0xb1a4}, /* '堡' -> 22561 */
{0x5824, 0xb5cc}, /* '堤' -> 22564 */
{0x582a, 0xbfb0}, /* '堪' -> 22570 */
{0x5830, 0xd1df}, /* '堰' -> 22576 */
{0x5835, 0xb6c2}, /* '堵' -> 22581 */
{0x5844, 0xdca8}, /* '塄' -> 22596 */
{0x584c, 0xcbfa}, /* '塌' -> 22604 */
{0x584d, 0xebf3}, /* '塍' -> 22605 */
{0x5851, 0xcbdc}, /* '塑' -> 22609 */
{0x5854, 0xcbfe}, /* '塔' -> 22612 */
{0x5858, 0xccc1}, /* '塘' -> 22616 */
{0x585e, 0xc8fb}, /* '塞' -> 22622 */
{0x5865, 0xdcaa}, /* '塥' -> 22629 */
{0x586b, 0xccee}, /* '填' -> 22635 */
{0x586c, 0xdcab}, /* '塬' -> 22636 */
{0x587e, 0xdbd3}, /* '塾' -> 22654 */
{0x5880, 0xdcaf}, /* '墀' -> 22656 */
{0x5881, 0xdcac}, /* '墁' -> 22657 */
{0x5883, 0xbeb3}, /* '境' -> 22659 */
{0x5885, 0xcafb}, /* '墅' -> 22661 */
{0x5889, 0xdcad}, /* '墉' -> 22665 */
{0x5892, 0xc9ca}, /* '墒' -> 22674 */
{0x5893, 0xc4b9}, /* '墓' -> 22675 */
{0x5899, 0xc7bd}, /* '墙' -> 22681 */
{0x589a, 0xdcae}, /* '墚' -> 22682 */
{0x589e, 0xd4f6}, /* '增' -> 22686 */
{0x589f, 0xd0e6}, /* '墟' -> 22687 */
{0x58a8, 0xc4ab}, /* '墨' -> 22696 */
{0x58a9, 0xb6d5}, /* '墩' -> 22697 */
{0x58bc, 0xdbd4}, /* '墼' -> 22716 */
{0x58c1, 0xb1da}, /* '壁' -> 22721 */
{0x58c5, 0xdbd5}, /* '壅' -> 22725 */
{0x58d1, 0xdbd6}, /* '壑' -> 22737 */
{0x58d5, 0xbabe}, /* '壕' -> 22741 */
{0x58e4, 0xc8c0}, /* '壤' -> 22756 */
{0x58eb, 0xcabf}, /* '士' -> 22763 */
{0x58ec, 0xc8c9}, /* '壬' -> 22764 */
{0x58ee, 0xd7b3}, /* '壮' -> 22766 */
{0x58f0, 0xc9f9}, /* '声' -> 22768 */
{0x58f3, 0xbfc7}, /* '壳' -> 22771 */
{0x58f6, 0xbaf8}, /* '壶' -> 22774 */
{0x58f9, 0xd2bc}, /* '壹' -> 22777 */
{0x5902, 0xe2ba}, /* '夂' -> 22786 */
{0x5904, 0xb4a6}, /* '处' -> 22788 */
{0x5907, 0xb1b8}, /* '备' -> 22791 */
{0x590d, 0xb8b4}, /* '复' -> 22797 */
{0x590f, 0xcfc4}, /* '夏' -> 22799 */
{0x5914, 0xd9e7}, /* '夔' -> 22804 */
{0x5915, 0xcfa6}, /* '夕' -> 22805 */
{0x5916, 0xcde2}, /* '外' -> 22806 */
{0x5919, 0xd9ed}, /* '夙' -> 22809 */
{0x591a, 0xb6e0}, /* '多' -> 22810 */
{0x591c, 0xd2b9}, /* '夜' -> 22812 */
{0x591f, 0xb9bb}, /* '够' -> 22815 */
{0x5924, 0xe2b9}, /* '夤' -> 22820 */
{0x5925, 0xe2b7}, /* '夥' -> 22821 */
{0x5927, 0xb4f3}, /* '大' -> 22823 */
{0x5929, 0xccec}, /* '天' -> 22825 */
{0x592a, 0xccab}, /* '太' -> 22826 */
{0x592b, 0xb7f2}, /* '夫' -> 22827 */
{0x592d, 0xd8b2}, /* '夭' -> 22829 */
{0x592e, 0xd1eb}, /* '央' -> 22830 */
{0x592f, 0xbabb}, /* '夯' -> 22831 */
{0x5931, 0xcaa7}, /* '失' -> 22833 */
{0x5934, 0xcdb7}, /* '头' -> 22836 */
{0x5937, 0xd2c4}, /* '夷' -> 22839 */
{0x5938, 0xbfe4}, /* '夸' -> 22840 */
{0x5939, 0xbcd0}, /* '夹' -> 22841 */
{0x593a, 0xb6e1}, /* '夺' -> 22842 */
{0x593c, 0xdec5}, /* '夼' -> 22844 */
{0x5941, 0xdec6}, /* '奁' -> 22849 */
{0x5942, 0xdbbc}, /* '奂' -> 22850 */
{0x5944, 0xd1d9}, /* '奄' -> 22852 */
{0x5947, 0xc6e6}, /* '奇' -> 22855 */
{0x5948, 0xc4ce}, /* '奈' -> 22856 */
{0x5949, 0xb7ee}, /* '奉' -> 22857 */
{0x594b, 0xb7dc}, /* '奋' -> 22859 */
{0x594e, 0xbffc}, /* '奎' -> 22862 */
{0x594f, 0xd7e0}, /* '奏' -> 22863 */
{0x5951, 0xc6f5}, /* '契' -> 22865 */
{0x5954, 0xb1bc}, /* '奔' -> 22868 */
{0x5955, 0xdec8}, /* '奕' -> 22869 */
{0x5956, 0xbdb1}, /* '奖' -> 22870 */
{0x5957, 0xccd7}, /* '套' -> 22871 */
{0x5958, 0xdeca}, /* '奘' -> 22872 */
{0x595a, 0xdec9}, /* '奚' -> 22874 */
{0x5960, 0xb5ec}, /* '奠' -> 22880 */
{0x5962, 0xc9dd}, /* '奢' -> 22882 */
{0x5965, 0xb0c2}, /* '奥' -> 22885 */
{0x5973, 0xc5ae}, /* '女' -> 22899 */
{0x5974, 0xc5ab}, /* '奴' -> 22900 */
{0x5976, 0xc4cc}, /* '奶' -> 22902 */
{0x5978, 0xbce9}, /* '奸' -> 22904 */
{0x5979, 0xcbfd}, /* '她' -> 22905 */
{0x597d, 0xbac3}, /* '好' -> 22909 */
{0x5981, 0xe5f9}, /* '妁' -> 22913 */
{0x5982, 0xc8e7}, /* '如' -> 22914 */
{0x5983, 0xe5fa}, /* '妃' -> 22915 */
{0x5984, 0xcdfd}, /* '妄' -> 22916 */
{0x5986, 0xd7b1}, /* '妆' -> 22918 */
{0x5987, 0xb8be}, /* '妇' -> 22919 */
{0x5988, 0xc2e8}, /* '妈' -> 22920 */
{0x598a, 0xc8d1}, /* '妊' -> 22922 */
{0x598d, 0xe5fb}, /* '妍' -> 22925 */
{0x5992, 0xb6ca}, /* '妒' -> 22930 */
{0x5993, 0xbccb}, /* '妓' -> 22931 */
{0x5996, 0xd1fd}, /* '妖' -> 22934 */
{0x5997, 0xe6a1}, /* '妗' -> 22935 */
{0x5999, 0xc3ee}, /* '妙' -> 22937 */
{0x599e, 0xe6a4}, /* '妞' -> 22942 */
{0x59a3, 0xe5fe}, /* '妣' -> 22947 */
{0x59a4, 0xe6a5}, /* '妤' -> 22948 */
{0x59a5, 0xcdd7}, /* '妥' -> 22949 */
{0x59a8, 0xb7c1}, /* '妨' -> 22952 */
{0x59a9, 0xe5fc}, /* '妩' -> 22953 */
{0x59aa, 0xe5fd}, /* '妪' -> 22954 */
{0x59ab, 0xe6a3}, /* '妫' -> 22955 */
{0x59ae, 0xc4dd}, /* '妮' -> 22958 */
{0x59af, 0xe6a8}, /* '妯' -> 22959 */
{0x59b2, 0xe6a7}, /* '妲' -> 22962 */
{0x59b9, 0xc3c3}, /* '妹' -> 22969 */
{0x59bb, 0xc6de}, /* '妻' -> 22971 */
{0x59be, 0xe6aa}, /* '妾' -> 22974 */
{0x59c6, 0xc4b7}, /* '姆' -> 22982 */
{0x59ca, 0xe6a2}, /* '姊' -> 22986 */
{0x59cb, 0xcabc}, /* '始' -> 22987 */
{0x59d0, 0xbde3}, /* '姐' -> 22992 */
{0x59d1, 0xb9c3}, /* '姑' -> 22993 */
{0x59d2, 0xe6a6}, /* '姒' -> 22994 */
{0x59d3, 0xd0d5}, /* '姓' -> 22995 */
{0x59d4, 0xceaf}, /* '委' -> 22996 */
{0x59d7, 0xe6a9}, /* '姗' -> 22999 */
{0x59d8, 0xe6b0}, /* '姘' -> 23000 */
{0x59da, 0xd2a6}, /* '姚' -> 23002 */
{0x59dc, 0xbdaa}, /* '姜' -> 23004 */
{0x59dd, 0xe6ad}, /* '姝' -> 23005 */
{0x59e3, 0xe6af}, /* '姣' -> 23011 */
{0x59e5, 0xc0d1}, /* '姥' -> 23013 */
{0x59e8, 0xd2cc}, /* '姨' -> 23016 */
{0x59ec, 0xbca7}, /* '姬' -> 23020 */
{0x59f9, 0xe6b1}, /* '姹' -> 23033 */
{0x59fb, 0xd2f6}, /* '姻' -> 23035 */
{0x59ff, 0xd7cb}, /* '姿' -> 23039 */
{0x5a01, 0xcdfe}, /* '威' -> 23041 */
{0x5a03, 0xcdde}, /* '娃' -> 23043 */
{0x5a04, 0xc2a6}, /* '娄' -> 23044 */
{0x5a05, 0xe6ab}, /* '娅' -> 23045 */
{0x5a06, 0xe6ac}, /* '娆' -> 23046 */
{0x5a07, 0xbdbf}, /* '娇' -> 23047 */
{0x5a08, 0xe6ae}, /* '娈' -> 23048 */
{0x5a09, 0xe6b3}, /* '娉' -> 23049 */
{0x5a0c, 0xe6b2}, /* '娌' -> 23052 */
{0x5a11, 0xe6b6}, /* '娑' -> 23057 */
{0x5a13, 0xe6b8}, /* '娓' -> 23059 */
{0x5a18, 0xc4ef}, /* '娘' -> 23064 */
{0x5a1c, 0xc4c8}, /* '娜' -> 23068 */
{0x5a1f, 0xbeea}, /* '娟' -> 23071 */
{0x5a20, 0xc9ef}, /* '娠' -> 23072 */
{0x5a23, 0xe6b7}, /* '娣' -> 23075 */
{0x5a25, 0xb6f0}, /* '娥' -> 23077 */
{0x5a29, 0xc3e4}, /* '娩' -> 23081 */
{0x5a31, 0xd3e9}, /* '娱' -> 23089 */
{0x5a32, 0xe6b4}, /* '娲' -> 23090 */
{0x5a34, 0xe6b5}, /* '娴' -> 23092 */
{0x5a36, 0xc8a2}, /* '娶' -> 23094 */
{0x5a3c, 0xe6bd}, /* '娼' -> 23100 */
{0x5a40, 0xe6b9}, /* '婀' -> 23104 */
{0x5a46, 0xc6c5}, /* '婆' -> 23110 */
{0x5a49, 0xcdf1}, /* '婉' -> 23113 */
{0x5a4a, 0xe6bb}, /* '婊' -> 23114 */
{0x5a55, 0xe6bc}, /* '婕' -> 23125 */
{0x5a5a, 0xbbe9}, /* '婚' -> 23130 */
{0x5a62, 0xe6be}, /* '婢' -> 23138 */
{0x5a67, 0xe6ba}, /* '婧' -> 23143 */
{0x5a6a, 0xc0b7}, /* '婪' -> 23146 */
{0x5a74, 0xd3a4}, /* '婴' -> 23156 */
{0x5a75, 0xe6bf}, /* '婵' -> 23157 */
{0x5a76, 0xc9f4}, /* '婶' -> 23158 */
{0x5a77, 0xe6c3}, /* '婷' -> 23159 */
{0x5a7a, 0xe6c4}, /* '婺' -> 23162 */
{0x5a7f, 0xd0f6}, /* '婿' -> 23167 */
{0x5a92, 0xc3bd}, /* '媒' -> 23186 */
{0x5a9a, 0xc3c4}, /* '媚' -> 23194 */
{0x5a9b, 0xe6c2}, /* '媛' -> 23195 */
{0x5aaa, 0xe6c1}, /* '媪' -> 23210 */
{0x5ab2, 0xe6c7}, /* '媲' -> 23218 */
{0x5ab3, 0xcfb1}, /* '媳' -> 23219 */
{0x5ab5, 0xebf4}, /* '媵' -> 23221 */
{0x5ab8, 0xe6ca}, /* '媸' -> 23224 */
{0x5abe, 0xe6c5}, /* '媾' -> 23230 */
{0x5ac1, 0xbcde}, /* '嫁' -> 23233 */
{0x5ac2, 0xc9a9}, /* '嫂' -> 23234 */
{0x5ac9, 0xbcb5}, /* '嫉' -> 23241 */
{0x5acc, 0xcfd3}, /* '嫌' -> 23244 */
{0x5ad2, 0xe6c8}, /* '嫒' -> 23250 */
{0x5ad4, 0xe6c9}, /* '嫔' -> 23252 */
{0x5ad6, 0xe6ce}, /* '嫖' -> 23254 */
{0x5ad8, 0xe6d0}, /* '嫘' -> 23256 */
{0x5adc, 0xe6d1}, /* '嫜' -> 23260 */
{0x5ae0, 0xe6cb}, /* '嫠' -> 23264 */
{0x5ae1, 0xb5d5}, /* '嫡' -> 23265 */
{0x5ae3, 0xe6cc}, /* '嫣' -> 23267 */
{0x5ae6, 0xe6cf}, /* '嫦' -> 23270 */
{0x5ae9, 0xc4db}, /* '嫩' -> 23273 */
{0x5aeb, 0xe6c6}, /* '嫫' -> 23275 */
{0x5af1, 0xe6cd}, /* '嫱' -> 23281 */
{0x5b09, 0xe6d2}, /* '嬉' -> 23305 */
{0x5b16, 0xe6d4}, /* '嬖' -> 23318 */
{0x5b17, 0xe6d3}, /* '嬗' -> 23319 */
{0x5b32, 0xe6d5}, /* '嬲' -> 23346 */
{0x5b34, 0xd9f8}, /* '嬴' -> 23348 */
{0x5b37, 0xe6d6}, /* '嬷' -> 23351 */
{0x5b40, 0xe6d7}, /* '孀' -> 23360 */
{0x5b50, 0xd7d3}, /* '子' -> 23376 */
{0x5b51, 0xe6dd}, /* '孑' -> 23377 */
{0x5b53, 0xe6de}, /* '孓' -> 23379 */
{0x5b54, 0xbfd7}, /* '孔' -> 23380 */
{0x5b55, 0xd4d0}, /* '孕' -> 23381 */
{0x5b57, 0xd7d6}, /* '字' -> 23383 */
{0x5b58, 0xb4e6}, /* '存' -> 23384 */
{0x5b59, 0xcbef}, /* '孙' -> 23385 */
{0x5b5a, 0xe6da}, /* '孚' -> 23386 */
{0x5b5b, 0xd8c3}, /* '孛' -> 23387 */
{0x5b5c, 0xd7ce}, /* '孜' -> 23388 */
{0x5b5d, 0xd0a2}, /* '孝' -> 23389 */
{0x5b5f, 0xc3cf}, /* '孟' -> 23391 */
{0x5b62, 0xe6df}, /* '孢' -> 23394 */
{0x5b63, 0xbcbe}, /* '季' -> 23395 */
{0x5b64, 0xb9c2}, /* '孤' -> 23396 */
{0x5b65, 0xe6db}, /* '孥' -> 23397 */
{0x5b66, 0xd1a7}, /* '学' -> 23398 */
{0x5b69, 0xbaa2}, /* '孩' -> 23401 */
{0x5b6a, 0xc2cf}, /* '孪' -> 23402 */
{0x5b6c, 0xd8ab}, /* '孬' -> 23404 */
{0x5b70, 0xcaeb}, /* '孰' -> 23408 */
{0x5b71, 0xe5ee}, /* '孱' -> 23409 */
{0x5b73, 0xe6dc}, /* '孳' -> 23411 */
{0x5b75, 0xb7f5}, /* '孵' -> 23413 */
{0x5b7a, 0xc8e6}, /* '孺' -> 23418 */
{0x5b7d, 0xc4f5}, /* '孽' -> 23421 */
{0x5b80, 0xe5b2}, /* '宀' -> 23424 */
{0x5b81, 0xc4fe}, /* '宁' -> 23425 */
{0x5b83, 0xcbfc}, /* '它' -> 23427 */
{0x5b84, 0xe5b3}, /* '宄' -> 23428 */
{0x5b85, 0xd5ac}, /* '宅' -> 23429 */
{0x5b87, 0xd3ee}, /* '宇' -> 23431 */
{0x5b88, 0xcad8}, /* '守' -> 23432 */
{0x5b89, 0xb0b2}, /* '安' -> 23433 */
{0x5b8b, 0xcbce}, /* '宋' -> 23435 */
{0x5b8c, 0xcdea}, /* '完' -> 23436 */
{0x5b8f, 0xbaea}, /* '宏' -> 23439 */
{0x5b93, 0xe5b5}, /* '宓' -> 23443 */
{0x5b95, 0xe5b4}, /* '宕' -> 23445 */
{0x5b97, 0xd7da}, /* '宗' -> 23447 */
{0x5b98, 0xb9d9}, /* '官' -> 23448 */
{0x5b99, 0xd6e6}, /* '宙' -> 23449 */
{0x5b9a, 0xb6a8}, /* '定' -> 23450 */
{0x5b9b, 0xcdf0}, /* '宛' -> 23451 */
{0x5b9c, 0xd2cb}, /* '宜' -> 23452 */
{0x5b9d, 0xb1a6}, /* '宝' -> 23453 */
{0x5b9e, 0xcab5}, /* '实' -> 23454 */
{0x5ba0, 0xb3e8}, /* '宠' -> 23456 */
{0x5ba1, 0xc9f3}, /* '审' -> 23457 */
{0x5ba2, 0xbfcd}, /* '客' -> 23458 */
{0x5ba3, 0xd0fb}, /* '宣' -> 23459 */
{0x5ba4, 0xcad2}, /* '室' -> 23460 */
{0x5ba5, 0xe5b6}, /* '宥' -> 23461 */
{0x5ba6, 0xbbc2}, /* '宦' -> 23462 */
{0x5baa, 0xcfdc}, /* '宪' -> 23466 */
{0x5bab, 0xb9ac}, /* '宫' -> 23467 */
{0x5bb0, 0xd4d7}, /* '宰' -> 23472 */
{0x5bb3, 0xbaa6}, /* '害' -> 23475 */
{0x5bb4, 0xd1e7}, /* '宴' -> 23476 */
{0x5bb5, 0xcffc}, /* '宵' -> 23477 */
{0x5bb6, 0xbcd2}, /* '家' -> 23478 */
{0x5bb8, 0xe5b7}, /* '宸' -> 23480 */
{0x5bb9, 0xc8dd}, /* '容' -> 23481 */
{0x5bbd, 0xbfed}, /* '宽' -> 23485 */
{0x5bbe, 0xb1f6}, /* '宾' -> 23486 */
{0x5bbf, 0xcbde}, /* '宿' -> 23487 */
{0x5bc2, 0xbcc5}, /* '寂' -> 23490 */
{0x5bc4, 0xbcc4}, /* '寄' -> 23492 */
{0x5bc5, 0xd2fa}, /* '寅' -> 23493 */
{0x5bc6, 0xc3dc}, /* '密' -> 23494 */
{0x5bc7, 0xbfdc}, /* '寇' -> 23495 */
{0x5bcc, 0xb8bb}, /* '富' -> 23500 */
{0x5bd0, 0xc3c2}, /* '寐' -> 23504 */
{0x5bd2, 0xbaae}, /* '寒' -> 23506 */
{0x5bd3, 0xd4a2}, /* '寓' -> 23507 */
{0x5bdd, 0xc7de}, /* '寝' -> 23517 */
{0x5bde, 0xc4af}, /* '寞' -> 23518 */
{0x5bdf, 0xb2ec}, /* '察' -> 23519 */
{0x5be1, 0xb9d1}, /* '寡' -> 23521 */
{0x5be4, 0xe5bb}, /* '寤' -> 23524 */
{0x5be5, 0xc1c8}, /* '寥' -> 23525 */
{0x5be8, 0xd5af}, /* '寨' -> 23528 */
{0x5bee, 0xe5bc}, /* '寮' -> 23534 */
{0x5bf0, 0xe5be}, /* '寰' -> 23536 */
{0x5bf8, 0xb4e7}, /* '寸' -> 23544 */
{0x5bf9, 0xb6d4}, /* '对' -> 23545 */
{0x5bfa, 0xcbc2}, /* '寺' -> 23546 */
{0x5bfb, 0xd1b0}, /* '寻' -> 23547 */
{0x5bfc, 0xb5bc}, /* '导' -> 23548 */
{0x5bff, 0xcad9}, /* '寿' -> 23551 */
{0x5c01, 0xb7e2}, /* '封' -> 23553 */
{0x5c04, 0xc9e4}, /* '射' -> 23556 */
{0x5c06, 0xbdab}, /* '将' -> 23558 */
{0x5c09, 0xcebe}, /* '尉' -> 23561 */
{0x5c0a, 0xd7f0}, /* '尊' -> 23562 */
{0x5c0f, 0xd0a1}, /* '小' -> 23567 */
{0x5c11, 0xc9d9}, /* '少' -> 23569 */
{0x5c14, 0xb6fb}, /* '尔' -> 23572 */
{0x5c15, 0xe6d8}, /* '尕' -> 23573 */
{0x5c16, 0xbce2}, /* '尖' -> 23574 */
{0x5c18, 0xb3be}, /* '尘' -> 23576 */
{0x5c1a, 0xc9d0}, /* '尚' -> 23578 */
{0x5c1c, 0xe6d9}, /* '尜' -> 23580 */
{0x5c1d, 0xb3a2}, /* '尝' -> 23581 */
{0x5c22, 0xdecc}, /* '尢' -> 23586 */
{0x5c24, 0xd3c8}, /* '尤' -> 23588 */
{0x5c25, 0xdecd}, /* '尥' -> 23589 */
{0x5c27, 0xd2a2}, /* '尧' -> 23591 */
{0x5c2c, 0xdece}, /* '尬' -> 23596 */
{0x5c31, 0xbecd}, /* '就' -> 23601 */
{0x5c34, 0xdecf}, /* '尴' -> 23604 */
{0x5c38, 0xcaac}, /* '尸' -> 23608 */
{0x5c39, 0xd2fc}, /* '尹' -> 23609 */
{0x5c3a, 0xb3df}, /* '尺' -> 23610 */
{0x5c3b, 0xe5ea}, /* '尻' -> 23611 */
{0x5c3c, 0xc4e1}, /* '尼' -> 23612 */
{0x5c3d, 0xbea1}, /* '尽' -> 23613 */
{0x5c3e, 0xceb2}, /* '尾' -> 23614 */
{0x5c3f, 0xc4f2}, /* '尿' -> 23615 */
{0x5c40, 0xbed6}, /* '局' -> 23616 */
{0x5c41, 0xc6a8}, /* '屁' -> 23617 */
{0x5c42, 0xb2e3}, /* '层' -> 23618 */
{0x5c45, 0xbed3}, /* '居' -> 23621 */
{0x5c48, 0xc7fc}, /* '屈' -> 23624 */
{0x5c49, 0xcceb}, /* '屉' -> 23625 */
{0x5c4a, 0xbdec}, /* '届' -> 23626 */
{0x5c4b, 0xcedd}, /* '屋' -> 23627 */
{0x5c4e, 0xcaba}, /* '屎' -> 23630 */
{0x5c4f, 0xc6c1}, /* '屏' -> 23631 */
{0x5c50, 0xe5ec}, /* '屐' -> 23632 */
{0x5c51, 0xd0bc}, /* '屑' -> 23633 */
{0x5c55, 0xd5b9}, /* '展' -> 23637 */
{0x5c59, 0xe5ed}, /* '屙' -> 23641 */
{0x5c5e, 0xcaf4}, /* '属' -> 23646 */
{0x5c60, 0xcdc0}, /* '屠' -> 23648 */
{0x5c61, 0xc2c5}, /* '屡' -> 23649 */
{0x5c63, 0xe5ef}, /* '屣' -> 23651 */
{0x5c65, 0xc2c4}, /* '履' -> 23653 */
{0x5c66, 0xe5f0}, /* '屦' -> 23654 */
{0x5c6e, 0xe5f8}, /* '屮' -> 23662 */
{0x5c6f, 0xcdcd}, /* '屯' -> 23663 */
{0x5c71, 0xc9bd}, /* '山' -> 23665 */
{0x5c79, 0xd2d9}, /* '屹' -> 23673 */
{0x5c7a, 0xe1a8}, /* '屺' -> 23674 */
{0x5c7f, 0xd3ec}, /* '屿' -> 23679 */
{0x5c81, 0xcbea}, /* '岁' -> 23681 */
{0x5c82, 0xc6f1}, /* '岂' -> 23682 */
{0x5c88, 0xe1ac}, /* '岈' -> 23688 */
{0x5c8c, 0xe1a7}, /* '岌' -> 23692 */
{0x5c8d, 0xe1a9}, /* '岍' -> 23693 */
{0x5c90, 0xe1aa}, /* '岐' -> 23696 */
{0x5c91, 0xe1af}, /* '岑' -> 23697 */
{0x5c94, 0xb2ed}, /* '岔' -> 23700 */
{0x5c96, 0xe1ab}, /* '岖' -> 23702 */
{0x5c97, 0xb8da}, /* '岗' -> 23703 */
{0x5c98, 0xe1ad}, /* '岘' -> 23704 */
{0x5c99, 0xe1ae}, /* '岙' -> 23705 */
{0x5c9a, 0xe1b0}, /* '岚' -> 23706 */
{0x5c9b, 0xb5ba}, /* '岛' -> 23707 */
{0x5c9c, 0xe1b1}, /* '岜' -> 23708 */
{0x5ca2, 0xe1b3}, /* '岢' -> 23714 */
{0x5ca3, 0xe1b8}, /* '岣' -> 23715 */
{0x5ca9, 0xd1d2}, /* '岩' -> 23721 */
{0x5cab, 0xe1b6}, /* '岫' -> 23723 */
{0x5cac, 0xe1b5}, /* '岬' -> 23724 */
{0x5cad, 0xc1eb}, /* '岭' -> 23725 */
{0x5cb1, 0xe1b7}, /* '岱' -> 23729 */
{0x5cb3, 0xd4c0}, /* '岳' -> 23731 */
{0x5cb5, 0xe1b2}, /* '岵' -> 23733 */
{0x5cb7, 0xe1ba}, /* '岷' -> 23735 */
{0x5cb8, 0xb0b6}, /* '岸' -> 23736 */
{0x5cbd, 0xe1b4}, /* '岽' -> 23741 */
{0x5cbf, 0xbff9}, /* '岿' -> 23743 */
{0x5cc1, 0xe1b9}, /* '峁' -> 23745 */
{0x5cc4, 0xe1bb}, /* '峄' -> 23748 */
{0x5ccb, 0xe1be}, /* '峋' -> 23755 */
{0x5cd2, 0xe1bc}, /* '峒' -> 23762 */
{0x5cd9, 0xd6c5}, /* '峙' -> 23769 */
{0x5ce1, 0xcfbf}, /* '峡' -> 23777 */
{0x5ce4, 0xe1bd}, /* '峤' -> 23780 */
{0x5ce5, 0xe1bf}, /* '峥' -> 23781 */
{0x5ce6, 0xc2cd}, /* '峦' -> 23782 */
{0x5ce8, 0xb6eb}, /* '峨' -> 23784 */
{0x5cea, 0xd3f8}, /* '峪' -> 23786 */
{0x5ced, 0xc7cd}, /* '峭' -> 23789 */
{0x5cf0, 0xb7e5}, /* '峰' -> 23792 */
{0x5cfb, 0xbefe}, /* '峻' -> 23803 */
{0x5d02, 0xe1c0}, /* '崂' -> 23810 */
{0x5d03, 0xe1c1}, /* '崃' -> 23811 */
{0x5d06, 0xe1c7}, /* '崆' -> 23814 */
{0x5d07, 0xb3e7}, /* '崇' -> 23815 */
{0x5d0e, 0xc6e9}, /* '崎' -> 23822 */
{0x5d14, 0xb4de}, /* '崔' -> 23828 */
{0x5d16, 0xd1c2}, /* '崖' -> 23830 */
{0x5d1b, 0xe1c8}, /* '崛' -> 23835 */
{0x5d1e, 0xe1c6}, /* '崞' -> 23838 */
{0x5d24, 0xe1c5}, /* '崤' -> 23844 */
{0x5d26, 0xe1c3}, /* '崦' -> 23846 */
{0x5d27, 0xe1c2}, /* '崧' -> 23847 */
{0x5d29, 0xb1c0}, /* '崩' -> 23849 */
{0x5d2d, 0xd5b8}, /* '崭' -> 23853 */
{0x5d2e, 0xe1c4}, /* '崮' -> 23854 */
{0x5d34, 0xe1cb}, /* '崴' -> 23860 */
{0x5d3d, 0xe1cc}, /* '崽' -> 23869 */
{0x5d3e, 0xe1ca}, /* '崾' -> 23870 */
{0x5d47, 0xeffa}, /* '嵇' -> 23879 */
{0x5d4a, 0xe1d3}, /* '嵊' -> 23882 */
{0x5d4b, 0xe1d2}, /* '嵋' -> 23883 */
{0x5d4c, 0xc7b6}, /* '嵌' -> 23884 */
{0x5d58, 0xe1c9}, /* '嵘' -> 23896 */
{0x5d5b, 0xe1ce}, /* '嵛' -> 23899 */
{0x5d5d, 0xe1d0}, /* '嵝' -> 23901 */
{0x5d69, 0xe1d4}, /* '嵩' -> 23913 */
{0x5d6b, 0xe1d1}, /* '嵫' -> 23915 */
{0x5d6c, 0xe1cd}, /* '嵬' -> 23916 */
{0x5d6f, 0xe1cf}, /* '嵯' -> 23919 */
{0x5d74, 0xe1d5}, /* '嵴' -> 23924 */
{0x5d82, 0xe1d6}, /* '嶂' -> 23938 */
{0x5d99, 0xe1d7}, /* '嶙' -> 23961 */
{0x5d9d, 0xe1d8}, /* '嶝' -> 23965 */
{0x5db7, 0xe1da}, /* '嶷' -> 23991 */
{0x5dc5, 0xe1db}, /* '巅' -> 24005 */
{0x5dcd, 0xcea1}, /* '巍' -> 24013 */
{0x5ddb, 0xe7dd}, /* '巛' -> 24027 */
{0x5ddd, 0xb4a8}, /* '川' -> 24029 */
{0x5dde, 0xd6dd}, /* '州' -> 24030 */
{0x5de1, 0xd1b2}, /* '巡' -> 24033 */
{0x5de2, 0xb3b2}, /* '巢' -> 24034 */
{0x5de5, 0xb9a4}, /* '工' -> 24037 */
{0x5de6, 0xd7f3}, /* '左' -> 24038 */
{0x5de7, 0xc7c9}, /* '巧' -> 24039 */
{0x5de8, 0xbede}, /* '巨' -> 24040 */
{0x5de9, 0xb9ae}, /* '巩' -> 24041 */
{0x5deb, 0xced7}, /* '巫' -> 24043 */
{0x5dee, 0xb2ee}, /* '差' -> 24046 */
{0x5def, 0xdbcf}, /* '巯' -> 24047 */
{0x5df1, 0xbcba}, /* '己' -> 24049 */
{0x5df2, 0xd2d1}, /* '已' -> 24050 */
{0x5df3, 0xcbc8}, /* '巳' -> 24051 */
{0x5df4, 0xb0cd}, /* '巴' -> 24052 */
{0x5df7, 0xcfef}, /* '巷' -> 24055 */
{0x5dfd, 0xd9e3}, /* '巽' -> 24061 */
{0x5dfe, 0xbded}, /* '巾' -> 24062 */
{0x5e01, 0xb1d2}, /* '币' -> 24065 */
{0x5e02, 0xcad0}, /* '市' -> 24066 */
{0x5e03, 0xb2bc}, /* '布' -> 24067 */
{0x5e05, 0xcba7}, /* '帅' -> 24069 */
{0x5e06, 0xb7ab}, /* '帆' -> 24070 */
{0x5e08, 0xcaa6}, /* '师' -> 24072 */
{0x5e0c, 0xcfa3}, /* '希' -> 24076 */
{0x5e0f, 0xe0f8}, /* '帏' -> 24079 */
{0x5e10, 0xd5ca}, /* '帐' -> 24080 */
{0x5e11, 0xe0fb}, /* '帑' -> 24081 */
{0x5e14, 0xe0fa}, /* '帔' -> 24084 */
{0x5e15, 0xc5c1}, /* '帕' -> 24085 */
{0x5e16, 0xccfb}, /* '帖' -> 24086 */
{0x5e18, 0xc1b1}, /* '帘' -> 24088 */
{0x5e19, 0xe0f9}, /* '帙' -> 24089 */
{0x5e1a, 0xd6e3}, /* '帚' -> 24090 */
{0x5e1b, 0xb2af}, /* '帛' -> 24091 */
{0x5e1c, 0xd6c4}, /* '帜' -> 24092 */
{0x5e1d, 0xb5db}, /* '帝' -> 24093 */
{0x5e26, 0xb4f8}, /* '带' -> 24102 */
{0x5e27, 0xd6a1}, /* '帧' -> 24103 */
{0x5e2d, 0xcfaf}, /* '席' -> 24109 */
{0x5e2e, 0xb0ef}, /* '帮' -> 24110 */
{0x5e31, 0xe0fc}, /* '帱' -> 24113 */
{0x5e37, 0xe1a1}, /* '帷' -> 24119 */
{0x5e38, 0xb3a3}, /* '常' -> 24120 */
{0x5e3b, 0xe0fd}, /* '帻' -> 24123 */
{0x5e3c, 0xe0fe}, /* '帼' -> 24124 */
{0x5e3d, 0xc3b1}, /* '帽' -> 24125 */
{0x5e42, 0xc3dd}, /* '幂' -> 24130 */
{0x5e44, 0xe1a2}, /* '幄' -> 24132 */
{0x5e45, 0xb7f9}, /* '幅' -> 24133 */
{0x5e4c, 0xbbcf}, /* '幌' -> 24140 */
{0x5e54, 0xe1a3}, /* '幔' -> 24148 */
{0x5e55, 0xc4bb}, /* '幕' -> 24149 */
{0x5e5b, 0xe1a4}, /* '幛' -> 24155 */
{0x5e5e, 0xe1a5}, /* '幞' -> 24158 */
{0x5e61, 0xe1a6}, /* '幡' -> 24161 */
{0x5e62, 0xb4b1}, /* '幢' -> 24162 */
{0x5e72, 0xb8c9}, /* '干' -> 24178 */
{0x5e73, 0xc6bd}, /* '平' -> 24179 */
{0x5e74, 0xc4ea}, /* '年' -> 24180 */
{0x5e76, 0xb2a2}, /* '并' -> 24182 */
{0x5e78, 0xd0d2}, /* '幸' -> 24184 */
{0x5e7a, 0xe7db}, /* '幺' -> 24186 */
{0x5e7b, 0xbbc3}, /* '幻' -> 24187 */
{0x5e7c, 0xd3d7}, /* '幼' -> 24188 */
{0x5e7d, 0xd3c4}, /* '幽' -> 24189 */
{0x5e7f, 0xb9e3}, /* '广' -> 24191 */
{0x5e80, 0xe2cf}, /* '庀' -> 24192 */
{0x5e84, 0xd7af}, /* '庄' -> 24196 */
{0x5e86, 0xc7ec}, /* '庆' -> 24198 */
{0x5e87, 0xb1d3}, /* '庇' -> 24199 */
{0x5e8a, 0xb4b2}, /* '床' -> 24202 */
{0x5e8b, 0xe2d1}, /* '庋' -> 24203 */
{0x5e8f, 0xd0f2}, /* '序' -> 24207 */
{0x5e90, 0xc2ae}, /* '庐' -> 24208 */
{0x5e91, 0xe2d0}, /* '庑' -> 24209 */
{0x5e93, 0xbfe2}, /* '库' -> 24211 */
{0x5e94, 0xd3a6}, /* '应' -> 24212 */
{0x5e95, 0xb5d7}, /* '底' -> 24213 */
{0x5e96, 0xe2d2}, /* '庖' -> 24214 */
{0x5e97, 0xb5ea}, /* '店' -> 24215 */
{0x5e99, 0xc3ed}, /* '庙' -> 24217 */
{0x5e9a, 0xb8fd}, /* '庚' -> 24218 */
{0x5e9c, 0xb8ae}, /* '府' -> 24220 */
{0x5e9e, 0xc5d3}, /* '庞' -> 24222 */
{0x5e9f, 0xb7cf}, /* '废' -> 24223 */
{0x5ea0, 0xe2d4}, /* '庠' -> 24224 */
{0x5ea5, 0xe2d3}, /* '庥' -> 24229 */
{0x5ea6, 0xb6c8}, /* '度' -> 24230 */
{0x5ea7, 0xd7f9}, /* '座' -> 24231 */
{0x5ead, 0xcda5}, /* '庭' -> 24237 */
{0x5eb3, 0xe2d8}, /* '庳' -> 24243 */
{0x5eb5, 0xe2d6}, /* '庵' -> 24245 */
{0x5eb6, 0xcafc}, /* '庶' -> 24246 */
{0x5eb7, 0xbfb5}, /* '康' -> 24247 */
{0x5eb8, 0xd3b9}, /* '庸' -> 24248 */
{0x5eb9, 0xe2d5}, /* '庹' -> 24249 */
{0x5ebe, 0xe2d7}, /* '庾' -> 24254 */
{0x5ec9, 0xc1ae}, /* '廉' -> 24265 */
{0x5eca, 0xc0c8}, /* '廊' -> 24266 */
{0x5ed1, 0xe2db}, /* '廑' -> 24273 */
{0x5ed2, 0xe2da}, /* '廒' -> 24274 */
{0x5ed3, 0xc0aa}, /* '廓' -> 24275 */
{0x5ed6, 0xc1ce}, /* '廖' -> 24278 */
{0x5edb, 0xe2dc}, /* '廛' -> 24283 */
{0x5ee8, 0xe2dd}, /* '廨' -> 24296 */
{0x5eea, 0xe2de}, /* '廪' -> 24298 */
{0x5ef4, 0xdbc8}, /* '廴' -> 24308 */
{0x5ef6, 0xd1d3}, /* '延' -> 24310 */
{0x5ef7, 0xcda2}, /* '廷' -> 24311 */
{0x5efa, 0xbda8}, /* '建' -> 24314 */
{0x5efe, 0xdec3}, /* '廾' -> 24318 */
{0x5eff, 0xd8a5}, /* '廿' -> 24319 */
{0x5f00, 0xbfaa}, /* '开' -> 24320 */
{0x5f01, 0xdbcd}, /* '弁' -> 24321 */
{0x5f02, 0xd2ec}, /* '异' -> 24322 */
{0x5f03, 0xc6fa}, /* '弃' -> 24323 */
{0x5f04, 0xc5aa}, /* '弄' -> 24324 */
{0x5f08, 0xdec4}, /* '弈' -> 24328 */
{0x5f0a, 0xb1d7}, /* '弊' -> 24330 */
{0x5f0b, 0xdfae}, /* '弋' -> 24331 */
{0x5f0f, 0xcabd}, /* '式' -> 24335 */
{0x5f11, 0xdfb1}, /* '弑' -> 24337 */
{0x5f13, 0xb9ad}, /* '弓' -> 24339 */
{0x5f15, 0xd2fd}, /* '引' -> 24341 */
{0x5f17, 0xb8a5}, /* '弗' -> 24343 */
{0x5f18, 0xbaeb}, /* '弘' -> 24344 */
{0x5f1b, 0xb3da}, /* '弛' -> 24347 */
{0x5f1f, 0xb5dc}, /* '弟' -> 24351 */
{0x5f20, 0xd5c5}, /* '张' -> 24352 */
{0x5f25, 0xc3d6}, /* '弥' -> 24357 */
{0x5f26, 0xcfd2}, /* '弦' -> 24358 */
{0x5f27, 0xbba1}, /* '弧' -> 24359 */
{0x5f29, 0xe5f3}, /* '弩' -> 24361 */
{0x5f2a, 0xe5f2}, /* '弪' -> 24362 */
{0x5f2d, 0xe5f4}, /* '弭' -> 24365 */
{0x5f2f, 0xcde4}, /* '弯' -> 24367 */
{0x5f31, 0xc8f5}, /* '弱' -> 24369 */
{0x5f39, 0xb5af}, /* '弹' -> 24377 */
{0x5f3a, 0xc7bf}, /* '强' -> 24378 */
{0x5f3c, 0xe5f6}, /* '弼' -> 24380 */
{0x5f40, 0xecb0}, /* '彀' -> 24384 */
{0x5f50, 0xe5e6}, /* '彐' -> 24400 */
{0x5f52, 0xb9e9}, /* '归' -> 24402 */
{0x5f53, 0xb5b1}, /* '当' -> 24403 */
{0x5f55, 0xc2bc}, /* '录' -> 24405 */
{0x5f56, 0xe5e8}, /* '彖' -> 24406 */
{0x5f57, 0xe5e7}, /* '彗' -> 24407 */
{0x5f58, 0xe5e9}, /* '彘' -> 24408 */
{0x5f5d, 0xd2cd}, /* '彝' -> 24413 */
{0x5f61, 0xe1ea}, /* '彡' -> 24417 */
{0x5f62, 0xd0ce}, /* '形' -> 24418 */
{0x5f64, 0xcdae}, /* '彤' -> 24420 */
{0x5f66, 0xd1e5}, /* '彦' -> 24422 */
{0x5f69, 0xb2ca}, /* '彩' -> 24425 */
{0x5f6a, 0xb1eb}, /* '彪' -> 24426 */
{0x5f6c, 0xb1f2}, /* '彬' -> 24428 */
{0x5f6d, 0xc5ed}, /* '彭' -> 24429 */
{0x5f70, 0xd5c3}, /* '彰' -> 24432 */
{0x5f71, 0xd3b0}, /* '影' -> 24433 */
{0x5f73, 0xe1dc}, /* '彳' -> 24435 */
{0x5f77, 0xe1dd}, /* '彷' -> 24439 */
{0x5f79, 0xd2db}, /* '役' -> 24441 */
{0x5f7b, 0xb3b9}, /* '彻' -> 24443 */
{0x5f7c, 0xb1cb}, /* '彼' -> 24444 */
{0x5f80, 0xcdf9}, /* '往' -> 24448 */
{0x5f81, 0xd5f7}, /* '征' -> 24449 */
{0x5f82, 0xe1de}, /* '徂' -> 24450 */
{0x5f84, 0xbeb6}, /* '径' -> 24452 */
{0x5f85, 0xb4fd}, /* '待' -> 24453 */
{0x5f87, 0xe1df}, /* '徇' -> 24455 */
{0x5f88, 0xbadc}, /* '很' -> 24456 */
{0x5f89, 0xe1e0}, /* '徉' -> 24457 */
{0x5f8a, 0xbbb2}, /* '徊' -> 24458 */
{0x5f8b, 0xc2c9}, /* '律' -> 24459 */
{0x5f8c, 0xe1e1}, /* '後' -> 24460 */
{0x5f90, 0xd0ec}, /* '徐' -> 24464 */
{0x5f92, 0xcdbd}, /* '徒' -> 24466 */
{0x5f95, 0xe1e2}, /* '徕' -> 24469 */
{0x5f97, 0xb5c3}, /* '得' -> 24471 */
{0x5f98, 0xc5c7}, /* '徘' -> 24472 */
{0x5f99, 0xe1e3}, /* '徙' -> 24473 */
{0x5f9c, 0xe1e4}, /* '徜' -> 24476 */
{0x5fa1, 0xd3f9}, /* '御' -> 24481 */
{0x5fa8, 0xe1e5}, /* '徨' -> 24488 */
{0x5faa, 0xd1ad}, /* '循' -> 24490 */
{0x5fad, 0xe1e6}, /* '徭' -> 24493 */
{0x5fae, 0xcea2}, /* '微' -> 24494 */
{0x5fb5, 0xe1e7}, /* '徵' -> 24501 */
{0x5fb7, 0xb5c2}, /* '德' -> 24503 */
{0x5fbc, 0xe1e8}, /* '徼' -> 24508 */
{0x5fbd, 0xbbd5}, /* '徽' -> 24509 */
{0x5fc3, 0xd0c4}, /* '心' -> 24515 */
{0x5fc4, 0xe2e0}, /* '忄' -> 24516 */
{0x5fc5, 0xb1d8}, /* '必' -> 24517 */
{0x5fc6, 0xd2e4}, /* '忆' -> 24518 */
{0x5fc9, 0xe2e1}, /* '忉' -> 24521 */
{0x5fcc, 0xbcc9}, /* '忌' -> 24524 */
{0x5fcd, 0xc8cc}, /* '忍' -> 24525 */
{0x5fcf, 0xe2e3}, /* '忏' -> 24527 */
{0x5fd0, 0xecfe}, /* '忐' -> 24528 */
{0x5fd1, 0xecfd}, /* '忑' -> 24529 */
{0x5fd2, 0xdfaf}, /* '忒' -> 24530 */
{0x5fd6, 0xe2e2}, /* '忖' -> 24534 */
{0x5fd7, 0xd6be}, /* '志' -> 24535 */
{0x5fd8, 0xcdfc}, /* '忘' -> 24536 */
{0x5fd9, 0xc3a6}, /* '忙' -> 24537 */
{0x5fdd, 0xe3c3}, /* '忝' -> 24541 */
{0x5fe0, 0xd6d2}, /* '忠' -> 24544 */
{0x5fe1, 0xe2e7}, /* '忡' -> 24545 */
{0x5fe4, 0xe2e8}, /* '忤' -> 24548 */
{0x5fe7, 0xd3c7}, /* '忧' -> 24551 */
{0x5fea, 0xe2ec}, /* '忪' -> 24554 */
{0x5feb, 0xbfec}, /* '快' -> 24555 */
{0x5fed, 0xe2ed}, /* '忭' -> 24557 */
{0x5fee, 0xe2e5}, /* '忮' -> 24558 */
{0x5ff1, 0xb3c0}, /* '忱' -> 24561 */
{0x5ff5, 0xc4ee}, /* '念' -> 24565 */
{0x5ff8, 0xe2ee}, /* '忸' -> 24568 */
{0x5ffb, 0xd0c3}, /* '忻' -> 24571 */
{0x5ffd, 0xbaf6}, /* '忽' -> 24573 */
{0x5ffe, 0xe2e9}, /* '忾' -> 24574 */
{0x5fff, 0xb7de}, /* '忿' -> 24575 */
{0x6000, 0xbbb3}, /* '怀' -> 24576 */
{0x6001, 0xccac}, /* '态' -> 24577 */
{0x6002, 0xcbcb}, /* '怂' -> 24578 */
{0x6003, 0xe2e4}, /* '怃' -> 24579 */
{0x6004, 0xe2e6}, /* '怄' -> 24580 */
{0x6005, 0xe2ea}, /* '怅' -> 24581 */
{0x6006, 0xe2eb}, /* '怆' -> 24582 */
{0x600a, 0xe2f7}, /* '怊' -> 24586 */
{0x600d, 0xe2f4}, /* '怍' -> 24589 */
{0x600e, 0xd4f5}, /* '怎' -> 24590 */
{0x600f, 0xe2f3}, /* '怏' -> 24591 */
{0x6012, 0xc5ad}, /* '怒' -> 24594 */
{0x6014, 0xd5fa}, /* '怔' -> 24596 */
{0x6015, 0xc5c2}, /* '怕' -> 24597 */
{0x6016, 0xb2c0}, /* '怖' -> 24598 */
{0x6019, 0xe2ef}, /* '怙' -> 24601 */
{0x601b, 0xe2f2}, /* '怛' -> 24603 */
{0x601c, 0xc1af}, /* '怜' -> 24604 */
{0x601d, 0xcbbc}, /* '思' -> 24605 */
{0x6020, 0xb5a1}, /* '怠' -> 24608 */
{0x6021, 0xe2f9}, /* '怡' -> 24609 */
{0x6025, 0xbcb1}, /* '急' -> 24613 */
{0x6026, 0xe2f1}, /* '怦' -> 24614 */
{0x6027, 0xd0d4}, /* '性' -> 24615 */
{0x6028, 0xd4b9}, /* '怨' -> 24616 */
{0x6029, 0xe2f5}, /* '怩' -> 24617 */
{0x602a, 0xb9d6}, /* '怪' -> 24618 */
{0x602b, 0xe2f6}, /* '怫' -> 24619 */
{0x602f, 0xc7d3}, /* '怯' -> 24623 */
{0x6035, 0xe2f0}, /* '怵' -> 24629 */
{0x603b, 0xd7dc}, /* '总' -> 24635 */
{0x603c, 0xeda1}, /* '怼' -> 24636 */
{0x603f, 0xe2f8}, /* '怿' -> 24639 */
{0x6041, 0xeda5}, /* '恁' -> 24641 */
{0x6042, 0xe2fe}, /* '恂' -> 24642 */
{0x6043, 0xcad1}, /* '恃' -> 24643 */
{0x604b, 0xc1b5}, /* '恋' -> 24651 */
{0x604d, 0xbbd0}, /* '恍' -> 24653 */
{0x6050, 0xbfd6}, /* '恐' -> 24656 */
{0x6052, 0xbae3}, /* '恒' -> 24658 */
{0x6055, 0xcba1}, /* '恕' -> 24661 */
{0x6059, 0xeda6}, /* '恙' -> 24665 */
{0x605a, 0xeda3}, /* '恚' -> 24666 */
{0x605d, 0xeda2}, /* '恝' -> 24669 */
{0x6062, 0xbbd6}, /* '恢' -> 24674 */
{0x6063, 0xeda7}, /* '恣' -> 24675 */
{0x6064, 0xd0f4}, /* '恤' -> 24676 */
{0x6067, 0xeda4}, /* '恧' -> 24679 */
{0x6068, 0xbade}, /* '恨' -> 24680 */
{0x6069, 0xb6f7}, /* '恩' -> 24681 */
{0x606a, 0xe3a1}, /* '恪' -> 24682 */
{0x606b, 0xb6b2}, /* '恫' -> 24683 */
{0x606c, 0xccf1}, /* '恬' -> 24684 */
{0x606d, 0xb9a7}, /* '恭' -> 24685 */
{0x606f, 0xcfa2}, /* '息' -> 24687 */
{0x6070, 0xc7a1}, /* '恰' -> 24688 */
{0x6073, 0xbfd2}, /* '恳' -> 24691 */
{0x6076, 0xb6f1}, /* '恶' -> 24694 */
{0x6078, 0xe2fa}, /* '恸' -> 24696 */
{0x6079, 0xe2fb}, /* '恹' -> 24697 */
{0x607a, 0xe2fd}, /* '恺' -> 24698 */
{0x607b, 0xe2fc}, /* '恻' -> 24699 */
{0x607c, 0xc4d5}, /* '恼' -> 24700 */
{0x607d, 0xe3a2}, /* '恽' -> 24701 */
{0x607f, 0xd3c1}, /* '恿' -> 24703 */
{0x6083, 0xe3a7}, /* '悃' -> 24707 */
{0x6084, 0xc7c4}, /* '悄' -> 24708 */
{0x6089, 0xcfa4}, /* '悉' -> 24713 */
{0x608c, 0xe3a9}, /* '悌' -> 24716 */
{0x608d, 0xbab7}, /* '悍' -> 24717 */
{0x6092, 0xe3a8}, /* '悒' -> 24722 */
{0x6094, 0xbbda}, /* '悔' -> 24724 */
{0x6096, 0xe3a3}, /* '悖' -> 24726 */
{0x609a, 0xe3a4}, /* '悚' -> 24730 */
{0x609b, 0xe3aa}, /* '悛' -> 24731 */
{0x609d, 0xe3a6}, /* '悝' -> 24733 */
{0x609f, 0xcef2}, /* '悟' -> 24735 */
{0x60a0, 0xd3c6}, /* '悠' -> 24736 */
{0x60a3, 0xbbbc}, /* '患' -> 24739 */
{0x60a6, 0xd4c3}, /* '悦' -> 24742 */
{0x60a8, 0xc4fa}, /* '您' -> 24744 */
{0x60ab, 0xeda8}, /* '悫' -> 24747 */
{0x60ac, 0xd0fc}, /* '悬' -> 24748 */
{0x60ad, 0xe3a5}, /* '悭' -> 24749 */
{0x60af, 0xc3f5}, /* '悯' -> 24751 */
{0x60b1, 0xe3ad}, /* '悱' -> 24753 */
{0x60b2, 0xb1af}, /* '悲' -> 24754 */
{0x60b4, 0xe3b2}, /* '悴' -> 24756 */
{0x60b8, 0xbcc2}, /* '悸' -> 24760 */
{0x60bb, 0xe3ac}, /* '悻' -> 24763 */
{0x60bc, 0xb5bf}, /* '悼' -> 24764 */
{0x60c5, 0xc7e9}, /* '情' -> 24773 */
{0x60c6, 0xe3b0}, /* '惆' -> 24774 */
{0x60ca, 0xbeaa}, /* '惊' -> 24778 */
{0x60cb, 0xcdef}, /* '惋' -> 24779 */
{0x60d1, 0xbbf3}, /* '惑' -> 24785 */
{0x60d5, 0xcce8}, /* '惕' -> 24789 */
{0x60d8, 0xe3af}, /* '惘' -> 24792 */
{0x60da, 0xe3b1}, /* '惚' -> 24794 */
{0x60dc, 0xcfa7}, /* '惜' -> 24796 */
{0x60dd, 0xe3ae}, /* '惝' -> 24797 */
{0x60df, 0xcea9}, /* '惟' -> 24799 */
{0x60e0, 0xbbdd}, /* '惠' -> 24800 */
{0x60e6, 0xb5eb}, /* '惦' -> 24806 */
{0x60e7, 0xbee5}, /* '惧' -> 24807 */
{0x60e8, 0xb2d2}, /* '惨' -> 24808 */
{0x60e9, 0xb3cd}, /* '惩' -> 24809 */
{0x60eb, 0xb1b9}, /* '惫' -> 24811 */
{0x60ec, 0xe3ab}, /* '惬' -> 24812 */
{0x60ed, 0xb2d1}, /* '惭' -> 24813 */
{0x60ee, 0xb5ac}, /* '惮' -> 24814 */
{0x60ef, 0xb9df}, /* '惯' -> 24815 */
{0x60f0, 0xb6e8}, /* '惰' -> 24816 */
{0x60f3, 0xcfeb}, /* '想' -> 24819 */
{0x60f4, 0xe3b7}, /* '惴' -> 24820 */
{0x60f6, 0xbbcc}, /* '惶' -> 24822 */
{0x60f9, 0xc8c7}, /* '惹' -> 24825 */
{0x60fa, 0xd0ca}, /* '惺' -> 24826 */
{0x6100, 0xe3b8}, /* '愀' -> 24832 */
{0x6101, 0xb3ee}, /* '愁' -> 24833 */
{0x6106, 0xeda9}, /* '愆' -> 24838 */
{0x6108, 0xd3fa}, /* '愈' -> 24840 */
{0x6109, 0xd3e4}, /* '愉' -> 24841 */
{0x610d, 0xedaa}, /* '愍' -> 24845 */
{0x610e, 0xe3b9}, /* '愎' -> 24846 */
{0x610f, 0xd2e2}, /* '意' -> 24847 */
{0x6115, 0xe3b5}, /* '愕' -> 24853 */
{0x611a, 0xd3de}, /* '愚' -> 24858 */
{0x611f, 0xb8d0}, /* '感' -> 24863 */
{0x6120, 0xe3b3}, /* '愠' -> 24864 */
{0x6123, 0xe3b6}, /* '愣' -> 24867 */
{0x6124, 0xb7df}, /* '愤' -> 24868 */
{0x6126, 0xe3b4}, /* '愦' -> 24870 */
{0x6127, 0xc0a2}, /* '愧' -> 24871 */
{0x612b, 0xe3ba}, /* '愫' -> 24875 */
{0x613f, 0xd4b8}, /* '愿' -> 24895 */
{0x6148, 0xb4c8}, /* '慈' -> 24904 */
{0x614a, 0xe3bb}, /* '慊' -> 24906 */
{0x614c, 0xbbc5}, /* '慌' -> 24908 */
{0x614e, 0xc9f7}, /* '慎' -> 24910 */
{0x6151, 0xc9e5}, /* '慑' -> 24913 */
{0x6155, 0xc4bd}, /* '慕' -> 24917 */
{0x615d, 0xedab}, /* '慝' -> 24925 */
{0x6162, 0xc2fd}, /* '慢' -> 24930 */
{0x6167, 0xbbdb}, /* '慧' -> 24935 */
{0x6168, 0xbfae}, /* '慨' -> 24936 */
{0x6170, 0xcebf}, /* '慰' -> 24944 */
{0x6175, 0xe3bc}, /* '慵' -> 24949 */
{0x6177, 0xbfb6}, /* '慷' -> 24951 */
{0x618b, 0xb1ef}, /* '憋' -> 24971 */
{0x618e, 0xd4f7}, /* '憎' -> 24974 */
{0x6194, 0xe3be}, /* '憔' -> 24980 */
{0x619d, 0xedad}, /* '憝' -> 24989 */
{0x61a7, 0xe3bf}, /* '憧' -> 24999 */
{0x61a8, 0xbaa9}, /* '憨' -> 25000 */
{0x61a9, 0xedac}, /* '憩' -> 25001 */
{0x61ac, 0xe3bd}, /* '憬' -> 25004 */
{0x61b7, 0xe3c0}, /* '憷' -> 25015 */
{0x61be, 0xbab6}, /* '憾' -> 25022 */
{0x61c2, 0xb6ae}, /* '懂' -> 25026 */
{0x61c8, 0xd0b8}, /* '懈' -> 25032 */
{0x61ca, 0xb0c3}, /* '懊' -> 25034 */
{0x61cb, 0xedae}, /* '懋' -> 25035 */
{0x61d1, 0xedaf}, /* '懑' -> 25041 */
{0x61d2, 0xc0c1}, /* '懒' -> 25042 */
{0x61d4, 0xe3c1}, /* '懔' -> 25044 */
{0x61e6, 0xc5b3}, /* '懦' -> 25062 */
{0x61f5, 0xe3c2}, /* '懵' -> 25077 */
{0x61ff, 0xdcb2}, /* '懿' -> 25087 */
{0x6206, 0xedb0}, /* '戆' -> 25094 */
{0x6208, 0xb8ea}, /* '戈' -> 25096 */
{0x620a, 0xceec}, /* '戊' -> 25098 */
{0x620b, 0xeaa7}, /* '戋' -> 25099 */
{0x620c, 0xd0e7}, /* '戌' -> 25100 */
{0x620d, 0xcaf9}, /* '戍' -> 25101 */
{0x620e, 0xc8d6}, /* '戎' -> 25102 */
{0x620f, 0xcfb7}, /* '戏' -> 25103 */
{0x6210, 0xb3c9}, /* '成' -> 25104 */
{0x6211, 0xced2}, /* '我' -> 25105 */
{0x6212, 0xbde4}, /* '戒' -> 25106 */
{0x6215, 0xe3de}, /* '戕' -> 25109 */
{0x6216, 0xbbf2}, /* '或' -> 25110 */
{0x6217, 0xeaa8}, /* '戗' -> 25111 */
{0x6218, 0xd5bd}, /* '战' -> 25112 */
{0x621a, 0xc6dd}, /* '戚' -> 25114 */
{0x621b, 0xeaa9}, /* '戛' -> 25115 */
{0x621f, 0xeaaa}, /* '戟' -> 25119 */
{0x6221, 0xeaac}, /* '戡' -> 25121 */
{0x6222, 0xeaab}, /* '戢' -> 25122 */
{0x6224, 0xeaae}, /* '戤' -> 25124 */
{0x6225, 0xeaad}, /* '戥' -> 25125 */
{0x622a, 0xbdd8}, /* '截' -> 25130 */
{0x622c, 0xeaaf}, /* '戬' -> 25132 */
{0x622e, 0xc2be}, /* '戮' -> 25134 */
{0x6233, 0xb4c1}, /* '戳' -> 25139 */
{0x6234, 0xb4f7}, /* '戴' -> 25140 */
{0x6237, 0xbba7}, /* '户' -> 25143 */
{0x623d, 0xece6}, /* '戽' -> 25149 */
{0x623e, 0xece5}, /* '戾' -> 25150 */
{0x623f, 0xb7bf}, /* '房' -> 25151 */
{0x6240, 0xcbf9}, /* '所' -> 25152 */
{0x6241, 0xb1e2}, /* '扁' -> 25153 */
{0x6243, 0xece7}, /* '扃' -> 25155 */
{0x6247, 0xc9c8}, /* '扇' -> 25159 */
{0x6248, 0xece8}, /* '扈' -> 25160 */
{0x6249, 0xece9}, /* '扉' -> 25161 */
{0x624b, 0xcad6}, /* '手' -> 25163 */
{0x624c, 0xded0}, /* '扌' -> 25164 */
{0x624d, 0xb2c5}, /* '才' -> 25165 */
{0x624e, 0xd4fa}, /* '扎' -> 25166 */
{0x6251, 0xc6cb}, /* '扑' -> 25169 */
{0x6252, 0xb0c7}, /* '扒' -> 25170 */
{0x6253, 0xb4f2}, /* '打' -> 25171 */
{0x6254, 0xc8d3}, /* '扔' -> 25172 */
{0x6258, 0xcdd0}, /* '托' -> 25176 */
{0x625b, 0xbfb8}, /* '扛' -> 25179 */
{0x6263, 0xbfdb}, /* '扣' -> 25187 */
{0x6266, 0xc7a4}, /* '扦' -> 25190 */
{0x6267, 0xd6b4}, /* '执' -> 25191 */
{0x6269, 0xc0a9}, /* '扩' -> 25193 */
{0x626a, 0xded1}, /* '扪' -> 25194 */
{0x626b, 0xc9a8}, /* '扫' -> 25195 */
{0x626c, 0xd1ef}, /* '扬' -> 25196 */
{0x626d, 0xc5a4}, /* '扭' -> 25197 */
{0x626e, 0xb0e7}, /* '扮' -> 25198 */
{0x626f, 0xb3b6}, /* '扯' -> 25199 */
{0x6270, 0xc8c5}, /* '扰' -> 25200 */
{0x6273, 0xb0e2}, /* '扳' -> 25203 */
{0x6276, 0xb7f6}, /* '扶' -> 25206 */
{0x6279, 0xc5fa}, /* '批' -> 25209 */
{0x627c, 0xb6f3}, /* '扼' -> 25212 */
{0x627e, 0xd5d2}, /* '找' -> 25214 */
{0x627f, 0xb3d0}, /* '承' -> 25215 */
{0x6280, 0xbcbc}, /* '技' -> 25216 */
{0x6284, 0xb3ad}, /* '抄' -> 25220 */
{0x6289, 0xbef1}, /* '抉' -> 25225 */
{0x628a, 0xb0d1}, /* '把' -> 25226 */
{0x6291, 0xd2d6}, /* '抑' -> 25233 */
{0x6292, 0xcae3}, /* '抒' -> 25234 */
{0x6293, 0xd7a5}, /* '抓' -> 25235 */
{0x6295, 0xcdb6}, /* '投' -> 25237 */
{0x6296, 0xb6b6}, /* '抖' -> 25238 */
{0x6297, 0xbfb9}, /* '抗' -> 25239 */
{0x6298, 0xd5db}, /* '折' -> 25240 */
{0x629a, 0xb8a7}, /* '抚' -> 25242 */
{0x629b, 0xc5d7}, /* '抛' -> 25243 */
{0x629f, 0xded2}, /* '抟' -> 25247 */
{0x62a0, 0xbfd9}, /* '抠' -> 25248 */
{0x62a1, 0xc2d5}, /* '抡' -> 25249 */
{0x62a2, 0xc7c0}, /* '抢' -> 25250 */
{0x62a4, 0xbba4}, /* '护' -> 25252 */
{0x62a5, 0xb1a8}, /* '报' -> 25253 */
{0x62a8, 0xc5ea}, /* '抨' -> 25256 */
{0x62ab, 0xc5fb}, /* '披' -> 25259 */
{0x62ac, 0xcca7}, /* '抬' -> 25260 */
{0x62b1, 0xb1a7}, /* '抱' -> 25265 */
{0x62b5, 0xb5d6}, /* '抵' -> 25269 */
{0x62b9, 0xc4a8}, /* '抹' -> 25273 */
{0x62bb, 0xded3}, /* '抻' -> 25275 */
{0x62bc, 0xd1ba}, /* '押' -> 25276 */
{0x62bd, 0xb3e9}, /* '抽' -> 25277 */
{0x62bf, 0xc3f2}, /* '抿' -> 25279 */
{0x62c2, 0xb7f7}, /* '拂' -> 25282 */
{0x62c4, 0xd6f4}, /* '拄' -> 25284 */
{0x62c5, 0xb5a3}, /* '担' -> 25285 */
{0x62c6, 0xb2f0}, /* '拆' -> 25286 */
{0x62c7, 0xc4b4}, /* '拇' -> 25287 */
{0x62c8, 0xc4e9}, /* '拈' -> 25288 */
{0x62c9, 0xc0ad}, /* '拉' -> 25289 */
{0x62ca, 0xded4}, /* '拊' -> 25290 */
{0x62cc, 0xb0e8}, /* '拌' -> 25292 */
{0x62cd, 0xc5c4}, /* '拍' -> 25293 */
{0x62ce, 0xc1e0}, /* '拎' -> 25294 */
{0x62d0, 0xb9d5}, /* '拐' -> 25296 */
{0x62d2, 0xbedc}, /* '拒' -> 25298 */
{0x62d3, 0xcdd8}, /* '拓' -> 25299 */
{0x62d4, 0xb0ce}, /* '拔' -> 25300 */
{0x62d6, 0xcdcf}, /* '拖' -> 25302 */
{0x62d7, 0xded6}, /* '拗' -> 25303 */
{0x62d8, 0xbed0}, /* '拘' -> 25304 */
{0x62d9, 0xd7be}, /* '拙' -> 25305 */
{0x62da, 0xded5}, /* '拚' -> 25306 */
{0x62db, 0xd5d0}, /* '招' -> 25307 */
{0x62dc, 0xb0dd}, /* '拜' -> 25308 */
{0x62df, 0xc4e2}, /* '拟' -> 25311 */
{0x62e2, 0xc2a3}, /* '拢' -> 25314 */
{0x62e3, 0xbcf0}, /* '拣' -> 25315 */
{0x62e5, 0xd3b5}, /* '拥' -> 25317 */
{0x62e6, 0xc0b9}, /* '拦' -> 25318 */
{0x62e7, 0xc5a1}, /* '拧' -> 25319 */
{0x62e8, 0xb2a6}, /* '拨' -> 25320 */
{0x62e9, 0xd4f1}, /* '择' -> 25321 */
{0x62ec, 0xc0a8}, /* '括' -> 25324 */
{0x62ed, 0xcac3}, /* '拭' -> 25325 */
{0x62ee, 0xded7}, /* '拮' -> 25326 */
{0x62ef, 0xd5fc}, /* '拯' -> 25327 */
{0x62f1, 0xb9b0}, /* '拱' -> 25329 */
{0x62f3, 0xc8ad}, /* '拳' -> 25331 */
{0x62f4, 0xcba9}, /* '拴' -> 25332 */
{0x62f6, 0xded9}, /* '拶' -> 25334 */
{0x62f7, 0xbfbd}, /* '拷' -> 25335 */
{0x62fc, 0xc6b4}, /* '拼' -> 25340 */
{0x62fd, 0xd7a7}, /* '拽' -> 25341 */
{0x62fe, 0xcab0}, /* '拾' -> 25342 */
{0x62ff, 0xc4c3}, /* '拿' -> 25343 */
{0x6301, 0xb3d6}, /* '持' -> 25345 */
{0x6302, 0xb9d2}, /* '挂' -> 25346 */
{0x6307, 0xd6b8}, /* '指' -> 25351 */
{0x6308, 0xeafc}, /* '挈' -> 25352 */
{0x6309, 0xb0b4}, /* '按' -> 25353 */
{0x630e, 0xbfe6}, /* '挎' -> 25358 */
{0x6311, 0xccf4}, /* '挑' -> 25361 */
{0x6316, 0xcdda}, /* '挖' -> 25366 */
{0x631a, 0xd6bf}, /* '挚' -> 25370 */
{0x631b, 0xc2ce}, /* '挛' -> 25371 */
{0x631d, 0xcece}, /* '挝' -> 25373 */
{0x631e, 0xcca2}, /* '挞' -> 25374 */
{0x631f, 0xd0ae}, /* '挟' -> 25375 */
{0x6320, 0xc4d3}, /* '挠' -> 25376 */
{0x6321, 0xb5b2}, /* '挡' -> 25377 */
{0x6322, 0xded8}, /* '挢' -> 25378 */
{0x6323, 0xd5f5}, /* '挣' -> 25379 */
{0x6324, 0xbcb7}, /* '挤' -> 25380 */
{0x6325, 0xbbd3}, /* '挥' -> 25381 */
{0x6328, 0xb0a4}, /* '挨' -> 25384 */
{0x632a, 0xc5b2}, /* '挪' -> 25386 */
{0x632b, 0xb4ec}, /* '挫' -> 25387 */
{0x632f, 0xd5f1}, /* '振' -> 25391 */
{0x6332, 0xeafd}, /* '挲' -> 25394 */
{0x6339, 0xdeda}, /* '挹' -> 25401 */
{0x633a, 0xcda6}, /* '挺' -> 25402 */
{0x633d, 0xcdec}, /* '挽' -> 25405 */
{0x6342, 0xcee6}, /* '捂' -> 25410 */
{0x6343, 0xdedc}, /* '捃' -> 25411 */
{0x6345, 0xcdb1}, /* '捅' -> 25413 */
{0x6346, 0xc0a6}, /* '捆' -> 25414 */
{0x6349, 0xd7bd}, /* '捉' -> 25417 */
{0x634b, 0xdedb}, /* '捋' -> 25419 */
{0x634c, 0xb0c6}, /* '捌' -> 25420 */
{0x634d, 0xbab4}, /* '捍' -> 25421 */
{0x634e, 0xc9d3}, /* '捎' -> 25422 */
{0x634f, 0xc4f3}, /* '捏' -> 25423 */
{0x6350, 0xbee8}, /* '捐' -> 25424 */
{0x6355, 0xb2b6}, /* '捕' -> 25429 */
{0x635e, 0xc0cc}, /* '捞' -> 25438 */
{0x635f, 0xcbf0}, /* '损' -> 25439 */
{0x6361, 0xbcf1}, /* '捡' -> 25441 */
{0x6362, 0xbbbb}, /* '换' -> 25442 */
{0x6363, 0xb5b7}, /* '捣' -> 25443 */
{0x6367, 0xc5f5}, /* '捧' -> 25447 */
{0x6369, 0xdee6}, /* '捩' -> 25449 */
{0x636d, 0xdee3}, /* '捭' -> 25453 */
{0x636e, 0xbedd}, /* '据' -> 25454 */
{0x6371, 0xdedf}, /* '捱' -> 25457 */
{0x6376, 0xb4b7}, /* '捶' -> 25462 */
{0x6377, 0xbddd}, /* '捷' -> 25463 */
{0x637a, 0xdee0}, /* '捺' -> 25466 */
{0x637b, 0xc4ed}, /* '捻' -> 25467 */
{0x6380, 0xcfc6}, /* '掀' -> 25472 */
{0x6382, 0xb5e0}, /* '掂' -> 25474 */
{0x6387, 0xb6de}, /* '掇' -> 25479 */
{0x6388, 0xcada}, /* '授' -> 25480 */
{0x6389, 0xb5f4}, /* '掉' -> 25481 */
{0x638a, 0xdee5}, /* '掊' -> 25482 */
{0x638c, 0xd5c6}, /* '掌' -> 25484 */
{0x638e, 0xdee1}, /* '掎' -> 25486 */
{0x638f, 0xcccd}, /* '掏' -> 25487 */
{0x6390, 0xc6fe}, /* '掐' -> 25488 */
{0x6392, 0xc5c5}, /* '排' -> 25490 */
{0x6396, 0xd2b4}, /* '掖' -> 25494 */
{0x6398, 0xbef2}, /* '掘' -> 25496 */
{0x63a0, 0xc2d3}, /* '掠' -> 25504 */
{0x63a2, 0xccbd}, /* '探' -> 25506 */
{0x63a3, 0xb3b8}, /* '掣' -> 25507 */
{0x63a5, 0xbdd3}, /* '接' -> 25509 */
{0x63a7, 0xbfd8}, /* '控' -> 25511 */
{0x63a8, 0xcdc6}, /* '推' -> 25512 */
{0x63a9, 0xd1da}, /* '掩' -> 25513 */
{0x63aa, 0xb4eb}, /* '措' -> 25514 */
{0x63ac, 0xdee4}, /* '掬' -> 25516 */
{0x63ad, 0xdedd}, /* '掭' -> 25517 */
{0x63ae, 0xdee7}, /* '掮' -> 25518 */
{0x63b0, 0xeafe}, /* '掰' -> 25520 */
{0x63b3, 0xc2b0}, /* '掳' -> 25523 */
{0x63b4, 0xdee2}, /* '掴' -> 25524 */
{0x63b7, 0xd6c0}, /* '掷' -> 25527 */
{0x63b8, 0xb5a7}, /* '掸' -> 25528 */
{0x63ba, 0xb2f4}, /* '掺' -> 25530 */
{0x63bc, 0xdee8}, /* '掼' -> 25532 */
{0x63be, 0xdef2}, /* '掾' -> 25534 */
{0x63c4, 0xdeed}, /* '揄' -> 25540 */
{0x63c6, 0xdef1}, /* '揆' -> 25542 */
{0x63c9, 0xc8e0}, /* '揉' -> 25545 */
{0x63cd, 0xd7e1}, /* '揍' -> 25549 */
{0x63ce, 0xdeef}, /* '揎' -> 25550 */
{0x63cf, 0xc3e8}, /* '描' -> 25551 */
{0x63d0, 0xcce1}, /* '提' -> 25552 */
{0x63d2, 0xb2e5}, /* '插' -> 25554 */
{0x63d6, 0xd2be}, /* '揖' -> 25558 */
{0x63de, 0xdeee}, /* '揞' -> 25566 */
{0x63e0, 0xdeeb}, /* '揠' -> 25568 */
{0x63e1, 0xced5}, /* '握' -> 25569 */
{0x63e3, 0xb4a7}, /* '揣' -> 25571 */
{0x63e9, 0xbfab}, /* '揩' -> 25577 */
{0x63ea, 0xbebe}, /* '揪' -> 25578 */
{0x63ed, 0xbdd2}, /* '揭' -> 25581 */
{0x63f2, 0xdee9}, /* '揲' -> 25586 */
{0x63f4, 0xd4ae}, /* '援' -> 25588 */
{0x63f6, 0xdede}, /* '揶' -> 25590 */
{0x63f8, 0xdeea}, /* '揸' -> 25592 */
{0x63fd, 0xc0bf}, /* '揽' -> 25597 */
{0x63ff, 0xdeec}, /* '揿' -> 25599 */
{0x6400, 0xb2f3}, /* '搀' -> 25600 */
{0x6401, 0xb8e9}, /* '搁' -> 25601 */
{0x6402, 0xc2a7}, /* '搂' -> 25602 */
{0x6405, 0xbdc1}, /* '搅' -> 25605 */
{0x640b, 0xdef5}, /* '搋' -> 25611 */
{0x640c, 0xdef8}, /* '搌' -> 25612 */
{0x640f, 0xb2ab}, /* '搏' -> 25615 */
{0x6410, 0xb4a4}, /* '搐' -> 25616 */
{0x6413, 0xb4ea}, /* '搓' -> 25619 */
{0x6414, 0xc9a6}, /* '搔' -> 25620 */
{0x641b, 0xdef6}, /* '搛' -> 25627 */
{0x641c, 0xcbd1}, /* '搜' -> 25628 */
{0x641e, 0xb8e3}, /* '搞' -> 25630 */
{0x6420, 0xdef7}, /* '搠' -> 25632 */
{0x6421, 0xdefa}, /* '搡' -> 25633 */
{0x6426, 0xdef9}, /* '搦' -> 25638 */
{0x642a, 0xccc2}, /* '搪' -> 25642 */
{0x642c, 0xb0e1}, /* '搬' -> 25644 */
{0x642d, 0xb4ee}, /* '搭' -> 25645 */
{0x6434, 0xe5ba}, /* '搴' -> 25652 */
{0x643a, 0xd0af}, /* '携' -> 25658 */
{0x643d, 0xb2eb}, /* '搽' -> 25661 */
{0x643f, 0xeba1}, /* '搿' -> 25663 */
{0x6441, 0xdef4}, /* '摁' -> 25665 */
{0x6444, 0xc9e3}, /* '摄' -> 25668 */
{0x6445, 0xdef3}, /* '摅' -> 25669 */
{0x6446, 0xb0da}, /* '摆' -> 25670 */
{0x6447, 0xd2a1}, /* '摇' -> 25671 */
{0x6448, 0xb1f7}, /* '摈' -> 25672 */
{0x644a, 0xccaf}, /* '摊' -> 25674 */
{0x6452, 0xdef0}, /* '摒' -> 25682 */
{0x6454, 0xcba4}, /* '摔' -> 25684 */
{0x6458, 0xd5aa}, /* '摘' -> 25688 */
{0x645e, 0xdefb}, /* '摞' -> 25694 */
{0x6467, 0xb4dd}, /* '摧' -> 25703 */
{0x6469, 0xc4a6}, /* '摩' -> 25705 */
{0x646d, 0xdefd}, /* '摭' -> 25709 */
{0x6478, 0xc3fe}, /* '摸' -> 25720 */
{0x6479, 0xc4a1}, /* '摹' -> 25721 */
{0x647a, 0xdfa1}, /* '摺' -> 25722 */
{0x6482, 0xc1cc}, /* '撂' -> 25730 */
{0x6484, 0xdefc}, /* '撄' -> 25732 */
{0x6485, 0xbeef}, /* '撅' -> 25733 */
{0x6487, 0xc6b2}, /* '撇' -> 25735 */
{0x6491, 0xb3c5}, /* '撑' -> 25745 */
{0x6492, 0xc8f6}, /* '撒' -> 25746 */
{0x6495, 0xcbba}, /* '撕' -> 25749 */
{0x6496, 0xdefe}, /* '撖' -> 25750 */
{0x6499, 0xdfa4}, /* '撙' -> 25753 */
{0x649e, 0xd7b2}, /* '撞' -> 25758 */
{0x64a4, 0xb3b7}, /* '撤' -> 25764 */
{0x64a9, 0xc1c3}, /* '撩' -> 25769 */
{0x64ac, 0xc7cb}, /* '撬' -> 25772 */
{0x64ad, 0xb2a5}, /* '播' -> 25773 */
{0x64ae, 0xb4e9}, /* '撮' -> 25774 */
{0x64b0, 0xd7ab}, /* '撰' -> 25776 */
{0x64b5, 0xc4ec}, /* '撵' -> 25781 */
{0x64b7, 0xdfa2}, /* '撷' -> 25783 */
{0x64b8, 0xdfa3}, /* '撸' -> 25784 */
{0x64ba, 0xdfa5}, /* '撺' -> 25786 */
{0x64bc, 0xbab3}, /* '撼' -> 25788 */
{0x64c0, 0xdfa6}, /* '擀' -> 25792 */
{0x64c2, 0xc0de}, /* '擂' -> 25794 */
{0x64c5, 0xc9c3}, /* '擅' -> 25797 */
{0x64cd, 0xb2d9}, /* '操' -> 25805 */
{0x64ce, 0xc7e6}, /* '擎' -> 25806 */
{0x64d0, 0xdfa7}, /* '擐' -> 25808 */
{0x64d2, 0xc7dc}, /* '擒' -> 25810 */
{0x64d7, 0xdfa8}, /* '擗' -> 25815 */
{0x64d8, 0xeba2}, /* '擘' -> 25816 */
{0x64de, 0xcbd3}, /* '擞' -> 25822 */
{0x64e2, 0xdfaa}, /* '擢' -> 25826 */
{0x64e4, 0xdfa9}, /* '擤' -> 25828 */
{0x64e6, 0xb2c1}, /* '擦' -> 25830 */
{0x6500, 0xc5ca}, /* '攀' -> 25856 */
{0x6509, 0xdfab}, /* '攉' -> 25865 */
{0x6512, 0xd4dc}, /* '攒' -> 25874 */
{0x6518, 0xc8c1}, /* '攘' -> 25880 */
{0x6525, 0xdfac}, /* '攥' -> 25893 */
{0x652b, 0xbef0}, /* '攫' -> 25899 */
{0x652e, 0xdfad}, /* '攮' -> 25902 */
{0x652f, 0xd6a7}, /* '支' -> 25903 */
{0x6534, 0xeab7}, /* '攴' -> 25908 */
{0x6535, 0xebb6}, /* '攵' -> 25909 */
{0x6536, 0xcad5}, /* '收' -> 25910 */
{0x6538, 0xd8fc}, /* '攸' -> 25912 */
{0x6539, 0xb8c4}, /* '改' -> 25913 */
{0x653b, 0xb9a5}, /* '攻' -> 25915 */
{0x653e, 0xb7c5}, /* '放' -> 25918 */
{0x653f, 0xd5fe}, /* '政' -> 25919 */
{0x6545, 0xb9ca}, /* '故' -> 25925 */
{0x6548, 0xd0a7}, /* '效' -> 25928 */
{0x6549, 0xf4cd}, /* '敉' -> 25929 */
{0x654c, 0xb5d0}, /* '敌' -> 25932 */
{0x654f, 0xc3f4}, /* '敏' -> 25935 */
{0x6551, 0xbec8}, /* '救' -> 25937 */
{0x6555, 0xebb7}, /* '敕' -> 25941 */
{0x6556, 0xb0bd}, /* '敖' -> 25942 */
{0x6559, 0xbdcc}, /* '教' -> 25945 */
{0x655b, 0xc1b2}, /* '敛' -> 25947 */
{0x655d, 0xb1d6}, /* '敝' -> 25949 */
{0x655e, 0xb3a8}, /* '敞' -> 25950 */
{0x6562, 0xb8d2}, /* '敢' -> 25954 */
{0x6563, 0xc9a2}, /* '散' -> 25955 */
{0x6566, 0xb6d8}, /* '敦' -> 25958 */
{0x656b, 0xebb8}, /* '敫' -> 25963 */
{0x656c, 0xbeb4}, /* '敬' -> 25964 */
{0x6570, 0xcafd}, /* '数' -> 25968 */
{0x6572, 0xc7c3}, /* '敲' -> 25970 */
{0x6574, 0xd5fb}, /* '整' -> 25972 */
{0x6577, 0xb7f3}, /* '敷' -> 25975 */
{0x6587, 0xcec4}, /* '文' -> 25991 */
{0x658b, 0xd5ab}, /* '斋' -> 25995 */
{0x658c, 0xb1f3}, /* '斌' -> 25996 */
{0x6590, 0xecb3}, /* '斐' -> 26000 */
{0x6591, 0xb0df}, /* '斑' -> 26001 */
{0x6593, 0xecb5}, /* '斓' -> 26003 */
{0x6597, 0xb6b7}, /* '斗' -> 26007 */
{0x6599, 0xc1cf}, /* '料' -> 26009 */
{0x659b, 0xf5fa}, /* '斛' -> 26011 */
{0x659c, 0xd0b1}, /* '斜' -> 26012 */
{0x659f, 0xd5e5}, /* '斟' -> 26015 */
{0x65a1, 0xced3}, /* '斡' -> 26017 */
{0x65a4, 0xbdef}, /* '斤' -> 26020 */
{0x65a5, 0xb3e2}, /* '斥' -> 26021 */
{0x65a7, 0xb8ab}, /* '斧' -> 26023 */
{0x65a9, 0xd5b6}, /* '斩' -> 26025 */
{0x65ab, 0xedbd}, /* '斫' -> 26027 */
{0x65ad, 0xb6cf}, /* '断' -> 26029 */
{0x65af, 0xcbb9}, /* '斯' -> 26031 */
{0x65b0, 0xd0c2}, /* '新' -> 26032 */
{0x65b9, 0xb7bd}, /* '方' -> 26041 */
{0x65bc, 0xecb6}, /* '於' -> 26044 */
{0x65bd, 0xcaa9}, /* '施' -> 26045 */
{0x65c1, 0xc5d4}, /* '旁' -> 26049 */
{0x65c3, 0xecb9}, /* '旃' -> 26051 */
{0x65c4, 0xecb8}, /* '旄' -> 26052 */
{0x65c5, 0xc2c3}, /* '旅' -> 26053 */
{0x65c6, 0xecb7}, /* '旆' -> 26054 */
{0x65cb, 0xd0fd}, /* '旋' -> 26059 */
{0x65cc, 0xecba}, /* '旌' -> 26060 */
{0x65ce, 0xecbb}, /* '旎' -> 26062 */
{0x65cf, 0xd7e5}, /* '族' -> 26063 */
{0x65d2, 0xecbc}, /* '旒' -> 26066 */
{0x65d6, 0xecbd}, /* '旖' -> 26070 */
{0x65d7, 0xc6ec}, /* '旗' -> 26071 */
{0x65e0, 0xcede}, /* '无' -> 26080 */
{0x65e2, 0xbcc8}, /* '既' -> 26082 */
{0x65e5, 0xc8d5}, /* '日' -> 26085 */
{0x65e6, 0xb5a9}, /* '旦' -> 26086 */
{0x65e7, 0xbec9}, /* '旧' -> 26087 */
{0x65e8, 0xd6bc}, /* '旨' -> 26088 */
{0x65e9, 0xd4e7}, /* '早' -> 26089 */
{0x65ec, 0xd1ae}, /* '旬' -> 26092 */
{0x65ed, 0xd0f1}, /* '旭' -> 26093 */
{0x65ee, 0xeab8}, /* '旮' -> 26094 */
{0x65ef, 0xeab9}, /* '旯' -> 26095 */
{0x65f0, 0xeaba}, /* '旰' -> 26096 */
{0x65f1, 0xbab5}, /* '旱' -> 26097 */
{0x65f6, 0xcab1}, /* '时' -> 26102 */
{0x65f7, 0xbff5}, /* '旷' -> 26103 */
{0x65fa, 0xcdfa}, /* '旺' -> 26106 */
{0x6600, 0xeac0}, /* '昀' -> 26112 */
{0x6602, 0xb0ba}, /* '昂' -> 26114 */
{0x6603, 0xeabe}, /* '昃' -> 26115 */
{0x6606, 0xc0a5}, /* '昆' -> 26118 */
{0x660a, 0xeabb}, /* '昊' -> 26122 */
{0x660c, 0xb2fd}, /* '昌' -> 26124 */
{0x660e, 0xc3f7}, /* '明' -> 26126 */
{0x660f, 0xbbe8}, /* '昏' -> 26127 */
{0x6613, 0xd2d7}, /* '易' -> 26131 */
{0x6614, 0xcef4}, /* '昔' -> 26132 */
{0x6615, 0xeabf}, /* '昕' -> 26133 */
{0x6619, 0xeabc}, /* '昙' -> 26137 */
{0x661d, 0xeac3}, /* '昝' -> 26141 */
{0x661f, 0xd0c7}, /* '星' -> 26143 */
{0x6620, 0xd3b3}, /* '映' -> 26144 */
{0x6625, 0xb4ba}, /* '春' -> 26149 */
{0x6627, 0xc3c1}, /* '昧' -> 26151 */
{0x6628, 0xd7f2}, /* '昨' -> 26152 */
{0x662d, 0xd5d1}, /* '昭' -> 26157 */
{0x662f, 0xcac7}, /* '是' -> 26159 */
{0x6631, 0xeac5}, /* '昱' -> 26161 */
{0x6634, 0xeac4}, /* '昴' -> 26164 */
{0x6635, 0xeac7}, /* '昵' -> 26165 */
{0x6636, 0xeac6}, /* '昶' -> 26166 */
{0x663c, 0xd6e7}, /* '昼' -> 26172 */
{0x663e, 0xcfd4}, /* '显' -> 26174 */
{0x6641, 0xeacb}, /* '晁' -> 26177 */
{0x6643, 0xbbce}, /* '晃' -> 26179 */
{0x664b, 0xbdfa}, /* '晋' -> 26187 */
{0x664c, 0xc9ce}, /* '晌' -> 26188 */
{0x664f, 0xeacc}, /* '晏' -> 26191 */
{0x6652, 0xc9b9}, /* '晒' -> 26194 */
{0x6653, 0xcffe}, /* '晓' -> 26195 */
{0x6654, 0xeaca}, /* '晔' -> 26196 */
{0x6655, 0xd4ce}, /* '晕' -> 26197 */
{0x6656, 0xeacd}, /* '晖' -> 26198 */
{0x6657, 0xeacf}, /* '晗' -> 26199 */
{0x665a, 0xcded}, /* '晚' -> 26202 */
{0x665f, 0xeac9}, /* '晟' -> 26207 */
{0x6661, 0xeace}, /* '晡' -> 26209 */
{0x6664, 0xceee}, /* '晤' -> 26212 */
{0x6666, 0xbbde}, /* '晦' -> 26214 */
{0x6668, 0xb3bf}, /* '晨' -> 26216 */
{0x666e, 0xc6d5}, /* '普' -> 26222 */
{0x666f, 0xbeb0}, /* '景' -> 26223 */
{0x6670, 0xcefa}, /* '晰' -> 26224 */
{0x6674, 0xc7e7}, /* '晴' -> 26228 */
{0x6676, 0xbea7}, /* '晶' -> 26230 */
{0x6677, 0xead0}, /* '晷' -> 26231 */
{0x667a, 0xd6c7}, /* '智' -> 26234 */
{0x667e, 0xc1c0}, /* '晾' -> 26238 */
{0x6682, 0xd4dd}, /* '暂' -> 26242 */
{0x6684, 0xead1}, /* '暄' -> 26244 */
{0x6687, 0xcfbe}, /* '暇' -> 26247 */
{0x668c, 0xead2}, /* '暌' -> 26252 */
{0x6691, 0xcaee}, /* '暑' -> 26257 */
{0x6696, 0xc5af}, /* '暖' -> 26262 */
{0x6697, 0xb0b5}, /* '暗' -> 26263 */
{0x669d, 0xead4}, /* '暝' -> 26269 */
{0x66a7, 0xead3}, /* '暧' -> 26279 */
{0x66a8, 0xf4df}, /* '暨' -> 26280 */
{0x66ae, 0xc4ba}, /* '暮' -> 26286 */
{0x66b4, 0xb1a9}, /* '暴' -> 26292 */
{0x66b9, 0xe5df}, /* '暹' -> 26297 */
{0x66be, 0xead5}, /* '暾' -> 26302 */
{0x66d9, 0xcaef}, /* '曙' -> 26329 */
{0x66db, 0xead6}, /* '曛' -> 26331 */
{0x66dc, 0xead7}, /* '曜' -> 26332 */
{0x66dd, 0xc6d8}, /* '曝' -> 26333 */
{0x66e6, 0xead8}, /* '曦' -> 26342 */
{0x66e9, 0xead9}, /* '曩' -> 26345 */
{0x66f0, 0xd4bb}, /* '曰' -> 26352 */
{0x66f2, 0xc7fa}, /* '曲' -> 26354 */
{0x66f3, 0xd2b7}, /* '曳' -> 26355 */
{0x66f4, 0xb8fc}, /* '更' -> 26356 */
{0x66f7, 0xeac2}, /* '曷' -> 26359 */
{0x66f9, 0xb2dc}, /* '曹' -> 26361 */
{0x66fc, 0xc2fc}, /* '曼' -> 26364 */
{0x66fe, 0xd4f8}, /* '曾' -> 26366 */
{0x66ff, 0xcce6}, /* '替' -> 26367 */
{0x6700, 0xd7ee}, /* '最' -> 26368 */
{0x6708, 0xd4c2}, /* '月' -> 26376 */
{0x6709, 0xd3d0}, /* '有' -> 26377 */
{0x670a, 0xebc3}, /* '朊' -> 26378 */
{0x670b, 0xc5f3}, /* '朋' -> 26379 */
{0x670d, 0xb7fe}, /* '服' -> 26381 */
{0x6710, 0xebd4}, /* '朐' -> 26384 */
{0x6714, 0xcbb7}, /* '朔' -> 26388 */
{0x6715, 0xebde}, /* '朕' -> 26389 */
{0x6717, 0xc0ca}, /* '朗' -> 26391 */
{0x671b, 0xcdfb}, /* '望' -> 26395 */
{0x671d, 0xb3af}, /* '朝' -> 26397 */
{0x671f, 0xc6da}, /* '期' -> 26399 */
{0x6726, 0xebfc}, /* '朦' -> 26406 */
{0x6728, 0xc4be}, /* '木' -> 26408 */
{0x672a, 0xceb4}, /* '未' -> 26410 */
{0x672b, 0xc4a9}, /* '末' -> 26411 */
{0x672c, 0xb1be}, /* '本' -> 26412 */
{0x672d, 0xd4fd}, /* '札' -> 26413 */
{0x672f, 0xcaf5}, /* '术' -> 26415 */
{0x6731, 0xd6ec}, /* '朱' -> 26417 */
{0x6734, 0xc6d3}, /* '朴' -> 26420 */
{0x6735, 0xb6e4}, /* '朵' -> 26421 */
{0x673a, 0xbbfa}, /* '机' -> 26426 */
{0x673d, 0xd0e0}, /* '朽' -> 26429 */
{0x6740, 0xc9b1}, /* '杀' -> 26432 */
{0x6742, 0xd4d3}, /* '杂' -> 26434 */
{0x6743, 0xc8a8}, /* '权' -> 26435 */
{0x6746, 0xb8cb}, /* '杆' -> 26438 */
{0x6748, 0xe8be}, /* '杈' -> 26440 */
{0x6749, 0xc9bc}, /* '杉' -> 26441 */
{0x674c, 0xe8bb}, /* '杌' -> 26444 */
{0x674e, 0xc0ee}, /* '李' -> 26446 */
{0x674f, 0xd0d3}, /* '杏' -> 26447 */
{0x6750, 0xb2c4}, /* '材' -> 26448 */
{0x6751, 0xb4e5}, /* '村' -> 26449 */
{0x6753, 0xe8bc}, /* '杓' -> 26451 */
{0x6756, 0xd5c8}, /* '杖' -> 26454 */
{0x675c, 0xb6c5}, /* '杜' -> 26460 */
{0x675e, 0xe8bd}, /* '杞' -> 26462 */
{0x675f, 0xcaf8}, /* '束' -> 26463 */
{0x6760, 0xb8dc}, /* '杠' -> 26464 */
{0x6761, 0xccf5}, /* '条' -> 26465 */
{0x6765, 0xc0b4}, /* '来' -> 26469 */
{0x6768, 0xd1ee}, /* '杨' -> 26472 */
{0x6769, 0xe8bf}, /* '杩' -> 26473 */
{0x676a, 0xe8c2}, /* '杪' -> 26474 */
{0x676d, 0xbabc}, /* '杭' -> 26477 */
{0x676f, 0xb1ad}, /* '杯' -> 26479 */
{0x6770, 0xbddc}, /* '杰' -> 26480 */
{0x6772, 0xeabd}, /* '杲' -> 26482 */
{0x6773, 0xe8c3}, /* '杳' -> 26483 */
{0x6775, 0xe8c6}, /* '杵' -> 26485 */
{0x6777, 0xe8cb}, /* '杷' -> 26487 */
{0x677c, 0xe8cc}, /* '杼' -> 26492 */
{0x677e, 0xcbc9}, /* '松' -> 26494 */
{0x677f, 0xb0e5}, /* '板' -> 26495 */
{0x6781, 0xbcab}, /* '极' -> 26497 */
{0x6784, 0xb9b9}, /* '构' -> 26500 */
{0x6787, 0xe8c1}, /* '枇' -> 26503 */
{0x6789, 0xcdf7}, /* '枉' -> 26505 */
{0x678b, 0xe8ca}, /* '枋' -> 26507 */
{0x6790, 0xcef6}, /* '析' -> 26512 */
{0x6795, 0xd5ed}, /* '枕' -> 26517 */
{0x6797, 0xc1d6}, /* '林' -> 26519 */
{0x6798, 0xe8c4}, /* '枘' -> 26520 */
{0x679a, 0xc3b6}, /* '枚' -> 26522 */
{0x679c, 0xb9fb}, /* '果' -> 26524 */
{0x679d, 0xd6a6}, /* '枝' -> 26525 */
{0x679e, 0xe8c8}, /* '枞' -> 26526 */
{0x67a2, 0xcae0}, /* '枢' -> 26530 */
{0x67a3, 0xd4e6}, /* '枣' -> 26531 */
{0x67a5, 0xe8c0}, /* '枥' -> 26533 */
{0x67a7, 0xe8c5}, /* '枧' -> 26535 */
{0x67a8, 0xe8c7}, /* '枨' -> 26536 */
{0x67aa, 0xc7b9}, /* '枪' -> 26538 */
{0x67ab, 0xb7e3}, /* '枫' -> 26539 */
{0x67ad, 0xe8c9}, /* '枭' -> 26541 */
{0x67af, 0xbfdd}, /* '枯' -> 26543 */
{0x67b0, 0xe8d2}, /* '枰' -> 26544 */
{0x67b3, 0xe8d7}, /* '枳' -> 26547 */
{0x67b5, 0xe8d5}, /* '枵' -> 26549 */
{0x67b6, 0xbcdc}, /* '架' -> 26550 */
{0x67b7, 0xbccf}, /* '枷' -> 26551 */
{0x67b8, 0xe8db}, /* '枸' -> 26552 */
{0x67c1, 0xe8de}, /* '柁' -> 26561 */
{0x67c3, 0xe8da}, /* '柃' -> 26563 */
{0x67c4, 0xb1fa}, /* '柄' -> 26564 */
{0x67cf, 0xb0d8}, /* '柏' -> 26575 */
{0x67d0, 0xc4b3}, /* '某' -> 26576 */
{0x67d1, 0xb8cc}, /* '柑' -> 26577 */
{0x67d2, 0xc6e2}, /* '柒' -> 26578 */
{0x67d3, 0xc8be}, /* '染' -> 26579 */
{0x67d4, 0xc8e1}, /* '柔' -> 26580 */
{0x67d8, 0xe8cf}, /* '柘' -> 26584 */
{0x67d9, 0xe8d4}, /* '柙' -> 26585 */
{0x67da, 0xe8d6}, /* '柚' -> 26586 */
{0x67dc, 0xb9f1}, /* '柜' -> 26588 */
{0x67dd, 0xe8d8}, /* '柝' -> 26589 */
{0x67de, 0xd7f5}, /* '柞' -> 26590 */
{0x67e0, 0xc4fb}, /* '柠' -> 26592 */
{0x67e2, 0xe8dc}, /* '柢' -> 26594 */
{0x67e5, 0xb2e9}, /* '查' -> 26597 */
{0x67e9, 0xe8d1}, /* '柩' -> 26601 */
{0x67ec, 0xbced}, /* '柬' -> 26604 */
{0x67ef, 0xbfc2}, /* '柯' -> 26607 */
{0x67f0, 0xe8cd}, /* '柰' -> 26608 */
{0x67f1, 0xd6f9}, /* '柱' -> 26609 */
{0x67f3, 0xc1f8}, /* '柳' -> 26611 */
{0x67f4, 0xb2f1}, /* '柴' -> 26612 */
{0x67fd, 0xe8df}, /* '柽' -> 26621 */
{0x67ff, 0xcac1}, /* '柿' -> 26623 */
{0x6800, 0xe8d9}, /* '栀' -> 26624 */
{0x6805, 0xd5a4}, /* '栅' -> 26629 */
{0x6807, 0xb1ea}, /* '标' -> 26631 */
{0x6808, 0xd5bb}, /* '栈' -> 26632 */
{0x6809, 0xe8ce}, /* '栉' -> 26633 */
{0x680a, 0xe8d0}, /* '栊' -> 26634 */
{0x680b, 0xb6b0}, /* '栋' -> 26635 */
{0x680c, 0xe8d3}, /* '栌' -> 26636 */
{0x680e, 0xe8dd}, /* '栎' -> 26638 */
{0x680f, 0xc0b8}, /* '栏' -> 26639 */
{0x6811, 0xcaf7}, /* '树' -> 26641 */
{0x6813, 0xcba8}, /* '栓' -> 26643 */
{0x6816, 0xc6dc}, /* '栖' -> 26646 */
{0x6817, 0xc0f5}, /* '栗' -> 26647 */
{0x681d, 0xe8e9}, /* '栝' -> 26653 */
{0x6821, 0xd0a3}, /* '校' -> 26657 */
{0x6829, 0xe8f2}, /* '栩' -> 26665 */
{0x682a, 0xd6ea}, /* '株' -> 26666 */
{0x6832, 0xe8e0}, /* '栲' -> 26674 */
{0x6833, 0xe8e1}, /* '栳' -> 26675 */
{0x6837, 0xd1f9}, /* '样' -> 26679 */
{0x6838, 0xbacb}, /* '核' -> 26680 */
{0x6839, 0xb8f9}, /* '根' -> 26681 */
{0x683c, 0xb8f1}, /* '格' -> 26684 */
{0x683d, 0xd4d4}, /* '栽' -> 26685 */
{0x683e, 0xe8ef}, /* '栾' -> 26686 */
{0x6840, 0xe8ee}, /* '桀' -> 26688 */
{0x6841, 0xe8ec}, /* '桁' -> 26689 */
{0x6842, 0xb9f0}, /* '桂' -> 26690 */
{0x6843, 0xccd2}, /* '桃' -> 26691 */
{0x6844, 0xe8e6}, /* '桄' -> 26692 */
{0x6845, 0xcea6}, /* '桅' -> 26693 */
{0x6846, 0xbff2}, /* '框' -> 26694 */
{0x6848, 0xb0b8}, /* '案' -> 26696 */
{0x6849, 0xe8f1}, /* '桉' -> 26697 */
{0x684a, 0xe8f0}, /* '桊' -> 26698 */
{0x684c, 0xd7c0}, /* '桌' -> 26700 */
{0x684e, 0xe8e4}, /* '桎' -> 26702 */
{0x6850, 0xcda9}, /* '桐' -> 26704 */
{0x6851, 0xc9a3}, /* '桑' -> 26705 */
{0x6853, 0xbbb8}, /* '桓' -> 26707 */
{0x6854, 0xbddb}, /* '桔' -> 26708 */
{0x6855, 0xe8ea}, /* '桕' -> 26709 */
{0x6860, 0xe8e2}, /* '桠' -> 26720 */
{0x6861, 0xe8e3}, /* '桡' -> 26721 */
{0x6862, 0xe8e5}, /* '桢' -> 26722 */
{0x6863, 0xb5b5}, /* '档' -> 26723 */
{0x6864, 0xe8e7}, /* '桤' -> 26724 */
{0x6865, 0xc7c5}, /* '桥' -> 26725 */
{0x6866, 0xe8eb}, /* '桦' -> 26726 */
{0x6867, 0xe8ed}, /* '桧' -> 26727 */
{0x6868, 0xbdb0}, /* '桨' -> 26728 */
{0x6869, 0xd7ae}, /* '桩' -> 26729 */
{0x686b, 0xe8f8}, /* '桫' -> 26731 */
{0x6874, 0xe8f5}, /* '桴' -> 26740 */
{0x6876, 0xcdb0}, /* '桶' -> 26742 */
{0x6877, 0xe8f6}, /* '桷' -> 26743 */
{0x6881, 0xc1ba}, /* '梁' -> 26753 */
{0x6883, 0xe8e8}, /* '梃' -> 26755 */
{0x6885, 0xc3b7}, /* '梅' -> 26757 */
{0x6886, 0xb0f0}, /* '梆' -> 26758 */
{0x688f, 0xe8f4}, /* '梏' -> 26767 */
{0x6893, 0xe8f7}, /* '梓' -> 26771 */
{0x6897, 0xb9a3}, /* '梗' -> 26775 */
{0x68a2, 0xc9d2}, /* '梢' -> 26786 */
{0x68a6, 0xc3ce}, /* '梦' -> 26790 */
{0x68a7, 0xcee0}, /* '梧' -> 26791 */
{0x68a8, 0xc0e6}, /* '梨' -> 26792 */
{0x68ad, 0xcbf3}, /* '梭' -> 26797 */
{0x68af, 0xccdd}, /* '梯' -> 26799 */
{0x68b0, 0xd0b5}, /* '械' -> 26800 */
{0x68b3, 0xcae1}, /* '梳' -> 26803 */
{0x68b5, 0xe8f3}, /* '梵' -> 26805 */
{0x68c0, 0xbcec}, /* '检' -> 26816 */
{0x68c2, 0xe8f9}, /* '棂' -> 26818 */
{0x68c9, 0xc3de}, /* '棉' -> 26825 */
{0x68cb, 0xc6e5}, /* '棋' -> 26827 */
{0x68cd, 0xb9f7}, /* '棍' -> 26829 */
{0x68d2, 0xb0f4}, /* '棒' -> 26834 */
{0x68d5, 0xd7d8}, /* '棕' -> 26837 */
{0x68d8, 0xbcac}, /* '棘' -> 26840 */
{0x68da, 0xc5ef}, /* '棚' -> 26842 */
{0x68e0, 0xccc4}, /* '棠' -> 26848 */
{0x68e3, 0xe9a6}, /* '棣' -> 26851 */
{0x68ee, 0xc9ad}, /* '森' -> 26862 */
{0x68f0, 0xe9a2}, /* '棰' -> 26864 */
{0x68f1, 0xc0e2}, /* '棱' -> 26865 */
{0x68f5, 0xbfc3}, /* '棵' -> 26869 */
{0x68f9, 0xe8fe}, /* '棹' -> 26873 */
{0x68fa, 0xb9d7}, /* '棺' -> 26874 */
{0x68fc, 0xe8fb}, /* '棼' -> 26876 */
{0x6901, 0xe9a4}, /* '椁' -> 26881 */
{0x6905, 0xd2ce}, /* '椅' -> 26885 */
{0x690b, 0xe9a3}, /* '椋' -> 26891 */
{0x690d, 0xd6b2}, /* '植' -> 26893 */
{0x690e, 0xd7b5}, /* '椎' -> 26894 */
{0x6910, 0xe9a7}, /* '椐' -> 26896 */
{0x6912, 0xbdb7}, /* '椒' -> 26898 */
{0x691f, 0xe8fc}, /* '椟' -> 26911 */
{0x6920, 0xe8fd}, /* '椠' -> 26912 */
{0x6924, 0xe9a1}, /* '椤' -> 26916 */
{0x692d, 0xcdd6}, /* '椭' -> 26925 */
{0x6930, 0xd2ac}, /* '椰' -> 26928 */
{0x6934, 0xe9b2}, /* '椴' -> 26932 */
{0x6939, 0xe9a9}, /* '椹' -> 26937 */
{0x693d, 0xb4aa}, /* '椽' -> 26941 */
{0x693f, 0xb4bb}, /* '椿' -> 26943 */
{0x6942, 0xe9ab}, /* '楂' -> 26946 */
{0x6954, 0xd0a8}, /* '楔' -> 26964 */
{0x6957, 0xe9a5}, /* '楗' -> 26967 */
{0x695a, 0xb3fe}, /* '楚' -> 26970 */
{0x695d, 0xe9ac}, /* '楝' -> 26973 */
{0x695e, 0xc0e3}, /* '楞' -> 26974 */
{0x6960, 0xe9aa}, /* '楠' -> 26976 */
{0x6963, 0xe9b9}, /* '楣' -> 26979 */
{0x6966, 0xe9b8}, /* '楦' -> 26982 */
{0x696b, 0xe9ae}, /* '楫' -> 26987 */
{0x696e, 0xe8fa}, /* '楮' -> 26990 */
{0x6971, 0xe9a8}, /* '楱' -> 26993 */
{0x6977, 0xbfac}, /* '楷' -> 26999 */
{0x6978, 0xe9b1}, /* '楸' -> 27000 */
{0x6979, 0xe9ba}, /* '楹' -> 27001 */
{0x697c, 0xc2a5}, /* '楼' -> 27004 */
{0x6980, 0xe9af}, /* '榀' -> 27008 */
{0x6982, 0xb8c5}, /* '概' -> 27010 */
{0x6984, 0xe9ad}, /* '榄' -> 27012 */
{0x6986, 0xd3dc}, /* '榆' -> 27014 */
{0x6987, 0xe9b4}, /* '榇' -> 27015 */
{0x6988, 0xe9b5}, /* '榈' -> 27016 */
{0x6989, 0xe9b7}, /* '榉' -> 27017 */
{0x698d, 0xe9c7}, /* '榍' -> 27021 */
{0x6994, 0xc0c6}, /* '榔' -> 27028 */
{0x6995, 0xe9c5}, /* '榕' -> 27029 */
{0x6998, 0xe9b0}, /* '榘' -> 27032 */
{0x699b, 0xe9bb}, /* '榛' -> 27035 */
{0x699c, 0xb0f1}, /* '榜' -> 27036 */
{0x69a7, 0xe9bc}, /* '榧' -> 27047 */
{0x69a8, 0xd5a5}, /* '榨' -> 27048 */
{0x69ab, 0xe9be}, /* '榫' -> 27051 */
{0x69ad, 0xe9bf}, /* '榭' -> 27053 */
{0x69b1, 0xe9c1}, /* '榱' -> 27057 */
{0x69b4, 0xc1f1}, /* '榴' -> 27060 */
{0x69b7, 0xc8b6}, /* '榷' -> 27063 */
{0x69bb, 0xe9bd}, /* '榻' -> 27067 */
{0x69c1, 0xe9c2}, /* '槁' -> 27073 */
{0x69ca, 0xe9c3}, /* '槊' -> 27082 */
{0x69cc, 0xe9b3}, /* '槌' -> 27084 */
{0x69ce, 0xe9b6}, /* '槎' -> 27086 */
{0x69d0, 0xbbb1}, /* '槐' -> 27088 */
{0x69d4, 0xe9c0}, /* '槔' -> 27092 */
{0x69db, 0xbcf7}, /* '槛' -> 27099 */
{0x69df, 0xe9c4}, /* '槟' -> 27103 */
{0x69e0, 0xe9c6}, /* '槠' -> 27104 */
{0x69ed, 0xe9ca}, /* '槭' -> 27117 */
{0x69f2, 0xe9ce}, /* '槲' -> 27122 */
{0x69fd, 0xb2db}, /* '槽' -> 27133 */
{0x69ff, 0xe9c8}, /* '槿' -> 27135 */
{0x6a0a, 0xb7ae}, /* '樊' -> 27146 */
{0x6a17, 0xe9cb}, /* '樗' -> 27159 */
{0x6a18, 0xe9cc}, /* '樘' -> 27160 */
{0x6a1f, 0xd5c1}, /* '樟' -> 27167 */
{0x6a21, 0xc4a3}, /* '模' -> 27169 */
{0x6a28, 0xe9d8}, /* '樨' -> 27176 */
{0x6a2a, 0xbae1}, /* '横' -> 27178 */
{0x6a2f, 0xe9c9}, /* '樯' -> 27183 */
{0x6a31, 0xd3a3}, /* '樱' -> 27185 */
{0x6a35, 0xe9d4}, /* '樵' -> 27189 */
{0x6a3d, 0xe9d7}, /* '樽' -> 27197 */
{0x6a3e, 0xe9d0}, /* '樾' -> 27198 */
{0x6a44, 0xe9cf}, /* '橄' -> 27204 */
{0x6a47, 0xc7c1}, /* '橇' -> 27207 */
{0x6a50, 0xe9d2}, /* '橐' -> 27216 */
{0x6a58, 0xe9d9}, /* '橘' -> 27224 */
{0x6a59, 0xb3c8}, /* '橙' -> 27225 */
{0x6a5b, 0xe9d3}, /* '橛' -> 27227 */
{0x6a61, 0xcff0}, /* '橡' -> 27233 */
{0x6a65, 0xe9cd}, /* '橥' -> 27237 */
{0x6a71, 0xb3f7}, /* '橱' -> 27249 */
{0x6a79, 0xe9d6}, /* '橹' -> 27257 */
{0x6a7c, 0xe9da}, /* '橼' -> 27260 */
{0x6a80, 0xccb4}, /* '檀' -> 27264 */
{0x6a84, 0xcfad}, /* '檄' -> 27268 */
{0x6a8e, 0xe9d5}, /* '檎' -> 27278 */
{0x6a90, 0xe9dc}, /* '檐' -> 27280 */
{0x6a91, 0xe9db}, /* '檑' -> 27281 */
{0x6a97, 0xe9de}, /* '檗' -> 27287 */
{0x6aa0, 0xe9d1}, /* '檠' -> 27296 */
{0x6aa9, 0xe9dd}, /* '檩' -> 27305 */
{0x6aab, 0xe9df}, /* '檫' -> 27307 */
{0x6aac, 0xc3ca}, /* '檬' -> 27308 */
{0x6b20, 0xc7b7}, /* '欠' -> 27424 */
{0x6b21, 0xb4ce}, /* '次' -> 27425 */
{0x6b22, 0xbbb6}, /* '欢' -> 27426 */
{0x6b23, 0xd0c0}, /* '欣' -> 27427 */
{0x6b24, 0xeca3}, /* '欤' -> 27428 */
{0x6b27, 0xc5b7}, /* '欧' -> 27431 */
{0x6b32, 0xd3fb}, /* '欲' -> 27442 */
{0x6b37, 0xeca4}, /* '欷' -> 27447 */
{0x6b39, 0xeca5}, /* '欹' -> 27449 */
{0x6b3a, 0xc6db}, /* '欺' -> 27450 */
{0x6b3e, 0xbfee}, /* '款' -> 27454 */
{0x6b43, 0xeca6}, /* '歃' -> 27459 */
{0x6b46, 0xeca7}, /* '歆' -> 27462 */
{0x6b47, 0xd0aa}, /* '歇' -> 27463 */
{0x6b49, 0xc7b8}, /* '歉' -> 27465 */
{0x6b4c, 0xb8e8}, /* '歌' -> 27468 */
{0x6b59, 0xeca8}, /* '歙' -> 27481 */
{0x6b62, 0xd6b9}, /* '止' -> 27490 */
{0x6b63, 0xd5fd}, /* '正' -> 27491 */
{0x6b64, 0xb4cb}, /* '此' -> 27492 */
{0x6b65, 0xb2bd}, /* '步' -> 27493 */
{0x6b66, 0xcee4}, /* '武' -> 27494 */
{0x6b67, 0xc6e7}, /* '歧' -> 27495 */
{0x6b6a, 0xcde1}, /* '歪' -> 27498 */
{0x6b79, 0xb4f5}, /* '歹' -> 27513 */
{0x6b7b, 0xcbc0}, /* '死' -> 27515 */
{0x6b7c, 0xbcdf}, /* '歼' -> 27516 */
{0x6b81, 0xe9e2}, /* '殁' -> 27521 */
{0x6b82, 0xe9e3}, /* '殂' -> 27522 */
{0x6b83, 0xd1ea}, /* '殃' -> 27523 */
{0x6b84, 0xe9e5}, /* '殄' -> 27524 */
{0x6b86, 0xb4f9}, /* '殆' -> 27526 */
{0x6b87, 0xe9e4}, /* '殇' -> 27527 */
{0x6b89, 0xd1b3}, /* '殉' -> 27529 */
{0x6b8a, 0xcae2}, /* '殊' -> 27530 */
{0x6b8b, 0xb2d0}, /* '残' -> 27531 */
{0x6b8d, 0xe9e8}, /* '殍' -> 27533 */
{0x6b92, 0xe9e6}, /* '殒' -> 27538 */
{0x6b93, 0xe9e7}, /* '殓' -> 27539 */
{0x6b96, 0xd6b3}, /* '殖' -> 27542 */
{0x6b9a, 0xe9e9}, /* '殚' -> 27546 */
{0x6b9b, 0xe9ea}, /* '殛' -> 27547 */
{0x6ba1, 0xe9eb}, /* '殡' -> 27553 */
{0x6baa, 0xe9ec}, /* '殪' -> 27562 */
{0x6bb3, 0xecaf}, /* '殳' -> 27571 */
{0x6bb4, 0xc5b9}, /* '殴' -> 27572 */
{0x6bb5, 0xb6ce}, /* '段' -> 27573 */
{0x6bb7, 0xd2f3}, /* '殷' -> 27575 */
{0x6bbf, 0xb5ee}, /* '殿' -> 27583 */
{0x6bc1, 0xbbd9}, /* '毁' -> 27585 */
{0x6bc2, 0xecb1}, /* '毂' -> 27586 */
{0x6bc5, 0xd2e3}, /* '毅' -> 27589 */
{0x6bcb, 0xcee3}, /* '毋' -> 27595 */
{0x6bcd, 0xc4b8}, /* '母' -> 27597 */
{0x6bcf, 0xc3bf}, /* '每' -> 27599 */
{0x6bd2, 0xb6be}, /* '毒' -> 27602 */
{0x6bd3, 0xd8b9}, /* '毓' -> 27603 */
{0x6bd4, 0xb1c8}, /* '比' -> 27604 */
{0x6bd5, 0xb1cf}, /* '毕' -> 27605 */
{0x6bd6, 0xb1d1}, /* '毖' -> 27606 */
{0x6bd7, 0xc5fe}, /* '毗' -> 27607 */
{0x6bd9, 0xb1d0}, /* '毙' -> 27609 */
{0x6bdb, 0xc3ab}, /* '毛' -> 27611 */
{0x6be1, 0xd5b1}, /* '毡' -> 27617 */
{0x6bea, 0xeba4}, /* '毪' -> 27626 */
{0x6beb, 0xbac1}, /* '毫' -> 27627 */
{0x6bef, 0xccba}, /* '毯' -> 27631 */
{0x6bf3, 0xeba5}, /* '毳' -> 27635 */
{0x6bf5, 0xeba7}, /* '毵' -> 27637 */
{0x6bf9, 0xeba8}, /* '毹' -> 27641 */
{0x6bfd, 0xeba6}, /* '毽' -> 27645 */
{0x6c05, 0xeba9}, /* '氅' -> 27653 */
{0x6c06, 0xebab}, /* '氆' -> 27654 */
{0x6c07, 0xebaa}, /* '氇' -> 27655 */
{0x6c0d, 0xebac}, /* '氍' -> 27661 */
{0x6c0f, 0xcacf}, /* '氏' -> 27663 */
{0x6c10, 0xd8b5}, /* '氐' -> 27664 */
{0x6c11, 0xc3f1}, /* '民' -> 27665 */
{0x6c13, 0xc3a5}, /* '氓' -> 27667 */
{0x6c14, 0xc6f8}, /* '气' -> 27668 */
{0x6c15, 0xebad}, /* '氕' -> 27669 */
{0x6c16, 0xc4ca}, /* '氖' -> 27670 */
{0x6c18, 0xebae}, /* '氘' -> 27672 */
{0x6c19, 0xebaf}, /* '氙' -> 27673 */
{0x6c1a, 0xebb0}, /* '氚' -> 27674 */
{0x6c1b, 0xb7d5}, /* '氛' -> 27675 */
{0x6c1f, 0xb7fa}, /* '氟' -> 27679 */
{0x6c21, 0xebb1}, /* '氡' -> 27681 */
{0x6c22, 0xc7e2}, /* '氢' -> 27682 */
{0x6c24, 0xebb3}, /* '氤' -> 27684 */
{0x6c26, 0xbaa4}, /* '氦' -> 27686 */
{0x6c27, 0xd1f5}, /* '氧' -> 27687 */
{0x6c28, 0xb0b1}, /* '氨' -> 27688 */
{0x6c29, 0xebb2}, /* '氩' -> 27689 */
{0x6c2a, 0xebb4}, /* '氪' -> 27690 */
{0x6c2e, 0xb5aa}, /* '氮' -> 27694 */
{0x6c2f, 0xc2c8}, /* '氯' -> 27695 */
{0x6c30, 0xc7e8}, /* '氰' -> 27696 */
{0x6c32, 0xebb5}, /* '氲' -> 27698 */
{0x6c34, 0xcbae}, /* '水' -> 27700 */
{0x6c35, 0xe3df}, /* '氵' -> 27701 */
{0x6c38, 0xd3c0}, /* '永' -> 27704 */
{0x6c3d, 0xd9db}, /* '氽' -> 27709 */
{0x6c40, 0xcda1}, /* '汀' -> 27712 */
{0x6c41, 0xd6ad}, /* '汁' -> 27713 */
{0x6c42, 0xc7f3}, /* '求' -> 27714 */
{0x6c46, 0xd9e0}, /* '汆' -> 27718 */
{0x6c47, 0xbbe3}, /* '汇' -> 27719 */
{0x6c49, 0xbaba}, /* '汉' -> 27721 */
{0x6c4a, 0xe3e2}, /* '汊' -> 27722 */
{0x6c50, 0xcfab}, /* '汐' -> 27728 */
{0x6c54, 0xe3e0}, /* '汔' -> 27732 */
{0x6c55, 0xc9c7}, /* '汕' -> 27733 */
{0x6c57, 0xbab9}, /* '汗' -> 27735 */
{0x6c5b, 0xd1b4}, /* '汛' -> 27739 */
{0x6c5c, 0xe3e1}, /* '汜' -> 27740 */
{0x6c5d, 0xc8ea}, /* '汝' -> 27741 */
{0x6c5e, 0xb9af}, /* '汞' -> 27742 */
{0x6c5f, 0xbdad}, /* '江' -> 27743 */
{0x6c60, 0xb3d8}, /* '池' -> 27744 */
{0x6c61, 0xcedb}, /* '污' -> 27745 */
{0x6c64, 0xccc0}, /* '汤' -> 27748 */
{0x6c68, 0xe3e8}, /* '汨' -> 27752 */
{0x6c69, 0xe3e9}, /* '汩' -> 27753 */
{0x6c6a, 0xcdf4}, /* '汪' -> 27754 */
{0x6c70, 0xccad}, /* '汰' -> 27760 */
{0x6c72, 0xbcb3}, /* '汲' -> 27762 */
{0x6c74, 0xe3ea}, /* '汴' -> 27764 */
{0x6c76, 0xe3eb}, /* '汶' -> 27766 */
{0x6c79, 0xd0da}, /* '汹' -> 27769 */
{0x6c7d, 0xc6fb}, /* '汽' -> 27773 */
{0x6c7e, 0xb7da}, /* '汾' -> 27774 */
{0x6c81, 0xc7df}, /* '沁' -> 27777 */
{0x6c82, 0xd2ca}, /* '沂' -> 27778 */
{0x6c83, 0xced6}, /* '沃' -> 27779 */
{0x6c85, 0xe3e4}, /* '沅' -> 27781 */
{0x6c86, 0xe3ec}, /* '沆' -> 27782 */
{0x6c88, 0xc9f2}, /* '沈' -> 27784 */
{0x6c89, 0xb3c1}, /* '沉' -> 27785 */
{0x6c8c, 0xe3e7}, /* '沌' -> 27788 */
{0x6c8f, 0xc6e3}, /* '沏' -> 27791 */
{0x6c90, 0xe3e5}, /* '沐' -> 27792 */
{0x6c93, 0xedb3}, /* '沓' -> 27795 */
{0x6c94, 0xe3e6}, /* '沔' -> 27796 */
{0x6c99, 0xc9b3}, /* '沙' -> 27801 */
{0x6c9b, 0xc5e6}, /* '沛' -> 27803 */
{0x6c9f, 0xb9b5}, /* '沟' -> 27807 */
{0x6ca1, 0xc3bb}, /* '没' -> 27809 */
{0x6ca3, 0xe3e3}, /* '沣' -> 27811 */
{0x6ca4, 0xc5bd}, /* '沤' -> 27812 */
{0x6ca5, 0xc1a4}, /* '沥' -> 27813 */
{0x6ca6, 0xc2d9}, /* '沦' -> 27814 */
{0x6ca7, 0xb2d7}, /* '沧' -> 27815 */
{0x6ca9, 0xe3ed}, /* '沩' -> 27817 */
{0x6caa, 0xbba6}, /* '沪' -> 27818 */
{0x6cab, 0xc4ad}, /* '沫' -> 27819 */
{0x6cad, 0xe3f0}, /* '沭' -> 27821 */
{0x6cae, 0xbeda}, /* '沮' -> 27822 */
{0x6cb1, 0xe3fb}, /* '沱' -> 27825 */
{0x6cb2, 0xe3f5}, /* '沲' -> 27826 */
{0x6cb3, 0xbad3}, /* '河' -> 27827 */
{0x6cb8, 0xb7d0}, /* '沸' -> 27832 */
{0x6cb9, 0xd3cd}, /* '油' -> 27833 */
{0x6cbb, 0xd6ce}, /* '治' -> 27835 */
{0x6cbc, 0xd5d3}, /* '沼' -> 27836 */
{0x6cbd, 0xb9c1}, /* '沽' -> 27837 */
{0x6cbe, 0xd5b4}, /* '沾' -> 27838 */
{0x6cbf, 0xd1d8}, /* '沿' -> 27839 */
{0x6cc4, 0xd0b9}, /* '泄' -> 27844 */
{0x6cc5, 0xc7f6}, /* '泅' -> 27845 */
{0x6cc9, 0xc8aa}, /* '泉' -> 27849 */
{0x6cca, 0xb2b4}, /* '泊' -> 27850 */
{0x6ccc, 0xc3da}, /* '泌' -> 27852 */
{0x6cd0, 0xe3ee}, /* '泐' -> 27856 */
{0x6cd3, 0xe3fc}, /* '泓' -> 27859 */
{0x6cd4, 0xe3ef}, /* '泔' -> 27860 */
{0x6cd5, 0xb7a8}, /* '法' -> 27861 */
{0x6cd6, 0xe3f7}, /* '泖' -> 27862 */
{0x6cd7, 0xe3f4}, /* '泗' -> 27863 */
{0x6cdb, 0xb7ba}, /* '泛' -> 27867 */
{0x6cde, 0xc5a2}, /* '泞' -> 27870 */
{0x6ce0, 0xe3f6}, /* '泠' -> 27872 */
{0x6ce1, 0xc5dd}, /* '泡' -> 27873 */
{0x6ce2, 0xb2a8}, /* '波' -> 27874 */
{0x6ce3, 0xc6fc}, /* '泣' -> 27875 */
{0x6ce5, 0xc4e0}, /* '泥' -> 27877 */
{0x6ce8, 0xd7a2}, /* '注' -> 27880 */
{0x6cea, 0xc0e1}, /* '泪' -> 27882 */
{0x6ceb, 0xe3f9}, /* '泫' -> 27883 */
{0x6cee, 0xe3fa}, /* '泮' -> 27886 */
{0x6cef, 0xe3fd}, /* '泯' -> 27887 */
{0x6cf0, 0xcca9}, /* '泰' -> 27888 */
{0x6cf1, 0xe3f3}, /* '泱' -> 27889 */
{0x6cf3, 0xd3be}, /* '泳' -> 27891 */
{0x6cf5, 0xb1c3}, /* '泵' -> 27893 */
{0x6cf6, 0xedb4}, /* '泶' -> 27894 */
{0x6cf7, 0xe3f1}, /* '泷' -> 27895 */
{0x6cf8, 0xe3f2}, /* '泸' -> 27896 */
{0x6cfa, 0xe3f8}, /* '泺' -> 27898 */
{0x6cfb, 0xd0ba}, /* '泻' -> 27899 */
{0x6cfc, 0xc6c3}, /* '泼' -> 27900 */
{0x6cfd, 0xd4f3}, /* '泽' -> 27901 */
{0x6cfe, 0xe3fe}, /* '泾' -> 27902 */
{0x6d01, 0xbde0}, /* '洁' -> 27905 */
{0x6d04, 0xe4a7}, /* '洄' -> 27908 */
{0x6d07, 0xe4a6}, /* '洇' -> 27911 */
{0x6d0b, 0xd1f3}, /* '洋' -> 27915 */
{0x6d0c, 0xe4a3}, /* '洌' -> 27916 */
{0x6d0e, 0xe4a9}, /* '洎' -> 27918 */
{0x6d12, 0xc8f7}, /* '洒' -> 27922 */
{0x6d17, 0xcfb4}, /* '洗' -> 27927 */
{0x6d19, 0xe4a8}, /* '洙' -> 27929 */
{0x6d1a, 0xe4ae}, /* '洚' -> 27930 */
{0x6d1b, 0xc2e5}, /* '洛' -> 27931 */
{0x6d1e, 0xb6b4}, /* '洞' -> 27934 */
{0x6d25, 0xbdf2}, /* '津' -> 27941 */
{0x6d27, 0xe4a2}, /* '洧' -> 27943 */
{0x6d2a, 0xbae9}, /* '洪' -> 27946 */
{0x6d2b, 0xe4aa}, /* '洫' -> 27947 */
{0x6d2e, 0xe4ac}, /* '洮' -> 27950 */
{0x6d31, 0xb6fd}, /* '洱' -> 27953 */
{0x6d32, 0xd6de}, /* '洲' -> 27954 */
{0x6d33, 0xe4b2}, /* '洳' -> 27955 */
{0x6d35, 0xe4ad}, /* '洵' -> 27957 */
{0x6d39, 0xe4a1}, /* '洹' -> 27961 */
{0x6d3b, 0xbbee}, /* '活' -> 27963 */
{0x6d3c, 0xcddd}, /* '洼' -> 27964 */
{0x6d3d, 0xc7a2}, /* '洽' -> 27965 */
{0x6d3e, 0xc5c9}, /* '派' -> 27966 */
{0x6d41, 0xc1f7}, /* '流' -> 27969 */
{0x6d43, 0xe4a4}, /* '浃' -> 27971 */
{0x6d45, 0xc7b3}, /* '浅' -> 27973 */
{0x6d46, 0xbdac}, /* '浆' -> 27974 */
{0x6d47, 0xbdbd}, /* '浇' -> 27975 */
{0x6d48, 0xe4a5}, /* '浈' -> 27976 */
{0x6d4a, 0xd7c7}, /* '浊' -> 27978 */
{0x6d4b, 0xb2e2}, /* '测' -> 27979 */
{0x6d4d, 0xe4ab}, /* '浍' -> 27981 */
{0x6d4e, 0xbcc3}, /* '济' -> 27982 */
{0x6d4f, 0xe4af}, /* '浏' -> 27983 */
{0x6d51, 0xbbeb}, /* '浑' -> 27985 */
{0x6d52, 0xe4b0}, /* '浒' -> 27986 */
{0x6d53, 0xc5a8}, /* '浓' -> 27987 */
{0x6d54, 0xe4b1}, /* '浔' -> 27988 */
{0x6d59, 0xd5e3}, /* '浙' -> 27993 */
{0x6d5a, 0xbfa3}, /* '浚' -> 27994 */
{0x6d5c, 0xe4ba}, /* '浜' -> 27996 */
{0x6d5e, 0xe4b7}, /* '浞' -> 27998 */
{0x6d60, 0xe4bb}, /* '浠' -> 28000 */
{0x6d63, 0xe4bd}, /* '浣' -> 28003 */
{0x6d66, 0xc6d6}, /* '浦' -> 28006 */
{0x6d69, 0xbac6}, /* '浩' -> 28009 */
{0x6d6a, 0xc0cb}, /* '浪' -> 28010 */
{0x6d6e, 0xb8a1}, /* '浮' -> 28014 */
{0x6d6f, 0xe4b4}, /* '浯' -> 28015 */
{0x6d74, 0xd4a1}, /* '浴' -> 28020 */
{0x6d77, 0xbaa3}, /* '海' -> 28023 */
{0x6d78, 0xbdfe}, /* '浸' -> 28024 */
{0x6d7c, 0xe4bc}, /* '浼' -> 28028 */
{0x6d82, 0xcdbf}, /* '涂' -> 28034 */
{0x6d85, 0xc4f9}, /* '涅' -> 28037 */
{0x6d88, 0xcffb}, /* '消' -> 28040 */
{0x6d89, 0xc9e6}, /* '涉' -> 28041 */
{0x6d8c, 0xd3bf}, /* '涌' -> 28044 */
{0x6d8e, 0xcfd1}, /* '涎' -> 28046 */
{0x6d91, 0xe4b3}, /* '涑' -> 28049 */
{0x6d93, 0xe4b8}, /* '涓' -> 28051 */
{0x6d94, 0xe4b9}, /* '涔' -> 28052 */
{0x6d95, 0xcce9}, /* '涕' -> 28053 */
{0x6d9b, 0xccce}, /* '涛' -> 28059 */
{0x6d9d, 0xc0d4}, /* '涝' -> 28061 */
{0x6d9e, 0xe4b5}, /* '涞' -> 28062 */
{0x6d9f, 0xc1b0}, /* '涟' -> 28063 */
{0x6da0, 0xe4b6}, /* '涠' -> 28064 */
{0x6da1, 0xced0}, /* '涡' -> 28065 */
{0x6da3, 0xbbc1}, /* '涣' -> 28067 */
{0x6da4, 0xb5d3}, /* '涤' -> 28068 */
{0x6da6, 0xc8f3}, /* '润' -> 28070 */
{0x6da7, 0xbda7}, /* '涧' -> 28071 */
{0x6da8, 0xd5c7}, /* '涨' -> 28072 */
{0x6da9, 0xc9ac}, /* '涩' -> 28073 */
{0x6daa, 0xb8a2}, /* '涪' -> 28074 */
{0x6dab, 0xe4ca}, /* '涫' -> 28075 */
{0x6dae, 0xe4cc}, /* '涮' -> 28078 */
{0x6daf, 0xd1c4}, /* '涯' -> 28079 */
{0x6db2, 0xd2ba}, /* '液' -> 28082 */
{0x6db5, 0xbaad}, /* '涵' -> 28085 */
{0x6db8, 0xbad4}, /* '涸' -> 28088 */
{0x6dbf, 0xe4c3}, /* '涿' -> 28095 */
{0x6dc0, 0xb5ed}, /* '淀' -> 28096 */
{0x6dc4, 0xd7cd}, /* '淄' -> 28100 */
{0x6dc5, 0xe4c0}, /* '淅' -> 28101 */
{0x6dc6, 0xcffd}, /* '淆' -> 28102 */
{0x6dc7, 0xe4bf}, /* '淇' -> 28103 */
{0x6dcb, 0xc1dc}, /* '淋' -> 28107 */
{0x6dcc, 0xccca}, /* '淌' -> 28108 */
{0x6dd1, 0xcae7}, /* '淑' -> 28113 */
{0x6dd6, 0xc4d7}, /* '淖' -> 28118 */
{0x6dd8, 0xccd4}, /* '淘' -> 28120 */
{0x6dd9, 0xe4c8}, /* '淙' -> 28121 */
{0x6ddd, 0xe4c7}, /* '淝' -> 28125 */
{0x6dde, 0xe4c1}, /* '淞' -> 28126 */
{0x6de0, 0xe4c4}, /* '淠' -> 28128 */
{0x6de1, 0xb5ad}, /* '淡' -> 28129 */
{0x6de4, 0xd3d9}, /* '淤' -> 28132 */
{0x6de6, 0xe4c6}, /* '淦' -> 28134 */
{0x6deb, 0xd2f9}, /* '淫' -> 28139 */
{0x6dec, 0xb4e3}, /* '淬' -> 28140 */
{0x6dee, 0xbbb4}, /* '淮' -> 28142 */
{0x6df1, 0xc9ee}, /* '深' -> 28145 */
{0x6df3, 0xb4be}, /* '淳' -> 28147 */
{0x6df7, 0xbbec}, /* '混' -> 28151 */
{0x6df9, 0xd1cd}, /* '淹' -> 28153 */
{0x6dfb, 0xcced}, /* '添' -> 28155 */
{0x6dfc, 0xedb5}, /* '淼' -> 28156 */
{0x6e05, 0xc7e5}, /* '清' -> 28165 */
{0x6e0a, 0xd4a8}, /* '渊' -> 28170 */
{0x6e0c, 0xe4cb}, /* '渌' -> 28172 */
{0x6e0d, 0xd7d5}, /* '渍' -> 28173 */
{0x6e0e, 0xe4c2}, /* '渎' -> 28174 */
{0x6e10, 0xbda5}, /* '渐' -> 28176 */
{0x6e11, 0xe4c5}, /* '渑' -> 28177 */
{0x6e14, 0xd3e6}, /* '渔' -> 28180 */
{0x6e16, 0xe4c9}, /* '渖' -> 28182 */
{0x6e17, 0xc9f8}, /* '渗' -> 28183 */
{0x6e1a, 0xe4be}, /* '渚' -> 28186 */
{0x6e1d, 0xd3e5}, /* '渝' -> 28189 */
{0x6e20, 0xc7fe}, /* '渠' -> 28192 */
{0x6e21, 0xb6c9}, /* '渡' -> 28193 */
{0x6e23, 0xd4fc}, /* '渣' -> 28195 */
{0x6e24, 0xb2b3}, /* '渤' -> 28196 */
{0x6e25, 0xe4d7}, /* '渥' -> 28197 */
{0x6e29, 0xcec2}, /* '温' -> 28201 */
{0x6e2b, 0xe4cd}, /* '渫' -> 28203 */
{0x6e2d, 0xcebc}, /* '渭' -> 28205 */
{0x6e2f, 0xb8db}, /* '港' -> 28207 */
{0x6e32, 0xe4d6}, /* '渲' -> 28210 */
{0x6e34, 0xbfca}, /* '渴' -> 28212 */
{0x6e38, 0xd3ce}, /* '游' -> 28216 */
{0x6e3a, 0xc3ec}, /* '渺' -> 28218 */
{0x6e43, 0xc5c8}, /* '湃' -> 28227 */
{0x6e44, 0xe4d8}, /* '湄' -> 28228 */
{0x6e4d, 0xcdc4}, /* '湍' -> 28237 */
{0x6e4e, 0xe4cf}, /* '湎' -> 28238 */
{0x6e53, 0xe4d4}, /* '湓' -> 28243 */
{0x6e54, 0xe4d5}, /* '湔' -> 28244 */
{0x6e56, 0xbafe}, /* '湖' -> 28246 */
{0x6e58, 0xcfe6}, /* '湘' -> 28248 */
{0x6e5b, 0xd5bf}, /* '湛' -> 28251 */
{0x6e5f, 0xe4d2}, /* '湟' -> 28255 */
{0x6e6b, 0xe4d0}, /* '湫' -> 28267 */
{0x6e6e, 0xe4ce}, /* '湮' -> 28270 */
{0x6e7e, 0xcde5}, /* '湾' -> 28286 */
{0x6e7f, 0xcaaa}, /* '湿' -> 28287 */
{0x6e83, 0xc0a3}, /* '溃' -> 28291 */
{0x6e85, 0xbda6}, /* '溅' -> 28293 */
{0x6e86, 0xe4d3}, /* '溆' -> 28294 */
{0x6e89, 0xb8c8}, /* '溉' -> 28297 */
{0x6e8f, 0xe4e7}, /* '溏' -> 28303 */
{0x6e90, 0xd4b4}, /* '源' -> 28304 */
{0x6e98, 0xe4db}, /* '溘' -> 28312 */
{0x6e9c, 0xc1ef}, /* '溜' -> 28316 */
{0x6e9f, 0xe4e9}, /* '溟' -> 28319 */
{0x6ea2, 0xd2e7}, /* '溢' -> 28322 */
{0x6ea5, 0xe4df}, /* '溥' -> 28325 */
{0x6ea7, 0xe4e0}, /* '溧' -> 28327 */
{0x6eaa, 0xcfaa}, /* '溪' -> 28330 */
{0x6eaf, 0xcbdd}, /* '溯' -> 28335 */
{0x6eb1, 0xe4da}, /* '溱' -> 28337 */
{0x6eb2, 0xe4d1}, /* '溲' -> 28338 */
{0x6eb4, 0xe4e5}, /* '溴' -> 28340 */
{0x6eb6, 0xc8dc}, /* '溶' -> 28342 */
{0x6eb7, 0xe4e3}, /* '溷' -> 28343 */
{0x6eba, 0xc4e7}, /* '溺' -> 28346 */
{0x6ebb, 0xe4e2}, /* '溻' -> 28347 */
{0x6ebd, 0xe4e1}, /* '溽' -> 28349 */
{0x6ec1, 0xb3fc}, /* '滁' -> 28353 */
{0x6ec2, 0xe4e8}, /* '滂' -> 28354 */
{0x6ec7, 0xb5e1}, /* '滇' -> 28359 */
{0x6ecb, 0xd7cc}, /* '滋' -> 28363 */
{0x6ecf, 0xe4e6}, /* '滏' -> 28367 */
{0x6ed1, 0xbbac}, /* '滑' -> 28369 */
{0x6ed3, 0xd7d2}, /* '滓' -> 28371 */
{0x6ed4, 0xcccf}, /* '滔' -> 28372 */
{0x6ed5, 0xebf8}, /* '滕' -> 28373 */
{0x6ed7, 0xe4e4}, /* '滗' -> 28375 */
{0x6eda, 0xb9f6}, /* '滚' -> 28378 */
{0x6ede, 0xd6cd}, /* '滞' -> 28382 */
{0x6edf, 0xe4d9}, /* '滟' -> 28383 */
{0x6ee0, 0xe4dc}, /* '滠' -> 28384 */
{0x6ee1, 0xc2fa}, /* '满' -> 28385 */
{0x6ee2, 0xe4de}, /* '滢' -> 28386 */
{0x6ee4, 0xc2cb}, /* '滤' -> 28388 */
{0x6ee5, 0xc0c4}, /* '滥' -> 28389 */
{0x6ee6, 0xc2d0}, /* '滦' -> 28390 */
{0x6ee8, 0xb1f5}, /* '滨' -> 28392 */
{0x6ee9, 0xccb2}, /* '滩' -> 28393 */
{0x6ef4, 0xb5ce}, /* '滴' -> 28404 */
{0x6ef9, 0xe4ef}, /* '滹' -> 28409 */
{0x6f02, 0xc6af}, /* '漂' -> 28418 */
{0x6f06, 0xc6e1}, /* '漆' -> 28422 */
{0x6f09, 0xe4f5}, /* '漉' -> 28425 */
{0x6f0f, 0xc2a9}, /* '漏' -> 28431 */
{0x6f13, 0xc0ec}, /* '漓' -> 28435 */
{0x6f14, 0xd1dd}, /* '演' -> 28436 */
{0x6f15, 0xe4ee}, /* '漕' -> 28437 */
{0x6f20, 0xc4ae}, /* '漠' -> 28448 */
{0x6f24, 0xe4ed}, /* '漤' -> 28452 */
{0x6f29, 0xe4f6}, /* '漩' -> 28457 */
{0x6f2a, 0xe4f4}, /* '漪' -> 28458 */
{0x6f2b, 0xc2fe}, /* '漫' -> 28459 */
{0x6f2d, 0xe4dd}, /* '漭' -> 28461 */
{0x6f2f, 0xe4f0}, /* '漯' -> 28463 */
{0x6f31, 0xcafe}, /* '漱' -> 28465 */
{0x6f33, 0xd5c4}, /* '漳' -> 28467 */
{0x6f36, 0xe4f1}, /* '漶' -> 28470 */
{0x6f3e, 0xd1fa}, /* '漾' -> 28478 */
{0x6f46, 0xe4eb}, /* '潆' -> 28486 */
{0x6f47, 0xe4ec}, /* '潇' -> 28487 */
{0x6f4b, 0xe4f2}, /* '潋' -> 28491 */
{0x6f4d, 0xceab}, /* '潍' -> 28493 */
{0x6f58, 0xc5cb}, /* '潘' -> 28504 */
{0x6f5c, 0xc7b1}, /* '潜' -> 28508 */
{0x6f5e, 0xc2ba}, /* '潞' -> 28510 */
{0x6f62, 0xe4ea}, /* '潢' -> 28514 */
{0x6f66, 0xc1ca}, /* '潦' -> 28518 */
{0x6f6d, 0xccb6}, /* '潭' -> 28525 */
{0x6f6e, 0xb3b1}, /* '潮' -> 28526 */
{0x6f72, 0xe4fb}, /* '潲' -> 28530 */
{0x6f74, 0xe4f3}, /* '潴' -> 28532 */
{0x6f78, 0xe4fa}, /* '潸' -> 28536 */
{0x6f7a, 0xe4fd}, /* '潺' -> 28538 */
{0x6f7c, 0xe4fc}, /* '潼' -> 28540 */
{0x6f84, 0xb3ce}, /* '澄' -> 28548 */
{0x6f88, 0xb3ba}, /* '澈' -> 28552 */
{0x6f89, 0xe4f7}, /* '澉' -> 28553 */
{0x6f8c, 0xe4f9}, /* '澌' -> 28556 */
{0x6f8d, 0xe4f8}, /* '澍' -> 28557 */
{0x6f8e, 0xc5ec}, /* '澎' -> 28558 */
{0x6f9c, 0xc0bd}, /* '澜' -> 28572 */
{0x6fa1, 0xd4e8}, /* '澡' -> 28577 */
{0x6fa7, 0xe5a2}, /* '澧' -> 28583 */
{0x6fb3, 0xb0c4}, /* '澳' -> 28595 */
{0x6fb6, 0xe5a4}, /* '澶' -> 28598 */
{0x6fb9, 0xe5a3}, /* '澹' -> 28601 */
{0x6fc0, 0xbca4}, /* '激' -> 28608 */
{0x6fc2, 0xe5a5}, /* '濂' -> 28610 */
{0x6fc9, 0xe5a1}, /* '濉' -> 28617 */
{0x6fd1, 0xe4fe}, /* '濑' -> 28625 */
{0x6fd2, 0xb1f4}, /* '濒' -> 28626 */
{0x6fde, 0xe5a8}, /* '濞' -> 28638 */
{0x6fe0, 0xe5a9}, /* '濠' -> 28640 */
{0x6fe1, 0xe5a6}, /* '濡' -> 28641 */
{0x6fee, 0xe5a7}, /* '濮' -> 28654 */
{0x6fef, 0xe5aa}, /* '濯' -> 28655 */
{0x7011, 0xc6d9}, /* '瀑' -> 28689 */
{0x701a, 0xe5ab}, /* '瀚' -> 28698 */
{0x701b, 0xe5ad}, /* '瀛' -> 28699 */
{0x7023, 0xe5ac}, /* '瀣' -> 28707 */
{0x7035, 0xe5af}, /* '瀵' -> 28725 */
{0x7039, 0xe5ae}, /* '瀹' -> 28729 */
{0x704c, 0xb9e0}, /* '灌' -> 28748 */
{0x704f, 0xe5b0}, /* '灏' -> 28751 */
{0x705e, 0xe5b1}, /* '灞' -> 28766 */
{0x706b, 0xbbf0}, /* '火' -> 28779 */
{0x706c, 0xece1}, /* '灬' -> 28780 */
{0x706d, 0xc3f0}, /* '灭' -> 28781 */
{0x706f, 0xb5c6}, /* '灯' -> 28783 */
{0x7070, 0xbbd2}, /* '灰' -> 28784 */
{0x7075, 0xc1e9}, /* '灵' -> 28789 */
{0x7076, 0xd4ee}, /* '灶' -> 28790 */
{0x7078, 0xbec4}, /* '灸' -> 28792 */
{0x707c, 0xd7c6}, /* '灼' -> 28796 */
{0x707e, 0xd4d6}, /* '灾' -> 28798 */
{0x707f, 0xb2d3}, /* '灿' -> 28799 */
{0x7080, 0xecbe}, /* '炀' -> 28800 */
{0x7085, 0xeac1}, /* '炅' -> 28805 */
{0x7089, 0xc2af}, /* '炉' -> 28809 */
{0x708a, 0xb4b6}, /* '炊' -> 28810 */
{0x708e, 0xd1d7}, /* '炎' -> 28814 */
{0x7092, 0xb3b4}, /* '炒' -> 28818 */
{0x7094, 0xc8b2}, /* '炔' -> 28820 */
{0x7095, 0xbfbb}, /* '炕' -> 28821 */
{0x7096, 0xecc0}, /* '炖' -> 28822 */
{0x7099, 0xd6cb}, /* '炙' -> 28825 */
{0x709c, 0xecbf}, /* '炜' -> 28828 */
{0x709d, 0xecc1}, /* '炝' -> 28829 */
{0x70ab, 0xecc5}, /* '炫' -> 28843 */
{0x70ac, 0xbee6}, /* '炬' -> 28844 */
{0x70ad, 0xccbf}, /* '炭' -> 28845 */
{0x70ae, 0xc5da}, /* '炮' -> 28846 */
{0x70af, 0xbebc}, /* '炯' -> 28847 */
{0x70b1, 0xecc6}, /* '炱' -> 28849 */
{0x70b3, 0xb1fe}, /* '炳' -> 28851 */
{0x70b7, 0xecc4}, /* '炷' -> 28855 */
{0x70b8, 0xd5a8}, /* '炸' -> 28856 */
{0x70b9, 0xb5e3}, /* '点' -> 28857 */
{0x70bb, 0xecc2}, /* '炻' -> 28859 */
{0x70bc, 0xc1b6}, /* '炼' -> 28860 */
{0x70bd, 0xb3e3}, /* '炽' -> 28861 */
{0x70c0, 0xecc3}, /* '烀' -> 28864 */
{0x70c1, 0xcbb8}, /* '烁' -> 28865 */
{0x70c2, 0xc0c3}, /* '烂' -> 28866 */
{0x70c3, 0xccfe}, /* '烃' -> 28867 */
{0x70c8, 0xc1d2}, /* '烈' -> 28872 */
{0x70ca, 0xecc8}, /* '烊' -> 28874 */
{0x70d8, 0xbae6}, /* '烘' -> 28888 */
{0x70d9, 0xc0d3}, /* '烙' -> 28889 */
{0x70db, 0xd6f2}, /* '烛' -> 28891 */
{0x70df, 0xd1cc}, /* '烟' -> 28895 */
{0x70e4, 0xbfbe}, /* '烤' -> 28900 */
{0x70e6, 0xb7b3}, /* '烦' -> 28902 */
{0x70e7, 0xc9d5}, /* '烧' -> 28903 */
{0x70e8, 0xecc7}, /* '烨' -> 28904 */
{0x70e9, 0xbbe2}, /* '烩' -> 28905 */
{0x70eb, 0xcccc}, /* '烫' -> 28907 */
{0x70ec, 0xbdfd}, /* '烬' -> 28908 */
{0x70ed, 0xc8c8}, /* '热' -> 28909 */
{0x70ef, 0xcfa9}, /* '烯' -> 28911 */
{0x70f7, 0xcde9}, /* '烷' -> 28919 */
{0x70f9, 0xc5eb}, /* '烹' -> 28921 */
{0x70fd, 0xb7e9}, /* '烽' -> 28925 */
{0x7109, 0xd1c9}, /* '焉' -> 28937 */
{0x710a, 0xbab8}, /* '焊' -> 28938 */
{0x7110, 0xecc9}, /* '焐' -> 28944 */
{0x7113, 0xecca}, /* '焓' -> 28947 */
{0x7115, 0xbbc0}, /* '焕' -> 28949 */
{0x7116, 0xeccb}, /* '焖' -> 28950 */
{0x7118, 0xece2}, /* '焘' -> 28952 */
{0x7119, 0xb1ba}, /* '焙' -> 28953 */
{0x711a, 0xb7d9}, /* '焚' -> 28954 */
{0x7126, 0xbdb9}, /* '焦' -> 28966 */
{0x712f, 0xeccc}, /* '焯' -> 28975 */
{0x7130, 0xd1e6}, /* '焰' -> 28976 */
{0x7131, 0xeccd}, /* '焱' -> 28977 */
{0x7136, 0xc8bb}, /* '然' -> 28982 */
{0x7145, 0xecd1}, /* '煅' -> 28997 */
{0x714a, 0xecd3}, /* '煊' -> 29002 */
{0x714c, 0xbbcd}, /* '煌' -> 29004 */
{0x714e, 0xbce5}, /* '煎' -> 29006 */
{0x715c, 0xeccf}, /* '煜' -> 29020 */
{0x715e, 0xc9b7}, /* '煞' -> 29022 */
{0x7164, 0xc3ba}, /* '煤' -> 29028 */
{0x7166, 0xece3}, /* '煦' -> 29030 */
{0x7167, 0xd5d5}, /* '照' -> 29031 */
{0x7168, 0xecd0}, /* '煨' -> 29032 */
{0x716e, 0xd6f3}, /* '煮' -> 29038 */
{0x7172, 0xecd2}, /* '煲' -> 29042 */
{0x7173, 0xecce}, /* '煳' -> 29043 */
{0x7178, 0xecd4}, /* '煸' -> 29048 */
{0x717a, 0xecd5}, /* '煺' -> 29050 */
{0x717d, 0xc9bf}, /* '煽' -> 29053 */
{0x7184, 0xcfa8}, /* '熄' -> 29060 */
{0x718a, 0xd0dc}, /* '熊' -> 29066 */
{0x718f, 0xd1ac}, /* '熏' -> 29071 */
{0x7194, 0xc8db}, /* '熔' -> 29076 */
{0x7198, 0xecd6}, /* '熘' -> 29080 */
{0x7199, 0xcef5}, /* '熙' -> 29081 */
{0x719f, 0xcaec}, /* '熟' -> 29087 */
{0x71a0, 0xecda}, /* '熠' -> 29088 */
{0x71a8, 0xecd9}, /* '熨' -> 29096 */
{0x71ac, 0xb0be}, /* '熬' -> 29100 */
{0x71b3, 0xecd7}, /* '熳' -> 29107 */
{0x71b5, 0xecd8}, /* '熵' -> 29109 */
{0x71b9, 0xece4}, /* '熹' -> 29113 */
{0x71c3, 0xc8bc}, /* '燃' -> 29123 */
{0x71ce, 0xc1c7}, /* '燎' -> 29134 */
{0x71d4, 0xecdc}, /* '燔' -> 29140 */
{0x71d5, 0xd1e0}, /* '燕' -> 29141 */
{0x71e0, 0xecdb}, /* '燠' -> 29152 */
{0x71e5, 0xd4ef}, /* '燥' -> 29157 */
{0x71e7, 0xecdd}, /* '燧' -> 29159 */
{0x71ee, 0xdbc6}, /* '燮' -> 29166 */
{0x71f9, 0xecde}, /* '燹' -> 29177 */
{0x7206, 0xb1ac}, /* '爆' -> 29190 */
{0x721d, 0xecdf}, /* '爝' -> 29213 */
{0x7228, 0xece0}, /* '爨' -> 29224 */
{0x722a, 0xd7a6}, /* '爪' -> 29226 */
{0x722c, 0xc5c0}, /* '爬' -> 29228 */
{0x7230, 0xebbc}, /* '爰' -> 29232 */
{0x7231, 0xb0ae}, /* '爱' -> 29233 */
{0x7235, 0xbef4}, /* '爵' -> 29237 */
{0x7236, 0xb8b8}, /* '父' -> 29238 */
{0x7237, 0xd2af}, /* '爷' -> 29239 */
{0x7238, 0xb0d6}, /* '爸' -> 29240 */
{0x7239, 0xb5f9}, /* '爹' -> 29241 */
{0x723b, 0xd8b3}, /* '爻' -> 29243 */
{0x723d, 0xcbac}, /* '爽' -> 29245 */
{0x723f, 0xe3dd}, /* '爿' -> 29247 */
{0x7247, 0xc6ac}, /* '片' -> 29255 */
{0x7248, 0xb0e6}, /* '版' -> 29256 */
{0x724c, 0xc5c6}, /* '牌' -> 29260 */
{0x724d, 0xebb9}, /* '牍' -> 29261 */
{0x7252, 0xebba}, /* '牒' -> 29266 */
{0x7256, 0xebbb}, /* '牖' -> 29270 */
{0x7259, 0xd1c0}, /* '牙' -> 29273 */
{0x725b, 0xc5a3}, /* '牛' -> 29275 */
{0x725d, 0xeaf2}, /* '牝' -> 29277 */
{0x725f, 0xc4b2}, /* '牟' -> 29279 */
{0x7261, 0xc4b5}, /* '牡' -> 29281 */
{0x7262, 0xc0ce}, /* '牢' -> 29282 */
{0x7266, 0xeaf3}, /* '牦' -> 29286 */
{0x7267, 0xc4c1}, /* '牧' -> 29287 */
{0x7269, 0xceef}, /* '物' -> 29289 */
{0x726e, 0xeaf0}, /* '牮' -> 29294 */
{0x726f, 0xeaf4}, /* '牯' -> 29295 */
{0x7272, 0xc9fc}, /* '牲' -> 29298 */
{0x7275, 0xc7a3}, /* '牵' -> 29301 */
{0x7279, 0xccd8}, /* '特' -> 29305 */
{0x727a, 0xcefe}, /* '牺' -> 29306 */
{0x727e, 0xeaf5}, /* '牾' -> 29310 */
{0x727f, 0xeaf6}, /* '牿' -> 29311 */
{0x7280, 0xcfac}, /* '犀' -> 29312 */
{0x7281, 0xc0e7}, /* '犁' -> 29313 */
{0x7284, 0xeaf7}, /* '犄' -> 29316 */
{0x728a, 0xb6bf}, /* '犊' -> 29322 */
{0x728b, 0xeaf8}, /* '犋' -> 29323 */
{0x728d, 0xeaf9}, /* '犍' -> 29325 */
{0x728f, 0xeafa}, /* '犏' -> 29327 */
{0x7292, 0xeafb}, /* '犒' -> 29330 */
{0x729f, 0xeaf1}, /* '犟' -> 29343 */
{0x72ac, 0xc8ae}, /* '犬' -> 29356 */
{0x72ad, 0xe1eb}, /* '犭' -> 29357 */
{0x72af, 0xb7b8}, /* '犯' -> 29359 */
{0x72b0, 0xe1ec}, /* '犰' -> 29360 */
{0x72b4, 0xe1ed}, /* '犴' -> 29364 */
{0x72b6, 0xd7b4}, /* '状' -> 29366 */
{0x72b7, 0xe1ee}, /* '犷' -> 29367 */
{0x72b8, 0xe1ef}, /* '犸' -> 29368 */
{0x72b9, 0xd3cc}, /* '犹' -> 29369 */
{0x72c1, 0xe1f1}, /* '狁' -> 29377 */
{0x72c2, 0xbff1}, /* '狂' -> 29378 */
{0x72c3, 0xe1f0}, /* '狃' -> 29379 */
{0x72c4, 0xb5d2}, /* '狄' -> 29380 */
{0x72c8, 0xb1b7}, /* '狈' -> 29384 */
{0x72cd, 0xe1f3}, /* '狍' -> 29389 */
{0x72ce, 0xe1f2}, /* '狎' -> 29390 */
{0x72d0, 0xbafc}, /* '狐' -> 29392 */
{0x72d2, 0xe1f4}, /* '狒' -> 29394 */
{0x72d7, 0xb9b7}, /* '狗' -> 29399 */
{0x72d9, 0xbed1}, /* '狙' -> 29401 */
{0x72de, 0xc4fc}, /* '狞' -> 29406 */
{0x72e0, 0xbadd}, /* '狠' -> 29408 */
{0x72e1, 0xbdc6}, /* '狡' -> 29409 */
{0x72e8, 0xe1f5}, /* '狨' -> 29416 */
{0x72e9, 0xe1f7}, /* '狩' -> 29417 */
{0x72ec, 0xb6c0}, /* '独' -> 29420 */
{0x72ed, 0xcfc1}, /* '狭' -> 29421 */
{0x72ee, 0xcaa8}, /* '狮' -> 29422 */
{0x72ef, 0xe1f6}, /* '狯' -> 29423 */
{0x72f0, 0xd5f8}, /* '狰' -> 29424 */
{0x72f1, 0xd3fc}, /* '狱' -> 29425 */
{0x72f2, 0xe1f8}, /* '狲' -> 29426 */
{0x72f3, 0xe1fc}, /* '狳' -> 29427 */
{0x72f4, 0xe1f9}, /* '狴' -> 29428 */
{0x72f7, 0xe1fa}, /* '狷' -> 29431 */
{0x72f8, 0xc0ea}, /* '狸' -> 29432 */
{0x72fa, 0xe1fe}, /* '狺' -> 29434 */
{0x72fb, 0xe2a1}, /* '狻' -> 29435 */
{0x72fc, 0xc0c7}, /* '狼' -> 29436 */
{0x7301, 0xe1fb}, /* '猁' -> 29441 */
{0x7303, 0xe1fd}, /* '猃' -> 29443 */
{0x730a, 0xe2a5}, /* '猊' -> 29450 */
{0x730e, 0xc1d4}, /* '猎' -> 29454 */
{0x7313, 0xe2a3}, /* '猓' -> 29459 */
{0x7315, 0xe2a8}, /* '猕' -> 29461 */
{0x7316, 0xb2fe}, /* '猖' -> 29462 */
{0x7317, 0xe2a2}, /* '猗' -> 29463 */
{0x731b, 0xc3cd}, /* '猛' -> 29467 */
{0x731c, 0xb2c2}, /* '猜' -> 29468 */
{0x731d, 0xe2a7}, /* '猝' -> 29469 */
{0x731e, 0xe2a6}, /* '猞' -> 29470 */
{0x7321, 0xe2a4}, /* '猡' -> 29473 */
{0x7322, 0xe2a9}, /* '猢' -> 29474 */
{0x7325, 0xe2ab}, /* '猥' -> 29477 */
{0x7329, 0xd0c9}, /* '猩' -> 29481 */
{0x732a, 0xd6ed}, /* '猪' -> 29482 */
{0x732b, 0xc3a8}, /* '猫' -> 29483 */
{0x732c, 0xe2ac}, /* '猬' -> 29484 */
{0x732e, 0xcfd7}, /* '献' -> 29486 */
{0x7331, 0xe2ae}, /* '猱' -> 29489 */
{0x7334, 0xbaef}, /* '猴' -> 29492 */
{0x7337, 0xe9e0}, /* '猷' -> 29495 */
{0x7338, 0xe2ad}, /* '猸' -> 29496 */
{0x7339, 0xe2aa}, /* '猹' -> 29497 */
{0x733e, 0xbbab}, /* '猾' -> 29502 */
{0x733f, 0xd4b3}, /* '猿' -> 29503 */
{0x734d, 0xe2b0}, /* '獍' -> 29517 */
{0x7350, 0xe2af}, /* '獐' -> 29520 */
{0x7352, 0xe9e1}, /* '獒' -> 29522 */
{0x7357, 0xe2b1}, /* '獗' -> 29527 */
{0x7360, 0xe2b2}, /* '獠' -> 29536 */
{0x736c, 0xe2b3}, /* '獬' -> 29548 */
{0x736d, 0xcca1}, /* '獭' -> 29549 */
{0x736f, 0xe2b4}, /* '獯' -> 29551 */
{0x737e, 0xe2b5}, /* '獾' -> 29566 */
{0x7384, 0xd0fe}, /* '玄' -> 29572 */
{0x7387, 0xc2ca}, /* '率' -> 29575 */
{0x7389, 0xd3f1}, /* '玉' -> 29577 */
{0x738b, 0xcdf5}, /* '王' -> 29579 */
{0x738e, 0xe7e0}, /* '玎' -> 29582 */
{0x7391, 0xe7e1}, /* '玑' -> 29585 */
{0x7396, 0xbec1}, /* '玖' -> 29590 */
{0x739b, 0xc2ea}, /* '玛' -> 29595 */
{0x739f, 0xe7e4}, /* '玟' -> 29599 */
{0x73a2, 0xe7e3}, /* '玢' -> 29602 */
{0x73a9, 0xcde6}, /* '玩' -> 29609 */
{0x73ab, 0xc3b5}, /* '玫' -> 29611 */
{0x73ae, 0xe7e2}, /* '玮' -> 29614 */
{0x73af, 0xbbb7}, /* '环' -> 29615 */
{0x73b0, 0xcfd6}, /* '现' -> 29616 */
{0x73b2, 0xc1e1}, /* '玲' -> 29618 */
{0x73b3, 0xe7e9}, /* '玳' -> 29619 */
{0x73b7, 0xe7e8}, /* '玷' -> 29623 */
{0x73ba, 0xe7f4}, /* '玺' -> 29626 */
{0x73bb, 0xb2a3}, /* '玻' -> 29627 */
{0x73c0, 0xe7ea}, /* '珀' -> 29632 */
{0x73c2, 0xe7e6}, /* '珂' -> 29634 */
{0x73c8, 0xe7ec}, /* '珈' -> 29640 */
{0x73c9, 0xe7eb}, /* '珉' -> 29641 */
{0x73ca, 0xc9ba}, /* '珊' -> 29642 */
{0x73cd, 0xd5e4}, /* '珍' -> 29645 */
{0x73cf, 0xe7e5}, /* '珏' -> 29647 */
{0x73d0, 0xb7a9}, /* '珐' -> 29648 */
{0x73d1, 0xe7e7}, /* '珑' -> 29649 */
{0x73d9, 0xe7ee}, /* '珙' -> 29657 */
{0x73de, 0xe7f3}, /* '珞' -> 29662 */
{0x73e0, 0xd6e9}, /* '珠' -> 29664 */
{0x73e5, 0xe7ed}, /* '珥' -> 29669 */
{0x73e7, 0xe7f2}, /* '珧' -> 29671 */
{0x73e9, 0xe7f1}, /* '珩' -> 29673 */
{0x73ed, 0xb0e0}, /* '班' -> 29677 */
{0x73f2, 0xe7f5}, /* '珲' -> 29682 */
{0x7403, 0xc7f2}, /* '球' -> 29699 */
{0x7405, 0xc0c5}, /* '琅' -> 29701 */
{0x7406, 0xc0ed}, /* '理' -> 29702 */
{0x7409, 0xc1f0}, /* '琉' -> 29705 */
{0x740a, 0xe7f0}, /* '琊' -> 29706 */
{0x740f, 0xe7f6}, /* '琏' -> 29711 */
{0x7410, 0xcbf6}, /* '琐' -> 29712 */
{0x741a, 0xe8a2}, /* '琚' -> 29722 */
{0x741b, 0xe8a1}, /* '琛' -> 29723 */
{0x7422, 0xd7c1}, /* '琢' -> 29730 */
{0x7425, 0xe7fa}, /* '琥' -> 29733 */
{0x7426, 0xe7f9}, /* '琦' -> 29734 */
{0x7428, 0xe7fb}, /* '琨' -> 29736 */
{0x742a, 0xe7f7}, /* '琪' -> 29738 */
{0x742c, 0xe7fe}, /* '琬' -> 29740 */
{0x742e, 0xe7fd}, /* '琮' -> 29742 */
{0x7430, 0xe7fc}, /* '琰' -> 29744 */
{0x7433, 0xc1d5}, /* '琳' -> 29747 */
{0x7434, 0xc7d9}, /* '琴' -> 29748 */
{0x7435, 0xc5fd}, /* '琵' -> 29749 */
{0x7436, 0xc5c3}, /* '琶' -> 29750 */
{0x743c, 0xc7ed}, /* '琼' -> 29756 */
{0x7441, 0xe8a3}, /* '瑁' -> 29761 */
{0x7455, 0xe8a6}, /* '瑕' -> 29781 */
{0x7457, 0xe8a5}, /* '瑗' -> 29783 */
{0x7459, 0xe8a7}, /* '瑙' -> 29785 */
{0x745a, 0xbaf7}, /* '瑚' -> 29786 */
{0x745b, 0xe7f8}, /* '瑛' -> 29787 */
{0x745c, 0xe8a4}, /* '瑜' -> 29788 */
{0x745e, 0xc8f0}, /* '瑞' -> 29790 */
{0x745f, 0xc9aa}, /* '瑟' -> 29791 */
{0x746d, 0xe8a9}, /* '瑭' -> 29805 */
{0x7470, 0xb9e5}, /* '瑰' -> 29808 */
{0x7476, 0xd1fe}, /* '瑶' -> 29814 */
{0x7477, 0xe8a8}, /* '瑷' -> 29815 */
{0x747e, 0xe8aa}, /* '瑾' -> 29822 */
{0x7480, 0xe8ad}, /* '璀' -> 29824 */
{0x7481, 0xe8ae}, /* '璁' -> 29825 */
{0x7483, 0xc1a7}, /* '璃' -> 29827 */
{0x7487, 0xe8af}, /* '璇' -> 29831 */
{0x748b, 0xe8b0}, /* '璋' -> 29835 */
{0x748e, 0xe8ac}, /* '璎' -> 29838 */
{0x7490, 0xe8b4}, /* '璐' -> 29840 */
{0x749c, 0xe8ab}, /* '璜' -> 29852 */
{0x749e, 0xe8b1}, /* '璞' -> 29854 */
{0x74a7, 0xe8b5}, /* '璧' -> 29863 */
{0x74a8, 0xe8b2}, /* '璨' -> 29864 */
{0x74a9, 0xe8b3}, /* '璩' -> 29865 */
{0x74ba, 0xe8b7}, /* '璺' -> 29882 */
{0x74d2, 0xe8b6}, /* '瓒' -> 29906 */
{0x74dc, 0xb9cf}, /* '瓜' -> 29916 */
{0x74de, 0xf0ac}, /* '瓞' -> 29918 */
{0x74e0, 0xf0ad}, /* '瓠' -> 29920 */
{0x74e2, 0xc6b0}, /* '瓢' -> 29922 */
{0x74e3, 0xb0ea}, /* '瓣' -> 29923 */
{0x74e4, 0xc8bf}, /* '瓤' -> 29924 */
{0x74e6, 0xcddf}, /* '瓦' -> 29926 */
{0x74ee, 0xcecd}, /* '瓮' -> 29934 */
{0x74ef, 0xeab1}, /* '瓯' -> 29935 */
{0x74f4, 0xeab2}, /* '瓴' -> 29940 */
{0x74f6, 0xc6bf}, /* '瓶' -> 29942 */
{0x74f7, 0xb4c9}, /* '瓷' -> 29943 */
{0x74ff, 0xeab3}, /* '瓿' -> 29951 */
{0x7504, 0xd5e7}, /* '甄' -> 29956 */
{0x750d, 0xddf9}, /* '甍' -> 29965 */
{0x750f, 0xeab4}, /* '甏' -> 29967 */
{0x7511, 0xeab5}, /* '甑' -> 29969 */
{0x7513, 0xeab6}, /* '甓' -> 29971 */
{0x7518, 0xb8ca}, /* '甘' -> 29976 */
{0x7519, 0xdfb0}, /* '甙' -> 29977 */
{0x751a, 0xc9f5}, /* '甚' -> 29978 */
{0x751c, 0xccf0}, /* '甜' -> 29980 */
{0x751f, 0xc9fa}, /* '生' -> 29983 */
{0x7525, 0xc9fb}, /* '甥' -> 29989 */
{0x7528, 0xd3c3}, /* '用' -> 29992 */
{0x7529, 0xcba6}, /* '甩' -> 29993 */
{0x752b, 0xb8a6}, /* '甫' -> 29995 */
{0x752c, 0xf0ae}, /* '甬' -> 29996 */
{0x752d, 0xb1c2}, /* '甭' -> 29997 */
{0x752f, 0xe5b8}, /* '甯' -> 29999 */
{0x7530, 0xccef}, /* '田' -> 30000 */
{0x7531, 0xd3c9}, /* '由' -> 30001 */
{0x7532, 0xbcd7}, /* '甲' -> 30002 */
{0x7533, 0xc9ea}, /* '申' -> 30003 */
{0x7535, 0xb5e7}, /* '电' -> 30005 */
{0x7537, 0xc4d0}, /* '男' -> 30007 */
{0x7538, 0xb5e9}, /* '甸' -> 30008 */
{0x753a, 0xeeae}, /* '町' -> 30010 */
{0x753b, 0xbbad}, /* '画' -> 30011 */
{0x753e, 0xe7de}, /* '甾' -> 30014 */
{0x7540, 0xeeaf}, /* '畀' -> 30016 */
{0x7545, 0xb3a9}, /* '畅' -> 30021 */
{0x7548, 0xeeb2}, /* '畈' -> 30024 */
{0x754b, 0xeeb1}, /* '畋' -> 30027 */
{0x754c, 0xbde7}, /* '界' -> 30028 */
{0x754e, 0xeeb0}, /* '畎' -> 30030 */
{0x754f, 0xceb7}, /* '畏' -> 30031 */
{0x7554, 0xc5cf}, /* '畔' -> 30036 */
{0x7559, 0xc1f4}, /* '留' -> 30041 */
{0x755a, 0xdbce}, /* '畚' -> 30042 */
{0x755b, 0xeeb3}, /* '畛' -> 30043 */
{0x755c, 0xd0f3}, /* '畜' -> 30044 */
{0x7565, 0xc2d4}, /* '略' -> 30053 */
{0x7566, 0xc6e8}, /* '畦' -> 30054 */
{0x756a, 0xb7ac}, /* '番' -> 30058 */
{0x7572, 0xeeb4}, /* '畲' -> 30066 */
{0x7574, 0xb3eb}, /* '畴' -> 30068 */
{0x7578, 0xbbfb}, /* '畸' -> 30072 */
{0x7579, 0xeeb5}, /* '畹' -> 30073 */
{0x757f, 0xe7dc}, /* '畿' -> 30079 */
{0x7583, 0xeeb6}, /* '疃' -> 30083 */
{0x7586, 0xbdae}, /* '疆' -> 30086 */
{0x758b, 0xf1e2}, /* '疋' -> 30091 */
{0x758f, 0xcae8}, /* '疏' -> 30095 */
{0x7591, 0xd2c9}, /* '疑' -> 30097 */
{0x7592, 0xf0da}, /* '疒' -> 30098 */
{0x7594, 0xf0db}, /* '疔' -> 30100 */
{0x7596, 0xf0dc}, /* '疖' -> 30102 */
{0x7597, 0xc1c6}, /* '疗' -> 30103 */
{0x7599, 0xb8ed}, /* '疙' -> 30105 */
{0x759a, 0xbece}, /* '疚' -> 30106 */
{0x759d, 0xf0de}, /* '疝' -> 30109 */
{0x759f, 0xc5b1}, /* '疟' -> 30111 */
{0x75a0, 0xf0dd}, /* '疠' -> 30112 */
{0x75a1, 0xd1f1}, /* '疡' -> 30113 */
{0x75a3, 0xf0e0}, /* '疣' -> 30115 */
{0x75a4, 0xb0cc}, /* '疤' -> 30116 */
{0x75a5, 0xbdea}, /* '疥' -> 30117 */
{0x75ab, 0xd2df}, /* '疫' -> 30123 */
{0x75ac, 0xf0df}, /* '疬' -> 30124 */
{0x75ae, 0xb4af}, /* '疮' -> 30126 */
{0x75af, 0xb7e8}, /* '疯' -> 30127 */
{0x75b0, 0xf0e6}, /* '疰' -> 30128 */
{0x75b1, 0xf0e5}, /* '疱' -> 30129 */
{0x75b2, 0xc6a3}, /* '疲' -> 30130 */
{0x75b3, 0xf0e1}, /* '疳' -> 30131 */
{0x75b4, 0xf0e2}, /* '疴' -> 30132 */
{0x75b5, 0xb4c3}, /* '疵' -> 30133 */
{0x75b8, 0xf0e3}, /* '疸' -> 30136 */
{0x75b9, 0xd5ee}, /* '疹' -> 30137 */
{0x75bc, 0xccdb}, /* '疼' -> 30140 */
{0x75bd, 0xbed2}, /* '疽' -> 30141 */
{0x75be, 0xbcb2}, /* '疾' -> 30142 */
{0x75c2, 0xf0e8}, /* '痂' -> 30146 */
{0x75c3, 0xf0e7}, /* '痃' -> 30147 */
{0x75c4, 0xf0e4}, /* '痄' -> 30148 */
{0x75c5, 0xb2a1}, /* '病' -> 30149 */
{0x75c7, 0xd6a2}, /* '症' -> 30151 */
{0x75c8, 0xd3b8}, /* '痈' -> 30152 */
{0x75c9, 0xbeb7}, /* '痉' -> 30153 */
{0x75ca, 0xc8ac}, /* '痊' -> 30154 */
{0x75cd, 0xf0ea}, /* '痍' -> 30157 */
{0x75d2, 0xd1f7}, /* '痒' -> 30162 */
{0x75d4, 0xd6cc}, /* '痔' -> 30164 */
{0x75d5, 0xbadb}, /* '痕' -> 30165 */
{0x75d6, 0xf0e9}, /* '痖' -> 30166 */
{0x75d8, 0xb6bb}, /* '痘' -> 30168 */
{0x75db, 0xcdb4}, /* '痛' -> 30171 */
{0x75de, 0xc6a6}, /* '痞' -> 30174 */
{0x75e2, 0xc1a1}, /* '痢' -> 30178 */
{0x75e3, 0xf0eb}, /* '痣' -> 30179 */
{0x75e4, 0xf0ee}, /* '痤' -> 30180 */
{0x75e6, 0xf0ed}, /* '痦' -> 30182 */
{0x75e7, 0xf0f0}, /* '痧' -> 30183 */
{0x75e8, 0xf0ec}, /* '痨' -> 30184 */
{0x75ea, 0xbbbe}, /* '痪' -> 30186 */
{0x75eb, 0xf0ef}, /* '痫' -> 30187 */
{0x75f0, 0xccb5}, /* '痰' -> 30192 */
{0x75f1, 0xf0f2}, /* '痱' -> 30193 */
{0x75f4, 0xb3d5}, /* '痴' -> 30196 */
{0x75f9, 0xb1d4}, /* '痹' -> 30201 */
{0x75fc, 0xf0f3}, /* '痼' -> 30204 */
{0x75ff, 0xf0f4}, /* '痿' -> 30207 */
{0x7600, 0xf0f6}, /* '瘀' -> 30208 */
{0x7601, 0xb4e1}, /* '瘁' -> 30209 */
{0x7603, 0xf0f1}, /* '瘃' -> 30211 */
{0x7605, 0xf0f7}, /* '瘅' -> 30213 */
{0x760a, 0xf0fa}, /* '瘊' -> 30218 */
{0x760c, 0xf0f8}, /* '瘌' -> 30220 */
{0x7610, 0xf0f5}, /* '瘐' -> 30224 */
{0x7615, 0xf0fd}, /* '瘕' -> 30229 */
{0x7617, 0xf0f9}, /* '瘗' -> 30231 */
{0x7618, 0xf0fc}, /* '瘘' -> 30232 */
{0x7619, 0xf0fe}, /* '瘙' -> 30233 */
{0x761b, 0xf1a1}, /* '瘛' -> 30235 */
{0x761f, 0xcec1}, /* '瘟' -> 30239 */
{0x7620, 0xf1a4}, /* '瘠' -> 30240 */
{0x7622, 0xf1a3}, /* '瘢' -> 30242 */
{0x7624, 0xc1f6}, /* '瘤' -> 30244 */
{0x7625, 0xf0fb}, /* '瘥' -> 30245 */
{0x7626, 0xcadd}, /* '瘦' -> 30246 */
{0x7629, 0xb4f1}, /* '瘩' -> 30249 */
{0x762a, 0xb1f1}, /* '瘪' -> 30250 */
{0x762b, 0xccb1}, /* '瘫' -> 30251 */
{0x762d, 0xf1a6}, /* '瘭' -> 30253 */
{0x7630, 0xf1a7}, /* '瘰' -> 30256 */
{0x7633, 0xf1ac}, /* '瘳' -> 30259 */
{0x7634, 0xd5ce}, /* '瘴' -> 30260 */
{0x7635, 0xf1a9}, /* '瘵' -> 30261 */
{0x7638, 0xc8b3}, /* '瘸' -> 30264 */
{0x763c, 0xf1a2}, /* '瘼' -> 30268 */
{0x763e, 0xf1ab}, /* '瘾' -> 30270 */
{0x763f, 0xf1a8}, /* '瘿' -> 30271 */
{0x7640, 0xf1a5}, /* '癀' -> 30272 */
{0x7643, 0xf1aa}, /* '癃' -> 30275 */
{0x764c, 0xb0a9}, /* '癌' -> 30284 */
{0x764d, 0xf1ad}, /* '癍' -> 30285 */
{0x7654, 0xf1af}, /* '癔' -> 30292 */
{0x7656, 0xf1b1}, /* '癖' -> 30294 */
{0x765c, 0xf1b0}, /* '癜' -> 30300 */
{0x765e, 0xf1ae}, /* '癞' -> 30302 */
{0x7663, 0xd1a2}, /* '癣' -> 30307 */
{0x766b, 0xf1b2}, /* '癫' -> 30315 */
{0x766f, 0xf1b3}, /* '癯' -> 30319 */
{0x7678, 0xb9ef}, /* '癸' -> 30328 */
{0x767b, 0xb5c7}, /* '登' -> 30331 */
{0x767d, 0xb0d7}, /* '白' -> 30333 */
{0x767e, 0xb0d9}, /* '百' -> 30334 */
{0x7682, 0xd4ed}, /* '皂' -> 30338 */
{0x7684, 0xb5c4}, /* '的' -> 30340 */
{0x7686, 0xbdd4}, /* '皆' -> 30342 */
{0x7687, 0xbbca}, /* '皇' -> 30343 */
{0x7688, 0xf0a7}, /* '皈' -> 30344 */
{0x768b, 0xb8de}, /* '皋' -> 30347 */
{0x768e, 0xf0a8}, /* '皎' -> 30350 */
{0x7691, 0xb0a8}, /* '皑' -> 30353 */
{0x7693, 0xf0a9}, /* '皓' -> 30355 */
{0x7696, 0xcdee}, /* '皖' -> 30358 */
{0x7699, 0xf0aa}, /* '皙' -> 30361 */
{0x76a4, 0xf0ab}, /* '皤' -> 30372 */
{0x76ae, 0xc6a4}, /* '皮' -> 30382 */
{0x76b1, 0xd6e5}, /* '皱' -> 30385 */
{0x76b2, 0xf1e4}, /* '皲' -> 30386 */
{0x76b4, 0xf1e5}, /* '皴' -> 30388 */
{0x76bf, 0xc3f3}, /* '皿' -> 30399 */
{0x76c2, 0xd3db}, /* '盂' -> 30402 */
{0x76c5, 0xd6d1}, /* '盅' -> 30405 */
{0x76c6, 0xc5e8}, /* '盆' -> 30406 */
{0x76c8, 0xd3af}, /* '盈' -> 30408 */
{0x76ca, 0xd2e6}, /* '益' -> 30410 */
{0x76cd, 0xeec1}, /* '盍' -> 30413 */
{0x76ce, 0xb0bb}, /* '盎' -> 30414 */
{0x76cf, 0xd5b5}, /* '盏' -> 30415 */
{0x76d0, 0xd1ce}, /* '盐' -> 30416 */
{0x76d1, 0xbce0}, /* '监' -> 30417 */
{0x76d2, 0xbad0}, /* '盒' -> 30418 */
{0x76d4, 0xbff8}, /* '盔' -> 30420 */
{0x76d6, 0xb8c7}, /* '盖' -> 30422 */
{0x76d7, 0xb5c1}, /* '盗' -> 30423 */
{0x76d8, 0xc5cc}, /* '盘' -> 30424 */
{0x76db, 0xcaa2}, /* '盛' -> 30427 */
{0x76df, 0xc3cb}, /* '盟' -> 30431 */
{0x76e5, 0xeec2}, /* '盥' -> 30437 */
{0x76ee, 0xc4bf}, /* '目' -> 30446 */
{0x76ef, 0xb6a2}, /* '盯' -> 30447 */
{0x76f1, 0xedec}, /* '盱' -> 30449 */
{0x76f2, 0xc3a4}, /* '盲' -> 30450 */
{0x76f4, 0xd6b1}, /* '直' -> 30452 */
{0x76f8, 0xcfe0}, /* '相' -> 30456 */
{0x76f9, 0xedef}, /* '盹' -> 30457 */
{0x76fc, 0xc5ce}, /* '盼' -> 30460 */
{0x76fe, 0xb6dc}, /* '盾' -> 30462 */
{0x7701, 0xcaa1}, /* '省' -> 30465 */
{0x7704, 0xeded}, /* '眄' -> 30468 */
{0x7707, 0xedf0}, /* '眇' -> 30471 */
{0x7708, 0xedf1}, /* '眈' -> 30472 */
{0x7709, 0xc3bc}, /* '眉' -> 30473 */
{0x770b, 0xbfb4}, /* '看' -> 30475 */
{0x770d, 0xedee}, /* '眍' -> 30477 */
{0x7719, 0xedf4}, /* '眙' -> 30489 */
{0x771a, 0xedf2}, /* '眚' -> 30490 */
{0x771f, 0xd5e6}, /* '真' -> 30495 */
{0x7720, 0xc3df}, /* '眠' -> 30496 */
{0x7722, 0xedf3}, /* '眢' -> 30498 */
{0x7726, 0xedf6}, /* '眦' -> 30502 */
{0x7728, 0xd5a3}, /* '眨' -> 30504 */
{0x7729, 0xd1a3}, /* '眩' -> 30505 */
{0x772d, 0xedf5}, /* '眭' -> 30509 */
{0x772f, 0xc3d0}, /* '眯' -> 30511 */
{0x7735, 0xedf7}, /* '眵' -> 30517 */
{0x7736, 0xbff4}, /* '眶' -> 30518 */
{0x7737, 0xbeec}, /* '眷' -> 30519 */
{0x7738, 0xedf8}, /* '眸' -> 30520 */
{0x773a, 0xccf7}, /* '眺' -> 30522 */
{0x773c, 0xd1db}, /* '眼' -> 30524 */
{0x7740, 0xd7c5}, /* '着' -> 30528 */
{0x7741, 0xd5f6}, /* '睁' -> 30529 */
{0x7743, 0xedfc}, /* '睃' -> 30531 */
{0x7747, 0xedfb}, /* '睇' -> 30535 */
{0x7750, 0xedf9}, /* '睐' -> 30544 */
{0x7751, 0xedfa}, /* '睑' -> 30545 */
{0x775a, 0xedfd}, /* '睚' -> 30554 */
{0x775b, 0xbea6}, /* '睛' -> 30555 */
{0x7761, 0xcbaf}, /* '睡' -> 30561 */
{0x7762, 0xeea1}, /* '睢' -> 30562 */
{0x7763, 0xb6bd}, /* '督' -> 30563 */
{0x7765, 0xeea2}, /* '睥' -> 30565 */
{0x7766, 0xc4c0}, /* '睦' -> 30566 */
{0x7768, 0xedfe}, /* '睨' -> 30568 */
{0x776b, 0xbdde}, /* '睫' -> 30571 */
{0x776c, 0xb2c7}, /* '睬' -> 30572 */
{0x7779, 0xb6c3}, /* '睹' -> 30585 */
{0x777d, 0xeea5}, /* '睽' -> 30589 */
{0x777e, 0xd8ba}, /* '睾' -> 30590 */
{0x777f, 0xeea3}, /* '睿' -> 30591 */
{0x7780, 0xeea6}, /* '瞀' -> 30592 */
{0x7784, 0xc3e9}, /* '瞄' -> 30596 */
{0x7785, 0xb3f2}, /* '瞅' -> 30597 */
{0x778c, 0xeea7}, /* '瞌' -> 30604 */
{0x778d, 0xeea4}, /* '瞍' -> 30605 */
{0x778e, 0xcfb9}, /* '瞎' -> 30606 */
{0x7791, 0xeea8}, /* '瞑' -> 30609 */
{0x7792, 0xc2f7}, /* '瞒' -> 30610 */
{0x779f, 0xeea9}, /* '瞟' -> 30623 */
{0x77a0, 0xeeaa}, /* '瞠' -> 30624 */
{0x77a2, 0xdeab}, /* '瞢' -> 30626 */
{0x77a5, 0xc6b3}, /* '瞥' -> 30629 */
{0x77a7, 0xc7c6}, /* '瞧' -> 30631 */
{0x77a9, 0xd6f5}, /* '瞩' -> 30633 */
{0x77aa, 0xb5c9}, /* '瞪' -> 30634 */
{0x77ac, 0xcbb2}, /* '瞬' -> 30636 */
{0x77b0, 0xeeab}, /* '瞰' -> 30640 */
{0x77b3, 0xcdab}, /* '瞳' -> 30643 */
{0x77b5, 0xeeac}, /* '瞵' -> 30645 */
{0x77bb, 0xd5b0}, /* '瞻' -> 30651 */
{0x77bd, 0xeead}, /* '瞽' -> 30653 */
{0x77bf, 0xf6c4}, /* '瞿' -> 30655 */
{0x77cd, 0xdbc7}, /* '矍' -> 30669 */
{0x77d7, 0xb4a3}, /* '矗' -> 30679 */
{0x77db, 0xc3ac}, /* '矛' -> 30683 */
{0x77dc, 0xf1e6}, /* '矜' -> 30684 */
{0x77e2, 0xcab8}, /* '矢' -> 30690 */
{0x77e3, 0xd2d3}, /* '矣' -> 30691 */
{0x77e5, 0xd6aa}, /* '知' -> 30693 */
{0x77e7, 0xeff2}, /* '矧' -> 30695 */
{0x77e9, 0xbed8}, /* '矩' -> 30697 */
{0x77eb, 0xbdc3}, /* '矫' -> 30699 */
{0x77ec, 0xeff3}, /* '矬' -> 30700 */
{0x77ed, 0xb6cc}, /* '短' -> 30701 */
{0x77ee, 0xb0ab}, /* '矮' -> 30702 */
{0x77f3, 0xcaaf}, /* '石' -> 30707 */
{0x77f6, 0xedb6}, /* '矶' -> 30710 */
{0x77f8, 0xedb7}, /* '矸' -> 30712 */
{0x77fd, 0xcef9}, /* '矽' -> 30717 */
{0x77fe, 0xb7af}, /* '矾' -> 30718 */
{0x77ff, 0xbff3}, /* '矿' -> 30719 */
{0x7800, 0xedb8}, /* '砀' -> 30720 */
{0x7801, 0xc2eb}, /* '码' -> 30721 */
{0x7802, 0xc9b0}, /* '砂' -> 30722 */
{0x7809, 0xedb9}, /* '砉' -> 30729 */
{0x780c, 0xc6f6}, /* '砌' -> 30732 */
{0x780d, 0xbfb3}, /* '砍' -> 30733 */
{0x7811, 0xedbc}, /* '砑' -> 30737 */
{0x7812, 0xc5f8}, /* '砒' -> 30738 */
{0x7814, 0xd1d0}, /* '研' -> 30740 */
{0x7816, 0xd7a9}, /* '砖' -> 30742 */
{0x7817, 0xedba}, /* '砗' -> 30743 */
{0x7818, 0xedbb}, /* '砘' -> 30744 */
{0x781a, 0xd1e2}, /* '砚' -> 30746 */
{0x781c, 0xedbf}, /* '砜' -> 30748 */
{0x781d, 0xedc0}, /* '砝' -> 30749 */
{0x781f, 0xedc4}, /* '砟' -> 30751 */
{0x7823, 0xedc8}, /* '砣' -> 30755 */
{0x7825, 0xedc6}, /* '砥' -> 30757 */
{0x7826, 0xedce}, /* '砦' -> 30758 */
{0x7827, 0xd5e8}, /* '砧' -> 30759 */
{0x7829, 0xedc9}, /* '砩' -> 30761 */
{0x782c, 0xedc7}, /* '砬' -> 30764 */
{0x782d, 0xedbe}, /* '砭' -> 30765 */
{0x7830, 0xc5e9}, /* '砰' -> 30768 */
{0x7834, 0xc6c6}, /* '破' -> 30772 */
{0x7837, 0xc9e9}, /* '砷' -> 30775 */
{0x7838, 0xd4d2}, /* '砸' -> 30776 */
{0x7839, 0xedc1}, /* '砹' -> 30777 */
{0x783a, 0xedc2}, /* '砺' -> 30778 */
{0x783b, 0xedc3}, /* '砻' -> 30779 */
{0x783c, 0xedc5}, /* '砼' -> 30780 */
{0x783e, 0xc0f9}, /* '砾' -> 30782 */
{0x7840, 0xb4a1}, /* '础' -> 30784 */
{0x7845, 0xb9e8}, /* '硅' -> 30789 */
{0x7847, 0xedd0}, /* '硇' -> 30791 */
{0x784c, 0xedd1}, /* '硌' -> 30796 */
{0x784e, 0xedca}, /* '硎' -> 30798 */
{0x7850, 0xedcf}, /* '硐' -> 30800 */
{0x7852, 0xcef8}, /* '硒' -> 30802 */
{0x7855, 0xcbb6}, /* '硕' -> 30805 */
{0x7856, 0xedcc}, /* '硖' -> 30806 */
{0x7857, 0xedcd}, /* '硗' -> 30807 */
{0x785d, 0xcff5}, /* '硝' -> 30813 */
{0x786a, 0xedd2}, /* '硪' -> 30826 */
{0x786b, 0xc1f2}, /* '硫' -> 30827 */
{0x786c, 0xd3b2}, /* '硬' -> 30828 */
{0x786d, 0xedcb}, /* '硭' -> 30829 */
{0x786e, 0xc8b7}, /* '确' -> 30830 */
{0x7877, 0xbcef}, /* '硷' -> 30839 */
{0x787c, 0xc5f0}, /* '硼' -> 30844 */
{0x7887, 0xedd6}, /* '碇' -> 30855 */
{0x7889, 0xb5ef}, /* '碉' -> 30857 */
{0x788c, 0xc2b5}, /* '碌' -> 30860 */
{0x788d, 0xb0ad}, /* '碍' -> 30861 */
{0x788e, 0xcbe9}, /* '碎' -> 30862 */
{0x7891, 0xb1ae}, /* '碑' -> 30865 */
{0x7893, 0xedd4}, /* '碓' -> 30867 */
{0x7897, 0xcdeb}, /* '碗' -> 30871 */
{0x7898, 0xb5e2}, /* '碘' -> 30872 */
{0x789a, 0xedd5}, /* '碚' -> 30874 */
{0x789b, 0xedd3}, /* '碛' -> 30875 */
{0x789c, 0xedd7}, /* '碜' -> 30876 */
{0x789f, 0xb5fa}, /* '碟' -> 30879 */
{0x78a1, 0xedd8}, /* '碡' -> 30881 */
{0x78a3, 0xedd9}, /* '碣' -> 30883 */
{0x78a5, 0xeddc}, /* '碥' -> 30885 */
{0x78a7, 0xb1cc}, /* '碧' -> 30887 */
{0x78b0, 0xc5f6}, /* '碰' -> 30896 */
{0x78b1, 0xbcee}, /* '碱' -> 30897 */
{0x78b2, 0xedda}, /* '碲' -> 30898 */
{0x78b3, 0xccbc}, /* '碳' -> 30899 */
{0x78b4, 0xb2ea}, /* '碴' -> 30900 */
{0x78b9, 0xeddb}, /* '碹' -> 30905 */
{0x78be, 0xc4eb}, /* '碾' -> 30910 */
{0x78c1, 0xb4c5}, /* '磁' -> 30913 */
{0x78c5, 0xb0f5}, /* '磅' -> 30917 */
{0x78c9, 0xeddf}, /* '磉' -> 30921 */
{0x78ca, 0xc0da}, /* '磊' -> 30922 */
{0x78cb, 0xb4e8}, /* '磋' -> 30923 */
{0x78d0, 0xc5cd}, /* '磐' -> 30928 */
{0x78d4, 0xeddd}, /* '磔' -> 30932 */
{0x78d5, 0xbfc4}, /* '磕' -> 30933 */
{0x78d9, 0xedde}, /* '磙' -> 30937 */
{0x78e8, 0xc4a5}, /* '磨' -> 30952 */
{0x78ec, 0xede0}, /* '磬' -> 30956 */
{0x78f2, 0xede1}, /* '磲' -> 30962 */
{0x78f4, 0xede3}, /* '磴' -> 30964 */
{0x78f7, 0xc1d7}, /* '磷' -> 30967 */
{0x78fa, 0xbbc7}, /* '磺' -> 30970 */
{0x7901, 0xbdb8}, /* '礁' -> 30977 */
{0x7905, 0xede2}, /* '礅' -> 30981 */
{0x7913, 0xede4}, /* '礓' -> 30995 */
{0x791e, 0xede6}, /* '礞' -> 31006 */
{0x7924, 0xede5}, /* '礤' -> 31012 */
{0x7934, 0xede7}, /* '礴' -> 31028 */
{0x793a, 0xcabe}, /* '示' -> 31034 */
{0x793b, 0xecea}, /* '礻' -> 31035 */
{0x793c, 0xc0f1}, /* '礼' -> 31036 */
{0x793e, 0xc9e7}, /* '社' -> 31038 */
{0x7940, 0xeceb}, /* '祀' -> 31040 */
{0x7941, 0xc6ee}, /* '祁' -> 31041 */
{0x7946, 0xecec}, /* '祆' -> 31046 */
{0x7948, 0xc6ed}, /* '祈' -> 31048 */
{0x7949, 0xeced}, /* '祉' -> 31049 */
{0x7953, 0xecf0}, /* '祓' -> 31059 */
{0x7956, 0xd7e6}, /* '祖' -> 31062 */
{0x7957, 0xecf3}, /* '祗' -> 31063 */
{0x795a, 0xecf1}, /* '祚' -> 31066 */
{0x795b, 0xecee}, /* '祛' -> 31067 */
{0x795c, 0xecef}, /* '祜' -> 31068 */
{0x795d, 0xd7a3}, /* '祝' -> 31069 */
{0x795e, 0xc9f1}, /* '神' -> 31070 */
{0x795f, 0xcbee}, /* '祟' -> 31071 */
{0x7960, 0xecf4}, /* '祠' -> 31072 */
{0x7962, 0xecf2}, /* '祢' -> 31074 */
{0x7965, 0xcfe9}, /* '祥' -> 31077 */
{0x7967, 0xecf6}, /* '祧' -> 31079 */
{0x7968, 0xc6b1}, /* '票' -> 31080 */
{0x796d, 0xbcc0}, /* '祭' -> 31085 */
{0x796f, 0xecf5}, /* '祯' -> 31087 */
{0x7977, 0xb5bb}, /* '祷' -> 31095 */
{0x7978, 0xbbf6}, /* '祸' -> 31096 */
{0x797a, 0xecf7}, /* '祺' -> 31098 */
{0x7980, 0xd9f7}, /* '禀' -> 31104 */
{0x7981, 0xbdfb}, /* '禁' -> 31105 */
{0x7984, 0xc2bb}, /* '禄' -> 31108 */
{0x7985, 0xecf8}, /* '禅' -> 31109 */
{0x798a, 0xecf9}, /* '禊' -> 31114 */
{0x798f, 0xb8a3}, /* '福' -> 31119 */
{0x799a, 0xecfa}, /* '禚' -> 31130 */
{0x79a7, 0xecfb}, /* '禧' -> 31143 */
{0x79b3, 0xecfc}, /* '禳' -> 31155 */
{0x79b9, 0xd3ed}, /* '禹' -> 31161 */
{0x79ba, 0xd8ae}, /* '禺' -> 31162 */
{0x79bb, 0xc0eb}, /* '离' -> 31163 */
{0x79bd, 0xc7dd}, /* '禽' -> 31165 */
{0x79be, 0xbacc}, /* '禾' -> 31166 */
{0x79c0, 0xd0e3}, /* '秀' -> 31168 */
{0x79c1, 0xcbbd}, /* '私' -> 31169 */
{0x79c3, 0xcdba}, /* '秃' -> 31171 */
{0x79c6, 0xb8d1}, /* '秆' -> 31174 */
{0x79c9, 0xb1fc}, /* '秉' -> 31177 */
{0x79cb, 0xc7ef}, /* '秋' -> 31179 */
{0x79cd, 0xd6d6}, /* '种' -> 31181 */
{0x79d1, 0xbfc6}, /* '科' -> 31185 */
{0x79d2, 0xc3eb}, /* '秒' -> 31186 */
{0x79d5, 0xeff5}, /* '秕' -> 31189 */
{0x79d8, 0xc3d8}, /* '秘' -> 31192 */
{0x79df, 0xd7e2}, /* '租' -> 31199 */
{0x79e3, 0xeff7}, /* '秣' -> 31203 */
{0x79e4, 0xb3d3}, /* '秤' -> 31204 */
{0x79e6, 0xc7d8}, /* '秦' -> 31206 */
{0x79e7, 0xd1ed}, /* '秧' -> 31207 */
{0x79e9, 0xd6c8}, /* '秩' -> 31209 */
{0x79eb, 0xeff8}, /* '秫' -> 31211 */
{0x79ed, 0xeff6}, /* '秭' -> 31213 */
{0x79ef, 0xbbfd}, /* '积' -> 31215 */
{0x79f0, 0xb3c6}, /* '称' -> 31216 */
{0x79f8, 0xbdd5}, /* '秸' -> 31224 */
{0x79fb, 0xd2c6}, /* '移' -> 31227 */
{0x79fd, 0xbbe0}, /* '秽' -> 31229 */
{0x7a00, 0xcfa1}, /* '稀' -> 31232 */
{0x7a02, 0xeffc}, /* '稂' -> 31234 */
{0x7a03, 0xeffb}, /* '稃' -> 31235 */
{0x7a06, 0xeff9}, /* '稆' -> 31238 */
{0x7a0b, 0xb3cc}, /* '程' -> 31243 */
{0x7a0d, 0xc9d4}, /* '稍' -> 31245 */
{0x7a0e, 0xcbb0}, /* '税' -> 31246 */
{0x7a14, 0xeffe}, /* '稔' -> 31252 */
{0x7a17, 0xb0de}, /* '稗' -> 31255 */
{0x7a1a, 0xd6c9}, /* '稚' -> 31258 */
{0x7a1e, 0xeffd}, /* '稞' -> 31262 */
{0x7a20, 0xb3ed}, /* '稠' -> 31264 */
{0x7a23, 0xf6d5}, /* '稣' -> 31267 */
{0x7a33, 0xcec8}, /* '稳' -> 31283 */
{0x7a37, 0xf0a2}, /* '稷' -> 31287 */
{0x7a39, 0xf0a1}, /* '稹' -> 31289 */
{0x7a3b, 0xb5be}, /* '稻' -> 31291 */
{0x7a3c, 0xbcda}, /* '稼' -> 31292 */
{0x7a3d, 0xbbfc}, /* '稽' -> 31293 */
{0x7a3f, 0xb8e5}, /* '稿' -> 31295 */
{0x7a46, 0xc4c2}, /* '穆' -> 31302 */
{0x7a51, 0xf0a3}, /* '穑' -> 31313 */
{0x7a57, 0xcbeb}, /* '穗' -> 31319 */
{0x7a70, 0xf0a6}, /* '穰' -> 31344 */
{0x7a74, 0xd1a8}, /* '穴' -> 31348 */
{0x7a76, 0xbebf}, /* '究' -> 31350 */
{0x7a77, 0xc7ee}, /* '穷' -> 31351 */
{0x7a78, 0xf1b6}, /* '穸' -> 31352 */
{0x7a79, 0xf1b7}, /* '穹' -> 31353 */
{0x7a7a, 0xbfd5}, /* '空' -> 31354 */
{0x7a7f, 0xb4a9}, /* '穿' -> 31359 */
{0x7a80, 0xf1b8}, /* '窀' -> 31360 */
{0x7a81, 0xcdbb}, /* '突' -> 31361 */
{0x7a83, 0xc7d4}, /* '窃' -> 31363 */
{0x7a84, 0xd5ad}, /* '窄' -> 31364 */
{0x7a86, 0xf1b9}, /* '窆' -> 31366 */
{0x7a88, 0xf1ba}, /* '窈' -> 31368 */
{0x7a8d, 0xc7cf}, /* '窍' -> 31373 */
{0x7a91, 0xd2a4}, /* '窑' -> 31377 */
{0x7a92, 0xd6cf}, /* '窒' -> 31378 */
{0x7a95, 0xf1bb}, /* '窕' -> 31381 */
{0x7a96, 0xbdd1}, /* '窖' -> 31382 */
{0x7a97, 0xb4b0}, /* '窗' -> 31383 */
{0x7a98, 0xbebd}, /* '窘' -> 31384 */
{0x7a9c, 0xb4dc}, /* '窜' -> 31388 */
{0x7a9d, 0xced1}, /* '窝' -> 31389 */
{0x7a9f, 0xbfdf}, /* '窟' -> 31391 */
{0x7aa0, 0xf1bd}, /* '窠' -> 31392 */
{0x7aa5, 0xbffa}, /* '窥' -> 31397 */
{0x7aa6, 0xf1bc}, /* '窦' -> 31398 */
{0x7aa8, 0xf1bf}, /* '窨' -> 31400 */
{0x7aac, 0xf1be}, /* '窬' -> 31404 */
{0x7aad, 0xf1c0}, /* '窭' -> 31405 */
{0x7ab3, 0xf1c1}, /* '窳' -> 31411 */
{0x7abf, 0xc1fe}, /* '窿' -> 31423 */
{0x7acb, 0xc1a2}, /* '立' -> 31435 */
{0x7ad6, 0xcafa}, /* '竖' -> 31446 */
{0x7ad9, 0xd5be}, /* '站' -> 31449 */
{0x7ade, 0xbeba}, /* '竞' -> 31454 */
{0x7adf, 0xbeb9}, /* '竟' -> 31455 */
{0x7ae0, 0xd5c2}, /* '章' -> 31456 */
{0x7ae3, 0xbfa2}, /* '竣' -> 31459 */
{0x7ae5, 0xcdaf}, /* '童' -> 31461 */
{0x7ae6, 0xf1b5}, /* '竦' -> 31462 */
{0x7aed, 0xbddf}, /* '竭' -> 31469 */
{0x7aef, 0xb6cb}, /* '端' -> 31471 */
{0x7af9, 0xd6f1}, /* '竹' -> 31481 */
{0x7afa, 0xf3c3}, /* '竺' -> 31482 */
{0x7afd, 0xf3c4}, /* '竽' -> 31485 */
{0x7aff, 0xb8cd}, /* '竿' -> 31487 */
{0x7b03, 0xf3c6}, /* '笃' -> 31491 */
{0x7b04, 0xf3c7}, /* '笄' -> 31492 */
{0x7b06, 0xb0ca}, /* '笆' -> 31494 */
{0x7b08, 0xf3c5}, /* '笈' -> 31496 */
{0x7b0a, 0xf3c9}, /* '笊' -> 31498 */
{0x7b0b, 0xcbf1}, /* '笋' -> 31499 */
{0x7b0f, 0xf3cb}, /* '笏' -> 31503 */
{0x7b11, 0xd0a6}, /* '笑' -> 31505 */
{0x7b14, 0xb1ca}, /* '笔' -> 31508 */
{0x7b15, 0xf3c8}, /* '笕' -> 31509 */
{0x7b19, 0xf3cf}, /* '笙' -> 31513 */
{0x7b1b, 0xb5d1}, /* '笛' -> 31515 */
{0x7b1e, 0xf3d7}, /* '笞' -> 31518 */
{0x7b20, 0xf3d2}, /* '笠' -> 31520 */
{0x7b24, 0xf3d4}, /* '笤' -> 31524 */
{0x7b25, 0xf3d3}, /* '笥' -> 31525 */
{0x7b26, 0xb7fb}, /* '符' -> 31526 */
{0x7b28, 0xb1bf}, /* '笨' -> 31528 */
{0x7b2a, 0xf3ce}, /* '笪' -> 31530 */
{0x7b2b, 0xf3ca}, /* '笫' -> 31531 */
{0x7b2c, 0xb5da}, /* '第' -> 31532 */
{0x7b2e, 0xf3d0}, /* '笮' -> 31534 */
{0x7b31, 0xf3d1}, /* '笱' -> 31537 */
{0x7b33, 0xf3d5}, /* '笳' -> 31539 */
{0x7b38, 0xf3cd}, /* '笸' -> 31544 */
{0x7b3a, 0xbce3}, /* '笺' -> 31546 */
{0x7b3c, 0xc1fd}, /* '笼' -> 31548 */
{0x7b3e, 0xf3d6}, /* '笾' -> 31550 */
{0x7b45, 0xf3da}, /* '筅' -> 31557 */
{0x7b47, 0xf3cc}, /* '筇' -> 31559 */
{0x7b49, 0xb5c8}, /* '等' -> 31561 */
{0x7b4b, 0xbdee}, /* '筋' -> 31563 */
{0x7b4c, 0xf3dc}, /* '筌' -> 31564 */
{0x7b4f, 0xb7a4}, /* '筏' -> 31567 */
{0x7b50, 0xbff0}, /* '筐' -> 31568 */
{0x7b51, 0xd6fe}, /* '筑' -> 31569 */
{0x7b52, 0xcdb2}, /* '筒' -> 31570 */
{0x7b54, 0xb4f0}, /* '答' -> 31572 */
{0x7b56, 0xb2df}, /* '策' -> 31574 */
{0x7b58, 0xf3d8}, /* '筘' -> 31576 */
{0x7b5a, 0xf3d9}, /* '筚' -> 31578 */
{0x7b5b, 0xc9b8}, /* '筛' -> 31579 */
{0x7b5d, 0xf3dd}, /* '筝' -> 31581 */
{0x7b60, 0xf3de}, /* '筠' -> 31584 */
{0x7b62, 0xf3e1}, /* '筢' -> 31586 */
{0x7b6e, 0xf3df}, /* '筮' -> 31598 */
{0x7b71, 0xf3e3}, /* '筱' -> 31601 */
{0x7b72, 0xf3e2}, /* '筲' -> 31602 */
{0x7b75, 0xf3db}, /* '筵' -> 31605 */
{0x7b77, 0xbfea}, /* '筷' -> 31607 */
{0x7b79, 0xb3ef}, /* '筹' -> 31609 */
{0x7b7b, 0xf3e0}, /* '筻' -> 31611 */
{0x7b7e, 0xc7a9}, /* '签' -> 31614 */
{0x7b80, 0xbcf2}, /* '简' -> 31616 */
{0x7b85, 0xf3eb}, /* '箅' -> 31621 */
{0x7b8d, 0xb9bf}, /* '箍' -> 31629 */
{0x7b90, 0xf3e4}, /* '箐' -> 31632 */
{0x7b94, 0xb2ad}, /* '箔' -> 31636 */
{0x7b95, 0xbbfe}, /* '箕' -> 31637 */
{0x7b97, 0xcbe3}, /* '算' -> 31639 */
{0x7b9c, 0xf3ed}, /* '箜' -> 31644 */
{0x7b9d, 0xf3e9}, /* '箝' -> 31645 */
{0x7ba1, 0xb9dc}, /* '管' -> 31649 */
{0x7ba2, 0xf3ee}, /* '箢' -> 31650 */
{0x7ba6, 0xf3e5}, /* '箦' -> 31654 */
{0x7ba7, 0xf3e6}, /* '箧' -> 31655 */
{0x7ba8, 0xf3ea}, /* '箨' -> 31656 */
{0x7ba9, 0xc2e1}, /* '箩' -> 31657 */
{0x7baa, 0xf3ec}, /* '箪' -> 31658 */
{0x7bab, 0xf3ef}, /* '箫' -> 31659 */
{0x7bac, 0xf3e8}, /* '箬' -> 31660 */
{0x7bad, 0xbcfd}, /* '箭' -> 31661 */
{0x7bb1, 0xcfe4}, /* '箱' -> 31665 */
{0x7bb4, 0xf3f0}, /* '箴' -> 31668 */
{0x7bb8, 0xf3e7}, /* '箸' -> 31672 */
{0x7bc1, 0xf3f2}, /* '篁' -> 31681 */
{0x7bc6, 0xd7ad}, /* '篆' -> 31686 */
{0x7bc7, 0xc6aa}, /* '篇' -> 31687 */
{0x7bcc, 0xf3f3}, /* '篌' -> 31692 */
{0x7bd1, 0xf3f1}, /* '篑' -> 31697 */
{0x7bd3, 0xc2a8}, /* '篓' -> 31699 */
{0x7bd9, 0xb8dd}, /* '篙' -> 31705 */
{0x7bda, 0xf3f5}, /* '篚' -> 31706 */
{0x7bdd, 0xf3f4}, /* '篝' -> 31709 */
{0x7be1, 0xb4db}, /* '篡' -> 31713 */
{0x7be5, 0xf3f6}, /* '篥' -> 31717 */
{0x7be6, 0xf3f7}, /* '篦' -> 31718 */
{0x7bea, 0xf3f8}, /* '篪' -> 31722 */
{0x7bee, 0xc0ba}, /* '篮' -> 31726 */
{0x7bf1, 0xc0e9}, /* '篱' -> 31729 */
{0x7bf7, 0xc5f1}, /* '篷' -> 31735 */
{0x7bfc, 0xf3fb}, /* '篼' -> 31740 */
{0x7bfe, 0xf3fa}, /* '篾' -> 31742 */
{0x7c07, 0xb4d8}, /* '簇' -> 31751 */
{0x7c0b, 0xf3fe}, /* '簋' -> 31755 */
{0x7c0c, 0xf3f9}, /* '簌' -> 31756 */
{0x7c0f, 0xf3fc}, /* '簏' -> 31759 */
{0x7c16, 0xf3fd}, /* '簖' -> 31766 */
{0x7c1f, 0xf4a1}, /* '簟' -> 31775 */
{0x7c26, 0xf4a3}, /* '簦' -> 31782 */
{0x7c27, 0xbbc9}, /* '簧' -> 31783 */
{0x7c2a, 0xf4a2}, /* '簪' -> 31786 */
{0x7c38, 0xf4a4}, /* '簸' -> 31800 */
{0x7c3f, 0xb2be}, /* '簿' -> 31807 */
{0x7c40, 0xf4a6}, /* '籀' -> 31808 */
{0x7c41, 0xf4a5}, /* '籁' -> 31809 */
{0x7c4d, 0xbcae}, /* '籍' -> 31821 */
{0x7c73, 0xc3d7}, /* '米' -> 31859 */
{0x7c74, 0xd9e1}, /* '籴' -> 31860 */
{0x7c7b, 0xc0e0}, /* '类' -> 31867 */
{0x7c7c, 0xf4cc}, /* '籼' -> 31868 */
{0x7c7d, 0xd7d1}, /* '籽' -> 31869 */
{0x7c89, 0xb7db}, /* '粉' -> 31881 */
{0x7c91, 0xf4ce}, /* '粑' -> 31889 */
{0x7c92, 0xc1a3}, /* '粒' -> 31890 */
{0x7c95, 0xc6c9}, /* '粕' -> 31893 */
{0x7c97, 0xb4d6}, /* '粗' -> 31895 */
{0x7c98, 0xd5b3}, /* '粘' -> 31896 */
{0x7c9c, 0xf4d0}, /* '粜' -> 31900 */
{0x7c9d, 0xf4cf}, /* '粝' -> 31901 */
{0x7c9e, 0xf4d1}, /* '粞' -> 31902 */
{0x7c9f, 0xcbda}, /* '粟' -> 31903 */
{0x7ca2, 0xf4d2}, /* '粢' -> 31906 */
{0x7ca4, 0xd4c1}, /* '粤' -> 31908 */
{0x7ca5, 0xd6e0}, /* '粥' -> 31909 */
{0x7caa, 0xb7e0}, /* '粪' -> 31914 */
{0x7cae, 0xc1b8}, /* '粮' -> 31918 */
{0x7cb1, 0xc1bb}, /* '粱' -> 31921 */
{0x7cb2, 0xf4d3}, /* '粲' -> 31922 */
{0x7cb3, 0xbeac}, /* '粳' -> 31923 */
{0x7cb9, 0xb4e2}, /* '粹' -> 31929 */
{0x7cbc, 0xf4d4}, /* '粼' -> 31932 */
{0x7cbd, 0xf4d5}, /* '粽' -> 31933 */
{0x7cbe, 0xbeab}, /* '精' -> 31934 */
{0x7cc1, 0xf4d6}, /* '糁' -> 31937 */
{0x7cc5, 0xf4db}, /* '糅' -> 31941 */
{0x7cc7, 0xf4d7}, /* '糇' -> 31943 */
{0x7cc8, 0xf4da}, /* '糈' -> 31944 */
{0x7cca, 0xbafd}, /* '糊' -> 31946 */
{0x7ccc, 0xf4d8}, /* '糌' -> 31948 */
{0x7ccd, 0xf4d9}, /* '糍' -> 31949 */
{0x7cd5, 0xb8e2}, /* '糕' -> 31957 */
{0x7cd6, 0xccc7}, /* '糖' -> 31958 */
{0x7cd7, 0xf4dc}, /* '糗' -> 31959 */
{0x7cd9, 0xb2da}, /* '糙' -> 31961 */
{0x7cdc, 0xc3d3}, /* '糜' -> 31964 */
{0x7cdf, 0xd4e3}, /* '糟' -> 31967 */
{0x7ce0, 0xbfb7}, /* '糠' -> 31968 */
{0x7ce8, 0xf4dd}, /* '糨' -> 31976 */
{0x7cef, 0xc5b4}, /* '糯' -> 31983 */
{0x7cf8, 0xf4e9}, /* '糸' -> 31992 */
{0x7cfb, 0xcfb5}, /* '系' -> 31995 */
{0x7d0a, 0xcec9}, /* '紊' -> 32010 */
{0x7d20, 0xcbd8}, /* '素' -> 32032 */
{0x7d22, 0xcbf7}, /* '索' -> 32034 */
{0x7d27, 0xbdf4}, /* '紧' -> 32039 */
{0x7d2b, 0xd7cf}, /* '紫' -> 32043 */
{0x7d2f, 0xc0db}, /* '累' -> 32047 */
{0x7d6e, 0xd0f5}, /* '絮' -> 32110 */
{0x7d77, 0xf4ea}, /* '絷' -> 32119 */
{0x7da6, 0xf4eb}, /* '綦' -> 32166 */
{0x7dae, 0xf4ec}, /* '綮' -> 32174 */
{0x7e3b, 0xf7e3}, /* '縻' -> 32315 */
{0x7e41, 0xb7b1}, /* '繁' -> 32321 */
{0x7e47, 0xf4ed}, /* '繇' -> 32327 */
{0x7e82, 0xd7eb}, /* '纂' -> 32386 */
{0x7e9b, 0xf4ee}, /* '纛' -> 32411 */
{0x7e9f, 0xe6f9}, /* '纟' -> 32415 */
{0x7ea0, 0xbec0}, /* '纠' -> 32416 */
{0x7ea1, 0xe6fa}, /* '纡' -> 32417 */
{0x7ea2, 0xbaec}, /* '红' -> 32418 */
{0x7ea3, 0xe6fb}, /* '纣' -> 32419 */
{0x7ea4, 0xcfcb}, /* '纤' -> 32420 */
{0x7ea5, 0xe6fc}, /* '纥' -> 32421 */
{0x7ea6, 0xd4bc}, /* '约' -> 32422 */
{0x7ea7, 0xbcb6}, /* '级' -> 32423 */
{0x7ea8, 0xe6fd}, /* '纨' -> 32424 */
{0x7ea9, 0xe6fe}, /* '纩' -> 32425 */
{0x7eaa, 0xbccd}, /* '纪' -> 32426 */
{0x7eab, 0xc8d2}, /* '纫' -> 32427 */
{0x7eac, 0xceb3}, /* '纬' -> 32428 */
{0x7ead, 0xe7a1}, /* '纭' -> 32429 */
{0x7eaf, 0xb4bf}, /* '纯' -> 32431 */
{0x7eb0, 0xe7a2}, /* '纰' -> 32432 */
{0x7eb1, 0xc9b4}, /* '纱' -> 32433 */
{0x7eb2, 0xb8d9}, /* '纲' -> 32434 */
{0x7eb3, 0xc4c9}, /* '纳' -> 32435 */
{0x7eb5, 0xd7dd}, /* '纵' -> 32437 */
{0x7eb6, 0xc2da}, /* '纶' -> 32438 */
{0x7eb7, 0xb7d7}, /* '纷' -> 32439 */
{0x7eb8, 0xd6bd}, /* '纸' -> 32440 */
{0x7eb9, 0xcec6}, /* '纹' -> 32441 */
{0x7eba, 0xb7c4}, /* '纺' -> 32442 */
{0x7ebd, 0xc5a6}, /* '纽' -> 32445 */
{0x7ebe, 0xe7a3}, /* '纾' -> 32446 */
{0x7ebf, 0xcfdf}, /* '线' -> 32447 */
{0x7ec0, 0xe7a4}, /* '绀' -> 32448 */
{0x7ec1, 0xe7a5}, /* '绁' -> 32449 */
{0x7ec2, 0xe7a6}, /* '绂' -> 32450 */
{0x7ec3, 0xc1b7}, /* '练' -> 32451 */
{0x7ec4, 0xd7e9}, /* '组' -> 32452 */
{0x7ec5, 0xc9f0}, /* '绅' -> 32453 */
{0x7ec6, 0xcfb8}, /* '细' -> 32454 */
{0x7ec7, 0xd6af}, /* '织' -> 32455 */
{0x7ec8, 0xd6d5}, /* '终' -> 32456 */
{0x7ec9, 0xe7a7}, /* '绉' -> 32457 */
{0x7eca, 0xb0ed}, /* '绊' -> 32458 */
{0x7ecb, 0xe7a8}, /* '绋' -> 32459 */
{0x7ecc, 0xe7a9}, /* '绌' -> 32460 */
{0x7ecd, 0xc9dc}, /* '绍' -> 32461 */
{0x7ece, 0xd2ef}, /* '绎' -> 32462 */
{0x7ecf, 0xbead}, /* '经' -> 32463 */
{0x7ed0, 0xe7aa}, /* '绐' -> 32464 */
{0x7ed1, 0xb0f3}, /* '绑' -> 32465 */
{0x7ed2, 0xc8de}, /* '绒' -> 32466 */
{0x7ed3, 0xbde1}, /* '结' -> 32467 */
{0x7ed4, 0xe7ab}, /* '绔' -> 32468 */
{0x7ed5, 0xc8c6}, /* '绕' -> 32469 */
{0x7ed7, 0xe7ac}, /* '绗' -> 32471 */
{0x7ed8, 0xbbe6}, /* '绘' -> 32472 */
{0x7ed9, 0xb8f8}, /* '给' -> 32473 */
{0x7eda, 0xd1a4}, /* '绚' -> 32474 */
{0x7edb, 0xe7ad}, /* '绛' -> 32475 */
{0x7edc, 0xc2e7}, /* '络' -> 32476 */
{0x7edd, 0xbef8}, /* '绝' -> 32477 */
{0x7ede, 0xbdca}, /* '绞' -> 32478 */
{0x7edf, 0xcdb3}, /* '统' -> 32479 */
{0x7ee0, 0xe7ae}, /* '绠' -> 32480 */
{0x7ee1, 0xe7af}, /* '绡' -> 32481 */
{0x7ee2, 0xbeee}, /* '绢' -> 32482 */
{0x7ee3, 0xd0e5}, /* '绣' -> 32483 */
{0x7ee5, 0xcbe7}, /* '绥' -> 32485 */
{0x7ee6, 0xccd0}, /* '绦' -> 32486 */
{0x7ee7, 0xbccc}, /* '继' -> 32487 */
{0x7ee8, 0xe7b0}, /* '绨' -> 32488 */
{0x7ee9, 0xbca8}, /* '绩' -> 32489 */
{0x7eea, 0xd0f7}, /* '绪' -> 32490 */
{0x7eeb, 0xe7b1}, /* '绫' -> 32491 */
{0x7eed, 0xd0f8}, /* '续' -> 32493 */
{0x7eee, 0xe7b2}, /* '绮' -> 32494 */
{0x7eef, 0xe7b3}, /* '绯' -> 32495 */
{0x7ef0, 0xb4c2}, /* '绰' -> 32496 */
{0x7ef1, 0xe7b4}, /* '绱' -> 32497 */
{0x7ef2, 0xe7b5}, /* '绲' -> 32498 */
{0x7ef3, 0xc9fe}, /* '绳' -> 32499 */
{0x7ef4, 0xceac}, /* '维' -> 32500 */
{0x7ef5, 0xc3e0}, /* '绵' -> 32501 */
{0x7ef6, 0xe7b7}, /* '绶' -> 32502 */
{0x7ef7, 0xb1c1}, /* '绷' -> 32503 */
{0x7ef8, 0xb3f1}, /* '绸' -> 32504 */
{0x7efa, 0xe7b8}, /* '绺' -> 32506 */
{0x7efb, 0xe7b9}, /* '绻' -> 32507 */
{0x7efc, 0xd7db}, /* '综' -> 32508 */
{0x7efd, 0xd5c0}, /* '绽' -> 32509 */
{0x7efe, 0xe7ba}, /* '绾' -> 32510 */
{0x7eff, 0xc2cc}, /* '绿' -> 32511 */
{0x7f00, 0xd7ba}, /* '缀' -> 32512 */
{0x7f01, 0xe7bb}, /* '缁' -> 32513 */
{0x7f02, 0xe7bc}, /* '缂' -> 32514 */
{0x7f03, 0xe7bd}, /* '缃' -> 32515 */
{0x7f04, 0xbcea}, /* '缄' -> 32516 */
{0x7f05, 0xc3e5}, /* '缅' -> 32517 */
{0x7f06, 0xc0c2}, /* '缆' -> 32518 */
{0x7f07, 0xe7be}, /* '缇' -> 32519 */
{0x7f08, 0xe7bf}, /* '缈' -> 32520 */
{0x7f09, 0xbca9}, /* '缉' -> 32521 */
{0x7f0b, 0xe7c0}, /* '缋' -> 32523 */
{0x7f0c, 0xe7c1}, /* '缌' -> 32524 */
{0x7f0d, 0xe7b6}, /* '缍' -> 32525 */
{0x7f0e, 0xb6d0}, /* '缎' -> 32526 */
{0x7f0f, 0xe7c2}, /* '缏' -> 32527 */
{0x7f11, 0xe7c3}, /* '缑' -> 32529 */
{0x7f12, 0xe7c4}, /* '缒' -> 32530 */
{0x7f13, 0xbbba}, /* '缓' -> 32531 */
{0x7f14, 0xb5de}, /* '缔' -> 32532 */
{0x7f15, 0xc2c6}, /* '缕' -> 32533 */
{0x7f16, 0xb1e0}, /* '编' -> 32534 */
{0x7f17, 0xe7c5}, /* '缗' -> 32535 */
{0x7f18, 0xd4b5}, /* '缘' -> 32536 */
{0x7f19, 0xe7c6}, /* '缙' -> 32537 */
{0x7f1a, 0xb8bf}, /* '缚' -> 32538 */
{0x7f1b, 0xe7c8}, /* '缛' -> 32539 */
{0x7f1c, 0xe7c7}, /* '缜' -> 32540 */
{0x7f1d, 0xb7ec}, /* '缝' -> 32541 */
{0x7f1f, 0xe7c9}, /* '缟' -> 32543 */
{0x7f20, 0xb2f8}, /* '缠' -> 32544 */
{0x7f21, 0xe7ca}, /* '缡' -> 32545 */
{0x7f22, 0xe7cb}, /* '缢' -> 32546 */
{0x7f23, 0xe7cc}, /* '缣' -> 32547 */
{0x7f24, 0xe7cd}, /* '缤' -> 32548 */
{0x7f25, 0xe7ce}, /* '缥' -> 32549 */
{0x7f26, 0xe7cf}, /* '缦' -> 32550 */
{0x7f27, 0xe7d0}, /* '缧' -> 32551 */
{0x7f28, 0xd3a7}, /* '缨' -> 32552 */
{0x7f29, 0xcbf5}, /* '缩' -> 32553 */
{0x7f2a, 0xe7d1}, /* '缪' -> 32554 */
{0x7f2b, 0xe7d2}, /* '缫' -> 32555 */
{0x7f2c, 0xe7d3}, /* '缬' -> 32556 */
{0x7f2d, 0xe7d4}, /* '缭' -> 32557 */
{0x7f2e, 0xc9c9}, /* '缮' -> 32558 */
{0x7f2f, 0xe7d5}, /* '缯' -> 32559 */
{0x7f30, 0xe7d6}, /* '缰' -> 32560 */
{0x7f31, 0xe7d7}, /* '缱' -> 32561 */
{0x7f32, 0xe7d8}, /* '缲' -> 32562 */
{0x7f33, 0xe7d9}, /* '缳' -> 32563 */
{0x7f34, 0xbdc9}, /* '缴' -> 32564 */
{0x7f35, 0xe7da}, /* '缵' -> 32565 */
{0x7f36, 0xf3be}, /* '缶' -> 32566 */
{0x7f38, 0xb8d7}, /* '缸' -> 32568 */
{0x7f3a, 0xc8b1}, /* '缺' -> 32570 */
{0x7f42, 0xf3bf}, /* '罂' -> 32578 */
{0x7f44, 0xf3c0}, /* '罄' -> 32580 */
{0x7f45, 0xf3c1}, /* '罅' -> 32581 */
{0x7f50, 0xb9de}, /* '罐' -> 32592 */
{0x7f51, 0xcdf8}, /* '网' -> 32593 */
{0x7f54, 0xd8e8}, /* '罔' -> 32596 */
{0x7f55, 0xbab1}, /* '罕' -> 32597 */
{0x7f57, 0xc2de}, /* '罗' -> 32599 */
{0x7f58, 0xeeb7}, /* '罘' -> 32600 */
{0x7f5a, 0xb7a3}, /* '罚' -> 32602 */
{0x7f5f, 0xeeb9}, /* '罟' -> 32607 */
{0x7f61, 0xeeb8}, /* '罡' -> 32609 */
{0x7f62, 0xb0d5}, /* '罢' -> 32610 */
{0x7f68, 0xeebb}, /* '罨' -> 32616 */
{0x7f69, 0xd5d6}, /* '罩' -> 32617 */
{0x7f6a, 0xd7ef}, /* '罪' -> 32618 */
{0x7f6e, 0xd6c3}, /* '置' -> 32622 */
{0x7f71, 0xeebd}, /* '罱' -> 32625 */
{0x7f72, 0xcaf0}, /* '署' -> 32626 */
{0x7f74, 0xeebc}, /* '罴' -> 32628 */
{0x7f79, 0xeebe}, /* '罹' -> 32633 */
{0x7f7e, 0xeec0}, /* '罾' -> 32638 */
{0x7f81, 0xeebf}, /* '羁' -> 32641 */
{0x7f8a, 0xd1f2}, /* '羊' -> 32650 */
{0x7f8c, 0xc7bc}, /* '羌' -> 32652 */
{0x7f8e, 0xc3c0}, /* '美' -> 32654 */
{0x7f94, 0xb8e1}, /* '羔' -> 32660 */
{0x7f9a, 0xc1e7}, /* '羚' -> 32666 */
{0x7f9d, 0xf4c6}, /* '羝' -> 32669 */
{0x7f9e, 0xd0df}, /* '羞' -> 32670 */
{0x7f9f, 0xf4c7}, /* '羟' -> 32671 */
{0x7fa1, 0xcfdb}, /* '羡' -> 32673 */
{0x7fa4, 0xc8ba}, /* '群' -> 32676 */
{0x7fa7, 0xf4c8}, /* '羧' -> 32679 */
{0x7faf, 0xf4c9}, /* '羯' -> 32687 */
{0x7fb0, 0xf4ca}, /* '羰' -> 32688 */
{0x7fb2, 0xf4cb}, /* '羲' -> 32690 */
{0x7fb8, 0xd9fa}, /* '羸' -> 32696 */
{0x7fb9, 0xb8fe}, /* '羹' -> 32697 */
{0x7fbc, 0xe5f1}, /* '羼' -> 32700 */
{0x7fbd, 0xd3f0}, /* '羽' -> 32701 */
{0x7fbf, 0xf4e0}, /* '羿' -> 32703 */
{0x7fc1, 0xcecc}, /* '翁' -> 32705 */
{0x7fc5, 0xb3e1}, /* '翅' -> 32709 */
{0x7fca, 0xf1b4}, /* '翊' -> 32714 */
{0x7fcc, 0xd2ee}, /* '翌' -> 32716 */
{0x7fce, 0xf4e1}, /* '翎' -> 32718 */
{0x7fd4, 0xcfe8}, /* '翔' -> 32724 */
{0x7fd5, 0xf4e2}, /* '翕' -> 32725 */
{0x7fd8, 0xc7cc}, /* '翘' -> 32728 */
{0x7fdf, 0xb5d4}, /* '翟' -> 32735 */
{0x7fe0, 0xb4e4}, /* '翠' -> 32736 */
{0x7fe1, 0xf4e4}, /* '翡' -> 32737 */
{0x7fe5, 0xf4e3}, /* '翥' -> 32741 */
{0x7fe6, 0xf4e5}, /* '翦' -> 32742 */
{0x7fe9, 0xf4e6}, /* '翩' -> 32745 */
{0x7fee, 0xf4e7}, /* '翮' -> 32750 */
{0x7ff0, 0xbab2}, /* '翰' -> 32752 */
{0x7ff1, 0xb0bf}, /* '翱' -> 32753 */
{0x7ff3, 0xf4e8}, /* '翳' -> 32755 */
{0x7ffb, 0xb7ad}, /* '翻' -> 32763 */
{0x7ffc, 0xd2ed}, /* '翼' -> 32764 */
{0x8000, 0xd2ab}, /* '耀' -> 32768 */
{0x8001, 0xc0cf}, /* '老' -> 32769 */
{0x8003, 0xbfbc}, /* '考' -> 32771 */
{0x8004, 0xeba3}, /* '耄' -> 32772 */
{0x8005, 0xd5df}, /* '者' -> 32773 */
{0x8006, 0xeac8}, /* '耆' -> 32774 */
{0x800b, 0xf1f3}, /* '耋' -> 32779 */
{0x800c, 0xb6f8}, /* '而' -> 32780 */
{0x800d, 0xcba3}, /* '耍' -> 32781 */
{0x8010, 0xc4cd}, /* '耐' -> 32784 */
{0x8012, 0xf1e7}, /* '耒' -> 32786 */
{0x8014, 0xf1e8}, /* '耔' -> 32788 */
{0x8015, 0xb8fb}, /* '耕' -> 32789 */
{0x8016, 0xf1e9}, /* '耖' -> 32790 */
{0x8017, 0xbac4}, /* '耗' -> 32791 */
{0x8018, 0xd4c5}, /* '耘' -> 32792 */
{0x8019, 0xb0d2}, /* '耙' -> 32793 */
{0x801c, 0xf1ea}, /* '耜' -> 32796 */
{0x8020, 0xf1eb}, /* '耠' -> 32800 */
{0x8022, 0xf1ec}, /* '耢' -> 32802 */
{0x8025, 0xf1ed}, /* '耥' -> 32805 */
{0x8026, 0xf1ee}, /* '耦' -> 32806 */
{0x8027, 0xf1ef}, /* '耧' -> 32807 */
{0x8028, 0xf1f1}, /* '耨' -> 32808 */
{0x8029, 0xf1f0}, /* '耩' -> 32809 */
{0x802a, 0xc5d5}, /* '耪' -> 32810 */
{0x8031, 0xf1f2}, /* '耱' -> 32817 */
{0x8033, 0xb6fa}, /* '耳' -> 32819 */
{0x8035, 0xf1f4}, /* '耵' -> 32821 */
{0x8036, 0xd2ae}, /* '耶' -> 32822 */
{0x8037, 0xdec7}, /* '耷' -> 32823 */
{0x8038, 0xcbca}, /* '耸' -> 32824 */
{0x803b, 0xb3dc}, /* '耻' -> 32827 */
{0x803d, 0xb5a2}, /* '耽' -> 32829 */
{0x803f, 0xb9a2}, /* '耿' -> 32831 */
{0x8042, 0xc4f4}, /* '聂' -> 32834 */
{0x8043, 0xf1f5}, /* '聃' -> 32835 */
{0x8046, 0xf1f6}, /* '聆' -> 32838 */
{0x804a, 0xc1c4}, /* '聊' -> 32842 */
{0x804b, 0xc1fb}, /* '聋' -> 32843 */
{0x804c, 0xd6b0}, /* '职' -> 32844 */
{0x804d, 0xf1f7}, /* '聍' -> 32845 */
{0x8052, 0xf1f8}, /* '聒' -> 32850 */
{0x8054, 0xc1aa}, /* '联' -> 32852 */
{0x8058, 0xc6b8}, /* '聘' -> 32856 */
{0x805a, 0xbedb}, /* '聚' -> 32858 */
{0x8069, 0xf1f9}, /* '聩' -> 32873 */
{0x806a, 0xb4cf}, /* '聪' -> 32874 */
{0x8071, 0xf1fa}, /* '聱' -> 32881 */
{0x807f, 0xedb2}, /* '聿' -> 32895 */
{0x8080, 0xedb1}, /* '肀' -> 32896 */
{0x8083, 0xcbe0}, /* '肃' -> 32899 */
{0x8084, 0xd2de}, /* '肄' -> 32900 */
{0x8086, 0xcbc1}, /* '肆' -> 32902 */
{0x8087, 0xd5d8}, /* '肇' -> 32903 */
{0x8089, 0xc8e2}, /* '肉' -> 32905 */
{0x808b, 0xc0df}, /* '肋' -> 32907 */
{0x808c, 0xbca1}, /* '肌' -> 32908 */
{0x8093, 0xebc1}, /* '肓' -> 32915 */
{0x8096, 0xd0a4}, /* '肖' -> 32918 */
{0x8098, 0xd6e2}, /* '肘' -> 32920 */
{0x809a, 0xb6c7}, /* '肚' -> 32922 */
{0x809b, 0xb8d8}, /* '肛' -> 32923 */
{0x809c, 0xebc0}, /* '肜' -> 32924 */
{0x809d, 0xb8ce}, /* '肝' -> 32925 */
{0x809f, 0xebbf}, /* '肟' -> 32927 */
{0x80a0, 0xb3a6}, /* '肠' -> 32928 */
{0x80a1, 0xb9c9}, /* '股' -> 32929 */
{0x80a2, 0xd6ab}, /* '肢' -> 32930 */
{0x80a4, 0xb7f4}, /* '肤' -> 32932 */
{0x80a5, 0xb7ca}, /* '肥' -> 32933 */
{0x80a9, 0xbce7}, /* '肩' -> 32937 */
{0x80aa, 0xb7be}, /* '肪' -> 32938 */
{0x80ab, 0xebc6}, /* '肫' -> 32939 */
{0x80ad, 0xebc7}, /* '肭' -> 32941 */
{0x80ae, 0xb0b9}, /* '肮' -> 32942 */
{0x80af, 0xbfcf}, /* '肯' -> 32943 */
{0x80b1, 0xebc5}, /* '肱' -> 32945 */
{0x80b2, 0xd3fd}, /* '育' -> 32946 */
{0x80b4, 0xebc8}, /* '肴' -> 32948 */
{0x80b7, 0xebc9}, /* '肷' -> 32951 */
{0x80ba, 0xb7ce}, /* '肺' -> 32954 */
{0x80bc, 0xebc2}, /* '肼' -> 32956 */
{0x80bd, 0xebc4}, /* '肽' -> 32957 */
{0x80be, 0xc9f6}, /* '肾' -> 32958 */
{0x80bf, 0xd6d7}, /* '肿' -> 32959 */
{0x80c0, 0xd5cd}, /* '胀' -> 32960 */
{0x80c1, 0xd0b2}, /* '胁' -> 32961 */
{0x80c2, 0xebcf}, /* '胂' -> 32962 */
{0x80c3, 0xceb8}, /* '胃' -> 32963 */
{0x80c4, 0xebd0}, /* '胄' -> 32964 */
{0x80c6, 0xb5a8}, /* '胆' -> 32966 */
{0x80cc, 0xb1b3}, /* '背' -> 32972 */
{0x80cd, 0xebd2}, /* '胍' -> 32973 */
{0x80ce, 0xcca5}, /* '胎' -> 32974 */
{0x80d6, 0xc5d6}, /* '胖' -> 32982 */
{0x80d7, 0xebd3}, /* '胗' -> 32983 */
{0x80d9, 0xebd1}, /* '胙' -> 32985 */
{0x80da, 0xc5df}, /* '胚' -> 32986 */
{0x80db, 0xebce}, /* '胛' -> 32987 */
{0x80dc, 0xcaa4}, /* '胜' -> 32988 */
{0x80dd, 0xebd5}, /* '胝' -> 32989 */
{0x80de, 0xb0fb}, /* '胞' -> 32990 */
{0x80e1, 0xbafa}, /* '胡' -> 32993 */
{0x80e4, 0xd8b7}, /* '胤' -> 32996 */
{0x80e5, 0xf1e3}, /* '胥' -> 32997 */
{0x80e7, 0xebca}, /* '胧' -> 32999 */
{0x80e8, 0xebcb}, /* '胨' -> 33000 */
{0x80e9, 0xebcc}, /* '胩' -> 33001 */
{0x80ea, 0xebcd}, /* '胪' -> 33002 */
{0x80eb, 0xebd6}, /* '胫' -> 33003 */
{0x80ec, 0xe6c0}, /* '胬' -> 33004 */
{0x80ed, 0xebd9}, /* '胭' -> 33005 */
{0x80ef, 0xbfe8}, /* '胯' -> 33007 */
{0x80f0, 0xd2c8}, /* '胰' -> 33008 */
{0x80f1, 0xebd7}, /* '胱' -> 33009 */
{0x80f2, 0xebdc}, /* '胲' -> 33010 */
{0x80f3, 0xb8ec}, /* '胳' -> 33011 */
{0x80f4, 0xebd8}, /* '胴' -> 33012 */
{0x80f6, 0xbdba}, /* '胶' -> 33014 */
{0x80f8, 0xd0d8}, /* '胸' -> 33016 */
{0x80fa, 0xb0b7}, /* '胺' -> 33018 */
{0x80fc, 0xebdd}, /* '胼' -> 33020 */
{0x80fd, 0xc4dc}, /* '能' -> 33021 */
{0x8102, 0xd6ac}, /* '脂' -> 33026 */
{0x8106, 0xb4e0}, /* '脆' -> 33030 */
{0x8109, 0xc2f6}, /* '脉' -> 33033 */
{0x810a, 0xbcb9}, /* '脊' -> 33034 */
{0x810d, 0xebda}, /* '脍' -> 33037 */
{0x810e, 0xebdb}, /* '脎' -> 33038 */
{0x810f, 0xd4e0}, /* '脏' -> 33039 */
{0x8110, 0xc6ea}, /* '脐' -> 33040 */
{0x8111, 0xc4d4}, /* '脑' -> 33041 */
{0x8112, 0xebdf}, /* '脒' -> 33042 */
{0x8113, 0xc5a7}, /* '脓' -> 33043 */
{0x8114, 0xd9f5}, /* '脔' -> 33044 */
{0x8116, 0xb2b1}, /* '脖' -> 33046 */
{0x8118, 0xebe4}, /* '脘' -> 33048 */
{0x811a, 0xbdc5}, /* '脚' -> 33050 */
{0x811e, 0xebe2}, /* '脞' -> 33054 */
{0x812c, 0xebe3}, /* '脬' -> 33068 */
{0x812f, 0xb8ac}, /* '脯' -> 33071 */
{0x8131, 0xcdd1}, /* '脱' -> 33073 */
{0x8132, 0xebe5}, /* '脲' -> 33074 */
{0x8136, 0xebe1}, /* '脶' -> 33078 */
{0x8138, 0xc1b3}, /* '脸' -> 33080 */
{0x813e, 0xc6a2}, /* '脾' -> 33086 */
{0x8146, 0xccf3}, /* '腆' -> 33094 */
{0x8148, 0xebe6}, /* '腈' -> 33096 */
{0x814a, 0xc0b0}, /* '腊' -> 33098 */
{0x814b, 0xd2b8}, /* '腋' -> 33099 */
{0x814c, 0xebe7}, /* '腌' -> 33100 */
{0x8150, 0xb8af}, /* '腐' -> 33104 */
{0x8151, 0xb8ad}, /* '腑' -> 33105 */
{0x8153, 0xebe8}, /* '腓' -> 33107 */
{0x8154, 0xc7bb}, /* '腔' -> 33108 */
{0x8155, 0xcdf3}, /* '腕' -> 33109 */
{0x8159, 0xebea}, /* '腙' -> 33113 */
{0x815a, 0xebeb}, /* '腚' -> 33114 */
{0x8160, 0xebed}, /* '腠' -> 33120 */
{0x8165, 0xd0c8}, /* '腥' -> 33125 */
{0x8167, 0xebf2}, /* '腧' -> 33127 */
{0x8169, 0xebee}, /* '腩' -> 33129 */
{0x816d, 0xebf1}, /* '腭' -> 33133 */
{0x816e, 0xc8f9}, /* '腮' -> 33134 */
{0x8170, 0xd1fc}, /* '腰' -> 33136 */
{0x8171, 0xebec}, /* '腱' -> 33137 */
{0x8174, 0xebe9}, /* '腴' -> 33140 */
{0x8179, 0xb8b9}, /* '腹' -> 33145 */
{0x817a, 0xcfd9}, /* '腺' -> 33146 */
{0x817b, 0xc4e5}, /* '腻' -> 33147 */
{0x817c, 0xebef}, /* '腼' -> 33148 */
{0x817d, 0xebf0}, /* '腽' -> 33149 */
{0x817e, 0xccda}, /* '腾' -> 33150 */
{0x817f, 0xcdc8}, /* '腿' -> 33151 */
{0x8180, 0xb0f2}, /* '膀' -> 33152 */
{0x8182, 0xebf6}, /* '膂' -> 33154 */
{0x8188, 0xebf5}, /* '膈' -> 33160 */
{0x818a, 0xb2b2}, /* '膊' -> 33162 */
{0x818f, 0xb8e0}, /* '膏' -> 33167 */
{0x8191, 0xebf7}, /* '膑' -> 33169 */
{0x8198, 0xb1ec}, /* '膘' -> 33176 */
{0x819b, 0xccc5}, /* '膛' -> 33179 */
{0x819c, 0xc4a4}, /* '膜' -> 33180 */
{0x819d, 0xcfa5}, /* '膝' -> 33181 */
{0x81a3, 0xebf9}, /* '膣' -> 33187 */
{0x81a6, 0xeca2}, /* '膦' -> 33190 */
{0x81a8, 0xc5f2}, /* '膨' -> 33192 */
{0x81aa, 0xebfa}, /* '膪' -> 33194 */
{0x81b3, 0xc9c5}, /* '膳' -> 33203 */
{0x81ba, 0xe2df}, /* '膺' -> 33210 */
{0x81bb, 0xebfe}, /* '膻' -> 33211 */
{0x81c0, 0xcdce}, /* '臀' -> 33216 */
{0x81c1, 0xeca1}, /* '臁' -> 33217 */
{0x81c2, 0xb1db}, /* '臂' -> 33218 */
{0x81c3, 0xd3b7}, /* '臃' -> 33219 */
{0x81c6, 0xd2dc}, /* '臆' -> 33222 */
{0x81ca, 0xebfd}, /* '臊' -> 33226 */
{0x81cc, 0xebfb}, /* '臌' -> 33228 */
{0x81e3, 0xb3bc}, /* '臣' -> 33251 */
{0x81e7, 0xeab0}, /* '臧' -> 33255 */
{0x81ea, 0xd7d4}, /* '自' -> 33258 */
{0x81ec, 0xf4ab}, /* '臬' -> 33260 */
{0x81ed, 0xb3f4}, /* '臭' -> 33261 */
{0x81f3, 0xd6c1}, /* '至' -> 33267 */
{0x81f4, 0xd6c2}, /* '致' -> 33268 */
{0x81fb, 0xd5e9}, /* '臻' -> 33275 */
{0x81fc, 0xbeca}, /* '臼' -> 33276 */
{0x81fe, 0xf4a7}, /* '臾' -> 33278 */
{0x8200, 0xd2a8}, /* '舀' -> 33280 */
{0x8201, 0xf4a8}, /* '舁' -> 33281 */
{0x8202, 0xf4a9}, /* '舂' -> 33282 */
{0x8204, 0xf4aa}, /* '舄' -> 33284 */
{0x8205, 0xbecb}, /* '舅' -> 33285 */
{0x8206, 0xd3df}, /* '舆' -> 33286 */
{0x820c, 0xc9e0}, /* '舌' -> 33292 */
{0x820d, 0xc9e1}, /* '舍' -> 33293 */
{0x8210, 0xf3c2}, /* '舐' -> 33296 */
{0x8212, 0xcae6}, /* '舒' -> 33298 */
{0x8214, 0xccf2}, /* '舔' -> 33300 */
{0x821b, 0xe2b6}, /* '舛' -> 33307 */
{0x821c, 0xcbb4}, /* '舜' -> 33308 */
{0x821e, 0xcee8}, /* '舞' -> 33310 */
{0x821f, 0xd6db}, /* '舟' -> 33311 */
{0x8221, 0xf4ad}, /* '舡' -> 33313 */
{0x8222, 0xf4ae}, /* '舢' -> 33314 */
{0x8223, 0xf4af}, /* '舣' -> 33315 */
{0x8228, 0xf4b2}, /* '舨' -> 33320 */
{0x822a, 0xbabd}, /* '航' -> 33322 */
{0x822b, 0xf4b3}, /* '舫' -> 33323 */
{0x822c, 0xb0e3}, /* '般' -> 33324 */
{0x822d, 0xf4b0}, /* '舭' -> 33325 */
{0x822f, 0xf4b1}, /* '舯' -> 33327 */
{0x8230, 0xbda2}, /* '舰' -> 33328 */
{0x8231, 0xb2d5}, /* '舱' -> 33329 */
{0x8233, 0xf4b6}, /* '舳' -> 33331 */
{0x8234, 0xf4b7}, /* '舴' -> 33332 */
{0x8235, 0xb6e6}, /* '舵' -> 33333 */
{0x8236, 0xb2b0}, /* '舶' -> 33334 */
{0x8237, 0xcfcf}, /* '舷' -> 33335 */
{0x8238, 0xf4b4}, /* '舸' -> 33336 */
{0x8239, 0xb4ac}, /* '船' -> 33337 */
{0x823b, 0xf4b5}, /* '舻' -> 33339 */
{0x823e, 0xf4b8}, /* '舾' -> 33342 */
{0x8244, 0xf4b9}, /* '艄' -> 33348 */
{0x8247, 0xcda7}, /* '艇' -> 33351 */
{0x8249, 0xf4ba}, /* '艉' -> 33353 */
{0x824b, 0xf4bb}, /* '艋' -> 33355 */
{0x824f, 0xf4bc}, /* '艏' -> 33359 */
{0x8258, 0xcbd2}, /* '艘' -> 33368 */
{0x825a, 0xf4bd}, /* '艚' -> 33370 */
{0x825f, 0xf4be}, /* '艟' -> 33375 */
{0x8268, 0xf4bf}, /* '艨' -> 33384 */
{0x826e, 0xf4de}, /* '艮' -> 33390 */
{0x826f, 0xc1bc}, /* '良' -> 33391 */
{0x8270, 0xbce8}, /* '艰' -> 33392 */
{0x8272, 0xc9ab}, /* '色' -> 33394 */
{0x8273, 0xd1de}, /* '艳' -> 33395 */
{0x8274, 0xe5f5}, /* '艴' -> 33396 */
{0x8279, 0xdcb3}, /* '艹' -> 33401 */
{0x827a, 0xd2d5}, /* '艺' -> 33402 */
{0x827d, 0xdcb4}, /* '艽' -> 33405 */
{0x827e, 0xb0ac}, /* '艾' -> 33406 */
{0x827f, 0xdcb5}, /* '艿' -> 33407 */
{0x8282, 0xbdda}, /* '节' -> 33410 */
{0x8284, 0xdcb9}, /* '芄' -> 33412 */
{0x8288, 0xd8c2}, /* '芈' -> 33416 */
{0x828a, 0xdcb7}, /* '芊' -> 33418 */
{0x828b, 0xd3f3}, /* '芋' -> 33419 */
{0x828d, 0xc9d6}, /* '芍' -> 33421 */
{0x828e, 0xdcba}, /* '芎' -> 33422 */
{0x828f, 0xdcb6}, /* '芏' -> 33423 */
{0x8291, 0xdcbb}, /* '芑' -> 33425 */
{0x8292, 0xc3a2}, /* '芒' -> 33426 */
{0x8297, 0xdcbc}, /* '芗' -> 33431 */
{0x8298, 0xdcc5}, /* '芘' -> 33432 */
{0x8299, 0xdcbd}, /* '芙' -> 33433 */
{0x829c, 0xcedf}, /* '芜' -> 33436 */
{0x829d, 0xd6a5}, /* '芝' -> 33437 */
{0x829f, 0xdccf}, /* '芟' -> 33439 */
{0x82a1, 0xdccd}, /* '芡' -> 33441 */
{0x82a4, 0xdcd2}, /* '芤' -> 33444 */
{0x82a5, 0xbde6}, /* '芥' -> 33445 */
{0x82a6, 0xc2ab}, /* '芦' -> 33446 */
{0x82a8, 0xdcb8}, /* '芨' -> 33448 */
{0x82a9, 0xdccb}, /* '芩' -> 33449 */
{0x82aa, 0xdcce}, /* '芪' -> 33450 */
{0x82ab, 0xdcbe}, /* '芫' -> 33451 */
{0x82ac, 0xb7d2}, /* '芬' -> 33452 */
{0x82ad, 0xb0c5}, /* '芭' -> 33453 */
{0x82ae, 0xdcc7}, /* '芮' -> 33454 */
{0x82af, 0xd0be}, /* '芯' -> 33455 */
{0x82b0, 0xdcc1}, /* '芰' -> 33456 */
{0x82b1, 0xbba8}, /* '花' -> 33457 */
{0x82b3, 0xb7bc}, /* '芳' -> 33459 */
{0x82b4, 0xdccc}, /* '芴' -> 33460 */
{0x82b7, 0xdcc6}, /* '芷' -> 33463 */
{0x82b8, 0xdcbf}, /* '芸' -> 33464 */
{0x82b9, 0xc7db}, /* '芹' -> 33465 */
{0x82bd, 0xd1bf}, /* '芽' -> 33469 */
{0x82be, 0xdcc0}, /* '芾' -> 33470 */
{0x82c1, 0xdcca}, /* '苁' -> 33473 */
{0x82c4, 0xdcd0}, /* '苄' -> 33476 */
{0x82c7, 0xcead}, /* '苇' -> 33479 */
{0x82c8, 0xdcc2}, /* '苈' -> 33480 */
{0x82ca, 0xdcc3}, /* '苊' -> 33482 */
{0x82cb, 0xdcc8}, /* '苋' -> 33483 */
{0x82cc, 0xdcc9}, /* '苌' -> 33484 */
{0x82cd, 0xb2d4}, /* '苍' -> 33485 */
{0x82ce, 0xdcd1}, /* '苎' -> 33486 */
{0x82cf, 0xcbd5}, /* '苏' -> 33487 */
{0x82d1, 0xd4b7}, /* '苑' -> 33489 */
{0x82d2, 0xdcdb}, /* '苒' -> 33490 */
{0x82d3, 0xdcdf}, /* '苓' -> 33491 */
{0x82d4, 0xcca6}, /* '苔' -> 33492 */
{0x82d5, 0xdce6}, /* '苕' -> 33493 */
{0x82d7, 0xc3e7}, /* '苗' -> 33495 */
{0x82d8, 0xdcdc}, /* '苘' -> 33496 */
{0x82db, 0xbfc1}, /* '苛' -> 33499 */
{0x82dc, 0xdcd9}, /* '苜' -> 33500 */
{0x82de, 0xb0fa}, /* '苞' -> 33502 */
{0x82df, 0xb9b6}, /* '苟' -> 33503 */
{0x82e0, 0xdce5}, /* '苠' -> 33504 */
{0x82e1, 0xdcd3}, /* '苡' -> 33505 */
{0x82e3, 0xdcc4}, /* '苣' -> 33507 */
{0x82e4, 0xdcd6}, /* '苤' -> 33508 */
{0x82e5, 0xc8f4}, /* '若' -> 33509 */
{0x82e6, 0xbfe0}, /* '苦' -> 33510 */
{0x82eb, 0xc9bb}, /* '苫' -> 33515 */
{0x82ef, 0xb1bd}, /* '苯' -> 33519 */
{0x82f1, 0xd3a2}, /* '英' -> 33521 */
{0x82f4, 0xdcda}, /* '苴' -> 33524 */
{0x82f7, 0xdcd5}, /* '苷' -> 33527 */
{0x82f9, 0xc6bb}, /* '苹' -> 33529 */
{0x82fb, 0xdcde}, /* '苻' -> 33531 */
{0x8301, 0xd7c2}, /* '茁' -> 33537 */
{0x8302, 0xc3af}, /* '茂' -> 33538 */
{0x8303, 0xb7b6}, /* '范' -> 33539 */
{0x8304, 0xc7d1}, /* '茄' -> 33540 */
{0x8305, 0xc3a9}, /* '茅' -> 33541 */
{0x8306, 0xdce2}, /* '茆' -> 33542 */
{0x8307, 0xdcd8}, /* '茇' -> 33543 */
{0x8308, 0xdceb}, /* '茈' -> 33544 */
{0x8309, 0xdcd4}, /* '茉' -> 33545 */
{0x830c, 0xdcdd}, /* '茌' -> 33548 */
{0x830e, 0xbea5}, /* '茎' -> 33550 */
{0x830f, 0xdcd7}, /* '茏' -> 33551 */
{0x8311, 0xdce0}, /* '茑' -> 33553 */
{0x8314, 0xdce3}, /* '茔' -> 33556 */
{0x8315, 0xdce4}, /* '茕' -> 33557 */
{0x8317, 0xdcf8}, /* '茗' -> 33559 */
{0x831a, 0xdce1}, /* '茚' -> 33562 */
{0x831b, 0xdda2}, /* '茛' -> 33563 */
{0x831c, 0xdce7}, /* '茜' -> 33564 */
{0x8327, 0xbceb}, /* '茧' -> 33575 */
{0x8328, 0xb4c4}, /* '茨' -> 33576 */
{0x832b, 0xc3a3}, /* '茫' -> 33579 */
{0x832c, 0xb2e7}, /* '茬' -> 33580 */
{0x832d, 0xdcfa}, /* '茭' -> 33581 */
{0x832f, 0xdcf2}, /* '茯' -> 33583 */
{0x8331, 0xdcef}, /* '茱' -> 33585 */
{0x8333, 0xdcfc}, /* '茳' -> 33587 */
{0x8334, 0xdcee}, /* '茴' -> 33588 */
{0x8335, 0xd2f0}, /* '茵' -> 33589 */
{0x8336, 0xb2e8}, /* '茶' -> 33590 */
{0x8338, 0xc8d7}, /* '茸' -> 33592 */
{0x8339, 0xc8e3}, /* '茹' -> 33593 */
{0x833a, 0xdcfb}, /* '茺' -> 33594 */
{0x833c, 0xdced}, /* '茼' -> 33596 */
{0x8340, 0xdcf7}, /* '荀' -> 33600 */
{0x8343, 0xdcf5}, /* '荃' -> 33603 */
{0x8346, 0xbea3}, /* '荆' -> 33606 */
{0x8347, 0xdcf4}, /* '荇' -> 33607 */
{0x8349, 0xb2dd}, /* '草' -> 33609 */
{0x834f, 0xdcf3}, /* '荏' -> 33615 */
{0x8350, 0xbcf6}, /* '荐' -> 33616 */
{0x8351, 0xdce8}, /* '荑' -> 33617 */
{0x8352, 0xbbc4}, /* '荒' -> 33618 */
{0x8354, 0xc0f3}, /* '荔' -> 33620 */
{0x835a, 0xbcd4}, /* '荚' -> 33626 */
{0x835b, 0xdce9}, /* '荛' -> 33627 */
{0x835c, 0xdcea}, /* '荜' -> 33628 */
{0x835e, 0xdcf1}, /* '荞' -> 33630 */
{0x835f, 0xdcf6}, /* '荟' -> 33631 */
{0x8360, 0xdcf9}, /* '荠' -> 33632 */
{0x8361, 0xb5b4}, /* '荡' -> 33633 */
{0x8363, 0xc8d9}, /* '荣' -> 33635 */
{0x8364, 0xbbe7}, /* '荤' -> 33636 */
{0x8365, 0xdcfe}, /* '荥' -> 33637 */
{0x8366, 0xdcfd}, /* '荦' -> 33638 */
{0x8367, 0xd3ab}, /* '荧' -> 33639 */
{0x8368, 0xdda1}, /* '荨' -> 33640 */
{0x8369, 0xdda3}, /* '荩' -> 33641 */
{0x836a, 0xdda5}, /* '荪' -> 33642 */
{0x836b, 0xd2f1}, /* '荫' -> 33643 */
{0x836c, 0xdda4}, /* '荬' -> 33644 */
{0x836d, 0xdda6}, /* '荭' -> 33645 */
{0x836e, 0xdda7}, /* '荮' -> 33646 */
{0x836f, 0xd2a9}, /* '药' -> 33647 */
{0x8377, 0xbac9}, /* '荷' -> 33655 */
{0x8378, 0xdda9}, /* '荸' -> 33656 */
{0x837b, 0xddb6}, /* '荻' -> 33659 */
{0x837c, 0xddb1}, /* '荼' -> 33660 */
{0x837d, 0xddb4}, /* '荽' -> 33661 */
{0x8385, 0xddb0}, /* '莅' -> 33669 */
{0x8386, 0xc6ce}, /* '莆' -> 33670 */
{0x8389, 0xc0f2}, /* '莉' -> 33673 */
{0x838e, 0xc9af}, /* '莎' -> 33678 */
{0x8392, 0xdcec}, /* '莒' -> 33682 */
{0x8393, 0xddae}, /* '莓' -> 33683 */
{0x8398, 0xddb7}, /* '莘' -> 33688 */
{0x839b, 0xdcf0}, /* '莛' -> 33691 */
{0x839c, 0xddaf}, /* '莜' -> 33692 */
{0x839e, 0xddb8}, /* '莞' -> 33694 */
{0x83a0, 0xddac}, /* '莠' -> 33696 */
{0x83a8, 0xddb9}, /* '莨' -> 33704 */
{0x83a9, 0xddb3}, /* '莩' -> 33705 */
{0x83aa, 0xddad}, /* '莪' -> 33706 */
{0x83ab, 0xc4aa}, /* '莫' -> 33707 */
{0x83b0, 0xdda8}, /* '莰' -> 33712 */
{0x83b1, 0xc0b3}, /* '莱' -> 33713 */
{0x83b2, 0xc1ab}, /* '莲' -> 33714 */
{0x83b3, 0xddaa}, /* '莳' -> 33715 */
{0x83b4, 0xddab}, /* '莴' -> 33716 */
{0x83b6, 0xddb2}, /* '莶' -> 33718 */
{0x83b7, 0xbbf1}, /* '获' -> 33719 */
{0x83b8, 0xddb5}, /* '莸' -> 33720 */
{0x83b9, 0xd3a8}, /* '莹' -> 33721 */
{0x83ba, 0xddba}, /* '莺' -> 33722 */
{0x83bc, 0xddbb}, /* '莼' -> 33724 */
{0x83bd, 0xc3a7}, /* '莽' -> 33725 */
{0x83c0, 0xddd2}, /* '菀' -> 33728 */
{0x83c1, 0xddbc}, /* '菁' -> 33729 */
{0x83c5, 0xddd1}, /* '菅' -> 33733 */
{0x83c7, 0xb9bd}, /* '菇' -> 33735 */
{0x83ca, 0xbed5}, /* '菊' -> 33738 */
{0x83cc, 0xbefa}, /* '菌' -> 33740 */
{0x83cf, 0xbaca}, /* '菏' -> 33743 */
{0x83d4, 0xddca}, /* '菔' -> 33748 */
{0x83d6, 0xddc5}, /* '菖' -> 33750 */
{0x83d8, 0xddbf}, /* '菘' -> 33752 */
{0x83dc, 0xb2cb}, /* '菜' -> 33756 */
{0x83dd, 0xddc3}, /* '菝' -> 33757 */
{0x83df, 0xddcb}, /* '菟' -> 33759 */
{0x83e0, 0xb2a4}, /* '菠' -> 33760 */
{0x83e1, 0xddd5}, /* '菡' -> 33761 */
{0x83e5, 0xddbe}, /* '菥' -> 33765 */
{0x83e9, 0xc6d0}, /* '菩' -> 33769 */
{0x83ea, 0xddd0}, /* '菪' -> 33770 */
{0x83f0, 0xddd4}, /* '菰' -> 33776 */
{0x83f1, 0xc1e2}, /* '菱' -> 33777 */
{0x83f2, 0xb7c6}, /* '菲' -> 33778 */
{0x83f8, 0xddce}, /* '菸' -> 33784 */
{0x83f9, 0xddcf}, /* '菹' -> 33785 */
{0x83fd, 0xddc4}, /* '菽' -> 33789 */
{0x8401, 0xddbd}, /* '萁' -> 33793 */
{0x8403, 0xddcd}, /* '萃' -> 33795 */
{0x8404, 0xccd1}, /* '萄' -> 33796 */
{0x8406, 0xddc9}, /* '萆' -> 33798 */
{0x840b, 0xddc2}, /* '萋' -> 33803 */
{0x840c, 0xc3c8}, /* '萌' -> 33804 */
{0x840d, 0xc6bc}, /* '萍' -> 33805 */
{0x840e, 0xceae}, /* '萎' -> 33806 */
{0x840f, 0xddcc}, /* '萏' -> 33807 */
{0x8411, 0xddc8}, /* '萑' -> 33809 */
{0x8418, 0xddc1}, /* '萘' -> 33816 */
{0x841c, 0xddc6}, /* '萜' -> 33820 */
{0x841d, 0xc2dc}, /* '萝' -> 33821 */
{0x8424, 0xd3a9}, /* '萤' -> 33828 */
{0x8425, 0xd3aa}, /* '营' -> 33829 */
{0x8426, 0xddd3}, /* '萦' -> 33830 */
{0x8427, 0xcff4}, /* '萧' -> 33831 */
{0x8428, 0xc8f8}, /* '萨' -> 33832 */
{0x8431, 0xdde6}, /* '萱' -> 33841 */
{0x8438, 0xddc7}, /* '萸' -> 33848 */
{0x843c, 0xdde0}, /* '萼' -> 33852 */
{0x843d, 0xc2e4}, /* '落' -> 33853 */
{0x8446, 0xdde1}, /* '葆' -> 33862 */
{0x8451, 0xddd7}, /* '葑' -> 33873 */
{0x8457, 0xd6f8}, /* '著' -> 33879 */
{0x8459, 0xddd9}, /* '葙' -> 33881 */
{0x845a, 0xddd8}, /* '葚' -> 33882 */
{0x845b, 0xb8f0}, /* '葛' -> 33883 */
{0x845c, 0xddd6}, /* '葜' -> 33884 */
{0x8461, 0xc6cf}, /* '葡' -> 33889 */
{0x8463, 0xb6ad}, /* '董' -> 33891 */
{0x8469, 0xdde2}, /* '葩' -> 33897 */
{0x846b, 0xbaf9}, /* '葫' -> 33899 */
{0x846c, 0xd4e1}, /* '葬' -> 33900 */
{0x846d, 0xdde7}, /* '葭' -> 33901 */
{0x8471, 0xb4d0}, /* '葱' -> 33905 */
{0x8473, 0xddda}, /* '葳' -> 33907 */
{0x8475, 0xbffb}, /* '葵' -> 33909 */
{0x8476, 0xdde3}, /* '葶' -> 33910 */
{0x8478, 0xdddf}, /* '葸' -> 33912 */
{0x847a, 0xdddd}, /* '葺' -> 33914 */
{0x8482, 0xb5d9}, /* '蒂' -> 33922 */
{0x8487, 0xdddb}, /* '蒇' -> 33927 */
{0x8488, 0xdddc}, /* '蒈' -> 33928 */
{0x8489, 0xddde}, /* '蒉' -> 33929 */
{0x848b, 0xbdaf}, /* '蒋' -> 33931 */
{0x848c, 0xdde4}, /* '蒌' -> 33932 */
{0x848e, 0xdde5}, /* '蒎' -> 33934 */
{0x8497, 0xddf5}, /* '蒗' -> 33943 */
{0x8499, 0xc3c9}, /* '蒙' -> 33945 */
{0x849c, 0xcbe2}, /* '蒜' -> 33948 */
{0x84a1, 0xddf2}, /* '蒡' -> 33953 */
{0x84af, 0xd8e1}, /* '蒯' -> 33967 */
{0x84b2, 0xc6d1}, /* '蒲' -> 33970 */
{0x84b4, 0xddf4}, /* '蒴' -> 33972 */
{0x84b8, 0xd5f4}, /* '蒸' -> 33976 */
{0x84b9, 0xddf3}, /* '蒹' -> 33977 */
{0x84ba, 0xddf0}, /* '蒺' -> 33978 */
{0x84bd, 0xddec}, /* '蒽' -> 33981 */
{0x84bf, 0xddef}, /* '蒿' -> 33983 */
{0x84c1, 0xdde8}, /* '蓁' -> 33985 */
{0x84c4, 0xd0ee}, /* '蓄' -> 33988 */
{0x84c9, 0xc8d8}, /* '蓉' -> 33993 */
{0x84ca, 0xddee}, /* '蓊' -> 33994 */
{0x84cd, 0xdde9}, /* '蓍' -> 33997 */
{0x84d0, 0xddea}, /* '蓐' -> 34000 */
{0x84d1, 0xcbf2}, /* '蓑' -> 34001 */
{0x84d3, 0xdded}, /* '蓓' -> 34003 */
{0x84d6, 0xb1cd}, /* '蓖' -> 34006 */
{0x84dd, 0xc0b6}, /* '蓝' -> 34013 */
{0x84df, 0xbcbb}, /* '蓟' -> 34015 */
{0x84e0, 0xddf1}, /* '蓠' -> 34016 */
{0x84e3, 0xddf7}, /* '蓣' -> 34019 */
{0x84e5, 0xddf6}, /* '蓥' -> 34021 */
{0x84e6, 0xddeb}, /* '蓦' -> 34022 */
{0x84ec, 0xc5ee}, /* '蓬' -> 34028 */
{0x84f0, 0xddfb}, /* '蓰' -> 34032 */
{0x84fc, 0xdea4}, /* '蓼' -> 34044 */
{0x84ff, 0xdea3}, /* '蓿' -> 34047 */
{0x850c, 0xddf8}, /* '蔌' -> 34060 */
{0x8511, 0xc3ef}, /* '蔑' -> 34065 */
{0x8513, 0xc2fb}, /* '蔓' -> 34067 */
{0x8517, 0xd5e1}, /* '蔗' -> 34071 */
{0x851a, 0xceb5}, /* '蔚' -> 34074 */
{0x851f, 0xddfd}, /* '蔟' -> 34079 */
{0x8521, 0xb2cc}, /* '蔡' -> 34081 */
{0x852b, 0xc4e8}, /* '蔫' -> 34091 */
{0x852c, 0xcadf}, /* '蔬' -> 34092 */
{0x8537, 0xc7be}, /* '蔷' -> 34103 */
{0x8538, 0xddfa}, /* '蔸' -> 34104 */
{0x8539, 0xddfc}, /* '蔹' -> 34105 */
{0x853a, 0xddfe}, /* '蔺' -> 34106 */
{0x853b, 0xdea2}, /* '蔻' -> 34107 */
{0x853c, 0xb0aa}, /* '蔼' -> 34108 */
{0x853d, 0xb1ce}, /* '蔽' -> 34109 */
{0x8543, 0xdeac}, /* '蕃' -> 34115 */
{0x8548, 0xdea6}, /* '蕈' -> 34120 */
{0x8549, 0xbdb6}, /* '蕉' -> 34121 */
{0x854a, 0xc8ef}, /* '蕊' -> 34122 */
{0x8556, 0xdea1}, /* '蕖' -> 34134 */
{0x8559, 0xdea5}, /* '蕙' -> 34137 */
{0x855e, 0xdea9}, /* '蕞' -> 34142 */
{0x8564, 0xdea8}, /* '蕤' -> 34148 */
{0x8568, 0xdea7}, /* '蕨' -> 34152 */
{0x8572, 0xdead}, /* '蕲' -> 34162 */
{0x8574, 0xd4cc}, /* '蕴' -> 34164 */
{0x8579, 0xdeb3}, /* '蕹' -> 34169 */
{0x857a, 0xdeaa}, /* '蕺' -> 34170 */
{0x857b, 0xdeae}, /* '蕻' -> 34171 */
{0x857e, 0xc0d9}, /* '蕾' -> 34174 */
{0x8584, 0xb1a1}, /* '薄' -> 34180 */
{0x8585, 0xdeb6}, /* '薅' -> 34181 */
{0x8587, 0xdeb1}, /* '薇' -> 34183 */
{0x858f, 0xdeb2}, /* '薏' -> 34191 */
{0x859b, 0xd1a6}, /* '薛' -> 34203 */
{0x859c, 0xdeb5}, /* '薜' -> 34204 */
{0x85a4, 0xdeaf}, /* '薤' -> 34212 */
{0x85a8, 0xdeb0}, /* '薨' -> 34216 */
{0x85aa, 0xd0bd}, /* '薪' -> 34218 */
{0x85ae, 0xdeb4}, /* '薮' -> 34222 */
{0x85af, 0xcaed}, /* '薯' -> 34223 */
{0x85b0, 0xdeb9}, /* '薰' -> 34224 */
{0x85b7, 0xdeb8}, /* '薷' -> 34231 */
{0x85b9, 0xdeb7}, /* '薹' -> 34233 */
{0x85c1, 0xdebb}, /* '藁' -> 34241 */
{0x85c9, 0xbde5}, /* '藉' -> 34249 */
{0x85cf, 0xb2d8}, /* '藏' -> 34255 */
{0x85d0, 0xc3ea}, /* '藐' -> 34256 */
{0x85d3, 0xdeba}, /* '藓' -> 34259 */
{0x85d5, 0xc5ba}, /* '藕' -> 34261 */
{0x85dc, 0xdebc}, /* '藜' -> 34268 */
{0x85e4, 0xccd9}, /* '藤' -> 34276 */
{0x85e9, 0xb7aa}, /* '藩' -> 34281 */
{0x85fb, 0xd4e5}, /* '藻' -> 34299 */
{0x85ff, 0xdebd}, /* '藿' -> 34303 */
{0x8605, 0xdebf}, /* '蘅' -> 34309 */
{0x8611, 0xc4a2}, /* '蘑' -> 34321 */
{0x8616, 0xdec1}, /* '蘖' -> 34326 */
{0x8627, 0xdebe}, /* '蘧' -> 34343 */
{0x8629, 0xdec0}, /* '蘩' -> 34345 */
{0x8638, 0xd5ba}, /* '蘸' -> 34360 */
{0x863c, 0xdec2}, /* '蘼' -> 34364 */
{0x864d, 0xf2ae}, /* '虍' -> 34381 */
{0x864e, 0xbba2}, /* '虎' -> 34382 */
{0x864f, 0xc2b2}, /* '虏' -> 34383 */
{0x8650, 0xc5b0}, /* '虐' -> 34384 */
{0x8651, 0xc2c7}, /* '虑' -> 34385 */
{0x8654, 0xf2af}, /* '虔' -> 34388 */
{0x865a, 0xd0e9}, /* '虚' -> 34394 */
{0x865e, 0xd3dd}, /* '虞' -> 34398 */
{0x8662, 0xebbd}, /* '虢' -> 34402 */
{0x866b, 0xb3e6}, /* '虫' -> 34411 */
{0x866c, 0xf2b0}, /* '虬' -> 34412 */
{0x866e, 0xf2b1}, /* '虮' -> 34414 */
{0x8671, 0xcaad}, /* '虱' -> 34417 */
{0x8679, 0xbae7}, /* '虹' -> 34425 */
{0x867a, 0xf2b3}, /* '虺' -> 34426 */
{0x867b, 0xf2b5}, /* '虻' -> 34427 */
{0x867c, 0xf2b4}, /* '虼' -> 34428 */
{0x867d, 0xcbe4}, /* '虽' -> 34429 */
{0x867e, 0xcfba}, /* '虾' -> 34430 */
{0x867f, 0xf2b2}, /* '虿' -> 34431 */
{0x8680, 0xcab4}, /* '蚀' -> 34432 */
{0x8681, 0xd2cf}, /* '蚁' -> 34433 */
{0x8682, 0xc2ec}, /* '蚂' -> 34434 */
{0x868a, 0xcec3}, /* '蚊' -> 34442 */
{0x868b, 0xf2b8}, /* '蚋' -> 34443 */
{0x868c, 0xb0f6}, /* '蚌' -> 34444 */
{0x868d, 0xf2b7}, /* '蚍' -> 34445 */
{0x8693, 0xf2be}, /* '蚓' -> 34451 */
{0x8695, 0xb2cf}, /* '蚕' -> 34453 */
{0x869c, 0xd1c1}, /* '蚜' -> 34460 */
{0x869d, 0xf2ba}, /* '蚝' -> 34461 */
{0x86a3, 0xf2bc}, /* '蚣' -> 34467 */
{0x86a4, 0xd4e9}, /* '蚤' -> 34468 */
{0x86a7, 0xf2bb}, /* '蚧' -> 34471 */
{0x86a8, 0xf2b6}, /* '蚨' -> 34472 */
{0x86a9, 0xf2bf}, /* '蚩' -> 34473 */
{0x86aa, 0xf2bd}, /* '蚪' -> 34474 */
{0x86ac, 0xf2b9}, /* '蚬' -> 34476 */
{0x86af, 0xf2c7}, /* '蚯' -> 34479 */
{0x86b0, 0xf2c4}, /* '蚰' -> 34480 */
{0x86b1, 0xf2c6}, /* '蚱' -> 34481 */
{0x86b4, 0xf2ca}, /* '蚴' -> 34484 */
{0x86b5, 0xf2c2}, /* '蚵' -> 34485 */
{0x86b6, 0xf2c0}, /* '蚶' -> 34486 */
{0x86ba, 0xf2c5}, /* '蚺' -> 34490 */
{0x86c0, 0xd6fb}, /* '蛀' -> 34496 */
{0x86c4, 0xf2c1}, /* '蛄' -> 34500 */
{0x86c6, 0xc7f9}, /* '蛆' -> 34502 */
{0x86c7, 0xc9df}, /* '蛇' -> 34503 */
{0x86c9, 0xf2c8}, /* '蛉' -> 34505 */
{0x86ca, 0xb9c6}, /* '蛊' -> 34506 */
{0x86cb, 0xb5b0}, /* '蛋' -> 34507 */
{0x86ce, 0xf2c3}, /* '蛎' -> 34510 */
{0x86cf, 0xf2c9}, /* '蛏' -> 34511 */
{0x86d0, 0xf2d0}, /* '蛐' -> 34512 */
{0x86d1, 0xf2d6}, /* '蛑' -> 34513 */
{0x86d4, 0xbbd7}, /* '蛔' -> 34516 */
{0x86d8, 0xf2d5}, /* '蛘' -> 34520 */
{0x86d9, 0xcddc}, /* '蛙' -> 34521 */
{0x86db, 0xd6eb}, /* '蛛' -> 34523 */
{0x86de, 0xf2d2}, /* '蛞' -> 34526 */
{0x86df, 0xf2d4}, /* '蛟' -> 34527 */
{0x86e4, 0xb8f2}, /* '蛤' -> 34532 */
{0x86e9, 0xf2cb}, /* '蛩' -> 34537 */
{0x86ed, 0xf2ce}, /* '蛭' -> 34541 */
{0x86ee, 0xc2f9}, /* '蛮' -> 34542 */
{0x86f0, 0xd5dd}, /* '蛰' -> 34544 */
{0x86f1, 0xf2cc}, /* '蛱' -> 34545 */
{0x86f2, 0xf2cd}, /* '蛲' -> 34546 */
{0x86f3, 0xf2cf}, /* '蛳' -> 34547 */
{0x86f4, 0xf2d3}, /* '蛴' -> 34548 */
{0x86f8, 0xf2d9}, /* '蛸' -> 34552 */
{0x86f9, 0xd3bc}, /* '蛹' -> 34553 */
{0x86fe, 0xb6ea}, /* '蛾' -> 34558 */
{0x8700, 0xcaf1}, /* '蜀' -> 34560 */
{0x8702, 0xb7e4}, /* '蜂' -> 34562 */
{0x8703, 0xf2d7}, /* '蜃' -> 34563 */
{0x8707, 0xf2d8}, /* '蜇' -> 34567 */
{0x8708, 0xf2da}, /* '蜈' -> 34568 */
{0x8709, 0xf2dd}, /* '蜉' -> 34569 */
{0x870a, 0xf2db}, /* '蜊' -> 34570 */
{0x870d, 0xf2dc}, /* '蜍' -> 34573 */
{0x8712, 0xd1d1}, /* '蜒' -> 34578 */
{0x8713, 0xf2d1}, /* '蜓' -> 34579 */
{0x8715, 0xcdc9}, /* '蜕' -> 34581 */
{0x8717, 0xcecf}, /* '蜗' -> 34583 */
{0x8718, 0xd6a9}, /* '蜘' -> 34584 */
{0x871a, 0xf2e3}, /* '蜚' -> 34586 */
{0x871c, 0xc3db}, /* '蜜' -> 34588 */
{0x871e, 0xf2e0}, /* '蜞' -> 34590 */
{0x8721, 0xc0af}, /* '蜡' -> 34593 */
{0x8722, 0xf2ec}, /* '蜢' -> 34594 */
{0x8723, 0xf2de}, /* '蜣' -> 34595 */
{0x8725, 0xf2e1}, /* '蜥' -> 34597 */
{0x8729, 0xf2e8}, /* '蜩' -> 34601 */
{0x872e, 0xf2e2}, /* '蜮' -> 34606 */
{0x8731, 0xf2e7}, /* '蜱' -> 34609 */
{0x8734, 0xf2e6}, /* '蜴' -> 34612 */
{0x8737, 0xf2e9}, /* '蜷' -> 34615 */
{0x873b, 0xf2df}, /* '蜻' -> 34619 */
{0x873e, 0xf2e4}, /* '蜾' -> 34622 */
{0x873f, 0xf2ea}, /* '蜿' -> 34623 */
{0x8747, 0xd3ac}, /* '蝇' -> 34631 */
{0x8748, 0xf2e5}, /* '蝈' -> 34632 */
{0x8749, 0xb2f5}, /* '蝉' -> 34633 */
{0x874c, 0xf2f2}, /* '蝌' -> 34636 */
{0x874e, 0xd0ab}, /* '蝎' -> 34638 */
{0x8753, 0xf2f5}, /* '蝓' -> 34643 */
{0x8757, 0xbbc8}, /* '蝗' -> 34647 */
{0x8759, 0xf2f9}, /* '蝙' -> 34649 */
{0x8760, 0xf2f0}, /* '蝠' -> 34656 */
{0x8763, 0xf2f6}, /* '蝣' -> 34659 */
{0x8764, 0xf2f8}, /* '蝤' -> 34660 */
{0x8765, 0xf2fa}, /* '蝥' -> 34661 */
{0x876e, 0xf2f3}, /* '蝮' -> 34670 */
{0x8770, 0xf2f1}, /* '蝰' -> 34672 */
{0x8774, 0xbafb}, /* '蝴' -> 34676 */
{0x8776, 0xb5fb}, /* '蝶' -> 34678 */
{0x877b, 0xf2ef}, /* '蝻' -> 34683 */
{0x877c, 0xf2f7}, /* '蝼' -> 34684 */
{0x877d, 0xf2ed}, /* '蝽' -> 34685 */
{0x877e, 0xf2ee}, /* '蝾' -> 34686 */
{0x8782, 0xf2eb}, /* '螂' -> 34690 */
{0x8783, 0xf3a6}, /* '螃' -> 34691 */
{0x8785, 0xf3a3}, /* '螅' -> 34693 */
{0x8788, 0xf3a2}, /* '螈' -> 34696 */
{0x878b, 0xf2f4}, /* '螋' -> 34699 */
{0x878d, 0xc8da}, /* '融' -> 34701 */
{0x8793, 0xf2fb}, /* '螓' -> 34707 */
{0x8797, 0xf3a5}, /* '螗' -> 34711 */
{0x879f, 0xc3f8}, /* '螟' -> 34719 */
{0x87a8, 0xf2fd}, /* '螨' -> 34728 */
{0x87ab, 0xf3a7}, /* '螫' -> 34731 */
{0x87ac, 0xf3a9}, /* '螬' -> 34732 */
{0x87ad, 0xf3a4}, /* '螭' -> 34733 */
{0x87af, 0xf2fc}, /* '螯' -> 34735 */
{0x87b3, 0xf3ab}, /* '螳' -> 34739 */
{0x87b5, 0xf3aa}, /* '螵' -> 34741 */
{0x87ba, 0xc2dd}, /* '螺' -> 34746 */
{0x87bd, 0xf3ae}, /* '螽' -> 34749 */
{0x87c0, 0xf3b0}, /* '蟀' -> 34752 */
{0x87c6, 0xf3a1}, /* '蟆' -> 34758 */
{0x87ca, 0xf3b1}, /* '蟊' -> 34762 */
{0x87cb, 0xf3ac}, /* '蟋' -> 34763 */
{0x87d1, 0xf3af}, /* '蟑' -> 34769 */
{0x87d2, 0xf2fe}, /* '蟒' -> 34770 */
{0x87d3, 0xf3ad}, /* '蟓' -> 34771 */
{0x87db, 0xf3b2}, /* '蟛' -> 34779 */
{0x87e0, 0xf3b4}, /* '蟠' -> 34784 */
{0x87e5, 0xf3a8}, /* '蟥' -> 34789 */
{0x87ea, 0xf3b3}, /* '蟪' -> 34794 */
{0x87ee, 0xf3b5}, /* '蟮' -> 34798 */
{0x87f9, 0xd0b7}, /* '蟹' -> 34809 */
{0x87fe, 0xf3b8}, /* '蟾' -> 34814 */
{0x8803, 0xd9f9}, /* '蠃' -> 34819 */
{0x880a, 0xf3b9}, /* '蠊' -> 34826 */
{0x8813, 0xf3b7}, /* '蠓' -> 34835 */
{0x8815, 0xc8e4}, /* '蠕' -> 34837 */
{0x8816, 0xf3b6}, /* '蠖' -> 34838 */
{0x881b, 0xf3ba}, /* '蠛' -> 34843 */
{0x8821, 0xf3bb}, /* '蠡' -> 34849 */
{0x8822, 0xb4c0}, /* '蠢' -> 34850 */
{0x8832, 0xeec3}, /* '蠲' -> 34866 */
{0x8839, 0xf3bc}, /* '蠹' -> 34873 */
{0x883c, 0xf3bd}, /* '蠼' -> 34876 */
{0x8840, 0xd1aa}, /* '血' -> 34880 */
{0x8844, 0xf4ac}, /* '衄' -> 34884 */
{0x8845, 0xd0c6}, /* '衅' -> 34885 */
{0x884c, 0xd0d0}, /* '行' -> 34892 */
{0x884d, 0xd1dc}, /* '衍' -> 34893 */
{0x8854, 0xcfce}, /* '衔' -> 34900 */
{0x8857, 0xbdd6}, /* '街' -> 34903 */
{0x8859, 0xd1c3}, /* '衙' -> 34905 */
{0x8861, 0xbae2}, /* '衡' -> 34913 */
{0x8862, 0xe1e9}, /* '衢' -> 34914 */
{0x8863, 0xd2c2}, /* '衣' -> 34915 */
{0x8864, 0xf1c2}, /* '衤' -> 34916 */
{0x8865, 0xb2b9}, /* '补' -> 34917 */
{0x8868, 0xb1ed}, /* '表' -> 34920 */
{0x8869, 0xf1c3}, /* '衩' -> 34921 */
{0x886b, 0xc9c0}, /* '衫' -> 34923 */
{0x886c, 0xb3c4}, /* '衬' -> 34924 */
{0x886e, 0xd9f2}, /* '衮' -> 34926 */
{0x8870, 0xcba5}, /* '衰' -> 34928 */
{0x8872, 0xf1c4}, /* '衲' -> 34930 */
{0x8877, 0xd6d4}, /* '衷' -> 34935 */
{0x887d, 0xf1c5}, /* '衽' -> 34941 */
{0x887e, 0xf4c0}, /* '衾' -> 34942 */
{0x887f, 0xf1c6}, /* '衿' -> 34943 */
{0x8881, 0xd4ac}, /* '袁' -> 34945 */
{0x8882, 0xf1c7}, /* '袂' -> 34946 */
{0x8884, 0xb0c0}, /* '袄' -> 34948 */
{0x8885, 0xf4c1}, /* '袅' -> 34949 */
{0x8888, 0xf4c2}, /* '袈' -> 34952 */
{0x888b, 0xb4fc}, /* '袋' -> 34955 */
{0x888d, 0xc5db}, /* '袍' -> 34957 */
{0x8892, 0xccbb}, /* '袒' -> 34962 */
{0x8896, 0xd0e4}, /* '袖' -> 34966 */
{0x889c, 0xcde0}, /* '袜' -> 34972 */
{0x88a2, 0xf1c8}, /* '袢' -> 34978 */
{0x88a4, 0xd9f3}, /* '袤' -> 34980 */
{0x88ab, 0xb1bb}, /* '被' -> 34987 */
{0x88ad, 0xcfae}, /* '袭' -> 34989 */
{0x88b1, 0xb8a4}, /* '袱' -> 34993 */
{0x88b7, 0xf1ca}, /* '袷' -> 34999 */
{0x88bc, 0xf1cb}, /* '袼' -> 35004 */
{0x88c1, 0xb2c3}, /* '裁' -> 35009 */
{0x88c2, 0xc1d1}, /* '裂' -> 35010 */
{0x88c5, 0xd7b0}, /* '装' -> 35013 */
{0x88c6, 0xf1c9}, /* '裆' -> 35014 */
{0x88c9, 0xf1cc}, /* '裉' -> 35017 */
{0x88ce, 0xf1ce}, /* '裎' -> 35022 */
{0x88d2, 0xd9f6}, /* '裒' -> 35026 */
{0x88d4, 0xd2e1}, /* '裔' -> 35028 */
{0x88d5, 0xd4a3}, /* '裕' -> 35029 */
{0x88d8, 0xf4c3}, /* '裘' -> 35032 */
{0x88d9, 0xc8b9}, /* '裙' -> 35033 */
{0x88df, 0xf4c4}, /* '裟' -> 35039 */
{0x88e2, 0xf1cd}, /* '裢' -> 35042 */
{0x88e3, 0xf1cf}, /* '裣' -> 35043 */
{0x88e4, 0xbfe3}, /* '裤' -> 35044 */
{0x88e5, 0xf1d0}, /* '裥' -> 35045 */
{0x88e8, 0xf1d4}, /* '裨' -> 35048 */
{0x88f0, 0xf1d6}, /* '裰' -> 35056 */
{0x88f1, 0xf1d1}, /* '裱' -> 35057 */
{0x88f3, 0xc9d1}, /* '裳' -> 35059 */
{0x88f4, 0xc5e1}, /* '裴' -> 35060 */
{0x88f8, 0xc2e3}, /* '裸' -> 35064 */
{0x88f9, 0xb9fc}, /* '裹' -> 35065 */
{0x88fc, 0xf1d3}, /* '裼' -> 35068 */
{0x88fe, 0xf1d5}, /* '裾' -> 35070 */
{0x8902, 0xb9d3}, /* '褂' -> 35074 */
{0x890a, 0xf1db}, /* '褊' -> 35082 */
{0x8910, 0xbad6}, /* '褐' -> 35088 */
{0x8912, 0xb0fd}, /* '褒' -> 35090 */
{0x8913, 0xf1d9}, /* '褓' -> 35091 */
{0x8919, 0xf1d8}, /* '褙' -> 35097 */
{0x891a, 0xf1d2}, /* '褚' -> 35098 */
{0x891b, 0xf1da}, /* '褛' -> 35099 */
{0x8921, 0xf1d7}, /* '褡' -> 35105 */
{0x8925, 0xc8ec}, /* '褥' -> 35109 */
{0x892a, 0xcdca}, /* '褪' -> 35114 */
{0x892b, 0xf1dd}, /* '褫' -> 35115 */
{0x8930, 0xe5bd}, /* '褰' -> 35120 */
{0x8934, 0xf1dc}, /* '褴' -> 35124 */
{0x8936, 0xf1de}, /* '褶' -> 35126 */
{0x8941, 0xf1df}, /* '襁' -> 35137 */
{0x8944, 0xcfe5}, /* '襄' -> 35140 */
{0x895e, 0xf4c5}, /* '襞' -> 35166 */
{0x895f, 0xbdf3}, /* '襟' -> 35167 */
{0x8966, 0xf1e0}, /* '襦' -> 35174 */
{0x897b, 0xf1e1}, /* '襻' -> 35195 */
{0x897f, 0xcef7}, /* '西' -> 35199 */
{0x8981, 0xd2aa}, /* '要' -> 35201 */
{0x8983, 0xf1fb}, /* '覃' -> 35203 */
{0x8986, 0xb8b2}, /* '覆' -> 35206 */
{0x89c1, 0xbcfb}, /* '见' -> 35265 */
{0x89c2, 0xb9db}, /* '观' -> 35266 */
{0x89c4, 0xb9e6}, /* '规' -> 35268 */
{0x89c5, 0xc3d9}, /* '觅' -> 35269 */
{0x89c6, 0xcad3}, /* '视' -> 35270 */
{0x89c7, 0xeae8}, /* '觇' -> 35271 */
{0x89c8, 0xc0c0}, /* '览' -> 35272 */
{0x89c9, 0xbef5}, /* '觉' -> 35273 */
{0x89ca, 0xeae9}, /* '觊' -> 35274 */
{0x89cb, 0xeaea}, /* '觋' -> 35275 */
{0x89cc, 0xeaeb}, /* '觌' -> 35276 */
{0x89ce, 0xeaec}, /* '觎' -> 35278 */
{0x89cf, 0xeaed}, /* '觏' -> 35279 */
{0x89d0, 0xeaee}, /* '觐' -> 35280 */
{0x89d1, 0xeaef}, /* '觑' -> 35281 */
{0x89d2, 0xbdc7}, /* '角' -> 35282 */
{0x89d6, 0xf5fb}, /* '觖' -> 35286 */
{0x89da, 0xf5fd}, /* '觚' -> 35290 */
{0x89dc, 0xf5fe}, /* '觜' -> 35292 */
{0x89de, 0xf5fc}, /* '觞' -> 35294 */
{0x89e3, 0xbde2}, /* '解' -> 35299 */
{0x89e5, 0xf6a1}, /* '觥' -> 35301 */
{0x89e6, 0xb4a5}, /* '触' -> 35302 */
{0x89eb, 0xf6a2}, /* '觫' -> 35307 */
{0x89ef, 0xf6a3}, /* '觯' -> 35311 */
{0x89f3, 0xecb2}, /* '觳' -> 35315 */
{0x8a00, 0xd1d4}, /* '言' -> 35328 */
{0x8a07, 0xd9ea}, /* '訇' -> 35335 */
{0x8a3e, 0xf6a4}, /* '訾' -> 35390 */
{0x8a48, 0xeeba}, /* '詈' -> 35400 */
{0x8a79, 0xd5b2}, /* '詹' -> 35449 */
{0x8a89, 0xd3fe}, /* '誉' -> 35465 */
{0x8a8a, 0xccdc}, /* '誊' -> 35466 */
{0x8a93, 0xcac4}, /* '誓' -> 35475 */
{0x8b07, 0xe5c0}, /* '謇' -> 35591 */
{0x8b26, 0xf6a5}, /* '謦' -> 35622 */
{0x8b66, 0xbeaf}, /* '警' -> 35686 */
{0x8b6c, 0xc6a9}, /* '譬' -> 35692 */
{0x8ba0, 0xdaa5}, /* '讠' -> 35744 */
{0x8ba1, 0xbcc6}, /* '计' -> 35745 */
{0x8ba2, 0xb6a9}, /* '订' -> 35746 */
{0x8ba3, 0xb8bc}, /* '讣' -> 35747 */
{0x8ba4, 0xc8cf}, /* '认' -> 35748 */
{0x8ba5, 0xbca5}, /* '讥' -> 35749 */
{0x8ba6, 0xdaa6}, /* '讦' -> 35750 */
{0x8ba7, 0xdaa7}, /* '讧' -> 35751 */
{0x8ba8, 0xccd6}, /* '讨' -> 35752 */
{0x8ba9, 0xc8c3}, /* '让' -> 35753 */
{0x8baa, 0xdaa8}, /* '讪' -> 35754 */
{0x8bab, 0xc6fd}, /* '讫' -> 35755 */
{0x8bad, 0xd1b5}, /* '训' -> 35757 */
{0x8bae, 0xd2e9}, /* '议' -> 35758 */
{0x8baf, 0xd1b6}, /* '讯' -> 35759 */
{0x8bb0, 0xbcc7}, /* '记' -> 35760 */
{0x8bb2, 0xbdb2}, /* '讲' -> 35762 */
{0x8bb3, 0xbbe4}, /* '讳' -> 35763 */
{0x8bb4, 0xdaa9}, /* '讴' -> 35764 */
{0x8bb5, 0xdaaa}, /* '讵' -> 35765 */
{0x8bb6, 0xd1c8}, /* '讶' -> 35766 */
{0x8bb7, 0xdaab}, /* '讷' -> 35767 */
{0x8bb8, 0xd0ed}, /* '许' -> 35768 */
{0x8bb9, 0xb6ef}, /* '讹' -> 35769 */
{0x8bba, 0xc2db}, /* '论' -> 35770 */
{0x8bbc, 0xcbcf}, /* '讼' -> 35772 */
{0x8bbd, 0xb7ed}, /* '讽' -> 35773 */
{0x8bbe, 0xc9e8}, /* '设' -> 35774 */
{0x8bbf, 0xb7c3}, /* '访' -> 35775 */
{0x8bc0, 0xbef7}, /* '诀' -> 35776 */
{0x8bc1, 0xd6a4}, /* '证' -> 35777 */
{0x8bc2, 0xdaac}, /* '诂' -> 35778 */
{0x8bc3, 0xdaad}, /* '诃' -> 35779 */
{0x8bc4, 0xc6c0}, /* '评' -> 35780 */
{0x8bc5, 0xd7e7}, /* '诅' -> 35781 */
{0x8bc6, 0xcab6}, /* '识' -> 35782 */
{0x8bc8, 0xd5a9}, /* '诈' -> 35784 */
{0x8bc9, 0xcbdf}, /* '诉' -> 35785 */
{0x8bca, 0xd5ef}, /* '诊' -> 35786 */
{0x8bcb, 0xdaae}, /* '诋' -> 35787 */
{0x8bcc, 0xd6df}, /* '诌' -> 35788 */
{0x8bcd, 0xb4ca}, /* '词' -> 35789 */
{0x8bce, 0xdab0}, /* '诎' -> 35790 */
{0x8bcf, 0xdaaf}, /* '诏' -> 35791 */
{0x8bd1, 0xd2eb}, /* '译' -> 35793 */
{0x8bd2, 0xdab1}, /* '诒' -> 35794 */
{0x8bd3, 0xdab2}, /* '诓' -> 35795 */
{0x8bd4, 0xdab3}, /* '诔' -> 35796 */
{0x8bd5, 0xcad4}, /* '试' -> 35797 */
{0x8bd6, 0xdab4}, /* '诖' -> 35798 */
{0x8bd7, 0xcaab}, /* '诗' -> 35799 */
{0x8bd8, 0xdab5}, /* '诘' -> 35800 */
{0x8bd9, 0xdab6}, /* '诙' -> 35801 */
{0x8bda, 0xb3cf}, /* '诚' -> 35802 */
{0x8bdb, 0xd6ef}, /* '诛' -> 35803 */
{0x8bdc, 0xdab7}, /* '诜' -> 35804 */
{0x8bdd, 0xbbb0}, /* '话' -> 35805 */
{0x8bde, 0xb5ae}, /* '诞' -> 35806 */
{0x8bdf, 0xdab8}, /* '诟' -> 35807 */
{0x8be0, 0xdab9}, /* '诠' -> 35808 */
{0x8be1, 0xb9ee}, /* '诡' -> 35809 */
{0x8be2, 0xd1af}, /* '询' -> 35810 */
{0x8be3, 0xd2e8}, /* '诣' -> 35811 */
{0x8be4, 0xdaba}, /* '诤' -> 35812 */
{0x8be5, 0xb8c3}, /* '该' -> 35813 */
{0x8be6, 0xcfea}, /* '详' -> 35814 */
{0x8be7, 0xb2ef}, /* '诧' -> 35815 */
{0x8be8, 0xdabb}, /* '诨' -> 35816 */
{0x8be9, 0xdabc}, /* '诩' -> 35817 */
{0x8beb, 0xbdeb}, /* '诫' -> 35819 */
{0x8bec, 0xcedc}, /* '诬' -> 35820 */
{0x8bed, 0xd3ef}, /* '语' -> 35821 */
{0x8bee, 0xdabd}, /* '诮' -> 35822 */
{0x8bef, 0xcef3}, /* '误' -> 35823 */
{0x8bf0, 0xdabe}, /* '诰' -> 35824 */
{0x8bf1, 0xd3d5}, /* '诱' -> 35825 */
{0x8bf2, 0xbbe5}, /* '诲' -> 35826 */
{0x8bf3, 0xdabf}, /* '诳' -> 35827 */
{0x8bf4, 0xcbb5}, /* '说' -> 35828 */
{0x8bf5, 0xcbd0}, /* '诵' -> 35829 */
{0x8bf6, 0xdac0}, /* '诶' -> 35830 */
{0x8bf7, 0xc7eb}, /* '请' -> 35831 */
{0x8bf8, 0xd6ee}, /* '诸' -> 35832 */
{0x8bf9, 0xdac1}, /* '诹' -> 35833 */
{0x8bfa, 0xc5b5}, /* '诺' -> 35834 */
{0x8bfb, 0xb6c1}, /* '读' -> 35835 */
{0x8bfc, 0xdac2}, /* '诼' -> 35836 */
{0x8bfd, 0xb7cc}, /* '诽' -> 35837 */
{0x8bfe, 0xbfce}, /* '课' -> 35838 */
{0x8bff, 0xdac3}, /* '诿' -> 35839 */
{0x8c00, 0xdac4}, /* '谀' -> 35840 */
{0x8c01, 0xcbad}, /* '谁' -> 35841 */
{0x8c02, 0xdac5}, /* '谂' -> 35842 */
{0x8c03, 0xb5f7}, /* '调' -> 35843 */
{0x8c04, 0xdac6}, /* '谄' -> 35844 */
{0x8c05, 0xc1c2}, /* '谅' -> 35845 */
{0x8c06, 0xd7bb}, /* '谆' -> 35846 */
{0x8c07, 0xdac7}, /* '谇' -> 35847 */
{0x8c08, 0xccb8}, /* '谈' -> 35848 */
{0x8c0a, 0xd2ea}, /* '谊' -> 35850 */
{0x8c0b, 0xc4b1}, /* '谋' -> 35851 */
{0x8c0c, 0xdac8}, /* '谌' -> 35852 */
{0x8c0d, 0xb5fd}, /* '谍' -> 35853 */
{0x8c0e, 0xbbd1}, /* '谎' -> 35854 */
{0x8c0f, 0xdac9}, /* '谏' -> 35855 */
{0x8c10, 0xd0b3}, /* '谐' -> 35856 */
{0x8c11, 0xdaca}, /* '谑' -> 35857 */
{0x8c12, 0xdacb}, /* '谒' -> 35858 */
{0x8c13, 0xcebd}, /* '谓' -> 35859 */
{0x8c14, 0xdacc}, /* '谔' -> 35860 */
{0x8c15, 0xdacd}, /* '谕' -> 35861 */
{0x8c16, 0xdace}, /* '谖' -> 35862 */
{0x8c17, 0xb2f7}, /* '谗' -> 35863 */
{0x8c18, 0xdad1}, /* '谘' -> 35864 */
{0x8c19, 0xdacf}, /* '谙' -> 35865 */
{0x8c1a, 0xd1e8}, /* '谚' -> 35866 */
{0x8c1b, 0xdad0}, /* '谛' -> 35867 */
{0x8c1c, 0xc3d5}, /* '谜' -> 35868 */
{0x8c1d, 0xdad2}, /* '谝' -> 35869 */
{0x8c1f, 0xdad3}, /* '谟' -> 35871 */
{0x8c20, 0xdad4}, /* '谠' -> 35872 */
{0x8c21, 0xdad5}, /* '谡' -> 35873 */
{0x8c22, 0xd0bb}, /* '谢' -> 35874 */
{0x8c23, 0xd2a5}, /* '谣' -> 35875 */
{0x8c24, 0xb0f9}, /* '谤' -> 35876 */
{0x8c25, 0xdad6}, /* '谥' -> 35877 */
{0x8c26, 0xc7ab}, /* '谦' -> 35878 */
{0x8c27, 0xdad7}, /* '谧' -> 35879 */
{0x8c28, 0xbdf7}, /* '谨' -> 35880 */
{0x8c29, 0xc3a1}, /* '谩' -> 35881 */
{0x8c2a, 0xdad8}, /* '谪' -> 35882 */
{0x8c2b, 0xdad9}, /* '谫' -> 35883 */
{0x8c2c, 0xc3fd}, /* '谬' -> 35884 */
{0x8c2d, 0xccb7}, /* '谭' -> 35885 */
{0x8c2e, 0xdada}, /* '谮' -> 35886 */
{0x8c2f, 0xdadb}, /* '谯' -> 35887 */
{0x8c30, 0xc0be}, /* '谰' -> 35888 */
{0x8c31, 0xc6d7}, /* '谱' -> 35889 */
{0x8c32, 0xdadc}, /* '谲' -> 35890 */
{0x8c33, 0xdadd}, /* '谳' -> 35891 */
{0x8c34, 0xc7b4}, /* '谴' -> 35892 */
{0x8c35, 0xdade}, /* '谵' -> 35893 */
{0x8c36, 0xdadf}, /* '谶' -> 35894 */
{0x8c37, 0xb9c8}, /* '谷' -> 35895 */
{0x8c41, 0xbbed}, /* '豁' -> 35905 */
{0x8c46, 0xb6b9}, /* '豆' -> 35910 */
{0x8c47, 0xf4f8}, /* '豇' -> 35911 */
{0x8c49, 0xf4f9}, /* '豉' -> 35913 */
{0x8c4c, 0xcde3}, /* '豌' -> 35916 */
{0x8c55, 0xf5b9}, /* '豕' -> 35925 */
{0x8c5a, 0xebe0}, /* '豚' -> 35930 */
{0x8c61, 0xcff3}, /* '象' -> 35937 */
{0x8c62, 0xbbbf}, /* '豢' -> 35938 */
{0x8c6a, 0xbac0}, /* '豪' -> 35946 */
{0x8c6b, 0xd4a5}, /* '豫' -> 35947 */
{0x8c73, 0xe1d9}, /* '豳' -> 35955 */
{0x8c78, 0xf5f4}, /* '豸' -> 35960 */
{0x8c79, 0xb1aa}, /* '豹' -> 35961 */
{0x8c7a, 0xb2f2}, /* '豺' -> 35962 */
{0x8c82, 0xf5f5}, /* '貂' -> 35970 */
{0x8c85, 0xf5f7}, /* '貅' -> 35973 */
{0x8c89, 0xbad1}, /* '貉' -> 35977 */
{0x8c8a, 0xf5f6}, /* '貊' -> 35978 */
{0x8c8c, 0xc3b2}, /* '貌' -> 35980 */
{0x8c94, 0xf5f9}, /* '貔' -> 35988 */
{0x8c98, 0xf5f8}, /* '貘' -> 35992 */
{0x8d1d, 0xb1b4}, /* '贝' -> 36125 */
{0x8d1e, 0xd5ea}, /* '贞' -> 36126 */
{0x8d1f, 0xb8ba}, /* '负' -> 36127 */
{0x8d21, 0xb9b1}, /* '贡' -> 36129 */
{0x8d22, 0xb2c6}, /* '财' -> 36130 */
{0x8d23, 0xd4f0}, /* '责' -> 36131 */
{0x8d24, 0xcfcd}, /* '贤' -> 36132 */
{0x8d25, 0xb0dc}, /* '败' -> 36133 */
{0x8d26, 0xd5cb}, /* '账' -> 36134 */
{0x8d27, 0xbbf5}, /* '货' -> 36135 */
{0x8d28, 0xd6ca}, /* '质' -> 36136 */
{0x8d29, 0xb7b7}, /* '贩' -> 36137 */
{0x8d2a, 0xccb0}, /* '贪' -> 36138 */
{0x8d2b, 0xc6b6}, /* '贫' -> 36139 */
{0x8d2c, 0xb1e1}, /* '贬' -> 36140 */
{0x8d2d, 0xb9ba}, /* '购' -> 36141 */
{0x8d2e, 0xd6fc}, /* '贮' -> 36142 */
{0x8d2f, 0xb9e1}, /* '贯' -> 36143 */
{0x8d30, 0xb7a1}, /* '贰' -> 36144 */
{0x8d31, 0xbcfa}, /* '贱' -> 36145 */
{0x8d32, 0xeada}, /* '贲' -> 36146 */
{0x8d33, 0xeadb}, /* '贳' -> 36147 */
{0x8d34, 0xccf9}, /* '贴' -> 36148 */
{0x8d35, 0xb9f3}, /* '贵' -> 36149 */
{0x8d36, 0xeadc}, /* '贶' -> 36150 */
{0x8d37, 0xb4fb}, /* '贷' -> 36151 */
{0x8d38, 0xc3b3}, /* '贸' -> 36152 */
{0x8d39, 0xb7d1}, /* '费' -> 36153 */
{0x8d3a, 0xbad8}, /* '贺' -> 36154 */
{0x8d3b, 0xeadd}, /* '贻' -> 36155 */
{0x8d3c, 0xd4f4}, /* '贼' -> 36156 */
{0x8d3d, 0xeade}, /* '贽' -> 36157 */
{0x8d3e, 0xbcd6}, /* '贾' -> 36158 */
{0x8d3f, 0xbbdf}, /* '贿' -> 36159 */
{0x8d40, 0xeadf}, /* '赀' -> 36160 */
{0x8d41, 0xc1de}, /* '赁' -> 36161 */
{0x8d42, 0xc2b8}, /* '赂' -> 36162 */
{0x8d43, 0xd4df}, /* '赃' -> 36163 */
{0x8d44, 0xd7ca}, /* '资' -> 36164 */
{0x8d45, 0xeae0}, /* '赅' -> 36165 */
{0x8d46, 0xeae1}, /* '赆' -> 36166 */
{0x8d47, 0xeae4}, /* '赇' -> 36167 */
{0x8d48, 0xeae2}, /* '赈' -> 36168 */
{0x8d49, 0xeae3}, /* '赉' -> 36169 */
{0x8d4a, 0xc9de}, /* '赊' -> 36170 */
{0x8d4b, 0xb8b3}, /* '赋' -> 36171 */
{0x8d4c, 0xb6c4}, /* '赌' -> 36172 */
{0x8d4d, 0xeae5}, /* '赍' -> 36173 */
{0x8d4e, 0xcaea}, /* '赎' -> 36174 */
{0x8d4f, 0xc9cd}, /* '赏' -> 36175 */
{0x8d50, 0xb4cd}, /* '赐' -> 36176 */
{0x8d53, 0xe2d9}, /* '赓' -> 36179 */
{0x8d54, 0xc5e2}, /* '赔' -> 36180 */
{0x8d55, 0xeae6}, /* '赕' -> 36181 */
{0x8d56, 0xc0b5}, /* '赖' -> 36182 */
{0x8d58, 0xd7b8}, /* '赘' -> 36184 */
{0x8d59, 0xeae7}, /* '赙' -> 36185 */
{0x8d5a, 0xd7ac}, /* '赚' -> 36186 */
{0x8d5b, 0xc8fc}, /* '赛' -> 36187 */
{0x8d5c, 0xd8d3}, /* '赜' -> 36188 */
{0x8d5d, 0xd8cd}, /* '赝' -> 36189 */
{0x8d5e, 0xd4de}, /* '赞' -> 36190 */
{0x8d60, 0xd4f9}, /* '赠' -> 36192 */
{0x8d61, 0xc9c4}, /* '赡' -> 36193 */
{0x8d62, 0xd3ae}, /* '赢' -> 36194 */
{0x8d63, 0xb8d3}, /* '赣' -> 36195 */
{0x8d64, 0xb3e0}, /* '赤' -> 36196 */
{0x8d66, 0xc9e2}, /* '赦' -> 36198 */
{0x8d67, 0xf4f6}, /* '赧' -> 36199 */
{0x8d6b, 0xbad5}, /* '赫' -> 36203 */
{0x8d6d, 0xf4f7}, /* '赭' -> 36205 */
{0x8d70, 0xd7df}, /* '走' -> 36208 */
{0x8d73, 0xf4f1}, /* '赳' -> 36211 */
{0x8d74, 0xb8b0}, /* '赴' -> 36212 */
{0x8d75, 0xd5d4}, /* '赵' -> 36213 */
{0x8d76, 0xb8cf}, /* '赶' -> 36214 */
{0x8d77, 0xc6f0}, /* '起' -> 36215 */
{0x8d81, 0xb3c3}, /* '趁' -> 36225 */
{0x8d84, 0xf4f2}, /* '趄' -> 36228 */
{0x8d85, 0xb3ac}, /* '超' -> 36229 */
{0x8d8a, 0xd4bd}, /* '越' -> 36234 */
{0x8d8b, 0xc7f7}, /* '趋' -> 36235 */
{0x8d91, 0xf4f4}, /* '趑' -> 36241 */
{0x8d94, 0xf4f3}, /* '趔' -> 36244 */
{0x8d9f, 0xcccb}, /* '趟' -> 36255 */
{0x8da3, 0xc8a4}, /* '趣' -> 36259 */
{0x8db1, 0xf4f5}, /* '趱' -> 36273 */
{0x8db3, 0xd7e3}, /* '足' -> 36275 */
{0x8db4, 0xc5bf}, /* '趴' -> 36276 */
{0x8db5, 0xf5c0}, /* '趵' -> 36277 */
{0x8db8, 0xf5bb}, /* '趸' -> 36280 */
{0x8dba, 0xf5c3}, /* '趺' -> 36282 */
{0x8dbc, 0xf5c2}, /* '趼' -> 36284 */
{0x8dbe, 0xd6ba}, /* '趾' -> 36286 */
{0x8dbf, 0xf5c1}, /* '趿' -> 36287 */
{0x8dc3, 0xd4be}, /* '跃' -> 36291 */
{0x8dc4, 0xf5c4}, /* '跄' -> 36292 */
{0x8dc6, 0xf5cc}, /* '跆' -> 36294 */
{0x8dcb, 0xb0cf}, /* '跋' -> 36299 */
{0x8dcc, 0xb5f8}, /* '跌' -> 36300 */
{0x8dce, 0xf5c9}, /* '跎' -> 36302 */
{0x8dcf, 0xf5ca}, /* '跏' -> 36303 */
{0x8dd1, 0xc5dc}, /* '跑' -> 36305 */
{0x8dd6, 0xf5c5}, /* '跖' -> 36310 */
{0x8dd7, 0xf5c6}, /* '跗' -> 36311 */
{0x8dda, 0xf5c7}, /* '跚' -> 36314 */
{0x8ddb, 0xf5cb}, /* '跛' -> 36315 */
{0x8ddd, 0xbee0}, /* '距' -> 36317 */
{0x8dde, 0xf5c8}, /* '跞' -> 36318 */
{0x8ddf, 0xb8fa}, /* '跟' -> 36319 */
{0x8de3, 0xf5d0}, /* '跣' -> 36323 */
{0x8de4, 0xf5d3}, /* '跤' -> 36324 */
{0x8de8, 0xbfe7}, /* '跨' -> 36328 */
{0x8dea, 0xb9f2}, /* '跪' -> 36330 */
{0x8deb, 0xf5bc}, /* '跫' -> 36331 */
{0x8dec, 0xf5cd}, /* '跬' -> 36332 */
{0x8def, 0xc2b7}, /* '路' -> 36335 */
{0x8df3, 0xccf8}, /* '跳' -> 36339 */
{0x8df5, 0xbcf9}, /* '践' -> 36341 */
{0x8df7, 0xf5ce}, /* '跷' -> 36343 */
{0x8df8, 0xf5cf}, /* '跸' -> 36344 */
{0x8df9, 0xf5d1}, /* '跹' -> 36345 */
{0x8dfa, 0xb6e5}, /* '跺' -> 36346 */
{0x8dfb, 0xf5d2}, /* '跻' -> 36347 */
{0x8dfd, 0xf5d5}, /* '跽' -> 36349 */
{0x8e05, 0xf5bd}, /* '踅' -> 36357 */
{0x8e09, 0xf5d4}, /* '踉' -> 36361 */
{0x8e0a, 0xd3bb}, /* '踊' -> 36362 */
{0x8e0c, 0xb3ec}, /* '踌' -> 36364 */
{0x8e0f, 0xcca4}, /* '踏' -> 36367 */
{0x8e14, 0xf5d6}, /* '踔' -> 36372 */
{0x8e1d, 0xf5d7}, /* '踝' -> 36381 */
{0x8e1e, 0xbee1}, /* '踞' -> 36382 */
{0x8e1f, 0xf5d8}, /* '踟' -> 36383 */
{0x8e22, 0xccdf}, /* '踢' -> 36386 */
{0x8e23, 0xf5db}, /* '踣' -> 36387 */
{0x8e29, 0xb2c8}, /* '踩' -> 36393 */
{0x8e2a, 0xd7d9}, /* '踪' -> 36394 */
{0x8e2c, 0xf5d9}, /* '踬' -> 36396 */
{0x8e2e, 0xf5da}, /* '踮' -> 36398 */
{0x8e2f, 0xf5dc}, /* '踯' -> 36399 */
{0x8e31, 0xf5e2}, /* '踱' -> 36401 */
{0x8e35, 0xf5e0}, /* '踵' -> 36405 */
{0x8e39, 0xf5df}, /* '踹' -> 36409 */
{0x8e3a, 0xf5dd}, /* '踺' -> 36410 */
{0x8e3d, 0xf5e1}, /* '踽' -> 36413 */
{0x8e40, 0xf5de}, /* '蹀' -> 36416 */
{0x8e41, 0xf5e4}, /* '蹁' -> 36417 */
{0x8e42, 0xf5e5}, /* '蹂' -> 36418 */
{0x8e44, 0xcce3}, /* '蹄' -> 36420 */
{0x8e47, 0xe5bf}, /* '蹇' -> 36423 */
{0x8e48, 0xb5b8}, /* '蹈' -> 36424 */
{0x8e49, 0xf5e3}, /* '蹉' -> 36425 */
{0x8e4a, 0xf5e8}, /* '蹊' -> 36426 */
{0x8e4b, 0xcca3}, /* '蹋' -> 36427 */
{0x8e51, 0xf5e6}, /* '蹑' -> 36433 */
{0x8e52, 0xf5e7}, /* '蹒' -> 36434 */
{0x8e59, 0xf5be}, /* '蹙' -> 36441 */
{0x8e66, 0xb1c4}, /* '蹦' -> 36454 */
{0x8e69, 0xf5bf}, /* '蹩' -> 36457 */
{0x8e6c, 0xb5c5}, /* '蹬' -> 36460 */
{0x8e6d, 0xb2e4}, /* '蹭' -> 36461 */
{0x8e6f, 0xf5ec}, /* '蹯' -> 36463 */
{0x8e70, 0xf5e9}, /* '蹰' -> 36464 */
{0x8e72, 0xb6d7}, /* '蹲' -> 36466 */
{0x8e74, 0xf5ed}, /* '蹴' -> 36468 */
{0x8e76, 0xf5ea}, /* '蹶' -> 36470 */
{0x8e7c, 0xf5eb}, /* '蹼' -> 36476 */
{0x8e7f, 0xb4da}, /* '蹿' -> 36479 */
{0x8e81, 0xd4ea}, /* '躁' -> 36481 */
{0x8e85, 0xf5ee}, /* '躅' -> 36485 */
{0x8e87, 0xb3f9}, /* '躇' -> 36487 */
{0x8e8f, 0xf5ef}, /* '躏' -> 36495 */
{0x8e90, 0xf5f1}, /* '躐' -> 36496 */
{0x8e94, 0xf5f0}, /* '躔' -> 36500 */
{0x8e9c, 0xf5f2}, /* '躜' -> 36508 */
{0x8e9e, 0xf5f3}, /* '躞' -> 36510 */
{0x8eab, 0xc9ed}, /* '身' -> 36523 */
{0x8eac, 0xb9aa}, /* '躬' -> 36524 */
{0x8eaf, 0xc7fb}, /* '躯' -> 36527 */
{0x8eb2, 0xb6e3}, /* '躲' -> 36530 */
{0x8eba, 0xccc9}, /* '躺' -> 36538 */
{0x8ece, 0xeaa6}, /* '軎' -> 36558 */
{0x8f66, 0xb3b5}, /* '车' -> 36710 */
{0x8f67, 0xd4fe}, /* '轧' -> 36711 */
{0x8f68, 0xb9ec}, /* '轨' -> 36712 */
{0x8f69, 0xd0f9}, /* '轩' -> 36713 */
{0x8f6b, 0xe9ed}, /* '轫' -> 36715 */
{0x8f6c, 0xd7aa}, /* '转' -> 36716 */
{0x8f6d, 0xe9ee}, /* '轭' -> 36717 */
{0x8f6e, 0xc2d6}, /* '轮' -> 36718 */
{0x8f6f, 0xc8ed}, /* '软' -> 36719 */
{0x8f70, 0xbae4}, /* '轰' -> 36720 */
{0x8f71, 0xe9ef}, /* '轱' -> 36721 */
{0x8f72, 0xe9f0}, /* '轲' -> 36722 */
{0x8f73, 0xe9f1}, /* '轳' -> 36723 */
{0x8f74, 0xd6e1}, /* '轴' -> 36724 */
{0x8f75, 0xe9f2}, /* '轵' -> 36725 */
{0x8f76, 0xe9f3}, /* '轶' -> 36726 */
{0x8f77, 0xe9f5}, /* '轷' -> 36727 */
{0x8f78, 0xe9f4}, /* '轸' -> 36728 */
{0x8f79, 0xe9f6}, /* '轹' -> 36729 */
{0x8f7a, 0xe9f7}, /* '轺' -> 36730 */
{0x8f7b, 0xc7e1}, /* '轻' -> 36731 */
{0x8f7c, 0xe9f8}, /* '轼' -> 36732 */
{0x8f7d, 0xd4d8}, /* '载' -> 36733 */
{0x8f7e, 0xe9f9}, /* '轾' -> 36734 */
{0x8f7f, 0xbdce}, /* '轿' -> 36735 */
{0x8f81, 0xe9fa}, /* '辁' -> 36737 */
{0x8f82, 0xe9fb}, /* '辂' -> 36738 */
{0x8f83, 0xbdcf}, /* '较' -> 36739 */
{0x8f84, 0xe9fc}, /* '辄' -> 36740 */
{0x8f85, 0xb8a8}, /* '辅' -> 36741 */
{0x8f86, 0xc1be}, /* '辆' -> 36742 */
{0x8f87, 0xe9fd}, /* '辇' -> 36743 */
{0x8f88, 0xb1b2}, /* '辈' -> 36744 */
{0x8f89, 0xbbd4}, /* '辉' -> 36745 */
{0x8f8a, 0xb9f5}, /* '辊' -> 36746 */
{0x8f8b, 0xe9fe}, /* '辋' -> 36747 */
{0x8f8d, 0xeaa1}, /* '辍' -> 36749 */
{0x8f8e, 0xeaa2}, /* '辎' -> 36750 */
{0x8f8f, 0xeaa3}, /* '辏' -> 36751 */
{0x8f90, 0xb7f8}, /* '辐' -> 36752 */
{0x8f91, 0xbcad}, /* '辑' -> 36753 */
{0x8f93, 0xcae4}, /* '输' -> 36755 */
{0x8f94, 0xe0ce}, /* '辔' -> 36756 */
{0x8f95, 0xd4af}, /* '辕' -> 36757 */
{0x8f96, 0xcfbd}, /* '辖' -> 36758 */
{0x8f97, 0xd5b7}, /* '辗' -> 36759 */
{0x8f98, 0xeaa4}, /* '辘' -> 36760 */
{0x8f99, 0xd5de}, /* '辙' -> 36761 */
{0x8f9a, 0xeaa5}, /* '辚' -> 36762 */
{0x8f9b, 0xd0c1}, /* '辛' -> 36763 */
{0x8f9c, 0xb9bc}, /* '辜' -> 36764 */
{0x8f9e, 0xb4c7}, /* '辞' -> 36766 */
{0x8f9f, 0xb1d9}, /* '辟' -> 36767 */
{0x8fa3, 0xc0b1}, /* '辣' -> 36771 */
{0x8fa8, 0xb1e6}, /* '辨' -> 36776 */
{0x8fa9, 0xb1e7}, /* '辩' -> 36777 */
{0x8fab, 0xb1e8}, /* '辫' -> 36779 */
{0x8fb0, 0xb3bd}, /* '辰' -> 36784 */
{0x8fb1, 0xc8e8}, /* '辱' -> 36785 */
{0x8fb6, 0xe5c1}, /* '辶' -> 36790 */
{0x8fb9, 0xb1df}, /* '边' -> 36793 */
{0x8fbd, 0xc1c9}, /* '辽' -> 36797 */
{0x8fbe, 0xb4ef}, /* '达' -> 36798 */
{0x8fc1, 0xc7a8}, /* '迁' -> 36801 */
{0x8fc2, 0xd3d8}, /* '迂' -> 36802 */
{0x8fc4, 0xc6f9}, /* '迄' -> 36804 */
{0x8fc5, 0xd1b8}, /* '迅' -> 36805 */
{0x8fc7, 0xb9fd}, /* '过' -> 36807 */
{0x8fc8, 0xc2f5}, /* '迈' -> 36808 */
{0x8fce, 0xd3ad}, /* '迎' -> 36814 */
{0x8fd0, 0xd4cb}, /* '运' -> 36816 */
{0x8fd1, 0xbdfc}, /* '近' -> 36817 */
{0x8fd3, 0xe5c2}, /* '迓' -> 36819 */
{0x8fd4, 0xb7b5}, /* '返' -> 36820 */
{0x8fd5, 0xe5c3}, /* '迕' -> 36821 */
{0x8fd8, 0xbbb9}, /* '还' -> 36824 */
{0x8fd9, 0xd5e2}, /* '这' -> 36825 */
{0x8fdb, 0xbdf8}, /* '进' -> 36827 */
{0x8fdc, 0xd4b6}, /* '远' -> 36828 */
{0x8fdd, 0xcea5}, /* '违' -> 36829 */
{0x8fde, 0xc1ac}, /* '连' -> 36830 */
{0x8fdf, 0xb3d9}, /* '迟' -> 36831 */
{0x8fe2, 0xccf6}, /* '迢' -> 36834 */
{0x8fe4, 0xe5c6}, /* '迤' -> 36836 */
{0x8fe5, 0xe5c4}, /* '迥' -> 36837 */
{0x8fe6, 0xe5c8}, /* '迦' -> 36838 */
{0x8fe8, 0xe5ca}, /* '迨' -> 36840 */
{0x8fe9, 0xe5c7}, /* '迩' -> 36841 */
{0x8fea, 0xb5cf}, /* '迪' -> 36842 */
{0x8feb, 0xc6c8}, /* '迫' -> 36843 */
{0x8fed, 0xb5fc}, /* '迭' -> 36845 */
{0x8fee, 0xe5c5}, /* '迮' -> 36846 */
{0x8ff0, 0xcaf6}, /* '述' -> 36848 */
{0x8ff3, 0xe5c9}, /* '迳' -> 36851 */
{0x8ff7, 0xc3d4}, /* '迷' -> 36855 */
{0x8ff8, 0xb1c5}, /* '迸' -> 36856 */
{0x8ff9, 0xbca3}, /* '迹' -> 36857 */
{0x8ffd, 0xd7b7}, /* '追' -> 36861 */
{0x9000, 0xcdcb}, /* '退' -> 36864 */
{0x9001, 0xcbcd}, /* '送' -> 36865 */
{0x9002, 0xcaca}, /* '适' -> 36866 */
{0x9003, 0xccd3}, /* '逃' -> 36867 */
{0x9004, 0xe5cc}, /* '逄' -> 36868 */
{0x9005, 0xe5cb}, /* '逅' -> 36869 */
{0x9006, 0xc4e6}, /* '逆' -> 36870 */
{0x9009, 0xd1a1}, /* '选' -> 36873 */
{0x900a, 0xd1b7}, /* '逊' -> 36874 */
{0x900b, 0xe5cd}, /* '逋' -> 36875 */
{0x900d, 0xe5d0}, /* '逍' -> 36877 */
{0x900f, 0xcdb8}, /* '透' -> 36879 */
{0x9010, 0xd6f0}, /* '逐' -> 36880 */
{0x9011, 0xe5cf}, /* '逑' -> 36881 */
{0x9012, 0xb5dd}, /* '递' -> 36882 */
{0x9014, 0xcdbe}, /* '途' -> 36884 */
{0x9016, 0xe5d1}, /* '逖' -> 36886 */
{0x9017, 0xb6ba}, /* '逗' -> 36887 */
{0x901a, 0xcda8}, /* '通' -> 36890 */
{0x901b, 0xb9e4}, /* '逛' -> 36891 */
{0x901d, 0xcac5}, /* '逝' -> 36893 */
{0x901e, 0xb3d1}, /* '逞' -> 36894 */
{0x901f, 0xcbd9}, /* '速' -> 36895 */
{0x9020, 0xd4ec}, /* '造' -> 36896 */
{0x9021, 0xe5d2}, /* '逡' -> 36897 */
{0x9022, 0xb7ea}, /* '逢' -> 36898 */
{0x9026, 0xe5ce}, /* '逦' -> 36902 */
{0x902d, 0xe5d5}, /* '逭' -> 36909 */
{0x902e, 0xb4fe}, /* '逮' -> 36910 */
{0x902f, 0xe5d6}, /* '逯' -> 36911 */
{0x9035, 0xe5d3}, /* '逵' -> 36917 */
{0x9036, 0xe5d4}, /* '逶' -> 36918 */
{0x9038, 0xd2dd}, /* '逸' -> 36920 */
{0x903b, 0xc2df}, /* '逻' -> 36923 */
{0x903c, 0xb1c6}, /* '逼' -> 36924 */
{0x903e, 0xd3e2}, /* '逾' -> 36926 */
{0x9041, 0xb6dd}, /* '遁' -> 36929 */
{0x9042, 0xcbec}, /* '遂' -> 36930 */
{0x9044, 0xe5d7}, /* '遄' -> 36932 */
{0x9047, 0xd3f6}, /* '遇' -> 36935 */
{0x904d, 0xb1e9}, /* '遍' -> 36941 */
{0x904f, 0xb6f4}, /* '遏' -> 36943 */
{0x9050, 0xe5da}, /* '遐' -> 36944 */
{0x9051, 0xe5d8}, /* '遑' -> 36945 */
{0x9052, 0xe5d9}, /* '遒' -> 36946 */
{0x9053, 0xb5c0}, /* '道' -> 36947 */
{0x9057, 0xd2c5}, /* '遗' -> 36951 */
{0x9058, 0xe5dc}, /* '遘' -> 36952 */
{0x905b, 0xe5de}, /* '遛' -> 36955 */
{0x9062, 0xe5dd}, /* '遢' -> 36962 */
{0x9063, 0xc7b2}, /* '遣' -> 36963 */
{0x9065, 0xd2a3}, /* '遥' -> 36965 */
{0x9068, 0xe5db}, /* '遨' -> 36968 */
{0x906d, 0xd4e2}, /* '遭' -> 36973 */
{0x906e, 0xd5da}, /* '遮' -> 36974 */
{0x9074, 0xe5e0}, /* '遴' -> 36980 */
{0x9075, 0xd7f1}, /* '遵' -> 36981 */
{0x907d, 0xe5e1}, /* '遽' -> 36989 */
{0x907f, 0xb1dc}, /* '避' -> 36991 */
{0x9080, 0xd1fb}, /* '邀' -> 36992 */
{0x9082, 0xe5e2}, /* '邂' -> 36994 */
{0x9083, 0xe5e4}, /* '邃' -> 36995 */
{0x9088, 0xe5e3}, /* '邈' -> 37000 */
{0x908b, 0xe5e5}, /* '邋' -> 37003 */
{0x9091, 0xd2d8}, /* '邑' -> 37009 */
{0x9093, 0xb5cb}, /* '邓' -> 37011 */
{0x9095, 0xe7df}, /* '邕' -> 37013 */
{0x9097, 0xdaf5}, /* '邗' -> 37015 */
{0x9099, 0xdaf8}, /* '邙' -> 37017 */
{0x909b, 0xdaf6}, /* '邛' -> 37019 */
{0x909d, 0xdaf7}, /* '邝' -> 37021 */
{0x90a1, 0xdafa}, /* '邡' -> 37025 */
{0x90a2, 0xd0cf}, /* '邢' -> 37026 */
{0x90a3, 0xc4c7}, /* '那' -> 37027 */
{0x90a6, 0xb0ee}, /* '邦' -> 37030 */
{0x90aa, 0xd0b0}, /* '邪' -> 37034 */
{0x90ac, 0xdaf9}, /* '邬' -> 37036 */
{0x90ae, 0xd3ca}, /* '邮' -> 37038 */
{0x90af, 0xbaaa}, /* '邯' -> 37039 */
{0x90b0, 0xdba2}, /* '邰' -> 37040 */
{0x90b1, 0xc7f1}, /* '邱' -> 37041 */
{0x90b3, 0xdafc}, /* '邳' -> 37043 */
{0x90b4, 0xdafb}, /* '邴' -> 37044 */
{0x90b5, 0xc9db}, /* '邵' -> 37045 */
{0x90b6, 0xdafd}, /* '邶' -> 37046 */
{0x90b8, 0xdba1}, /* '邸' -> 37048 */
{0x90b9, 0xd7de}, /* '邹' -> 37049 */
{0x90ba, 0xdafe}, /* '邺' -> 37050 */
{0x90bb, 0xc1da}, /* '邻' -> 37051 */
{0x90be, 0xdba5}, /* '邾' -> 37054 */
{0x90c1, 0xd3f4}, /* '郁' -> 37057 */
{0x90c4, 0xdba7}, /* '郄' -> 37060 */
{0x90c5, 0xdba4}, /* '郅' -> 37061 */
{0x90c7, 0xdba8}, /* '郇' -> 37063 */
{0x90ca, 0xbdbc}, /* '郊' -> 37066 */
{0x90ce, 0xc0c9}, /* '郎' -> 37070 */
{0x90cf, 0xdba3}, /* '郏' -> 37071 */
{0x90d0, 0xdba6}, /* '郐' -> 37072 */
{0x90d1, 0xd6a3}, /* '郑' -> 37073 */
{0x90d3, 0xdba9}, /* '郓' -> 37075 */
{0x90d7, 0xdbad}, /* '郗' -> 37079 */
{0x90db, 0xdbae}, /* '郛' -> 37083 */
{0x90dc, 0xdbac}, /* '郜' -> 37084 */
{0x90dd, 0xbac2}, /* '郝' -> 37085 */
{0x90e1, 0xbfa4}, /* '郡' -> 37089 */
{0x90e2, 0xdbab}, /* '郢' -> 37090 */
{0x90e6, 0xdbaa}, /* '郦' -> 37094 */
{0x90e7, 0xd4c7}, /* '郧' -> 37095 */
{0x90e8, 0xb2bf}, /* '部' -> 37096 */
{0x90eb, 0xdbaf}, /* '郫' -> 37099 */
{0x90ed, 0xb9f9}, /* '郭' -> 37101 */
{0x90ef, 0xdbb0}, /* '郯' -> 37103 */
{0x90f4, 0xb3bb}, /* '郴' -> 37108 */
{0x90f8, 0xb5a6}, /* '郸' -> 37112 */
{0x90fd, 0xb6bc}, /* '都' -> 37117 */
{0x90fe, 0xdbb1}, /* '郾' -> 37118 */
{0x9102, 0xb6f5}, /* '鄂' -> 37122 */
{0x9104, 0xdbb2}, /* '鄄' -> 37124 */
{0x9119, 0xb1c9}, /* '鄙' -> 37145 */
{0x911e, 0xdbb4}, /* '鄞' -> 37150 */
{0x9122, 0xdbb3}, /* '鄢' -> 37154 */
{0x9123, 0xdbb5}, /* '鄣' -> 37155 */
{0x912f, 0xdbb7}, /* '鄯' -> 37167 */
{0x9131, 0xdbb6}, /* '鄱' -> 37169 */
{0x9139, 0xdbb8}, /* '鄹' -> 37177 */
{0x9143, 0xdbb9}, /* '酃' -> 37187 */
{0x9146, 0xdbba}, /* '酆' -> 37190 */
{0x9149, 0xd3cf}, /* '酉' -> 37193 */
{0x914a, 0xf4fa}, /* '酊' -> 37194 */
{0x914b, 0xc7f5}, /* '酋' -> 37195 */
{0x914c, 0xd7c3}, /* '酌' -> 37196 */
{0x914d, 0xc5e4}, /* '配' -> 37197 */
{0x914e, 0xf4fc}, /* '酎' -> 37198 */
{0x914f, 0xf4fd}, /* '酏' -> 37199 */
{0x9150, 0xf4fb}, /* '酐' -> 37200 */
{0x9152, 0xbec6}, /* '酒' -> 37202 */
{0x9157, 0xd0ef}, /* '酗' -> 37207 */
{0x915a, 0xb7d3}, /* '酚' -> 37210 */
{0x915d, 0xd4cd}, /* '酝' -> 37213 */
{0x915e, 0xccaa}, /* '酞' -> 37214 */
{0x9161, 0xf5a2}, /* '酡' -> 37217 */
{0x9162, 0xf5a1}, /* '酢' -> 37218 */
{0x9163, 0xbaa8}, /* '酣' -> 37219 */
{0x9164, 0xf4fe}, /* '酤' -> 37220 */
{0x9165, 0xcbd6}, /* '酥' -> 37221 */
{0x9169, 0xf5a4}, /* '酩' -> 37225 */
{0x916a, 0xc0d2}, /* '酪' -> 37226 */
{0x916c, 0xb3ea}, /* '酬' -> 37228 */
{0x916e, 0xcdaa}, /* '酮' -> 37230 */
{0x916f, 0xf5a5}, /* '酯' -> 37231 */
{0x9170, 0xf5a3}, /* '酰' -> 37232 */
{0x9171, 0xbdb4}, /* '酱' -> 37233 */
{0x9172, 0xf5a8}, /* '酲' -> 37234 */
{0x9174, 0xf5a9}, /* '酴' -> 37236 */
{0x9175, 0xbdcd}, /* '酵' -> 37237 */
{0x9176, 0xc3b8}, /* '酶' -> 37238 */
{0x9177, 0xbfe1}, /* '酷' -> 37239 */
{0x9178, 0xcbe1}, /* '酸' -> 37240 */
{0x9179, 0xf5aa}, /* '酹' -> 37241 */
{0x917d, 0xf5a6}, /* '酽' -> 37245 */
{0x917e, 0xf5a7}, /* '酾' -> 37246 */
{0x917f, 0xc4f0}, /* '酿' -> 37247 */
{0x9185, 0xf5ac}, /* '醅' -> 37253 */
{0x9187, 0xb4bc}, /* '醇' -> 37255 */
{0x9189, 0xd7ed}, /* '醉' -> 37257 */
{0x918b, 0xb4d7}, /* '醋' -> 37259 */
{0x918c, 0xf5ab}, /* '醌' -> 37260 */
{0x918d, 0xf5ae}, /* '醍' -> 37261 */
{0x9190, 0xf5ad}, /* '醐' -> 37264 */
{0x9191, 0xf5af}, /* '醑' -> 37265 */
{0x9192, 0xd0d1}, /* '醒' -> 37266 */
{0x919a, 0xc3d1}, /* '醚' -> 37274 */
{0x919b, 0xc8a9}, /* '醛' -> 37275 */
{0x91a2, 0xf5b0}, /* '醢' -> 37282 */
{0x91a3, 0xf5b1}, /* '醣' -> 37283 */
{0x91aa, 0xf5b2}, /* '醪' -> 37290 */
{0x91ad, 0xf5b3}, /* '醭' -> 37293 */
{0x91ae, 0xf5b4}, /* '醮' -> 37294 */
{0x91af, 0xf5b5}, /* '醯' -> 37295 */
{0x91b4, 0xf5b7}, /* '醴' -> 37300 */
{0x91b5, 0xf5b6}, /* '醵' -> 37301 */
{0x91ba, 0xf5b8}, /* '醺' -> 37306 */
{0x91c7, 0xb2c9}, /* '采' -> 37319 */
{0x91c9, 0xd3d4}, /* '釉' -> 37321 */
{0x91ca, 0xcacd}, /* '释' -> 37322 */
{0x91cc, 0xc0ef}, /* '里' -> 37324 */
{0x91cd, 0xd6d8}, /* '重' -> 37325 */
{0x91ce, 0xd2b0}, /* '野' -> 37326 */
{0x91cf, 0xc1bf}, /* '量' -> 37327 */
{0x91d1, 0xbdf0}, /* '金' -> 37329 */
{0x91dc, 0xb8aa}, /* '釜' -> 37340 */
{0x9274, 0xbcf8}, /* '鉴' -> 37492 */
{0x928e, 0xf6c6}, /* '銎' -> 37518 */
{0x92ae, 0xf6c7}, /* '銮' -> 37550 */
{0x92c8, 0xf6c8}, /* '鋈' -> 37576 */
{0x933e, 0xf6c9}, /* '錾' -> 37694 */
{0x936a, 0xf6ca}, /* '鍪' -> 37738 */
{0x938f, 0xf6cc}, /* '鎏' -> 37775 */
{0x93ca, 0xf6cb}, /* '鏊' -> 37834 */
{0x93d6, 0xf7e9}, /* '鏖' -> 37846 */
{0x943e, 0xf6cd}, /* '鐾' -> 37950 */
{0x946b, 0xf6ce}, /* '鑫' -> 37995 */
{0x9485, 0xeec4}, /* '钅' -> 38021 */
{0x9486, 0xeec5}, /* '钆' -> 38022 */
{0x9487, 0xeec6}, /* '钇' -> 38023 */
{0x9488, 0xd5eb}, /* '针' -> 38024 */
{0x9489, 0xb6a4}, /* '钉' -> 38025 */
{0x948a, 0xeec8}, /* '钊' -> 38026 */
{0x948b, 0xeec7}, /* '钋' -> 38027 */
{0x948c, 0xeec9}, /* '钌' -> 38028 */
{0x948d, 0xeeca}, /* '钍' -> 38029 */
{0x948e, 0xc7a5}, /* '钎' -> 38030 */
{0x948f, 0xeecb}, /* '钏' -> 38031 */
{0x9490, 0xeecc}, /* '钐' -> 38032 */
{0x9492, 0xb7b0}, /* '钒' -> 38034 */
{0x9493, 0xb5f6}, /* '钓' -> 38035 */
{0x9494, 0xeecd}, /* '钔' -> 38036 */
{0x9495, 0xeecf}, /* '钕' -> 38037 */
{0x9497, 0xeece}, /* '钗' -> 38039 */
{0x9499, 0xb8c6}, /* '钙' -> 38041 */
{0x949a, 0xeed0}, /* '钚' -> 38042 */
{0x949b, 0xeed1}, /* '钛' -> 38043 */
{0x949c, 0xeed2}, /* '钜' -> 38044 */
{0x949d, 0xb6db}, /* '钝' -> 38045 */
{0x949e, 0xb3ae}, /* '钞' -> 38046 */
{0x949f, 0xd6d3}, /* '钟' -> 38047 */
{0x94a0, 0xc4c6}, /* '钠' -> 38048 */
{0x94a1, 0xb1b5}, /* '钡' -> 38049 */
{0x94a2, 0xb8d6}, /* '钢' -> 38050 */
{0x94a3, 0xeed3}, /* '钣' -> 38051 */
{0x94a4, 0xeed4}, /* '钤' -> 38052 */
{0x94a5, 0xd4bf}, /* '钥' -> 38053 */
{0x94a6, 0xc7d5}, /* '钦' -> 38054 */
{0x94a7, 0xbefb}, /* '钧' -> 38055 */
{0x94a8, 0xced9}, /* '钨' -> 38056 */
{0x94a9, 0xb9b3}, /* '钩' -> 38057 */
{0x94aa, 0xeed6}, /* '钪' -> 38058 */
{0x94ab, 0xeed5}, /* '钫' -> 38059 */
{0x94ac, 0xeed8}, /* '钬' -> 38060 */
{0x94ad, 0xeed7}, /* '钭' -> 38061 */
{0x94ae, 0xc5a5}, /* '钮' -> 38062 */
{0x94af, 0xeed9}, /* '钯' -> 38063 */
{0x94b0, 0xeeda}, /* '钰' -> 38064 */
{0x94b1, 0xc7ae}, /* '钱' -> 38065 */
{0x94b2, 0xeedb}, /* '钲' -> 38066 */
{0x94b3, 0xc7af}, /* '钳' -> 38067 */
{0x94b4, 0xeedc}, /* '钴' -> 38068 */
{0x94b5, 0xb2a7}, /* '钵' -> 38069 */
{0x94b6, 0xeedd}, /* '钶' -> 38070 */
{0x94b7, 0xeede}, /* '钷' -> 38071 */
{0x94b8, 0xeedf}, /* '钸' -> 38072 */
{0x94b9, 0xeee0}, /* '钹' -> 38073 */
{0x94ba, 0xeee1}, /* '钺' -> 38074 */
{0x94bb, 0xd7ea}, /* '钻' -> 38075 */
{0x94bc, 0xeee2}, /* '钼' -> 38076 */
{0x94bd, 0xeee3}, /* '钽' -> 38077 */
{0x94be, 0xbcd8}, /* '钾' -> 38078 */
{0x94bf, 0xeee4}, /* '钿' -> 38079 */
{0x94c0, 0xd3cb}, /* '铀' -> 38080 */
{0x94c1, 0xccfa}, /* '铁' -> 38081 */
{0x94c2, 0xb2ac}, /* '铂' -> 38082 */
{0x94c3, 0xc1e5}, /* '铃' -> 38083 */
{0x94c4, 0xeee5}, /* '铄' -> 38084 */
{0x94c5, 0xc7a6}, /* '铅' -> 38085 */
{0x94c6, 0xc3ad}, /* '铆' -> 38086 */
{0x94c8, 0xeee6}, /* '铈' -> 38088 */
{0x94c9, 0xeee7}, /* '铉' -> 38089 */
{0x94ca, 0xeee8}, /* '铊' -> 38090 */
{0x94cb, 0xeee9}, /* '铋' -> 38091 */
{0x94cc, 0xeeea}, /* '铌' -> 38092 */
{0x94cd, 0xeeeb}, /* '铍' -> 38093 */
{0x94ce, 0xeeec}, /* '铎' -> 38094 */
{0x94d0, 0xeeed}, /* '铐' -> 38096 */
{0x94d1, 0xeeee}, /* '铑' -> 38097 */
{0x94d2, 0xeeef}, /* '铒' -> 38098 */
{0x94d5, 0xeef0}, /* '铕' -> 38101 */
{0x94d6, 0xeef1}, /* '铖' -> 38102 */
{0x94d7, 0xeef2}, /* '铗' -> 38103 */
{0x94d8, 0xeef4}, /* '铘' -> 38104 */
{0x94d9, 0xeef3}, /* '铙' -> 38105 */
{0x94db, 0xeef5}, /* '铛' -> 38107 */
{0x94dc, 0xcdad}, /* '铜' -> 38108 */
{0x94dd, 0xc2c1}, /* '铝' -> 38109 */
{0x94de, 0xeef6}, /* '铞' -> 38110 */
{0x94df, 0xeef7}, /* '铟' -> 38111 */
{0x94e0, 0xeef8}, /* '铠' -> 38112 */
{0x94e1, 0xd5a1}, /* '铡' -> 38113 */
{0x94e2, 0xeef9}, /* '铢' -> 38114 */
{0x94e3, 0xcfb3}, /* '铣' -> 38115 */
{0x94e4, 0xeefa}, /* '铤' -> 38116 */
{0x94e5, 0xeefb}, /* '铥' -> 38117 */
{0x94e7, 0xeefc}, /* '铧' -> 38119 */
{0x94e8, 0xeefd}, /* '铨' -> 38120 */
{0x94e9, 0xefa1}, /* '铩' -> 38121 */
{0x94ea, 0xeefe}, /* '铪' -> 38122 */
{0x94eb, 0xefa2}, /* '铫' -> 38123 */
{0x94ec, 0xb8f5}, /* '铬' -> 38124 */
{0x94ed, 0xc3fa}, /* '铭' -> 38125 */
{0x94ee, 0xefa3}, /* '铮' -> 38126 */
{0x94ef, 0xefa4}, /* '铯' -> 38127 */
{0x94f0, 0xbdc2}, /* '铰' -> 38128 */
{0x94f1, 0xd2bf}, /* '铱' -> 38129 */
{0x94f2, 0xb2f9}, /* '铲' -> 38130 */
{0x94f3, 0xefa5}, /* '铳' -> 38131 */
{0x94f4, 0xefa6}, /* '铴' -> 38132 */
{0x94f5, 0xefa7}, /* '铵' -> 38133 */
{0x94f6, 0xd2f8}, /* '银' -> 38134 */
{0x94f7, 0xefa8}, /* '铷' -> 38135 */
{0x94f8, 0xd6fd}, /* '铸' -> 38136 */
{0x94f9, 0xefa9}, /* '铹' -> 38137 */
{0x94fa, 0xc6cc}, /* '铺' -> 38138 */
{0x94fc, 0xefaa}, /* '铼' -> 38140 */
{0x94fd, 0xefab}, /* '铽' -> 38141 */
{0x94fe, 0xc1b4}, /* '链' -> 38142 */
{0x94ff, 0xefac}, /* '铿' -> 38143 */
{0x9500, 0xcffa}, /* '销' -> 38144 */
{0x9501, 0xcbf8}, /* '锁' -> 38145 */
{0x9502, 0xefae}, /* '锂' -> 38146 */
{0x9503, 0xefad}, /* '锃' -> 38147 */
{0x9504, 0xb3fa}, /* '锄' -> 38148 */
{0x9505, 0xb9f8}, /* '锅' -> 38149 */
{0x9506, 0xefaf}, /* '锆' -> 38150 */
{0x9507, 0xefb0}, /* '锇' -> 38151 */
{0x9508, 0xd0e2}, /* '锈' -> 38152 */
{0x9509, 0xefb1}, /* '锉' -> 38153 */
{0x950a, 0xefb2}, /* '锊' -> 38154 */
{0x950b, 0xb7e6}, /* '锋' -> 38155 */
{0x950c, 0xd0bf}, /* '锌' -> 38156 */
{0x950d, 0xefb3}, /* '锍' -> 38157 */
{0x950e, 0xefb4}, /* '锎' -> 38158 */
{0x950f, 0xefb5}, /* '锏' -> 38159 */
{0x9510, 0xc8f1}, /* '锐' -> 38160 */
{0x9511, 0xcce0}, /* '锑' -> 38161 */
{0x9512, 0xefb6}, /* '锒' -> 38162 */
{0x9513, 0xefb7}, /* '锓' -> 38163 */
{0x9514, 0xefb8}, /* '锔' -> 38164 */
{0x9515, 0xefb9}, /* '锕' -> 38165 */
{0x9516, 0xefba}, /* '锖' -> 38166 */
{0x9517, 0xd5e0}, /* '锗' -> 38167 */
{0x9518, 0xefbb}, /* '锘' -> 38168 */
{0x9519, 0xb4ed}, /* '错' -> 38169 */
{0x951a, 0xc3aa}, /* '锚' -> 38170 */
{0x951b, 0xefbc}, /* '锛' -> 38171 */
{0x951d, 0xefbd}, /* '锝' -> 38173 */
{0x951e, 0xefbe}, /* '锞' -> 38174 */
{0x951f, 0xefbf}, /* '锟' -> 38175 */
{0x9521, 0xcefd}, /* '锡' -> 38177 */
{0x9522, 0xefc0}, /* '锢' -> 38178 */
{0x9523, 0xc2e0}, /* '锣' -> 38179 */
{0x9524, 0xb4b8}, /* '锤' -> 38180 */
{0x9525, 0xd7b6}, /* '锥' -> 38181 */
{0x9526, 0xbdf5}, /* '锦' -> 38182 */
{0x9528, 0xcfc7}, /* '锨' -> 38184 */
{0x9529, 0xefc3}, /* '锩' -> 38185 */
{0x952a, 0xefc1}, /* '锪' -> 38186 */
{0x952b, 0xefc2}, /* '锫' -> 38187 */
{0x952c, 0xefc4}, /* '锬' -> 38188 */
{0x952d, 0xb6a7}, /* '锭' -> 38189 */
{0x952e, 0xbcfc}, /* '键' -> 38190 */
{0x952f, 0xbee2}, /* '锯' -> 38191 */
{0x9530, 0xc3cc}, /* '锰' -> 38192 */
{0x9531, 0xefc5}, /* '锱' -> 38193 */
{0x9532, 0xefc6}, /* '锲' -> 38194 */
{0x9534, 0xefc7}, /* '锴' -> 38196 */
{0x9535, 0xefcf}, /* '锵' -> 38197 */
{0x9536, 0xefc8}, /* '锶' -> 38198 */
{0x9537, 0xefc9}, /* '锷' -> 38199 */
{0x9538, 0xefca}, /* '锸' -> 38200 */
{0x9539, 0xc7c2}, /* '锹' -> 38201 */
{0x953a, 0xeff1}, /* '锺' -> 38202 */
{0x953b, 0xb6cd}, /* '锻' -> 38203 */
{0x953c, 0xefcb}, /* '锼' -> 38204 */
{0x953e, 0xefcc}, /* '锾' -> 38206 */
{0x953f, 0xefcd}, /* '锿' -> 38207 */
{0x9540, 0xb6c6}, /* '镀' -> 38208 */
{0x9541, 0xc3be}, /* '镁' -> 38209 */
{0x9542, 0xefce}, /* '镂' -> 38210 */
{0x9544, 0xefd0}, /* '镄' -> 38212 */
{0x9545, 0xefd1}, /* '镅' -> 38213 */
{0x9546, 0xefd2}, /* '镆' -> 38214 */
{0x9547, 0xd5f2}, /* '镇' -> 38215 */
{0x9549, 0xefd3}, /* '镉' -> 38217 */
{0x954a, 0xc4f7}, /* '镊' -> 38218 */
{0x954c, 0xefd4}, /* '镌' -> 38220 */
{0x954d, 0xc4f8}, /* '镍' -> 38221 */
{0x954e, 0xefd5}, /* '镎' -> 38222 */
{0x954f, 0xefd6}, /* '镏' -> 38223 */
{0x9550, 0xb8e4}, /* '镐' -> 38224 */
{0x9551, 0xb0f7}, /* '镑' -> 38225 */
{0x9552, 0xefd7}, /* '镒' -> 38226 */
{0x9553, 0xefd8}, /* '镓' -> 38227 */
{0x9554, 0xefd9}, /* '镔' -> 38228 */
{0x9556, 0xefda}, /* '镖' -> 38230 */
{0x9557, 0xefdb}, /* '镗' -> 38231 */
{0x9558, 0xefdc}, /* '镘' -> 38232 */
{0x9559, 0xefdd}, /* '镙' -> 38233 */
{0x955b, 0xefde}, /* '镛' -> 38235 */
{0x955c, 0xbeb5}, /* '镜' -> 38236 */
{0x955d, 0xefe1}, /* '镝' -> 38237 */
{0x955e, 0xefdf}, /* '镞' -> 38238 */
{0x955f, 0xefe0}, /* '镟' -> 38239 */
{0x9561, 0xefe2}, /* '镡' -> 38241 */
{0x9562, 0xefe3}, /* '镢' -> 38242 */
{0x9563, 0xc1cd}, /* '镣' -> 38243 */
{0x9564, 0xefe4}, /* '镤' -> 38244 */
{0x9565, 0xefe5}, /* '镥' -> 38245 */
{0x9566, 0xefe6}, /* '镦' -> 38246 */
{0x9567, 0xefe7}, /* '镧' -> 38247 */
{0x9568, 0xefe8}, /* '镨' -> 38248 */
{0x9569, 0xefe9}, /* '镩' -> 38249 */
{0x956a, 0xefea}, /* '镪' -> 38250 */
{0x956b, 0xefeb}, /* '镫' -> 38251 */
{0x956c, 0xefec}, /* '镬' -> 38252 */
{0x956d, 0xc0d8}, /* '镭' -> 38253 */
{0x956f, 0xefed}, /* '镯' -> 38255 */
{0x9570, 0xc1ad}, /* '镰' -> 38256 */
{0x9571, 0xefee}, /* '镱' -> 38257 */
{0x9572, 0xefef}, /* '镲' -> 38258 */
{0x9573, 0xeff0}, /* '镳' -> 38259 */
{0x9576, 0xcfe2}, /* '镶' -> 38262 */
{0x957f, 0xb3a4}, /* '长' -> 38271 */
{0x95e8, 0xc3c5}, /* '门' -> 38376 */
{0x95e9, 0xe3c5}, /* '闩' -> 38377 */
{0x95ea, 0xc9c1}, /* '闪' -> 38378 */
{0x95eb, 0xe3c6}, /* '闫' -> 38379 */
{0x95ed, 0xb1d5}, /* '闭' -> 38381 */
{0x95ee, 0xceca}, /* '问' -> 38382 */
{0x95ef, 0xb4b3}, /* '闯' -> 38383 */
{0x95f0, 0xc8f2}, /* '闰' -> 38384 */
{0x95f1, 0xe3c7}, /* '闱' -> 38385 */
{0x95f2, 0xcfd0}, /* '闲' -> 38386 */
{0x95f3, 0xe3c8}, /* '闳' -> 38387 */
{0x95f4, 0xbce4}, /* '间' -> 38388 */
{0x95f5, 0xe3c9}, /* '闵' -> 38389 */
{0x95f6, 0xe3ca}, /* '闶' -> 38390 */
{0x95f7, 0xc3c6}, /* '闷' -> 38391 */
{0x95f8, 0xd5a2}, /* '闸' -> 38392 */
{0x95f9, 0xc4d6}, /* '闹' -> 38393 */
{0x95fa, 0xb9eb}, /* '闺' -> 38394 */
{0x95fb, 0xcec5}, /* '闻' -> 38395 */
{0x95fc, 0xe3cb}, /* '闼' -> 38396 */
{0x95fd, 0xc3f6}, /* '闽' -> 38397 */
{0x95fe, 0xe3cc}, /* '闾' -> 38398 */
{0x9600, 0xb7a7}, /* '阀' -> 38400 */
{0x9601, 0xb8f3}, /* '阁' -> 38401 */
{0x9602, 0xbad2}, /* '阂' -> 38402 */
{0x9603, 0xe3cd}, /* '阃' -> 38403 */
{0x9604, 0xe3ce}, /* '阄' -> 38404 */
{0x9605, 0xd4c4}, /* '阅' -> 38405 */
{0x9606, 0xe3cf}, /* '阆' -> 38406 */
{0x9608, 0xe3d0}, /* '阈' -> 38408 */
{0x9609, 0xd1cb}, /* '阉' -> 38409 */
{0x960a, 0xe3d1}, /* '阊' -> 38410 */
{0x960b, 0xe3d2}, /* '阋' -> 38411 */
{0x960c, 0xe3d3}, /* '阌' -> 38412 */
{0x960d, 0xe3d4}, /* '阍' -> 38413 */
{0x960e, 0xd1d6}, /* '阎' -> 38414 */
{0x960f, 0xe3d5}, /* '阏' -> 38415 */
{0x9610, 0xb2fb}, /* '阐' -> 38416 */
{0x9611, 0xc0bb}, /* '阑' -> 38417 */
{0x9612, 0xe3d6}, /* '阒' -> 38418 */
{0x9614, 0xc0ab}, /* '阔' -> 38420 */
{0x9615, 0xe3d7}, /* '阕' -> 38421 */
{0x9616, 0xe3d8}, /* '阖' -> 38422 */
{0x9617, 0xe3d9}, /* '阗' -> 38423 */
{0x9619, 0xe3da}, /* '阙' -> 38425 */
{0x961a, 0xe3db}, /* '阚' -> 38426 */
{0x961c, 0xb8b7}, /* '阜' -> 38428 */
{0x961d, 0xdae2}, /* '阝' -> 38429 */
{0x961f, 0xb6d3}, /* '队' -> 38431 */
{0x9621, 0xdae4}, /* '阡' -> 38433 */
{0x9622, 0xdae3}, /* '阢' -> 38434 */
{0x962a, 0xdae6}, /* '阪' -> 38442 */
{0x962e, 0xc8ee}, /* '阮' -> 38446 */
{0x9631, 0xdae5}, /* '阱' -> 38449 */
{0x9632, 0xb7c0}, /* '防' -> 38450 */
{0x9633, 0xd1f4}, /* '阳' -> 38451 */
{0x9634, 0xd2f5}, /* '阴' -> 38452 */
{0x9635, 0xd5f3}, /* '阵' -> 38453 */
{0x9636, 0xbdd7}, /* '阶' -> 38454 */
{0x963b, 0xd7e8}, /* '阻' -> 38459 */
{0x963c, 0xdae8}, /* '阼' -> 38460 */
{0x963d, 0xdae7}, /* '阽' -> 38461 */
{0x963f, 0xb0a2}, /* '阿' -> 38463 */
{0x9640, 0xcdd3}, /* '陀' -> 38464 */
{0x9642, 0xdae9}, /* '陂' -> 38466 */
{0x9644, 0xb8bd}, /* '附' -> 38468 */
{0x9645, 0xbcca}, /* '际' -> 38469 */
{0x9646, 0xc2bd}, /* '陆' -> 38470 */
{0x9647, 0xc2a4}, /* '陇' -> 38471 */
{0x9648, 0xb3c2}, /* '陈' -> 38472 */
{0x9649, 0xdaea}, /* '陉' -> 38473 */
{0x964b, 0xc2aa}, /* '陋' -> 38475 */
{0x964c, 0xc4b0}, /* '陌' -> 38476 */
{0x964d, 0xbdb5}, /* '降' -> 38477 */
{0x9650, 0xcfde}, /* '限' -> 38480 */
{0x9654, 0xdaeb}, /* '陔' -> 38484 */
{0x9655, 0xc9c2}, /* '陕' -> 38485 */
{0x965b, 0xb1dd}, /* '陛' -> 38491 */
{0x965f, 0xdaec}, /* '陟' -> 38495 */
{0x9661, 0xb6b8}, /* '陡' -> 38497 */
{0x9662, 0xd4ba}, /* '院' -> 38498 */
{0x9664, 0xb3fd}, /* '除' -> 38500 */
{0x9667, 0xdaed}, /* '陧' -> 38503 */
{0x9668, 0xd4c9}, /* '陨' -> 38504 */
{0x9669, 0xcfd5}, /* '险' -> 38505 */
{0x966a, 0xc5e3}, /* '陪' -> 38506 */
{0x966c, 0xdaee}, /* '陬' -> 38508 */
{0x9672, 0xdaef}, /* '陲' -> 38514 */
{0x9674, 0xdaf0}, /* '陴' -> 38516 */
{0x9675, 0xc1ea}, /* '陵' -> 38517 */
{0x9676, 0xccd5}, /* '陶' -> 38518 */
{0x9677, 0xcfdd}, /* '陷' -> 38519 */
{0x9685, 0xd3e7}, /* '隅' -> 38533 */
{0x9686, 0xc2a1}, /* '隆' -> 38534 */
{0x9688, 0xdaf1}, /* '隈' -> 38536 */
{0x968b, 0xcbe5}, /* '隋' -> 38539 */
{0x968d, 0xdaf2}, /* '隍' -> 38541 */
{0x968f, 0xcbe6}, /* '随' -> 38543 */
{0x9690, 0xd2fe}, /* '隐' -> 38544 */
{0x9694, 0xb8f4}, /* '隔' -> 38548 */
{0x9697, 0xdaf3}, /* '隗' -> 38551 */
{0x9698, 0xb0af}, /* '隘' -> 38552 */
{0x9699, 0xcfb6}, /* '隙' -> 38553 */
{0x969c, 0xd5cf}, /* '障' -> 38556 */
{0x96a7, 0xcbed}, /* '隧' -> 38567 */
{0x96b0, 0xdaf4}, /* '隰' -> 38576 */
{0x96b3, 0xe3c4}, /* '隳' -> 38579 */
{0x96b6, 0xc1a5}, /* '隶' -> 38582 */
{0x96b9, 0xf6bf}, /* '隹' -> 38585 */
{0x96bc, 0xf6c0}, /* '隼' -> 38588 */
{0x96bd, 0xf6c1}, /* '隽' -> 38589 */
{0x96be, 0xc4d1}, /* '难' -> 38590 */
{0x96c0, 0xc8b8}, /* '雀' -> 38592 */
{0x96c1, 0xd1e3}, /* '雁' -> 38593 */
{0x96c4, 0xd0db}, /* '雄' -> 38596 */
{0x96c5, 0xd1c5}, /* '雅' -> 38597 */
{0x96c6, 0xbcaf}, /* '集' -> 38598 */
{0x96c7, 0xb9cd}, /* '雇' -> 38599 */
{0x96c9, 0xeff4}, /* '雉' -> 38601 */
{0x96cc, 0xb4c6}, /* '雌' -> 38604 */
{0x96cd, 0xd3ba}, /* '雍' -> 38605 */
{0x96ce, 0xf6c2}, /* '雎' -> 38606 */
{0x96cf, 0xb3fb}, /* '雏' -> 38607 */
{0x96d2, 0xf6c3}, /* '雒' -> 38610 */
{0x96d5, 0xb5f1}, /* '雕' -> 38613 */
{0x96e0, 0xf6c5}, /* '雠' -> 38624 */
{0x96e8, 0xd3ea}, /* '雨' -> 38632 */
{0x96e9, 0xf6a7}, /* '雩' -> 38633 */
{0x96ea, 0xd1a9}, /* '雪' -> 38634 */
{0x96ef, 0xf6a9}, /* '雯' -> 38639 */
{0x96f3, 0xf6a8}, /* '雳' -> 38643 */
{0x96f6, 0xc1e3}, /* '零' -> 38646 */
{0x96f7, 0xc0d7}, /* '雷' -> 38647 */
{0x96f9, 0xb1a2}, /* '雹' -> 38649 */
{0x96fe, 0xceed}, /* '雾' -> 38654 */
{0x9700, 0xd0e8}, /* '需' -> 38656 */
{0x9701, 0xf6ab}, /* '霁' -> 38657 */
{0x9704, 0xcff6}, /* '霄' -> 38660 */
{0x9706, 0xf6aa}, /* '霆' -> 38662 */
{0x9707, 0xd5f0}, /* '震' -> 38663 */
{0x9708, 0xf6ac}, /* '霈' -> 38664 */
{0x9709, 0xc3b9}, /* '霉' -> 38665 */
{0x970d, 0xbbf4}, /* '霍' -> 38669 */
{0x970e, 0xf6ae}, /* '霎' -> 38670 */
{0x970f, 0xf6ad}, /* '霏' -> 38671 */
{0x9713, 0xc4de}, /* '霓' -> 38675 */
{0x9716, 0xc1d8}, /* '霖' -> 38678 */
{0x971c, 0xcbaa}, /* '霜' -> 38684 */
{0x971e, 0xcfbc}, /* '霞' -> 38686 */
{0x972a, 0xf6af}, /* '霪' -> 38698 */
{0x972d, 0xf6b0}, /* '霭' -> 38701 */
{0x9730, 0xf6b1}, /* '霰' -> 38704 */
{0x9732, 0xc2b6}, /* '露' -> 38706 */
{0x9738, 0xb0d4}, /* '霸' -> 38712 */
{0x9739, 0xc5f9}, /* '霹' -> 38713 */
{0x973e, 0xf6b2}, /* '霾' -> 38718 */
{0x9752, 0xc7e0}, /* '青' -> 38738 */
{0x9753, 0xf6a6}, /* '靓' -> 38739 */
{0x9756, 0xbeb8}, /* '靖' -> 38742 */
{0x9759, 0xbeb2}, /* '静' -> 38745 */
{0x975b, 0xb5e5}, /* '靛' -> 38747 */
{0x975e, 0xb7c7}, /* '非' -> 38750 */
{0x9760, 0xbfbf}, /* '靠' -> 38752 */
{0x9761, 0xc3d2}, /* '靡' -> 38753 */
{0x9762, 0xc3e6}, /* '面' -> 38754 */
{0x9765, 0xd8cc}, /* '靥' -> 38757 */
{0x9769, 0xb8ef}, /* '革' -> 38761 */
{0x9773, 0xbdf9}, /* '靳' -> 38771 */
{0x9774, 0xd1a5}, /* '靴' -> 38772 */
{0x9776, 0xb0d0}, /* '靶' -> 38774 */
{0x977c, 0xf7b0}, /* '靼' -> 38780 */
{0x9785, 0xf7b1}, /* '鞅' -> 38789 */
{0x978b, 0xd0ac}, /* '鞋' -> 38795 */
{0x978d, 0xb0b0}, /* '鞍' -> 38797 */
{0x9791, 0xf7b2}, /* '鞑' -> 38801 */
{0x9792, 0xf7b3}, /* '鞒' -> 38802 */
{0x9794, 0xf7b4}, /* '鞔' -> 38804 */
{0x9798, 0xc7ca}, /* '鞘' -> 38808 */
{0x97a0, 0xbecf}, /* '鞠' -> 38816 */
{0x97a3, 0xf7b7}, /* '鞣' -> 38819 */
{0x97ab, 0xf7b6}, /* '鞫' -> 38827 */
{0x97ad, 0xb1de}, /* '鞭' -> 38829 */
{0x97af, 0xf7b5}, /* '鞯' -> 38831 */
{0x97b2, 0xf7b8}, /* '鞲' -> 38834 */
{0x97b4, 0xf7b9}, /* '鞴' -> 38836 */
{0x97e6, 0xcea4}, /* '韦' -> 38886 */
{0x97e7, 0xc8cd}, /* '韧' -> 38887 */
{0x97e9, 0xbaab}, /* '韩' -> 38889 */
{0x97ea, 0xe8b8}, /* '韪' -> 38890 */
{0x97eb, 0xe8b9}, /* '韫' -> 38891 */
{0x97ec, 0xe8ba}, /* '韬' -> 38892 */
{0x97ed, 0xbec2}, /* '韭' -> 38893 */
{0x97f3, 0xd2f4}, /* '音' -> 38899 */
{0x97f5, 0xd4cf}, /* '韵' -> 38901 */
{0x97f6, 0xc9d8}, /* '韶' -> 38902 */
{0x9875, 0xd2b3}, /* '页' -> 39029 */
{0x9876, 0xb6a5}, /* '顶' -> 39030 */
{0x9877, 0xc7ea}, /* '顷' -> 39031 */
{0x9878, 0xf1fc}, /* '顸' -> 39032 */
{0x9879, 0xcfee}, /* '项' -> 39033 */
{0x987a, 0xcbb3}, /* '顺' -> 39034 */
{0x987b, 0xd0eb}, /* '须' -> 39035 */
{0x987c, 0xe7ef}, /* '顼' -> 39036 */
{0x987d, 0xcde7}, /* '顽' -> 39037 */
{0x987e, 0xb9cb}, /* '顾' -> 39038 */
{0x987f, 0xb6d9}, /* '顿' -> 39039 */
{0x9880, 0xf1fd}, /* '颀' -> 39040 */
{0x9881, 0xb0e4}, /* '颁' -> 39041 */
{0x9882, 0xcbcc}, /* '颂' -> 39042 */
{0x9883, 0xf1fe}, /* '颃' -> 39043 */
{0x9884, 0xd4a4}, /* '预' -> 39044 */
{0x9885, 0xc2ad}, /* '颅' -> 39045 */
{0x9886, 0xc1ec}, /* '领' -> 39046 */
{0x9887, 0xc6c4}, /* '颇' -> 39047 */
{0x9888, 0xbeb1}, /* '颈' -> 39048 */
{0x9889, 0xf2a1}, /* '颉' -> 39049 */
{0x988a, 0xbcd5}, /* '颊' -> 39050 */
{0x988c, 0xf2a2}, /* '颌' -> 39052 */
{0x988d, 0xf2a3}, /* '颍' -> 39053 */
{0x988f, 0xf2a4}, /* '颏' -> 39055 */
{0x9890, 0xd2c3}, /* '颐' -> 39056 */
{0x9891, 0xc6b5}, /* '频' -> 39057 */
{0x9893, 0xcdc7}, /* '颓' -> 39059 */
{0x9894, 0xf2a5}, /* '颔' -> 39060 */
{0x9896, 0xd3b1}, /* '颖' -> 39062 */
{0x9897, 0xbfc5}, /* '颗' -> 39063 */
{0x9898, 0xcce2}, /* '题' -> 39064 */
{0x989a, 0xf2a6}, /* '颚' -> 39066 */
{0x989b, 0xf2a7}, /* '颛' -> 39067 */
{0x989c, 0xd1d5}, /* '颜' -> 39068 */
{0x989d, 0xb6ee}, /* '额' -> 39069 */
{0x989e, 0xf2a8}, /* '颞' -> 39070 */
{0x989f, 0xf2a9}, /* '颟' -> 39071 */
{0x98a0, 0xb5df}, /* '颠' -> 39072 */
{0x98a1, 0xf2aa}, /* '颡' -> 39073 */
{0x98a2, 0xf2ab}, /* '颢' -> 39074 */
{0x98a4, 0xb2fc}, /* '颤' -> 39076 */
{0x98a5, 0xf2ac}, /* '颥' -> 39077 */
{0x98a6, 0xf2ad}, /* '颦' -> 39078 */
{0x98a7, 0xc8a7}, /* '颧' -> 39079 */
{0x98ce, 0xb7e7}, /* '风' -> 39118 */
{0x98d1, 0xeca9}, /* '飑' -> 39121 */
{0x98d2, 0xecaa}, /* '飒' -> 39122 */
{0x98d3, 0xecab}, /* '飓' -> 39123 */
{0x98d5, 0xecac}, /* '飕' -> 39125 */
{0x98d8, 0xc6ae}, /* '飘' -> 39128 */
{0x98d9, 0xecad}, /* '飙' -> 39129 */
{0x98da, 0xecae}, /* '飚' -> 39130 */
{0x98de, 0xb7c9}, /* '飞' -> 39134 */
{0x98df, 0xcab3}, /* '食' -> 39135 */
{0x98e7, 0xe2b8}, /* '飧' -> 39143 */
{0x98e8, 0xf7cf}, /* '飨' -> 39144 */
{0x990d, 0xf7d0}, /* '餍' -> 39181 */
{0x9910, 0xb2cd}, /* '餐' -> 39184 */
{0x992e, 0xf7d1}, /* '餮' -> 39214 */
{0x9954, 0xf7d3}, /* '饔' -> 39252 */
{0x9955, 0xf7d2}, /* '饕' -> 39253 */
{0x9963, 0xe2bb}, /* '饣' -> 39267 */
{0x9965, 0xbca2}, /* '饥' -> 39269 */
{0x9967, 0xe2bc}, /* '饧' -> 39271 */
{0x9968, 0xe2bd}, /* '饨' -> 39272 */
{0x9969, 0xe2be}, /* '饩' -> 39273 */
{0x996a, 0xe2bf}, /* '饪' -> 39274 */
{0x996b, 0xe2c0}, /* '饫' -> 39275 */
{0x996c, 0xe2c1}, /* '饬' -> 39276 */
{0x996d, 0xb7b9}, /* '饭' -> 39277 */
{0x996e, 0xd2fb}, /* '饮' -> 39278 */
{0x996f, 0xbda4}, /* '饯' -> 39279 */
{0x9970, 0xcace}, /* '饰' -> 39280 */
{0x9971, 0xb1a5}, /* '饱' -> 39281 */
{0x9972, 0xcbc7}, /* '饲' -> 39282 */
{0x9974, 0xe2c2}, /* '饴' -> 39284 */
{0x9975, 0xb6fc}, /* '饵' -> 39285 */
{0x9976, 0xc8c4}, /* '饶' -> 39286 */
{0x9977, 0xe2c3}, /* '饷' -> 39287 */
{0x997a, 0xbdc8}, /* '饺' -> 39290 */
{0x997c, 0xb1fd}, /* '饼' -> 39292 */
{0x997d, 0xe2c4}, /* '饽' -> 39293 */
{0x997f, 0xb6f6}, /* '饿' -> 39295 */
{0x9980, 0xe2c5}, /* '馀' -> 39296 */
{0x9981, 0xc4d9}, /* '馁' -> 39297 */
{0x9984, 0xe2c6}, /* '馄' -> 39300 */
{0x9985, 0xcfda}, /* '馅' -> 39301 */
{0x9986, 0xb9dd}, /* '馆' -> 39302 */
{0x9987, 0xe2c7}, /* '馇' -> 39303 */
{0x9988, 0xc0a1}, /* '馈' -> 39304 */
{0x998a, 0xe2c8}, /* '馊' -> 39306 */
{0x998b, 0xb2f6}, /* '馋' -> 39307 */
{0x998d, 0xe2c9}, /* '馍' -> 39309 */
{0x998f, 0xc1f3}, /* '馏' -> 39311 */
{0x9990, 0xe2ca}, /* '馐' -> 39312 */
{0x9991, 0xe2cb}, /* '馑' -> 39313 */
{0x9992, 0xc2f8}, /* '馒' -> 39314 */
{0x9993, 0xe2cc}, /* '馓' -> 39315 */
{0x9994, 0xe2cd}, /* '馔' -> 39316 */
{0x9995, 0xe2ce}, /* '馕' -> 39317 */
{0x9996, 0xcad7}, /* '首' -> 39318 */
{0x9997, 0xd8b8}, /* '馗' -> 39319 */
{0x9998, 0xd9e5}, /* '馘' -> 39320 */
{0x9999, 0xcfe3}, /* '香' -> 39321 */
{0x99a5, 0xf0a5}, /* '馥' -> 39333 */
{0x99a8, 0xdcb0}, /* '馨' -> 39336 */
{0x9a6c, 0xc2ed}, /* '马' -> 39532 */
{0x9a6d, 0xd4a6}, /* '驭' -> 39533 */
{0x9a6e, 0xcdd4}, /* '驮' -> 39534 */
{0x9a6f, 0xd1b1}, /* '驯' -> 39535 */
{0x9a70, 0xb3db}, /* '驰' -> 39536 */
{0x9a71, 0xc7fd}, /* '驱' -> 39537 */
{0x9a73, 0xb2b5}, /* '驳' -> 39539 */
{0x9a74, 0xc2bf}, /* '驴' -> 39540 */
{0x9a75, 0xe6e0}, /* '驵' -> 39541 */
{0x9a76, 0xcabb}, /* '驶' -> 39542 */
{0x9a77, 0xe6e1}, /* '驷' -> 39543 */
{0x9a78, 0xe6e2}, /* '驸' -> 39544 */
{0x9a79, 0xbed4}, /* '驹' -> 39545 */
{0x9a7a, 0xe6e3}, /* '驺' -> 39546 */
{0x9a7b, 0xd7a4}, /* '驻' -> 39547 */
{0x9a7c, 0xcdd5}, /* '驼' -> 39548 */
{0x9a7d, 0xe6e5}, /* '驽' -> 39549 */
{0x9a7e, 0xbcdd}, /* '驾' -> 39550 */
{0x9a7f, 0xe6e4}, /* '驿' -> 39551 */
{0x9a80, 0xe6e6}, /* '骀' -> 39552 */
{0x9a81, 0xe6e7}, /* '骁' -> 39553 */
{0x9a82, 0xc2ee}, /* '骂' -> 39554 */
{0x9a84, 0xbdbe}, /* '骄' -> 39556 */
{0x9a85, 0xe6e8}, /* '骅' -> 39557 */
{0x9a86, 0xc2e6}, /* '骆' -> 39558 */
{0x9a87, 0xbaa7}, /* '骇' -> 39559 */
{0x9a88, 0xe6e9}, /* '骈' -> 39560 */
{0x9a8a, 0xe6ea}, /* '骊' -> 39562 */
{0x9a8b, 0xb3d2}, /* '骋' -> 39563 */
{0x9a8c, 0xd1e9}, /* '验' -> 39564 */
{0x9a8f, 0xbfa5}, /* '骏' -> 39567 */
{0x9a90, 0xe6eb}, /* '骐' -> 39568 */
{0x9a91, 0xc6ef}, /* '骑' -> 39569 */
{0x9a92, 0xe6ec}, /* '骒' -> 39570 */
{0x9a93, 0xe6ed}, /* '骓' -> 39571 */
{0x9a96, 0xe6ee}, /* '骖' -> 39574 */
{0x9a97, 0xc6ad}, /* '骗' -> 39575 */
{0x9a98, 0xe6ef}, /* '骘' -> 39576 */
{0x9a9a, 0xc9a7}, /* '骚' -> 39578 */
{0x9a9b, 0xe6f0}, /* '骛' -> 39579 */
{0x9a9c, 0xe6f1}, /* '骜' -> 39580 */
{0x9a9d, 0xe6f2}, /* '骝' -> 39581 */
{0x9a9e, 0xe5b9}, /* '骞' -> 39582 */
{0x9a9f, 0xe6f3}, /* '骟' -> 39583 */
{0x9aa0, 0xe6f4}, /* '骠' -> 39584 */
{0x9aa1, 0xc2e2}, /* '骡' -> 39585 */
{0x9aa2, 0xe6f5}, /* '骢' -> 39586 */
{0x9aa3, 0xe6f6}, /* '骣' -> 39587 */
{0x9aa4, 0xd6e8}, /* '骤' -> 39588 */
{0x9aa5, 0xe6f7}, /* '骥' -> 39589 */
{0x9aa7, 0xe6f8}, /* '骧' -> 39591 */
{0x9aa8, 0xb9c7}, /* '骨' -> 39592 */
{0x9ab0, 0xf7bb}, /* '骰' -> 39600 */
{0x9ab1, 0xf7ba}, /* '骱' -> 39601 */
{0x9ab6, 0xf7be}, /* '骶' -> 39606 */
{0x9ab7, 0xf7bc}, /* '骷' -> 39607 */
{0x9ab8, 0xbaa1}, /* '骸' -> 39608 */
{0x9aba, 0xf7bf}, /* '骺' -> 39610 */
{0x9abc, 0xf7c0}, /* '骼' -> 39612 */
{0x9ac0, 0xf7c2}, /* '髀' -> 39616 */
{0x9ac1, 0xf7c1}, /* '髁' -> 39617 */
{0x9ac2, 0xf7c4}, /* '髂' -> 39618 */
{0x9ac5, 0xf7c3}, /* '髅' -> 39621 */
{0x9acb, 0xf7c5}, /* '髋' -> 39627 */
{0x9acc, 0xf7c6}, /* '髌' -> 39628 */
{0x9ad1, 0xf7c7}, /* '髑' -> 39633 */
{0x9ad3, 0xcbe8}, /* '髓' -> 39635 */
{0x9ad8, 0xb8df}, /* '高' -> 39640 */
{0x9adf, 0xf7d4}, /* '髟' -> 39647 */
{0x9ae1, 0xf7d5}, /* '髡' -> 39649 */
{0x9ae6, 0xf7d6}, /* '髦' -> 39654 */
{0x9aeb, 0xf7d8}, /* '髫' -> 39659 */
{0x9aed, 0xf7da}, /* '髭' -> 39661 */
{0x9aef, 0xf7d7}, /* '髯' -> 39663 */
{0x9af9, 0xf7db}, /* '髹' -> 39673 */
{0x9afb, 0xf7d9}, /* '髻' -> 39675 */
{0x9b03, 0xd7d7}, /* '鬃' -> 39683 */
{0x9b08, 0xf7dc}, /* '鬈' -> 39688 */
{0x9b0f, 0xf7dd}, /* '鬏' -> 39695 */
{0x9b13, 0xf7de}, /* '鬓' -> 39699 */
{0x9b1f, 0xf7df}, /* '鬟' -> 39711 */
{0x9b23, 0xf7e0}, /* '鬣' -> 39715 */
{0x9b2f, 0xdbcb}, /* '鬯' -> 39727 */
{0x9b32, 0xd8aa}, /* '鬲' -> 39730 */
{0x9b3b, 0xe5f7}, /* '鬻' -> 39739 */
{0x9b3c, 0xb9ed}, /* '鬼' -> 39740 */
{0x9b41, 0xbffd}, /* '魁' -> 39745 */
{0x9b42, 0xbbea}, /* '魂' -> 39746 */
{0x9b43, 0xf7c9}, /* '魃' -> 39747 */
{0x9b44, 0xc6c7}, /* '魄' -> 39748 */
{0x9b45, 0xf7c8}, /* '魅' -> 39749 */
{0x9b47, 0xf7ca}, /* '魇' -> 39751 */
{0x9b48, 0xf7cc}, /* '魈' -> 39752 */
{0x9b49, 0xf7cb}, /* '魉' -> 39753 */
{0x9b4d, 0xf7cd}, /* '魍' -> 39757 */
{0x9b4f, 0xceba}, /* '魏' -> 39759 */
{0x9b51, 0xf7ce}, /* '魑' -> 39761 */
{0x9b54, 0xc4a7}, /* '魔' -> 39764 */
{0x9c7c, 0xd3e3}, /* '鱼' -> 40060 */
{0x9c7f, 0xf6cf}, /* '鱿' -> 40063 */
{0x9c81, 0xc2b3}, /* '鲁' -> 40065 */
{0x9c82, 0xf6d0}, /* '鲂' -> 40066 */
{0x9c85, 0xf6d1}, /* '鲅' -> 40069 */
{0x9c86, 0xf6d2}, /* '鲆' -> 40070 */
{0x9c87, 0xf6d3}, /* '鲇' -> 40071 */
{0x9c88, 0xf6d4}, /* '鲈' -> 40072 */
{0x9c8b, 0xf6d6}, /* '鲋' -> 40075 */
{0x9c8d, 0xb1ab}, /* '鲍' -> 40077 */
{0x9c8e, 0xf6d7}, /* '鲎' -> 40078 */
{0x9c90, 0xf6d8}, /* '鲐' -> 40080 */
{0x9c91, 0xf6d9}, /* '鲑' -> 40081 */
{0x9c92, 0xf6da}, /* '鲒' -> 40082 */
{0x9c94, 0xf6db}, /* '鲔' -> 40084 */
{0x9c95, 0xf6dc}, /* '鲕' -> 40085 */
{0x9c9a, 0xf6dd}, /* '鲚' -> 40090 */
{0x9c9b, 0xf6de}, /* '鲛' -> 40091 */
{0x9c9c, 0xcfca}, /* '鲜' -> 40092 */
{0x9c9e, 0xf6df}, /* '鲞' -> 40094 */
{0x9c9f, 0xf6e0}, /* '鲟' -> 40095 */
{0x9ca0, 0xf6e1}, /* '鲠' -> 40096 */
{0x9ca1, 0xf6e2}, /* '鲡' -> 40097 */
{0x9ca2, 0xf6e3}, /* '鲢' -> 40098 */
{0x9ca3, 0xf6e4}, /* '鲣' -> 40099 */
{0x9ca4, 0xc0f0}, /* '鲤' -> 40100 */
{0x9ca5, 0xf6e5}, /* '鲥' -> 40101 */
{0x9ca6, 0xf6e6}, /* '鲦' -> 40102 */
{0x9ca7, 0xf6e7}, /* '鲧' -> 40103 */
{0x9ca8, 0xf6e8}, /* '鲨' -> 40104 */
{0x9ca9, 0xf6e9}, /* '鲩' -> 40105 */
{0x9cab, 0xf6ea}, /* '鲫' -> 40107 */
{0x9cad, 0xf6eb}, /* '鲭' -> 40109 */
{0x9cae, 0xf6ec}, /* '鲮' -> 40110 */
{0x9cb0, 0xf6ed}, /* '鲰' -> 40112 */
{0x9cb1, 0xf6ee}, /* '鲱' -> 40113 */
{0x9cb2, 0xf6ef}, /* '鲲' -> 40114 */
{0x9cb3, 0xf6f0}, /* '鲳' -> 40115 */
{0x9cb4, 0xf6f1}, /* '鲴' -> 40116 */
{0x9cb5, 0xf6f2}, /* '鲵' -> 40117 */
{0x9cb6, 0xf6f3}, /* '鲶' -> 40118 */
{0x9cb7, 0xf6f4}, /* '鲷' -> 40119 */
{0x9cb8, 0xbea8}, /* '鲸' -> 40120 */
{0x9cba, 0xf6f5}, /* '鲺' -> 40122 */
{0x9cbb, 0xf6f6}, /* '鲻' -> 40123 */
{0x9cbc, 0xf6f7}, /* '鲼' -> 40124 */
{0x9cbd, 0xf6f8}, /* '鲽' -> 40125 */
{0x9cc3, 0xc8fa}, /* '鳃' -> 40131 */
{0x9cc4, 0xf6f9}, /* '鳄' -> 40132 */
{0x9cc5, 0xf6fa}, /* '鳅' -> 40133 */
{0x9cc6, 0xf6fb}, /* '鳆' -> 40134 */
{0x9cc7, 0xf6fc}, /* '鳇' -> 40135 */
{0x9cca, 0xf6fd}, /* '鳊' -> 40138 */
{0x9ccb, 0xf6fe}, /* '鳋' -> 40139 */
{0x9ccc, 0xf7a1}, /* '鳌' -> 40140 */
{0x9ccd, 0xf7a2}, /* '鳍' -> 40141 */
{0x9cce, 0xf7a3}, /* '鳎' -> 40142 */
{0x9ccf, 0xf7a4}, /* '鳏' -> 40143 */
{0x9cd0, 0xf7a5}, /* '鳐' -> 40144 */
{0x9cd3, 0xf7a6}, /* '鳓' -> 40147 */
{0x9cd4, 0xf7a7}, /* '鳔' -> 40148 */
{0x9cd5, 0xf7a8}, /* '鳕' -> 40149 */
{0x9cd6, 0xb1ee}, /* '鳖' -> 40150 */
{0x9cd7, 0xf7a9}, /* '鳗' -> 40151 */
{0x9cd8, 0xf7aa}, /* '鳘' -> 40152 */
{0x9cd9, 0xf7ab}, /* '鳙' -> 40153 */
{0x9cdc, 0xf7ac}, /* '鳜' -> 40156 */
{0x9cdd, 0xf7ad}, /* '鳝' -> 40157 */
{0x9cde, 0xc1db}, /* '鳞' -> 40158 */
{0x9cdf, 0xf7ae}, /* '鳟' -> 40159 */
{0x9ce2, 0xf7af}, /* '鳢' -> 40162 */
{0x9e1f, 0xc4f1}, /* '鸟' -> 40479 */
{0x9e20, 0xf0af}, /* '鸠' -> 40480 */
{0x9e21, 0xbca6}, /* '鸡' -> 40481 */
{0x9e22, 0xf0b0}, /* '鸢' -> 40482 */
{0x9e23, 0xc3f9}, /* '鸣' -> 40483 */
{0x9e25, 0xc5b8}, /* '鸥' -> 40485 */
{0x9e26, 0xd1bb}, /* '鸦' -> 40486 */
{0x9e28, 0xf0b1}, /* '鸨' -> 40488 */
{0x9e29, 0xf0b2}, /* '鸩' -> 40489 */
{0x9e2a, 0xf0b3}, /* '鸪' -> 40490 */
{0x9e2b, 0xf0b4}, /* '鸫' -> 40491 */
{0x9e2c, 0xf0b5}, /* '鸬' -> 40492 */
{0x9e2d, 0xd1bc}, /* '鸭' -> 40493 */
{0x9e2f, 0xd1ec}, /* '鸯' -> 40495 */
{0x9e31, 0xf0b7}, /* '鸱' -> 40497 */
{0x9e32, 0xf0b6}, /* '鸲' -> 40498 */
{0x9e33, 0xd4a7}, /* '鸳' -> 40499 */
{0x9e35, 0xcdd2}, /* '鸵' -> 40501 */
{0x9e36, 0xf0b8}, /* '鸶' -> 40502 */
{0x9e37, 0xf0ba}, /* '鸷' -> 40503 */
{0x9e38, 0xf0b9}, /* '鸸' -> 40504 */
{0x9e39, 0xf0bb}, /* '鸹' -> 40505 */
{0x9e3a, 0xf0bc}, /* '鸺' -> 40506 */
{0x9e3d, 0xb8eb}, /* '鸽' -> 40509 */
{0x9e3e, 0xf0bd}, /* '鸾' -> 40510 */
{0x9e3f, 0xbae8}, /* '鸿' -> 40511 */
{0x9e41, 0xf0be}, /* '鹁' -> 40513 */
{0x9e42, 0xf0bf}, /* '鹂' -> 40514 */
{0x9e43, 0xbee9}, /* '鹃' -> 40515 */
{0x9e44, 0xf0c0}, /* '鹄' -> 40516 */
{0x9e45, 0xb6ec}, /* '鹅' -> 40517 */
{0x9e46, 0xf0c1}, /* '鹆' -> 40518 */
{0x9e47, 0xf0c2}, /* '鹇' -> 40519 */
{0x9e48, 0xf0c3}, /* '鹈' -> 40520 */
{0x9e49, 0xf0c4}, /* '鹉' -> 40521 */
{0x9e4a, 0xc8b5}, /* '鹊' -> 40522 */
{0x9e4b, 0xf0c5}, /* '鹋' -> 40523 */
{0x9e4c, 0xf0c6}, /* '鹌' -> 40524 */
{0x9e4e, 0xf0c7}, /* '鹎' -> 40526 */
{0x9e4f, 0xc5f4}, /* '鹏' -> 40527 */
{0x9e51, 0xf0c8}, /* '鹑' -> 40529 */
{0x9e55, 0xf0c9}, /* '鹕' -> 40533 */
{0x9e57, 0xf0ca}, /* '鹗' -> 40535 */
{0x9e58, 0xf7bd}, /* '鹘' -> 40536 */
{0x9e5a, 0xf0cb}, /* '鹚' -> 40538 */
{0x9e5b, 0xf0cc}, /* '鹛' -> 40539 */
{0x9e5c, 0xf0cd}, /* '鹜' -> 40540 */
{0x9e5e, 0xf0ce}, /* '鹞' -> 40542 */
{0x9e63, 0xf0cf}, /* '鹣' -> 40547 */
{0x9e64, 0xbad7}, /* '鹤' -> 40548 */
{0x9e66, 0xf0d0}, /* '鹦' -> 40550 */
{0x9e67, 0xf0d1}, /* '鹧' -> 40551 */
{0x9e68, 0xf0d2}, /* '鹨' -> 40552 */
{0x9e69, 0xf0d3}, /* '鹩' -> 40553 */
{0x9e6a, 0xf0d4}, /* '鹪' -> 40554 */
{0x9e6b, 0xf0d5}, /* '鹫' -> 40555 */
{0x9e6c, 0xf0d6}, /* '鹬' -> 40556 */
{0x9e6d, 0xf0d8}, /* '鹭' -> 40557 */
{0x9e70, 0xd3a5}, /* '鹰' -> 40560 */
{0x9e71, 0xf0d7}, /* '鹱' -> 40561 */
{0x9e73, 0xf0d9}, /* '鹳' -> 40563 */
{0x9e7e, 0xf5ba}, /* '鹾' -> 40574 */
{0x9e7f, 0xc2b9}, /* '鹿' -> 40575 */
{0x9e82, 0xf7e4}, /* '麂' -> 40578 */
{0x9e87, 0xf7e5}, /* '麇' -> 40583 */
{0x9e88, 0xf7e6}, /* '麈' -> 40584 */
{0x9e8b, 0xf7e7}, /* '麋' -> 40587 */
{0x9e92, 0xf7e8}, /* '麒' -> 40594 */
{0x9e93, 0xc2b4}, /* '麓' -> 40595 */
{0x9e9d, 0xf7ea}, /* '麝' -> 40605 */
{0x9e9f, 0xf7eb}, /* '麟' -> 40607 */
{0x9ea6, 0xc2f3}, /* '麦' -> 40614 */
{0x9eb4, 0xf4f0}, /* '麴' -> 40628 */
{0x9eb8, 0xf4ef}, /* '麸' -> 40632 */
{0x9ebb, 0xc2e9}, /* '麻' -> 40635 */
{0x9ebd, 0xf7e1}, /* '麽' -> 40637 */
{0x9ebe, 0xf7e2}, /* '麾' -> 40638 */
{0x9ec4, 0xbbc6}, /* '黄' -> 40644 */
{0x9ec9, 0xd9e4}, /* '黉' -> 40649 */
{0x9ecd, 0xcaf2}, /* '黍' -> 40653 */
{0x9ece, 0xc0e8}, /* '黎' -> 40654 */
{0x9ecf, 0xf0a4}, /* '黏' -> 40655 */
{0x9ed1, 0xbada}, /* '黑' -> 40657 */
{0x9ed4, 0xc7ad}, /* '黔' -> 40660 */
{0x9ed8, 0xc4ac}, /* '默' -> 40664 */
{0x9edb, 0xf7ec}, /* '黛' -> 40667 */
{0x9edc, 0xf7ed}, /* '黜' -> 40668 */
{0x9edd, 0xf7ee}, /* '黝' -> 40669 */
{0x9edf, 0xf7f0}, /* '黟' -> 40671 */
{0x9ee0, 0xf7ef}, /* '黠' -> 40672 */
{0x9ee2, 0xf7f1}, /* '黢' -> 40674 */
{0x9ee5, 0xf7f4}, /* '黥' -> 40677 */
{0x9ee7, 0xf7f3}, /* '黧' -> 40679 */
{0x9ee9, 0xf7f2}, /* '黩' -> 40681 */
{0x9eea, 0xf7f5}, /* '黪' -> 40682 */
{0x9eef, 0xf7f6}, /* '黯' -> 40687 */
{0x9ef9, 0xede9}, /* '黹' -> 40697 */
{0x9efb, 0xedea}, /* '黻' -> 40699 */
{0x9efc, 0xedeb}, /* '黼' -> 40700 */
{0x9efe, 0xf6bc}, /* '黾' -> 40702 */
{0x9f0b, 0xf6bd}, /* '鼋' -> 40715 */
{0x9f0d, 0xf6be}, /* '鼍' -> 40717 */
{0x9f0e, 0xb6a6}, /* '鼎' -> 40718 */
{0x9f10, 0xd8be}, /* '鼐' -> 40720 */
{0x9f13, 0xb9c4}, /* '鼓' -> 40723 */
{0x9f17, 0xd8bb}, /* '鼗' -> 40727 */
{0x9f19, 0xdcb1}, /* '鼙' -> 40729 */
{0x9f20, 0xcaf3}, /* '鼠' -> 40736 */
{0x9f22, 0xf7f7}, /* '鼢' -> 40738 */
{0x9f2c, 0xf7f8}, /* '鼬' -> 40748 */
{0x9f2f, 0xf7f9}, /* '鼯' -> 40751 */
{0x9f37, 0xf7fb}, /* '鼷' -> 40759 */
{0x9f39, 0xf7fa}, /* '鼹' -> 40761 */
{0x9f3b, 0xb1c7}, /* '鼻' -> 40763 */
{0x9f3d, 0xf7fc}, /* '鼽' -> 40765 */
{0x9f3e, 0xf7fd}, /* '鼾' -> 40766 */
{0x9f44, 0xf7fe}, /* '齄' -> 40772 */
{0x9f50, 0xc6eb}, /* '齐' -> 40784 */
{0x9f51, 0xecb4}, /* '齑' -> 40785 */
{0x9f7f, 0xb3dd}, /* '齿' -> 40831 */
{0x9f80, 0xf6b3}, /* '龀' -> 40832 */
{0x9f83, 0xf6b4}, /* '龃' -> 40835 */
{0x9f84, 0xc1e4}, /* '龄' -> 40836 */
{0x9f85, 0xf6b5}, /* '龅' -> 40837 */
{0x9f86, 0xf6b6}, /* '龆' -> 40838 */
{0x9f87, 0xf6b7}, /* '龇' -> 40839 */
{0x9f88, 0xf6b8}, /* '龈' -> 40840 */
{0x9f89, 0xf6b9}, /* '龉' -> 40841 */
{0x9f8a, 0xf6ba}, /* '龊' -> 40842 */
{0x9f8b, 0xc8a3}, /* '龋' -> 40843 */
{0x9f8c, 0xf6bb}, /* '龌' -> 40844 */
{0x9f99, 0xc1fa}, /* '龙' -> 40857 */
{0x9f9a, 0xb9a8}, /* '龚' -> 40858 */
{0x9f9b, 0xede8}, /* '龛' -> 40859 */
{0x9f9f, 0xb9ea}, /* '龟' -> 40863 */
{0x9fa0, 0xd9df}, /* '龠' -> 40864 */
{0xff01, 0xa3a1}, /* '!' -> 65281 */
{0xff02, 0xa3a2}, /* '"' -> 65282 */
{0xff03, 0xa3a3}, /* '#' -> 65283 */
{0xff04, 0xa1e7}, /* '$' -> 65284 */
{0xff05, 0xa3a5}, /* '%' -> 65285 */
{0xff06, 0xa3a6}, /* '&' -> 65286 */
{0xff07, 0xa3a7}, /* ''' -> 65287 */
{0xff08, 0xa3a8}, /* '(' -> 65288 */
{0xff09, 0xa3a9}, /* ')' -> 65289 */
{0xff0a, 0xa3aa}, /* '*' -> 65290 */
{0xff0b, 0xa3ab}, /* '+' -> 65291 */
{0xff0c, 0xa3ac}, /* ',' -> 65292 */
{0xff0d, 0xa3ad}, /* '-' -> 65293 */
{0xff0e, 0xa3ae}, /* '.' -> 65294 */
{0xff0f, 0xa3af}, /* '/' -> 65295 */
{0xff10, 0xa3b0}, /* '0' -> 65296 */
{0xff11, 0xa3b1}, /* '1' -> 65297 */
{0xff12, 0xa3b2}, /* '2' -> 65298 */
{0xff13, 0xa3b3}, /* '3' -> 65299 */
{0xff14, 0xa3b4}, /* '4' -> 65300 */
{0xff15, 0xa3b5}, /* '5' -> 65301 */
{0xff16, 0xa3b6}, /* '6' -> 65302 */
{0xff17, 0xa3b7}, /* '7' -> 65303 */
{0xff18, 0xa3b8}, /* '8' -> 65304 */
{0xff19, 0xa3b9}, /* '9' -> 65305 */
{0xff1a, 0xa3ba}, /* ':' -> 65306 */
{0xff1b, 0xa3bb}, /* ';' -> 65307 */
{0xff1c, 0xa3bc}, /* '<' -> 65308 */
{0xff1d, 0xa3bd}, /* '=' -> 65309 */
{0xff1e, 0xa3be}, /* '>' -> 65310 */
{0xff1f, 0xa3bf}, /* '?' -> 65311 */
{0xff20, 0xa3c0}, /* '@' -> 65312 */
{0xff21, 0xa3c1}, /* 'a' -> 65313 */
{0xff22, 0xa3c2}, /* 'b' -> 65314 */
{0xff23, 0xa3c3}, /* 'c' -> 65315 */
{0xff24, 0xa3c4}, /* 'd' -> 65316 */
{0xff25, 0xa3c5}, /* 'e' -> 65317 */
{0xff26, 0xa3c6}, /* 'f' -> 65318 */
{0xff27, 0xa3c7}, /* 'g' -> 65319 */
{0xff28, 0xa3c8}, /* 'h' -> 65320 */
{0xff29, 0xa3c9}, /* 'i' -> 65321 */
{0xff2a, 0xa3ca}, /* 'j' -> 65322 */
{0xff2b, 0xa3cb}, /* 'k' -> 65323 */
{0xff2c, 0xa3cc}, /* 'l' -> 65324 */
{0xff2d, 0xa3cd}, /* 'm' -> 65325 */
{0xff2e, 0xa3ce}, /* 'n' -> 65326 */
{0xff2f, 0xa3cf}, /* 'o' -> 65327 */
{0xff30, 0xa3d0}, /* 'p' -> 65328 */
{0xff31, 0xa3d1}, /* 'q' -> 65329 */
{0xff32, 0xa3d2}, /* 'r' -> 65330 */
{0xff33, 0xa3d3}, /* 's' -> 65331 */
{0xff34, 0xa3d4}, /* 't' -> 65332 */
{0xff35, 0xa3d5}, /* 'u' -> 65333 */
{0xff36, 0xa3d6}, /* 'v' -> 65334 */
{0xff37, 0xa3d7}, /* 'w' -> 65335 */
{0xff38, 0xa3d8}, /* 'x' -> 65336 */
{0xff39, 0xa3d9}, /* 'y' -> 65337 */
{0xff3a, 0xa3da}, /* 'z' -> 65338 */
{0xff3b, 0xa3db}, /* '[' -> 65339 */
{0xff3c, 0xa3dc}, /* '\' -> 65340 */
{0xff3d, 0xa3dd}, /* ']' -> 65341 */
{0xff3e, 0xa3de}, /* '^' -> 65342 */
{0xff3f, 0xa3df}, /* '_' -> 65343 */
{0xff40, 0xa3e0}, /* '`' -> 65344 */
{0xff41, 0xa3e1}, /* 'a' -> 65345 */
{0xff42, 0xa3e2}, /* 'b' -> 65346 */
{0xff43, 0xa3e3}, /* 'c' -> 65347 */
{0xff44, 0xa3e4}, /* 'd' -> 65348 */
{0xff45, 0xa3e5}, /* 'e' -> 65349 */
{0xff46, 0xa3e6}, /* 'f' -> 65350 */
{0xff47, 0xa3e7}, /* 'g' -> 65351 */
{0xff48, 0xa3e8}, /* 'h' -> 65352 */
{0xff49, 0xa3e9}, /* 'i' -> 65353 */
{0xff4a, 0xa3ea}, /* 'j' -> 65354 */
{0xff4b, 0xa3eb}, /* 'k' -> 65355 */
{0xff4c, 0xa3ec}, /* 'l' -> 65356 */
{0xff4d, 0xa3ed}, /* 'm' -> 65357 */
{0xff4e, 0xa3ee}, /* 'n' -> 65358 */
{0xff4f, 0xa3ef}, /* 'o' -> 65359 */
{0xff50, 0xa3f0}, /* 'p' -> 65360 */
{0xff51, 0xa3f1}, /* 'q' -> 65361 */
{0xff52, 0xa3f2}, /* 'r' -> 65362 */
{0xff53, 0xa3f3}, /* 's' -> 65363 */
{0xff54, 0xa3f4}, /* 't' -> 65364 */
{0xff55, 0xa3f5}, /* 'u' -> 65365 */
{0xff56, 0xa3f6}, /* 'v' -> 65366 */
{0xff57, 0xa3f7}, /* 'w' -> 65367 */
{0xff58, 0xa3f8}, /* 'x' -> 65368 */
{0xff59, 0xa3f9}, /* 'y' -> 65369 */
{0xff5a, 0xa3fa}, /* 'z' -> 65370 */
{0xff5b, 0xa3fb}, /* '{' -> 65371 */
{0xff5c, 0xa3fc}, /* '|' -> 65372 */
{0xff5d, 0xa3fd}, /* '}' -> 65373 */
{0xff5e, 0xa1ab}, /* '~' -> 65374 */
{0xffe0, 0xa1e9}, /* '¢' -> 65504 */
{0xffe1, 0xa1ea}, /* '£' -> 65505 */
{0xffe3, 0xa3fe}, /* ' ̄' -> 65507 */
{0xffe5, 0xa3a4} /* '¥' -> 65509 */
};
tb_size_t g_charset_gb2312_to_ucs4_table_size = sizeof(g_charset_gb2312_to_ucs4_table_data);
tb_size_t g_charset_ucs4_to_gb2312_table_size = sizeof(g_charset_ucs4_to_gb2312_table_data);
tbox-1.7.6/src/tbox/charset/iso8859.c 0000664 0000000 0000000 00000003455 14671175054 0017212 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file iso8859.c
* @ingroup charset
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../stream/stream.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_long_t tb_charset_iso8859_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch);
tb_long_t tb_charset_iso8859_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch)
{
tb_byte_t b = tb_static_stream_read_u8(sstream);
if (b < 0xa0) *ch = b;
else
{
// @note: need lookup characters table
tb_trace_d("iso8859: unknown character: %x", b);
*ch = 0;
}
return 1;
}
tb_long_t tb_charset_iso8859_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch);
tb_long_t tb_charset_iso8859_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch)
{
if (ch <= 0xa0) tb_static_stream_writ_u8(sstream, (tb_uint8_t)ch);
else
{
// @note: need lookup characters table
tb_trace_d("iso8859: unknown character: %x", ch);
}
return 1;
}
tbox-1.7.6/src/tbox/charset/prefix.h 0000664 0000000 0000000 00000001577 14671175054 0017367 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_CHARSET_PREFIX_H
#define TB_CHARSET_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/charset/ucs2.c 0000664 0000000 0000000 00000003144 14671175054 0016731 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file ucs2.c
* @ingroup charset
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../stream/stream.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_long_t tb_charset_ucs2_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch);
tb_long_t tb_charset_ucs2_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch)
{
*ch = be? tb_static_stream_read_u16_be(sstream) : tb_static_stream_read_u16_le(sstream);
return 1;
}
tb_long_t tb_charset_ucs2_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch);
tb_long_t tb_charset_ucs2_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch)
{
if (ch > 0xffff) ch = 0xfffd;
if (be) tb_static_stream_writ_u16_be(sstream, ch);
else tb_static_stream_writ_u16_le(sstream, ch);
return 1;
}
tbox-1.7.6/src/tbox/charset/ucs4.c 0000664 0000000 0000000 00000003104 14671175054 0016727 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file ucs4.c
* @ingroup charset
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../stream/stream.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_long_t tb_charset_ucs4_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch);
tb_long_t tb_charset_ucs4_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch)
{
*ch = be ? tb_static_stream_read_u32_be(sstream) : tb_static_stream_read_u32_le(sstream);
return 1;
}
tb_long_t tb_charset_ucs4_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch);
tb_long_t tb_charset_ucs4_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch)
{
if (be) tb_static_stream_writ_u32_be(sstream, ch);
else tb_static_stream_writ_u32_le(sstream, ch);
return 1;
}
tbox-1.7.6/src/tbox/charset/utf16.c 0000664 0000000 0000000 00000006443 14671175054 0017027 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file utf16.c
* @ingroup charset
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../stream/stream.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_long_t tb_charset_utf16_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch);
tb_long_t tb_charset_utf16_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch)
{
// init
tb_byte_t const* p = tb_static_stream_pos(sstream);
tb_byte_t const* q = p;
tb_size_t n = tb_static_stream_left(sstream);
// not enough? break it
tb_check_return_val(n > 1, -1);
// the first character
tb_uint32_t c = be? tb_bits_get_u16_be(p) : tb_bits_get_u16_le(p);
p += 2;
// large?
if (c >= 0xd800 && c <= 0xdbff)
{
// not enough? break it
tb_check_return_val(n > 3, -1);
// the next character
tb_uint32_t c2 = be? tb_bits_get_u16_be(p) : tb_bits_get_u16_le(p);
if (c2 >= 0xdc00 && c2 <= 0xdfff)
{
c = ((c - 0xd800) << 10) + (c2 - 0xdc00) + 0x0010000;
p += 2;
}
};
// next
if (p > q) tb_static_stream_skip(sstream, p - q);
// set character
*ch = c;
// ok?
return p > q? 1 : 0;
}
tb_long_t tb_charset_utf16_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch);
tb_long_t tb_charset_utf16_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch)
{
// init
tb_size_t n = tb_static_stream_left(sstream);
if (ch <= 0x0000ffff)
{
// not enough? break it
tb_check_return_val(n > 1, -1);
// set character
if (be) tb_static_stream_writ_u16_be(sstream, ch);
else tb_static_stream_writ_u16_le(sstream, ch);
}
else if (ch > 0x0010ffff)
{
// not enough? break it
tb_check_return_val(n > 1, -1);
// set character
if (be) tb_static_stream_writ_u16_be(sstream, 0x0000fffd);
else tb_static_stream_writ_u16_le(sstream, 0x0000fffd);
}
else
{
// not enough? break it
tb_check_return_val(n > 3, -1);
// set character
ch -= 0x0010000;
if (be)
{
tb_static_stream_writ_u16_be(sstream, (ch >> 10) + 0xd800);
tb_static_stream_writ_u16_be(sstream, (ch & 0x3ff) + 0xdc00);
}
else
{
tb_static_stream_writ_u16_le(sstream, (ch >> 10) + 0xd800);
tb_static_stream_writ_u16_le(sstream, (ch & 0x3ff) + 0xdc00);
}
}
// ok
return 1;
}
tbox-1.7.6/src/tbox/charset/utf32.c 0000664 0000000 0000000 00000003111 14671175054 0017012 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file utf32.c
* @ingroup charset
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../stream/stream.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_long_t tb_charset_utf32_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch);
tb_long_t tb_charset_utf32_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch)
{
*ch = be ? tb_static_stream_read_u32_be(sstream) : tb_static_stream_read_u32_le(sstream);
return 1;
}
tb_long_t tb_charset_utf32_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch);
tb_long_t tb_charset_utf32_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch)
{
if (be) tb_static_stream_writ_u32_be(sstream, ch);
else tb_static_stream_writ_u32_le(sstream, ch);
return 1;
}
tbox-1.7.6/src/tbox/charset/utf8.c 0000664 0000000 0000000 00000015022 14671175054 0016741 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file utf8.c
* @ingroup charset
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../stream/stream.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
/*
* 0x00000000 - 0x0000007f: 0xxxxxxx
* 0x00000080 - 0x000007ff: 110xxxxx 10xxxxxx
* 0x00000800 - 0x0000ffff: 1110xxxx 10xxxxxx 10xxxxxx
* 0x00010000 - 0x001fffff: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
* 0x00200000 - 0x03ffffff: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
* 0x04000000 - 0x7fffffff: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
*/
tb_long_t tb_charset_utf8_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch);
tb_long_t tb_charset_utf8_get(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t* ch)
{
// init
tb_byte_t const* p = tb_static_stream_pos(sstream);
tb_byte_t const* q = p;
tb_size_t n = tb_static_stream_left(sstream);
// 0x00000000 - 0x0000007f
if (!(*p & 0x80))
{
// not enough? break it
tb_check_return_val(n, -1);
// get character
*ch = *p++;
}
// 0x00000080 - 0x000007ff
else if ((*p & 0xe0) == 0xc0)
{
// not enough? break it
tb_check_return_val(n > 1, -1);
// get character
*ch = ((((tb_uint32_t)(p[0] & 0x1f)) << 6) | (p[1] & 0x3f));
p += 2;
}
// 0x00000800 - 0x0000ffff
else if ((*p & 0xf0) == 0xe0)
{
// not enough? break it
tb_check_return_val(n > 2, -1);
// get character
*ch = ((((tb_uint32_t)(p[0] & 0x0f)) << 12) | (((tb_uint32_t)(p[1] & 0x3f)) << 6) | (p[2] & 0x3f));
p += 3;
}
// 0x00010000 - 0x001fffff
else if ((*p & 0xf8) == 0xf0)
{
// not enough? break it
tb_check_return_val(n > 3, -1);
// get character
*ch = ((((tb_uint32_t)(p[0] & 0x07)) << 18) | (((tb_uint32_t)(p[1] & 0x3f)) << 12) | (((tb_uint32_t)(p[2] & 0x3f)) << 6) | (p[3] & 0x3f));
p += 4;
}
// 0x00200000 - 0x03ffffff
else if ((*p & 0xfc) == 0xf8)
{
// not enough? break it
tb_check_return_val(n > 4, -1);
// get character
*ch = ((((tb_uint32_t)(p[0] & 0x03)) << 24) | (((tb_uint32_t)(p[1] & 0x3f)) << 18) | (((tb_uint32_t)(p[2] & 0x3f)) << 12) | (((tb_uint32_t)(p[3] & 0x3f)) << 6) | (p[4] & 0x3f));
p += 5;
}
// 0x04000000 - 0x7fffffff
else if ((*p & 0xfe) == 0xfc)
{
// not enough? break it
tb_check_return_val(n > 5, -1);
// get character
*ch = ((((tb_uint32_t)(p[0] & 0x01)) << 30) | (((tb_uint32_t)(p[1] & 0x3f)) << 24) | (((tb_uint32_t)(p[2] & 0x3f)) << 18) | (((tb_uint32_t)(p[3] & 0x3f)) << 12) | (((tb_uint32_t)(p[4] & 0x3f)) << 6) | (p[5] & 0x3f));
p += 6;
}
else
{
// invalid character
tb_trace_d("invalid utf8 character: %x", *p);
// skip it
tb_static_stream_skip(sstream, 1);
// no character
return 0;
}
// next
if (p > q) tb_static_stream_skip(sstream, p - q);
// ok?
return p > q? 1 : 0;
}
tb_long_t tb_charset_utf8_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch);
tb_long_t tb_charset_utf8_set(tb_static_stream_ref_t sstream, tb_bool_t be, tb_uint32_t ch)
{
// init
tb_byte_t* p = (tb_byte_t*)tb_static_stream_pos(sstream);
tb_byte_t* q = p;
tb_size_t n = tb_static_stream_left(sstream);
// 0x00000000 - 0x0000007f
if (ch <= 0x0000007f)
{
// not enough? break it
tb_check_return_val(n, -1);
// set character
*p++ = ch;
}
// 0x00000080 - 0x000007ff
else if (ch <= 0x000007ff)
{
// not enough? break it
tb_check_return_val(n > 1, -1);
// set character
// 110xxxxx 10xxxxxx
// xxx xxxxxxxx
*p++ = ((ch >> 6) & 0x1f) | 0xc0;
*p++ = (ch & 0x3f) | 0x80;
}
// 0x00000800 - 0x0000ffff
else if (ch <= 0x0000ffff)
{
// not enough? break it
tb_check_return_val(n > 2, -1);
// set character
// 1110xxxx 10xxxxxx 10xxxxxx
// xxxxxxxx xxxxxxxx
*p++ = ((ch >> 12) & 0x0f) | 0xe0;
*p++ = ((ch >> 6) & 0x3f) | 0x80;
*p++ = (ch & 0x3f) | 0x80;
}
// 0x00010000 - 0x001fffff
else if (ch <= 0x001fffff)
{
// not enough? break it
tb_check_return_val(n > 3, -1);
// set character
// 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
// xxxxx xxxxxxxx xxxxxxxx
*p++ = ((ch >> 18) & 0x07) | 0xf0;
*p++ = ((ch >> 12) & 0x3f) | 0x80;
*p++ = ((ch >> 6) & 0x3f) | 0x80;
*p++ = (ch & 0x3f) | 0x80;
}
// 0x00200000 - 0x03ffffff
else if (ch <= 0x03ffffff)
{
// not enough? break it
tb_check_return_val(n > 4, -1);
// set character
// 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
// xx xxxxxxxx xxxxxxxx xxxxxxxx
*p++ = ((ch >> 24) & 0x03) | 0xf8;
*p++ = ((ch >> 18) & 0x3f) | 0x80;
*p++ = ((ch >> 12) & 0x3f) | 0x80;
*p++ = ((ch >> 6) & 0x3f) | 0x80;
*p++ = (ch & 0x3f) | 0x80;
}
// 0x04000000 - 0x7fffffff
else if (ch <= 0x7fffffff)
{
// not enough? break it
tb_check_return_val(n > 5, -1);
// set character
// 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
// xxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
*p++ = ((ch >> 30) & 0x01) | 0xfc;
*p++ = ((ch >> 24) & 0x3f) | 0x80;
*p++ = ((ch >> 18) & 0x3f) | 0x80;
*p++ = ((ch >> 12) & 0x3f) | 0x80;
*p++ = ((ch >> 6) & 0x3f) | 0x80;
*p++ = (ch & 0x3f) | 0x80;
}
// next
if (p > q) tb_static_stream_skip(sstream, p - q);
// ok?
return p > q? 1 : 0;
}
tbox-1.7.6/src/tbox/config.h 0000664 0000000 0000000 00000001575 14671175054 0015704 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file config.h
*
*/
#ifndef TB_TBOX_CONFIG_H
#define TB_TBOX_CONFIG_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "tbox.config.h"
#endif
tbox-1.7.6/src/tbox/container/ 0000775 0000000 0000000 00000000000 14671175054 0016240 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/container/array_iterator.c 0000664 0000000 0000000 00000024062 14671175054 0021437 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file array_iterator.c
* @ingroup container
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../libc/libc.h"
#include "../utils/utils.h"
#include "../memory/memory.h"
#include "../object/object.h"
#include "../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* iterator implementation for pointer element
*/
static tb_size_t tb_array_iterator_ptr_size(tb_iterator_ref_t iterator)
{
// check
tb_assert(iterator);
// the size
return ((tb_array_iterator_ref_t)iterator)->count;
}
static tb_size_t tb_array_iterator_ptr_head(tb_iterator_ref_t iterator)
{
return 0;
}
static tb_size_t tb_array_iterator_ptr_tail(tb_iterator_ref_t iterator)
{
// check
tb_assert(iterator);
// the tail
return ((tb_array_iterator_ref_t)iterator)->count;
}
static tb_size_t tb_array_iterator_ptr_next(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_assert(iterator && itor < ((tb_array_iterator_ref_t)iterator)->count);
// the next
return itor + 1;
}
static tb_size_t tb_array_iterator_ptr_prev(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_assert(iterator && itor);
// the prev
return itor - 1;
}
static tb_pointer_t tb_array_iterator_ptr_item(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_assert(iterator && itor < ((tb_array_iterator_ref_t)iterator)->count);
// the item
return ((tb_pointer_t*)((tb_array_iterator_ref_t)iterator)->items)[itor];
}
static tb_void_t tb_array_iterator_ptr_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item)
{
// check
tb_assert(iterator && itor < ((tb_array_iterator_ref_t)iterator)->count);
// copy
((tb_cpointer_t*)((tb_array_iterator_ref_t)iterator)->items)[itor] = item;
}
static tb_long_t tb_array_iterator_ptr_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem)
{
return (litem < ritem)? -1 : (litem > ritem);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* iterator implementation for memory element
*/
static tb_pointer_t tb_array_iterator_mem_item(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_assert(iterator && itor < ((tb_array_iterator_ref_t)iterator)->count);
// the item
return (tb_pointer_t)((tb_byte_t*)((tb_array_iterator_ref_t)iterator)->items + itor * iterator->step);
}
static tb_void_t tb_array_iterator_mem_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item)
{
// check
tb_assert(iterator && itor < ((tb_array_iterator_ref_t)iterator)->count);
// copy
tb_memcpy((tb_byte_t*)((tb_array_iterator_ref_t)iterator)->items + itor * iterator->step, item, iterator->step);
}
static tb_long_t tb_array_iterator_mem_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem)
{
// check
tb_assert(litem && ritem);
// compare it
return tb_memcmp(litem, ritem, iterator->step);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* iterator implementation for c-string element
*/
static tb_long_t tb_array_iterator_str_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem)
{
// check
tb_assert(litem && ritem);
// compare it
return tb_strcmp((tb_char_t const*)litem, (tb_char_t const*)ritem);
}
static tb_long_t tb_array_iterator_istr_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem)
{
// check
tb_assert(litem && ritem);
// compare it
return tb_stricmp((tb_char_t const*)litem, (tb_char_t const*)ritem);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* iterator implementation for long element
*/
static tb_long_t tb_array_iterator_long_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem)
{
return ((tb_long_t)litem < (tb_long_t)ritem)? -1 : ((tb_long_t)litem > (tb_long_t)ritem);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_iterator_ref_t tb_array_iterator_init_ptr(tb_array_iterator_ref_t iterator, tb_pointer_t* items, tb_size_t count)
{
// check
tb_assert(iterator && items && count);
// init operation
static tb_iterator_op_t op =
{
tb_array_iterator_ptr_size
, tb_array_iterator_ptr_head
, tb_null
, tb_array_iterator_ptr_tail
, tb_array_iterator_ptr_prev
, tb_array_iterator_ptr_next
, tb_array_iterator_ptr_item
, tb_array_iterator_ptr_comp
, tb_array_iterator_ptr_copy
, tb_null
, tb_null
};
// init iterator
iterator->base.priv = tb_null;
iterator->base.step = sizeof(tb_pointer_t);
iterator->base.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE | TB_ITERATOR_MODE_RACCESS | TB_ITERATOR_MODE_MUTABLE;
iterator->base.flag = TB_ITERATOR_FLAG_ITEM_VAL;
iterator->base.op = &op;
iterator->items = items;
iterator->count = count;
// ok
return (tb_iterator_ref_t)iterator;
}
tb_iterator_ref_t tb_array_iterator_init_mem(tb_array_iterator_ref_t iterator, tb_pointer_t items, tb_size_t count, tb_size_t size)
{
// check
tb_assert(iterator && items && count && size);
// init operation
static tb_iterator_op_t op =
{
tb_array_iterator_ptr_size
, tb_array_iterator_ptr_head
, tb_null
, tb_array_iterator_ptr_tail
, tb_array_iterator_ptr_prev
, tb_array_iterator_ptr_next
, tb_array_iterator_mem_item
, tb_array_iterator_mem_comp
, tb_array_iterator_mem_copy
, tb_null
, tb_null
};
// init
iterator->base.priv = tb_null;
iterator->base.step = size;
iterator->base.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE | TB_ITERATOR_MODE_RACCESS | TB_ITERATOR_MODE_MUTABLE;
iterator->base.flag = TB_ITERATOR_FLAG_ITEM_REF;
iterator->base.op = &op;
iterator->items = items;
iterator->count = count;
// ok
return (tb_iterator_ref_t)iterator;
}
tb_iterator_ref_t tb_array_iterator_init_str(tb_array_iterator_ref_t iterator, tb_char_t** items, tb_size_t count)
{
// check
tb_assert(iterator && items && count);
// init operation
static tb_iterator_op_t op =
{
tb_array_iterator_ptr_size
, tb_array_iterator_ptr_head
, tb_null
, tb_array_iterator_ptr_tail
, tb_array_iterator_ptr_prev
, tb_array_iterator_ptr_next
, tb_array_iterator_ptr_item
, tb_array_iterator_str_comp
, tb_array_iterator_ptr_copy
, tb_null
, tb_null
};
// init iterator
iterator->base.priv = tb_null;
iterator->base.step = sizeof(tb_char_t const*);
iterator->base.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE | TB_ITERATOR_MODE_RACCESS | TB_ITERATOR_MODE_MUTABLE;
iterator->base.flag = TB_ITERATOR_FLAG_ITEM_VAL;
iterator->base.op = &op;
iterator->items = items;
iterator->count = count;
// ok
return (tb_iterator_ref_t)iterator;
}
tb_iterator_ref_t tb_array_iterator_init_istr(tb_array_iterator_ref_t iterator, tb_char_t** items, tb_size_t count)
{
// check
tb_assert(iterator && items && count);
// init operation
static tb_iterator_op_t op =
{
tb_array_iterator_ptr_size
, tb_array_iterator_ptr_head
, tb_null
, tb_array_iterator_ptr_tail
, tb_array_iterator_ptr_prev
, tb_array_iterator_ptr_next
, tb_array_iterator_ptr_item
, tb_array_iterator_istr_comp
, tb_array_iterator_ptr_copy
, tb_null
, tb_null
};
// init iterator
iterator->base.priv = tb_null;
iterator->base.step = sizeof(tb_char_t const*);
iterator->base.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE | TB_ITERATOR_MODE_RACCESS | TB_ITERATOR_MODE_MUTABLE;
iterator->base.flag = TB_ITERATOR_FLAG_ITEM_VAL;
iterator->base.op = &op;
iterator->items = items;
iterator->count = count;
// ok
return (tb_iterator_ref_t)iterator;
}
tb_iterator_ref_t tb_array_iterator_init_size(tb_array_iterator_ref_t iterator, tb_size_t* items, tb_size_t count)
{
return tb_array_iterator_init_ptr(iterator, (tb_pointer_t*)items, count);
}
tb_iterator_ref_t tb_array_iterator_init_long(tb_array_iterator_ref_t iterator, tb_long_t* items, tb_size_t count)
{
// check
tb_assert(iterator && items && count);
// init operation
static tb_iterator_op_t op =
{
tb_array_iterator_ptr_size
, tb_array_iterator_ptr_head
, tb_null
, tb_array_iterator_ptr_tail
, tb_array_iterator_ptr_prev
, tb_array_iterator_ptr_next
, tb_array_iterator_ptr_item
, tb_array_iterator_long_comp
, tb_array_iterator_ptr_copy
, tb_null
, tb_null
};
// init iterator
iterator->base.priv = tb_null;
iterator->base.step = sizeof(tb_long_t);
iterator->base.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE | TB_ITERATOR_MODE_RACCESS | TB_ITERATOR_MODE_MUTABLE;
iterator->base.flag = TB_ITERATOR_FLAG_ITEM_VAL;
iterator->base.op = &op;
iterator->items = items;
iterator->count = count;
// ok
return (tb_iterator_ref_t)iterator;
}
tbox-1.7.6/src/tbox/container/array_iterator.h 0000664 0000000 0000000 00000007024 14671175054 0021443 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file array_iterator.h
* @ingroup container
*
*/
#ifndef TB_CONTAINER_ARRAY_ITERATOR_H
#define TB_CONTAINER_ARRAY_ITERATOR_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "iterator.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the array iterator type
typedef struct __tb_array_iterator_t
{
/// the iterator base
tb_iterator_t base;
/// the items
tb_pointer_t items;
/// the items count
tb_size_t count;
}tb_array_iterator_t, *tb_array_iterator_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init array iterator for pointer element
*
* @param iterator the array iterator
* @param items the items
* @param count the count
*
* @return the iterator
*/
tb_iterator_ref_t tb_array_iterator_init_ptr(tb_array_iterator_ref_t iterator, tb_pointer_t* items, tb_size_t count);
/*! init array iterator for memory element
*
* @param iterator the array iterator
* @param items the items
* @param count the count
* @param size the element size
*
* @return the iterator
*/
tb_iterator_ref_t tb_array_iterator_init_mem(tb_array_iterator_ref_t iterator, tb_pointer_t items, tb_size_t count, tb_size_t size);
/*! init array iterator for c-string element
*
* @param iterator the array iterator
* @param items the items
* @param count the count
*
* @return the iterator
*/
tb_iterator_ref_t tb_array_iterator_init_str(tb_array_iterator_ref_t iterator, tb_char_t** items, tb_size_t count);
/*! init array iterator for c-string element and ignore case
*
* @param iterator the array iterator
* @param items the items
* @param count the count
*
* @return the iterator
*/
tb_iterator_ref_t tb_array_iterator_init_istr(tb_array_iterator_ref_t iterator, tb_char_t** items, tb_size_t count);
/*! init array iterator for long element
*
* @param iterator the array iterator
* @param items the items
* @param count the count
*
* @return the iterator
*/
tb_iterator_ref_t tb_array_iterator_init_long(tb_array_iterator_ref_t iterator, tb_long_t* items, tb_size_t count);
/*! init array iterator for size element
*
* @param iterator the array iterator
* @param items the items
* @param count the count
*
* @return the iterator
*/
tb_iterator_ref_t tb_array_iterator_init_size(tb_array_iterator_ref_t iterator, tb_size_t* items, tb_size_t count);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/container/bloom_filter.c 0000664 0000000 0000000 00000035120 14671175054 0021062 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file bloom_filter.c
* @ingroup container
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "bloom_filter"
#define TB_TRACE_MODULE_DEBUG (1)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "bloom_filter.h"
#include "../libc/libc.h"
#include "../libm/libm.h"
#include "../math/math.h"
#include "../utils/utils.h"
#include "../memory/memory.h"
#include "../stream/stream.h"
#include "../platform/platform.h"
#include "../algorithm/algorithm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the data size maxn
#ifdef __tb_small__
# define TB_BLOOM_FILTER_DATA_MAXN (1 << 28)
#else
# define TB_BLOOM_FILTER_DATA_MAXN (1 << 30)
#endif
// the item default maxn
#ifdef __tb_small__
# define TB_BLOOM_FILTER_ITEM_MAXN_DEFAULT TB_BLOOM_FILTER_ITEM_MAXN_MICRO
#else
# define TB_BLOOM_FILTER_ITEM_MAXN_DEFAULT TB_BLOOM_FILTER_ITEM_MAXN_SMALL
#endif
// the bit sets
#define tb_bloom_filter_set1(data, i) do {(data)[(i) >> 3] |= (0x1 << ((i) & 7));} while (0)
#define tb_bloom_filter_set0(data, i) do {(data)[(i) >> 3] &= ~(0x1 << ((i) & 7));} while (0)
#define tb_bloom_filter_bset(data, i) ((data)[(i) >> 3] & (0x1 << ((i) & 7)))
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the bloom filter type
typedef struct __tb_bloom_filter_t
{
// the probability
tb_size_t probability;
// the hash count
tb_size_t hash_count;
// the maxn
tb_size_t maxn;
// the element
tb_element_t element;
// the size
tb_size_t size;
// the data
tb_byte_t* data;
// the hash mask
tb_size_t mask;
}tb_bloom_filter_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bloom_filter_ref_t tb_bloom_filter_init(tb_size_t probability, tb_size_t hash_count, tb_size_t item_maxn, tb_element_t element)
{
// check
tb_assert_and_check_return_val(element.hash, tb_null);
// done
tb_bool_t ok = tb_false;
tb_bloom_filter_t* filter = tb_null;
do
{
// check
tb_assert_and_check_break(probability && probability < 32);
#ifdef __tb_small__
tb_assert_and_check_break(hash_count && hash_count < 4);
#else
tb_assert_and_check_break(hash_count && hash_count < 16);
#endif
// check item maxn
if (!item_maxn) item_maxn = TB_BLOOM_FILTER_ITEM_MAXN_DEFAULT;
tb_assert_and_check_break(item_maxn < TB_MAXU32);
// make filter
filter = tb_malloc0_type(tb_bloom_filter_t);
tb_assert_and_check_break(filter);
// init filter
filter->element = element;
filter->maxn = item_maxn;
filter->hash_count = hash_count;
filter->probability = probability;
/* compute the storage space
*
* c = p^(1/k)
* s = m / n = 2k / (2c + c * c)
*/
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
tb_double_t k = (tb_double_t)hash_count;
tb_double_t p = 1. / (tb_double_t)(1 << probability);
tb_double_t c = tb_pow(p, 1 / k);
tb_double_t s = (k + k) / (c + c + c * c);
tb_size_t n = item_maxn;
tb_size_t m = tb_round(s * n);
tb_trace_d("k: %lf, p: %lf, c: %lf, s: %lf => p: %lf, m: %lu, n: %lu", k, p, c, s, tb_pow((1 - tb_exp(-k / s)), k), m, n);
#else
#if 0
// make scale table
tb_size_t i = 0;
for (i = 1; i < 16; i++)
{
tb_printf(",\t{ ");
tb_size_t j = 0;
for (j = 0; j < 31; j++)
{
tb_double_t k = (tb_double_t)i;
tb_double_t p = 1. / (tb_double_t)(1 << j);
tb_double_t c = tb_pow(p, 1 / k);
tb_double_t s = (k + k) / (c + c + c * c);
if (j != 30) tb_printf("%#010x, ", tb_float_to_fixed(s));
else tb_printf("%#010x }\n", tb_float_to_fixed(s));
}
}
#endif
// the scale
static tb_size_t s_scale[15][31] =
{
{ 0x0000aaaa, 0x00019999, 0x00038e38, 0x00078787, 0x000f83e0, 0x001f81f8, 0x003f80fe, 0x007f807f, 0x00ff803f, 0x01ff801f, 0x03ff800f, 0x07ff8007, 0x0fff8003, 0x1fff8001, 0x3fff8000, 0x7fff8000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000 }
, { 0x00015555, 0x000216f2, 0x00033333, 0x0004ce9c, 0x00071c71, 0x000a6519, 0x000f0f0f, 0x0015ab74, 0x001f07c1, 0x002c46c5, 0x003f03f0, 0x00598545, 0x007f01fc, 0x00b4065b, 0x00ff00ff, 0x01690a9a, 0x01ff007f, 0x02d31427, 0x03ff003f, 0x05a727c6, 0x07ff001f, 0x0b4f4f49, 0x0fff000f, 0x169f9e71, 0x1fff0007, 0x2d403cd2, 0x3fff0003, 0x5a81799c, 0x7fff0001, 0x80000000, 0x80000000 }
, { 0x00020000, 0x0002b4b7, 0x00039f1a, 0x0004cccc, 0x00064ed1, 0x00083a7e, 0x000aaaaa, 0x000dc122, 0x0011a886, 0x00169696, 0x001ccf1a, 0x0024a789, 0x002e8ba2, 0x003b0334, 0x004ab965, 0x005e85e8, 0x00777886, 0x0096e7b6, 0x00be82fa, 0x00f06a01, 0x012f49d1, 0x017e817e, 0x01e25077, 0x026010d0, 0x02fe80bf, 0x03c61f26, 0x04c1a037, 0x05fe805f, 0x078dbd69, 0x0984bfba, 0x0bfe802f }
, { 0x0002aaaa, 0x0003594c, 0x00042de4, 0x00052f7d, 0x00066666, 0x0007dc6f, 0x00099d38, 0x000bb692, 0x000e38e3, 0x001137b0, 0x0014ca32, 0x00190c0b, 0x001e1e1e, 0x0024278c, 0x002b56e8, 0x0033e397, 0x003e0f83, 0x004a2914, 0x00588d8b, 0x0069abd5, 0x007e07e0, 0x00963e94, 0x00b30a8b, 0x00d549b3, 0x00fe03f8, 0x012e7338, 0x01680cb6, 0x01ac8c57, 0x01fe01fe, 0x025ee16e, 0x02d21535 }
, { 0x00035555, 0x0004006d, 0x0004c8d7, 0x0005b2de, 0x0006c365, 0x00080000, 0x00096f0f, 0x000b17e2, 0x000d02d9, 0x000f3993, 0x0011c71c, 0x0014b825, 0x00181b43, 0x001c013a, 0x00207d4e, 0x0025a5a5, 0x002b93b2, 0x003264b4, 0x003a3a48, 0x00433b0d, 0x004d9364, 0x0059764a, 0x00671e54, 0x0076cecd, 0x0088d509, 0x009d89d8, 0x00b55345, 0x00d0a688, 0x00f00a47, 0x01141931, 0x013d84f6 }
, { 0x00040000, 0x0004a8c7, 0x0005696e, 0x000644d6, 0x00073e35, 0x00085921, 0x00099999, 0x000b0419, 0x000c9da2, 0x000e6bd5, 0x001074fd, 0x0012c02d, 0x00155555, 0x00183d5c, 0x001b8245, 0x001f2f4c, 0x0023510d, 0x0027f5b5, 0x002d2d2d, 0x00330952, 0x00399e34, 0x0041025c, 0x00494f13, 0x0052a0c0, 0x005d1745, 0x0068d66e, 0x00760668, 0x0084d450, 0x009572cb, 0x00a81ab0, 0x00bd0bd0 }
, { 0x0004aaaa, 0x000551d0, 0x00060d16, 0x0006de8d, 0x0007c87b, 0x0008cd5c, 0x0009efee, 0x000b3333, 0x000c9a7b, 0x000e296d, 0x000fe410, 0x0011ced6, 0x0013eea3, 0x001648e3, 0x0018e38e, 0x001bc53c, 0x001ef538, 0x00227b8e, 0x00266121, 0x002aafc2, 0x002f724a, 0x0034b4b4, 0x003a843a, 0x0040ef7a, 0x00480696, 0x004fdb60, 0x00588189, 0x00620eca, 0x006c9b26, 0x0078411d, 0x00851df4 }
, { 0x00055555, 0x0005fb45, 0x0006b298, 0x00077cdf, 0x00085bc8, 0x00095128, 0x000a5efb, 0x000b8769, 0x000ccccc, 0x000e31b1, 0x000fb8de, 0x0011655a, 0x00133a71, 0x00153bbc, 0x00176d24, 0x0019d2ef, 0x001c71c7, 0x001f4ebe, 0x00226f61, 0x0025d9bb, 0x00299465, 0x002da690, 0x00321817, 0x0036f188, 0x003c3c3c, 0x00420262, 0x00484f19, 0x004f2e80, 0x0056add0, 0x005edb76, 0x0067c72f }
, { 0x00060000, 0x0006a500, 0x0007594f, 0x00081e25, 0x0008f4ce, 0x0009deb1, 0x000add50, 0x000bf249, 0x000d1f5a, 0x000e6666, 0x000fc972, 0x00114aad, 0x0012ec74, 0x0014b150, 0x00169c01, 0x0018af7c, 0x001aeef6, 0x001d5de3, 0x00200000, 0x0022d953, 0x0025ee3a, 0x00294368, 0x002cddf5, 0x0030c35e, 0x0034f994, 0x00398700, 0x003e7291, 0x0043c3c3, 0x004982ad, 0x004fb80b, 0x00566d4f }
, { 0x0006aaaa, 0x00074eec, 0x000800da, 0x0008c16d, 0x000991af, 0x000a72ba, 0x000b65bd, 0x000c6bfa, 0x000d86ca, 0x000eb79e, 0x00100000, 0x00116194, 0x0012de1e, 0x00147782, 0x00162fc4, 0x0018090e, 0x001a05b2, 0x001c282d, 0x001e7327, 0x0020e97b, 0x00238e38, 0x002664a7, 0x0029704a, 0x002cb4e6, 0x00303686, 0x0033f97e, 0x00380274, 0x003c5662, 0x0040fa9d, 0x0045f4df, 0x004b4b4b }
, { 0x00075555, 0x0007f8fb, 0x0008a8fc, 0x00096622, 0x000a3147, 0x000b0b4e, 0x000bf52c, 0x000cefe2, 0x000dfc83, 0x000f1c30, 0x0010501f, 0x00119999, 0x0012f9fb, 0x001472b9, 0x0016055f, 0x0017b390, 0x00197f0d, 0x001b69b3, 0x001d757e, 0x001fa48a, 0x0021f917, 0x0024758a, 0x00271c71, 0x0029f084, 0x002cf4a7, 0x00302bf1, 0x003399ab, 0x00374154, 0x003b26a9, 0x003f4da1, 0x0043ba79 }
, { 0x00080000, 0x0008a325, 0x0009518e, 0x000a0be5, 0x000ad2dc, 0x000ba731, 0x000c89ac, 0x000d7b1f, 0x000e7c6a, 0x000f8e78, 0x0010b242, 0x0011e8ce, 0x00133333, 0x00149297, 0x00160832, 0x0017954d, 0x00193b45, 0x001afb8d, 0x001cd7aa, 0x001ed13d, 0x0020e9fb, 0x002323b6, 0x0025805b, 0x002801f4, 0x002aaaaa, 0x002d7cc8, 0x00307ab9, 0x0033a712, 0x0037048b, 0x003a9608, 0x003e5e98 }
, { 0x0008aaaa, 0x00094d63, 0x0009fa76, 0x000ab273, 0x000b75f0, 0x000c458d, 0x000d21f2, 0x000e0bcc, 0x000f03d6, 0x00100ad2, 0x0011218b, 0x001248da, 0x001381a0, 0x0014cccc, 0x00162b5a, 0x00179e52, 0x001926cc, 0x001ac5ed, 0x001c7cec, 0x001e4d0f, 0x002037af, 0x00223e37, 0x00246228, 0x0026a515, 0x002908a8, 0x002b8ea4, 0x002e38e3, 0x0031095a, 0x00340218, 0x0037254b, 0x003a753f }
, { 0x00095555, 0x0009f7b1, 0x000aa3a1, 0x000b599e, 0x000c1a2c, 0x000ce5d1, 0x000dbd1b, 0x000ea09e, 0x000f90f6, 0x00108ec6, 0x00119ab9, 0x0012b582, 0x0013dfdc, 0x00151a8e, 0x00166666, 0x0017c43d, 0x001934f6, 0x001ab982, 0x001c52db, 0x001e0209, 0x001fc821, 0x0021a647, 0x00239dac, 0x0025af91, 0x0027dd47, 0x002a2832, 0x002c91c7, 0x002f1b8b, 0x0031c71c, 0x00349629, 0x00378a79 }
, { 0x000a0000, 0x000aa20c, 0x000b4d00, 0x000c0147, 0x000cbf51, 0x000d8793, 0x000e5a86, 0x000f38aa, 0x00102283, 0x0011189b, 0x00121b85, 0x00132bd7, 0x00144a30, 0x00157735, 0x0016b393, 0x00180000, 0x00195d38, 0x001acc02, 0x001c4d2d, 0x001de193, 0x001f8a17, 0x002147a6, 0x00231b39, 0x002505d5, 0x0027088c, 0x0029247a, 0x002b5acc, 0x002dacba, 0x00301b8e, 0x0032a89f, 0x00355555 }
};
// m = (s * n) >> 16
tb_size_t m = tb_fixed_mul(s_scale[hash_count - 1][probability], item_maxn);
#endif
// init size
filter->size = tb_align8(m) >> 3;
tb_assert_and_check_break(filter->size);
if (filter->size > TB_BLOOM_FILTER_DATA_MAXN)
{
tb_trace_e("the need space too large, size: %lu, please decrease hash count and probability!", filter->size);
break;
}
tb_trace_d("size: %lu", filter->size);
// init data
filter->data = tb_malloc0_bytes(filter->size);
tb_assert_and_check_break(filter->data);
// init hash mask
filter->mask = tb_align_pow2((filter->size << 3)) - 1;
tb_assert_and_check_break(filter->mask);
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (filter) tb_bloom_filter_exit((tb_bloom_filter_ref_t)filter);
filter = tb_null;
}
// ok?
return (tb_bloom_filter_ref_t)filter;
}
tb_void_t tb_bloom_filter_exit(tb_bloom_filter_ref_t self)
{
// check
tb_bloom_filter_t* filter = (tb_bloom_filter_t*)self;
tb_assert_and_check_return(filter);
// exit data
if (filter->data) tb_free(filter->data);
filter->data = tb_null;
// exit it
tb_free(filter);
}
tb_void_t tb_bloom_filter_clear(tb_bloom_filter_ref_t self)
{
// check
tb_bloom_filter_t* filter = (tb_bloom_filter_t*)self;
tb_assert_and_check_return(filter);
// clear it
if (filter->data && filter->size) tb_memset(filter->data, 0, filter->size);
}
tb_bool_t tb_bloom_filter_set(tb_bloom_filter_ref_t self, tb_cpointer_t data)
{
// check
tb_bloom_filter_t* filter = (tb_bloom_filter_t*)self;
tb_assert_and_check_return_val(filter, tb_false);
// walk
tb_size_t i = 0;
tb_size_t n = filter->hash_count;
tb_bool_t ok = tb_false;
for (i = 0; i < n; i++)
{
// compute the bit index
tb_size_t index = filter->element.hash(&filter->element, data, filter->mask, i);
if (index >= (filter->size << 3)) index %= (filter->size << 3);
// not exists?
if (!tb_bloom_filter_bset(filter->data, index))
{
// set it
tb_bloom_filter_set1(filter->data, index);
// ok
ok = tb_true;
}
}
// ok?
return ok;
}
tb_bool_t tb_bloom_filter_get(tb_bloom_filter_ref_t self, tb_cpointer_t data)
{
// check
tb_bloom_filter_t* filter = (tb_bloom_filter_t*)self;
tb_assert_and_check_return_val(filter, tb_false);
// walk
tb_size_t i = 0;
tb_size_t n = filter->hash_count;
for (i = 0; i < n; i++)
{
// compute the bit index
tb_size_t index = filter->element.hash(&filter->element, data, filter->mask, i);
if (index >= (filter->size << 3)) index %= (filter->size << 3);
// not exists? break it
if (!tb_bloom_filter_bset(filter->data, index)) break;
}
// ok?
return (i == n)? tb_true : tb_false;
}
tb_byte_t const* tb_bloom_filter_data(tb_bloom_filter_ref_t self)
{
// check
tb_bloom_filter_t* filter = (tb_bloom_filter_t*)self;
tb_assert_and_check_return_val(filter, tb_null);
return filter->data;
}
tb_size_t tb_bloom_filter_size(tb_bloom_filter_ref_t self)
{
// check
tb_bloom_filter_t* filter = (tb_bloom_filter_t*)self;
tb_assert_and_check_return_val(filter, 0);
return filter->size;
}
tb_bool_t tb_bloom_filter_data_set(tb_bloom_filter_ref_t self, tb_byte_t const* data, tb_size_t size)
{
// check
tb_bloom_filter_t* filter = (tb_bloom_filter_t*)self;
tb_assert_and_check_return_val(filter && data && size, tb_false);
// ensure data space
if (filter->data) filter->data = tb_ralloc_bytes(filter->data, size);
else filter->data = tb_malloc_bytes(size);
tb_assert_and_check_return_val(filter->data, tb_false);
// copy data
tb_memcpy(filter->data, data, size);
filter->size = size;
return tb_true;
}
tbox-1.7.6/src/tbox/container/bloom_filter.h 0000664 0000000 0000000 00000017217 14671175054 0021076 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file bloom_filter.h
* @ingroup container
*
*/
#ifndef TB_CONTAINER_BLOOM_FILTER_H
#define TB_CONTAINER_BLOOM_FILTER_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "element.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the item maxn
#define TB_BLOOM_FILTER_ITEM_MAXN_MICRO (1 << 16)
#define TB_BLOOM_FILTER_ITEM_MAXN_SMALL (1 << 20)
#define TB_BLOOM_FILTER_ITEM_MAXN_LARGE (1 << 24)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/*! the bloom filter type
*
* A Bloom filter is a space-efficient probabilistic data structure,
* conceived by Burton Howard Bloom in 1970, that is used to test whether an element is a member of a set.
* False positive matches are possible, but false negatives are not;
* i.e. a query returns either "possibly in set" or "definitely not in set".
* Elements can be added to the set, but not removed (though this can be addressed with a "counting" filter).
* The more elements that are added to the set, the larger the probability of false positives.
*
* Assume that a hash function selects each array position with equal probability.
* If m is the number of bits in the array, and k is the number of hash functions,
* then the probability that a certain bit is not set to 1 by a certain hash function
* during the insertion of an element is then
* 1 - 1 / m
*
* The probability that it is not set to 1 by any of the hash functions is
* (1 - 1/ m) ^ k
*
* If we have inserted n elements, the probability that a certain bit is still 0 is
* (1 - 1/ m) ^ kn
*
* the probability that it is 1 is therefore
* 1 - ((1 - 1/ m) ^ kn)
*
* Now test membership of an element that is not in the set.
* Each of the k array positions computed by the hash functions is 1 with a probability as above.
* The probability of all of them being 1,
* which would cause the algorithm to erroneously claim that the element is in the set, is often given as
* p = (1 - ((1 - 1/ m) ^ kn))^k ~= (1 - e^(-kn/m))^k
*
* For a given m and n, the value of k (the number of hash functions) that minimizes the probability is
* k = (m / n) * ln2 ~= (m / n) * (9 / 13)
*
* which gives
* 2 ^ -k ~= 0.6185 ^ (m / n)
*
* The required number of bits m, given n (the number of inserted elements)
* and a desired false positive probability p (and assuming the optimal value of k is used)
* can be computed by substituting the optimal value of k in the probability expression above:
* p = (1 - e ^-(m/nln2)n/m))^(m/nln2)
*
* which can be simplified to:
* lnp = -m/n * (ln2)^2
*
* This optimal results in:
* s = m/n = -lnp / (ln2 * ln2) = -log2(p) / ln2
* k = s * ln2 = -log2(p) <= note: this k will be larger
*
* compute s(m/n) for given k and p:
* p = (1 - e^(-kn/m))^k = (1 - e^(-k/s))^k
* => lnp = k * ln(1 - e^(-k/s))
* => (lnp) / k = ln(1 - e^(-k/s))
* => e^((lnp) / k) = 1 - e^(-k/s)
* => e^(-k/s) = 1 - e^((lnp) / k) = 1 - (e^lnp)^(1/k) = 1 - p^(1/k)
* => -k/s = ln(1 - p^(1/k))
* => s = -k / ln(1 - p^(1/k)) and define c = p^(1/k)
* => s = -k / ln(1 - c)) and ln(1 + x) ~= x - 0.5x^2 while x < 1
* => s ~= -k / (-c-0.5c^2) = 2k / (2c + c * c)
*
* so
* c = p^(1/k)
* s = m / n = 2k / (2c + c * c)
*/
typedef __tb_typeref__(bloom_filter);
/// the probability of false positives
typedef enum __tb_bloom_filter_probability_e
{
TB_BLOOM_FILTER_PROBABILITY_0_1 = 3 ///!< 1 / 2^3 = 0.125 ~= 0.1
, TB_BLOOM_FILTER_PROBABILITY_0_01 = 6 ///!< 1 / 2^6 = 0.015625 ~= 0.01
, TB_BLOOM_FILTER_PROBABILITY_0_001 = 10 ///!< 1 / 2^10 = 0.0009765625 ~= 0.001
, TB_BLOOM_FILTER_PROBABILITY_0_0001 = 13 ///!< 1 / 2^13 = 0.0001220703125 ~= 0.0001
, TB_BLOOM_FILTER_PROBABILITY_0_00001 = 16 ///!< 1 / 2^16 = 0.0000152587890625 ~= 0.00001
, TB_BLOOM_FILTER_PROBABILITY_0_000001 = 20 ///!< 1 / 2^20 = 0.00000095367431640625 ~= 0.000001
}tb_bloom_filter_probability_e;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init bloom filter
*
* @note not supports iterator
*
* @param probability the probability of false positives
* @param hash_count the hash count: < 16
* @param item_maxn the item maxn
* @param element the element only for hash
*
* @return the bloom filter
*/
tb_bloom_filter_ref_t tb_bloom_filter_init(tb_size_t probability, tb_size_t hash_count, tb_size_t item_maxn, tb_element_t element);
/*! exit bloom filter
*
* @param bloom_filter the bloom filter
*/
tb_void_t tb_bloom_filter_exit(tb_bloom_filter_ref_t bloom_filter);
/*! clear bloom filter
*
* @param bloom_filter the bloom filter
*/
tb_void_t tb_bloom_filter_clear(tb_bloom_filter_ref_t bloom_filter);
/*! set data to the bloom filter
*
* @code
* if (tb_bloom_filter_set(filter, data))
* {
* tb_trace_i("this data not exists, set ok!");
* }
* else
* {
* tb_trace_i("this data have been existed, set failed!");
*
* // note: maybe false positives
* }
* @endcode
*
* @param bloom_filter the bloom filter
* @param data the item data
*
* @return return tb_false if the data have been existed, otherwise set it and return tb_true
*/
tb_bool_t tb_bloom_filter_set(tb_bloom_filter_ref_t bloom_filter, tb_cpointer_t data);
/*! get data to the bloom filter
*
* @code
* if (tb_bloom_filter_get(filter, data))
* {
* tb_trace_i("this data have been existed, get ok!");
*
* // note: maybe false positives
* }
* else
* {
* tb_trace_i("this data not exists, get failed!");
* }
* @endcode
*
* @param bloom_filter the bloom filter
* @param data the item data
*
* @return return tb_true if the data exists, otherwise return tb_false
*/
tb_bool_t tb_bloom_filter_get(tb_bloom_filter_ref_t bloom_filter, tb_cpointer_t data);
/* get data
*
* @param bloom_filter the bloom filter
*
* @return the bloom filter data
*/
tb_byte_t const* tb_bloom_filter_data(tb_bloom_filter_ref_t bloom_filter);
/* get data size
*
* @param bloom_filter the bloom filter
*
* @return the bloom filter data size
*/
tb_size_t tb_bloom_filter_size(tb_bloom_filter_ref_t bloom_filter);
/* set data, we can use this to copy data from another bloom filter
*
* @param bloom_filter the bloom filter
* @param data the bloom filter data
* @param size the bloom filter size
*
* @return tb_true or tb_false
*/
tb_bool_t tb_bloom_filter_data_set(tb_bloom_filter_ref_t bloom_filter, tb_byte_t const* data, tb_size_t size);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/container/circle_queue.c 0000664 0000000 0000000 00000023202 14671175054 0021050 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file circle_queue.c
* @ingroup container
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "circle_queue.h"
#include "../libc/libc.h"
#include "../math/math.h"
#include "../utils/utils.h"
#include "../memory/memory.h"
#include "../stream/stream.h"
#include "../platform/platform.h"
#include "../algorithm/algorithm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef __tb_small__
# define TB_CIRCLE_QUEUE_SIZE_DEFAULT (256)
#else
# define TB_CIRCLE_QUEUE_SIZE_DEFAULT (65536)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the circle queue type
typedef struct __tb_circle_queue_t
{
// the itor
tb_iterator_t itor;
// the data
tb_byte_t* data;
// the head
tb_size_t head;
// the tail
tb_size_t tail;
// the maxn
tb_size_t maxn;
// the size
tb_size_t size;
// the element
tb_element_t element;
}tb_circle_queue_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_size_t tb_circle_queue_itor_size(tb_iterator_ref_t iterator)
{
// check
tb_circle_queue_t* queue = (tb_circle_queue_t*)iterator;
tb_assert_and_check_return_val(queue, 0);
// the size
return queue->size;
}
static tb_size_t tb_circle_queue_itor_head(tb_iterator_ref_t iterator)
{
// check
tb_circle_queue_t* queue = (tb_circle_queue_t*)iterator;
tb_assert_and_check_return_val(queue, 0);
// head
return queue->head;
}
static tb_size_t tb_circle_queue_itor_last(tb_iterator_ref_t iterator)
{
// check
tb_circle_queue_t* queue = (tb_circle_queue_t*)iterator;
tb_assert_and_check_return_val(queue, 0);
// last
return (queue->tail + queue->maxn - 1) % queue->maxn;
}
static tb_size_t tb_circle_queue_itor_tail(tb_iterator_ref_t iterator)
{
// check
tb_circle_queue_t* queue = (tb_circle_queue_t*)iterator;
tb_assert_and_check_return_val(queue, 0);
// tail
return queue->tail;
}
static tb_size_t tb_circle_queue_itor_next(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_circle_queue_t* queue = (tb_circle_queue_t*)iterator;
tb_assert_and_check_return_val(queue, 0);
// next
return (itor + 1) % queue->maxn;
}
static tb_size_t tb_circle_queue_itor_prev(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_circle_queue_t* queue = (tb_circle_queue_t*)iterator;
tb_assert_and_check_return_val(queue, 0);
// prev
return (itor + queue->maxn - 1) % queue->maxn;
}
static tb_pointer_t tb_circle_queue_itor_item(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_circle_queue_t* queue = (tb_circle_queue_t*)iterator;
tb_assert_and_check_return_val(queue && itor < queue->maxn, tb_null);
// item
return queue->element.data(&queue->element, queue->data + itor * iterator->step);
}
static tb_void_t tb_circle_queue_itor_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item)
{
// check
tb_circle_queue_t* queue = (tb_circle_queue_t*)iterator;
tb_assert(queue);
// copy
queue->element.copy(&queue->element, queue->data + itor * iterator->step, item);
}
static tb_long_t tb_circle_queue_itor_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem)
{
// check
tb_circle_queue_t* queue = (tb_circle_queue_t*)iterator;
tb_assert_and_check_return_val(queue && queue->element.comp, 0);
// comp
return queue->element.comp(&queue->element, litem, ritem);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_circle_queue_ref_t tb_circle_queue_init(tb_size_t maxn, tb_element_t element)
{
// check
tb_assert_and_check_return_val(element.size && element.dupl && element.data, tb_null);
// done
tb_bool_t ok = tb_false;
tb_circle_queue_t* queue = tb_null;
do
{
// make queue
queue = tb_malloc0_type(tb_circle_queue_t);
tb_assert_and_check_break(queue);
// using the default maxn
if (!maxn) maxn = TB_CIRCLE_QUEUE_SIZE_DEFAULT;
// init queue, + tail
queue->maxn = maxn + 1;
queue->element = element;
// init operation
static tb_iterator_op_t op =
{
tb_circle_queue_itor_size
, tb_circle_queue_itor_head
, tb_circle_queue_itor_last
, tb_circle_queue_itor_tail
, tb_circle_queue_itor_prev
, tb_circle_queue_itor_next
, tb_circle_queue_itor_item
, tb_circle_queue_itor_comp
, tb_circle_queue_itor_copy
, tb_null
, tb_null
};
// init iterator
queue->itor.priv = tb_null;
queue->itor.step = element.size;
queue->itor.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE | TB_ITERATOR_MODE_MUTABLE;
queue->itor.op = &op;
if (element.type == TB_ELEMENT_TYPE_MEM)
queue->itor.flag = TB_ITERATOR_FLAG_ITEM_REF;
// make data
queue->data = (tb_byte_t*)tb_nalloc0(queue->maxn, element.size);
tb_assert_and_check_break(queue->data);
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
if (queue) tb_circle_queue_exit((tb_circle_queue_ref_t)queue);
queue = tb_null;
}
// ok?
return (tb_circle_queue_ref_t)queue;
}
tb_void_t tb_circle_queue_exit(tb_circle_queue_ref_t self)
{
// check
tb_circle_queue_t* queue = (tb_circle_queue_t*)self;
tb_assert_and_check_return(queue);
// clear data
tb_circle_queue_clear(self);
// free data
if (queue->data) tb_free(queue->data);
// free it
tb_free(queue);
}
tb_void_t tb_circle_queue_clear(tb_circle_queue_ref_t self)
{
// check
tb_circle_queue_t* queue = (tb_circle_queue_t*)self;
tb_assert_and_check_return(queue);
// clear it
while (!tb_circle_queue_null(self)) tb_circle_queue_pop(self);
queue->head = 0;
queue->tail = 0;
queue->size = 0;
}
tb_void_t tb_circle_queue_put(tb_circle_queue_ref_t self, tb_cpointer_t data)
{
// check
tb_circle_queue_t* queue = (tb_circle_queue_t*)self;
tb_assert_and_check_return(queue && queue->size < queue->maxn);
// put it
queue->element.dupl(&queue->element, queue->data + queue->tail * queue->element.size, data);
queue->tail = (queue->tail + 1) % queue->maxn;
queue->size++;
}
tb_void_t tb_circle_queue_pop(tb_circle_queue_ref_t self)
{
// check
tb_circle_queue_t* queue = (tb_circle_queue_t*)self;
tb_assert_and_check_return(queue && queue->size);
// pop it
if (queue->element.free) queue->element.free(&queue->element, queue->data + queue->head * queue->element.size);
queue->head = (queue->head + 1) % queue->maxn;
queue->size--;
}
tb_pointer_t tb_circle_queue_get(tb_circle_queue_ref_t self)
{
// get the head item
return tb_circle_queue_head(self);
}
tb_pointer_t tb_circle_queue_head(tb_circle_queue_ref_t self)
{
// the head item
return tb_iterator_item((tb_iterator_ref_t)self, tb_iterator_head((tb_iterator_ref_t)self));
}
tb_pointer_t tb_circle_queue_last(tb_circle_queue_ref_t self)
{
// the last item
return tb_iterator_item((tb_iterator_ref_t)self, tb_iterator_last((tb_iterator_ref_t)self));
}
tb_size_t tb_circle_queue_size(tb_circle_queue_ref_t self)
{
// check
tb_circle_queue_t* queue = (tb_circle_queue_t*)self;
tb_assert_and_check_return_val(queue, 0);
// the size
return queue->size;
}
tb_size_t tb_circle_queue_maxn(tb_circle_queue_ref_t self)
{
// check
tb_circle_queue_t* queue = (tb_circle_queue_t*)self;
tb_assert_and_check_return_val(queue, 0);
// the maxn
return queue->maxn;
}
tb_bool_t tb_circle_queue_full(tb_circle_queue_ref_t self)
{
// check
tb_circle_queue_t* queue = (tb_circle_queue_t*)self;
tb_assert_and_check_return_val(queue, tb_true);
// is full?
return (queue->size + 1) == queue->maxn;
}
tb_bool_t tb_circle_queue_null(tb_circle_queue_ref_t self)
{
// check
tb_circle_queue_t* queue = (tb_circle_queue_t*)self;
tb_assert_and_check_return_val(queue, tb_true);
// is null?
return !queue->size;
}
#ifdef __tb_debug__
tb_void_t tb_circle_queue_dump(tb_circle_queue_ref_t self)
{
// check
tb_circle_queue_t* queue = (tb_circle_queue_t*)self;
tb_assert_and_check_return(queue);
// trace
tb_trace_i("self: size: %lu", tb_circle_queue_size(self));
// done
tb_char_t cstr[4096];
tb_for_all (tb_pointer_t, data, self)
{
// trace
if (queue->element.cstr)
{
tb_trace_i(" %s", queue->element.cstr(&queue->element, data, cstr, sizeof(cstr)));
}
else
{
tb_trace_i(" %p", data);
}
}
}
#endif
tbox-1.7.6/src/tbox/container/circle_queue.h 0000664 0000000 0000000 00000010326 14671175054 0021060 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file queue.h
* @ingroup container
*
*/
#ifndef TB_CONTAINER_CIRCLE_QUEUE_H
#define TB_CONTAINER_CIRCLE_QUEUE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "element.h"
#include "iterator.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/*! the circle queue ref type
*
*
* queue: |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||------|
* head last tail
*
* queue: ||||||||||||||-----|--------------------------||||||||||||||||||||||||||
* last tail head
*
* performance:
*
* put: O(1)
* pop: O(1)
*
* iterator:
*
* next: fast
* prev: fast
*
*
*
* @note the index of the same item is mutable
*
*/
typedef tb_iterator_ref_t tb_circle_queue_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init queue
*
* @param maxn the item maxn, using the default maxn if be zero
* @param element the element
*
* @return the queue
*/
tb_circle_queue_ref_t tb_circle_queue_init(tb_size_t maxn, tb_element_t element);
/*! exit queue
*
* @param queue the queue
*/
tb_void_t tb_circle_queue_exit(tb_circle_queue_ref_t queue);
/*! the queue head item
*
* @param queue the queue
*
* @return the head item
*/
tb_pointer_t tb_circle_queue_head(tb_circle_queue_ref_t queue);
/*! the queue last item
*
* @param queue the queue
*
* @return the last item
*/
tb_pointer_t tb_circle_queue_last(tb_circle_queue_ref_t queue);
/*! clear the queue
*
* @param queue the queue
*/
tb_void_t tb_circle_queue_clear(tb_circle_queue_ref_t queue);
/*! put the queue item
*
* @param queue the queue
* @param data the item data
*/
tb_void_t tb_circle_queue_put(tb_circle_queue_ref_t queue, tb_cpointer_t data);
/*! pop the queue item
*
* @param queue the queue
*/
tb_void_t tb_circle_queue_pop(tb_circle_queue_ref_t queue);
/*! get the queue item
*
* @param queue the queue
*
* @return the queue item
*/
tb_pointer_t tb_circle_queue_get(tb_circle_queue_ref_t queue);
/*! the queue size
*
* @param queue the queue
*
* @return the queue size
*/
tb_size_t tb_circle_queue_size(tb_circle_queue_ref_t queue);
/*! the queue maxn
*
* @param queue the queue
*
* @return the queue maxn
*/
tb_size_t tb_circle_queue_maxn(tb_circle_queue_ref_t queue);
/*! the queue full?
*
* @param queue the queue
*
* @return tb_true or tb_false
*/
tb_bool_t tb_circle_queue_full(tb_circle_queue_ref_t queue);
/*! the queue null?
*
* @param queue the queue
*
* @return tb_true or tb_false
*/
tb_bool_t tb_circle_queue_null(tb_circle_queue_ref_t queue);
#ifdef __tb_debug__
/*! dump queue
*
* @param queue the queue
*/
tb_void_t tb_circle_queue_dump(tb_circle_queue_ref_t circle_queue);
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/container/container.h 0000664 0000000 0000000 00000002400 14671175054 0020367 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file container.h
* @defgroup container
*
*/
#ifndef TB_CONTAINER_H
#define TB_CONTAINER_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "element.h"
#include "iterator.h"
#include "array_iterator.h"
#include "heap.h"
#include "stack.h"
#include "vector.h"
#include "hash_set.h"
#include "hash_map.h"
#include "queue.h"
#include "circle_queue.h"
#include "priority_queue.h"
#include "list.h"
#include "list_entry.h"
#include "single_list.h"
#include "single_list_entry.h"
#include "bloom_filter.h"
#endif
tbox-1.7.6/src/tbox/container/element.h 0000664 0000000 0000000 00000022625 14671175054 0020051 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file element.h
* @ingroup container
*
*/
#ifndef TB_CONTAINER_ELEMENT_H
#define TB_CONTAINER_ELEMENT_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the element ref type
typedef struct __tb_element_t* tb_element_ref_t;
/*! the element data hash function type
*
* @param element the element
* @param data the element data
* @param mask the hash mask
* @param index the hash index
*
* @return the hash value
*/
typedef tb_size_t (*tb_element_hash_func_t)(tb_element_ref_t element, tb_cpointer_t data, tb_size_t mask, tb_size_t index);
/*! the element data compare function type
*
* @param element the element
* @param ldata the left-hand data
* @param rdata the right-hand data
*
* @return equal: 0, 1: >, -1: <
*/
typedef tb_long_t (*tb_element_comp_func_t)(tb_element_ref_t element, tb_cpointer_t ldata, tb_cpointer_t rdata);
/*! the element data function type
*
* @param element the element
* @param buff the element data address
*
* @return the element data
*/
typedef tb_pointer_t (*tb_element_data_func_t)(tb_element_ref_t element, tb_cpointer_t buff);
/*! the element data string function type
*
* @param element the element
* @param data the element data
* @param cstr the string buffer
* @param maxn the string buffer maximum size
*
* @return the string pointer
*/
typedef tb_char_t const* (*tb_element_cstr_func_t)(tb_element_ref_t element, tb_cpointer_t data, tb_char_t* cstr, tb_size_t maxn);
/*! the element free function type
*
* @param element the element
* @param buff the element buffer
*/
typedef tb_void_t (*tb_element_free_func_t)(tb_element_ref_t element, tb_pointer_t buff);
/*! the element duplicate function type
*
* allocate a new element and copy the element data
*
* @param element the element
* @param buff the element buffer
* @param data the element data
*/
typedef tb_void_t (*tb_element_dupl_func_t)(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data);
/*! the element replace function type
*
* free the previous element data and duplicate the new data
*
* @param element the element
* @param buff the element buffer
* @param data the element data
*/
typedef tb_void_t (*tb_element_repl_func_t)(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data);
/*! the element copy function type
*
* only copy the element data and not allocate new element
*
* @param element the element
* @param buff the element buffer
* @param data the element data
*/
typedef tb_void_t (*tb_element_copy_func_t)(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data);
/*! the elements free function type
*
* free some elements
*
* @param element the element
* @param buff the element buffer
* @param size the element count
*/
typedef tb_void_t (*tb_element_nfree_func_t)(tb_element_ref_t element, tb_pointer_t buff, tb_size_t size);
/*! the elements duplicate function type
*
* duplicate some elements
*
* @param element the element
* @param buff the element buffer
* @param data the element data
* @param size the element count
*/
typedef tb_void_t (*tb_element_ndupl_func_t)(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size);
/*! the elements replace function type
*
* replace some elements
*
* @param element the element
* @param buff the element buffer
* @param data the element data
* @param size the element count
*/
typedef tb_void_t (*tb_element_nrepl_func_t)(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size);
/*! the elements copy function type
*
* copy some elements
*
* @param element the element
* @param buff the element buffer
* @param data the element data
* @param size the element count
*/
typedef tb_void_t (*tb_element_ncopy_func_t)(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size);
/// the element type
typedef enum __tb_element_type_t
{
TB_ELEMENT_TYPE_NULL = 0 //!< null
, TB_ELEMENT_TYPE_LONG = 1 //!< long
, TB_ELEMENT_TYPE_SIZE = 2 //!< size
, TB_ELEMENT_TYPE_UINT8 = 3 //!< uint8
, TB_ELEMENT_TYPE_UINT16 = 4 //!< uint16
, TB_ELEMENT_TYPE_UINT32 = 5 //!< uint32
, TB_ELEMENT_TYPE_STR = 6 //!< string
, TB_ELEMENT_TYPE_PTR = 7 //!< pointer
, TB_ELEMENT_TYPE_MEM = 8 //!< memory
, TB_ELEMENT_TYPE_OBJ = 9 //!< object
, TB_ELEMENT_TYPE_TRUE = 10 //!< true
, TB_ELEMENT_TYPE_USER = 11 //!< the user-defined type
}tb_element_type_t;
/// the element type
typedef struct __tb_element_t
{
/// the element type
tb_uint16_t type;
/// the element flag
tb_uint16_t flag;
/// the element size
tb_uint16_t size;
/// the priv data
tb_cpointer_t priv;
/// the hash function
tb_element_hash_func_t hash;
/// the compare function
tb_element_comp_func_t comp;
/// the data function
tb_element_data_func_t data;
/// the string function
tb_element_cstr_func_t cstr;
/// the free element
tb_element_free_func_t free;
/// the duplicate function
tb_element_dupl_func_t dupl;
/// the replace function
tb_element_repl_func_t repl;
/// the copy function
tb_element_copy_func_t copy;
/// the free elements function
tb_element_nfree_func_t nfree;
/// the duplicate elements function
tb_element_ndupl_func_t ndupl;
/// the replace elements function
tb_element_nrepl_func_t nrepl;
/// the copy elements function
tb_element_ncopy_func_t ncopy;
}tb_element_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the null element, no space
*
* @return the element
*/
tb_element_t tb_element_null(tb_noarg_t);
/*! the true element, no space
*
* .e.g for hash data
*
* @return the element
*/
tb_element_t tb_element_true(tb_noarg_t);
/*! the long element
*
* @return the element
*/
tb_element_t tb_element_long(tb_noarg_t);
/*! the size element
*
* @return the element
*/
tb_element_t tb_element_size(tb_noarg_t);
/*! the uint8 element
*
* @return the element
*/
tb_element_t tb_element_uint8(tb_noarg_t);
/*! the uint16 element for
*
* @return the element
*/
tb_element_t tb_element_uint16(tb_noarg_t);
/*! the uint32 element
*
* @return the element
*/
tb_element_t tb_element_uint32(tb_noarg_t);
/*! the string element
*
* @param is_case is case?
*
* @return the element
*/
tb_element_t tb_element_str(tb_bool_t is_case);
/*! the pointer element
*
* @note if the free function have been hooked, the nfree need hook too.
*
* @param free the element free function
* @param priv the private data of the element free function
*
* @return the element
*/
tb_element_t tb_element_ptr(tb_element_free_func_t free, tb_cpointer_t priv);
/*! the object element
*
* @return the element
*/
tb_element_t tb_element_obj(tb_noarg_t);
/*! the memory element with the fixed space
*
* @param size the element size
* @param free the element free function
* @param priv the private data of the element free function
*
* @return the element
*/
tb_element_t tb_element_mem(tb_size_t size, tb_element_free_func_t free, tb_cpointer_t priv);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/container/element/ 0000775 0000000 0000000 00000000000 14671175054 0017671 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/container/element/hash.c 0000664 0000000 0000000 00000023307 14671175054 0020765 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file hash.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "hash.h"
#include "../../hash/hash.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* data hash implementation
*/
static tb_size_t tb_element_hash_data_func_0(tb_byte_t const* data, tb_size_t size)
{
return tb_bkdr_make(data, size, 0);
}
static tb_size_t tb_element_hash_data_func_1(tb_byte_t const* data, tb_size_t size)
{
return tb_adler32_make(data, size, 0);
}
static tb_size_t tb_element_hash_data_func_2(tb_byte_t const* data, tb_size_t size)
{
return tb_fnv32_1a_make(data, size, 0);
}
#if !defined(__tb_small__) && defined(TB_CONFIG_MODULE_HAVE_HASH)
static tb_size_t tb_element_hash_data_func_3(tb_byte_t const* data, tb_size_t size)
{
return tb_ap_make(data, size, 0);
}
static tb_size_t tb_element_hash_data_func_4(tb_byte_t const* data, tb_size_t size)
{
return tb_murmur_make(data, size, 0);
}
static tb_size_t tb_element_hash_data_func_5(tb_byte_t const* data, tb_size_t size)
{
return tb_crc32_le_make(data, size, 0);
}
static tb_size_t tb_element_hash_data_func_6(tb_byte_t const* data, tb_size_t size)
{
return tb_fnv32_make(data, size, 0);
}
static tb_size_t tb_element_hash_data_func_7(tb_byte_t const* data, tb_size_t size)
{
return tb_djb2_make(data, size, 0);
}
static tb_size_t tb_element_hash_data_func_8(tb_byte_t const* data, tb_size_t size)
{
return tb_blizzard_make(data, size, 0);
}
static tb_size_t tb_element_hash_data_func_9(tb_byte_t const* data, tb_size_t size)
{
return tb_rs_make(data, size, 0);
}
static tb_size_t tb_element_hash_data_func_10(tb_byte_t const* data, tb_size_t size)
{
return tb_sdbm_make(data, size, 0);
}
static tb_size_t tb_element_hash_data_func_11(tb_byte_t const* data, tb_size_t size)
{
// using md5, better but too slower
tb_byte_t b[16] = {0};
tb_md5_make(data, size, b, 16);
return tb_bits_get_u32_ne(b);
}
static tb_size_t tb_element_hash_data_func_12(tb_byte_t const* data, tb_size_t size)
{
// using sha, better but too slower
tb_byte_t b[32] = {0};
tb_sha_make(TB_SHA_MODE_SHA1_160, data, size, b, 32);
return tb_bits_get_u32_ne(b);
}
static tb_size_t tb_element_hash_data_func_13(tb_byte_t const* data, tb_size_t size)
{
tb_trace_noimpl();
return 0;
}
static tb_size_t tb_element_hash_data_func_14(tb_byte_t const* data, tb_size_t size)
{
tb_trace_noimpl();
return 0;
}
static tb_size_t tb_element_hash_data_func_15(tb_byte_t const* data, tb_size_t size)
{
tb_trace_noimpl();
return 0;
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* cstr hash implementation
*/
static tb_size_t tb_element_hash_cstr_func_0(tb_char_t const* data)
{
return tb_bkdr_make_from_cstr(data, 0);
}
static tb_size_t tb_element_hash_cstr_func_1(tb_char_t const* data)
{
return tb_fnv32_1a_make_from_cstr(data, 0);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* uint8 hash implementation
*/
static tb_size_t tb_element_hash_uint8_func_0(tb_uint8_t value)
{
return (tb_size_t)value;
}
static tb_size_t tb_element_hash_uint8_func_1(tb_uint8_t value)
{
return (tb_size_t)(((tb_uint64_t)(value) * 2654435761ul) >> 16);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* uint16 hash implementation
*/
static tb_size_t tb_element_hash_uint16_func_0(tb_uint16_t value)
{
return (tb_size_t)(((tb_uint64_t)(value) * 2654435761ul) >> 16);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* uint32 hash implementation
*/
static tb_size_t tb_element_hash_uint32_func_0(tb_uint32_t value)
{
return (tb_size_t)(((tb_uint64_t)(value) * 2654435761ul) >> 16);
}
static tb_size_t tb_element_hash_uint32_func_1(tb_uint32_t value)
{
// Bob Jenkins' 32 bit integer hash function
value = (value + 0x7ed55d16) + (value << 12);
value = (value ^ 0xc761c23c) ^ (value >> 19);
value = (value + 0x165667b1) + (value << 5);
value = (value + 0xd3a2646c) ^ (value << 9);
value = (value + 0xfd7046c5) + (value << 3);
value = (value ^ 0xb55a4f09) ^ (value >> 16);
return value;
}
static tb_size_t tb_element_hash_uint32_func_2(tb_uint32_t value)
{
// Tomas Wang
value = ~value + (value << 15);
value = value ^ (value >> 12);
value = value + (value << 2);
value = value ^ (value >> 4);
value = value * 2057;
value = value ^ (value >> 16);
return value;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* uint64 hash implementation
*/
static tb_size_t tb_element_hash_uint64_func_0(tb_uint64_t value)
{
return (tb_size_t)((value * 2654435761ul) >> 16);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_element_hash_uint8(tb_uint8_t value, tb_size_t mask, tb_size_t index)
{
// check
tb_assert_and_check_return_val(mask, 0);
// for optimization
if (index < 2)
{
// the func
static tb_size_t (*s_func[])(tb_uint8_t) =
{
tb_element_hash_uint8_func_0
, tb_element_hash_uint8_func_1
};
tb_assert_and_check_return_val(index < tb_arrayn(s_func), 0);
// done
return s_func[index](value) & mask;
}
// using uint32 hash
tb_uint32_t v = (tb_uint32_t)value;
return tb_element_hash_uint32(v | (v << 8) | (v << 16) | (v << 24), mask, index - 1);
}
tb_size_t tb_element_hash_uint16(tb_uint16_t value, tb_size_t mask, tb_size_t index)
{
// check
tb_assert_and_check_return_val(mask, 0);
// for optimization
if (index < 1)
{
// the func
static tb_size_t (*s_func[])(tb_uint16_t) =
{
tb_element_hash_uint16_func_0
};
tb_assert_and_check_return_val(index < tb_arrayn(s_func), 0);
// done
return s_func[index](value) & mask;
}
// using uint32 hash
tb_uint32_t v = (tb_uint32_t)value;
return tb_element_hash_uint32(v | (v << 16), mask, index);
}
tb_size_t tb_element_hash_uint32(tb_uint32_t value, tb_size_t mask, tb_size_t index)
{
// check
tb_assert_and_check_return_val(mask, 0);
// for optimization
if (index < 3)
{
// the func
static tb_size_t (*s_func[])(tb_uint32_t) =
{
tb_element_hash_uint32_func_0
, tb_element_hash_uint32_func_1
, tb_element_hash_uint32_func_2
};
tb_assert_and_check_return_val(index < tb_arrayn(s_func), 0);
// done
return s_func[index](value) & mask;
}
// done
return tb_element_hash_data((tb_byte_t const*)&value, sizeof(tb_uint32_t), mask, index - 3);
}
tb_size_t tb_element_hash_uint64(tb_uint64_t value, tb_size_t mask, tb_size_t index)
{
// for optimization
if (index < 1)
{
// the func
static tb_size_t (*s_func[])(tb_uint64_t) =
{
tb_element_hash_uint64_func_0
};
tb_assert_and_check_return_val(index < tb_arrayn(s_func), 0);
// done
return s_func[index](value) & mask;
}
// using the uint32 hash
tb_size_t hash0 = tb_element_hash_uint32((tb_uint32_t)value, mask, index);
tb_size_t hash1 = tb_element_hash_uint32((tb_uint32_t)(value >> 32), mask, index);
return ((hash0 ^ hash1) & mask);
}
tb_size_t tb_element_hash_data(tb_byte_t const* data, tb_size_t size, tb_size_t mask, tb_size_t index)
{
// check
tb_assert_and_check_return_val(data && size && mask, 0);
// the func
static tb_size_t (*s_func[])(tb_byte_t const* , tb_size_t) =
{
tb_element_hash_data_func_0
, tb_element_hash_data_func_1
, tb_element_hash_data_func_2
#if !defined(__tb_small__) && defined(TB_CONFIG_MODULE_HAVE_HASH)
, tb_element_hash_data_func_3
, tb_element_hash_data_func_4
, tb_element_hash_data_func_5
, tb_element_hash_data_func_6
, tb_element_hash_data_func_7
, tb_element_hash_data_func_8
, tb_element_hash_data_func_9
, tb_element_hash_data_func_10
, tb_element_hash_data_func_11
, tb_element_hash_data_func_12
, tb_element_hash_data_func_13
, tb_element_hash_data_func_14
, tb_element_hash_data_func_15
#endif
};
tb_assert_and_check_return_val(index < tb_arrayn(s_func), 0);
// done
return s_func[index](data, size) & mask;
}
tb_size_t tb_element_hash_cstr(tb_char_t const* cstr, tb_size_t mask, tb_size_t index)
{
// check
tb_assert_and_check_return_val(cstr && mask, 0);
// for optimization
if (index < 2)
{
// the func
static tb_size_t (*s_func[])(tb_char_t const*) =
{
tb_element_hash_cstr_func_0
, tb_element_hash_cstr_func_1
};
tb_assert_and_check_return_val(index < tb_arrayn(s_func), 0);
// done
return s_func[index](cstr) & mask;
}
// using the data hash
return tb_element_hash_data((tb_byte_t const*)cstr, tb_strlen(cstr), mask, index);
}
tbox-1.7.6/src/tbox/container/element/hash.h 0000664 0000000 0000000 00000005553 14671175054 0020775 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file hash.h
*
*/
#ifndef TB_CONTAINER_ELEMENT_HASH_H
#define TB_CONTAINER_ELEMENT_HASH_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* compute the uint8 hash
*
* @param value the value
* @param mask the mask
* @param index the hash func index
*
* @return the hash value
*/
tb_size_t tb_element_hash_uint8(tb_uint8_t value, tb_size_t mask, tb_size_t index);
/* compute the uint16 hash
*
* @param value the value
* @param mask the mask
* @param index the hash func index
*
* @return the hash value
*/
tb_size_t tb_element_hash_uint16(tb_uint16_t value, tb_size_t mask, tb_size_t index);
/* compute the uint32 hash
*
* @param value the value
* @param mask the mask
* @param index the hash func index
*
* @return the hash value
*/
tb_size_t tb_element_hash_uint32(tb_uint32_t value, tb_size_t mask, tb_size_t index);
/* compute the uint64 hash
*
* @param value the value
* @param mask the mask
* @param index the hash func index
*
* @return the hash value
*/
tb_size_t tb_element_hash_uint64(tb_uint64_t value, tb_size_t mask, tb_size_t index);
/* compute the data hash
*
* @param data the data
* @param size the size
* @param mask the mask
* @param index the hash func index
*
* @return the hash value
*/
tb_size_t tb_element_hash_data(tb_byte_t const* data, tb_size_t size, tb_size_t mask, tb_size_t index);
/* compute the cstring hash
*
* @param cstr the cstring
* @param mask the mask
* @param index the hash func index
*
* @return the hash value
*/
tb_size_t tb_element_hash_cstr(tb_char_t const* cstr, tb_size_t mask, tb_size_t index);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/container/element/long.c 0000664 0000000 0000000 00000007037 14671175054 0021003 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file long.c
* @ingroup container
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_long_t tb_element_long_comp(tb_element_ref_t element, tb_cpointer_t ldata, tb_cpointer_t rdata)
{
// compare it
return ((tb_long_t)ldata < (tb_long_t)rdata)? -1 : ((tb_long_t)ldata > (tb_long_t)rdata);
}
static tb_pointer_t tb_element_long_data(tb_element_ref_t element, tb_cpointer_t buff)
{
// check
tb_assert_and_check_return_val(buff, tb_null);
// the element data
return (tb_pointer_t)*((tb_long_t*)buff);
}
static tb_char_t const* tb_element_long_cstr(tb_element_ref_t element, tb_cpointer_t data, tb_char_t* cstr, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(element && cstr, "");
// format string
tb_long_t n = tb_snprintf(cstr, maxn, "%ld", (tb_long_t)data);
if (n >= 0 && n < (tb_long_t)maxn) cstr[n] = '\0';
// ok?
return (tb_char_t const*)cstr;
}
static tb_void_t tb_element_long_free(tb_element_ref_t element, tb_pointer_t buff)
{
// check
tb_assert_and_check_return(buff);
// clear
*((tb_size_t*)buff) = 0;
}
static tb_void_t tb_element_long_copy(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data)
{
// check
tb_assert_and_check_return(buff);
// copy element
*((tb_long_t*)buff) = (tb_long_t)data;
}
static tb_void_t tb_element_long_nfree(tb_element_ref_t element, tb_pointer_t buff, tb_size_t size)
{
// check
tb_assert_and_check_return(buff);
// clear elements
if (size) tb_memset(buff, 0, size * sizeof(tb_long_t));
}
static tb_void_t tb_element_long_ncopy(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size)
{
// check
tb_assert_and_check_return(buff);
// copy elements
if (size) tb_memset_ptr(buff, data, size);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_element_t tb_element_long()
{
// the size element
tb_element_t element_size = tb_element_size();
// init element
tb_element_t element = {0};
element.type = TB_ELEMENT_TYPE_LONG;
element.flag = 0;
element.hash = element_size.hash;
element.comp = tb_element_long_comp;
element.data = tb_element_long_data;
element.cstr = tb_element_long_cstr;
element.free = tb_element_long_free;
element.dupl = tb_element_long_copy;
element.repl = tb_element_long_copy;
element.copy = tb_element_long_copy;
element.nfree = tb_element_long_nfree;
element.ndupl = tb_element_long_ncopy;
element.nrepl = tb_element_long_ncopy;
element.ncopy = tb_element_long_ncopy;
element.size = sizeof(tb_long_t);
// ok?
return element;
}
tbox-1.7.6/src/tbox/container/element/mem.c 0000664 0000000 0000000 00000013136 14671175054 0020617 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file mem.c
* @ingroup container
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "hash.h"
#include "../../hash/hash.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_size_t tb_element_mem_hash(tb_element_ref_t element, tb_cpointer_t data, tb_size_t mask, tb_size_t index)
{
return tb_element_hash_data((tb_byte_t const*)data, element->size, mask, index);
}
static tb_long_t tb_element_mem_comp(tb_element_ref_t element, tb_cpointer_t ldata, tb_cpointer_t rdata)
{
// check
tb_assert_and_check_return_val(element && element->size && ldata && rdata, 0);
// comp
return tb_memcmp(ldata, rdata, element->size);
}
static tb_pointer_t tb_element_mem_data(tb_element_ref_t element, tb_cpointer_t buff)
{
// check
tb_assert_and_check_return_val(element && buff, tb_null);
// the element data
return (tb_pointer_t)buff;
}
static tb_char_t const* tb_element_mem_cstr(tb_element_ref_t element, tb_cpointer_t data, tb_char_t* cstr, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(element && element->size && cstr && data, tb_null);
// make info
tb_long_t size = tb_snprintf(cstr, maxn, "0x%x", tb_adler32_make((tb_byte_t const*)data, element->size, 0));
if (size >= 0) cstr[size] = '\0';
// ok?
return cstr;
}
static tb_void_t tb_element_mem_free(tb_element_ref_t element, tb_pointer_t buff)
{
// check
tb_assert_and_check_return(element && element->size && buff);
// clear it
tb_memset(buff, 0, element->size);
}
static tb_void_t tb_element_mem_dupl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data)
{
// check
tb_assert_and_check_return(element && element->size && buff && data);
// copy element
tb_memcpy(buff, data, element->size);
}
static tb_void_t tb_element_mem_repl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data)
{
// check
tb_assert_and_check_return(element && element->size && buff && data);
// the free is hooked? free it
if (element->free != tb_element_mem_free && element->free)
element->free(element, buff);
// copy element
tb_memcpy(buff, data, element->size);
}
static tb_void_t tb_element_mem_copy(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data)
{
// check
tb_assert_and_check_return(element && element->size && buff && data);
// copy element
tb_memcpy(buff, data, element->size);
}
static tb_void_t tb_element_mem_nfree(tb_element_ref_t element, tb_pointer_t buff, tb_size_t size)
{
// check
tb_assert_and_check_return(element && element->size && buff);
// the free is hooked? free it
if (element->free != tb_element_mem_free && element->free)
{
tb_size_t n = size;
while (n--) element->free(element, (tb_byte_t*)buff + n * element->size);
}
// clear
if (size) tb_memset(buff, 0, size * element->size);
}
static tb_void_t tb_element_mem_ndupl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size)
{
// check
tb_assert_and_check_return(element && element->size && buff && data);
// copy elements
if (element->ncopy) element->ncopy(element, buff, data, size);
}
static tb_void_t tb_element_mem_nrepl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size)
{
// check
tb_assert_and_check_return(element && element->size && buff && data);
// free elements
if (element->nfree) element->nfree(element, buff, size);
// copy elements
if (element->ncopy) element->ncopy(element, buff, data, size);
}
static tb_void_t tb_element_mem_ncopy(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size)
{
// check
tb_assert_and_check_return(element && element->size && buff && data);
// copy elements
while (size--) tb_memcpy((tb_byte_t*)buff + size * element->size, data, element->size);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_element_t tb_element_mem(tb_size_t size, tb_element_free_func_t free, tb_cpointer_t priv)
{
// check
tb_assert(size < TB_MAXU16);
// init element
tb_element_t element = {0};
element.type = TB_ELEMENT_TYPE_MEM;
element.flag = 0;
element.hash = tb_element_mem_hash;
element.comp = tb_element_mem_comp;
element.data = tb_element_mem_data;
element.cstr = tb_element_mem_cstr;
element.free = free? free : tb_element_mem_free;
element.dupl = tb_element_mem_dupl;
element.repl = tb_element_mem_repl;
element.copy = tb_element_mem_copy;
element.nfree = tb_element_mem_nfree;
element.ndupl = tb_element_mem_ndupl;
element.nrepl = tb_element_mem_nrepl;
element.ncopy = tb_element_mem_ncopy;
element.size = (tb_uint16_t)size;
element.priv = priv;
// ok?
return element;
}
tbox-1.7.6/src/tbox/container/element/null.c 0000664 0000000 0000000 00000005730 14671175054 0021014 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file null.c
* @ingroup container
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_size_t tb_element_null_hash(tb_element_ref_t element, tb_cpointer_t data, tb_size_t size, tb_size_t index)
{
return 0;
}
static tb_long_t tb_element_null_comp(tb_element_ref_t element, tb_cpointer_t ldata, tb_cpointer_t rdata)
{
// always be equal
return 0;
}
static tb_pointer_t tb_element_null_data(tb_element_ref_t element, tb_cpointer_t buff)
{
// the element data
return (tb_pointer_t)tb_null;
}
static tb_char_t const* tb_element_null_cstr(tb_element_ref_t element, tb_cpointer_t data, tb_char_t* cstr, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(element && cstr && maxn, "");
// format string
tb_strlcpy(cstr, "null", maxn);
// ok?
return (tb_char_t const*)cstr;
}
static tb_void_t tb_element_null_free(tb_element_ref_t element, tb_pointer_t buff)
{
}
static tb_void_t tb_element_null_nfree(tb_element_ref_t element, tb_pointer_t buff, tb_size_t size)
{
}
static tb_void_t tb_element_null_repl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data)
{
tb_assert(data == tb_null);
}
static tb_void_t tb_element_null_nrepl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size)
{
tb_assert(data == tb_null);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_element_t tb_element_null()
{
// init element
tb_element_t element = {0};
element.type = TB_ELEMENT_TYPE_NULL;
element.flag = 0;
element.hash = tb_element_null_hash;
element.comp = tb_element_null_comp;
element.data = tb_element_null_data;
element.cstr = tb_element_null_cstr;
element.free = tb_element_null_free;
element.dupl = tb_element_null_repl;
element.repl = tb_element_null_repl;
element.copy = tb_element_null_repl;
element.nfree = tb_element_null_nfree;
element.ndupl = tb_element_null_nrepl;
element.nrepl = tb_element_null_nrepl;
element.ncopy = tb_element_null_nrepl;
element.size = 0;
// ok?
return element;
}
tbox-1.7.6/src/tbox/container/element/obj.c 0000664 0000000 0000000 00000006456 14671175054 0020622 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file obj.c
* @ingroup container
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_char_t const* tb_element_obj_cstr(tb_element_ref_t element, tb_cpointer_t data, tb_char_t* cstr, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(cstr, "");
// format string
tb_long_t n = tb_snprintf(cstr, maxn, "", data);
if (n >= 0 && n < (tb_long_t)maxn) cstr[n] = '\0';
// ok?
return (tb_char_t const*)cstr;
}
static tb_void_t tb_element_obj_free(tb_element_ref_t element, tb_pointer_t buff)
{
// check
tb_assert_and_check_return(element && buff);
// exit
tb_object_ref_t object = *((tb_object_ref_t*)buff);
if (object)
{
tb_object_exit(object);
*((tb_object_ref_t*)buff) = tb_null;
}
}
static tb_void_t tb_element_obj_dupl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data)
{
// check
tb_assert_and_check_return(element && buff);
// refn++
if (data) tb_object_retain((tb_object_ref_t)data);
// copy it
*((tb_cpointer_t*)buff) = data;
}
static tb_void_t tb_element_obj_repl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data)
{
// check
tb_assert_and_check_return(element && buff);
// save the previous object
tb_object_ref_t object = *((tb_object_ref_t*)buff);
// refn++
if (data) tb_object_retain((tb_object_ref_t)data);
// copy it
*((tb_cpointer_t*)buff) = data;
// refn--
if (object) tb_object_exit(object);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_element_t tb_element_obj()
{
// the ptr element
tb_element_t element_ptr = tb_element_ptr(tb_null, tb_null);
// the str element
tb_element_t element_str = tb_element_str(tb_true);
// init element
tb_element_t element = {0};
element.type = TB_ELEMENT_TYPE_OBJ;
element.flag = 0;
element.hash = element_ptr.hash;
element.comp = element_ptr.comp;
element.data = element_ptr.data;
element.cstr = tb_element_obj_cstr;
element.free = tb_element_obj_free;
element.dupl = tb_element_obj_dupl;
element.repl = tb_element_obj_repl;
element.copy = element_ptr.copy;
element.nfree = element_str.nfree;
element.ndupl = element_str.ndupl;
element.nrepl = element_str.nrepl;
element.ncopy = element_ptr.ncopy;
element.size = sizeof(tb_object_ref_t);
// ok?
return element;
}
tbox-1.7.6/src/tbox/container/element/prefix.h 0000664 0000000 0000000 00000002160 14671175054 0021336 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_CONTAINER_ELEMENT_PREFIX_H
#define TB_CONTAINER_ELEMENT_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#include "../element.h"
#include "../../libc/libc.h"
#include "../../utils/utils.h"
#include "../../memory/memory.h"
#include "../../object/object.h"
#include "../../stream/stream.h"
#include "../../platform/platform.h"
#endif
tbox-1.7.6/src/tbox/container/element/ptr.c 0000664 0000000 0000000 00000011622 14671175054 0020644 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file ptr.c
* @ingroup container
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_long_t tb_element_ptr_comp(tb_element_ref_t element, tb_cpointer_t ldata, tb_cpointer_t rdata)
{
return (ldata < rdata)? -1 : (ldata > rdata);
}
static tb_pointer_t tb_element_ptr_data(tb_element_ref_t element, tb_cpointer_t buff)
{
// check
tb_assert_and_check_return_val(buff, tb_null);
// the element data
return *((tb_pointer_t*)buff);
}
static tb_char_t const* tb_element_ptr_cstr(tb_element_ref_t element, tb_cpointer_t data, tb_char_t* cstr, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(cstr, "");
// format string
tb_long_t n = tb_snprintf(cstr, maxn - 1, "%p", data);
if (n >= 0 && n < (tb_long_t)maxn) cstr[n] = '\0';
// ok?
return (tb_char_t const*)cstr;
}
static tb_void_t tb_element_ptr_free(tb_element_ref_t element, tb_pointer_t buff)
{
// check
tb_assert_and_check_return(buff);
// clear it
*((tb_pointer_t*)buff) = tb_null;
}
static tb_void_t tb_element_ptr_repl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data)
{
// check
tb_assert_and_check_return(element && buff);
// the free is hooked? free it
if (element->free != tb_element_ptr_free && element->free)
element->free(element, buff);
// copy it
*((tb_cpointer_t*)buff) = data;
}
static tb_void_t tb_element_ptr_copy(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data)
{
// check
tb_assert_and_check_return(buff);
// copy it
*((tb_cpointer_t*)buff) = data;
}
static tb_void_t tb_element_ptr_dupl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data)
{
// check
tb_assert_and_check_return(buff);
// dupl it
*((tb_cpointer_t*)buff) = data;
}
static tb_void_t tb_element_ptr_nfree(tb_element_ref_t element, tb_pointer_t buff, tb_size_t size)
{
// check
tb_assert_and_check_return(element && buff);
// the free is hooked? free it
if (element->free != tb_element_ptr_free && element->free)
{
tb_size_t n = size;
while (n--) element->free(element, (tb_byte_t*)buff + n * sizeof(tb_pointer_t));
}
// clear
if (size) tb_memset(buff, 0, size * sizeof(tb_pointer_t));
}
static tb_void_t tb_element_ptr_ndupl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size)
{
// check
tb_assert_and_check_return(buff);
// copy elements
if (element->ncopy) element->ncopy(element, buff, data, size);
}
static tb_void_t tb_element_ptr_nrepl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size)
{
// check
tb_assert_and_check_return(element && buff);
// free element
if (element->nfree) element->nfree(element, buff, size);
// copy elements
if (element->ncopy) element->ncopy(element, buff, data, size);
}
static tb_void_t tb_element_ptr_ncopy(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size)
{
// check
tb_assert_and_check_return(buff);
// fill elements
if (size) tb_memset_ptr(buff, data, size);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_element_t tb_element_ptr(tb_element_free_func_t free, tb_cpointer_t priv)
{
// the size element
tb_element_t element_size = tb_element_size();
// init element
tb_element_t element = {0};
element.type = TB_ELEMENT_TYPE_PTR;
element.flag = 0;
element.hash = element_size.hash;
element.comp = tb_element_ptr_comp;
element.data = tb_element_ptr_data;
element.cstr = tb_element_ptr_cstr;
element.free = free? free : tb_element_ptr_free;
element.dupl = tb_element_ptr_dupl;
element.repl = tb_element_ptr_repl;
element.copy = tb_element_ptr_copy;
element.nfree = tb_element_ptr_nfree;
element.ndupl = tb_element_ptr_ndupl;
element.nrepl = tb_element_ptr_nrepl;
element.ncopy = tb_element_ptr_ncopy;
element.priv = priv;
element.size = sizeof(tb_pointer_t);
// ok?
return element;
}
tbox-1.7.6/src/tbox/container/element/size.c 0000664 0000000 0000000 00000007606 14671175054 0021020 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file size.c
* @ingroup container
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "hash.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_size_t tb_element_size_hash(tb_element_ref_t element, tb_cpointer_t data, tb_size_t mask, tb_size_t index)
{
#if TB_CPU_BIT64
tb_assert_static(sizeof(tb_size_t) == sizeof(tb_uint64_t));
return tb_element_hash_uint64((tb_uint64_t)data, mask, index);
#else
tb_assert_static(sizeof(tb_size_t) == sizeof(tb_uint32_t));
return tb_element_hash_uint32((tb_uint32_t)data, mask, index);
#endif
}
static tb_long_t tb_element_size_comp(tb_element_ref_t element, tb_cpointer_t ldata, tb_cpointer_t rdata)
{
// compare it
return ((tb_size_t)ldata < (tb_size_t)rdata)? -1 : ((tb_size_t)ldata > (tb_size_t)rdata);
}
static tb_pointer_t tb_element_size_data(tb_element_ref_t element, tb_cpointer_t buff)
{
// check
tb_assert_and_check_return_val(buff, tb_null);
// the element data
return (tb_pointer_t)*((tb_size_t*)buff);
}
static tb_char_t const* tb_element_size_cstr(tb_element_ref_t element, tb_cpointer_t data, tb_char_t* cstr, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(element && cstr, "");
// format string
tb_long_t n = tb_snprintf(cstr, maxn, "%lu", (tb_size_t)data);
if (n >= 0 && n < (tb_long_t)maxn) cstr[n] = '\0';
// ok?
return (tb_char_t const*)cstr;
}
static tb_void_t tb_element_size_free(tb_element_ref_t element, tb_pointer_t buff)
{
// check
tb_assert_and_check_return(buff);
// clear
*((tb_size_t*)buff) = 0;
}
static tb_void_t tb_element_size_copy(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data)
{
// check
tb_assert_and_check_return(buff);
// copy element
*((tb_size_t*)buff) = (tb_size_t)data;
}
static tb_void_t tb_element_size_nfree(tb_element_ref_t element, tb_pointer_t buff, tb_size_t size)
{
// check
tb_assert_and_check_return(buff);
// clear elements
if (size) tb_memset(buff, 0, size * sizeof(tb_size_t));
}
static tb_void_t tb_element_size_ncopy(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size)
{
// check
tb_assert_and_check_return(buff);
// copy elements
if (size) tb_memset_ptr(buff, data, size);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_element_t tb_element_size()
{
// init element
tb_element_t element = {0};
element.type = TB_ELEMENT_TYPE_SIZE;
element.flag = 0;
element.hash = tb_element_size_hash;
element.comp = tb_element_size_comp;
element.data = tb_element_size_data;
element.cstr = tb_element_size_cstr;
element.free = tb_element_size_free;
element.dupl = tb_element_size_copy;
element.repl = tb_element_size_copy;
element.copy = tb_element_size_copy;
element.nfree = tb_element_size_nfree;
element.ndupl = tb_element_size_ncopy;
element.nrepl = tb_element_size_ncopy;
element.ncopy = tb_element_size_ncopy;
element.size = sizeof(tb_size_t);
// ok?
return element;
}
tbox-1.7.6/src/tbox/container/element/str.c 0000664 0000000 0000000 00000014335 14671175054 0020653 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file str.c
* @ingroup container
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "hash.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_size_t tb_element_str_hash(tb_element_ref_t element, tb_cpointer_t data, tb_size_t mask, tb_size_t index)
{
return tb_element_hash_cstr((tb_char_t const*)data, mask, index);
}
static tb_long_t tb_element_str_comp(tb_element_ref_t element, tb_cpointer_t ldata, tb_cpointer_t rdata)
{
// check
tb_assert_and_check_return_val(element && ldata && rdata, 0);
// compare it
return element->flag? tb_strcmp((tb_char_t const*)ldata, (tb_char_t const*)rdata) : tb_stricmp((tb_char_t const*)ldata, (tb_char_t const*)rdata);
}
static tb_pointer_t tb_element_str_data(tb_element_ref_t element, tb_cpointer_t buff)
{
// check
tb_assert_and_check_return_val(buff, tb_null);
// the element data
return *((tb_pointer_t*)buff);
}
static tb_char_t const* tb_element_str_cstr(tb_element_ref_t element, tb_cpointer_t data, tb_char_t* cstr, tb_size_t maxn)
{
// the c-string
return (tb_char_t const*)data;
}
static tb_void_t tb_element_str_free(tb_element_ref_t element, tb_pointer_t buff)
{
// check
tb_assert_and_check_return(element && buff);
// exists?
tb_pointer_t cstr = *((tb_pointer_t*)buff);
if (cstr)
{
// free it
tb_free(cstr);
// clear it
*((tb_pointer_t*)buff) = tb_null;
}
}
static tb_void_t tb_element_str_dupl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data)
{
// check
tb_assert_and_check_return(element && buff);
// duplicate it
if (data) *((tb_char_t const**)buff) = tb_strdup((tb_char_t const*)data);
// clear it
else *((tb_char_t const**)buff) = tb_null;
}
static tb_void_t tb_element_str_repl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data)
{
// check
tb_assert_and_check_return(element && element->dupl && buff);
#if 0
// free it
if (element->free) element->free(element, buff);
// dupl it
element->dupl(element, buff, data);
#else
// replace it
tb_pointer_t cstr = *((tb_pointer_t*)buff);
if (cstr && data)
{
// attempt to replace it
tb_char_t* p = (tb_char_t*)cstr;
tb_char_t const* q = (tb_char_t const*)data;
while (*p && *q) *p++ = *q++;
// not enough space?
if (!*p && *q)
{
// the left size
tb_size_t left = tb_strlen(q);
tb_assert(left);
// the copy size
tb_size_t copy = p - (tb_char_t*)cstr;
// grow size
cstr = tb_ralloc(cstr, copy + left + 1);
tb_assert(cstr);
// copy the left data
tb_memcpy((tb_char_t*)cstr + copy, q, left + 1);
// update the cstr
*((tb_pointer_t*)buff) = cstr;
}
// end
else *p = '\0';
}
// duplicate it
else if (data) element->dupl(element, buff, data);
// free it
else if (element->free) element->free(element, buff);
// clear it
else *((tb_char_t const**)buff) = tb_null;
#endif
}
static tb_void_t tb_element_str_copy(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data)
{
// check
tb_assert_and_check_return(buff);
// copy it
*((tb_cpointer_t*)buff) = data;
}
static tb_void_t tb_element_str_nfree(tb_element_ref_t element, tb_pointer_t buff, tb_size_t size)
{
// check
tb_assert_and_check_return(element && buff);
// free elements
if (element->free)
{
tb_size_t n = size;
while (n--) element->free(element, (tb_byte_t*)buff + n * sizeof(tb_char_t*));
}
// clear
if (size) tb_memset(buff, 0, size * sizeof(tb_char_t*));
}
static tb_void_t tb_element_str_ndupl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size)
{
// check
tb_assert_and_check_return(element && buff);
// dupl elements
if (element->dupl) while (size--) element->dupl(element, (tb_byte_t*)buff + size * sizeof(tb_char_t*), data);
}
static tb_void_t tb_element_str_nrepl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size)
{
// check
tb_assert_and_check_return(element && buff && data);
// repl elements
if (element->repl) while (size--) element->repl(element, (tb_byte_t*)buff + size * sizeof(tb_char_t*), data);
}
static tb_void_t tb_element_str_ncopy(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size)
{
// check
tb_assert_and_check_return(buff);
// fill elements
if (size) tb_memset_ptr(buff, data, size);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_element_t tb_element_str(tb_bool_t bcase)
{
// init element
tb_element_t element = {0};
element.type = TB_ELEMENT_TYPE_STR;
element.flag = !!bcase;
element.hash = tb_element_str_hash;
element.comp = tb_element_str_comp;
element.data = tb_element_str_data;
element.cstr = tb_element_str_cstr;
element.free = tb_element_str_free;
element.dupl = tb_element_str_dupl;
element.repl = tb_element_str_repl;
element.copy = tb_element_str_copy;
element.nfree = tb_element_str_nfree;
element.ndupl = tb_element_str_ndupl;
element.nrepl = tb_element_str_nrepl;
element.ncopy = tb_element_str_ncopy;
element.size = sizeof(tb_char_t*);
// ok?
return element;
}
tbox-1.7.6/src/tbox/container/element/true.c 0000664 0000000 0000000 00000006004 14671175054 0021014 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file true.c
* @ingroup container
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_size_t tb_element_true_hash(tb_element_ref_t element, tb_cpointer_t data, tb_size_t size, tb_size_t index)
{
return 0;
}
static tb_long_t tb_element_true_comp(tb_element_ref_t element, tb_cpointer_t ldata, tb_cpointer_t rdata)
{
// always be equal
return 0;
}
static tb_pointer_t tb_element_true_data(tb_element_ref_t element, tb_cpointer_t buff)
{
// the element data
return (tb_pointer_t)tb_true;
}
static tb_char_t const* tb_element_true_cstr(tb_element_ref_t element, tb_cpointer_t data, tb_char_t* cstr, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(element && cstr && maxn, "");
// format string
tb_strlcpy(cstr, "true", maxn);
// ok?
return (tb_char_t const*)cstr;
}
static tb_void_t tb_element_true_free(tb_element_ref_t element, tb_pointer_t buff)
{
}
static tb_void_t tb_element_true_nfree(tb_element_ref_t element, tb_pointer_t buff, tb_size_t size)
{
}
static tb_void_t tb_element_true_repl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data)
{
tb_assert((tb_bool_t)(tb_size_t)data == tb_true);
}
static tb_void_t tb_element_true_nrepl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size)
{
tb_assert((tb_bool_t)(tb_size_t)data == tb_true);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_element_t tb_element_true()
{
// init element
tb_element_t element = {0};
element.type = TB_ELEMENT_TYPE_TRUE;
element.flag = 0;
element.hash = tb_element_true_hash;
element.comp = tb_element_true_comp;
element.data = tb_element_true_data;
element.cstr = tb_element_true_cstr;
element.free = tb_element_true_free;
element.dupl = tb_element_true_repl;
element.repl = tb_element_true_repl;
element.copy = tb_element_true_repl;
element.nfree = tb_element_true_nfree;
element.ndupl = tb_element_true_nrepl;
element.nrepl = tb_element_true_nrepl;
element.ncopy = tb_element_true_nrepl;
element.size = 0;
// ok?
return element;
}
tbox-1.7.6/src/tbox/container/element/uint16.c 0000664 0000000 0000000 00000007334 14671175054 0021172 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file uint16.c
* @ingroup container
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "hash.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_size_t tb_element_uint16_hash(tb_element_ref_t element, tb_cpointer_t data, tb_size_t mask, tb_size_t index)
{
return tb_element_hash_uint16(tb_p2u16(data), mask, index);
}
static tb_long_t tb_element_uint16_comp(tb_element_ref_t element, tb_cpointer_t ldata, tb_cpointer_t rdata)
{
// compare it
return ((tb_p2u16(ldata) < tb_p2u16(rdata))? -1 : (tb_p2u16(ldata) > tb_p2u16(rdata)));
}
static tb_pointer_t tb_element_uint16_data(tb_element_ref_t element, tb_cpointer_t buff)
{
// check
tb_assert_and_check_return_val(buff, tb_null);
// the element data
return tb_u2p(*((tb_uint16_t*)buff));
}
static tb_char_t const* tb_element_uint16_cstr(tb_element_ref_t element, tb_cpointer_t data, tb_char_t* cstr, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(element && cstr, "");
// format string
tb_long_t n = tb_snprintf(cstr, maxn, "%u", (tb_uint16_t)(tb_size_t)data);
if (n >= 0 && n < (tb_long_t)maxn) cstr[n] = '\0';
// ok?
return (tb_char_t const*)cstr;
}
static tb_void_t tb_element_uint16_free(tb_element_ref_t element, tb_pointer_t buff)
{
// check
tb_assert_and_check_return(buff);
// clear
*((tb_uint16_t*)buff) = 0;
}
static tb_void_t tb_element_uint16_copy(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data)
{
// check
tb_assert_and_check_return(buff);
// copy element
*((tb_uint16_t*)buff) = tb_p2u16(data);
}
static tb_void_t tb_element_uint16_nfree(tb_element_ref_t element, tb_pointer_t buff, tb_size_t size)
{
// check
tb_assert_and_check_return(buff);
// clear elements
if (size) tb_memset(buff, 0, size * sizeof(tb_uint16_t));
}
static tb_void_t tb_element_uint16_ncopy(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size)
{
// check
tb_assert_and_check_return(buff);
// copy elements
tb_memset_u16(buff, tb_p2u16(data), size);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_element_t tb_element_uint16()
{
// init element
tb_element_t element = {0};
element.type = TB_ELEMENT_TYPE_UINT16;
element.flag = 0;
element.hash = tb_element_uint16_hash;
element.comp = tb_element_uint16_comp;
element.data = tb_element_uint16_data;
element.cstr = tb_element_uint16_cstr;
element.free = tb_element_uint16_free;
element.dupl = tb_element_uint16_copy;
element.repl = tb_element_uint16_copy;
element.copy = tb_element_uint16_copy;
element.nfree = tb_element_uint16_nfree;
element.ndupl = tb_element_uint16_ncopy;
element.nrepl = tb_element_uint16_ncopy;
element.ncopy = tb_element_uint16_ncopy;
element.size = sizeof(tb_uint16_t);
// ok?
return element;
}
tbox-1.7.6/src/tbox/container/element/uint32.c 0000664 0000000 0000000 00000007334 14671175054 0021170 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file uint32.c
* @ingroup container
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "hash.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_size_t tb_element_uint32_hash(tb_element_ref_t element, tb_cpointer_t data, tb_size_t mask, tb_size_t index)
{
return tb_element_hash_uint32(tb_p2u32(data), mask, index);
}
static tb_long_t tb_element_uint32_comp(tb_element_ref_t element, tb_cpointer_t ldata, tb_cpointer_t rdata)
{
// compare it
return ((tb_p2u32(ldata) < tb_p2u32(rdata))? -1 : (tb_p2u32(ldata) > tb_p2u32(rdata)));
}
static tb_pointer_t tb_element_uint32_data(tb_element_ref_t element, tb_cpointer_t buff)
{
// check
tb_assert_and_check_return_val(buff, tb_null);
// the element data
return tb_u2p(*((tb_uint32_t*)buff));
}
static tb_char_t const* tb_element_uint32_cstr(tb_element_ref_t element, tb_cpointer_t data, tb_char_t* cstr, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(element && cstr, "");
// format string
tb_long_t n = tb_snprintf(cstr, maxn, "%u", (tb_uint32_t)(tb_size_t)data);
if (n >= 0 && n < (tb_long_t)maxn) cstr[n] = '\0';
// ok?
return (tb_char_t const*)cstr;
}
static tb_void_t tb_element_uint32_free(tb_element_ref_t element, tb_pointer_t buff)
{
// check
tb_assert_and_check_return(buff);
// clear
*((tb_uint32_t*)buff) = 0;
}
static tb_void_t tb_element_uint32_copy(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data)
{
// check
tb_assert_and_check_return(buff);
// copy element
*((tb_uint32_t*)buff) = tb_p2u32(data);
}
static tb_void_t tb_element_uint32_nfree(tb_element_ref_t element, tb_pointer_t buff, tb_size_t size)
{
// check
tb_assert_and_check_return(buff);
// clear elements
if (size) tb_memset(buff, 0, size * sizeof(tb_uint32_t));
}
static tb_void_t tb_element_uint32_ncopy(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size)
{
// check
tb_assert_and_check_return(buff);
// copy elements
tb_memset_u16(buff, tb_p2u32(data), size);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_element_t tb_element_uint32()
{
// init element
tb_element_t element = {0};
element.type = TB_ELEMENT_TYPE_UINT32;
element.flag = 0;
element.hash = tb_element_uint32_hash;
element.comp = tb_element_uint32_comp;
element.data = tb_element_uint32_data;
element.cstr = tb_element_uint32_cstr;
element.free = tb_element_uint32_free;
element.dupl = tb_element_uint32_copy;
element.repl = tb_element_uint32_copy;
element.copy = tb_element_uint32_copy;
element.nfree = tb_element_uint32_nfree;
element.ndupl = tb_element_uint32_ncopy;
element.nrepl = tb_element_uint32_ncopy;
element.ncopy = tb_element_uint32_ncopy;
element.size = sizeof(tb_uint32_t);
// ok?
return element;
}
tbox-1.7.6/src/tbox/container/element/uint8.c 0000664 0000000 0000000 00000007236 14671175054 0021114 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file uint8.c
* @ingroup container
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "hash.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_size_t tb_element_uint8_hash(tb_element_ref_t element, tb_cpointer_t data, tb_size_t mask, tb_size_t index)
{
return tb_element_hash_uint8(tb_p2u8(data), mask, index);
}
static tb_long_t tb_element_uint8_comp(tb_element_ref_t element, tb_cpointer_t ldata, tb_cpointer_t rdata)
{
// compare it
return ((tb_p2u8(ldata) < tb_p2u8(rdata))? -1 : (tb_p2u8(ldata) > tb_p2u8(rdata)));
}
static tb_pointer_t tb_element_uint8_data(tb_element_ref_t element, tb_cpointer_t buff)
{
// check
tb_assert_and_check_return_val(buff, tb_null);
// the element data
return tb_u2p(*((tb_uint8_t*)buff));
}
static tb_char_t const* tb_element_uint8_cstr(tb_element_ref_t element, tb_cpointer_t data, tb_char_t* cstr, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(element && cstr, "");
// format string
tb_long_t n = tb_snprintf(cstr, maxn, "%u", (tb_uint8_t)(tb_size_t)data);
if (n >= 0 && n < (tb_long_t)maxn) cstr[n] = '\0';
// ok?
return (tb_char_t const*)cstr;
}
static tb_void_t tb_element_uint8_free(tb_element_ref_t element, tb_pointer_t buff)
{
// check
tb_assert_and_check_return(buff);
// clear
*((tb_uint8_t*)buff) = 0;
}
static tb_void_t tb_element_uint8_copy(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data)
{
// check
tb_assert_and_check_return(buff);
// copy element
*((tb_uint8_t*)buff) = tb_p2u8(data);
}
static tb_void_t tb_element_uint8_nfree(tb_element_ref_t element, tb_pointer_t buff, tb_size_t size)
{
// check
tb_assert_and_check_return(buff);
// clear elements
if (size) tb_memset(buff, 0, size);
}
static tb_void_t tb_element_uint8_ncopy(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size)
{
// check
tb_assert_and_check_return(buff);
// copy elements
tb_memset(buff, tb_p2u8(data), size);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_element_t tb_element_uint8()
{
// init element
tb_element_t element = {0};
element.type = TB_ELEMENT_TYPE_UINT8;
element.flag = 0;
element.hash = tb_element_uint8_hash;
element.comp = tb_element_uint8_comp;
element.data = tb_element_uint8_data;
element.cstr = tb_element_uint8_cstr;
element.free = tb_element_uint8_free;
element.dupl = tb_element_uint8_copy;
element.repl = tb_element_uint8_copy;
element.copy = tb_element_uint8_copy;
element.nfree = tb_element_uint8_nfree;
element.ndupl = tb_element_uint8_ncopy;
element.nrepl = tb_element_uint8_ncopy;
element.ncopy = tb_element_uint8_ncopy;
element.size = sizeof(tb_uint8_t);
// ok?
return element;
}
tbox-1.7.6/src/tbox/container/hash_map.c 0000664 0000000 0000000 00000065047 14671175054 0020200 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file hash_map.c
* @ingroup container
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "hash_map"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "hash_map.h"
#include "../libc/libc.h"
#include "../math/math.h"
#include "../utils/utils.h"
#include "../memory/memory.h"
#include "../stream/stream.h"
#include "../platform/platform.h"
#include "../algorithm/algorithm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// index
#if TB_CPU_BIT64
# define tb_hash_map_index_make(buck, item) (((tb_size_t)((item) & 0xffffffff) << 32) | ((buck) & 0xffffffff))
# define tb_hash_map_index_buck(index) ((index) & 0xffffffff)
# define tb_hash_map_index_item(index) (((index) >> 32) & 0xffffffff)
#else
# define tb_hash_map_index_make(buck, item) (((tb_size_t)((item) & 0xffff) << 16) | ((buck) & 0xffff))
# define tb_hash_map_index_buck(index) ((index) & 0xffff)
# define tb_hash_map_index_item(index) (((index) >> 16) & 0xffff)
#endif
// the self bucket default size
#ifdef __tb_small__
# define TB_HASH_MAP_BUCKET_SIZE_DEFAULT TB_HASH_MAP_BUCKET_SIZE_MICRO
#else
# define TB_HASH_MAP_BUCKET_SIZE_DEFAULT TB_HASH_MAP_BUCKET_SIZE_SMALL
#endif
// the self bucket maximum size
#define TB_HASH_MAP_BUCKET_MAXN (1 << 16)
// the self bucket item maximum size
#define TB_HASH_MAP_BUCKET_ITEM_MAXN (1 << 16)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the hash map item list type
typedef struct __tb_hash_map_item_list_t
{
// the list size
tb_size_t size;
// the list maxn
tb_size_t maxn;
}tb_hash_map_item_list_t;
// the hash map type
typedef struct __tb_hash_map_t
{
// the item itor
tb_iterator_t itor;
// the hash list
tb_hash_map_item_list_t** hash_list;
// the hash list size
tb_size_t hash_size;
// the current item for iterator
tb_hash_map_item_t item;
// the item size
tb_size_t item_size;
// the item maxn
tb_size_t item_maxn;
// the item grow
tb_size_t item_grow;
// the element for name
tb_element_t element_name;
// the element for data
tb_element_t element_data;
}tb_hash_map_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
#if 0
// linear finder
static tb_bool_t tb_hash_map_item_find(tb_hash_map_t* hash_map, tb_cpointer_t name, tb_size_t* pbuck, tb_size_t* pitem)
{
tb_assert_and_check_return_val(hash_map && hash_map->hash_list && hash_map->hash_size, tb_false);
// get step
tb_size_t step = hash_map->element_name.size + hash_map->element_data.size;
tb_assert_and_check_return_val(step, tb_false);
// comupte hash_map from name
tb_size_t buck = hash_map->element_name.hash(&hash_map->element_name, name, hash_map->hash_size - 1, 0);
tb_assert_and_check_return_val(buck < hash_map->hash_size, tb_false);
// update buck
if (pbuck) *pbuck = buck;
// get list
tb_hash_map_item_list_t* list = hash_map->hash_list[buck];
tb_check_return_val(list && list->size, tb_false);
// find item
tb_long_t r = 1;
tb_size_t i = 0;
tb_size_t n = list->size;
for (i = 0; i < n; i++)
{
// get item
tb_byte_t const* item = ((tb_byte_t*)&list[1]) + i * step;
// compare it
r = hash_map->element_name.comp(&hash_map->element_name, name, hash_map->element_name.data(&hash_map->element_name, item));
if (r <= 0) break;
}
// update item
if (pitem) *pitem = i;
// ok?
return !r? tb_true : tb_false;
}
#else
// binary finder
static tb_bool_t tb_hash_map_item_find(tb_hash_map_t* hash_map, tb_cpointer_t name, tb_size_t* pbuck, tb_size_t* pitem)
{
// check
tb_assert_and_check_return_val(hash_map && hash_map->hash_list && hash_map->hash_size, tb_false);
// get step
tb_size_t step = hash_map->element_name.size + hash_map->element_data.size;
tb_assert_and_check_return_val(step, tb_false);
// comupte hash_map from name
tb_size_t buck = hash_map->element_name.hash(&hash_map->element_name, name, hash_map->hash_size - 1, 0);
tb_assert_and_check_return_val(buck < hash_map->hash_size, tb_false);
// update buck
if (pbuck) *pbuck = buck;
// get list
tb_hash_map_item_list_t* list = hash_map->hash_list[buck];
tb_check_return_val(list && list->size, tb_false);
// find item
tb_long_t t = 1;
tb_size_t l = 0;
tb_size_t r = list->size;
tb_size_t m = (l + r) >> 1;
while (l < r)
{
// get item
tb_byte_t const* item = ((tb_byte_t*)&list[1]) + m * step;
// compare it
t = hash_map->element_name.comp(&hash_map->element_name, name, hash_map->element_name.data(&hash_map->element_name, item));
if (t < 0) r = m;
else if (t > 0) l = m + 1;
else break;
// next
m = (l + r) >> 1;
}
/* update item
*
* @note: m is not the prev not same item if not found and list has repeat items
* but this hash_map not exists repeat
*
* @see tb_binary_pfind()
*/
if (pitem) *pitem = m;
// ok?
return !t? tb_true : tb_false;
}
#endif
static tb_bool_t tb_hash_map_item_at(tb_hash_map_t* hash_map, tb_size_t buck, tb_size_t item, tb_pointer_t* pname, tb_pointer_t* pdata)
{
// check
tb_assert_and_check_return_val(hash_map && hash_map->hash_list && hash_map->hash_size && buck < hash_map->hash_size, tb_false);
// get step
tb_size_t step = hash_map->element_name.size + hash_map->element_data.size;
tb_assert_and_check_return_val(step, tb_false);
// get list
tb_hash_map_item_list_t* list = hash_map->hash_list[buck];
tb_check_return_val(list && list->size && item < list->size, tb_false);
// get name
if (pname) *pname = hash_map->element_name.data(&hash_map->element_name, ((tb_byte_t*)&list[1]) + item * step);
// get data
if (pdata) *pdata = hash_map->element_data.data(&hash_map->element_data, ((tb_byte_t*)&list[1]) + item * step + hash_map->element_name.size);
// ok
return tb_true;
}
static tb_size_t tb_hash_map_itor_size(tb_iterator_ref_t iterator)
{
// check
tb_hash_map_t* hash_map = (tb_hash_map_t*)iterator;
tb_assert(hash_map);
// the size
return hash_map->item_size;
}
static tb_size_t tb_hash_map_itor_head(tb_iterator_ref_t iterator)
{
// check
tb_hash_map_t* hash_map = (tb_hash_map_t*)iterator;
tb_assert(hash_map);
// find the head
tb_size_t i = 0;
tb_size_t n = hash_map->hash_size;
for (i = 0; i < n; i++)
{
tb_hash_map_item_list_t* list = hash_map->hash_list[i];
if (list && list->size) return tb_hash_map_index_make(i + 1, 1);
}
return 0;
}
static tb_size_t tb_hash_map_itor_tail(tb_iterator_ref_t iterator)
{
return 0;
}
static tb_size_t tb_hash_map_itor_next(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_hash_map_t* hash_map = (tb_hash_map_t*)iterator;
tb_assert(hash_map && hash_map->hash_list && hash_map->hash_size);
// the current buck and item
tb_size_t buck = tb_hash_map_index_buck(itor);
tb_size_t item = tb_hash_map_index_item(itor);
tb_assert(buck && item);
// compute index
buck--;
item--;
tb_assert(buck < hash_map->hash_size && (item + 1) < TB_HASH_MAP_BUCKET_ITEM_MAXN);
// find the next from the current buck first
if (hash_map->hash_list[buck] && item + 1 < hash_map->hash_list[buck]->size) return tb_hash_map_index_make(buck + 1, item + 2);
// find the next from the next buckets
tb_size_t i;
tb_size_t n = hash_map->hash_size;
for (i = buck + 1; i < n; i++)
{
tb_hash_map_item_list_t* list = hash_map->hash_list[i];
if (list && list->size) return tb_hash_map_index_make(i + 1, 1);
}
// tail
return 0;
}
static tb_pointer_t tb_hash_map_itor_item(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_hash_map_t* hash_map = (tb_hash_map_t*)iterator;
tb_assert(hash_map && itor);
// get the buck and item
tb_size_t buck = tb_hash_map_index_buck(itor);
tb_size_t item = tb_hash_map_index_item(itor);
tb_assert_and_check_return_val(buck && item, tb_null);
// get item
if (tb_hash_map_item_at(hash_map, buck - 1, item - 1, &((tb_hash_map_t*)hash_map)->item.name, &((tb_hash_map_t*)hash_map)->item.data))
return &(hash_map->item);
return tb_null;
}
static tb_void_t tb_hash_map_itor_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item)
{
// check
tb_hash_map_t* hash_map = (tb_hash_map_t*)iterator;
tb_assert(hash_map && hash_map->hash_list && hash_map->hash_size);
// the buck and item
tb_size_t b = tb_hash_map_index_buck(itor);
tb_size_t i = tb_hash_map_index_item(itor);
tb_assert(b && i); b--; i--;
tb_assert(b < hash_map->hash_size);
// step
tb_size_t step = hash_map->element_name.size + hash_map->element_data.size;
tb_assert(step);
// list
tb_hash_map_item_list_t* list = hash_map->hash_list[b];
tb_check_return(list && list->size && i < list->size);
// note: copy data only, will destroy hash_map index if copy name
hash_map->element_data.copy(&hash_map->element_data, ((tb_byte_t*)&list[1]) + i * step + hash_map->element_name.size, item);
}
static tb_long_t tb_hash_map_itor_comp(tb_iterator_ref_t iterator, tb_cpointer_t lelement, tb_cpointer_t relement)
{
// check
tb_hash_map_t* hash_map = (tb_hash_map_t*)iterator;
tb_assert(hash_map && hash_map->element_name.comp && lelement && relement);
// done
return hash_map->element_name.comp(&hash_map->element_name, ((tb_hash_map_item_ref_t)lelement)->name, ((tb_hash_map_item_ref_t)relement)->name);
}
static tb_void_t tb_hash_map_itor_remove(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_hash_map_t* hash_map = (tb_hash_map_t*)iterator;
tb_assert(hash_map && hash_map->hash_list && hash_map->hash_size);
// buck & item
tb_size_t buck = tb_hash_map_index_buck(itor);
tb_size_t item = tb_hash_map_index_item(itor);
tb_assert(buck && item); buck--; item--;
tb_assert(buck < hash_map->hash_size);
// the step
tb_size_t step = hash_map->element_name.size + hash_map->element_data.size;
tb_assert(step);
// get list
tb_hash_map_item_list_t* list = hash_map->hash_list[buck];
tb_assert(list && list->size && item < list->size);
// free item
if (hash_map->element_name.free) hash_map->element_name.free(&hash_map->element_name, ((tb_byte_t*)&list[1]) + item * step);
if (hash_map->element_data.free) hash_map->element_data.free(&hash_map->element_data, ((tb_byte_t*)&list[1]) + item * step + hash_map->element_name.size);
// remove item from the list
if (list->size > 1)
{
// move items
if (item < list->size - 1) tb_memmov(((tb_byte_t*)&list[1]) + item * step, ((tb_byte_t*)&list[1]) + (item + 1) * step, (list->size - item - 1) * step);
// update size
list->size--;
}
// remove list
else
{
// free it
tb_free(list);
// reset
hash_map->hash_list[buck] = tb_null;
}
// update the hash_map item size
hash_map->item_size--;
}
static tb_void_t tb_hash_map_itor_nremove(tb_iterator_ref_t iterator, tb_size_t prev, tb_size_t next, tb_size_t size)
{
// check
tb_hash_map_t* hash_map = (tb_hash_map_t*)iterator;
tb_assert(hash_map && hash_map->hash_list && hash_map->hash_size);
// no size
tb_check_return(size);
// the step
tb_size_t step = hash_map->element_name.size + hash_map->element_data.size;
tb_assert(step);
// the first itor
tb_size_t itor = prev? tb_hash_map_itor_next(iterator, prev) : tb_hash_map_itor_head(iterator);
// the head buck and item
tb_size_t buck_head = tb_hash_map_index_buck(itor);
tb_size_t item_head = tb_hash_map_index_item(itor);
tb_assert(buck_head && item_head);
// compute index
buck_head--;
item_head--;
tb_assert(buck_head < hash_map->hash_size && item_head < TB_HASH_MAP_BUCKET_ITEM_MAXN);
// the last buck and the tail item
tb_size_t buck_last;
tb_size_t item_tail;
if (next)
{
// next => buck and item
buck_last = tb_hash_map_index_buck(next);
item_tail = tb_hash_map_index_item(next);
tb_assert(buck_last && item_tail);
// compute index
buck_last--;
item_tail--;
tb_assert(buck_last < hash_map->hash_size && item_tail < TB_HASH_MAP_BUCKET_ITEM_MAXN);
}
else
{
buck_last = hash_map->hash_size - 1;
item_tail = -1;
}
// remove items: [itor, next)
tb_size_t buck;
tb_size_t item;
tb_element_free_func_t name_free = hash_map->element_name.free;
tb_element_free_func_t data_free = hash_map->element_data.free;
for (buck = buck_head, item = item_head; buck <= buck_last; buck++, item = 0)
{
// the list
tb_hash_map_item_list_t* list = hash_map->hash_list[buck];
tb_check_continue(list && list->size);
// the tail
tb_size_t tail = (buck == buck_last && next)? item_tail : list->size;
tb_assert(tail != -1);
tb_check_continue(item < tail);
// the data
tb_byte_t* data = (tb_byte_t*)&list[1];
// free items
tb_size_t i = 0;
for (i = item; i < tail; i++)
{
if (name_free) name_free(&hash_map->element_name, data + i * step);
if (data_free) data_free(&hash_map->element_data, data + i * step + hash_map->element_name.size);
}
// move items
if (buck == buck_last && tail < list->size) tb_memmov(data + item * step, data + tail * step, (list->size - tail) * step);
// update the list size
list->size -= tail - item;
// update the item size
hash_map->item_size -= tail - item;
}
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_hash_map_ref_t tb_hash_map_init(tb_size_t bucket_size, tb_element_t element_name, tb_element_t element_data)
{
// check
tb_assert_and_check_return_val(element_name.size && element_name.hash && element_name.comp && element_name.data && element_name.dupl, tb_null);
tb_assert_and_check_return_val(element_data.data && element_data.dupl && element_data.repl, tb_null);
// check bucket size
if (!bucket_size) bucket_size = TB_HASH_MAP_BUCKET_SIZE_DEFAULT;
tb_assert_and_check_return_val(bucket_size <= TB_HASH_MAP_BUCKET_SIZE_LARGE, tb_null);
// done
tb_bool_t ok = tb_false;
tb_hash_map_t* hash_map = tb_null;
do
{
// make self
hash_map = tb_malloc0_type(tb_hash_map_t);
tb_assert_and_check_break(hash_map);
// init self func
hash_map->element_name = element_name;
hash_map->element_data = element_data;
// init operation
static tb_iterator_op_t op =
{
tb_hash_map_itor_size
, tb_hash_map_itor_head
, tb_null
, tb_hash_map_itor_tail
, tb_null
, tb_hash_map_itor_next
, tb_hash_map_itor_item
, tb_hash_map_itor_comp
, tb_hash_map_itor_copy
, tb_hash_map_itor_remove
, tb_hash_map_itor_nremove
};
// init iterator
hash_map->itor.priv = tb_null;
hash_map->itor.step = sizeof(tb_hash_map_item_t);
hash_map->itor.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_MUTABLE;
hash_map->itor.op = &op;
// init self size
hash_map->hash_size = tb_align_pow2(bucket_size);
tb_assert_and_check_break(hash_map->hash_size <= TB_HASH_MAP_BUCKET_MAXN);
// init self list
hash_map->hash_list = (tb_hash_map_item_list_t**)tb_nalloc0(hash_map->hash_size, sizeof(tb_size_t));
tb_assert_and_check_break(hash_map->hash_list);
// init item grow
hash_map->item_grow = tb_isqrti((tb_uint32_t)bucket_size);
if (hash_map->item_grow < 8) hash_map->item_grow = 8;
hash_map->item_grow = tb_align_pow2(hash_map->item_grow);
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (hash_map) tb_hash_map_exit((tb_hash_map_ref_t)hash_map);
hash_map = tb_null;
}
// ok?
return (tb_hash_map_ref_t)hash_map;
}
tb_void_t tb_hash_map_exit(tb_hash_map_ref_t self)
{
// check
tb_hash_map_t* hash_map = (tb_hash_map_t*)self;
tb_assert_and_check_return(hash_map);
// clear it
tb_hash_map_clear(self);
// free hash_map list
if (hash_map->hash_list) tb_free(hash_map->hash_list);
// free it
tb_free(hash_map);
}
tb_void_t tb_hash_map_clear(tb_hash_map_ref_t self)
{
// check
tb_hash_map_t* hash_map = (tb_hash_map_t*)self;
tb_assert_and_check_return(hash_map && hash_map->hash_list);
// step
tb_size_t step = hash_map->element_name.size + hash_map->element_data.size;
tb_assert_and_check_return(step);
// clear hash_map
tb_size_t i = 0;
tb_size_t n = hash_map->hash_size;
for (i = 0; i < n; i++)
{
tb_hash_map_item_list_t* list = hash_map->hash_list[i];
if (list)
{
// free items
if (hash_map->element_name.free || hash_map->element_data.free)
{
tb_size_t j = 0;
tb_size_t m = list->size;
for (j = 0; j < m; j++)
{
tb_byte_t* item = ((tb_byte_t*)&list[1]) + j * step;
if (hash_map->element_name.free) hash_map->element_name.free(&hash_map->element_name, item);
if (hash_map->element_data.free) hash_map->element_data.free(&hash_map->element_data, item + hash_map->element_name.size);
}
}
// free list
tb_free(list);
}
hash_map->hash_list[i] = tb_null;
}
// reset info
hash_map->item_size = 0;
hash_map->item_maxn = 0;
tb_memset(&hash_map->item, 0, sizeof(tb_hash_map_item_t));
}
tb_pointer_t tb_hash_map_get(tb_hash_map_ref_t self, tb_cpointer_t name)
{
// check
tb_hash_map_t* hash_map = (tb_hash_map_t*)self;
tb_assert_and_check_return_val(hash_map, tb_null);
// find it
tb_size_t buck = 0;
tb_size_t item = 0;
if (!tb_hash_map_item_find(hash_map, name, &buck, &item)) return tb_null;
// get data
tb_pointer_t data = tb_null;
return tb_hash_map_item_at(hash_map, buck, item, tb_null, &data)? data : tb_null;
}
tb_size_t tb_hash_map_find(tb_hash_map_ref_t self, tb_cpointer_t name)
{
// check
tb_hash_map_t* hash_map = (tb_hash_map_t*)self;
tb_assert_and_check_return_val(hash_map, 0);
// find
tb_size_t buck = 0;
tb_size_t item = 0;
return tb_hash_map_item_find(hash_map, name, &buck, &item)? tb_hash_map_index_make(buck + 1, item + 1) : 0;
}
tb_size_t tb_hash_map_insert(tb_hash_map_ref_t self, tb_cpointer_t name, tb_cpointer_t data)
{
// check
tb_hash_map_t* hash_map = (tb_hash_map_t*)self;
tb_assert_and_check_return_val(hash_map, 0);
// the step
tb_size_t step = hash_map->element_name.size + hash_map->element_data.size;
tb_assert_and_check_return_val(step, 0);
// find it
tb_size_t buck = 0;
tb_size_t item = 0;
if (tb_hash_map_item_find(hash_map, name, &buck, &item))
{
// check
tb_assert_and_check_return_val(buck < hash_map->hash_size, 0);
// get list
tb_hash_map_item_list_t* list = hash_map->hash_list[buck];
tb_assert_and_check_return_val(list && list->size && item < list->size, 0);
// replace data
hash_map->element_data.repl(&hash_map->element_data, ((tb_byte_t*)&list[1]) + item * step + hash_map->element_name.size, data);
}
else
{
// check
tb_assert_and_check_return_val(buck < hash_map->hash_size, 0);
// get list
tb_hash_map_item_list_t* list = hash_map->hash_list[buck];
// insert item
if (list)
{
// grow?
if (list->size >= list->maxn)
{
// check
tb_assert_and_check_return_val(hash_map->item_grow, 0);
// resize maxn
tb_size_t maxn = tb_align_pow2(list->maxn + hash_map->item_grow);
tb_assert_and_check_return_val(maxn > list->maxn, 0);
// realloc it
list = (tb_hash_map_item_list_t*)tb_ralloc(list, sizeof(tb_hash_map_item_list_t) + maxn * step);
tb_assert_and_check_return_val(list, 0);
// update the hash_map item maxn
hash_map->item_maxn += maxn - list->maxn;
// update maxn
list->maxn = maxn;
// reattach list
hash_map->hash_list[buck] = list;
}
tb_assert_and_check_return_val(item <= list->size && list->size < list->maxn, 0);
// move items
if (item != list->size) tb_memmov(((tb_byte_t*)&list[1]) + (item + 1) * step, ((tb_byte_t*)&list[1]) + item * step, (list->size - item) * step);
// dupl item
list->size++;
hash_map->element_name.dupl(&hash_map->element_name, ((tb_byte_t*)&list[1]) + item * step, name);
hash_map->element_data.dupl(&hash_map->element_data, ((tb_byte_t*)&list[1]) + item * step + hash_map->element_name.size, data);
}
// create list for adding item
else
{
// check
tb_assert_and_check_return_val(hash_map->item_grow, 0);
// make list
list = (tb_hash_map_item_list_t*)tb_malloc0(sizeof(tb_hash_map_item_list_t) + hash_map->item_grow * step);
tb_assert_and_check_return_val(list, 0);
// init list
list->size = 1;
list->maxn = hash_map->item_grow;
hash_map->element_name.dupl(&hash_map->element_name, ((tb_byte_t*)&list[1]), name);
hash_map->element_data.dupl(&hash_map->element_data, ((tb_byte_t*)&list[1]) + hash_map->element_name.size, data);
// attach list
hash_map->hash_list[buck] = list;
// update the hash_map item maxn
hash_map->item_maxn += list->maxn;
}
// update the hash_map item size
hash_map->item_size++;
}
// ok?
return tb_hash_map_index_make(buck + 1, item + 1);
}
tb_void_t tb_hash_map_remove(tb_hash_map_ref_t self, tb_cpointer_t name)
{
// check
tb_hash_map_t* hash_map = (tb_hash_map_t*)self;
tb_assert_and_check_return(hash_map);
// find it
tb_size_t buck = 0;
tb_size_t item = 0;
if (tb_hash_map_item_find(hash_map, name, &buck, &item))
tb_hash_map_itor_remove((tb_iterator_ref_t)hash_map, tb_hash_map_index_make(buck + 1, item + 1));
}
tb_size_t tb_hash_map_size(tb_hash_map_ref_t self)
{
// check
tb_hash_map_t const* hash_map = (tb_hash_map_t const*)self;
tb_assert_and_check_return_val(hash_map, 0);
// the size
return hash_map->item_size;
}
tb_size_t tb_hash_map_maxn(tb_hash_map_ref_t self)
{
// check
tb_hash_map_t const* hash_map = (tb_hash_map_t const*)self;
tb_assert_and_check_return_val(hash_map, 0);
// the maxn
return hash_map->item_maxn;
}
#ifdef __tb_debug__
tb_void_t tb_hash_map_dump(tb_hash_map_ref_t self)
{
// check
tb_hash_map_t* hash_map = (tb_hash_map_t*)self;
tb_assert_and_check_return(hash_map && hash_map->hash_list);
// the step
tb_size_t step = hash_map->element_name.size + hash_map->element_data.size;
tb_assert_and_check_return(step);
// trace
tb_trace_i("");
tb_trace_i("self: size: %lu", tb_hash_map_size(self));
// done
tb_size_t i = 0;
tb_char_t name[4096];
tb_char_t data[4096];
for (i = 0; i < hash_map->hash_size; i++)
{
// the list
tb_hash_map_item_list_t* list = hash_map->hash_list[i];
if (list)
{
// trace
tb_trace_i("buck[%u]: size: %u, maxn: %u", i, list->size, list->maxn);
// done
tb_size_t j = 0;
for (j = 0; j < list->size; j++)
{
// the item
tb_byte_t const* item = ((tb_byte_t*)&list[1]) + j * step;
// the item name
tb_pointer_t element_name = hash_map->element_name.data(&hash_map->element_name, item);
// the item data
tb_pointer_t element_data = hash_map->element_data.data(&hash_map->element_data, item + hash_map->element_name.size);
// trace
if (hash_map->element_name.cstr && hash_map->element_data.cstr)
{
tb_trace_i(" %s => %s", hash_map->element_name.cstr(&hash_map->element_name, element_name, name, sizeof(name)), hash_map->element_data.cstr(&hash_map->element_data, element_data, data, sizeof(data)));
}
else if (hash_map->element_name.cstr)
{
tb_trace_i(" %s => %p", hash_map->element_name.cstr(&hash_map->element_name, element_name, name, sizeof(name)), element_data);
}
else if (hash_map->element_data.cstr)
{
tb_trace_i(" %x => %p", element_name, hash_map->element_data.cstr(&hash_map->element_data, element_data, data, sizeof(data)));
}
else
{
tb_trace_i(" %p => %p", element_name, element_data);
}
}
}
}
}
#endif
tbox-1.7.6/src/tbox/container/hash_map.h 0000664 0000000 0000000 00000013512 14671175054 0020173 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file hash_map.h
* @ingroup container
*
*/
#ifndef TB_CONTAINER_HASH_MAP_H
#define TB_CONTAINER_HASH_MAP_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "element.h"
#include "iterator.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/// the micro hash bucket size
#define TB_HASH_MAP_BUCKET_SIZE_MICRO (64)
/// the small hash bucket size
#define TB_HASH_MAP_BUCKET_SIZE_SMALL (256)
/// the large hash bucket size
#define TB_HASH_MAP_BUCKET_SIZE_LARGE (65536)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the hash map item type
typedef struct __tb_hash_map_item_t
{
/// the item name
tb_pointer_t name;
/// the item data
tb_pointer_t data;
}tb_hash_map_item_t, *tb_hash_map_item_ref_t;
/*! the hash map ref type
*
*
* 0 1 3 ... ... n n + 1
* hash_list: |--------|--------|--------|--------|--------|--------|--------|--------|
* |
* -----
* item_list: | | key:0
* -----
* | | key:1
* ----- <= insert by binary search algorithm
* | | key:2
* -----
* | | key:3
* -----
* | | key:4
* -----
* | |
* -----
* | |
* -----
* | |
* -----
*
*
*
* @note the itor of the same item is mutable
*/
typedef tb_iterator_ref_t tb_hash_map_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init hash map
*
* @param bucket_size the hash bucket size, using the default size if be zero
* @param element_name the item for name
* @param element_data the item for data
*
* @return the hash map
*/
tb_hash_map_ref_t tb_hash_map_init(tb_size_t bucket_size, tb_element_t element_name, tb_element_t element_data);
/*! exit hash map
*
* @param hash_map the hash map
*/
tb_void_t tb_hash_map_exit(tb_hash_map_ref_t hash_map);
/*! clear hash map
*
* @param hash_map the hash map
*/
tb_void_t tb_hash_map_clear(tb_hash_map_ref_t hash_map);
/*! get item data from name
*
* @note
* the return value may be zero if the item type is integer
* so we need call tb_hash_map_find for judging whether to get value successfully
*
* @code
*
* // find item and get item data
* tb_xxxx_ref_t data = (tb_xxxx_ref_t)tb_hash_map_get(hash_map, name);
* if (data)
* {
* // ...
* }
* @endcode
*
* @param hash_map the hash map
* @param name the item name
*
* @return the item data
*/
tb_pointer_t tb_hash_map_get(tb_hash_map_ref_t hash_map, tb_cpointer_t name);
/*! find item from name
*
* @code
*
* // find item
* tb_size_t itor = tb_hash_map_find(hash_map, name);
* if (itor != tb_iterator_tail(hash_map))
* {
* // get data
* tb_xxxx_ref_t data = (tb_xxxx_ref_t)tb_iterator_item(hash_map, itor);
* tb_assert(data);
*
* // remove it
* tb_iterator_remove(hash_map, itor);
* }
* @endcode
*
* @param hash_map the hash map
* @param name the item name
*
* @return the item itor, @note: the itor of the same item is mutable
*/
tb_size_t tb_hash_map_find(tb_hash_map_ref_t hash_map, tb_cpointer_t name);
/*! insert item data from name
*
* @note the pair (name => data) is unique
*
* @param hash_map the hash map
* @param name the item name
* @param data the item data
*
* @return the item itor, @note: the itor of the same item is mutable
*/
tb_size_t tb_hash_map_insert(tb_hash_map_ref_t hash_map, tb_cpointer_t name, tb_cpointer_t data);
/*! remove item from name
*
* @param hash_map the hash map
* @param name the item name
*/
tb_void_t tb_hash_map_remove(tb_hash_map_ref_t hash_map, tb_cpointer_t name);
/*! the hash map size
*
* @param hash_map the hash map
*
* @return the hash map size
*/
tb_size_t tb_hash_map_size(tb_hash_map_ref_t hash_map);
/*! the hash map maxn
*
* @param hash_map the hash map
*
* @return the hash map maxn
*/
tb_size_t tb_hash_map_maxn(tb_hash_map_ref_t hash_map);
#ifdef __tb_debug__
/*! dump hash
*
* @param hash_map the hash map
*/
tb_void_t tb_hash_map_dump(tb_hash_map_ref_t hash_map);
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/container/hash_set.c 0000664 0000000 0000000 00000007356 14671175054 0020215 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file hash_set.c
* @ingroup container
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "hash_set"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "hash_set.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the hash map itor item func type
typedef tb_pointer_t (*gb_hash_map_item_func_t)(tb_iterator_ref_t, tb_size_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_pointer_t tb_hash_set_itor_item(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_assert(iterator && iterator->priv);
// the item func for the hash map
gb_hash_map_item_func_t func = (gb_hash_map_item_func_t)iterator->priv;
// get the item of the hash map
tb_hash_map_item_ref_t item = (tb_hash_map_item_ref_t)func(iterator, itor);
// get the item of the hash set
return item? item->name : tb_null;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_hash_set_ref_t tb_hash_set_init(tb_size_t bucket_size, tb_element_t element)
{
// init hash set
tb_iterator_ref_t hash_set = (tb_iterator_ref_t)tb_hash_map_init(bucket_size, element, tb_element_true());
tb_assert_and_check_return_val(hash_set, tb_null);
// @note the private data of the hash map iterator cannot be used
tb_assert(!hash_set->priv);
// init operation
static tb_iterator_op_t op = {0};
if (op.item != tb_hash_set_itor_item)
{
op = *hash_set->op;
op.item = tb_hash_set_itor_item;
}
// hacking hash_map and hook the item
hash_set->priv = (tb_pointer_t)hash_set->op->item;
hash_set->op = &op;
// ok?
return (tb_hash_set_ref_t)hash_set;
}
tb_void_t tb_hash_set_exit(tb_hash_set_ref_t self)
{
tb_hash_map_exit((tb_hash_map_ref_t)self);
}
tb_void_t tb_hash_set_clear(tb_hash_set_ref_t self)
{
tb_hash_map_clear((tb_hash_map_ref_t)self);
}
tb_bool_t tb_hash_set_get(tb_hash_set_ref_t self, tb_cpointer_t data)
{
return tb_p2b(tb_hash_map_get((tb_hash_map_ref_t)self, data));
}
tb_size_t tb_hash_set_find(tb_hash_set_ref_t self, tb_cpointer_t data)
{
return tb_hash_map_find((tb_hash_map_ref_t)self, data);
}
tb_size_t tb_hash_set_insert(tb_hash_set_ref_t self, tb_cpointer_t data)
{
return tb_hash_map_insert((tb_hash_map_ref_t)self, data, tb_b2p(tb_true));
}
tb_void_t tb_hash_set_remove(tb_hash_set_ref_t self, tb_cpointer_t data)
{
tb_hash_map_remove((tb_hash_map_ref_t)self, data);
}
tb_size_t tb_hash_set_size(tb_hash_set_ref_t self)
{
return tb_hash_map_size((tb_hash_map_ref_t)self);
}
tb_size_t tb_hash_set_maxn(tb_hash_set_ref_t self)
{
return tb_hash_map_maxn((tb_hash_map_ref_t)self);
}
#ifdef __tb_debug__
tb_void_t tb_hash_set_dump(tb_hash_set_ref_t self)
{
tb_hash_map_dump((tb_hash_map_ref_t)self);
}
#endif
tbox-1.7.6/src/tbox/container/hash_set.h 0000664 0000000 0000000 00000010350 14671175054 0020206 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file hash_set.h
* @ingroup container
*
*/
#ifndef TB_CONTAINER_HASH_SET_H
#define TB_CONTAINER_HASH_SET_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "hash_map.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/// the micro hash bucket size
#define TB_HASH_SET_BUCKET_SIZE_MICRO TB_HASH_MAP_BUCKET_SIZE_MICRO
/// the small hash bucket size
#define TB_HASH_SET_BUCKET_SIZE_SMALL TB_HASH_MAP_BUCKET_SIZE_SMALL
/// the large hash bucket size
#define TB_HASH_SET_BUCKET_SIZE_LARGE TB_HASH_MAP_BUCKET_SIZE_LARGE
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/*! the hash set ref type
*
* @note the itor of the same item is mutable
*/
typedef tb_iterator_ref_t tb_hash_set_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init hash set
*
* @param bucket_size the hash bucket size, using the default size if be zero
* @param element the element
*
* @return the hash set
*/
tb_hash_set_ref_t tb_hash_set_init(tb_size_t bucket_size, tb_element_t element);
/*! exit hash set
*
* @param hash_set the hash set
*/
tb_void_t tb_hash_set_exit(tb_hash_set_ref_t hash_set);
/*! clear hash set
*
* @param hash_set the hash set
*/
tb_void_t tb_hash_set_clear(tb_hash_set_ref_t hash_set);
/*! get item?
*
* @code
* if (tb_hash_set_get(hash_set, name))
* {
* }
* @endcode
*
* @param hash_set the hash set
* @param data the item data
*
* @return tb_true or tb_false
*/
tb_bool_t tb_hash_set_get(tb_hash_set_ref_t hash_set, tb_cpointer_t data);
/*! find item
*
* @code
*
* // find item
* tb_size_t itor = tb_hash_set_find(hash_set, data);
* if (itor != tb_iterator_tail(hash_set))
* {
* // remove it
* tb_iterator_remove(hash_set, itor);
* }
* @endcode
*
* @param hash_set the hash set
* @param data the item data
*
* @return the item itor, @note: the itor of the same item is mutable
*/
tb_size_t tb_hash_set_find(tb_hash_set_ref_t hash_set, tb_cpointer_t data);
/*! insert item
*
* @note each item is unique
*
* @param hash_set the hash set
* @param data the item data
*
* @return the item itor, @note: the itor of the same item is mutable
*/
tb_size_t tb_hash_set_insert(tb_hash_set_ref_t hash_set, tb_cpointer_t data);
/*! remove item
*
* @param hash_set the hash set
* @param data the item data
*/
tb_void_t tb_hash_set_remove(tb_hash_set_ref_t hash_set, tb_cpointer_t data);
/*! the hash set size
*
* @param hash_set the hash set
*
* @return the hash set size
*/
tb_size_t tb_hash_set_size(tb_hash_set_ref_t hash_set);
/*! the hash set maxn
*
* @param hash_set the hash set
*
* @return the hash set maxn
*/
tb_size_t tb_hash_set_maxn(tb_hash_set_ref_t hash_set);
#ifdef __tb_debug__
/*! dump hash
*
* @param hash_set the hash set
*/
tb_void_t tb_hash_set_dump(tb_hash_set_ref_t hash_set);
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/container/heap.c 0000664 0000000 0000000 00000050573 14671175054 0017333 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file heap.c
* @ingroup container
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "heap"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "heap.h"
#include "../libc/libc.h"
#include "../math/math.h"
#include "../utils/utils.h"
#include "../memory/memory.h"
#include "../stream/stream.h"
#include "../platform/platform.h"
#include "../algorithm/algorithm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the self grow
#ifdef __tb_small__
# define TB_HEAP_GROW (128)
#else
# define TB_HEAP_GROW (256)
#endif
// the self maxn
#ifdef __tb_small__
# define TB_HEAP_MAXN (1 << 16)
#else
# define TB_HEAP_MAXN (1 << 30)
#endif
// enable check
#ifdef __tb_debug__
# define TB_HEAP_CHECK_ENABLE (0)
#else
# define TB_HEAP_CHECK_ENABLE (0)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the self type
typedef struct __tb_heap_t
{
// the itor
tb_iterator_t itor;
// the data
tb_byte_t* data;
// the size
tb_size_t size;
// the maxn
tb_size_t maxn;
// the grow
tb_size_t grow;
// the element
tb_element_t element;
}tb_heap_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
#if TB_HEAP_CHECK_ENABLE
static tb_void_t tb_heap_check(tb_heap_t* heap)
{
// init
tb_byte_t* data = heap->data;
tb_size_t tail = heap->size;
tb_size_t step = heap->element.size;
tb_size_t parent = 0;
// done
for (; parent < tail; parent++)
{
// the left child node
tb_size_t lchild = (parent << 1) + 1;
tb_check_break(lchild < tail);
// the parent data
tb_pointer_t parent_data = heap->element.data(&heap->element, data + parent * step);
// check?
if (heap->element.comp(&heap->element, heap->element.data(&heap->element, data + lchild * step), parent_data) < 0)
{
// dump self
tb_heap_dump((tb_heap_ref_t)heap);
// abort
tb_assertf(0, "lchild[%lu]: invalid, parent: %lu, tail: %lu", lchild, parent, tail);
}
// the right child node
tb_size_t rchild = lchild + 1;
tb_check_break(rchild < tail);
// check?
if (heap->element.comp(&heap->element, heap->element.data(&heap->element, data + rchild * step), parent_data) < 0)
{
// dump self
tb_heap_dump((tb_heap_ref_t)heap);
// abort
tb_assertf(0, "rchild[%lu]: invalid, parent: %lu, tail: %lu", rchild, parent, tail);
}
}
}
#endif
/*! shift up the self
*
*
*
* before:
*
* 1(head)
* -------------------------
* | |
* 4 2
* -------------- -------------
* | | | |
* 6(parent) 9 7 8
* ---------
* | |
* 10 5(hole) <------ data
* after:
*
* 1(head)
* -------------------------
* | |
* 4 2
* -------------- -------------
* | | | |
* data -------> 5(hole) 9 7 8
* ---------
* | |
* 10 6
*
*/
static tb_pointer_t tb_heap_shift_up(tb_heap_t* heap, tb_size_t hole, tb_cpointer_t data)
{
// check
tb_assert_and_check_return_val(heap && heap->data, tb_null);
// the element function
tb_element_comp_func_t func_comp = heap->element.comp;
tb_element_data_func_t func_data = heap->element.data;
tb_assert(func_comp && func_data);
// (hole - 1) / 2: the parent node of the hole
tb_size_t parent = 0;
tb_byte_t* head = heap->data;
tb_size_t step = heap->element.size;
switch (step)
{
case sizeof(tb_size_t):
{
for (parent = (hole - 1) >> 1; hole && (func_comp(&heap->element, func_data(&heap->element, head + parent * step), data) > 0); parent = (hole - 1) >> 1)
{
// move item: parent => hole
*((tb_size_t*)(head + hole * step)) = *((tb_size_t*)(head + parent * step));
// move node: hole => parent
hole = parent;
}
}
break;
default:
for (parent = (hole - 1) >> 1; hole && (func_comp(&heap->element, func_data(&heap->element, head + parent * step), data) > 0); parent = (hole - 1) >> 1)
{
// move item: parent => hole
tb_memcpy(head + hole * step, head + parent * step, step);
// move node: hole => parent
hole = parent;
}
break;
}
// ok?
return head + hole * step;
}
/*! shift down the self
*
*
*
* before:
* 1(head)
* -------------------------
* | |
* (hole) 2
* -------------- -------------
* | | | |
* lchild --> 6(smaller) 7 7 8
* --------- ------
* | | |
* 11 16 10
*
*
* move hole:
* 1(head)
* -------------------------
* | |
* 6 2
* -------------- -------------
* | | | |
* (hole) 7 7 8
* --------- -----
* | | |
* lchild --> 11(smaller)16 10
*
* 11 >= data: 9? break it
*
* move data to hole:
* 1(head)
* -------------------------
* | |
* 6 2
* -------------- -------------
* | | | |
* data ------------> 9 7 7 8
* --------- ---
* | | |
* 11 16 10
*
*
*/
static tb_pointer_t tb_heap_shift_down(tb_heap_t* heap, tb_size_t hole, tb_cpointer_t data)
{
// check
tb_assert_and_check_return_val(heap && heap->data, tb_null);
// init element
tb_element_comp_func_t func_comp = heap->element.comp;
tb_element_data_func_t func_data = heap->element.data;
tb_assert(func_comp && func_data);
// 2 * hole + 1: the left child node of hole
tb_size_t step = heap->element.size;
tb_byte_t* head = heap->data;
tb_byte_t* tail = head + heap->size * step;
tb_byte_t* phole = head + hole * step;
tb_byte_t* lchild = head + ((hole << 1) + 1) * step;
tb_pointer_t data_lchild = tb_null;
tb_pointer_t data_rchild = tb_null;
switch (step)
{
case sizeof(tb_size_t):
{
for (; lchild < tail; lchild = head + (((lchild - head) << 1) + step))
{
// the smaller child node
data_lchild = func_data(&heap->element, lchild);
if (lchild + step < tail && func_comp(&heap->element, data_lchild, (data_rchild = func_data(&heap->element, lchild + step))) > 0)
{
lchild += step;
data_lchild = data_rchild;
}
// end?
if (func_comp(&heap->element, data_lchild, data) >= 0) break;
// the smaller child node => hole
*((tb_size_t*)phole) = *((tb_size_t*)lchild);
// move the hole down to it's smaller child node
phole = lchild;
}
}
break;
default:
{
for (; lchild < tail; lchild = head + (((lchild - head) << 1) + step))
{
// the smaller child node
data_lchild = func_data(&heap->element, lchild);
if (lchild + step < tail && func_comp(&heap->element, data_lchild, (data_rchild = func_data(&heap->element, lchild + step))) > 0)
{
lchild += step;
data_lchild = data_rchild;
}
// end?
if (func_comp(&heap->element, data_lchild, data) >= 0) break;
// the smaller child node => hole
tb_memcpy(phole, lchild, step);
// move the hole down to it's smaller child node
phole = lchild;
}
}
break;
}
// ok?
return phole;
}
static tb_size_t tb_heap_itor_size(tb_iterator_ref_t iterator)
{
// check
tb_heap_t* heap = (tb_heap_t*)iterator;
tb_assert_and_check_return_val(heap, 0);
// size
return heap->size;
}
static tb_size_t tb_heap_itor_head(tb_iterator_ref_t iterator)
{
// check
tb_heap_t* heap = (tb_heap_t*)iterator;
tb_assert_and_check_return_val(heap, 0);
// head
return 0;
}
static tb_size_t tb_heap_itor_last(tb_iterator_ref_t iterator)
{
// check
tb_heap_t* heap = (tb_heap_t*)iterator;
tb_assert_and_check_return_val(heap, 0);
// last
return heap->size? heap->size - 1 : 0;
}
static tb_size_t tb_heap_itor_tail(tb_iterator_ref_t iterator)
{
// check
tb_heap_t* heap = (tb_heap_t*)iterator;
tb_assert_and_check_return_val(heap, 0);
// tail
return heap->size;
}
static tb_size_t tb_heap_itor_next(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_heap_t* heap = (tb_heap_t*)iterator;
tb_assert_and_check_return_val(heap, 0);
tb_assert_and_check_return_val(itor < heap->size, heap->size);
// next
return itor + 1;
}
static tb_size_t tb_heap_itor_prev(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_heap_t* heap = (tb_heap_t*)iterator;
tb_assert_and_check_return_val(heap, 0);
tb_assert_and_check_return_val(itor && itor < heap->size, 0);
// prev
return itor - 1;
}
static tb_pointer_t tb_heap_itor_item(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_heap_t* heap = (tb_heap_t*)iterator;
tb_assert_and_check_return_val(heap && itor < heap->size, tb_null);
// data
return heap->element.data(&heap->element, heap->data + itor * iterator->step);
}
static tb_void_t tb_heap_itor_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item)
{
// check
tb_heap_t* heap = (tb_heap_t*)iterator;
tb_assert_and_check_return(heap);
// copy
heap->element.copy(&heap->element, heap->data + itor * iterator->step, item);
}
static tb_long_t tb_heap_itor_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem)
{
// check
tb_heap_t* heap = (tb_heap_t*)iterator;
tb_assert_and_check_return_val(heap && heap->element.comp, 0);
// comp
return heap->element.comp(&heap->element, litem, ritem);
}
static tb_void_t tb_heap_itor_remove(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_heap_t* heap = (tb_heap_t*)iterator;
tb_assert_and_check_return(heap && heap->data && heap->size && itor < heap->size);
// check the element function
tb_assert(heap->element.comp && heap->element.data);
// the step
tb_size_t step = heap->element.size;
tb_assert(step);
// free the item first
if (heap->element.free) heap->element.free(&heap->element, heap->data + itor * step);
// the removed item is not the last item?
if (itor != heap->size - 1)
{
// the last and parent
tb_pointer_t last = heap->data + (heap->size - 1) * step;
tb_pointer_t parent = heap->data + ((itor - 1) >> 1) * step;
// the last and parent data
tb_pointer_t data_last = heap->element.data(&heap->element, last);
tb_pointer_t data_parent = heap->element.data(&heap->element, parent);
/* we might need to shift it upward if it is less than its parent,
* or downward if it is greater than one or both its children.
*
* since the children are known to be less than the parent,
* it can't need to shift both up and down.
*/
tb_pointer_t hole = tb_null;
if (itor && heap->element.comp(&heap->element, data_parent, data_last) > 0)
{
// shift up the self from the given hole
hole = tb_heap_shift_up(heap, itor, data_last);
}
// shift down the self from the given hole
else hole = tb_heap_shift_down(heap, itor, data_last);
tb_assert(hole);
// copy the last data to the hole
if (hole != last) tb_memcpy(hole, last, step);
}
// size--
heap->size--;
// check
#if TB_HEAP_CHECK_ENABLE
tb_heap_check(heap);
#endif
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_heap_ref_t tb_heap_init(tb_size_t grow, tb_element_t element)
{
// check
tb_assert_and_check_return_val(element.size && element.data && element.dupl && element.repl, tb_null);
// done
tb_bool_t ok = tb_false;
tb_heap_t* heap = tb_null;
do
{
// using the default grow
if (!grow) grow = TB_HEAP_GROW;
// make heap
heap = tb_malloc0_type(tb_heap_t);
tb_assert_and_check_break(heap);
// init heap
heap->size = 0;
heap->grow = grow;
heap->maxn = grow;
heap->element = element;
tb_assert_and_check_break(heap->maxn < TB_HEAP_MAXN);
// init operation
static tb_iterator_op_t op =
{
tb_heap_itor_size
, tb_heap_itor_head
, tb_heap_itor_last
, tb_heap_itor_tail
, tb_heap_itor_prev
, tb_heap_itor_next
, tb_heap_itor_item
, tb_heap_itor_comp
, tb_heap_itor_copy
, tb_heap_itor_remove
, tb_null
};
// init iterator
heap->itor.priv = tb_null;
heap->itor.step = element.size;
heap->itor.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE | TB_ITERATOR_MODE_RACCESS | TB_ITERATOR_MODE_MUTABLE;
heap->itor.op = &op;
if (element.type == TB_ELEMENT_TYPE_MEM)
heap->itor.flag = TB_ITERATOR_FLAG_ITEM_REF;
// make data
heap->data = (tb_byte_t*)tb_nalloc0(heap->maxn, element.size);
tb_assert_and_check_break(heap->data);
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (heap) tb_heap_exit((tb_heap_ref_t)heap);
heap = tb_null;
}
// ok?
return (tb_heap_ref_t)heap;
}
tb_void_t tb_heap_exit(tb_heap_ref_t self)
{
// check
tb_heap_t* heap = (tb_heap_t*)self;
tb_assert_and_check_return(heap);
// clear data
tb_heap_clear(self);
// free data
if (heap->data) tb_free(heap->data);
heap->data = tb_null;
// free it
tb_free(heap);
}
tb_void_t tb_heap_clear(tb_heap_ref_t self)
{
// check
tb_heap_t* heap = (tb_heap_t*)self;
tb_assert_and_check_return(heap);
// free data
if (heap->element.nfree)
heap->element.nfree(&heap->element, heap->data, heap->size);
// reset size
heap->size = 0;
}
tb_size_t tb_heap_size(tb_heap_ref_t self)
{
// check
tb_heap_t const* heap = (tb_heap_t const*)self;
tb_assert_and_check_return_val(heap, 0);
// size
return heap->size;
}
tb_size_t tb_heap_maxn(tb_heap_ref_t self)
{
// check
tb_heap_t const* heap = (tb_heap_t const*)self;
tb_assert_and_check_return_val(heap, 0);
// maxn
return heap->maxn;
}
tb_pointer_t tb_heap_top(tb_heap_ref_t self)
{
return tb_iterator_item(self, tb_iterator_head(self));
}
tb_void_t tb_heap_put(tb_heap_ref_t self, tb_cpointer_t data)
{
// check
tb_heap_t* heap = (tb_heap_t*)self;
tb_assert_and_check_return(heap && heap->element.dupl && heap->data);
// no enough? grow it
if (heap->size == heap->maxn)
{
// the maxn
tb_size_t maxn = tb_align4(heap->maxn + heap->grow);
tb_assert_and_check_return(maxn < TB_HEAP_MAXN);
// realloc data
heap->data = (tb_byte_t*)tb_ralloc(heap->data, maxn * heap->element.size);
tb_assert_and_check_return(heap->data);
// must be align by 4-bytes
tb_assert_and_check_return(!(((tb_size_t)(heap->data)) & 3));
// clear the grow data
tb_memset(heap->data + heap->size * heap->element.size, 0, (maxn - heap->maxn) * heap->element.size);
// save maxn
heap->maxn = maxn;
}
// check
tb_assert_and_check_return(heap->size < heap->maxn);
// shift up the self from the tail hole
tb_pointer_t hole = tb_heap_shift_up(heap, heap->size, data);
tb_assert(hole);
// save data to the hole
if (hole) heap->element.dupl(&heap->element, hole, data);
// update the size
heap->size++;
// check
#if TB_HEAP_CHECK_ENABLE
tb_heap_check(heap);
#endif
}
tb_void_t tb_heap_pop(tb_heap_ref_t self)
{
// check
tb_heap_t* heap = (tb_heap_t*)self;
tb_assert_and_check_return(heap && heap->data && heap->size);
// free the top item first
if (heap->element.free) heap->element.free(&heap->element, heap->data);
// the last item is not in top
if (heap->size > 1)
{
// check the element function
tb_assert(heap->element.data);
// the step
tb_size_t step = heap->element.size;
tb_assert(step);
// the last
tb_pointer_t last = heap->data + (heap->size - 1) * step;
// shift down the self from the top hole
tb_pointer_t hole = tb_heap_shift_down(heap, 0, heap->element.data(&heap->element, last));
tb_assert(hole);
// copy the last data to the hole
if (hole != last) tb_memcpy(hole, last, step);
}
// update the size
heap->size--;
// check
#if TB_HEAP_CHECK_ENABLE
tb_heap_check(heap);
#endif
}
tb_void_t tb_heap_remove(tb_heap_ref_t self, tb_size_t itor)
{
tb_heap_itor_remove(self, itor);
}
#ifdef __tb_debug__
tb_void_t tb_heap_dump(tb_heap_ref_t self)
{
// check
tb_heap_t* heap = (tb_heap_t*)self;
tb_assert_and_check_return(heap);
// trace
tb_trace_i("self: size: %lu", tb_heap_size(self));
// done
tb_char_t cstr[4096];
tb_for_all (tb_pointer_t, data, self)
{
// trace
if (heap->element.cstr)
{
#if TB_HEAP_CHECK_ENABLE
tb_trace_i(" [%lu]: %s", data_itor, heap->element.cstr(&heap->element, data, cstr, sizeof(cstr)));
#else
tb_trace_i(" %s", heap->element.cstr(&heap->element, data, cstr, sizeof(cstr)));
#endif
}
else
{
tb_trace_i(" %p", data);
}
}
}
#endif
tbox-1.7.6/src/tbox/container/heap.h 0000664 0000000 0000000 00000007453 14671175054 0017337 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file heap.h
* @ingroup container
*
*/
#ifndef TB_CONTAINER_HEAP_H
#define TB_CONTAINER_HEAP_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "element.h"
#include "iterator.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/*! the head ref type
*
*
* heap: 1 4 2 6 9 7 8 10 14 16
*
* 1(head)
* -------------------------
* | |
* 4 2
* -------------- -------------
* | | | |
* 6 (last / 2 - 1)9 7 8
* --------- ----
* | | |
* 10 14 16(last - 1)
*
* performance:
*
* put: O(lgn)
* pop: O(1)
* top: O(1)
* del: O(lgn) + find: O(n)
*
* iterator:
*
* next: fast
* prev: fast
*
*
*
* @note the itor of the same item is mutable
*/
typedef tb_iterator_ref_t tb_heap_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init heap, default: minheap
*
* @param grow the item grow, using the default grow if be zero
* @param element the element
*
* @return the heap
*/
tb_heap_ref_t tb_heap_init(tb_size_t grow, tb_element_t element);
/*! exit heap
*
* @param heap the heap
*/
tb_void_t tb_heap_exit(tb_heap_ref_t heap);
/*! clear the heap
*
* @param heap the heap
*/
tb_void_t tb_heap_clear(tb_heap_ref_t heap);
/*! the heap size
*
* @param heap the heap
*
* @return the heap size
*/
tb_size_t tb_heap_size(tb_heap_ref_t heap);
/*! the heap maxn
*
* @param heap the heap
*
* @return the heap maxn
*/
tb_size_t tb_heap_maxn(tb_heap_ref_t heap);
/*! the heap top item
*
* @param heap the heap
*
* @return the heap top item
*/
tb_pointer_t tb_heap_top(tb_heap_ref_t heap);
/*! put the heap item
*
* @param heap the heap
* @param data the item data
*/
tb_void_t tb_heap_put(tb_heap_ref_t heap, tb_cpointer_t data);
/*! pop the heap item
*
* @param heap the heap
*/
tb_void_t tb_heap_pop(tb_heap_ref_t heap);
/*! remove the heap item using iterator only for algorithm(find, ...)
*
* @param heap the heap
* @param itor the itor
*/
tb_void_t tb_heap_remove(tb_heap_ref_t heap, tb_size_t itor);
#ifdef __tb_debug__
/*! dump heap
*
* @param heap the heap
*/
tb_void_t tb_heap_dump(tb_heap_ref_t heap);
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/container/iterator.c 0000664 0000000 0000000 00000006552 14671175054 0020245 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX op->n Source Group.
*
* @author ruki
* @file iterator.c
* @ingroup container
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "iterator.h"
#include "../libc/libc.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_iterator_mode(tb_iterator_ref_t iterator)
{
tb_assert(iterator);
return (tb_size_t)iterator->mode;
}
tb_size_t tb_iterator_flag(tb_iterator_ref_t iterator)
{
tb_assert(iterator);
return (tb_size_t)iterator->flag;
}
tb_size_t tb_iterator_step(tb_iterator_ref_t iterator)
{
tb_assert(iterator);
return (tb_size_t)iterator->step;
}
tb_size_t tb_iterator_size(tb_iterator_ref_t iterator)
{
tb_assert(iterator && iterator->op && iterator->op->size);
return iterator->op->size(iterator);
}
tb_size_t tb_iterator_head(tb_iterator_ref_t iterator)
{
tb_assert(iterator && iterator->op && iterator->op->head);
return iterator->op->head(iterator);
}
tb_size_t tb_iterator_last(tb_iterator_ref_t iterator)
{
tb_assert(iterator && iterator->op && iterator->op->last);
return iterator->op->last(iterator);
}
tb_size_t tb_iterator_tail(tb_iterator_ref_t iterator)
{
tb_assert(iterator && iterator->op && iterator->op->tail);
return iterator->op->tail(iterator);
}
tb_size_t tb_iterator_prev(tb_iterator_ref_t iterator, tb_size_t itor)
{
tb_assert(iterator && iterator->op && iterator->op->prev);
return iterator->op->prev(iterator, itor);
}
tb_size_t tb_iterator_next(tb_iterator_ref_t iterator, tb_size_t itor)
{
tb_assert(iterator && iterator->op && iterator->op->next);
return iterator->op->next(iterator, itor);
}
tb_pointer_t tb_iterator_item(tb_iterator_ref_t iterator, tb_size_t itor)
{
tb_assert(iterator && iterator->op && iterator->op->item);
return iterator->op->item(iterator, itor);
}
tb_void_t tb_iterator_remove(tb_iterator_ref_t iterator, tb_size_t itor)
{
tb_assert(iterator && iterator->op && iterator->op->remove);
return iterator->op->remove(iterator, itor);
}
tb_void_t tb_iterator_nremove(tb_iterator_ref_t iterator, tb_size_t prev, tb_size_t next, tb_size_t size)
{
tb_assert(iterator && iterator->op && iterator->op->nremove);
return iterator->op->nremove(iterator, prev, next, size);
}
tb_void_t tb_iterator_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item)
{
tb_assert(iterator && iterator->op && iterator->op->copy);
return iterator->op->copy(iterator, itor, item);
}
tb_long_t tb_iterator_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem)
{
tb_assert(iterator && iterator->op && iterator->op->comp);
return iterator->op->comp(iterator, litem, ritem);
}
tbox-1.7.6/src/tbox/container/iterator.h 0000664 0000000 0000000 00000015663 14671175054 0020255 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file iterator.h
* @ingroup container
*
*/
#ifndef TB_CONTAINER_ITERATOR_H
#define TB_CONTAINER_ITERATOR_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the iterator mode enum
typedef enum __tb_iterator_mode_e
{
TB_ITERATOR_MODE_FORWARD = 1 //!< forward iterator
, TB_ITERATOR_MODE_REVERSE = 2 //!< reverse iterator
, TB_ITERATOR_MODE_RACCESS = 4 //!< random access iterator
, TB_ITERATOR_MODE_MUTABLE = 8 //!< mutable iterator, the item of the same iterator is mutable for removing and moving, .e.g vector, hash, ...
, TB_ITERATOR_MODE_READONLY = 16 //!< readonly iterator
}tb_iterator_mode_e;
/// the iterator flag enum
typedef enum __tb_iterator_flag_e
{
TB_ITERATOR_FLAG_ITEM_VAL = 1 //!< the value item: int, pointer, c-string
, TB_ITERATOR_FLAG_ITEM_REF = 2 //!< the reference of value, &value
}tb_iterator_flag_e;
/// the iterator operation type
struct __tb_iterator_t;
typedef struct __tb_iterator_op_t
{
/// the iterator size
tb_size_t (*size)(struct __tb_iterator_t* iterator);
/// the iterator head
tb_size_t (*head)(struct __tb_iterator_t* iterator);
/// the iterator last
tb_size_t (*last)(struct __tb_iterator_t* iterator);
/// the iterator tail
tb_size_t (*tail)(struct __tb_iterator_t* iterator);
/// the iterator prev
tb_size_t (*prev)(struct __tb_iterator_t* iterator, tb_size_t itor);
/// the iterator next
tb_size_t (*next)(struct __tb_iterator_t* iterator, tb_size_t itor);
/// the iterator item
tb_pointer_t (*item)(struct __tb_iterator_t* iterator, tb_size_t itor);
/// the iterator comp
tb_long_t (*comp)(struct __tb_iterator_t* iterator, tb_cpointer_t litem, tb_cpointer_t ritem);
/// the iterator copy
tb_void_t (*copy)(struct __tb_iterator_t* iterator, tb_size_t itor, tb_cpointer_t item);
/// the iterator remove
tb_void_t (*remove)(struct __tb_iterator_t* iterator, tb_size_t itor);
/// the iterator nremove
tb_void_t (*nremove)(struct __tb_iterator_t* iterator, tb_size_t prev, tb_size_t next, tb_size_t size);
}tb_iterator_op_t;
/// the iterator operation ref type
typedef tb_iterator_op_t const* tb_iterator_op_ref_t;
/// the iterator type
typedef struct __tb_iterator_t
{
/// the iterator mode
tb_uint32_t mode : 8;
/// the iterator flag
tb_uint32_t flag : 8;
/// the iterator step
tb_uint32_t step : 16;
/// the iterator priv
tb_pointer_t priv;
/// the iterator operation
tb_iterator_op_ref_t op;
}tb_iterator_t, *tb_iterator_ref_t;
/// the iterator comp func type
typedef tb_long_t (*tb_iterator_comp_t)(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the iterator mode
*
* @param iterator the iterator
*
* @return the iterator mode
*/
tb_size_t tb_iterator_mode(tb_iterator_ref_t iterator);
/*! the iterator flag
*
* @param iterator the iterator
*
* @return the iterator flag
*/
tb_size_t tb_iterator_flag(tb_iterator_ref_t iterator);
/*! the iterator step
*
* @param iterator the iterator
*
* @return the iterator step
*/
tb_size_t tb_iterator_step(tb_iterator_ref_t iterator);
/*! the iterator size
*
* @param iterator the iterator
*
* @return the iterator size
*/
tb_size_t tb_iterator_size(tb_iterator_ref_t iterator);
/*! the iterator head
*
* @param iterator the iterator
*
* @return the iterator head
*/
tb_size_t tb_iterator_head(tb_iterator_ref_t iterator);
/*! the iterator last
*
* @param iterator the iterator
*
* @return the iterator last
*/
tb_size_t tb_iterator_last(tb_iterator_ref_t iterator);
/*! the iterator tail
*
* @param iterator the iterator
*
* @return the iterator tail
*/
tb_size_t tb_iterator_tail(tb_iterator_ref_t iterator);
/*! the iterator prev
*
* @param iterator the iterator
* @param itor the item itor
*
* @return the iterator prev
*/
tb_size_t tb_iterator_prev(tb_iterator_ref_t iterator, tb_size_t itor);
/*! the iterator next
*
* @param iterator the iterator
* @param itor the item itor
*
* @return the iterator next
*/
tb_size_t tb_iterator_next(tb_iterator_ref_t iterator, tb_size_t itor);
/*! the iterator item
*
* @param iterator the iterator
* @param itor the item itor
*
* @return the iterator item
*/
tb_pointer_t tb_iterator_item(tb_iterator_ref_t iterator, tb_size_t itor);
/*! remove the iterator item
*
* @param iterator the iterator
* @param itor the item itor
*/
tb_void_t tb_iterator_remove(tb_iterator_ref_t iterator, tb_size_t itor);
/*! remove the iterator items from range(prev, next)
*
* @param iterator the iterator
* @param prev the prev item
* @param next the next item
* @param size the removed size
*/
tb_void_t tb_iterator_nremove(tb_iterator_ref_t iterator, tb_size_t prev, tb_size_t next, tb_size_t size);
/*! copy the iterator item
*
* @param iterator the iterator
* @param itor the item itor
* @param item the copied item
*/
tb_void_t tb_iterator_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item);
/*! compare the iterator item
*
* @param iterator the iterator
* @param litem the item
* @param ritem the compared item
*
* @return =: 0, >: 1, <: -1
*/
tb_long_t tb_iterator_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/container/list.c 0000664 0000000 0000000 00000030724 14671175054 0017365 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file list.c
* @ingroup container
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "list"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "list.h"
#include "list_entry.h"
#include "../libc/libc.h"
#include "../math/math.h"
#include "../memory/memory.h"
#include "../stream/stream.h"
#include "../platform/platform.h"
#include "../algorithm/algorithm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the self grow
#ifdef __tb_small__
# define TB_LIST_GROW (128)
#else
# define TB_LIST_GROW (256)
#endif
// the self maxn
#ifdef __tb_small__
# define TB_LIST_MAXN (1 << 16)
#else
# define TB_LIST_MAXN (1 << 30)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the self type
typedef struct __tb_list_t
{
// the itor
tb_iterator_t itor;
// the pool
tb_fixed_pool_ref_t pool;
// the head
tb_list_entry_head_t head;
// the element
tb_element_t element;
}tb_list_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_size_t tb_list_itor_size(tb_iterator_ref_t iterator)
{
// the size
return tb_list_size((tb_list_ref_t)iterator);
}
static tb_size_t tb_list_itor_head(tb_iterator_ref_t iterator)
{
// check
tb_list_t* list = (tb_list_t*)iterator;
tb_assert(list);
// head
return (tb_size_t)tb_list_entry_head(&list->head);
}
static tb_size_t tb_list_itor_last(tb_iterator_ref_t iterator)
{
// check
tb_list_t* list = (tb_list_t*)iterator;
tb_assert(list);
// last
return (tb_size_t)tb_list_entry_last(&list->head);
}
static tb_size_t tb_list_itor_tail(tb_iterator_ref_t iterator)
{
// check
tb_list_t* list = (tb_list_t*)iterator;
tb_assert(list);
// tail
return (tb_size_t)tb_list_entry_tail(&list->head);
}
static tb_size_t tb_list_itor_next(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_assert(itor);
// next
return (tb_size_t)tb_list_entry_next((tb_list_entry_t*)itor);
}
static tb_size_t tb_list_itor_prev(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_assert(itor);
// prev
return (tb_size_t)tb_list_entry_prev((tb_list_entry_t*)itor);
}
static tb_pointer_t tb_list_itor_item(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_list_t* list = (tb_list_t*)iterator;
tb_assert(list && itor);
// data
return list->element.data(&list->element, (tb_cpointer_t)(((tb_list_entry_t*)itor) + 1));
}
static tb_void_t tb_list_itor_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item)
{
// check
tb_list_t* list = (tb_list_t*)iterator;
tb_assert(list && itor);
// copy
list->element.copy(&list->element, (tb_pointer_t)(((tb_list_entry_t*)itor) + 1), item);
}
static tb_long_t tb_list_itor_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem)
{
// check
tb_list_t* list = (tb_list_t*)iterator;
tb_assert(list && list->element.comp);
// comp
return list->element.comp(&list->element, litem, ritem);
}
static tb_void_t tb_list_itor_remove(tb_iterator_ref_t iterator, tb_size_t itor)
{
// remove it
tb_list_remove((tb_list_ref_t)iterator, itor);
}
static tb_void_t tb_list_itor_nremove(tb_iterator_ref_t iterator, tb_size_t prev, tb_size_t next, tb_size_t size)
{
// no size?
tb_check_return(size);
// the self size
tb_size_t list_size = tb_list_size((tb_list_ref_t)iterator);
tb_check_return(list_size);
// limit size
if (size > list_size) size = list_size;
// remove the body items
if (prev)
{
tb_size_t itor = tb_iterator_next((tb_list_ref_t)iterator, prev);
while (itor != next && size--) itor = tb_list_remove((tb_list_ref_t)iterator, itor);
}
// remove the head items
else
{
while (size--) tb_list_remove_head((tb_list_ref_t)iterator);
}
}
static tb_void_t tb_list_item_exit(tb_pointer_t data, tb_cpointer_t priv)
{
// check
tb_list_t* list = (tb_list_t*)priv;
tb_assert_and_check_return(list);
// free data
if (list->element.free) list->element.free(&list->element, (tb_pointer_t)(((tb_list_entry_t*)data) + 1));
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_list_ref_t tb_list_init(tb_size_t grow, tb_element_t element)
{
// check
tb_assert_and_check_return_val(element.size && element.data && element.dupl && element.repl, tb_null);
// done
tb_bool_t ok = tb_false;
tb_list_t* list = tb_null;
do
{
// using the default grow
if (!grow) grow = TB_LIST_GROW;
// make self
list = tb_malloc0_type(tb_list_t);
tb_assert_and_check_break(list);
// init element
list->element = element;
// init operation
static tb_iterator_op_t op =
{
tb_list_itor_size
, tb_list_itor_head
, tb_list_itor_last
, tb_list_itor_tail
, tb_list_itor_prev
, tb_list_itor_next
, tb_list_itor_item
, tb_list_itor_comp
, tb_list_itor_copy
, tb_list_itor_remove
, tb_list_itor_nremove
};
// init iterator
list->itor.priv = tb_null;
list->itor.step = element.size;
list->itor.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE;
list->itor.op = &op;
if (element.type == TB_ELEMENT_TYPE_MEM)
list->itor.flag = TB_ITERATOR_FLAG_ITEM_REF;
// init pool, item = entry + data
list->pool = tb_fixed_pool_init(tb_null, grow, sizeof(tb_list_entry_t) + element.size, tb_null, tb_list_item_exit, (tb_cpointer_t)list);
tb_assert_and_check_break(list->pool);
// init head
tb_list_entry_init_(&list->head, 0, sizeof(tb_list_entry_t) + element.size, tb_null);
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (list) tb_list_exit((tb_list_ref_t)list);
list = tb_null;
}
// ok?
return (tb_list_ref_t)list;
}
tb_void_t tb_list_exit(tb_list_ref_t self)
{
// check
tb_list_t* list = (tb_list_t*)self;
tb_assert_and_check_return(list);
// clear data
tb_list_clear((tb_list_ref_t)list);
// exit pool
if (list->pool) tb_fixed_pool_exit(list->pool);
// exit it
tb_free(list);
}
tb_void_t tb_list_clear(tb_list_ref_t self)
{
// check
tb_list_t* list = (tb_list_t*)self;
tb_assert_and_check_return(list);
// clear pool
if (list->pool) tb_fixed_pool_clear(list->pool);
// clear head
tb_list_entry_clear(&list->head);
}
tb_pointer_t tb_list_head(tb_list_ref_t self)
{
return tb_iterator_item(self, tb_iterator_head(self));
}
tb_pointer_t tb_list_last(tb_list_ref_t self)
{
return tb_iterator_item(self, tb_iterator_last(self));
}
tb_size_t tb_list_size(tb_list_ref_t self)
{
// check
tb_list_t* list = (tb_list_t*)self;
tb_assert_and_check_return_val(list && list->pool, 0);
tb_assert(tb_list_entry_size(&list->head) == tb_fixed_pool_size(list->pool));
// the size
return tb_list_entry_size(&list->head);
}
tb_size_t tb_list_maxn(tb_list_ref_t self)
{
// the item maxn
return TB_LIST_MAXN;
}
tb_size_t tb_list_insert_prev(tb_list_ref_t self, tb_size_t itor, tb_cpointer_t data)
{
// check
tb_list_t* list = (tb_list_t*)self;
tb_assert_and_check_return_val(list && list->element.dupl && list->pool, 0);
// full?
tb_assert_and_check_return_val(tb_list_size(self) < tb_list_maxn(self), tb_iterator_tail(self));
// the node
tb_list_entry_ref_t node = (tb_list_entry_ref_t)itor;
tb_assert_and_check_return_val(node, tb_iterator_tail(self));
// make entry
tb_list_entry_ref_t entry = (tb_list_entry_ref_t)tb_fixed_pool_malloc(list->pool);
tb_assert_and_check_return_val(entry, tb_iterator_tail(self));
// init entry data
list->element.dupl(&list->element, (tb_pointer_t)(((tb_list_entry_t*)entry) + 1), data);
// insert it
tb_list_entry_insert_prev(&list->head, node, entry);
// ok
return (tb_size_t)entry;
}
tb_size_t tb_list_insert_next(tb_list_ref_t self, tb_size_t itor, tb_cpointer_t data)
{
return tb_list_insert_prev(self, tb_iterator_next(self, itor), data);
}
tb_size_t tb_list_insert_head(tb_list_ref_t self, tb_cpointer_t data)
{
return tb_list_insert_prev(self, tb_iterator_head(self), data);
}
tb_size_t tb_list_insert_tail(tb_list_ref_t self, tb_cpointer_t data)
{
return tb_list_insert_prev(self, tb_iterator_tail(self), data);
}
tb_void_t tb_list_replace(tb_list_ref_t self, tb_size_t itor, tb_cpointer_t data)
{
// check
tb_list_t* list = (tb_list_t*)self;
tb_assert_and_check_return(list && list->element.repl && itor);
// the node
tb_list_entry_ref_t node = (tb_list_entry_ref_t)itor;
tb_assert_and_check_return(node);
// replace data
list->element.repl(&list->element, (tb_pointer_t)(((tb_list_entry_t*)node) + 1), data);
}
tb_void_t tb_list_replace_head(tb_list_ref_t self, tb_cpointer_t data)
{
tb_list_replace(self, tb_iterator_head(self), data);
}
tb_void_t tb_list_replace_last(tb_list_ref_t self, tb_cpointer_t data)
{
tb_list_replace(self, tb_iterator_last(self), data);
}
tb_size_t tb_list_remove(tb_list_ref_t self, tb_size_t itor)
{
// check
tb_list_t* list = (tb_list_t*)self;
tb_assert_and_check_return_val(list && list->pool && itor, 0);
// the node
tb_list_entry_ref_t node = (tb_list_entry_ref_t)itor;
tb_assert_and_check_return_val(node, tb_iterator_tail(self));
// the next node
tb_list_entry_ref_t next = tb_list_entry_next(node);
// remove node
tb_list_entry_remove(&list->head, node);
// free node
tb_fixed_pool_free(list->pool, node);
// the next node
return (tb_size_t)next;
}
tb_void_t tb_list_remove_head(tb_list_ref_t self)
{
tb_list_remove(self, tb_iterator_head(self));
}
tb_void_t tb_list_remove_last(tb_list_ref_t self)
{
tb_list_remove(self, tb_iterator_last(self));
}
tb_void_t tb_list_moveto_prev(tb_list_ref_t self, tb_size_t itor, tb_size_t move)
{
// check
tb_list_t* list = (tb_list_t*)self;
tb_assert_and_check_return(list && list->pool && move);
// the node
tb_list_entry_ref_t node = (tb_list_entry_ref_t)itor;
tb_assert_and_check_return(node);
// the entry
tb_list_entry_ref_t entry = (tb_list_entry_ref_t)move;
tb_assert_and_check_return(entry);
// move to the prev node
tb_list_entry_moveto_prev(&list->head, node, entry);
}
tb_void_t tb_list_moveto_next(tb_list_ref_t self, tb_size_t itor, tb_size_t move)
{
tb_list_moveto_prev(self, tb_iterator_next(self, itor), move);
}
tb_void_t tb_list_moveto_head(tb_list_ref_t self, tb_size_t move)
{
tb_list_moveto_prev(self, tb_iterator_head(self), move);
}
tb_void_t tb_list_moveto_tail(tb_list_ref_t self, tb_size_t move)
{
tb_list_moveto_prev(self, tb_iterator_tail(self), move);
}
#ifdef __tb_debug__
tb_void_t tb_list_dump(tb_list_ref_t self)
{
// check
tb_list_t* list = (tb_list_t*)self;
tb_assert_and_check_return(list);
// trace
tb_trace_i("self: size: %lu", tb_list_size(self));
// done
tb_char_t cstr[4096];
tb_for_all (tb_pointer_t, data, self)
{
// trace
if (list->element.cstr)
{
tb_trace_i(" %s", list->element.cstr(&list->element, data, cstr, sizeof(cstr)));
}
else
{
tb_trace_i(" %p", data);
}
}
}
#endif
tbox-1.7.6/src/tbox/container/list.h 0000664 0000000 0000000 00000014000 14671175054 0017357 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file list.h
* @ingroup container
*
*/
#ifndef TB_CONTAINER_LIST_H
#define TB_CONTAINER_LIST_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "element.h"
#include "iterator.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/*! the doubly-linked list ref type
*
*
*
* list: tail => |-----| => |-------------------------------------------------=> |------| => |------| => tail
* | head last |
* | |
* <-----------------------------------------------------------------------------------------------
*
* performance:
*
* insert:
* insert midd: fast
* insert head: fast
* insert tail: fast
* insert next: fast
*
* remove:
* remove midd: fast
* remove head: fast
* remove last: fast
* remove next: fast
*
* iterator:
* next: fast
* prev: fast
*
*
*/
typedef tb_iterator_ref_t tb_list_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init list
*
* @param grow the grow size
* @param element the element
*
* @return the list
*/
tb_list_ref_t tb_list_init(tb_size_t grow, tb_element_t element);
/*! exit list
*
* @param list the list
*/
tb_void_t tb_list_exit(tb_list_ref_t list);
/*! clear list
*
* @param list the list
*/
tb_void_t tb_list_clear(tb_list_ref_t list);
/*! the list head item
*
* @param list the list
*
* @return the head item
*/
tb_pointer_t tb_list_head(tb_list_ref_t list);
/*! the list last item
*
* @param list the list
*
* @return the last item
*/
tb_pointer_t tb_list_last(tb_list_ref_t list);
/*! insert the prev item
*
* @param list the list
* @param itor the item itor
* @param data the item data
*
* @return the item itor
*/
tb_size_t tb_list_insert_prev(tb_list_ref_t list, tb_size_t itor, tb_cpointer_t data);
/*! insert the next item
*
* @param list the list
* @param itor the item itor
* @param data the item data
*
* @return the item itor
*/
tb_size_t tb_list_insert_next(tb_list_ref_t list, tb_size_t itor, tb_cpointer_t data);
/*! insert the head item
*
* @param list the list
* @param data the item data
*
* @return the item itor
*/
tb_size_t tb_list_insert_head(tb_list_ref_t list, tb_cpointer_t data);
/*! insert the tail item
*
* @param list the list
* @param data the item data
*
* @return the item itor
*/
tb_size_t tb_list_insert_tail(tb_list_ref_t list, tb_cpointer_t data);
/*! replace the item
*
* @param list the list
* @param itor the item itor
* @param data the item data
*/
tb_void_t tb_list_replace(tb_list_ref_t list, tb_size_t itor, tb_cpointer_t data);
/*! replace the head item
*
* @param list the list
* @param data the item data
*/
tb_void_t tb_list_replace_head(tb_list_ref_t list, tb_cpointer_t data);
/*! replace the tail item
*
* @param list the list
* @param data the item data
*/
tb_void_t tb_list_replace_last(tb_list_ref_t list, tb_cpointer_t data);
/*! remove the item
*
* @param list the list
* @param itor the item itor
*
* @return the next item
*/
tb_size_t tb_list_remove(tb_list_ref_t list, tb_size_t itor);
/*! remove the head item
*
* @param list the list
*/
tb_void_t tb_list_remove_head(tb_list_ref_t list);
/*! remove the last item
*
* @param list the list
*/
tb_void_t tb_list_remove_last(tb_list_ref_t list);
/*! moveto the prev item
*
* @param list the list
* @param itor the item itor
* @param move the move itor
*/
tb_void_t tb_list_moveto_prev(tb_list_ref_t list, tb_size_t itor, tb_size_t move);
/*! moveto the next item
*
* @param list the list
* @param itor the item itor
* @param move the move itor
*/
tb_void_t tb_list_moveto_next(tb_list_ref_t list, tb_size_t itor, tb_size_t move);
/*! moveto the head item
*
* @param list the list
* @param move the move itor
*/
tb_void_t tb_list_moveto_head(tb_list_ref_t list, tb_size_t move);
/*! moveto the tail item
*
* @param list the list
* @param move the move itor
*/
tb_void_t tb_list_moveto_tail(tb_list_ref_t list, tb_size_t move);
/*! the item count
*
* @param list the list
*
* @return the item count
*/
tb_size_t tb_list_size(tb_list_ref_t list);
/*! the item max count
*
* @param list the list
*
* @return the item max count
*/
tb_size_t tb_list_maxn(tb_list_ref_t list);
#ifdef __tb_debug__
/*! dump list
*
* @param list the list
*/
tb_void_t tb_list_dump(tb_list_ref_t list);
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/container/list_entry.c 0000664 0000000 0000000 00000012615 14671175054 0020605 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file list_entry.c
* @ingroup container
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "list_entry.h"
#include "../libc/libc.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* iterator implementation
*/
static tb_size_t tb_list_entry_itor_size(tb_iterator_ref_t iterator)
{
// check
tb_list_entry_head_ref_t list = tb_container_of(tb_list_entry_head_t, itor, iterator);
tb_assert(list);
// the size
return list->size;
}
static tb_size_t tb_list_entry_itor_head(tb_iterator_ref_t iterator)
{
// check
tb_list_entry_head_ref_t list = tb_container_of(tb_list_entry_head_t, itor, iterator);
tb_assert(list);
// head
return (tb_size_t)list->next;
}
static tb_size_t tb_list_entry_itor_last(tb_iterator_ref_t iterator)
{
// check
tb_list_entry_head_ref_t list = tb_container_of(tb_list_entry_head_t, itor, iterator);
tb_assert(list);
// last
return (tb_size_t)list->prev;
}
static tb_size_t tb_list_entry_itor_tail(tb_iterator_ref_t iterator)
{
// check
tb_list_entry_head_ref_t list = tb_container_of(tb_list_entry_head_t, itor, iterator);
tb_assert(list);
// tail
return (tb_size_t)list;
}
static tb_size_t tb_list_entry_itor_next(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_assert(itor);
// next
return (tb_size_t)((tb_list_entry_ref_t)itor)->next;
}
static tb_size_t tb_list_entry_itor_prev(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_assert(itor);
// prev
return (tb_size_t)((tb_list_entry_ref_t)itor)->prev;
}
static tb_pointer_t tb_list_entry_itor_item(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_list_entry_head_ref_t list = tb_container_of(tb_list_entry_head_t, itor, iterator);
tb_assert(list && list->eoff < itor);
// data
return (tb_pointer_t)(itor - list->eoff);
}
static tb_void_t tb_list_entry_itor_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item)
{
// check
tb_list_entry_head_ref_t list = tb_container_of(tb_list_entry_head_t, itor, iterator);
tb_assert(list && list->copy);
tb_assert(list->eoff < itor && item);
// copy it
list->copy((tb_pointer_t)(itor - list->eoff), (tb_pointer_t)item);
}
static tb_void_t tb_list_entry_itor_remove(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_list_entry_head_ref_t list = tb_container_of(tb_list_entry_head_t, itor, iterator);
tb_assert(list && itor);
// remove it
tb_list_entry_remove(list, (tb_list_entry_ref_t)itor);
}
static tb_void_t tb_list_entry_itor_nremove(tb_iterator_ref_t iterator, tb_size_t prev, tb_size_t next, tb_size_t size)
{
// check
tb_list_entry_head_ref_t list = tb_container_of(tb_list_entry_head_t, itor, iterator);
tb_assert(list && prev && next);
// no size?
tb_check_return(size);
// the entry
tb_list_entry_ref_t prev_entry = (tb_list_entry_ref_t)prev;
tb_list_entry_ref_t next_entry = (tb_list_entry_ref_t)next;
// remove entries
prev_entry->next = next_entry;
next_entry->prev = prev_entry;
// update size
list->size -= size;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_iterator_ref_t tb_list_entry_itor(tb_list_entry_head_ref_t list)
{
// check
tb_assert_and_check_return_val(list, tb_null);
// the iterator
return &list->itor;
}
tb_void_t tb_list_entry_init_(tb_list_entry_head_ref_t list, tb_size_t entry_offset, tb_size_t entry_size, tb_entry_copy_t copy)
{
// check
tb_assert_and_check_return(list && entry_size > sizeof(tb_list_entry_t));
// init list
list->next = (tb_list_entry_ref_t)list;
list->prev = (tb_list_entry_ref_t)list;
list->size = 0;
list->eoff = entry_offset;
list->copy = copy;
// init operation
static tb_iterator_op_t op =
{
tb_list_entry_itor_size
, tb_list_entry_itor_head
, tb_list_entry_itor_last
, tb_list_entry_itor_tail
, tb_list_entry_itor_prev
, tb_list_entry_itor_next
, tb_list_entry_itor_item
, tb_null
, tb_list_entry_itor_copy
, tb_list_entry_itor_remove
, tb_list_entry_itor_nremove
};
// init iterator
list->itor.priv = tb_null;
list->itor.step = entry_size;
list->itor.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE;
list->itor.flag = TB_ITERATOR_FLAG_ITEM_REF;
list->itor.op = &op;
}
tb_void_t tb_list_entry_exit(tb_list_entry_head_ref_t list)
{
// check
tb_assert_and_check_return(list);
// exit it
list->next = (tb_list_entry_ref_t)list;
list->prev = (tb_list_entry_ref_t)list;
list->size = 0;
}
tbox-1.7.6/src/tbox/container/list_entry.h 0000664 0000000 0000000 00000044700 14671175054 0020612 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file list_entry.h
* @ingroup container
*
*/
#ifndef TB_CONTAINER_LIST_ENTRY_H
#define TB_CONTAINER_LIST_ENTRY_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "iterator.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/// get the list entry
#define tb_list_entry(head, entry) ((((tb_byte_t*)(entry)) - (head)->eoff))
/*! get the list entry with zero offset
*
* @code
*
// the xxxx entry type
typedef struct __tb_xxxx_entry_t
{
// the list entry (be placed in header with zero offset)
tb_list_entry_t entry;
// ..
}tb_xxxx_entry_t;
*
* @endcode
*/
#define tb_list_entry0(entry) (entry)
/*! init the list entry
*
* @code
*
// the xxxx entry type
typedef struct __tb_xxxx_entry_t
{
// the list entry
tb_list_entry_t entry;
// the data
tb_size_t data;
}tb_xxxx_entry_t;
// the xxxx entry copy func
static tb_void_t tb_xxxx_entry_copy(tb_pointer_t litem, tb_pointer_t ritem)
{
// check
tb_assert(litem && ritem);
// copy it
((tb_xxxx_entry_t*)litem)->data = ((tb_xxxx_entry_t*)ritem)->data;
}
// init the list
tb_list_entry_head_t list;
tb_list_entry_init(&list, tb_xxxx_entry_t, entry, tb_xxxx_entry_copy);
* @endcode
*/
#define tb_list_entry_init(list, type, entry, copy) tb_list_entry_init_(list, tb_offsetof(type, entry), sizeof(type), copy)
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/*! the doubly-linked list entry type
*
*
* list: list => ... => last
* | |
* <---------------
*
*
*/
typedef struct __tb_list_entry_t
{
/// the next entry
struct __tb_list_entry_t* next;
/// the prev entry
struct __tb_list_entry_t* prev;
}tb_list_entry_t, *tb_list_entry_ref_t;
/// the list entry head type
typedef struct __tb_list_entry_head_t
{
/// the next entry
struct __tb_list_entry_t* next;
/// the prev entry
struct __tb_list_entry_t* prev;
/// the list size
tb_size_t size;
/// the iterator
tb_iterator_t itor;
/// the entry offset
tb_size_t eoff;
/// the entry copy func
tb_entry_copy_t copy;
}tb_list_entry_head_t, *tb_list_entry_head_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the list iterator
*
* @param list the list
*
* @return the list iterator
*/
tb_iterator_ref_t tb_list_entry_itor(tb_list_entry_head_ref_t list);
/*! init list
*
* @param list the list
* @param entry_offset the entry offset
* @param entry_size the entry size
* @param copy the copy func of the entry for algorithm, .e.g sort
*/
tb_void_t tb_list_entry_init_(tb_list_entry_head_ref_t list, tb_size_t entry_offset, tb_size_t entry_size, tb_entry_copy_t copy);
/*! exit list
*
* @param list the list
*/
tb_void_t tb_list_entry_exit(tb_list_entry_head_ref_t list);
/*! clear list
*
* @param list the list
*/
static __tb_inline__ tb_void_t tb_list_entry_clear(tb_list_entry_head_ref_t list)
{
// check
tb_assert(list);
// clear it
list->next = (tb_list_entry_ref_t)list;
list->prev = (tb_list_entry_ref_t)list;
list->size = 0;
}
/*! the list entry count
*
* @param list the list
*
* @return the list entry count
*/
static __tb_inline__ tb_size_t tb_list_entry_size(tb_list_entry_head_ref_t list)
{
// check
tb_assert(list);
// done
return list->size;
}
/*! the list next entry
*
* @param entry the entry
*
* @return the next entry
*/
static __tb_inline__ tb_list_entry_ref_t tb_list_entry_next(tb_list_entry_ref_t entry)
{
// check
tb_assert(entry);
// done
return entry->next;
}
/*! the list prev entry
*
* @param entry the entry
*
* @return the prev entry
*/
static __tb_inline__ tb_list_entry_ref_t tb_list_entry_prev(tb_list_entry_ref_t entry)
{
// check
tb_assert(entry);
// done
return entry->prev;
}
/*! the list head entry
*
* @param list the list
*
* @return the head entry
*/
static __tb_inline__ tb_list_entry_ref_t tb_list_entry_head(tb_list_entry_head_ref_t list)
{
// check
tb_assert(list);
// done
return list->next;
}
/*! the list last entry
*
* @param list the list
*
* @return the last entry
*/
static __tb_inline__ tb_list_entry_ref_t tb_list_entry_last(tb_list_entry_head_ref_t list)
{
// check
tb_assert(list);
// done
return list->prev;
}
/*! the list tail entry
*
* @param list the list
*
* @return the tail entry
*/
static __tb_inline__ tb_list_entry_ref_t tb_list_entry_tail(tb_list_entry_head_ref_t list)
{
// done
return (tb_list_entry_ref_t)list;
}
/*! the list is null?
*
* @param list the list
*
* @return tb_true or tb_false
*/
static __tb_inline__ tb_bool_t tb_list_entry_is_null(tb_list_entry_head_ref_t list)
{
// check
tb_assert(list);
// done
return !list->size;
}
/*! is the list head entry?
*
* @param list the list
* @param entry the entry
*
* @return tb_true or tb_false
*/
static __tb_inline__ tb_bool_t tb_list_entry_is_head(tb_list_entry_head_ref_t list, tb_list_entry_ref_t entry)
{
// check
tb_assert(list);
// done
return list->next == entry;
}
/*! is the list last entry?
*
* @param list the list
* @param entry the entry
*
* @return tb_true or tb_false
*/
static __tb_inline__ tb_bool_t tb_list_entry_is_last(tb_list_entry_head_ref_t list, tb_list_entry_ref_t entry)
{
// check
tb_assert(list);
// done
return list->prev == entry;
}
/*! the list is valid?
*
* @param list the list
*
* @return tb_true or tb_false
*/
static __tb_inline__ tb_bool_t tb_list_entry_is_valid(tb_list_entry_head_ref_t list)
{
// check
tb_assert(list);
// done
return (list->next && list->next->prev == (tb_list_entry_ref_t)list) && (list->prev && list->prev->next == (tb_list_entry_ref_t)list);
}
/*! splice the spliced_list to list[prev, next]
*
* @param list the list
* @param prev the prev
* @param next the next
* @param spliced_list the spliced list
*/
static __tb_inline__ tb_void_t tb_list_entry_splice(tb_list_entry_head_ref_t list, tb_list_entry_ref_t prev, tb_list_entry_ref_t next, tb_list_entry_head_ref_t spliced_list)
{
// check
tb_assert(list && prev && next);
tb_assert(spliced_list && spliced_list->next && spliced_list->prev);
// valid?
tb_assert(tb_list_entry_is_valid(list));
tb_assert(tb_list_entry_is_valid(spliced_list));
// empty?
tb_check_return(!tb_list_entry_is_null(spliced_list));
// done
spliced_list->next->prev = prev;
prev->next = spliced_list->next;
spliced_list->prev->next = next;
next->prev = spliced_list->prev;
// update size
list->size += spliced_list->size;
// clear the spliced list
tb_list_entry_clear(spliced_list);
}
/*! splice the spliced_list at the list head
*
* @param list the list
* @param spliced_list the spliced list
*/
static __tb_inline__ tb_void_t tb_list_entry_splice_head(tb_list_entry_head_ref_t list, tb_list_entry_head_ref_t spliced_list)
{
// check
tb_assert(list);
// done
tb_list_entry_splice(list, (tb_list_entry_ref_t)list, list->next, spliced_list);
}
/*! splice the spliced_list at the list tail
*
* @param list the list
* @param spliced_list the spliced list
*/
static __tb_inline__ tb_void_t tb_list_entry_splice_tail(tb_list_entry_head_ref_t list, tb_list_entry_head_ref_t spliced_list)
{
// check
tb_assert(list);
// done
tb_list_entry_splice(list, list->prev, (tb_list_entry_ref_t)list, spliced_list);
}
/*! insert entry to the next
*
* @param list the list
* @param node the list node
* @param entry the inserted list entry
*/
static __tb_inline__ tb_void_t tb_list_entry_insert_next(tb_list_entry_head_ref_t list, tb_list_entry_ref_t node, tb_list_entry_ref_t entry)
{
// check
tb_assert(list && node && node->next && entry);
tb_assert(node != entry);
// valid?
tb_assert(tb_list_entry_is_valid(list));
// insert entry
node->next->prev = entry;
entry->next = node->next;
entry->prev = node;
node->next = entry;
// size++
list->size++;
}
/*! insert entry to the prev
*
* @param list the list
* @param node the list node
* @param entry the inserted list entry
*/
static __tb_inline__ tb_void_t tb_list_entry_insert_prev(tb_list_entry_head_ref_t list, tb_list_entry_ref_t node, tb_list_entry_ref_t entry)
{
// check
tb_assert(list && node);
// insert it
tb_list_entry_insert_next(list, node->prev, entry);
}
/*! insert entry to the head
*
* @param list the list
* @param entry the inserted list entry
*/
static __tb_inline__ tb_void_t tb_list_entry_insert_head(tb_list_entry_head_ref_t list, tb_list_entry_ref_t entry)
{
tb_list_entry_insert_next(list, (tb_list_entry_ref_t)list, entry);
}
/*! insert entry to the tail
*
* @param list the list
* @param entry the inserted list entry
*/
static __tb_inline__ tb_void_t tb_list_entry_insert_tail(tb_list_entry_head_ref_t list, tb_list_entry_ref_t entry)
{
// check
tb_assert(list && entry);
// insert it
tb_list_entry_insert_next(list, list->prev, entry);
}
/*! replace the entry
*
* @param list the list
* @param node the replaced list node
* @param entry the new list entry
*/
static __tb_inline__ tb_void_t tb_list_entry_replace(tb_list_entry_head_ref_t list, tb_list_entry_ref_t node, tb_list_entry_ref_t entry)
{
// check
tb_assert(node && node->next && node->prev && entry);
tb_assert(node != entry);
// valid?
tb_assert(tb_list_entry_is_valid(list));
// replace it
entry->next = node->next;
entry->next->prev = entry;
entry->prev = node->prev;
entry->prev->next = entry;
}
/*! replace the next entry
*
* @param list the list
* @param node the list node
* @param entry the new list entry
*/
static __tb_inline__ tb_void_t tb_list_entry_replace_next(tb_list_entry_head_ref_t list, tb_list_entry_ref_t node, tb_list_entry_ref_t entry)
{
// check
tb_assert(node);
// replace it
tb_list_entry_replace(list, node->next, entry);
}
/*! replace the prev entry
*
* @param list the list
* @param node the list node
* @param entry the new list entry
*/
static __tb_inline__ tb_void_t tb_list_entry_replace_prev(tb_list_entry_head_ref_t list, tb_list_entry_ref_t node, tb_list_entry_ref_t entry)
{
// check
tb_assert(node);
// replace it
tb_list_entry_replace(list, node->prev, entry);
}
/*! replace the head entry
*
* @param list the list
* @param entry the new list entry
*/
static __tb_inline__ tb_void_t tb_list_entry_replace_head(tb_list_entry_head_ref_t list, tb_list_entry_ref_t entry)
{
// check
tb_assert(list);
// replace it
tb_list_entry_replace(list, list->next, entry);
}
/*! replace the last entry
*
* @param list the list
* @param entry the new list entry
*/
static __tb_inline__ tb_void_t tb_list_entry_replace_last(tb_list_entry_head_ref_t list, tb_list_entry_ref_t entry)
{
// check
tb_assert(list);
// replace it
tb_list_entry_replace(list, list->prev, entry);
}
/*! remove the entry (private interface)
*
* @param list the list
* @param prev the prev entry
* @param next the next entry
*/
static __tb_inline__ tb_void_t tb_list_entry_remove_(tb_list_entry_head_ref_t list, tb_list_entry_ref_t prev, tb_list_entry_ref_t next)
{
// check
tb_assert(list && list->size && prev && next);
// valid?
tb_assert(tb_list_entry_is_valid(list));
// remove entries
prev->next = next;
next->prev = prev;
// update size
list->size--;
}
/*! remove the entry
*
* @param list the list
* @param entry the removed list entry
*/
static __tb_inline__ tb_void_t tb_list_entry_remove(tb_list_entry_head_ref_t list, tb_list_entry_ref_t entry)
{
// check
tb_assert(entry);
// remove it
tb_list_entry_remove_(list, entry->prev, entry->next);
}
/*! remove the next entry
*
* @param list the list
* @param prev the prev entry
*/
static __tb_inline__ tb_void_t tb_list_entry_remove_next(tb_list_entry_head_ref_t list, tb_list_entry_ref_t prev)
{
// check
tb_assert(prev && prev->next);
// remove it
tb_list_entry_remove_(list, prev, prev->next->next);
}
/*! remove the prev entry
*
* @param list the list
* @param next the next entry
*/
static __tb_inline__ tb_void_t tb_list_entry_remove_prev(tb_list_entry_head_ref_t list, tb_list_entry_ref_t next)
{
// check
tb_assert(next && next->prev);
// remove it
tb_list_entry_remove_(list, next->prev->prev, next);
}
/*! remove the head entry
*
* @param list the list
*/
static __tb_inline__ tb_void_t tb_list_entry_remove_head(tb_list_entry_head_ref_t list)
{
// check
tb_assert(list && list->next);
// remove it
tb_list_entry_remove_(list, (tb_list_entry_ref_t)list, list->next->next);
}
/*! remove the last entry
*
* @param list the list
*/
static __tb_inline__ tb_void_t tb_list_entry_remove_last(tb_list_entry_head_ref_t list)
{
// check
tb_assert(list && list->prev);
// remove it
tb_list_entry_remove_(list, list->prev->prev, (tb_list_entry_ref_t)list);
}
/*! moveto the next entry
*
* @param list the list
* @param node the list node
* @param entry the moved list entry
*/
static __tb_inline__ tb_void_t tb_list_entry_moveto_next(tb_list_entry_head_ref_t list, tb_list_entry_ref_t node, tb_list_entry_ref_t entry)
{
// check
tb_check_return(node != entry);
// move it
tb_list_entry_remove(list, entry);
tb_list_entry_insert_next(list, node, entry);
}
/*! moveto the prev entry
*
* @param list the list
* @param node the list node
* @param entry the moved list entry
*/
static __tb_inline__ tb_void_t tb_list_entry_moveto_prev(tb_list_entry_head_ref_t list, tb_list_entry_ref_t node, tb_list_entry_ref_t entry)
{
// check
tb_assert(node);
// move it
tb_list_entry_moveto_next(list, node->prev, entry);
}
/*! moveto the head entry
*
* @param list the list
* @param entry the moved list entry
*/
static __tb_inline__ tb_void_t tb_list_entry_moveto_head(tb_list_entry_head_ref_t list, tb_list_entry_ref_t entry)
{
// move it
tb_list_entry_moveto_next(list, (tb_list_entry_ref_t)list, entry);
}
/*! moveto the tail entry
*
* @param list the list
* @param entry the moved list entry
*/
static __tb_inline__ tb_void_t tb_list_entry_moveto_tail(tb_list_entry_head_ref_t list, tb_list_entry_ref_t entry)
{
// check
tb_assert(list);
// move it
tb_list_entry_moveto_next(list, list->prev, entry);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/container/prefix.h 0000664 0000000 0000000 00000002145 14671175054 0017710 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_CONTAINER_PREFIX_H
#define TB_CONTAINER_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the entry copy func type
typedef tb_void_t (*tb_entry_copy_t)(tb_pointer_t litem, tb_pointer_t ritem);
#endif
tbox-1.7.6/src/tbox/container/priority_queue.c 0000664 0000000 0000000 00000004207 14671175054 0021474 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file priority_queue.c
* @ingroup container
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "priority_queue.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_priority_queue_ref_t tb_priority_queue_init(tb_size_t grow, tb_element_t element)
{
return (tb_priority_queue_ref_t)tb_heap_init(grow, element);
}
tb_void_t tb_priority_queue_exit(tb_priority_queue_ref_t self)
{
tb_heap_exit((tb_heap_ref_t)self);
}
tb_void_t tb_priority_queue_clear(tb_priority_queue_ref_t self)
{
tb_heap_clear((tb_heap_ref_t)self);
}
tb_size_t tb_priority_queue_size(tb_priority_queue_ref_t self)
{
return tb_heap_size((tb_heap_ref_t)self);
}
tb_size_t tb_priority_queue_maxn(tb_priority_queue_ref_t self)
{
return tb_heap_maxn((tb_heap_ref_t)self);
}
tb_pointer_t tb_priority_queue_get(tb_priority_queue_ref_t self)
{
return tb_heap_top((tb_heap_ref_t)self);
}
tb_void_t tb_priority_queue_put(tb_priority_queue_ref_t self, tb_cpointer_t data)
{
tb_heap_put((tb_heap_ref_t)self, data);
}
tb_void_t tb_priority_queue_pop(tb_priority_queue_ref_t self)
{
tb_heap_pop((tb_heap_ref_t)self);
}
tb_void_t tb_priority_queue_remove(tb_priority_queue_ref_t self, tb_size_t itor)
{
tb_heap_remove((tb_heap_ref_t)self, itor);
}
#ifdef __tb_debug__
tb_void_t tb_priority_queue_dump(tb_priority_queue_ref_t self)
{
tb_heap_dump((tb_heap_ref_t)self);
}
#endif
tbox-1.7.6/src/tbox/container/priority_queue.h 0000664 0000000 0000000 00000006653 14671175054 0021510 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file priority_queue.h
* @ingroup container
*
*/
#ifndef TB_CONTAINER_PRIORITY_QUEUE_H
#define TB_CONTAINER_PRIORITY_QUEUE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "element.h"
#include "heap.h"
#include "iterator.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/*! the priority queue ref type
*
* using the min/max heap
*/
typedef tb_heap_ref_t tb_priority_queue_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init queue, default: min-priority
*
* @param grow the element grow, using the default grow if be zero
* @param element the element
*
* @return the queue
*/
tb_priority_queue_ref_t tb_priority_queue_init(tb_size_t grow, tb_element_t element);
/*! exit queue
*
* @param queue the queue
*/
tb_void_t tb_priority_queue_exit(tb_priority_queue_ref_t queue);
/*! clear the queue
*
* @param queue the queue
*/
tb_void_t tb_priority_queue_clear(tb_priority_queue_ref_t queue);
/*! the queue size
*
* @param queue the queue
*
* @return the queue size
*/
tb_size_t tb_priority_queue_size(tb_priority_queue_ref_t queue);
/*! the queue maxn
*
* @param queue the queue
*
* @return the queue maxn
*/
tb_size_t tb_priority_queue_maxn(tb_priority_queue_ref_t queue);
/*! get the queue item
*
* @param queue the queue
*
* @return the queue top item
*/
tb_pointer_t tb_priority_queue_get(tb_priority_queue_ref_t queue);
/*! put the queue item
*
* @param queue the queue
* @param data the item data
*/
tb_void_t tb_priority_queue_put(tb_priority_queue_ref_t queue, tb_cpointer_t data);
/*! pop the queue item
*
* @param queue the queue
*/
tb_void_t tb_priority_queue_pop(tb_priority_queue_ref_t queue);
/*! remove the queue item
*
* @param queue the queue
* @param itor the itor
*/
tb_void_t tb_priority_queue_remove(tb_priority_queue_ref_t queue, tb_size_t itor);
#ifdef __tb_debug__
/*! dump queue
*
* @param queue the queue
*/
tb_void_t tb_priority_queue_dump(tb_priority_queue_ref_t queue);
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/container/queue.c 0000664 0000000 0000000 00000004743 14671175054 0017540 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file queue.c
* @ingroup container
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "queue.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_queue_ref_t tb_queue_init(tb_size_t grow, tb_element_t element)
{
return (tb_queue_ref_t)tb_single_list_init(grow, element);
}
tb_void_t tb_queue_exit(tb_queue_ref_t queue)
{
tb_single_list_exit((tb_single_list_ref_t)queue);
}
tb_void_t tb_queue_clear(tb_queue_ref_t queue)
{
tb_single_list_clear((tb_single_list_ref_t)queue);
}
tb_void_t tb_queue_put(tb_queue_ref_t queue, tb_cpointer_t data)
{
tb_single_list_insert_tail((tb_single_list_ref_t)queue, data);
}
tb_void_t tb_queue_pop(tb_queue_ref_t queue)
{
tb_single_list_remove_head((tb_single_list_ref_t)queue);
}
tb_pointer_t tb_queue_get(tb_queue_ref_t queue)
{
return tb_queue_head(queue);
}
tb_pointer_t tb_queue_head(tb_queue_ref_t queue)
{
return tb_single_list_head((tb_single_list_ref_t)queue);
}
tb_pointer_t tb_queue_last(tb_queue_ref_t queue)
{
return tb_single_list_last((tb_single_list_ref_t)queue);
}
tb_size_t tb_queue_size(tb_queue_ref_t queue)
{
return tb_single_list_size((tb_single_list_ref_t)queue);
}
tb_size_t tb_queue_maxn(tb_queue_ref_t queue)
{
return tb_single_list_maxn((tb_single_list_ref_t)queue);
}
tb_bool_t tb_queue_full(tb_queue_ref_t queue)
{
return (tb_single_list_size((tb_single_list_ref_t)queue) < tb_single_list_maxn((tb_single_list_ref_t)queue))? tb_false : tb_true;
}
tb_bool_t tb_queue_null(tb_queue_ref_t queue)
{
return tb_single_list_size((tb_single_list_ref_t)queue)? tb_false : tb_true;
}
#ifdef __tb_debug__
tb_void_t tb_queue_dump(tb_queue_ref_t queue)
{
tb_single_list_dump((tb_single_list_ref_t)queue);
}
#endif
tbox-1.7.6/src/tbox/container/queue.h 0000664 0000000 0000000 00000007314 14671175054 0017542 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file queue.h
* @ingroup container
*
*/
#ifndef TB_CONTAINER_QUEUE_H
#define TB_CONTAINER_QUEUE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "element.h"
#include "iterator.h"
#include "single_list.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/*! the queue ref type
*
*
* queue: |-----| => |-----| => ... => |-----| => tail
* head last
*
* performance:
*
* put: O(1)
* pop: O(1)
*
* iterator:
*
* next: fast
* prev: fast
*
*
*/
typedef tb_single_list_ref_t tb_queue_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init queue
*
* @param grow the grow size, using the default grow size if be zero
* @param element the element
*
* @return the queue
*/
tb_queue_ref_t tb_queue_init(tb_size_t grow, tb_element_t element);
/*! exit queue
*
* @param queue the queue
*/
tb_void_t tb_queue_exit(tb_queue_ref_t queue);
/*! the queue head item
*
* @param queue the queue
*
* @return the head item
*/
tb_pointer_t tb_queue_head(tb_queue_ref_t queue);
/*! the queue last item
*
* @param queue the queue
*
* @return the last item
*/
tb_pointer_t tb_queue_last(tb_queue_ref_t queue);
/*! clear the queue
*
* @param queue the queue
*/
tb_void_t tb_queue_clear(tb_queue_ref_t queue);
/*! put the queue item
*
* @param queue the queue
* @param data the item data
*/
tb_void_t tb_queue_put(tb_queue_ref_t queue, tb_cpointer_t data);
/*! pop the queue item
*
* @param queue the queue
*/
tb_void_t tb_queue_pop(tb_queue_ref_t queue);
/*! get the queue item
*
* @param queue the queue
*
* @return the queue item
*/
tb_pointer_t tb_queue_get(tb_queue_ref_t queue);
/*! the queue size
*
* @param queue the queue
*
* @return the queue size
*/
tb_size_t tb_queue_size(tb_queue_ref_t queue);
/*! the queue maxn
*
* @param queue the queue
*
* @return the queue maxn
*/
tb_size_t tb_queue_maxn(tb_queue_ref_t queue);
/*! the queue full?
*
* @param queue the queue
*
* @return tb_true or tb_false
*/
tb_bool_t tb_queue_full(tb_queue_ref_t queue);
/*! the queue null?
*
* @param queue the queue
*
* @return tb_true or tb_false
*/
tb_bool_t tb_queue_null(tb_queue_ref_t queue);
#ifdef __tb_debug__
/*! dump queue
*
* @param queue the queue
*/
tb_void_t tb_queue_dump(tb_queue_ref_t queue);
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/container/single_list.c 0000664 0000000 0000000 00000033171 14671175054 0020725 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file single_list.c
* @ingroup container
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "single_list"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "single_list.h"
#include "single_list_entry.h"
#include "../libc/libc.h"
#include "../math/math.h"
#include "../memory/memory.h"
#include "../stream/stream.h"
#include "../platform/platform.h"
#include "../algorithm/algorithm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the self grow
#ifdef __tb_small__
# define TB_SINGLE_LIST_GROW (128)
#else
# define TB_SINGLE_LIST_GROW (256)
#endif
// the self maxn
#ifdef __tb_small__
# define TB_SINGLE_LIST_MAXN (1 << 16)
#else
# define TB_SINGLE_LIST_MAXN (1 << 30)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the single list type
typedef struct __tb_single_list_t
{
// the itor
tb_iterator_t itor;
// the pool
tb_fixed_pool_ref_t pool;
// the head
tb_single_list_entry_head_t head;
// the element
tb_element_t element;
}tb_single_list_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_size_t tb_single_list_itor_size(tb_iterator_ref_t iterator)
{
// the size
return tb_single_list_size((tb_single_list_ref_t)iterator);
}
static tb_size_t tb_single_list_itor_head(tb_iterator_ref_t iterator)
{
// check
tb_single_list_t* list = (tb_single_list_t*)iterator;
tb_assert(list);
// head
return (tb_size_t)tb_single_list_entry_head(&list->head);
}
static tb_size_t tb_single_list_itor_last(tb_iterator_ref_t iterator)
{
// check
tb_single_list_t* list = (tb_single_list_t*)iterator;
tb_assert(list);
// last
return (tb_size_t)tb_single_list_entry_last(&list->head);
}
static tb_size_t tb_single_list_itor_tail(tb_iterator_ref_t iterator)
{
// check
tb_single_list_t* list = (tb_single_list_t*)iterator;
tb_assert(list);
// tail
return (tb_size_t)tb_single_list_entry_tail(&list->head);
}
static tb_size_t tb_single_list_itor_next(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_assert(itor);
// next
return (tb_size_t)tb_single_list_entry_next((tb_single_list_entry_t*)itor);
}
static tb_pointer_t tb_single_list_itor_item(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_single_list_t* list = (tb_single_list_t*)iterator;
tb_assert(list && itor);
// data
return list->element.data(&list->element, (tb_cpointer_t)(((tb_single_list_entry_t*)itor) + 1));
}
static tb_void_t tb_single_list_itor_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item)
{
// check
tb_single_list_t* list = (tb_single_list_t*)iterator;
tb_assert(list && itor);
// copy
list->element.copy(&list->element, (tb_pointer_t)(((tb_single_list_entry_t*)itor) + 1), item);
}
static tb_long_t tb_single_list_itor_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem)
{
// check
tb_single_list_t* list = (tb_single_list_t*)iterator;
tb_assert(list && list->element.comp);
// comp
return list->element.comp(&list->element, litem, ritem);
}
static tb_void_t tb_single_list_itor_nremove(tb_iterator_ref_t iterator, tb_size_t prev, tb_size_t next, tb_size_t size)
{
// no size?
tb_check_return(size);
// the self size
tb_size_t single_list_size = tb_single_list_size((tb_single_list_ref_t)iterator);
tb_check_return(single_list_size);
// limit size
if (size > single_list_size) size = single_list_size;
// remove the body items
if (prev)
{
// done
tb_bool_t end = tb_false;
while (size-- && !end)
{
// end?
end = (tb_iterator_next((tb_single_list_ref_t)iterator, prev) == next)? tb_true : tb_false;
// remove next
tb_single_list_remove_next((tb_single_list_ref_t)iterator, prev);
}
}
// remove the head items
else
{
while (size--) tb_single_list_remove_head((tb_single_list_ref_t)iterator);
}
}
static tb_void_t tb_single_list_item_exit(tb_pointer_t data, tb_cpointer_t priv)
{
// check
tb_single_list_t* list = (tb_single_list_t*)priv;
tb_assert_and_check_return(list);
// free data
if (list->element.free) list->element.free(&list->element, (tb_pointer_t)(((tb_single_list_entry_t*)data) + 1));
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_single_list_ref_t tb_single_list_init(tb_size_t grow, tb_element_t element)
{
// check
tb_assert_and_check_return_val(element.size && element.data && element.dupl && element.repl, tb_null);
// done
tb_bool_t ok = tb_false;
tb_single_list_t* list = tb_null;
do
{
// using the default grow
if (!grow) grow = TB_SINGLE_LIST_GROW;
// make self
list = tb_malloc0_type(tb_single_list_t);
tb_assert_and_check_break(list);
// init element
list->element = element;
// init operation
static tb_iterator_op_t op =
{
tb_single_list_itor_size
, tb_single_list_itor_head
, tb_single_list_itor_last
, tb_single_list_itor_tail
, tb_null
, tb_single_list_itor_next
, tb_single_list_itor_item
, tb_single_list_itor_comp
, tb_single_list_itor_copy
, tb_null
, tb_single_list_itor_nremove
};
// init iterator
list->itor.priv = tb_null;
list->itor.step = element.size;
list->itor.mode = TB_ITERATOR_MODE_FORWARD;
list->itor.op = &op;
if (element.type == TB_ELEMENT_TYPE_MEM)
list->itor.flag = TB_ITERATOR_FLAG_ITEM_REF;
// init pool, item = entry + data
list->pool = tb_fixed_pool_init(tb_null, grow, sizeof(tb_single_list_entry_t) + element.size, tb_null, tb_single_list_item_exit, (tb_cpointer_t)list);
tb_assert_and_check_break(list->pool);
// init head
tb_single_list_entry_init_(&list->head, 0, sizeof(tb_single_list_entry_t) + element.size, tb_null);
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (list) tb_single_list_exit((tb_single_list_ref_t)list);
list = tb_null;
}
// ok?
return (tb_single_list_ref_t)list;
}
tb_void_t tb_single_list_exit(tb_single_list_ref_t self)
{
// check
tb_single_list_t* list = (tb_single_list_t*)self;
tb_assert_and_check_return(list);
// clear data
tb_single_list_clear((tb_single_list_ref_t)list);
// free pool
if (list->pool) tb_fixed_pool_exit(list->pool);
// free it
tb_free(list);
}
tb_void_t tb_single_list_clear(tb_single_list_ref_t self)
{
// check
tb_single_list_t* list = (tb_single_list_t*)self;
tb_assert_and_check_return(list);
// clear pool
if (list->pool) tb_fixed_pool_clear(list->pool);
// clear head
tb_single_list_entry_clear(&list->head);
}
tb_pointer_t tb_single_list_head(tb_single_list_ref_t self)
{
return tb_iterator_item(self, tb_iterator_head(self));
}
tb_pointer_t tb_single_list_last(tb_single_list_ref_t self)
{
return tb_iterator_item(self, tb_iterator_last(self));
}
tb_size_t tb_single_list_size(tb_single_list_ref_t self)
{
// check
tb_single_list_t* list = (tb_single_list_t*)self;
tb_assert_and_check_return_val(list && list->pool, 0);
tb_assert(tb_single_list_entry_size(&list->head) == tb_fixed_pool_size(list->pool));
// the size
return tb_single_list_entry_size(&list->head);
}
tb_size_t tb_single_list_maxn(tb_single_list_ref_t self)
{
// the item maxn
return TB_SINGLE_LIST_MAXN;
}
tb_size_t tb_single_list_insert_next(tb_single_list_ref_t self, tb_size_t itor, tb_cpointer_t data)
{
// check
tb_single_list_t* list = (tb_single_list_t*)self;
tb_assert_and_check_return_val(list && list->element.dupl && list->pool, 0);
// full?
tb_assert_and_check_return_val(tb_single_list_size(self) < tb_single_list_maxn(self), tb_iterator_tail(self));
// the node
tb_single_list_entry_ref_t node = (tb_single_list_entry_ref_t)itor;
tb_assert_and_check_return_val(node, tb_iterator_tail(self));
// make entry
tb_single_list_entry_ref_t entry = (tb_single_list_entry_ref_t)tb_fixed_pool_malloc(list->pool);
tb_assert_and_check_return_val(entry, tb_iterator_tail(self));
// init entry data
list->element.dupl(&list->element, (tb_pointer_t)(((tb_single_list_entry_t*)entry) + 1), data);
// insert it
tb_single_list_entry_insert_next(&list->head, node, entry);
// ok
return (tb_size_t)entry;
}
tb_size_t tb_single_list_insert_head(tb_single_list_ref_t self, tb_cpointer_t data)
{
// check
tb_single_list_t* list = (tb_single_list_t*)self;
tb_assert_and_check_return_val(list && list->element.dupl && list->pool, 0);
// full?
tb_assert_and_check_return_val(tb_single_list_size(self) < tb_single_list_maxn(self), tb_iterator_tail(self));
// make entry
tb_single_list_entry_ref_t entry = (tb_single_list_entry_ref_t)tb_fixed_pool_malloc(list->pool);
tb_assert_and_check_return_val(entry, tb_iterator_tail(self));
// init entry data
list->element.dupl(&list->element, (tb_pointer_t)(((tb_single_list_entry_t*)entry) + 1), data);
// insert it
tb_single_list_entry_insert_head(&list->head, entry);
// ok
return (tb_size_t)entry;
}
tb_size_t tb_single_list_insert_tail(tb_single_list_ref_t self, tb_cpointer_t data)
{
// check
tb_single_list_t* list = (tb_single_list_t*)self;
tb_assert_and_check_return_val(list && list->element.dupl && list->pool, 0);
// full?
tb_assert_and_check_return_val(tb_single_list_size(self) < tb_single_list_maxn(self), tb_iterator_tail(self));
// make entry
tb_single_list_entry_ref_t entry = (tb_single_list_entry_ref_t)tb_fixed_pool_malloc(list->pool);
tb_assert_and_check_return_val(entry, tb_iterator_tail(self));
// init entry data
list->element.dupl(&list->element, (tb_pointer_t)(((tb_single_list_entry_t*)entry) + 1), data);
// insert it
tb_single_list_entry_insert_tail(&list->head, entry);
// ok
return (tb_size_t)entry;
}
tb_void_t tb_single_list_replace(tb_single_list_ref_t self, tb_size_t itor, tb_cpointer_t data)
{
// check
tb_single_list_t* list = (tb_single_list_t*)self;
tb_assert_and_check_return(list && list->element.repl && itor);
// the node
tb_single_list_entry_ref_t node = (tb_single_list_entry_ref_t)itor;
tb_assert_and_check_return(node);
// replace data
list->element.repl(&list->element, (tb_pointer_t)(((tb_single_list_entry_t*)node) + 1), data);
}
tb_void_t tb_single_list_replace_head(tb_single_list_ref_t self, tb_cpointer_t data)
{
tb_single_list_replace(self, tb_iterator_head(self), data);
}
tb_void_t tb_single_list_replace_last(tb_single_list_ref_t self, tb_cpointer_t data)
{
tb_single_list_replace(self, tb_iterator_last(self), data);
}
tb_void_t tb_single_list_remove_next(tb_single_list_ref_t self, tb_size_t itor)
{
// check
tb_single_list_t* list = (tb_single_list_t*)self;
tb_assert_and_check_return(list && list->pool && itor);
// the node
tb_single_list_entry_ref_t node = (tb_single_list_entry_ref_t)itor;
tb_assert_and_check_return(node);
// the next node
tb_single_list_entry_ref_t next = tb_single_list_entry_next(node);
tb_assert_and_check_return(next);
// remove next node
tb_single_list_entry_remove_next(&list->head, node);
// free next node
tb_fixed_pool_free(list->pool, next);
}
tb_void_t tb_single_list_remove_head(tb_single_list_ref_t self)
{
// check
tb_single_list_t* list = (tb_single_list_t*)self;
tb_assert_and_check_return(list && list->pool);
// the node
tb_single_list_entry_ref_t node = tb_single_list_entry_head(&list->head);
tb_assert_and_check_return(node);
// remove next node
tb_single_list_entry_remove_head(&list->head);
// free head node
tb_fixed_pool_free(list->pool, node);
}
#ifdef __tb_debug__
tb_void_t tb_single_list_dump(tb_single_list_ref_t self)
{
// check
tb_single_list_t* list = (tb_single_list_t*)self;
tb_assert_and_check_return(list);
// trace
tb_trace_i("single_list: size: %lu", tb_single_list_size(self));
// done
tb_char_t cstr[4096];
tb_for_all (tb_pointer_t, data, self)
{
// trace
if (list->element.cstr)
{
tb_trace_i(" %s", list->element.cstr(&list->element, data, cstr, sizeof(cstr)));
}
else
{
tb_trace_i(" %p", data);
}
}
}
#endif
tbox-1.7.6/src/tbox/container/single_list.h 0000664 0000000 0000000 00000012003 14671175054 0020721 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file single_list.h
* @ingroup container
*
*/
#ifndef TB_CONTAINER_SINGLE_LIST_H
#define TB_CONTAINER_SINGLE_LIST_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "element.h"
#include "iterator.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/*! the double list ref type
*
*
*
* list: |-----| => |-------------------------------------------------=> |------| => |------| => tail
* head last
*
* performance:
*
* insert:
* insert midd: slow
* insert head: fast
* insert tail: fast
* insert next: fast
*
* remove:
* remove midd: slow
* remove head: fast
* remove last: fast
* remove next: fast
*
* iterator:
* next: fast
*
*
*/
typedef tb_iterator_ref_t tb_single_list_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init list
*
* @param grow the grow size
* @param element the element
*
* @return the list
*/
tb_single_list_ref_t tb_single_list_init(tb_size_t grow, tb_element_t element);
/*! exit list
*
* @param list the list
*/
tb_void_t tb_single_list_exit(tb_single_list_ref_t list);
/*! clear list
*
* @param list the list
*/
tb_void_t tb_single_list_clear(tb_single_list_ref_t list);
/*! the list head item
*
* @param list the list
*
* @return the head item
*/
tb_pointer_t tb_single_list_head(tb_single_list_ref_t list);
/*! the list last item
*
* @param list the list
*
* @return the last item
*/
tb_pointer_t tb_single_list_last(tb_single_list_ref_t list);
/*! insert the next item
*
* @param list the list
* @param itor the item itor
* @param data the item data
*
* @return the item itor
*/
tb_size_t tb_single_list_insert_next(tb_single_list_ref_t list, tb_size_t itor, tb_cpointer_t data);
/*! insert the head item
*
* @param list the list
* @param data the item data
*
* @return the item itor
*/
tb_size_t tb_single_list_insert_head(tb_single_list_ref_t list, tb_cpointer_t data);
/*! insert the tail item
*
* @param list the list
* @param data the item data
*
* @return the item itor
*/
tb_size_t tb_single_list_insert_tail(tb_single_list_ref_t list, tb_cpointer_t data);
/*! replace the item
*
* @param list the list
* @param itor the item itor
* @param data the item data
*/
tb_void_t tb_single_list_replace(tb_single_list_ref_t list, tb_size_t itor, tb_cpointer_t data);
/*! replace the head item
*
* @param list the list
* @param data the item data
*/
tb_void_t tb_single_list_replace_head(tb_single_list_ref_t list, tb_cpointer_t data);
/*! replace the tail item
*
* @param list the list
* @param data the item data
*/
tb_void_t tb_single_list_replace_last(tb_single_list_ref_t list, tb_cpointer_t data);
/*! remove the next item
*
* @param list the list
* @param itor the item itor
*/
tb_void_t tb_single_list_remove_next(tb_single_list_ref_t list, tb_size_t itor);
/*! remove the head item
*
* @param list the list
*/
tb_void_t tb_single_list_remove_head(tb_single_list_ref_t list);
/*! the item count
*
* @param list the list
*
* @return the item count
*/
tb_size_t tb_single_list_size(tb_single_list_ref_t list);
/*! the item max count
*
* @param list the list
*
* @return the item max count
*/
tb_size_t tb_single_list_maxn(tb_single_list_ref_t list);
#ifdef __tb_debug__
/*! dump list
*
* @param list the list
*/
tb_void_t tb_single_list_dump(tb_single_list_ref_t list);
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/container/single_list_entry.c 0000664 0000000 0000000 00000011656 14671175054 0022152 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file single_list_entry.c
* @ingroup container
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "single_list_entry.h"
#include "../libc/libc.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* iterator implementation
*/
static tb_size_t tb_single_list_entry_itor_size(tb_iterator_ref_t iterator)
{
// check
tb_single_list_entry_head_ref_t list = tb_container_of(tb_single_list_entry_head_t, itor, iterator);
tb_assert(list);
// the size
return list->size;
}
static tb_size_t tb_single_list_entry_itor_head(tb_iterator_ref_t iterator)
{
// check
tb_single_list_entry_head_ref_t list = tb_container_of(tb_single_list_entry_head_t, itor, iterator);
tb_assert(list);
// head
return (tb_size_t)list->next;
}
static tb_size_t tb_single_list_entry_itor_last(tb_iterator_ref_t iterator)
{
// check
tb_single_list_entry_head_ref_t list = tb_container_of(tb_single_list_entry_head_t, itor, iterator);
tb_assert(list);
// last
return (tb_size_t)list->last;
}
static tb_size_t tb_single_list_entry_itor_tail(tb_iterator_ref_t iterator)
{
// tail
return (tb_size_t)0;
}
static tb_size_t tb_single_list_entry_itor_next(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_assert(itor);
// next
return (tb_size_t)((tb_single_list_entry_ref_t)itor)->next;
}
static tb_pointer_t tb_single_list_entry_itor_item(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_single_list_entry_head_ref_t list = tb_container_of(tb_single_list_entry_head_t, itor, iterator);
tb_assert(list && list->eoff < itor);
// data
return (tb_pointer_t)(itor - list->eoff);
}
static tb_void_t tb_single_list_entry_itor_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item)
{
// check
tb_single_list_entry_head_ref_t list = tb_container_of(tb_single_list_entry_head_t, itor, iterator);
tb_assert(list && list->copy);
tb_assert(list->eoff < itor && item);
// copy it
list->copy((tb_pointer_t)(itor - list->eoff), (tb_pointer_t)item);
}
static tb_void_t tb_single_list_entry_itor_nremove(tb_iterator_ref_t iterator, tb_size_t prev, tb_size_t next, tb_size_t size)
{
// check
tb_single_list_entry_head_ref_t list = tb_container_of(tb_single_list_entry_head_t, itor, iterator);
tb_assert(list && prev && next);
// no size?
tb_check_return(size);
// the entry
tb_single_list_entry_ref_t prev_entry = (tb_single_list_entry_ref_t)prev;
tb_single_list_entry_ref_t next_entry = (tb_single_list_entry_ref_t)next;
// remove entries
prev_entry->next = next_entry;
// update size
list->size -= size;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_iterator_ref_t tb_single_list_entry_itor(tb_single_list_entry_head_ref_t list)
{
// check
tb_assert_and_check_return_val(list, tb_null);
// the iterator
return &list->itor;
}
tb_void_t tb_single_list_entry_init_(tb_single_list_entry_head_ref_t list, tb_size_t entry_offset, tb_size_t entry_size, tb_entry_copy_t copy)
{
// check
tb_assert_and_check_return(list && entry_size > sizeof(tb_single_list_entry_t));
// init list
list->next = tb_null;
list->last = tb_null;
list->size = 0;
list->eoff = entry_offset;
list->copy = copy;
// init operation
static tb_iterator_op_t op =
{
tb_single_list_entry_itor_size
, tb_single_list_entry_itor_head
, tb_single_list_entry_itor_last
, tb_single_list_entry_itor_tail
, tb_null
, tb_single_list_entry_itor_next
, tb_single_list_entry_itor_item
, tb_null
, tb_single_list_entry_itor_copy
, tb_null
, tb_single_list_entry_itor_nremove
};
// init iterator
list->itor.priv = tb_null;
list->itor.step = entry_size;
list->itor.mode = TB_ITERATOR_MODE_FORWARD;
list->itor.flag = TB_ITERATOR_FLAG_ITEM_REF;
list->itor.op = &op;
}
tb_void_t tb_single_list_entry_exit(tb_single_list_entry_head_ref_t list)
{
// check
tb_assert_and_check_return(list);
// exit it
list->next = tb_null;
list->last = tb_null;
list->size = 0;
}
tbox-1.7.6/src/tbox/container/single_list_entry.h 0000664 0000000 0000000 00000027375 14671175054 0022164 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file single_list_entry.h
* @ingroup container
*
*/
#ifndef TB_CONTAINER_SINGLE_LIST_ENTRY_H
#define TB_CONTAINER_SINGLE_LIST_ENTRY_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "iterator.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/// the list entry
#define tb_single_list_entry(head, entry) ((((tb_byte_t*)(entry)) - (head)->eoff))
/*! get the list entry with zero offset
*
* @code
*
// the xxxx entry type
typedef struct __tb_xxxx_entry_t
{
// the list entry (be placed in header with zero offset)
tb_single_list_entry_t entry;
// ..
}tb_xxxx_entry_t;
*
* @endcode
*/
#define tb_single_list_entry0(entry) (entry)
/*! init the list entry
*
* @code
*
// the xxxx entry type
typedef struct __tb_xxxx_entry_t
{
// the list entry
tb_single_list_entry_t entry;
// the data
tb_size_t data;
}tb_xxxx_entry_t;
// the xxxx entry copy func
static tb_void_t tb_xxxx_entry_copy(tb_pointer_t litem, tb_pointer_t ritem)
{
// check
tb_assert(litem && ritem);
// copy it
((tb_xxxx_entry_t*)litem)->data = ((tb_xxxx_entry_t*)ritem)->data;
}
// init the list
tb_single_list_entry_head_t list;
tb_single_list_entry_init(&list, tb_xxxx_entry_t, entry, tb_xxxx_entry_copy);
* @endcode
*/
#define tb_single_list_entry_init(list, type, entry, copy) tb_single_list_entry_init_(list, tb_offsetof(type, entry), sizeof(type), copy)
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/*! the single-linked list entry type
*
*
* list: head => ... => last => null
*
*
*/
typedef struct __tb_single_list_entry_t
{
/// the next entry
struct __tb_single_list_entry_t* next;
}tb_single_list_entry_t, *tb_single_list_entry_ref_t;
/// the single-linked list entry head type
typedef struct __tb_single_list_entry_head_t
{
/// the next entry
struct __tb_single_list_entry_t* next;
/// the last entry
struct __tb_single_list_entry_t* last;
/// the list size
tb_size_t size;
/// the iterator
tb_iterator_t itor;
/// the entry offset
tb_size_t eoff;
/// the entry copy func
tb_entry_copy_t copy;
}tb_single_list_entry_head_t, *tb_single_list_entry_head_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the list iterator
*
* @param list the list
*
* @return the list iterator
*/
tb_iterator_ref_t tb_single_list_entry_itor(tb_single_list_entry_head_ref_t list);
/*! init list
*
* @param list the list
* @param entry_offset the entry offset
* @param entry_size the entry size
* @param copy the copy func of the entry for algorithm, .e.g sort
*/
tb_void_t tb_single_list_entry_init_(tb_single_list_entry_head_ref_t list, tb_size_t entry_offset, tb_size_t entry_size, tb_entry_copy_t copy);
/*! exit list
*
* @param list the list
*/
tb_void_t tb_single_list_entry_exit(tb_single_list_entry_head_ref_t list);
/*! clear list
*
* @param list the list
*/
static __tb_inline__ tb_void_t tb_single_list_entry_clear(tb_single_list_entry_head_ref_t list)
{
// check
tb_assert(list);
// clear it
list->next = tb_null;
list->last = tb_null;
list->size = 0;
}
/*! the list entry count
*
* @param list the list
*
* @return the list entry count
*/
static __tb_inline__ tb_size_t tb_single_list_entry_size(tb_single_list_entry_head_ref_t list)
{
// check
tb_assert(list);
// done
return list->size;
}
/*! the list next entry
*
* @param entry the entry
*
* @return the next entry
*/
static __tb_inline__ tb_single_list_entry_ref_t tb_single_list_entry_next(tb_single_list_entry_ref_t entry)
{
// check
tb_assert(entry);
// done
return entry->next;
}
/*! the list head entry
*
* @param list the list
*
* @return the head entry
*/
static __tb_inline__ tb_single_list_entry_ref_t tb_single_list_entry_head(tb_single_list_entry_head_ref_t list)
{
// check
tb_assert(list);
// done
return list->next;
}
/*! the list last entry
*
* @param list the list
*
* @return the last entry
*/
static __tb_inline__ tb_single_list_entry_ref_t tb_single_list_entry_last(tb_single_list_entry_head_ref_t list)
{
// check
tb_assert(list);
// done
return list->last;
}
/*! the list tail entry
*
* @param list the list
*
* @return the tail entry
*/
static __tb_inline__ tb_single_list_entry_ref_t tb_single_list_entry_tail(tb_single_list_entry_head_ref_t list)
{
return tb_null;
}
/*! the list is null?
*
* @param list the list
*
* @return tb_true or tb_false
*/
static __tb_inline__ tb_bool_t tb_single_list_entry_is_null(tb_single_list_entry_head_ref_t list)
{
// check
tb_assert(list);
// done
return !list->size;
}
/*! is the list head entry?
*
* @param list the list
* @param entry the entry
*
* @return tb_true or tb_false
*/
static __tb_inline__ tb_bool_t tb_single_list_entry_is_head(tb_single_list_entry_head_ref_t list, tb_single_list_entry_ref_t entry)
{
// check
tb_assert(list);
// done
return list->next == entry;
}
/*! is the list last entry?
*
* @param list the list
* @param entry the entry
*
* @return tb_true or tb_false
*/
static __tb_inline__ tb_bool_t tb_single_list_entry_is_last(tb_single_list_entry_head_ref_t list, tb_single_list_entry_ref_t entry)
{
// check
tb_assert(list);
// done
return list->last == entry;
}
/*! insert entry to the next
*
* @param list the list
* @param node the list node
* @param entry the inserted list entry
*/
static __tb_inline__ tb_void_t tb_single_list_entry_insert_next(tb_single_list_entry_head_ref_t list, tb_single_list_entry_ref_t node, tb_single_list_entry_ref_t entry)
{
// check
tb_assert(list && node && entry);
tb_assert(node != entry);
// update last
if (node == list->last || !list->next) list->last = entry;
// insert entry
entry->next = node->next;
node->next = entry;
// size++
list->size++;
}
/*! insert entry to the head
*
* @param list the list
* @param entry the inserted list entry
*/
static __tb_inline__ tb_void_t tb_single_list_entry_insert_head(tb_single_list_entry_head_ref_t list, tb_single_list_entry_ref_t entry)
{
// insert it
tb_single_list_entry_insert_next(list, (tb_single_list_entry_ref_t)list, entry);
}
/*! insert entry to the tail
*
* @param list the list
* @param entry the inserted list entry
*/
static __tb_inline__ tb_void_t tb_single_list_entry_insert_tail(tb_single_list_entry_head_ref_t list, tb_single_list_entry_ref_t entry)
{
// check
tb_assert(list && entry);
// insert it
if (list->last) tb_single_list_entry_insert_next(list, list->last, entry);
else tb_single_list_entry_insert_head(list, entry);
}
/*! replace the next entry
*
* @param list the list
* @param node the list node
* @param entry the new list entry
*/
static __tb_inline__ tb_void_t tb_single_list_entry_replace_next(tb_single_list_entry_head_ref_t list, tb_single_list_entry_ref_t node, tb_single_list_entry_ref_t entry)
{
// check
tb_assert(node && node->next);
tb_assert(node != entry);
// update last
if (node->next == list->last) list->last = entry;
// replace it
entry->next = node->next->next;
node->next = entry;
}
/*! replace the head entry
*
* @param list the list
* @param entry the new list entry
*/
static __tb_inline__ tb_void_t tb_single_list_entry_replace_head(tb_single_list_entry_head_ref_t list, tb_single_list_entry_ref_t entry)
{
// replace it
tb_single_list_entry_replace_next(list, (tb_single_list_entry_ref_t)list, entry);
}
/*! remove the entry (private interface)
*
* @param list the list
* @param prev the prev entry
* @param next the next entry
*/
static __tb_inline__ tb_void_t tb_single_list_entry_remove_(tb_single_list_entry_head_ref_t list, tb_single_list_entry_ref_t prev, tb_single_list_entry_ref_t next)
{
// check
tb_assert(list && list->size && prev);
// update last, prev -> last -> next (null)
if (prev->next == list->last) list->last = prev;
// remove entries
prev->next = next;
// update size
list->size--;
}
/*! remove the next entry
*
* @param list the list
* @param prev the prev entry
*/
static __tb_inline__ tb_void_t tb_single_list_entry_remove_next(tb_single_list_entry_head_ref_t list, tb_single_list_entry_ref_t prev)
{
// check
tb_assert(prev && prev->next);
// remove it
tb_single_list_entry_remove_(list, prev, prev->next->next);
}
/*! remove the head entry
*
* @param list the list
*/
static __tb_inline__ tb_void_t tb_single_list_entry_remove_head(tb_single_list_entry_head_ref_t list)
{
// check
tb_assert(list->next);
// remove it
tb_single_list_entry_remove_(list, (tb_single_list_entry_ref_t)list, list->next->next);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/container/stack.c 0000664 0000000 0000000 00000004465 14671175054 0017522 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file stack.c
* @ingroup container
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "stack.h"
#include "../libc/libc.h"
#include "../utils/utils.h"
#include "../memory/memory.h"
#include "../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_stack_ref_t tb_stack_init(tb_size_t grow, tb_element_t element)
{
return (tb_stack_ref_t)tb_vector_init(grow, element);
}
tb_void_t tb_stack_exit(tb_stack_ref_t self)
{
tb_vector_exit((tb_vector_ref_t)self);
}
tb_void_t tb_stack_clear(tb_stack_ref_t self)
{
tb_vector_clear((tb_vector_ref_t)self);
}
tb_void_t tb_stack_copy(tb_stack_ref_t self, tb_stack_ref_t copy)
{
tb_vector_copy((tb_vector_ref_t)self, copy);
}
tb_void_t tb_stack_put(tb_stack_ref_t self, tb_cpointer_t data)
{
tb_vector_insert_tail((tb_vector_ref_t)self, data);
}
tb_void_t tb_stack_pop(tb_stack_ref_t self)
{
tb_vector_remove_last((tb_vector_ref_t)self);
}
tb_pointer_t tb_stack_top(tb_stack_ref_t self)
{
return tb_vector_last((tb_vector_ref_t)self);
}
tb_pointer_t tb_stack_head(tb_stack_ref_t self)
{
return tb_vector_head((tb_vector_ref_t)self);
}
tb_pointer_t tb_stack_last(tb_stack_ref_t self)
{
return tb_vector_last((tb_vector_ref_t)self);
}
tb_size_t tb_stack_size(tb_stack_ref_t self)
{
return tb_vector_size((tb_vector_ref_t)self);
}
tb_size_t tb_stack_maxn(tb_stack_ref_t self)
{
return tb_vector_maxn((tb_vector_ref_t)self);
}
#ifdef __tb_debug__
tb_void_t tb_stack_dump(tb_stack_ref_t self)
{
tb_vector_dump((tb_vector_ref_t)self);
}
#endif
tbox-1.7.6/src/tbox/container/stack.h 0000664 0000000 0000000 00000007232 14671175054 0017522 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file stack.h
* @ingroup container
*
*/
#ifndef TB_CONTAINER_STACK_H
#define TB_CONTAINER_STACK_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "vector.h"
#include "element.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/*! the stack ref type
*
*
* stack: |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||------|
* head last tail
*
* stack: |||||||||||||||||||||||||||||||||||||||||------|
* head last tail
*
* performance:
*
* push: fast
* pop: fast
*
* iterator:
* next: fast
* prev: fast
*
*
* @note the itor of the same item is fixed
*
*/
typedef tb_vector_ref_t tb_stack_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init stack
*
* @param grow the item grow
* @param element the element
*
* @return the stack
*/
tb_stack_ref_t tb_stack_init(tb_size_t grow, tb_element_t element);
/*! exit stack
*
* @param stack the stack
*/
tb_void_t tb_stack_exit(tb_stack_ref_t stack);
/*! the stack head item
*
* @param stack the stack
*
* @return the head item
*/
tb_pointer_t tb_stack_head(tb_stack_ref_t stack);
/*! the stack last item
*
* @param stack the stack
*
* @return the last item
*/
tb_pointer_t tb_stack_last(tb_stack_ref_t stack);
/*! clear the stack
*
* @param stack the stack
*/
tb_void_t tb_stack_clear(tb_stack_ref_t stack);
/*! copy the stack
*
* @param stack the stack
* @param copy the copied stack
*/
tb_void_t tb_stack_copy(tb_stack_ref_t stack, tb_stack_ref_t copy);
/*! put the stack item
*
* @param stack the stack
* @param data the item data
*/
tb_void_t tb_stack_put(tb_stack_ref_t stack, tb_cpointer_t data);
/*! pop the stack item
*
* @param stack the stack
*/
tb_void_t tb_stack_pop(tb_stack_ref_t stack);
/*! the stack top item
*
* @param stack the stack
*
* @return the stack top item
*/
tb_pointer_t tb_stack_top(tb_stack_ref_t stack);
/*! the stack size
*
* @param stack the stack
*
* @return the stack size
*/
tb_size_t tb_stack_size(tb_stack_ref_t stack);
/*! the stack maxn
*
* @param stack the stack
*
* @return the stack maxn
*/
tb_size_t tb_stack_maxn(tb_stack_ref_t stack);
#ifdef __tb_debug__
/*! dump stack
*
* @param stack the stack
*/
tb_void_t tb_stack_dump(tb_stack_ref_t stack);
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/container/vector.c 0000664 0000000 0000000 00000044035 14671175054 0017714 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file vector.c
* @ingroup container
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "vector"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "vector.h"
#include "../libc/libc.h"
#include "../utils/utils.h"
#include "../memory/memory.h"
#include "../stream/stream.h"
#include "../platform/platform.h"
#include "../algorithm/algorithm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the vector grow
#ifdef __tb_small__
# define TB_VECTOR_GROW (128)
#else
# define TB_VECTOR_GROW (256)
#endif
// the vector maxn
#ifdef __tb_small__
# define TB_VECTOR_MAXN (1 << 16)
#else
# define TB_VECTOR_MAXN (1 << 30)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the vector type
typedef struct __tb_vector_t
{
// the itor
tb_iterator_t itor;
// the data
tb_byte_t* data;
// the size
tb_size_t size;
// the grow
tb_size_t grow;
// the maxn
tb_size_t maxn;
// the element
tb_element_t element;
}tb_vector_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_size_t tb_vector_itor_size(tb_iterator_ref_t iterator)
{
// check
tb_vector_t* vector = (tb_vector_t*)iterator;
tb_assert(vector);
// size
return vector->size;
}
static tb_size_t tb_vector_itor_head(tb_iterator_ref_t iterator)
{
// head
return 0;
}
static tb_size_t tb_vector_itor_last(tb_iterator_ref_t iterator)
{
// check
tb_vector_t* vector = (tb_vector_t*)iterator;
tb_assert(vector);
// last
return vector->size? vector->size - 1 : 0;
}
static tb_size_t tb_vector_itor_tail(tb_iterator_ref_t iterator)
{
// check
tb_vector_t* vector = (tb_vector_t*)iterator;
tb_assert(vector);
// tail
return vector->size;
}
static tb_size_t tb_vector_itor_next(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_vector_t* vector = (tb_vector_t*)iterator;
tb_assert(vector);
tb_assert_and_check_return_val(itor < vector->size, vector->size);
// next
return itor + 1;
}
static tb_size_t tb_vector_itor_prev(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_vector_t* vector = (tb_vector_t*)iterator;
tb_assert(vector);
tb_assert_and_check_return_val(itor && itor <= vector->size, 0);
// prev
return itor - 1;
}
static tb_pointer_t tb_vector_itor_item(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_vector_t* vector = (tb_vector_t*)iterator;
tb_assert_and_check_return_val(vector && itor < vector->size, tb_null);
// data
return vector->element.data(&vector->element, vector->data + itor * iterator->step);
}
static tb_void_t tb_vector_itor_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item)
{
// check
tb_vector_t* vector = (tb_vector_t*)iterator;
tb_assert(vector);
// copy
vector->element.copy(&vector->element, vector->data + itor * iterator->step, item);
}
static tb_long_t tb_vector_itor_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem)
{
// check
tb_vector_t* vector = (tb_vector_t*)iterator;
tb_assert(vector && vector->element.comp);
// comp
return vector->element.comp(&vector->element, litem, ritem);
}
static tb_void_t tb_vector_itor_remove(tb_iterator_ref_t iterator, tb_size_t itor)
{
// remove it
tb_vector_remove((tb_vector_ref_t)iterator, itor);
}
static tb_void_t tb_vector_itor_nremove(tb_iterator_ref_t iterator, tb_size_t prev, tb_size_t next, tb_size_t size)
{
// check
tb_vector_t* vector = (tb_vector_t*)iterator;
tb_assert(vector);
// remove the items
if (size) tb_vector_nremove((tb_vector_ref_t)iterator, prev != vector->size? prev + 1 : 0, size);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_vector_ref_t tb_vector_init(tb_size_t grow, tb_element_t element)
{
// check
tb_assert_and_check_return_val(element.size && element.data && element.dupl && element.repl && element.ndupl && element.nrepl, tb_null);
// done
tb_bool_t ok = tb_false;
tb_vector_t* vector = tb_null;
do
{
// using the default grow
if (!grow) grow = TB_VECTOR_GROW;
// make vector
vector = tb_malloc0_type(tb_vector_t);
tb_assert_and_check_break(vector);
// init vector
vector->size = 0;
vector->grow = grow;
vector->maxn = grow;
vector->element = element;
tb_assert_and_check_break(vector->maxn < TB_VECTOR_MAXN);
// init operation
static tb_iterator_op_t op =
{
tb_vector_itor_size
, tb_vector_itor_head
, tb_vector_itor_last
, tb_vector_itor_tail
, tb_vector_itor_prev
, tb_vector_itor_next
, tb_vector_itor_item
, tb_vector_itor_comp
, tb_vector_itor_copy
, tb_vector_itor_remove
, tb_vector_itor_nremove
};
// init iterator
vector->itor.priv = tb_null;
vector->itor.step = element.size;
vector->itor.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE | TB_ITERATOR_MODE_RACCESS | TB_ITERATOR_MODE_MUTABLE;
vector->itor.op = &op;
if (element.type == TB_ELEMENT_TYPE_MEM)
vector->itor.flag = TB_ITERATOR_FLAG_ITEM_REF;
// make data
vector->data = (tb_byte_t*)tb_nalloc0(vector->maxn, element.size);
tb_assert_and_check_break(vector->data);
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (vector) tb_vector_exit((tb_vector_ref_t)vector);
vector = tb_null;
}
return (tb_vector_ref_t)vector;
}
tb_void_t tb_vector_exit(tb_vector_ref_t self)
{
// check
tb_vector_t* vector = (tb_vector_t*)self;
tb_assert_and_check_return(vector);
// clear data
tb_vector_clear(self);
// free data
if (vector->data) tb_free(vector->data);
vector->data = tb_null;
// free it
tb_free(vector);
}
tb_void_t tb_vector_clear(tb_vector_ref_t self)
{
// check
tb_vector_t* vector = (tb_vector_t*)self;
tb_assert_and_check_return(vector);
// free data
if (vector->element.nfree)
vector->element.nfree(&vector->element, vector->data, vector->size);
// reset size
vector->size = 0;
}
tb_void_t tb_vector_copy(tb_vector_ref_t self, tb_vector_ref_t copy)
{
// check
tb_vector_t* vector = (tb_vector_t*)self;
tb_vector_t const* vector_copy = (tb_vector_t const*)copy;
tb_assert_and_check_return(vector && vector_copy);
// check element
tb_assert_and_check_return(vector->element.type == vector_copy->element.type);
tb_assert_and_check_return(vector->element.size == vector_copy->element.size);
// check itor
tb_assert_and_check_return(vector->itor.step == vector_copy->itor.step);
// null? clear it
if (!vector_copy->size)
{
tb_vector_clear(self);
return ;
}
// resize if small
if (vector->size < vector_copy->size) tb_vector_resize(self, vector_copy->size);
tb_assert_and_check_return(vector->data && vector_copy->data && vector->size >= vector_copy->size);
// copy data
if (vector_copy->data != vector->data) tb_memcpy(vector->data, vector_copy->data, vector_copy->size * vector_copy->element.size);
// copy size
vector->size = vector_copy->size;
}
tb_pointer_t tb_vector_data(tb_vector_ref_t self)
{
// check
tb_vector_t* vector = (tb_vector_t*)self;
tb_assert_and_check_return_val(vector, tb_null);
// data
return vector->data;
}
tb_pointer_t tb_vector_head(tb_vector_ref_t self)
{
return tb_iterator_item(self, tb_iterator_head(self));
}
tb_pointer_t tb_vector_last(tb_vector_ref_t self)
{
return tb_iterator_item(self, tb_iterator_last(self));
}
tb_size_t tb_vector_size(tb_vector_ref_t self)
{
// check
tb_vector_t const* vector = (tb_vector_t const*)self;
tb_assert_and_check_return_val(vector, 0);
// size
return vector->size;
}
tb_size_t tb_vector_grow(tb_vector_ref_t self)
{
// check
tb_vector_t const* vector = (tb_vector_t const*)self;
tb_assert_and_check_return_val(vector, 0);
// grow
return vector->grow;
}
tb_size_t tb_vector_maxn(tb_vector_ref_t self)
{
// check
tb_vector_t const* vector = (tb_vector_t const*)self;
tb_assert_and_check_return_val(vector, 0);
// maxn
return vector->maxn;
}
tb_bool_t tb_vector_resize(tb_vector_ref_t self, tb_size_t size)
{
// check
tb_vector_t* vector = (tb_vector_t*)self;
tb_assert_and_check_return_val(vector, tb_false);
// free items if the vector is decreased
if (size < vector->size)
{
// free data
if (vector->element.nfree)
vector->element.nfree(&vector->element, vector->data + size * vector->element.size, vector->size - size);
}
// resize buffer
if (size > vector->maxn)
{
tb_size_t maxn = tb_align4(size + vector->grow);
tb_assert_and_check_return_val(maxn < TB_VECTOR_MAXN, tb_false);
// realloc data
vector->data = (tb_byte_t*)tb_ralloc(vector->data, maxn * vector->element.size);
tb_assert_and_check_return_val(vector->data, tb_false);
// must be align by 4-bytes
tb_assert_and_check_return_val(!(((tb_size_t)(vector->data)) & 3), tb_false);
// clear the grow data
tb_memset(vector->data + vector->size * vector->element.size, 0, (maxn - vector->maxn) * vector->element.size);
// save maxn
vector->maxn = maxn;
}
// update size
vector->size = size;
return tb_true;
}
tb_void_t tb_vector_insert_prev(tb_vector_ref_t self, tb_size_t itor, tb_cpointer_t data)
{
// check
tb_vector_t* vector = (tb_vector_t*)self;
tb_assert_and_check_return(vector && vector->data && vector->element.size && itor <= vector->size);
// save size
tb_size_t osize = vector->size;
// grow a item
if (!tb_vector_resize(self, osize + 1))
{
tb_trace_d("vector resize: %u => %u failed", osize, osize + 1);
return ;
}
// move items if not at tail
if (osize != itor) tb_memmov(vector->data + (itor + 1) * vector->element.size, vector->data + itor * vector->element.size, (osize - itor) * vector->element.size);
// save data
vector->element.dupl(&vector->element, vector->data + itor * vector->element.size, data);
}
tb_void_t tb_vector_insert_next(tb_vector_ref_t self, tb_size_t itor, tb_cpointer_t data)
{
tb_vector_insert_prev(self, tb_iterator_next(self, itor), data);
}
tb_void_t tb_vector_insert_head(tb_vector_ref_t self, tb_cpointer_t data)
{
tb_vector_insert_prev(self, 0, data);
}
tb_void_t tb_vector_insert_tail(tb_vector_ref_t self, tb_cpointer_t data)
{
tb_vector_insert_prev(self, tb_vector_size(self), data);
}
tb_void_t tb_vector_ninsert_prev(tb_vector_ref_t self, tb_size_t itor, tb_cpointer_t data, tb_size_t size)
{
// check
tb_vector_t* vector = (tb_vector_t*)self;
tb_assert_and_check_return(vector && vector->data && size && itor <= vector->size);
// save size
tb_size_t osize = vector->size;
// grow size
if (!tb_vector_resize(self, osize + size))
{
tb_trace_d("vector resize: %u => %u failed", osize, osize + 1);
return ;
}
// move items if not at tail
if (osize != itor) tb_memmov(vector->data + (itor + size) * vector->element.size, vector->data + itor * vector->element.size, (osize - itor) * vector->element.size);
// duplicate data
vector->element.ndupl(&vector->element, vector->data + itor * vector->element.size, data, size);
}
tb_void_t tb_vector_ninsert_next(tb_vector_ref_t self, tb_size_t itor, tb_cpointer_t data, tb_size_t size)
{
tb_vector_ninsert_prev(self, tb_iterator_next(self, itor), data, size);
}
tb_void_t tb_vector_ninsert_head(tb_vector_ref_t self, tb_cpointer_t data, tb_size_t size)
{
tb_vector_ninsert_prev(self, 0, data, size);
}
tb_void_t tb_vector_ninsert_tail(tb_vector_ref_t self, tb_cpointer_t data, tb_size_t size)
{
tb_vector_ninsert_prev(self, tb_vector_size(self), data, size);
}
tb_void_t tb_vector_replace(tb_vector_ref_t self, tb_size_t itor, tb_cpointer_t data)
{
// check
tb_vector_t* vector = (tb_vector_t*)self;
tb_assert_and_check_return(vector && vector->data && itor <= vector->size);
// replace data
vector->element.repl(&vector->element, vector->data + itor * vector->element.size, data);
}
tb_void_t tb_vector_replace_head(tb_vector_ref_t self, tb_cpointer_t data)
{
tb_vector_replace(self, 0, data);
}
tb_void_t tb_vector_replace_last(tb_vector_ref_t self, tb_cpointer_t data)
{
// check
tb_vector_t* vector = (tb_vector_t*)self;
tb_assert_and_check_return(vector && vector->size);
// replace
tb_vector_replace(self, vector->size - 1, data);
}
tb_void_t tb_vector_nreplace(tb_vector_ref_t self, tb_size_t itor, tb_cpointer_t data, tb_size_t size)
{
// check
tb_vector_t* vector = (tb_vector_t*)self;
tb_assert_and_check_return(vector && vector->data && vector->size && itor <= vector->size && size);
// strip size
if (itor + size > vector->size) size = vector->size - itor;
// replace data
vector->element.nrepl(&vector->element, vector->data + itor * vector->element.size, data, size);
}
tb_void_t tb_vector_nreplace_head(tb_vector_ref_t self, tb_cpointer_t data, tb_size_t size)
{
tb_vector_nreplace(self, 0, data, size);
}
tb_void_t tb_vector_nreplace_last(tb_vector_ref_t self, tb_cpointer_t data, tb_size_t size)
{
// check
tb_vector_t* vector = (tb_vector_t*)self;
tb_assert_and_check_return(vector && vector->size && size);
// replace
tb_vector_nreplace(self, size >= vector->size? 0 : vector->size - size, data, size);
}
tb_void_t tb_vector_remove(tb_vector_ref_t self, tb_size_t itor)
{
// check
tb_vector_t* vector = (tb_vector_t*)self;
tb_assert_and_check_return(vector && itor < vector->size);
if (vector->size)
{
// do free
if (vector->element.free) vector->element.free(&vector->element, vector->data + itor * vector->element.size);
// move data if itor is not last
if (itor < vector->size - 1) tb_memmov(vector->data + itor * vector->element.size, vector->data + (itor + 1) * vector->element.size, (vector->size - itor - 1) * vector->element.size);
// resize
vector->size--;
}
}
tb_void_t tb_vector_remove_head(tb_vector_ref_t self)
{
tb_vector_remove(self, 0);
}
tb_void_t tb_vector_remove_last(tb_vector_ref_t self)
{
// check
tb_vector_t* vector = (tb_vector_t*)self;
tb_assert_and_check_return(vector);
if (vector->size)
{
// do free
if (vector->element.free) vector->element.free(&vector->element, vector->data + (vector->size - 1) * vector->element.size);
// resize
vector->size--;
}
}
tb_void_t tb_vector_nremove(tb_vector_ref_t self, tb_size_t itor, tb_size_t size)
{
// check
tb_vector_t* vector = (tb_vector_t*)self;
tb_assert_and_check_return(vector && size && itor < vector->size);
// clear it
if (!itor && size >= vector->size)
{
tb_vector_clear(self);
return ;
}
// strip size
if (itor + size > vector->size) size = vector->size - itor;
// compute the left size
tb_size_t left = vector->size - itor - size;
// free data
if (vector->element.nfree)
vector->element.nfree(&vector->element, vector->data + itor * vector->element.size, size);
// move the left data
if (left)
{
tb_byte_t* pd = vector->data + itor * vector->element.size;
tb_byte_t* ps = vector->data + (itor + size) * vector->element.size;
tb_memmov(pd, ps, left * vector->element.size);
}
// update size
vector->size -= size;
}
tb_void_t tb_vector_nremove_head(tb_vector_ref_t self, tb_size_t size)
{
// check
tb_vector_t* vector = (tb_vector_t*)self;
tb_assert_and_check_return(vector && size);
// clear it
if (size >= vector->size)
{
tb_vector_clear(self);
return ;
}
// remove head
tb_vector_nremove(self, 0, size);
}
tb_void_t tb_vector_nremove_last(tb_vector_ref_t self, tb_size_t size)
{
// check
tb_vector_t* vector = (tb_vector_t*)self;
tb_assert_and_check_return(vector && size);
// clear it
if (size >= vector->size)
{
tb_vector_clear(self);
return ;
}
// remove last
tb_vector_nremove(self, vector->size - size, size);
}
#ifdef __tb_debug__
tb_void_t tb_vector_dump(tb_vector_ref_t self)
{
// check
tb_vector_t* vector = (tb_vector_t*)self;
tb_assert_and_check_return(vector);
// trace
tb_trace_i("vector: size: %lu", tb_vector_size(self));
// done
tb_char_t cstr[4096];
tb_for_all (tb_pointer_t, data, self)
{
// trace
if (vector->element.cstr)
{
tb_trace_i(" %s", vector->element.cstr(&vector->element, data, cstr, sizeof(cstr)));
}
else
{
tb_trace_i(" %p", data);
}
}
}
#endif
tbox-1.7.6/src/tbox/container/vector.h 0000664 0000000 0000000 00000021617 14671175054 0017722 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file vector.h
* @ingroup container
*
*/
#ifndef TB_CONTAINER_VECTOR_H
#define TB_CONTAINER_VECTOR_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "element.h"
#include "iterator.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/*! the vector ref type
*
*
* vector: |-----|--------------------------------------------------------|------|
* head last tail
*
* performance:
*
* insert:
* insert midd: slow
* insert head: slow
* insert tail: fast
*
* ninsert:
* ninsert midd: fast
* ninsert head: fast
* ninsert tail: fast
*
* remove:
* remove midd: slow
* remove head: slow
* remove last: fast
*
* nremove:
* nremove midd: fast
* nremove head: fast
* nremove last: fast
*
* iterator:
* next: fast
* prev: fast
*
*
* @note the itor of the same item is mutable
*
*/
typedef tb_iterator_ref_t tb_vector_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init vector
*
* @code
*
// init vector
tb_vector_ref_t vector = tb_vector_init(0, tb_element_str(tb_true));
if (vector)
{
// insert elements into head
tb_vector_insert_head(vector, "hi!");
// insert elements into tail
tb_vector_insert_tail(vector, "how");
tb_vector_insert_tail(vector, "are");
tb_vector_insert_tail(vector, "you");
// dump elements
tb_for_all (tb_char_t const*, cstr, vector)
{
// trace
tb_trace_d("%s", cstr);
}
// exit vector
tb_vector_exit(vector);
}
* @endcode
*
* @param grow the item grow
* @param element the element
*
* @return the vector
*/
tb_vector_ref_t tb_vector_init(tb_size_t grow, tb_element_t element);
/*! exist vector
*
* @param vector the vector
*/
tb_void_t tb_vector_exit(tb_vector_ref_t vector);
/*! the vector data
*
* @param vector the vector
*
* @return the vector data
*/
tb_pointer_t tb_vector_data(tb_vector_ref_t vector);
/*! the vector head item
*
* @param vector the vector
*
* @return the vector head item
*/
tb_pointer_t tb_vector_head(tb_vector_ref_t vector);
/*! the vector last item
*
* @param vector the vector
*
* @return the vector last item
*/
tb_pointer_t tb_vector_last(tb_vector_ref_t vector);
/*! resize the vector
*
* @param vector the vector
* @param size the vector size
*
* @return tb_true or tb_false
*/
tb_bool_t tb_vector_resize(tb_vector_ref_t vector, tb_size_t size);
/*! clear the vector
*
* @param vector the vector
*/
tb_void_t tb_vector_clear(tb_vector_ref_t vector);
/*! copy the vector
*
* @param vector the vector
* @param copy the copied vector
*/
tb_void_t tb_vector_copy(tb_vector_ref_t vector, tb_vector_ref_t copy);
/*! insert the vector prev item
*
* @param vector the vector
* @param itor the item itor
* @param data the item data
*/
tb_void_t tb_vector_insert_prev(tb_vector_ref_t vector, tb_size_t itor, tb_cpointer_t data);
/*! insert the vector next item
*
* @param vector the vector
* @param itor the item itor
* @param data the item data
*/
tb_void_t tb_vector_insert_next(tb_vector_ref_t vector, tb_size_t itor, tb_cpointer_t data);
/*! insert the vector head item
*
* @param vector the vector
* @param data the item data
*/
tb_void_t tb_vector_insert_head(tb_vector_ref_t vector, tb_cpointer_t data);
/*! insert the vector tail item
*
* @param vector the vector
* @param data the item data
*/
tb_void_t tb_vector_insert_tail(tb_vector_ref_t vector, tb_cpointer_t data);
/*! insert the vector prev items
*
* @param vector the vector
* @param itor the item itor
* @param data the item data
* @param size the item count
*/
tb_void_t tb_vector_ninsert_prev(tb_vector_ref_t vector, tb_size_t itor, tb_cpointer_t data, tb_size_t size);
/*! insert the vector next items
*
* @param vector the vector
* @param itor the item itor
* @param data the item data
* @param size the item count
*/
tb_void_t tb_vector_ninsert_next(tb_vector_ref_t vector, tb_size_t itor, tb_cpointer_t data, tb_size_t size);
/*! insert the vector head items
*
* @param vector the vector
* @param data the item data
* @param size the item count
*/
tb_void_t tb_vector_ninsert_head(tb_vector_ref_t vector, tb_cpointer_t data, tb_size_t size);
/*! insert the vector tail items
*
* @param vector the vector
* @param data the item data
* @param size the item count
*/
tb_void_t tb_vector_ninsert_tail(tb_vector_ref_t vector, tb_cpointer_t data, tb_size_t size);
/*! replace the vector item
*
* @param vector the vector
* @param itor the item itor
* @param data the item data
*/
tb_void_t tb_vector_replace(tb_vector_ref_t vector, tb_size_t itor, tb_cpointer_t data);
/*! replace the vector head item
*
* @param vector the vector
* @param data the item data
*/
tb_void_t tb_vector_replace_head(tb_vector_ref_t vector, tb_cpointer_t data);
/*! replace the vector last item
*
* @param vector the vector
* @param data the item data
*/
tb_void_t tb_vector_replace_last(tb_vector_ref_t vector, tb_cpointer_t data);
/*! replace the vector items
*
* @param vector the vector
* @param itor the item itor
* @param data the item data
* @param size the item count
*/
tb_void_t tb_vector_nreplace(tb_vector_ref_t vector, tb_size_t itor, tb_cpointer_t data, tb_size_t size);
/*! replace the vector head items
*
* @param vector the vector
* @param data the item data
* @param size the item count
*/
tb_void_t tb_vector_nreplace_head(tb_vector_ref_t vector, tb_cpointer_t data, tb_size_t size);
/*! replace the vector last items
*
* @param vector the vector
* @param data the item data
* @param size the item count
*/
tb_void_t tb_vector_nreplace_last(tb_vector_ref_t vector, tb_cpointer_t data, tb_size_t size);
/*! remove the vector item
*
* @param vector the vector
* @param itor the item itor
*/
tb_void_t tb_vector_remove(tb_vector_ref_t vector, tb_size_t itor);
/*! remove the vector head item
*
* @param vector the vector
*/
tb_void_t tb_vector_remove_head(tb_vector_ref_t vector);
/*! remove the vector last item
*
* @param vector the vector
*/
tb_void_t tb_vector_remove_last(tb_vector_ref_t vector);
/*! remove the vector items
*
* @param vector the vector
* @param itor the item itor
* @param size the item count
*/
tb_void_t tb_vector_nremove(tb_vector_ref_t vector, tb_size_t itor, tb_size_t size);
/*! remove the vector head items
*
* @param vector the vector
* @param size the item count
*/
tb_void_t tb_vector_nremove_head(tb_vector_ref_t vector, tb_size_t size);
/*! remove the vector last items
*
* @param vector the vector
* @param size the item count
*/
tb_void_t tb_vector_nremove_last(tb_vector_ref_t vector, tb_size_t size);
/*! the vector size
*
* @param vector the vector
*
* @return the vector size
*/
tb_size_t tb_vector_size(tb_vector_ref_t vector);
/*! the vector grow
*
* @param vector the vector
*
* @return the vector grow
*/
tb_size_t tb_vector_grow(tb_vector_ref_t vector);
/*! the vector maxn
*
* @param vector the vector
*
* @return the vector maxn
*/
tb_size_t tb_vector_maxn(tb_vector_ref_t vector);
#ifdef __tb_debug__
/*! dump vector
*
* @param vector the vector
*/
tb_void_t tb_vector_dump(tb_vector_ref_t vector);
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/coroutine/ 0000775 0000000 0000000 00000000000 14671175054 0016265 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/coroutine/channel.c 0000664 0000000 0000000 00000032106 14671175054 0020043 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file channel.h
* @ingroup coroutine
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "channel"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "channel.h"
#include "coroutine.h"
#include "scheduler.h"
#include "impl/impl.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/* the channel queue type
*
* we do not use tb_circle_queue_t because it is too heavy
*/
typedef struct __tb_co_channel_queue_t
{
// the data
tb_cpointer_t* data;
// the head
tb_size_t head;
// the tail
tb_size_t tail;
// the maxn
tb_size_t maxn;
// the size
tb_size_t size;
}tb_co_channel_queue_t;
// the coroutine channel type
typedef struct __tb_co_channel_t
{
// the queue
tb_co_channel_queue_t queue;
// the free function
tb_co_channel_free_func_t free;
// the user private data
tb_cpointer_t priv;
// the waiting send coroutines
tb_single_list_entry_head_t waiting_send;
// the waiting recv coroutines
tb_single_list_entry_head_t waiting_recv;
}tb_co_channel_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_bool_t tb_co_channel_send_resume(tb_co_channel_t* channel, tb_pointer_t* pdata)
{
// check
tb_assert(channel);
// resume the first waiting send coroutine and recv data
tb_bool_t ok = tb_false;
if (tb_single_list_entry_size(&channel->waiting_send))
{
// get the next entry from head
tb_single_list_entry_ref_t entry = tb_single_list_entry_head(&channel->waiting_send);
tb_assert(entry);
// remove it from the waiting send coroutines
tb_single_list_entry_remove_head(&channel->waiting_send);
// get the waiting send coroutine
tb_coroutine_ref_t waiting = (tb_coroutine_ref_t)tb_single_list_entry(&channel->waiting_send, entry);
// resume this coroutine and recv data
tb_pointer_t data = tb_coroutine_resume(waiting, tb_null);
// save data
if (pdata) *pdata = data;
// ok
ok = tb_true;
}
// ok?
return ok;
}
static tb_void_t tb_co_channel_recv_resume(tb_co_channel_t* channel)
{
// check
tb_assert(channel);
// resume the first waiting recv coroutine
if (tb_single_list_entry_size(&channel->waiting_recv))
{
// get the next entry from head
tb_single_list_entry_ref_t entry = tb_single_list_entry_head(&channel->waiting_recv);
tb_assert(entry);
// remove it from the waiting recv coroutines
tb_single_list_entry_remove_head(&channel->waiting_recv);
// get the waiting recv coroutine
tb_coroutine_ref_t waiting = (tb_coroutine_ref_t)tb_single_list_entry(&channel->waiting_recv, entry);
// resume this coroutine
tb_coroutine_resume(waiting, tb_null);
}
}
static tb_void_t tb_co_channel_send_suspend(tb_co_channel_t* channel, tb_cpointer_t data)
{
// check
tb_assert(channel);
// get the running coroutine
tb_coroutine_t* running = (tb_coroutine_t*)tb_coroutine_self();
tb_assert(running);
// save this coroutine to the waiting send coroutines
tb_single_list_entry_insert_tail(&channel->waiting_send, &running->rs.single_entry);
// send data and wait it
tb_coroutine_suspend(data);
}
static tb_void_t tb_co_channel_recv_suspend(tb_co_channel_t* channel)
{
// check
tb_assert(channel);
// get the running coroutine
tb_coroutine_t* running = (tb_coroutine_t*)tb_coroutine_self();
tb_assert(running);
// save this coroutine to the waiting recv coroutines
tb_single_list_entry_insert_tail(&channel->waiting_recv, &running->rs.single_entry);
// wait data
tb_coroutine_suspend(tb_null);
}
static tb_void_t tb_co_channel_send_buffer(tb_co_channel_t* channel, tb_cpointer_t data)
{
// check
tb_assert_and_check_return(channel && channel->queue.data);
// done
do
{
// put data into queue if be not full
if (channel->queue.size + 1 < channel->queue.maxn)
{
// trace
tb_trace_d("send[%p]: put data(%p)", tb_coroutine_self(), data);
// put data
channel->queue.data[channel->queue.tail] = data;
channel->queue.tail = (channel->queue.tail + 1) % channel->queue.maxn;
channel->queue.size++;
// notify to recv data
tb_co_channel_recv_resume(channel);
// send ok
break;
}
// wait it if be full
else
{
// trace
tb_trace_d("send[%p]: wait ..", tb_coroutine_self());
// wait send
tb_co_channel_send_suspend(channel, tb_null);
// trace
tb_trace_d("send[%p]: wait ok", tb_coroutine_self());
}
} while (1);
// trace
tb_trace_d("send[%p]: ok", tb_coroutine_self());
}
static tb_pointer_t tb_co_channel_recv_buffer(tb_co_channel_t* channel)
{
// check
tb_assert_and_check_return_val(channel && channel->queue.data, tb_null);
// done
tb_pointer_t data = tb_null;
do
{
// recv data from channel if be not null
if (channel->queue.size)
{
// get data
data = (tb_pointer_t)channel->queue.data[channel->queue.head];
// pop data
channel->queue.head = (channel->queue.head + 1) % channel->queue.maxn;
channel->queue.size--;
// trace
tb_trace_d("recv[%p]: get data(%p)", tb_coroutine_self(), data);
// notify to send data
tb_co_channel_send_resume(channel, tb_null);
// recv ok
break;
}
// wait it if be null
else
{
// trace
tb_trace_d("recv[%p]: wait ..", tb_coroutine_self());
// wait recv
tb_co_channel_recv_suspend(channel);
// trace
tb_trace_d("recv[%p]: wait ok", tb_coroutine_self());
}
} while (1);
// trace
tb_trace_d("recv[%p]: ok", tb_coroutine_self());
// get data
return data;
}
static tb_bool_t tb_co_channel_send_buffer_try(tb_co_channel_t* channel, tb_cpointer_t data)
{
// check
tb_assert_and_check_return_val(channel && channel->queue.data, tb_false);
// put data into queue if be not full
if (channel->queue.size + 1 < channel->queue.maxn)
{
// trace
tb_trace_d("send[%p]: put data(%p)", tb_coroutine_self(), data);
// put data
channel->queue.data[channel->queue.tail] = data;
channel->queue.tail = (channel->queue.tail + 1) % channel->queue.maxn;
channel->queue.size++;
// notify to recv data
tb_co_channel_recv_resume(channel);
// send ok
return tb_true;
}
// failed
return tb_false;
}
static tb_bool_t tb_co_channel_recv_buffer_try(tb_co_channel_t* channel, tb_pointer_t* pdata)
{
// check
tb_assert_and_check_return_val(channel && channel->queue.data && pdata, tb_false);
// recv data from channel if be not null
if (channel->queue.size)
{
// get data
*pdata = (tb_pointer_t)channel->queue.data[channel->queue.head];
// pop data
channel->queue.head = (channel->queue.head + 1) % channel->queue.maxn;
channel->queue.size--;
// trace
tb_trace_d("recv[%p]: get data(%p)", tb_coroutine_self(), *pdata);
// notify to send data
tb_co_channel_send_resume(channel, tb_null);
// recv ok
return tb_true;
}
// failed
return tb_false;
}
static tb_void_t tb_co_channel_send_buffer0(tb_co_channel_t* channel, tb_cpointer_t data)
{
// check
tb_assert(channel);
// resume one waiting recv coroutine
tb_co_channel_recv_resume(channel);
// send data and wait it
tb_co_channel_send_suspend(channel, data);
}
static tb_pointer_t tb_co_channel_recv_buffer0(tb_co_channel_t* channel)
{
// check
tb_assert(channel);
// done
tb_pointer_t data = tb_null;
do
{
// resume the first waiting send coroutine and recv data
if (tb_co_channel_send_resume(channel, &data))
{
// recv ok
break;
}
// no data?
else
{
// wait data
tb_co_channel_recv_suspend(channel);
}
} while (1);
// ok?
return data;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_co_channel_ref_t tb_co_channel_init(tb_size_t size, tb_co_channel_free_func_t free, tb_cpointer_t priv)
{
// done
tb_bool_t ok = tb_false;
tb_co_channel_t* channel = tb_null;
do
{
// make channel
channel = tb_malloc0_type(tb_co_channel_t);
tb_assert_and_check_break(channel);
// init waiting send coroutines
tb_single_list_entry_init(&channel->waiting_send, tb_coroutine_t, rs.single_entry, tb_null);
// init waiting recv coroutines
tb_single_list_entry_init(&channel->waiting_recv, tb_coroutine_t, rs.single_entry, tb_null);
// init free function and data
channel->free = free;
channel->priv = priv;
// with buffer?
if (size)
{
// init maxn, + tail
channel->queue.maxn = size + 1;
// make data
channel->queue.data = tb_nalloc_type(channel->queue.maxn, tb_cpointer_t);
tb_assert_and_check_break(channel->queue.data);
}
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (channel) tb_co_channel_exit((tb_co_channel_ref_t)channel);
channel = tb_null;
}
// ok?
return (tb_co_channel_ref_t)channel;
}
tb_void_t tb_co_channel_exit(tb_co_channel_ref_t self)
{
// check
tb_co_channel_t* channel = (tb_co_channel_t*)self;
tb_assert_and_check_return(channel);
// exit queue
if (channel->queue.data)
{
// free data
if (channel->free)
{
tb_size_t head = channel->queue.head;
tb_size_t maxn = channel->queue.maxn;
tb_size_t size = channel->queue.size;
while (size--)
{
channel->free((tb_pointer_t)channel->queue.data[head], channel->priv);
head = (head + 1) % maxn;
}
}
// free it
tb_free(channel->queue.data);
}
channel->queue.data = tb_null;
channel->queue.size = 0;
// check waiting coroutines
tb_assert(!tb_single_list_entry_size(&channel->waiting_send));
tb_assert(!tb_single_list_entry_size(&channel->waiting_recv));
// exit waiting coroutines
tb_single_list_entry_exit(&channel->waiting_send);
tb_single_list_entry_exit(&channel->waiting_recv);
// exit the channel
tb_free(channel);
}
tb_void_t tb_co_channel_send(tb_co_channel_ref_t self, tb_cpointer_t data)
{
// check
tb_co_channel_t* channel = (tb_co_channel_t*)self;
tb_assert_and_check_return(channel);
// send it
if (channel->queue.data) tb_co_channel_send_buffer(channel, data);
else tb_co_channel_send_buffer0(channel, data);
}
tb_pointer_t tb_co_channel_recv(tb_co_channel_ref_t self)
{
// check
tb_co_channel_t* channel = (tb_co_channel_t*)self;
tb_assert_and_check_return_val(channel, tb_null);
// recv it
return channel->queue.data? tb_co_channel_recv_buffer(channel) : tb_co_channel_recv_buffer0(channel);
}
tb_bool_t tb_co_channel_send_try(tb_co_channel_ref_t self, tb_cpointer_t data)
{
// check
tb_co_channel_t* channel = (tb_co_channel_t*)self;
tb_assert_and_check_return_val(channel, tb_false);
// try sending it
return channel->queue.data? tb_co_channel_send_buffer_try(channel, data) : tb_false;
}
tb_bool_t tb_co_channel_recv_try(tb_co_channel_ref_t self, tb_pointer_t* pdata)
{
// check
tb_co_channel_t* channel = (tb_co_channel_t*)self;
tb_assert_and_check_return_val(channel && pdata, tb_false);
// try recving it
return channel->queue.data? tb_co_channel_recv_buffer_try(channel, pdata) : tb_false;
}
tbox-1.7.6/src/tbox/coroutine/channel.h 0000664 0000000 0000000 00000006457 14671175054 0020062 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file channel.h
* @ingroup coroutine
*
*/
#ifndef TB_COROUTINE_CHANNEL_H
#define TB_COROUTINE_CHANNEL_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../container/container.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the coroutine channel ref type
typedef __tb_typeref__(co_channel);
/*! the free function type
*
* @param data the channel data
* @param priv the user private data
*/
typedef tb_void_t (*tb_co_channel_free_func_t)(tb_pointer_t data, tb_cpointer_t priv);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init channel
*
* @param size the buffer size, 0: no buffer
* @param free the free function
* @param priv the user private data
*
* @return the channel
*/
tb_co_channel_ref_t tb_co_channel_init(tb_size_t size, tb_co_channel_free_func_t free, tb_cpointer_t priv);
/*! exit channel
*
* @param channel the channel
*/
tb_void_t tb_co_channel_exit(tb_co_channel_ref_t channel);
/*! send data into channel
*
* the current coroutine will be suspend if this channel is full
*
* @param channel the channel
* @param data the channel data
*/
tb_void_t tb_co_channel_send(tb_co_channel_ref_t channel, tb_cpointer_t data);
/*! recv data from channel
*
* the current coroutine will be suspend if no data
*
* @param channel the channel
*
* @return the channel data
*/
tb_pointer_t tb_co_channel_recv(tb_co_channel_ref_t channel);
/*! try sending data into channel only with buffer
*
* the current coroutine will be suspend if this channel is full
*
* @param channel the channel
* @param data the channel data
*
* @return tb_true or tb_false
*/
tb_bool_t tb_co_channel_send_try(tb_co_channel_ref_t channel, tb_cpointer_t data);
/*! try recving data from channel only with buffer
*
* the current coroutine will be suspend if no data
*
* @param channel the channel
* @param pdata the channel data pointer
*
* @return tb_true or tb_false
*/
tb_bool_t tb_co_channel_recv_try(tb_co_channel_ref_t channel, tb_pointer_t* pdata);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/coroutine/coroutine.c 0000664 0000000 0000000 00000007502 14671175054 0020444 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file coroutine.h
* @ingroup coroutine
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "coroutine"
#define TB_TRACE_MODULE_DEBUG (1)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "coroutine.h"
#include "scheduler.h"
#include "impl/impl.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_coroutine_start(tb_co_scheduler_ref_t scheduler, tb_coroutine_func_t func, tb_cpointer_t priv, tb_size_t stacksize)
{
// check
tb_assert_and_check_return_val(func, tb_false);
// start it
return tb_co_scheduler_start((tb_co_scheduler_t*)scheduler, func, priv, stacksize);
}
tb_bool_t tb_coroutine_yield()
{
// get current scheduler
tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self();
// yield the current coroutine
return scheduler? tb_co_scheduler_yield(scheduler) : tb_false;
}
tb_pointer_t tb_coroutine_resume(tb_coroutine_ref_t coroutine, tb_cpointer_t priv)
{
// get current scheduler
tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self();
// resume the given coroutine
return scheduler? tb_co_scheduler_resume(scheduler, (tb_coroutine_t*)coroutine, priv) : tb_null;
}
tb_pointer_t tb_coroutine_suspend(tb_cpointer_t priv)
{
// get current scheduler
tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self();
// suspend the current coroutine
return scheduler? tb_co_scheduler_suspend(scheduler, priv) : tb_null;
}
tb_pointer_t tb_coroutine_sleep(tb_long_t interval)
{
// get current scheduler
tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self();
// sleep the current coroutine
return scheduler? tb_co_scheduler_sleep(scheduler, interval) : tb_null;
}
tb_long_t tb_coroutine_waitio(tb_poller_object_ref_t object, tb_size_t events, tb_long_t timeout)
{
// get current scheduler
tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self();
// wait events
return scheduler? tb_co_scheduler_wait(scheduler, object, events, timeout) : -1;
}
tb_long_t tb_coroutine_waitproc(tb_poller_object_ref_t object, tb_long_t* pstatus, tb_long_t timeout)
{
// get current scheduler
tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self();
// wait process status
return scheduler? tb_co_scheduler_wait_proc(scheduler, object, pstatus, timeout) : -1;
}
tb_long_t tb_coroutine_waitfs(tb_poller_object_ref_t object, tb_fwatcher_event_t* pevent, tb_long_t timeout)
{
// get current scheduler
tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self();
// wait fwatcher event
return scheduler? tb_co_scheduler_wait_fwatcher(scheduler, object, pevent, timeout) : -1;
}
tb_coroutine_ref_t tb_coroutine_self()
{
// get coroutine
tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self();
// get running coroutine
return scheduler? (tb_coroutine_ref_t)tb_co_scheduler_running(scheduler) : tb_null;
}
tbox-1.7.6/src/tbox/coroutine/coroutine.h 0000664 0000000 0000000 00000010574 14671175054 0020454 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file coroutine.h
* @defgroup coroutine
*
*/
#ifndef TB_COROUTINE_H
#define TB_COROUTINE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "lock.h"
#include "channel.h"
#include "semaphore.h"
#include "scheduler.h"
#include "../platform/poller.h"
#include "../platform/fwatcher.h"
#include "stackless/stackless.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the coroutine ref type
typedef __tb_typeref__(coroutine);
/// the coroutine function type
typedef tb_void_t (*tb_coroutine_func_t)(tb_cpointer_t priv);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! start coroutine
*
* @param scheduler the scheduler, uses the current scheduler if be null
* @param func the coroutine function
* @param priv the passed user private data as the argument of function
* @param stacksize the stack size
*
* @return tb_true or tb_false
*/
tb_bool_t tb_coroutine_start(tb_co_scheduler_ref_t scheduler, tb_coroutine_func_t func, tb_cpointer_t priv, tb_size_t stacksize);
/*! yield the current coroutine
*
* @return tb_true(yield ok) or tb_false(yield failed, no more coroutines)
*/
tb_bool_t tb_coroutine_yield(tb_noarg_t);
/*! resume the given coroutine (suspended)
*
* @param coroutine the suspended coroutine
* @param priv the user private data as the return value of suspend() or sleep()
*
* @return the user private data from suspend(priv)
*/
tb_pointer_t tb_coroutine_resume(tb_coroutine_ref_t coroutine, tb_cpointer_t priv);
/*! suspend the current coroutine
*
* @param priv the user private data as the return value of resume()
*
* @return the user private data from resume(priv)
*/
tb_pointer_t tb_coroutine_suspend(tb_cpointer_t priv);
/*! sleep some times (ms)
*
* @param interval the interval (ms), infinity: -1
*
* @return the user private data from resume(priv)
*/
tb_pointer_t tb_coroutine_sleep(tb_long_t interval);
/*! wait io events
*
* @param object the poller object
* @param events the waited events, will remove this object from io scheduler if be TB_SOCKET_EVENT_NONE
* @param timeout the timeout, infinity: -1
*
* @return > 0: the events, 0: timeout, -1: failed
*/
tb_long_t tb_coroutine_waitio(tb_poller_object_ref_t object, tb_size_t events, tb_long_t timeout);
/*! wait process status
*
* @param object the poller object
* @param pstatus the process exited status pointer, maybe null
* @param timeout the timeout, infinity: -1
*
* @return > 0: process exited, 0: timeout, -1: failed
*/
tb_long_t tb_coroutine_waitproc(tb_poller_object_ref_t object, tb_long_t* pstatus, tb_long_t timeout);
/*! wait fwatcher event
*
* @param object the poller object
* @param pevent the fwatcher event pointer
* @param timeout the timeout, infinity: -1
*
* @return > 0: has event, 0: timeout, -1: failed
*/
tb_long_t tb_coroutine_waitfs(tb_poller_object_ref_t object, tb_fwatcher_event_t* pevent, tb_long_t timeout);
/*! get the current coroutine
*
* @return the current coroutine
*/
tb_coroutine_ref_t tb_coroutine_self(tb_noarg_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/coroutine/impl/ 0000775 0000000 0000000 00000000000 14671175054 0017226 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/coroutine/impl/coroutine.c 0000664 0000000 0000000 00000021104 14671175054 0021377 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file coroutine.h
* @ingroup coroutine
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "coroutine"
#define TB_TRACE_MODULE_DEBUG (1)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "coroutine.h"
#include "scheduler.h"
#include "../../memory/memory.h"
#if defined(__tb_valgrind__) && defined(TB_CONFIG_VALGRIND_HAVE_VALGRIND_STACK_REGISTER)
# include "valgrind/valgrind.h"
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the stack guard magic
#define TB_COROUTINE_STACK_GUARD (0xbeef)
// the default stack size, @note we will allocate it from large/virtual allocator if size >= TB_VIRTUAL_MEMORY_DATA_MINN
#define TB_COROUTINE_STACK_DEFSIZE TB_VIRTUAL_MEMORY_DATA_MINN
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_coroutine_entry(tb_context_from_t from)
{
// get the from-coroutine
tb_coroutine_t* coroutine_from = (tb_coroutine_t*)from.priv;
tb_assert(coroutine_from && from.context);
// update the context
coroutine_from->context = from.context;
tb_assert(from.context);
// get the current coroutine
tb_coroutine_t* coroutine = (tb_coroutine_t*)tb_coroutine_self();
tb_assert(coroutine);
// trace
tb_trace_d("entry: %p stack: %p - %p from coroutine(%p)", coroutine, coroutine->stackbase - coroutine->stacksize, coroutine->stackbase, coroutine_from);
#ifdef __tb_debug__
// check it
tb_coroutine_check(coroutine);
#endif
// get function and private data
tb_coroutine_func_t func = coroutine->rs.func.func;
tb_cpointer_t priv = coroutine->rs.func.priv;
tb_assert(func);
// reset rs data first for waiting io
tb_memset(&coroutine->rs, 0, sizeof(coroutine->rs));
// call the coroutine function
func(priv);
// finish the current coroutine and switch to the other coroutine
tb_co_scheduler_finish((tb_co_scheduler_t*)tb_co_scheduler_self());
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_coroutine_t* tb_coroutine_init(tb_co_scheduler_ref_t scheduler, tb_coroutine_func_t func, tb_cpointer_t priv, tb_size_t stacksize)
{
// check
tb_assert_and_check_return_val(scheduler && func, tb_null);
// done
tb_bool_t ok = tb_false;
tb_coroutine_t* coroutine = tb_null;
do
{
// init stack size
if (!stacksize) stacksize = TB_COROUTINE_STACK_DEFSIZE;
#ifdef __tb_debug__
// patch debug stack size for (assert, trace ..)
stacksize <<= 1;
#endif
/* make coroutine
*
* TODO:
*
* - segment stack
*
* -----------------------------------------------
* | coroutine | guard | ... stacksize ... | guard |
* -----------------------------------------------
*/
coroutine = (tb_coroutine_t*)tb_malloc_bytes(sizeof(tb_coroutine_t) + stacksize + sizeof(tb_uint16_t));
tb_assert_and_check_break(coroutine);
// save scheduler
coroutine->scheduler = scheduler;
// init stack
coroutine->stackbase = (tb_byte_t*)&(coroutine[1]) + stacksize;
coroutine->stacksize = stacksize;
// fill guard
coroutine->guard = TB_COROUTINE_STACK_GUARD;
tb_bits_set_u16_ne(coroutine->stackbase, TB_COROUTINE_STACK_GUARD);
// init function and user private data
coroutine->rs.func.func = func;
coroutine->rs.func.priv = priv;
// make context
coroutine->context = tb_context_make(coroutine->stackbase - stacksize, stacksize, tb_coroutine_entry);
tb_assert_and_check_break(coroutine->context);
#if defined(__tb_valgrind__) && defined(TB_CONFIG_VALGRIND_HAVE_VALGRIND_STACK_REGISTER)
// register valgrind stack
coroutine->valgrind_stack_id = VALGRIND_STACK_REGISTER(coroutine->stackbase - stacksize, coroutine->stackbase);
#endif
#ifdef __tb_debug__
// check it
tb_coroutine_check(coroutine);
#endif
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (coroutine) tb_coroutine_exit(coroutine);
coroutine = tb_null;
}
// trace
tb_trace_d("init %p", coroutine);
// ok?
return coroutine;
}
tb_coroutine_t* tb_coroutine_reinit(tb_coroutine_t* coroutine, tb_coroutine_func_t func, tb_cpointer_t priv, tb_size_t stacksize)
{
// check
tb_assert_and_check_return_val(coroutine && func, tb_null);
// done
tb_bool_t ok = tb_false;
do
{
// init stack size
if (!stacksize) stacksize = TB_COROUTINE_STACK_DEFSIZE;
#ifdef __tb_debug__
// patch debug stack size for (assert, trace ..)
stacksize <<= 1;
// check coroutine
tb_coroutine_check(coroutine);
#endif
#if defined(__tb_valgrind__) && defined(TB_CONFIG_VALGRIND_HAVE_VALGRIND_STACK_REGISTER)
// deregister valgrind stack
VALGRIND_STACK_DEREGISTER(coroutine->valgrind_stack_id);
#endif
// remake coroutine
if (stacksize > coroutine->stacksize)
coroutine = (tb_coroutine_t*)tb_ralloc_bytes(coroutine, sizeof(tb_coroutine_t) + stacksize + sizeof(tb_uint16_t));
else stacksize = coroutine->stacksize;
tb_assert_and_check_break(coroutine && coroutine->scheduler);
// init stack
coroutine->stackbase = (tb_byte_t*)&(coroutine[1]) + stacksize;
coroutine->stacksize = stacksize;
// fill guard
coroutine->guard = TB_COROUTINE_STACK_GUARD;
tb_bits_set_u16_ne(coroutine->stackbase, TB_COROUTINE_STACK_GUARD);
// init function and user private data
coroutine->rs.func.func = func;
coroutine->rs.func.priv = priv;
// make context
coroutine->context = tb_context_make(coroutine->stackbase - stacksize, stacksize, tb_coroutine_entry);
tb_assert_and_check_break(coroutine->context);
#if defined(__tb_valgrind__) && defined(TB_CONFIG_VALGRIND_HAVE_VALGRIND_STACK_REGISTER)
// re-register valgrind stack
coroutine->valgrind_stack_id = VALGRIND_STACK_REGISTER(coroutine->stackbase - stacksize, coroutine->stackbase);
#endif
// ok
ok = tb_true;
} while (0);
// failed? reset it
if (!ok) coroutine = tb_null;
// trace
tb_trace_d("reinit %p", coroutine);
// ok?
return coroutine;
}
tb_void_t tb_coroutine_exit(tb_coroutine_t* coroutine)
{
// check
tb_assert_and_check_return(coroutine);
// trace
tb_trace_d("exit: %p", coroutine);
#ifdef __tb_debug__
// check it
tb_coroutine_check(coroutine);
#endif
#if defined(__tb_valgrind__) && defined(TB_CONFIG_VALGRIND_HAVE_VALGRIND_STACK_REGISTER)
// deregister valgrind stack
VALGRIND_STACK_DEREGISTER(coroutine->valgrind_stack_id);
#endif
// exit it
tb_free(coroutine);
}
#ifdef __tb_debug__
tb_void_t tb_coroutine_check(tb_coroutine_t* coroutine)
{
// check
tb_assert(coroutine);
// this coroutine is original for scheduler?
tb_check_return(!tb_coroutine_is_original(coroutine));
// check stack underflow
if (coroutine->guard != TB_COROUTINE_STACK_GUARD)
{
// trace
tb_trace_e("this coroutine stack is underflow!");
// dump stack
tb_dump_data((tb_byte_t const*)coroutine, sizeof(tb_coroutine_t));
// abort
tb_abort();
}
// check stack overflow
if (tb_bits_get_u16_ne(coroutine->stackbase) != TB_COROUTINE_STACK_GUARD)
{
// trace
tb_trace_e("this coroutine stack is overflow!");
// dump stack
tb_dump_data(coroutine->stackbase - 64, 64 + 2);
// abort
tb_abort();
}
// check
tb_assert(coroutine->context);
}
#endif
tbox-1.7.6/src/tbox/coroutine/impl/coroutine.h 0000664 0000000 0000000 00000011775 14671175054 0021421 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file coroutine.h
* @ingroup coroutine
*
*/
#ifndef TB_COROUTINE_IMPL_COROUTINE_H
#define TB_COROUTINE_IMPL_COROUTINE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// get scheduler
#define tb_coroutine_scheduler(coroutine) ((coroutine)->scheduler)
// is original?
#define tb_coroutine_is_original(coroutine) ((coroutine)->scheduler == (tb_co_scheduler_ref_t)(coroutine))
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the coroutine function type
typedef struct __tb_coroutine_rs_func_t
{
// the function
tb_coroutine_func_t func;
// the user private data as the argument of function
tb_cpointer_t priv;
}tb_coroutine_rs_func_t;
// the coroutine wait type
typedef struct __tb_coroutine_rs_wait_t
{
// the waited poller object
tb_poller_object_t object;
// the timer task pointer for ltimer or timer
tb_cpointer_t task;
// the object event, (process status or fwatcher event)
tb_long_t object_event;
// has pending process status?
tb_uint16_t object_pending : 1;
// waiting process?
tb_uint16_t object_waiting : 1;
// is ltimer?
tb_uint16_t is_ltimer : 1;
}tb_coroutine_rs_wait_t;
// the coroutine type
typedef struct __tb_coroutine_t
{
/* the list entry for ready, suspend and dead lists
*
* be placed in the head for optimization
*/
tb_list_entry_t entry;
// the scheduler
tb_co_scheduler_ref_t scheduler;
// the context
tb_context_ref_t context;
// the stack base (top)
tb_byte_t* stackbase;
// the stack size
tb_size_t stacksize;
// the passed user private data between priv = resume(priv) and priv = suspend(priv)
tb_cpointer_t rs_priv;
// the passed private data between resume() and suspend()
union
{
// the function
tb_coroutine_rs_func_t func;
// the arguments for wait()
tb_coroutine_rs_wait_t wait;
// the single entry
tb_single_list_entry_t single_entry;
} rs;
// the guard
tb_uint16_t guard;
#if defined(__tb_valgrind__) && defined(TB_CONFIG_VALGRIND_HAVE_VALGRIND_STACK_REGISTER)
// the valgrind stack id, helo valgrind to understand coroutine
tb_uint_t valgrind_stack_id;
#endif
}tb_coroutine_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* init coroutine
*
* @param scheduler the scheduler
* @param func the coroutine function
* @param priv the passed user private data as the argument of function
* @param stacksize the stack size, uses the default stack size if be zero
*
* @return the coroutine
*/
tb_coroutine_t* tb_coroutine_init(tb_co_scheduler_ref_t scheduler, tb_coroutine_func_t func, tb_cpointer_t priv, tb_size_t stacksize);
/* reinit the given coroutine
*
* @param coroutine the coroutine
* @param func the coroutine function
* @param priv the passed user private data as the argument of function
* @param stacksize the stack size, uses the default stack size if be zero
*
* @return the coroutine
*/
tb_coroutine_t* tb_coroutine_reinit(tb_coroutine_t* coroutine, tb_coroutine_func_t func, tb_cpointer_t priv, tb_size_t stacksize);
/* exit coroutine
*
* @param coroutine the coroutine
*/
tb_void_t tb_coroutine_exit(tb_coroutine_t* coroutine);
#ifdef __tb_debug__
/* check coroutine
*
* @param coroutine the coroutine
*/
tb_void_t tb_coroutine_check(tb_coroutine_t* coroutine);
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/coroutine/impl/impl.h 0000664 0000000 0000000 00000001743 14671175054 0020345 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file impl.h
*
*/
#ifndef TB_COROUTINE_IMPL_H
#define TB_COROUTINE_IMPL_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "coroutine.h"
#include "scheduler.h"
#include "scheduler_io.h"
#include "stackless/stackless.h"
#endif
tbox-1.7.6/src/tbox/coroutine/impl/prefix.h 0000664 0000000 0000000 00000002060 14671175054 0020672 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_COROUTINE_IMPL_PREFIX_H
#define TB_COROUTINE_IMPL_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#include "../coroutine.h"
#include "../../libc/libc.h"
#include "../../utils/utils.h"
#include "../../platform/platform.h"
#include "../../container/container.h"
#endif
tbox-1.7.6/src/tbox/coroutine/impl/scheduler.c 0000664 0000000 0000000 00000032127 14671175054 0021355 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file scheduler.c
* @ingroup coroutine
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "scheduler"
#define TB_TRACE_MODULE_DEBUG (1)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "scheduler.h"
#include "coroutine.h"
#include "scheduler_io.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the dead cache maximum count
#ifdef __tb_small__
# define TB_SCHEDULER_DEAD_CACHE_MAXN (64)
#else
# define TB_SCHEDULER_DEAD_CACHE_MAXN (256)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_void_t tb_co_scheduler_make_dead(tb_co_scheduler_t* scheduler, tb_coroutine_t* coroutine)
{
// check
tb_assert(scheduler && coroutine);
// cannot be original coroutine
tb_assert(!tb_coroutine_is_original(coroutine));
// remove this coroutine from the ready coroutines
tb_list_entry_remove(&scheduler->coroutines_ready, (tb_list_entry_ref_t)coroutine);
// append this coroutine to dead coroutines
tb_list_entry_insert_tail(&scheduler->coroutines_dead, (tb_list_entry_ref_t)coroutine);
}
static tb_void_t tb_co_scheduler_make_ready(tb_co_scheduler_t* scheduler, tb_coroutine_t* coroutine)
{
// check
tb_assert(scheduler && coroutine);
// insert this coroutine to ready coroutines
if (__tb_unlikely__(tb_coroutine_is_original(scheduler->running)))
{
// .. last -> coroutine(inserted)
tb_list_entry_insert_tail(&scheduler->coroutines_ready, (tb_list_entry_ref_t)coroutine);
}
else
{
// .. -> coroutine(inserted) -> running -> ..
tb_list_entry_insert_prev(&scheduler->coroutines_ready, (tb_list_entry_ref_t)scheduler->running, (tb_list_entry_ref_t)coroutine);
}
}
static tb_void_t tb_co_scheduler_make_suspend(tb_co_scheduler_t* scheduler, tb_coroutine_t* coroutine)
{
// check
tb_assert(scheduler && coroutine);
// cannot be original coroutine
tb_assert(!tb_coroutine_is_original(coroutine));
// remove this coroutine from the ready coroutines
tb_list_entry_remove(&scheduler->coroutines_ready, (tb_list_entry_ref_t)coroutine);
// append this coroutine to suspend coroutines
tb_list_entry_insert_tail(&scheduler->coroutines_suspend, (tb_list_entry_ref_t)coroutine);
}
static __tb_inline__ tb_coroutine_t* tb_co_scheduler_next_ready(tb_co_scheduler_t* scheduler)
{
// check
tb_assert(scheduler && scheduler->running && tb_list_entry_size(&scheduler->coroutines_ready));
// get the next entry
tb_list_entry_ref_t entry_next = tb_list_entry_next((tb_list_entry_ref_t)scheduler->running);
tb_assert(entry_next);
// is list header? skip it and get the first entry
if (entry_next == (tb_list_entry_ref_t)&scheduler->coroutines_ready)
entry_next = tb_list_entry_next(entry_next);
// get the next ready coroutine
return (tb_coroutine_t*)tb_list_entry0(entry_next);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_co_scheduler_start(tb_co_scheduler_t* scheduler, tb_coroutine_func_t func, tb_cpointer_t priv, tb_size_t stacksize)
{
// check
tb_assert(func);
// done
tb_bool_t ok = tb_false;
tb_coroutine_t* coroutine = tb_null;
do
{
// trace
tb_trace_d("start ..");
// uses the current scheduler if be null
if (!scheduler) scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self();
tb_assert_and_check_break(scheduler);
// have been stopped? do not continue to start new coroutines
tb_check_break(!scheduler->stopped);
// reuses dead coroutines in init function
if (tb_list_entry_size(&scheduler->coroutines_dead))
{
// get the next entry from head
tb_list_entry_ref_t entry = tb_list_entry_head(&scheduler->coroutines_dead);
tb_assert_and_check_break(entry);
// remove it from the ready coroutines
tb_list_entry_remove_head(&scheduler->coroutines_dead);
// get the dead coroutine
tb_coroutine_t* coroutine_dead = (tb_coroutine_t*)tb_list_entry0(entry);
// reinit this coroutine
coroutine = tb_coroutine_reinit(coroutine_dead, func, priv, stacksize);
// failed? exit this coroutine
if (!coroutine) tb_coroutine_exit(coroutine_dead);
}
// init coroutine
if (!coroutine) coroutine = tb_coroutine_init((tb_co_scheduler_ref_t)scheduler, func, priv, stacksize);
tb_assert_and_check_break(coroutine);
// ready coroutine
tb_co_scheduler_make_ready(scheduler, coroutine);
// the dead coroutines is too much? free some coroutines
while (tb_list_entry_size(&scheduler->coroutines_dead) > TB_SCHEDULER_DEAD_CACHE_MAXN)
{
// get the next entry from head
tb_list_entry_ref_t entry = tb_list_entry_head(&scheduler->coroutines_dead);
tb_assert(entry);
// remove it from the ready coroutines
tb_list_entry_remove_head(&scheduler->coroutines_dead);
// exit this coroutine
tb_coroutine_exit((tb_coroutine_t*)tb_list_entry0(entry));
}
// ok
ok = tb_true;
} while (0);
// trace
tb_trace_d("start %s", ok? "ok" : "no");
// ok?
return ok;
}
tb_bool_t tb_co_scheduler_yield(tb_co_scheduler_t* scheduler)
{
// check
tb_assert(scheduler && scheduler->running);
tb_assert(scheduler->running == (tb_coroutine_t*)tb_coroutine_self());
// trace
tb_trace_d("yield coroutine(%p)", scheduler->running);
#ifdef __tb_debug__
// check it
tb_coroutine_check(scheduler->running);
#endif
// get the next ready coroutine
tb_coroutine_t* coroutine_next = tb_co_scheduler_next_ready(scheduler);
if (coroutine_next != scheduler->running)
{
// switch to the next coroutine
tb_co_scheduler_switch(scheduler, coroutine_next);
// ok
return tb_true;
}
// no more coroutine (only running)?
else
{
// trace
tb_trace_d("continue to run current coroutine(%p)", tb_coroutine_self());
// check
tb_assert((tb_list_entry_ref_t)scheduler->running == tb_list_entry_head(&scheduler->coroutines_ready));
}
// return it directly and continue to run this coroutine
return tb_false;
}
tb_pointer_t tb_co_scheduler_resume(tb_co_scheduler_t* scheduler, tb_coroutine_t* coroutine, tb_cpointer_t priv)
{
// check
tb_assert(scheduler && coroutine);
// trace
tb_trace_d("resume coroutine(%p)", coroutine);
// remove it from the suspend coroutines
tb_list_entry_remove(&scheduler->coroutines_suspend, (tb_list_entry_ref_t)coroutine);
// get the passed private data from suspend(priv)
tb_pointer_t retval = (tb_pointer_t)coroutine->rs_priv;
// pass the user private data to suspend()
coroutine->rs_priv = priv;
// make it as ready
tb_co_scheduler_make_ready(scheduler, coroutine);
// return it
return retval;
}
tb_pointer_t tb_co_scheduler_suspend(tb_co_scheduler_t* scheduler, tb_cpointer_t priv)
{
// check
tb_assert(scheduler && scheduler->running);
tb_assert(scheduler->running == (tb_coroutine_t*)tb_coroutine_self());
// have been stopped? return it directly
tb_check_return_val(!scheduler->stopped, tb_null);
// trace
tb_trace_d("suspend coroutine(%p)", scheduler->running);
#ifdef __tb_debug__
// check it
tb_coroutine_check(scheduler->running);
#endif
// pass the private data to resume() first
scheduler->running->rs_priv = priv;
// get the next ready coroutine first
tb_coroutine_t* coroutine_next = tb_co_scheduler_next_ready(scheduler);
// make the running coroutine as suspend
tb_co_scheduler_make_suspend(scheduler, scheduler->running);
// switch to next coroutine
if (coroutine_next != scheduler->running) tb_co_scheduler_switch(scheduler, coroutine_next);
// no more coroutine?
else
{
// trace
tb_trace_d("switch to original coroutine");
// switch to the original coroutine
tb_co_scheduler_switch(scheduler, &scheduler->original);
}
// check
tb_assert(scheduler->running);
// return the user private data from resume(priv)
return (tb_pointer_t)scheduler->running->rs_priv;
}
tb_void_t tb_co_scheduler_finish(tb_co_scheduler_t* scheduler)
{
// check
tb_assert(scheduler && scheduler->running);
tb_assert(scheduler->running == (tb_coroutine_t*)tb_coroutine_self());
// trace
tb_trace_d("finish coroutine(%p)", scheduler->running);
#ifdef __tb_debug__
// check it
tb_coroutine_check(scheduler->running);
#endif
// get the next ready coroutine first
tb_coroutine_t* coroutine_next = tb_co_scheduler_next_ready(scheduler);
// make the running coroutine as dead
tb_co_scheduler_make_dead(scheduler, scheduler->running);
// switch to next coroutine
if (coroutine_next != scheduler->running) tb_co_scheduler_switch(scheduler, coroutine_next);
// no more coroutine?
else
{
// trace
tb_trace_d("switch to original coroutine");
// switch to the original coroutine
tb_co_scheduler_switch(scheduler, &scheduler->original);
}
}
tb_pointer_t tb_co_scheduler_sleep(tb_co_scheduler_t* scheduler, tb_long_t interval)
{
// check
tb_assert(scheduler && scheduler->running);
tb_assert(scheduler->running == (tb_coroutine_t*)tb_coroutine_self());
// have been stopped? return it directly
tb_check_return_val(!scheduler->stopped, tb_null);
// need io scheduler
if (!tb_co_scheduler_io_need(scheduler)) return tb_null;
// sleep it
return tb_co_scheduler_io_sleep(scheduler->scheduler_io, interval);
}
tb_void_t tb_co_scheduler_switch(tb_co_scheduler_t* scheduler, tb_coroutine_t* coroutine)
{
// check
tb_assert(scheduler && scheduler->running);
tb_assert(coroutine && coroutine->context);
// the current running coroutine
tb_coroutine_t* running = scheduler->running;
// mark the given coroutine as running
scheduler->running = coroutine;
// trace
tb_trace_d("switch to coroutine(%p) from coroutine(%p)", coroutine, running);
// jump to the given coroutine
tb_context_from_t from = tb_context_jump(coroutine->context, running);
// the from-coroutine
tb_coroutine_t* coroutine_from = (tb_coroutine_t*)from.priv;
tb_assert(coroutine_from && from.context);
#ifdef __tb_debug__
// check it
tb_coroutine_check(coroutine_from);
#endif
// update the context
coroutine_from->context = from.context;
}
tb_long_t tb_co_scheduler_wait(tb_co_scheduler_t* scheduler, tb_poller_object_ref_t object, tb_size_t events, tb_long_t timeout)
{
// check
tb_assert(scheduler && scheduler->running);
tb_assert(scheduler->running == (tb_coroutine_t*)tb_coroutine_self());
// have been stopped? return it directly
tb_check_return_val(!scheduler->stopped, -1);
// need io scheduler
if (!tb_co_scheduler_io_need(scheduler)) return -1;
// wait it
return tb_co_scheduler_io_wait(scheduler->scheduler_io, object, events, timeout);
}
tb_long_t tb_co_scheduler_wait_proc(tb_co_scheduler_t* scheduler, tb_poller_object_ref_t object, tb_long_t* pstatus, tb_long_t timeout)
{
// check
tb_assert(scheduler && scheduler->running);
tb_assert(scheduler->running == (tb_coroutine_t*)tb_coroutine_self());
// have been stopped? return it directly
tb_check_return_val(!scheduler->stopped, -1);
// need io scheduler
if (!tb_co_scheduler_io_need(scheduler)) return -1;
// wait it
return tb_co_scheduler_io_wait_proc(scheduler->scheduler_io, object, pstatus, timeout);
}
tb_long_t tb_co_scheduler_wait_fwatcher(tb_co_scheduler_t* scheduler, tb_poller_object_ref_t object, tb_fwatcher_event_t* pevent, tb_long_t timeout)
{
// check
tb_assert(scheduler && scheduler->running);
tb_assert(scheduler->running == (tb_coroutine_t*)tb_coroutine_self());
// have been stopped? return it directly
tb_check_return_val(!scheduler->stopped, -1);
// need io scheduler
if (!tb_co_scheduler_io_need(scheduler)) return -1;
// wait it
return tb_co_scheduler_io_wait_fwatcher(scheduler->scheduler_io, object, pevent, timeout);
}
tbox-1.7.6/src/tbox/coroutine/impl/scheduler.h 0000664 0000000 0000000 00000015020 14671175054 0021353 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file scheduler.h
* @ingroup coroutine
*
*/
#ifndef TB_COROUTINE_IMPL_SCHEDULER_H
#define TB_COROUTINE_IMPL_SCHEDULER_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "coroutine.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// get the running coroutine
#define tb_co_scheduler_running(scheduler) ((scheduler)->running)
// get the ready coroutines count
#define tb_co_scheduler_ready_count(scheduler) tb_list_entry_size(&(scheduler)->coroutines_ready)
// get the suspended coroutines count
#define tb_co_scheduler_suspend_count(scheduler) tb_list_entry_size(&(scheduler)->coroutines_suspend)
// get the io scheduler
#define tb_co_scheduler_io(scheduler) ((scheduler)->scheduler_io)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the io scheduler type
struct __tb_co_scheduler_io_t;
// the scheduler type
typedef struct __tb_co_scheduler_t
{
/* the original coroutine (in main loop)
*
* coroutine->scheduler == (tb_co_scheduler_ref_t)coroutine
*/
tb_coroutine_t original;
// is stopped
tb_bool_t stopped;
// the running coroutine
tb_coroutine_t* running;
// the io scheduler
struct __tb_co_scheduler_io_t* scheduler_io;
// the dead coroutines
tb_list_entry_head_t coroutines_dead;
/* the ready coroutines
*
* ready: head -> ready -> .. -> running -> .. -> ready -> ..->
* | |
* ---------------------------<-----------------------
*/
tb_list_entry_head_t coroutines_ready;
// the suspend coroutines
tb_list_entry_head_t coroutines_suspend;
}tb_co_scheduler_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* start the coroutine function
*
* @param scheduler the scheduler, uses the default scheduler if be null
* @param func the coroutine function
* @param priv the passed user private data as the argument of function
* @param stacksize the stack size
*
* @return tb_true or tb_false
*/
tb_bool_t tb_co_scheduler_start(tb_co_scheduler_t* scheduler, tb_coroutine_func_t func, tb_cpointer_t priv, tb_size_t stacksize);
/* yield the current coroutine
*
* @param scheduler the scheduler
*
* @return tb_true(yield ok) or tb_false(yield failed, no more coroutines)
*/
tb_bool_t tb_co_scheduler_yield(tb_co_scheduler_t* scheduler);
/*! resume the given coroutine (suspended)
*
* @param scheduler the scheduler
* @param coroutine the suspended coroutine
* @param priv the user private data as the return value of suspend() or sleep()
*
* @return the user private data from suspend(priv)
*/
tb_pointer_t tb_co_scheduler_resume(tb_co_scheduler_t* scheduler, tb_coroutine_t* coroutine, tb_cpointer_t priv);
/* suspend the current coroutine
*
* @param scheduler the scheduler
* @param priv the user private data as the return value of resume()
*
* @return the user private data from resume(priv)
*/
tb_pointer_t tb_co_scheduler_suspend(tb_co_scheduler_t* scheduler, tb_cpointer_t priv);
/* finish the current coroutine
*
* @param scheduler the scheduler
*/
tb_void_t tb_co_scheduler_finish(tb_co_scheduler_t* scheduler);
/* sleep the current coroutine
*
* @param scheduler the scheduler
* @param interval the interval (ms), infinity: -1
*
* @return the user private data from resume(priv)
*/
tb_pointer_t tb_co_scheduler_sleep(tb_co_scheduler_t* scheduler, tb_long_t interval);
/* switch to the given coroutine
*
* @param scheduler the scheduler
* @param coroutine the coroutine
*/
tb_void_t tb_co_scheduler_switch(tb_co_scheduler_t* scheduler, tb_coroutine_t* coroutine);
/* wait io events
*
* @param scheduler the scheduler
* @param object the poller object
* @param events the waited events
* @param timeout the timeout, infinity: -1
*
* @return > 0: the events, 0: timeout, -1: failed
*/
tb_long_t tb_co_scheduler_wait(tb_co_scheduler_t* scheduler, tb_poller_object_ref_t object, tb_size_t events, tb_long_t timeout);
/* wait process status
*
* @param scheduler the scheduler
* @param object the process poller object
* @param pstatus the process exited status pointer, maybe null
* @param timeout the timeout, infinity: -1
*
* @return > 0: process exited, 0: timeout, -1: failed
*/
tb_long_t tb_co_scheduler_wait_proc(tb_co_scheduler_t* scheduler, tb_poller_object_ref_t object, tb_long_t* pstatus, tb_long_t timeout);
/* wait fwatcher event
*
* @param scheduler the scheduler
* @param object the fwatcher poller object
* @param pevent the fwatcher event pointer
* @param timeout the timeout, infinity: -1
*
* @return > 0: has event, 0: timeout, -1: failed
*/
tb_long_t tb_co_scheduler_wait_fwatcher(tb_co_scheduler_t* scheduler, tb_poller_object_ref_t object, tb_fwatcher_event_t* pevent, tb_long_t timeout);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/coroutine/impl/scheduler_io.c 0000664 0000000 0000000 00000064421 14671175054 0022046 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file scheduler_io.c
* @ingroup coroutine
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "scheduler_io"
#define TB_TRACE_MODULE_DEBUG (1)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "scheduler_io.h"
#include "coroutine.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the ltimer grow
#ifdef __tb_small__
# define TB_SCHEDULER_IO_LTIMER_GROW (64)
#else
# define TB_SCHEDULER_IO_LTIMER_GROW (4096)
#endif
// the timer grow
#define TB_SCHEDULER_IO_TIMER_GROW (TB_SCHEDULER_IO_LTIMER_GROW >> 4)
// the poller object data grow
#ifdef __tb_small__
# define TB_SCHEDULER_IO_POLLERDATA_GROW (64)
#else
# define TB_SCHEDULER_IO_POLLERDATA_GROW (4096)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_void_t tb_co_scheduler_io_resume(tb_co_scheduler_t* scheduler, tb_coroutine_t* coroutine, tb_size_t events)
{
// exists the timer task? remove it
tb_cpointer_t task = coroutine->rs.wait.task;
if (task)
{
// get io scheduler
tb_co_scheduler_io_ref_t scheduler_io = tb_co_scheduler_io(scheduler);
tb_assert(scheduler_io && scheduler_io->poller);
// remove the timer task
if (coroutine->rs.wait.is_ltimer) tb_ltimer_task_exit(scheduler_io->ltimer, (tb_ltimer_task_ref_t)task);
else tb_timer_task_exit(scheduler_io->timer, (tb_timer_task_ref_t)task);
coroutine->rs.wait.task = tb_null;
}
// resume the coroutine
tb_co_scheduler_resume(scheduler, coroutine, (tb_cpointer_t)((events & TB_POLLER_EVENT_ERROR)? -1 : events));
}
static tb_void_t tb_co_scheduler_io_timeout(tb_bool_t killed, tb_cpointer_t priv)
{
// check
tb_coroutine_t* coroutine = (tb_coroutine_t*)priv;
tb_assert(coroutine);
// get scheduler
tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_coroutine_scheduler(coroutine);
tb_assert(scheduler);
// trace
tb_trace_d("coroutine(%p): timer(%s) %s", coroutine, coroutine->rs.wait.object.type? "poller object" : "sleep", killed? "killed" : "timeout");
// resume the waited coroutine if timer task has been not canceled
if (!killed)
{
// reset the waited coroutines in the poller object data
tb_size_t object_type = coroutine->rs.wait.object.type;
if (object_type == TB_POLLER_OBJECT_PROC || object_type == TB_POLLER_OBJECT_FWATCHER)
coroutine->rs.wait.object_waiting = 0;
else if (object_type)
{
tb_co_scheduler_io_ref_t scheduler_io = tb_co_scheduler_io(scheduler);
tb_co_pollerdata_io_ref_t pollerdata = (tb_co_pollerdata_io_ref_t)(scheduler_io? tb_pollerdata_get(&scheduler_io->pollerdata, &coroutine->rs.wait.object) : tb_null);
if (pollerdata)
{
if (coroutine == pollerdata->co_recv)
pollerdata->co_recv = tb_null;
if (coroutine == pollerdata->co_send)
pollerdata->co_send = tb_null;
}
}
// resume the coroutine
tb_co_scheduler_io_resume(scheduler, coroutine, TB_POLLER_EVENT_NONE);
}
}
static tb_void_t tb_co_scheduler_io_events(tb_poller_ref_t poller, tb_poller_object_ref_t object, tb_long_t events, tb_cpointer_t priv)
{
// check
tb_co_scheduler_io_ref_t scheduler_io = (tb_co_scheduler_io_ref_t)tb_poller_priv(poller);
tb_assert(scheduler_io && scheduler_io->scheduler && object);
// is process/fwatcher object?
if (object->type == TB_POLLER_OBJECT_PROC || object->type == TB_POLLER_OBJECT_FWATCHER)
{
// resume coroutine and return the process exit status
tb_coroutine_t* coroutine = (tb_coroutine_t*)priv;
tb_assert(coroutine);
coroutine->rs.wait.object_event = events;
// waiting process? resume this coroutine
if (coroutine->rs.wait.object_waiting)
{
coroutine->rs.wait.object_waiting = 0;
tb_co_scheduler_io_resume(scheduler_io->scheduler, coroutine, 1);
}
else coroutine->rs.wait.object_pending = 1;
return ;
}
// get pollerdata data
tb_co_pollerdata_io_ref_t pollerdata = (tb_co_pollerdata_io_ref_t)tb_pollerdata_get(&scheduler_io->pollerdata, object);
tb_assert(pollerdata);
// get poller object events
tb_size_t events_prev_wait = pollerdata->poller_events_wait;
tb_size_t events_prev_save = pollerdata->poller_events_save;
// eof for edge trigger?
if (events & TB_POLLER_EVENT_EOF)
{
// cache this eof as next recv/send event
events &= ~TB_POLLER_EVENT_EOF;
events_prev_save |= events_prev_wait;
pollerdata->poller_events_save = (tb_uint16_t)events_prev_save;
}
// get the waiting coroutines
tb_coroutine_t* co_recv = (events & TB_POLLER_EVENT_RECV)? pollerdata->co_recv : tb_null;
tb_coroutine_t* co_send = (events & TB_POLLER_EVENT_SEND)? pollerdata->co_send : tb_null;
// trace
tb_trace_d("object: %p, trigger events %lu, co_recv(%p), co_send(%p)", object->ref.ptr, events, co_recv, co_send);
// return the events result for the waiting coroutines
if (co_recv && co_recv == co_send)
{
pollerdata->co_recv = tb_null;
pollerdata->co_send = tb_null;
tb_co_scheduler_io_resume(scheduler_io->scheduler, co_recv, events);
}
else
{
if (co_recv)
{
pollerdata->co_recv = tb_null;
tb_co_scheduler_io_resume(scheduler_io->scheduler, co_recv, events & ~TB_POLLER_EVENT_SEND);
events &= ~TB_POLLER_EVENT_RECV;
}
if (co_send)
{
pollerdata->co_send = tb_null;
tb_co_scheduler_io_resume(scheduler_io->scheduler, co_send, events & ~TB_POLLER_EVENT_RECV);
events &= ~TB_POLLER_EVENT_SEND;
}
// no coroutines are waiting? cache this events
if ((events & TB_POLLER_EVENT_RECV) || (events & TB_POLLER_EVENT_SEND))
{
// trace
tb_trace_d("object: %p, cache events %lu", object->ref.ptr, events);
// cache this events
events_prev_save |= events;
pollerdata->poller_events_save = (tb_uint16_t)events_prev_save;
}
}
}
static tb_bool_t tb_co_scheduler_io_timer_spak(tb_co_scheduler_io_ref_t scheduler_io)
{
// check
tb_assert(scheduler_io && scheduler_io->timer && scheduler_io->ltimer);
// spak ctime
tb_cache_time_spak();
// spak timer
if (!tb_timer_spak(scheduler_io->timer)) return tb_false;
// spak ltimer
if (!tb_ltimer_spak(scheduler_io->ltimer)) return tb_false;
// pk
return tb_true;
}
static tb_void_t tb_co_scheduler_io_loop(tb_cpointer_t priv)
{
// check
tb_co_scheduler_io_ref_t scheduler_io = (tb_co_scheduler_io_ref_t)priv;
tb_assert_and_check_return(scheduler_io && scheduler_io->timer && scheduler_io->ltimer);
// the scheduler
tb_co_scheduler_t* scheduler = scheduler_io->scheduler;
tb_assert_and_check_return(scheduler);
// the poller
tb_poller_ref_t poller = scheduler_io->poller;
tb_assert_and_check_return(poller);
// loop
while (!scheduler->stopped)
{
// finish all other ready coroutines first
while (tb_co_scheduler_yield(scheduler))
{
// spak timer
if (!tb_co_scheduler_io_timer_spak(scheduler_io)) break;
}
// no more suspended coroutines? loop end
tb_check_break(tb_co_scheduler_suspend_count(scheduler));
// the delay
tb_size_t delay = tb_timer_delay(scheduler_io->timer);
// the ldelay
tb_size_t ldelay = tb_ltimer_delay(scheduler_io->ltimer);
// trace
tb_trace_d("loop: wait %lu ms, %lu pending coroutines ..", tb_min(delay, ldelay), tb_co_scheduler_suspend_count(scheduler));
// no more ready coroutines? wait io events and timers
if (tb_poller_wait(poller, tb_co_scheduler_io_events, tb_min(delay, ldelay)) < 0)
{
tb_trace_e("loop: wait poller failed!");
break;
}
// trace
tb_trace_d("loop: wait ok, left %lu pending coroutines ..", tb_co_scheduler_suspend_count(scheduler));
// spak timer
if (!tb_co_scheduler_io_timer_spak(scheduler_io)) break;
}
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_co_scheduler_io_ref_t tb_co_scheduler_io_init(tb_co_scheduler_t* scheduler)
{
// done
tb_bool_t ok = tb_false;
tb_co_scheduler_io_ref_t scheduler_io = tb_null;
do
{
// init io scheduler
scheduler_io = tb_malloc0_type(tb_co_scheduler_io_t);
tb_assert_and_check_break(scheduler_io);
// save scheduler
scheduler_io->scheduler = (tb_co_scheduler_t*)scheduler;
// init timer and using cache time
scheduler_io->timer = tb_timer_init(TB_SCHEDULER_IO_TIMER_GROW, tb_true);
tb_assert_and_check_break(scheduler_io->timer);
// init ltimer and using cache time
scheduler_io->ltimer = tb_ltimer_init(TB_SCHEDULER_IO_LTIMER_GROW, TB_LTIMER_TICK_S, tb_true);
tb_assert_and_check_break(scheduler_io->ltimer);
// init poller
scheduler_io->poller = tb_poller_init(scheduler_io);
tb_assert_and_check_break(scheduler_io->poller);
// attach poller
tb_poller_attach(scheduler_io->poller);
// init poller object data pool
scheduler_io->pollerdata_pool = tb_fixed_pool_init(tb_null, TB_SCHEDULER_IO_POLLERDATA_GROW, sizeof(tb_co_pollerdata_io_t), tb_null, tb_null, tb_null);
tb_assert_and_check_break(scheduler_io->pollerdata_pool);
// init poller object data
tb_pollerdata_init(&scheduler_io->pollerdata);
// start the io loop coroutine
if (!tb_co_scheduler_start(scheduler_io->scheduler, tb_co_scheduler_io_loop, scheduler_io, 0)) break;
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit io scheduler
if (scheduler_io) tb_co_scheduler_io_exit(scheduler_io);
scheduler_io = tb_null;
}
// ok?
return scheduler_io;
}
tb_void_t tb_co_scheduler_io_exit(tb_co_scheduler_io_ref_t scheduler_io)
{
// check
tb_assert_and_check_return(scheduler_io);
// exit poller object data
tb_pollerdata_exit(&scheduler_io->pollerdata);
// exit poller object data pool
if (scheduler_io->pollerdata_pool) tb_fixed_pool_exit(scheduler_io->pollerdata_pool);
scheduler_io->pollerdata_pool = tb_null;
// exit poller
if (scheduler_io->poller) tb_poller_exit(scheduler_io->poller);
scheduler_io->poller = tb_null;
// exit timer
if (scheduler_io->timer) tb_timer_exit(scheduler_io->timer);
scheduler_io->timer = tb_null;
// exit ltimer
if (scheduler_io->ltimer) tb_ltimer_exit(scheduler_io->ltimer);
scheduler_io->ltimer = tb_null;
// clear scheduler
scheduler_io->scheduler = tb_null;
// exit it
tb_free(scheduler_io);
}
tb_co_scheduler_io_ref_t tb_co_scheduler_io_need(tb_co_scheduler_t* scheduler)
{
// get the current scheduler
if (!scheduler) scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self();
if (scheduler)
{
// init io scheduler first
if (!scheduler->scheduler_io) scheduler->scheduler_io = tb_co_scheduler_io_init(scheduler);
tb_assert(scheduler->scheduler_io);
// get the current io scheduler
return (tb_co_scheduler_io_ref_t)scheduler->scheduler_io;
}
return tb_null;
}
tb_void_t tb_co_scheduler_io_kill(tb_co_scheduler_io_ref_t scheduler_io)
{
// check
tb_assert_and_check_return(scheduler_io);
// trace
tb_trace_d("kill: ..");
// kill timer
if (scheduler_io->timer) tb_timer_kill(scheduler_io->timer);
// kill ltimer
if (scheduler_io->ltimer) tb_ltimer_kill(scheduler_io->ltimer);
// kill poller
if (scheduler_io->poller) tb_poller_kill(scheduler_io->poller);
}
tb_pointer_t tb_co_scheduler_io_sleep(tb_co_scheduler_io_ref_t scheduler_io, tb_long_t interval)
{
// check
tb_assert_and_check_return_val(scheduler_io && scheduler_io->poller && scheduler_io->scheduler, tb_null);
// no sleep?
tb_check_return_val(interval, tb_null);
// get the current coroutine
tb_coroutine_t* coroutine = tb_co_scheduler_running(scheduler_io->scheduler);
tb_assert(coroutine);
// trace
tb_trace_d("coroutine(%p): sleep %ld ms ..", coroutine, interval);
// clear waiting task first
coroutine->rs.wait.task = tb_null;
coroutine->rs.wait.object.type = TB_POLLER_OBJECT_NONE;
// infinity?
if (interval > 0)
{
// high-precision interval?
if (interval % 1000)
{
// post task to timer
tb_timer_task_post(scheduler_io->timer, interval, tb_false, tb_co_scheduler_io_timeout, coroutine);
}
// low-precision interval?
else
{
// post task to ltimer (faster)
tb_ltimer_task_post(scheduler_io->ltimer, interval, tb_false, tb_co_scheduler_io_timeout, coroutine);
}
}
// suspend it
return tb_co_scheduler_suspend(scheduler_io->scheduler, tb_null);
}
tb_long_t tb_co_scheduler_io_wait(tb_co_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object, tb_size_t events, tb_long_t timeout)
{
// check
tb_assert(scheduler_io && object && scheduler_io->poller && scheduler_io->scheduler && events);
// get the current coroutine
tb_coroutine_t* coroutine = tb_co_scheduler_running(scheduler_io->scheduler);
tb_assert(coroutine);
// get the poller
tb_poller_ref_t poller = scheduler_io->poller;
tb_assert(poller);
// trace
tb_trace_d("coroutine(%p): wait events(%lu) with %ld ms for object(%p) ..", coroutine, events, timeout, object->ref.ptr);
// get and allocate a poller object data
tb_co_pollerdata_io_ref_t pollerdata = (tb_co_pollerdata_io_ref_t)tb_pollerdata_get(&scheduler_io->pollerdata, object);
if (!pollerdata)
{
tb_assert(scheduler_io->pollerdata_pool);
pollerdata = (tb_co_pollerdata_io_ref_t)tb_fixed_pool_malloc0(scheduler_io->pollerdata_pool);
tb_pollerdata_set(&scheduler_io->pollerdata, object, pollerdata);
}
tb_assert_and_check_return_val(pollerdata, -1);
// enable edge-trigger mode if be supported
if (tb_poller_support(poller, TB_POLLER_EVENT_CLEAR))
events |= TB_POLLER_EVENT_CLEAR;
// get the previous poller object events
tb_size_t events_wait = events;
if (pollerdata->poller_events_wait)
{
// return the cached events directly if the waiting events exists cache
tb_size_t events_prev_wait = pollerdata->poller_events_wait;
tb_size_t events_prev_save = pollerdata->poller_events_save;
if (events_prev_save && (events_prev_wait & events))
{
// check error?
if (events_prev_save & TB_POLLER_EVENT_ERROR)
{
pollerdata->poller_events_save = 0;
return -1;
}
// clear cache events
pollerdata->poller_events_save = (tb_uint16_t)(events_prev_save & ~events);
// return the cached events
return events_prev_save & events;
}
// modify the wait events and reserve the pending events in other coroutine
events_wait = events_prev_wait;
if ((events_wait & TB_POLLER_EVENT_RECV) && !pollerdata->co_recv) events_wait &= ~TB_POLLER_EVENT_RECV;
if ((events_wait & TB_POLLER_EVENT_SEND) && !pollerdata->co_send) events_wait &= ~TB_POLLER_EVENT_SEND;
events_wait |= events;
// modify poller object from poller for waiting events if the waiting events has been changed
if ((events_prev_wait & events_wait) != events_wait)
{
// trace
tb_trace_d("modify poller object: %p events: %lx", object->ref.ptr, events_wait);
// may be wait recv/send at same time
if (!tb_poller_modify(poller, object, events_wait | TB_POLLER_EVENT_NOEXTRA, tb_null))
{
// trace
tb_trace_e("failed to modify object(%p) to poller on coroutine(%p)!", object->ref.ptr, coroutine);
return -1;
}
}
}
else
{
// trace
tb_trace_d("insert poller object: %p events: %lx", object->ref.ptr, events_wait);
// insert poller object to poller for waiting events
if (!tb_poller_insert(poller, object, events_wait | TB_POLLER_EVENT_NOEXTRA, tb_null))
{
// trace
tb_trace_e("failed to insert object(%p) to poller on coroutine(%p)!", object->ref.ptr, coroutine);
return -1;
}
}
// exists timeout?
tb_cpointer_t task = tb_null;
tb_bool_t is_ltimer = tb_false;
if (timeout >= 0)
{
// high-precision interval?
if (timeout % 1000)
{
// init task for timer
task = tb_timer_task_init(scheduler_io->timer, timeout, tb_false, tb_co_scheduler_io_timeout, coroutine);
tb_assert_and_check_return_val(task, tb_false);
}
// low-precision interval?
else
{
// init task for ltimer (faster)
task = tb_ltimer_task_init(scheduler_io->ltimer, timeout, tb_false, tb_co_scheduler_io_timeout, coroutine);
tb_assert_and_check_return_val(task, tb_false);
// mark as low-precision timer
is_ltimer = tb_true;
}
}
// save the timer task to coroutine
coroutine->rs.wait.task = task;
coroutine->rs.wait.object = *object;
coroutine->rs.wait.is_ltimer = is_ltimer;
// save waiting events
pollerdata->poller_events_wait = (tb_uint16_t)events_wait;
pollerdata->poller_events_save = 0;
// save the current coroutine
if (events & TB_POLLER_EVENT_RECV) pollerdata->co_recv = coroutine;
if (events & TB_POLLER_EVENT_SEND) pollerdata->co_send = coroutine;
// suspend the current coroutine and return the waited result
return (tb_long_t)tb_co_scheduler_suspend(scheduler_io->scheduler, tb_null);
}
tb_long_t tb_co_scheduler_io_wait_proc(tb_co_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object, tb_long_t* pstatus, tb_long_t timeout)
{
// check
tb_assert(scheduler_io && scheduler_io->poller && scheduler_io->scheduler);
tb_assert(object && object->type == TB_POLLER_OBJECT_PROC && object->ref.proc);
// get the current coroutine
tb_coroutine_t* coroutine = tb_co_scheduler_running(scheduler_io->scheduler);
tb_assert(coroutine);
// get the poller
tb_poller_ref_t poller = scheduler_io->poller;
tb_assert(poller);
// trace
tb_trace_d("coroutine(%p): wait process object(%p) with %ld ms ..", coroutine, object->ref.proc, timeout);
// has pending process status?
if (coroutine->rs.wait.object_pending)
{
if (pstatus) *pstatus = coroutine->rs.wait.object_event;
coroutine->rs.wait.object_pending = 0;
return 1;
}
// insert poller object to poller for waiting process
if (!tb_poller_insert(poller, object, 0, coroutine))
{
// trace
tb_trace_e("failed to insert process object(%p) to poller on coroutine(%p)!", object->ref.proc, coroutine);
return -1;
}
// exists timeout?
tb_cpointer_t task = tb_null;
tb_bool_t is_ltimer = tb_false;
if (timeout >= 0)
{
// high-precision interval?
if (timeout % 1000)
{
// init task for timer
task = tb_timer_task_init(scheduler_io->timer, timeout, tb_false, tb_co_scheduler_io_timeout, coroutine);
tb_assert_and_check_return_val(task, tb_false);
}
// low-precision interval?
else
{
// init task for ltimer (faster)
task = tb_ltimer_task_init(scheduler_io->ltimer, timeout, tb_false, tb_co_scheduler_io_timeout, coroutine);
tb_assert_and_check_return_val(task, tb_false);
// mark as low-precision timer
is_ltimer = tb_true;
}
}
// save the timer task to coroutine
coroutine->rs.wait.task = task;
coroutine->rs.wait.object = *object;
coroutine->rs.wait.is_ltimer = is_ltimer;
coroutine->rs.wait.object_event = 0;
coroutine->rs.wait.object_pending = 0;
coroutine->rs.wait.object_waiting = 1;
// suspend the current coroutine and return the waited result
tb_long_t ok = (tb_long_t)tb_co_scheduler_suspend(scheduler_io->scheduler, tb_null);
if (ok > 0 && pstatus) *pstatus = coroutine->rs.wait.object_event;
return ok;
}
tb_long_t tb_co_scheduler_io_wait_fwatcher(tb_co_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object, tb_fwatcher_event_t* pevent, tb_long_t timeout)
{
// check
tb_assert(scheduler_io && scheduler_io->poller && scheduler_io->scheduler);
tb_assert(object && object->type == TB_POLLER_OBJECT_FWATCHER && object->ref.fwatcher);
// get the current coroutine
tb_coroutine_t* coroutine = tb_co_scheduler_running(scheduler_io->scheduler);
tb_assert(coroutine);
// get the poller
tb_poller_ref_t poller = scheduler_io->poller;
tb_assert(poller);
// trace
tb_trace_d("coroutine(%p): wait fwatcher object(%p) with %ld ms ..", coroutine, object->ref.fwatcher, timeout);
// has pending fwatcher event?
if (coroutine->rs.wait.object_pending)
{
if (pevent) *pevent = *((tb_fwatcher_event_t*)coroutine->rs.wait.object_event);
coroutine->rs.wait.object_pending = 0;
return 1;
}
// insert poller object to poller for waiting fwatcher
if (!tb_poller_insert(poller, object, 0, coroutine))
{
// trace
tb_trace_e("failed to insert fwatcher object(%p) to poller on coroutine(%p)!", object->ref.fwatcher, coroutine);
return -1;
}
// exists timeout?
tb_cpointer_t task = tb_null;
tb_bool_t is_ltimer = tb_false;
if (timeout >= 0)
{
// high-precision interval?
if (timeout % 1000)
{
// init task for timer
task = tb_timer_task_init(scheduler_io->timer, timeout, tb_false, tb_co_scheduler_io_timeout, coroutine);
tb_assert_and_check_return_val(task, tb_false);
}
// low-precision interval?
else
{
// init task for ltimer (faster)
task = tb_ltimer_task_init(scheduler_io->ltimer, timeout, tb_false, tb_co_scheduler_io_timeout, coroutine);
tb_assert_and_check_return_val(task, tb_false);
// mark as low-precision timer
is_ltimer = tb_true;
}
}
// save the timer task to coroutine
coroutine->rs.wait.task = task;
coroutine->rs.wait.object = *object;
coroutine->rs.wait.is_ltimer = is_ltimer;
coroutine->rs.wait.object_event = 0;
coroutine->rs.wait.object_pending = 0;
coroutine->rs.wait.object_waiting = 1;
// suspend the current coroutine and return the waited result
tb_long_t ok = (tb_long_t)tb_co_scheduler_suspend(scheduler_io->scheduler, tb_null);
if (ok > 0 && pevent) *pevent = *((tb_fwatcher_event_t*)coroutine->rs.wait.object_event);
return ok;
}
tb_bool_t tb_co_scheduler_io_cancel(tb_co_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object)
{
// check
tb_assert(scheduler_io && object && scheduler_io->poller && scheduler_io->scheduler);
// get the current coroutine
tb_coroutine_t* coroutine = tb_co_scheduler_running(scheduler_io->scheduler);
tb_check_return_val(coroutine, tb_false);
// trace
tb_trace_d("coroutine(%p): cancel poller object(%p) ..", coroutine, object->ref.ptr);
// cancel process object
if (object->type == TB_POLLER_OBJECT_PROC || object->type == TB_POLLER_OBJECT_FWATCHER)
{
// clear process status
coroutine->rs.wait.object_event = 0;
coroutine->rs.wait.object_pending = 0;
coroutine->rs.wait.object_waiting = 0;
// remove the previous poller object first if exists
if (!tb_poller_remove(scheduler_io->poller, object))
{
// trace
tb_trace_e("failed to remove object(%p) to poller on coroutine(%p)!", object->ref.ptr, coroutine);
return tb_false;
}
return tb_true;
}
// reset the pollerdata data
tb_co_pollerdata_io_ref_t pollerdata = (tb_co_pollerdata_io_ref_t)tb_pollerdata_get(&scheduler_io->pollerdata, object);
if (pollerdata)
{
// clear the waiting coroutines
pollerdata->co_recv = tb_null;
pollerdata->co_send = tb_null;
// remove the this poller object from poller
if (pollerdata->poller_events_wait)
{
// remove the previous poller object first if exists
if (!tb_poller_remove(scheduler_io->poller, object))
{
// trace
tb_trace_e("failed to remove object(%p) to poller on coroutine(%p)!", object->ref.ptr, coroutine);
return tb_false;
}
// remove the poller object events
pollerdata->poller_events_wait = 0;
pollerdata->poller_events_save = 0;
return tb_true;
}
}
// no this poller object
return tb_false;
}
tb_co_scheduler_io_ref_t tb_co_scheduler_io_self()
{
// get the current scheduler
tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self();
// get the current io scheduler
return scheduler? (tb_co_scheduler_io_ref_t)scheduler->scheduler_io : tb_null;
}
tbox-1.7.6/src/tbox/coroutine/impl/scheduler_io.h 0000664 0000000 0000000 00000012767 14671175054 0022061 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file scheduler_io.h
* @ingroup coroutine
*
*/
#ifndef TB_COROUTINE_IMPL_SCHEDULER_IO_H
#define TB_COROUTINE_IMPL_SCHEDULER_IO_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "scheduler.h"
#include "../../memory/fixed_pool.h"
#include "../../platform/poller.h"
#include "../../platform/impl/pollerdata.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the io poller data type
typedef struct __tb_co_pollerdata_io_t
{
// the suspended coroutine for waiting poller/recv
tb_coroutine_t* co_recv;
// the suspended coroutine for waiting poller/send
tb_coroutine_t* co_send;
// the waited events for poller
tb_uint16_t poller_events_wait;
// the saved events for poller (triggered)
tb_uint16_t poller_events_save;
}tb_co_pollerdata_io_t, *tb_co_pollerdata_io_ref_t;
// the io scheduler type
typedef struct __tb_co_scheduler_io_t
{
// is stopped?
tb_bool_t stop;
// the scheduler
tb_co_scheduler_t* scheduler;
// the poller
tb_poller_ref_t poller;
// the timer
tb_timer_ref_t timer;
// the low-precision timer (faster)
tb_ltimer_ref_t ltimer;
// the poller data
tb_pollerdata_t pollerdata;
// the poller data pool
tb_fixed_pool_ref_t pollerdata_pool;
}tb_co_scheduler_io_t, *tb_co_scheduler_io_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* init io scheduler
*
* @param scheduler the scheduler
*
* @return the io scheduler
*/
tb_co_scheduler_io_ref_t tb_co_scheduler_io_init(tb_co_scheduler_t* scheduler);
/*! exit io scheduler
*
* @param scheduler_io the io scheduler
*/
tb_void_t tb_co_scheduler_io_exit(tb_co_scheduler_io_ref_t scheduler_io);
/* need io scheduler
*
* ensure the io scheduler has been initialized
*
* @param scheduler the scheduler, get self scheduler if be null
*
* @return the io scheduler
*/
tb_co_scheduler_io_ref_t tb_co_scheduler_io_need(tb_co_scheduler_t* scheduler);
/* kill the current io scheduler
*
* @param scheduler_io the io scheduler
*/
tb_void_t tb_co_scheduler_io_kill(tb_co_scheduler_io_ref_t scheduler_io);
/* sleep the current coroutine
*
* @param scheduler_io the io scheduler
* @param interval the interval (ms), infinity: -1
*
* @return the user private data from resume(priv)
*/
tb_pointer_t tb_co_scheduler_io_sleep(tb_co_scheduler_io_ref_t scheduler_io, tb_long_t interval);
/*! wait io events
*
* @param scheduler_io the io scheduler
* @param object the poller object, socket or pipe
* @param events the waited events
* @param timeout the timeout, infinity: -1
*
* @return > 0: the events, 0: timeout, -1: failed
*/
tb_long_t tb_co_scheduler_io_wait(tb_co_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object, tb_size_t events, tb_long_t timeout);
/*! wait process status
*
* @param scheduler_io the io scheduler
* @param object the process poller object
* @param pstatus the process exited status pointer, maybe null
* @param timeout the timeout, infinity: -1
*
* @return > 0: process exited, 0: timeout, -1: failed
*/
tb_long_t tb_co_scheduler_io_wait_proc(tb_co_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object, tb_long_t* pstatus, tb_long_t timeout);
/*! wait fwatcher event
*
* @param scheduler_io the io scheduler
* @param object the process poller object
* @param pevent the fwatcher event pointer
* @param timeout the timeout, infinity: -1
*
* @return > 0: has event, 0: timeout, -1: failed
*/
tb_long_t tb_co_scheduler_io_wait_fwatcher(tb_co_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object, tb_fwatcher_event_t* pevent, tb_long_t timeout);
/*! cancel io events for the given poller object
*
* @param scheduler_io the io scheduler
* @param object the poller object
*
* @return tb_true or tb_false
*/
tb_bool_t tb_co_scheduler_io_cancel(tb_co_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object);
/* get the current io scheduler
*
* @return the io scheduler
*/
tb_co_scheduler_io_ref_t tb_co_scheduler_io_self(tb_noarg_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/coroutine/impl/stackless/ 0000775 0000000 0000000 00000000000 14671175054 0021222 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/coroutine/impl/stackless/coroutine.h 0000664 0000000 0000000 00000007436 14671175054 0023414 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file coroutine.h
*
*/
#ifndef TB_COROUTINE_IMPL_STACKLESS_COROUTINE_H
#define TB_COROUTINE_IMPL_STACKLESS_COROUTINE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the coroutine wait type
typedef struct __tb_lo_coroutine_rs_wait_t
{
// the waited poller object
tb_poller_object_t object;
#ifndef TB_CONFIG_MICRO_ENABLE
// the timer task pointer for ltimer or timer
tb_cpointer_t task;
// is ltimer?
tb_sint32_t is_ltimer : 1;
// the process status
tb_long_t object_event;
// has pending process status?
tb_uint16_t object_pending : 1;
// waiting process?
tb_uint16_t object_waiting : 1;
#endif
// the waited result
tb_sint32_t result : 16;
}tb_lo_coroutine_rs_wait_t;
/// the stackless coroutine type
typedef struct __tb_lo_coroutine_t
{
// the coroutine core
tb_lo_core_t core;
// the list entry
tb_list_entry_t entry;
// the coroutine function
tb_lo_coroutine_func_t func;
// the user private data of the coroutine function
tb_cpointer_t priv;
// the user private data free function
tb_lo_coroutine_free_t free;
// the scheduler
tb_lo_scheduler_ref_t scheduler;
// the passed private data between resume() and suspend()
union
{
// the arguments for wait()
tb_lo_coroutine_rs_wait_t wait;
} rs;
}tb_lo_coroutine_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* init coroutine
*
* @param scheduler the scheduler
* @param func the coroutine function
* @param priv the passed user private data as the argument of function
* @param free the user private data free function
*
* @return the coroutine
*/
tb_lo_coroutine_t* tb_lo_coroutine_init(tb_lo_scheduler_ref_t scheduler, tb_lo_coroutine_func_t func, tb_cpointer_t priv, tb_lo_coroutine_free_t free);
/* reinit the given coroutine
*
* @param coroutine the coroutine
* @param func the coroutine function
* @param priv the passed user private data as the argument of function
* @param free the user private data free function
*
* @return tb_true or tb_false
*/
tb_bool_t tb_lo_coroutine_reinit(tb_lo_coroutine_t* coroutine, tb_lo_coroutine_func_t func, tb_cpointer_t priv, tb_lo_coroutine_free_t free);
/* exit coroutine
*
* @param coroutine the coroutine
*/
tb_void_t tb_lo_coroutine_exit(tb_lo_coroutine_t* coroutine);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/coroutine/impl/stackless/prefix.h 0000664 0000000 0000000 00000001763 14671175054 0022677 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_COROUTINE_IMPL_STACKLESS_PREFIX_H
#define TB_COROUTINE_IMPL_STACKLESS_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#include "../../stackless/coroutine.h"
#include "../../../container/container.h"
#endif
tbox-1.7.6/src/tbox/coroutine/impl/stackless/scheduler.h 0000664 0000000 0000000 00000007124 14671175054 0023355 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file scheduler.h
*
*/
#ifndef TB_COROUTINE_IMPL_STACKLESS_SCHEDULER_H
#define TB_COROUTINE_IMPL_STACKLESS_SCHEDULER_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "coroutine.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// get the running coroutine
#define tb_lo_scheduler_running(scheduler) ((scheduler)->running)
// get the ready coroutines count
#define tb_lo_scheduler_ready_count(scheduler) tb_list_entry_size(&(scheduler)->coroutines_ready)
// get the suspended coroutines count
#define tb_lo_scheduler_suspend_count(scheduler) tb_list_entry_size(&(scheduler)->coroutines_suspend)
// get the io scheduler
#define tb_lo_scheduler_io(scheduler) ((scheduler)->scheduler_io)
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the io scheduler type
struct __tb_lo_scheduler_io_t;
/// the stackless coroutine scheduler type
typedef struct __tb_lo_scheduler_t
{
// is stopped
tb_bool_t stopped;
// the running coroutine
tb_lo_coroutine_t* running;
// the io scheduler
struct __tb_lo_scheduler_io_t* scheduler_io;
// the dead coroutines
tb_list_entry_head_t coroutines_dead;
/* the ready coroutines
*
* ready: head -> ready -> .. -> running -> .. -> ready -> ..->
* | |
* ---------------------------<-----------------------
*/
tb_list_entry_head_t coroutines_ready;
// the suspend coroutines
tb_list_entry_head_t coroutines_suspend;
}tb_lo_scheduler_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* start coroutine
*
* @param scheduler the scheduler
* @param func the coroutine function
* @param priv the passed user private data as the argument of function
* @param free the user private data free function
*
* @return tb_true or tb_false
*/
tb_bool_t tb_lo_scheduler_start(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_func_t func, tb_cpointer_t priv, tb_lo_coroutine_free_t free);
/* resume the given coroutine
*
* @param scheduler the scheduler
* @param coroutine the coroutine
*/
tb_void_t tb_lo_scheduler_resume(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_t* coroutine);
/* get the current scheduler
*
* @return the scheduler
*/
tb_lo_scheduler_ref_t tb_lo_scheduler_self_(tb_noarg_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/coroutine/impl/stackless/scheduler_io.c 0000664 0000000 0000000 00000060426 14671175054 0024043 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file scheduler_io.c
* @ingroup coroutine
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "scheduler_io"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "scheduler_io.h"
#include "coroutine.h"
#include "../../stackless/coroutine.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the ltimer grow
#ifdef __tb_small__
# define TB_SCHEDULER_IO_LTIMER_GROW (64)
#else
# define TB_SCHEDULER_IO_LTIMER_GROW (4096)
#endif
// the timer grow
#define TB_SCHEDULER_IO_TIMER_GROW (TB_SCHEDULER_IO_LTIMER_GROW >> 4)
// the poller data grow
#ifdef __tb_small__
# define TB_SCHEDULER_IO_POLLERDATA_GROW (64)
#else
# define TB_SCHEDULER_IO_POLLERDATA_GROW (4096)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_void_t tb_lo_scheduler_io_resume(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_t* coroutine, tb_size_t events)
{
#ifndef TB_CONFIG_MICRO_ENABLE
// exists the timer task? remove it
tb_cpointer_t task = coroutine->rs.wait.task;
if (task)
{
// get io scheduler
tb_lo_scheduler_io_ref_t scheduler_io = tb_lo_scheduler_io(scheduler);
tb_assert(scheduler_io && scheduler_io->poller);
// remove the timer task
if (coroutine->rs.wait.is_ltimer) tb_ltimer_task_exit(scheduler_io->ltimer, (tb_ltimer_task_ref_t)task);
else tb_timer_task_exit(scheduler_io->timer, (tb_timer_task_ref_t)task);
coroutine->rs.wait.task = tb_null;
}
#endif
// return events
coroutine->rs.wait.result = (tb_sint32_t)((events & TB_POLLER_EVENT_ERROR)? -1 : events);
// resume the coroutine
tb_lo_scheduler_resume(scheduler, coroutine);
}
#ifndef TB_CONFIG_MICRO_ENABLE
static tb_void_t tb_lo_scheduler_io_timeout(tb_bool_t killed, tb_cpointer_t priv)
{
// check
tb_lo_coroutine_t* coroutine = (tb_lo_coroutine_t*)priv;
tb_assert(coroutine);
// get scheduler
tb_lo_scheduler_t* scheduler = (tb_lo_scheduler_t*)coroutine->scheduler;
tb_assert(scheduler);
// trace
tb_trace_d("coroutine(%p): timer(%s) %s", coroutine, coroutine->rs.wait.object.type? "poller" : "sleep", killed? "killed" : "timeout");
// resume the waited coroutine if timer task has been not canceled
if (!killed)
{
// reset the waited coroutines in the poller data
tb_size_t object_type = coroutine->rs.wait.object.type;
#ifndef TB_CONFIG_MICRO_ENABLE
if (object_type == TB_POLLER_OBJECT_PROC)
coroutine->rs.wait.object_waiting = 0;
else
#endif
if (object_type)
{
tb_lo_scheduler_io_ref_t scheduler_io = tb_lo_scheduler_io(scheduler);
tb_lo_pollerdata_io_ref_t pollerdata = (tb_lo_pollerdata_io_ref_t)(scheduler_io? tb_pollerdata_get(&scheduler_io->pollerdata, &coroutine->rs.wait.object) : tb_null);
if (pollerdata)
{
if (coroutine == pollerdata->lo_recv)
pollerdata->lo_recv = tb_null;
if (coroutine == pollerdata->lo_send)
pollerdata->lo_send = tb_null;
}
}
// resume the coroutine
tb_lo_scheduler_io_resume(scheduler, coroutine, TB_POLLER_EVENT_NONE);
}
}
#endif
static tb_void_t tb_lo_scheduler_io_events(tb_poller_ref_t poller, tb_poller_object_ref_t object, tb_long_t events, tb_cpointer_t priv)
{
// check
tb_lo_scheduler_io_ref_t scheduler_io = (tb_lo_scheduler_io_ref_t)tb_poller_priv(poller);
tb_assert(scheduler_io && scheduler_io->scheduler && object);
#ifndef TB_CONFIG_MICRO_ENABLE
// is process object?
if (object->type == TB_POLLER_OBJECT_PROC)
{
// resume coroutine and return the process exit status
tb_lo_coroutine_t* coroutine = (tb_lo_coroutine_t*)priv;
tb_assert(coroutine);
coroutine->rs.wait.object_event = events;
// waiting process? resume this coroutine
if (coroutine->rs.wait.object_waiting)
{
coroutine->rs.wait.object_waiting = 0;
tb_lo_scheduler_io_resume(scheduler_io->scheduler, coroutine, 1);
}
else coroutine->rs.wait.object_pending = 1;
return ;
}
#endif
// get pollerdata data
tb_lo_pollerdata_io_ref_t pollerdata = (tb_lo_pollerdata_io_ref_t)tb_pollerdata_get(&scheduler_io->pollerdata, object);
tb_assert(pollerdata);
// get poller events
tb_size_t events_prev_wait = pollerdata->poller_events_wait;
tb_size_t events_prev_save = pollerdata->poller_events_save;
// eof for edge trigger?
if (events & TB_POLLER_EVENT_EOF)
{
// cache this eof as next recv/send event
events &= ~TB_POLLER_EVENT_EOF;
events_prev_save |= events_prev_wait;
pollerdata->poller_events_save = (tb_uint16_t)events_prev_save;
}
// get the waiting coroutines
tb_lo_coroutine_t* lo_recv = (events & TB_POLLER_EVENT_RECV)? pollerdata->lo_recv : tb_null;
tb_lo_coroutine_t* lo_send = (events & TB_POLLER_EVENT_SEND)? pollerdata->lo_send : tb_null;
// trace
tb_trace_d("object: %p, trigger events %lu, lo_recv(%p), lo_send(%p)", object->ref.ptr, events, lo_recv, lo_send);
// return the events result for the waiting coroutines
if (lo_recv && lo_recv == lo_send)
{
pollerdata->lo_recv = tb_null;
pollerdata->lo_send = tb_null;
tb_lo_scheduler_io_resume(scheduler_io->scheduler, lo_recv, events);
}
else
{
if (lo_recv)
{
pollerdata->lo_recv = tb_null;
tb_lo_scheduler_io_resume(scheduler_io->scheduler, lo_recv, events & ~TB_POLLER_EVENT_SEND);
events &= ~TB_POLLER_EVENT_RECV;
}
if (lo_send)
{
pollerdata->lo_send = tb_null;
tb_lo_scheduler_io_resume(scheduler_io->scheduler, lo_send, events & ~TB_POLLER_EVENT_RECV);
events &= ~TB_POLLER_EVENT_SEND;
}
// no coroutines are waiting? cache this events
if ((events & TB_POLLER_EVENT_RECV) || (events & TB_POLLER_EVENT_SEND))
{
// trace
tb_trace_d("object: %p, cache events %lu", object->ref.ptr, events);
// cache this events
events_prev_save |= events;
pollerdata->poller_events_save = (tb_uint16_t)events_prev_save;
}
}
}
#ifndef TB_CONFIG_MICRO_ENABLE
static tb_bool_t tb_lo_scheduler_io_timer_spak(tb_lo_scheduler_io_ref_t scheduler_io)
{
// check
tb_assert(scheduler_io && scheduler_io->timer && scheduler_io->ltimer);
// spak ctime
tb_cache_time_spak();
// spak timer
if (!tb_timer_spak(scheduler_io->timer)) return tb_false;
// spak ltimer
if (!tb_ltimer_spak(scheduler_io->ltimer)) return tb_false;
// pk
return tb_true;
}
static tb_long_t tb_lo_scheduler_io_timer_delay(tb_lo_scheduler_io_ref_t scheduler_io)
{
// check
tb_assert(scheduler_io && scheduler_io->timer && scheduler_io->ltimer);
// the delay
tb_size_t delay = tb_timer_delay(scheduler_io->timer);
// the ldelay
tb_size_t ldelay = tb_ltimer_delay(scheduler_io->ltimer);
// return the timer delay
return tb_min(delay, ldelay);
}
#else
static __tb_inline__ tb_long_t tb_lo_scheduler_io_timer_delay(tb_lo_scheduler_io_ref_t scheduler_io)
{
return 1000;
}
#endif
static tb_void_t tb_lo_scheduler_io_loop(tb_lo_coroutine_ref_t coroutine, tb_cpointer_t priv)
{
// check
tb_lo_scheduler_io_ref_t scheduler_io = (tb_lo_scheduler_io_ref_t)priv;
tb_assert(scheduler_io && scheduler_io->poller);
// the scheduler
tb_lo_scheduler_t* scheduler = scheduler_io->scheduler;
tb_assert(scheduler);
// enter coroutine
tb_lo_coroutine_enter(coroutine)
{
// loop
while (!scheduler->stopped)
{
// finish all other ready coroutines first
while (tb_lo_scheduler_ready_count(scheduler) > 1)
{
// yield it
tb_lo_coroutine_yield();
#ifndef TB_CONFIG_MICRO_ENABLE
// spak timer
if (!tb_lo_scheduler_io_timer_spak(scheduler_io)) break;
#endif
}
// no more suspended coroutines? loop end
tb_check_break(tb_lo_scheduler_suspend_count(scheduler));
// trace
tb_trace_d("loop: wait %ld ms ..", tb_lo_scheduler_io_timer_delay(scheduler_io));
// no more ready coroutines? wait io events and timers (TODO)
if (tb_poller_wait(scheduler_io->poller, tb_lo_scheduler_io_events, tb_lo_scheduler_io_timer_delay(scheduler_io)) < 0) break;
#ifndef TB_CONFIG_MICRO_ENABLE
// spak timer
if (!tb_lo_scheduler_io_timer_spak(scheduler_io)) break;
#endif
}
}
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_lo_scheduler_io_ref_t tb_lo_scheduler_io_init(tb_lo_scheduler_t* scheduler)
{
// done
tb_bool_t ok = tb_false;
tb_lo_scheduler_io_ref_t scheduler_io = tb_null;
do
{
// init io scheduler
scheduler_io = tb_malloc0_type(tb_lo_scheduler_io_t);
tb_assert_and_check_break(scheduler_io);
// save scheduler
scheduler_io->scheduler = (tb_lo_scheduler_t*)scheduler;
// init poller
scheduler_io->poller = tb_poller_init(scheduler_io);
tb_assert_and_check_break(scheduler_io->poller);
// attach poller
tb_poller_attach(scheduler_io->poller);
#ifndef TB_CONFIG_MICRO_ENABLE
// init timer and using cache time
scheduler_io->timer = tb_timer_init(TB_SCHEDULER_IO_TIMER_GROW, tb_true);
tb_assert_and_check_break(scheduler_io->timer);
// init ltimer and using cache time
scheduler_io->ltimer = tb_ltimer_init(TB_SCHEDULER_IO_LTIMER_GROW, TB_LTIMER_TICK_S, tb_true);
tb_assert_and_check_break(scheduler_io->ltimer);
#endif
// init poller data pool
scheduler_io->pollerdata_pool = tb_fixed_pool_init(tb_null, TB_SCHEDULER_IO_POLLERDATA_GROW, sizeof(tb_lo_pollerdata_io_t), tb_null, tb_null, tb_null);
tb_assert_and_check_break(scheduler_io->pollerdata_pool);
// init poller data
tb_pollerdata_init(&scheduler_io->pollerdata);
// start the io loop coroutine
if (!tb_lo_coroutine_start((tb_lo_scheduler_ref_t)scheduler, tb_lo_scheduler_io_loop, scheduler_io, tb_null)) break;
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit io scheduler
if (scheduler_io) tb_lo_scheduler_io_exit(scheduler_io);
scheduler_io = tb_null;
}
// ok?
return scheduler_io;
}
tb_void_t tb_lo_scheduler_io_exit(tb_lo_scheduler_io_ref_t scheduler_io)
{
// check
tb_assert_and_check_return(scheduler_io);
// exit poller data
tb_pollerdata_exit(&scheduler_io->pollerdata);
// exit poller data pool
if (scheduler_io->pollerdata_pool) tb_fixed_pool_exit(scheduler_io->pollerdata_pool);
scheduler_io->pollerdata_pool = tb_null;
// exit poller
if (scheduler_io->poller) tb_poller_exit(scheduler_io->poller);
scheduler_io->poller = tb_null;
#ifndef TB_CONFIG_MICRO_ENABLE
// exit timer
if (scheduler_io->timer) tb_timer_exit(scheduler_io->timer);
scheduler_io->timer = tb_null;
// exit ltimer
if (scheduler_io->ltimer) tb_ltimer_exit(scheduler_io->ltimer);
scheduler_io->ltimer = tb_null;
#endif
// clear scheduler
scheduler_io->scheduler = tb_null;
// exit it
tb_free(scheduler_io);
}
tb_lo_scheduler_io_ref_t tb_lo_scheduler_io_need(tb_lo_scheduler_t* scheduler)
{
// get the current scheduler
if (!scheduler) scheduler = (tb_lo_scheduler_t*)tb_lo_scheduler_self_();
if (scheduler)
{
// init io scheduler first
if (!scheduler->scheduler_io) scheduler->scheduler_io = tb_lo_scheduler_io_init(scheduler);
tb_assert(scheduler->scheduler_io);
// get the current io scheduler
return (tb_lo_scheduler_io_ref_t)scheduler->scheduler_io;
}
return tb_null;
}
tb_void_t tb_lo_scheduler_io_kill(tb_lo_scheduler_io_ref_t scheduler_io)
{
// check
tb_assert_and_check_return(scheduler_io);
// trace
tb_trace_d("kill: ..");
#ifndef TB_CONFIG_MICRO_ENABLE
// kill timer
if (scheduler_io->timer) tb_timer_kill(scheduler_io->timer);
// kill ltimer
if (scheduler_io->ltimer) tb_ltimer_kill(scheduler_io->ltimer);
#endif
// kill poller
if (scheduler_io->poller) tb_poller_kill(scheduler_io->poller);
}
tb_void_t tb_lo_scheduler_io_sleep(tb_lo_scheduler_io_ref_t scheduler_io, tb_long_t interval)
{
#ifndef TB_CONFIG_MICRO_ENABLE
// check
tb_assert_and_check_return(scheduler_io && scheduler_io->poller && scheduler_io->scheduler);
// get the current coroutine
tb_lo_coroutine_t* coroutine = tb_lo_scheduler_running(scheduler_io->scheduler);
tb_assert(coroutine);
// trace
tb_trace_d("coroutine(%p): sleep %ld ms ..", coroutine, interval);
// clear waiting task first
coroutine->rs.wait.task = tb_null;
coroutine->rs.wait.object.type = TB_POLLER_OBJECT_NONE;
// infinity?
if (interval > 0)
{
// high-precision interval?
if (interval % 1000)
{
// post task to timer
tb_timer_task_post(scheduler_io->timer, interval, tb_false, tb_lo_scheduler_io_timeout, coroutine);
}
// low-precision interval?
else
{
// post task to ltimer (faster)
tb_ltimer_task_post(scheduler_io->ltimer, interval, tb_false, tb_lo_scheduler_io_timeout, coroutine);
}
}
#else
// not impl
tb_trace_noimpl();
#endif
}
tb_bool_t tb_lo_scheduler_io_wait(tb_lo_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object, tb_size_t events, tb_long_t timeout)
{
// check
tb_assert(scheduler_io && object && scheduler_io->poller && scheduler_io->scheduler && events);
// get the current coroutine
tb_lo_coroutine_t* coroutine = tb_lo_scheduler_running(scheduler_io->scheduler);
tb_assert(coroutine);
// get the poller
tb_poller_ref_t poller = scheduler_io->poller;
tb_assert(poller);
// trace
tb_trace_d("coroutine(%p): wait events(%lu) with %ld ms for poller(%p) ..", coroutine, events, timeout, object->ref.ptr);
// get and allocate a poller data
tb_lo_pollerdata_io_ref_t pollerdata = (tb_lo_pollerdata_io_ref_t)tb_pollerdata_get(&scheduler_io->pollerdata, object);
if (!pollerdata)
{
tb_assert(scheduler_io->pollerdata_pool);
pollerdata = (tb_lo_pollerdata_io_ref_t)tb_fixed_pool_malloc0(scheduler_io->pollerdata_pool);
tb_pollerdata_set(&scheduler_io->pollerdata, object, pollerdata);
}
tb_assert_and_check_return_val(pollerdata, -1);
// enable edge-trigger mode if be supported
if (tb_poller_support(poller, TB_POLLER_EVENT_CLEAR))
events |= TB_POLLER_EVENT_CLEAR;
// get the previous poller events
tb_size_t events_wait = events;
if (pollerdata->poller_events_wait)
{
// return the cached events directly if the waiting events exists cache
tb_size_t events_prev_wait = pollerdata->poller_events_wait;
tb_size_t events_prev_save = pollerdata->poller_events_save;
if (events_prev_save && (events_prev_wait & events))
{
// check error?
if (events_prev_save & TB_POLLER_EVENT_ERROR)
{
pollerdata->poller_events_save = 0;
coroutine->rs.wait.result = -1;
return tb_false;
}
// clear cache events
pollerdata->poller_events_save = (tb_uint16_t)(events_prev_save & ~events);
// return the cached events
coroutine->rs.wait.result = events_prev_save & events;
return tb_false;
}
// modify the wait events and reserve the pending events in other coroutine
events_wait = events_prev_wait;
if ((events_wait & TB_POLLER_EVENT_RECV) && !pollerdata->lo_recv) events_wait &= ~TB_POLLER_EVENT_RECV;
if ((events_wait & TB_POLLER_EVENT_SEND) && !pollerdata->lo_send) events_wait &= ~TB_POLLER_EVENT_SEND;
events_wait |= events;
// modify poller from poller for waiting events if the waiting events has been changed
if ((events_prev_wait & events_wait) != events_wait)
{
// trace
tb_trace_d("modify poller object: %p events: %lx", object, events_wait);
// may be wait recv/send at same time
if (!tb_poller_modify(poller, object, events_wait | TB_POLLER_EVENT_NOEXTRA, tb_null))
{
// trace
tb_trace_e("failed to modify object(%p) to poller on coroutine(%p)!", object->ref.ptr, coroutine);
coroutine->rs.wait.result = -1;
return tb_false;
}
}
}
else
{
// trace
tb_trace_d("insert poller object: %p events: %lx", object->ref.ptr, events_wait);
// insert poller to poller for waiting events
if (!tb_poller_insert(poller, object, events_wait | TB_POLLER_EVENT_NOEXTRA, tb_null))
{
// trace
tb_trace_e("failed to insert object(%p) to poller on coroutine(%p)!", object->ref.ptr, coroutine);
coroutine->rs.wait.result = -1;
return tb_false;
}
}
#ifndef TB_CONFIG_MICRO_ENABLE
// exists timeout?
tb_cpointer_t task = tb_null;
tb_bool_t is_ltimer = tb_false;
if (timeout >= 0)
{
// high-precision interval?
if (timeout % 1000)
{
// init task for timer
task = tb_timer_task_init(scheduler_io->timer, timeout, tb_false, tb_lo_scheduler_io_timeout, coroutine);
tb_assert_and_check_return_val(task, tb_false);
}
// low-precision interval?
else
{
// init task for ltimer (faster)
task = tb_ltimer_task_init(scheduler_io->ltimer, timeout, tb_false, tb_lo_scheduler_io_timeout, coroutine);
tb_assert_and_check_return_val(task, tb_false);
// mark as low-precision timer
is_ltimer = tb_true;
}
}
// save the timer task to coroutine
coroutine->rs.wait.task = task;
coroutine->rs.wait.is_ltimer = is_ltimer;
#endif
coroutine->rs.wait.object = *object;
coroutine->rs.wait.result = 0;
// save waiting events
pollerdata->poller_events_wait = (tb_uint16_t)events_wait;
pollerdata->poller_events_save = 0;
// save the current coroutine
if (events & TB_POLLER_EVENT_RECV) pollerdata->lo_recv = coroutine;
if (events & TB_POLLER_EVENT_SEND) pollerdata->lo_send = coroutine;
// suspend the current coroutine
return tb_true;
}
#ifndef TB_CONFIG_MICRO_ENABLE
tb_bool_t tb_lo_scheduler_io_wait_proc(tb_lo_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object, tb_long_t timeout)
{
// check
tb_assert(scheduler_io && scheduler_io->poller && scheduler_io->scheduler);
tb_assert(object && object->type == TB_POLLER_OBJECT_PROC && object->ref.proc);
// get the current coroutine
tb_lo_coroutine_t* coroutine = tb_lo_scheduler_running(scheduler_io->scheduler);
tb_assert(coroutine);
// get the poller
tb_poller_ref_t poller = scheduler_io->poller;
tb_assert(poller);
// trace
tb_trace_d("coroutine(%p): wait process object(%p) with %ld ms ..", coroutine, object->ref.proc, timeout);
// has pending process status?
if (coroutine->rs.wait.object_pending)
{
coroutine->rs.wait.object_pending = 0;
coroutine->rs.wait.result = 1;
return tb_false;
}
// insert poller object to poller for waiting process
if (!tb_poller_insert(poller, object, 0, coroutine))
{
// trace
tb_trace_e("failed to insert process object(%p) to poller on coroutine(%p)!", object->ref.proc, coroutine);
coroutine->rs.wait.result = -1;
return tb_false;
}
// exists timeout?
tb_cpointer_t task = tb_null;
tb_bool_t is_ltimer = tb_false;
if (timeout >= 0)
{
// high-precision interval?
if (timeout % 1000)
{
// init task for timer
task = tb_timer_task_init(scheduler_io->timer, timeout, tb_false, tb_lo_scheduler_io_timeout, coroutine);
tb_assert_and_check_return_val(task, tb_false);
}
// low-precision interval?
else
{
// init task for ltimer (faster)
task = tb_ltimer_task_init(scheduler_io->ltimer, timeout, tb_false, tb_lo_scheduler_io_timeout, coroutine);
tb_assert_and_check_return_val(task, tb_false);
// mark as low-precision timer
is_ltimer = tb_true;
}
}
// save the timer task to coroutine
coroutine->rs.wait.task = task;
coroutine->rs.wait.object = *object;
coroutine->rs.wait.is_ltimer = is_ltimer;
coroutine->rs.wait.object_event = 0;
coroutine->rs.wait.object_pending = 0;
coroutine->rs.wait.object_waiting = 1;
// suspend the current coroutine
return tb_true;
}
#endif
tb_bool_t tb_lo_scheduler_io_cancel(tb_lo_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object)
{
// check
tb_assert(scheduler_io && object && scheduler_io->poller && scheduler_io->scheduler);
// get the current coroutine
tb_lo_coroutine_t* coroutine = tb_lo_scheduler_running(scheduler_io->scheduler);
tb_check_return_val(coroutine, tb_false);
// trace
tb_trace_d("coroutine(%p): cancel poller object(%p) ..", coroutine, object->ref.ptr);
#ifndef TB_CONFIG_MICRO_ENABLE
// cancel process object
if (object->type == TB_POLLER_OBJECT_PROC)
{
// clear process status
coroutine->rs.wait.object_event = 0;
coroutine->rs.wait.object_pending = 0;
coroutine->rs.wait.object_waiting = 0;
// remove the previous poller object first if exists
if (!tb_poller_remove(scheduler_io->poller, object))
{
// trace
tb_trace_e("failed to remove object(%p) to poller on coroutine(%p)!", object->ref.ptr, coroutine);
return tb_false;
}
return tb_true;
}
#endif
// reset the pollerdata data
tb_lo_pollerdata_io_ref_t pollerdata = (tb_lo_pollerdata_io_ref_t)tb_pollerdata_get(&scheduler_io->pollerdata, object);
if (pollerdata)
{
// clear the waiting coroutines
pollerdata->lo_recv = tb_null;
pollerdata->lo_send = tb_null;
// remove the this poller from poller
if (pollerdata->poller_events_wait)
{
// remove the previous poller first if exists
if (!tb_poller_remove(scheduler_io->poller, object))
{
// trace
tb_trace_e("failed to remove object(%p) to poller on coroutine(%p)!", object->ref.ptr, coroutine);
// failed
coroutine->rs.wait.result = -1;
return tb_false;
}
// remove the poller events
coroutine->rs.wait.result = 0;
pollerdata->poller_events_wait = 0;
pollerdata->poller_events_save = 0;
return tb_true;
}
}
// no this poller
return tb_false;
}
tb_lo_scheduler_io_ref_t tb_lo_scheduler_io_self()
{
// get the current scheduler
tb_lo_scheduler_t* scheduler = (tb_lo_scheduler_t*)tb_lo_scheduler_self_();
// get the current io scheduler
return scheduler? (tb_lo_scheduler_io_ref_t)scheduler->scheduler_io : tb_null;
}
tbox-1.7.6/src/tbox/coroutine/impl/stackless/scheduler_io.h 0000664 0000000 0000000 00000011526 14671175054 0024045 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file scheduler_io.h
* @ingroup coroutine
*
*/
#ifndef TB_COROUTINE_IMPL_STACKLESS_SCHEDULER_IO_H
#define TB_COROUTINE_IMPL_STACKLESS_SCHEDULER_IO_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "scheduler.h"
#include "../../../memory/fixed_pool.h"
#include "../../../platform/poller.h"
#include "../../../platform/impl/pollerdata.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the io poller data type
typedef struct __tb_lo_pollerdata_io_t
{
// the suspended coroutine for waiting poller/recv
tb_lo_coroutine_t* lo_recv;
// the suspended coroutine for waiting poller/send
tb_lo_coroutine_t* lo_send;
// the waited events for poller
tb_uint16_t poller_events_wait;
// the saved events for poller (triggered)
tb_uint16_t poller_events_save;
}tb_lo_pollerdata_io_t, *tb_lo_pollerdata_io_ref_t;
// the io scheduler type
typedef struct __tb_lo_scheduler_io_t
{
// is stopped?
tb_bool_t stop;
// the scheduler
tb_lo_scheduler_t* scheduler;
// the poller
tb_poller_ref_t poller;
#ifndef TB_CONFIG_MICRO_ENABLE
// the timer
tb_timer_ref_t timer;
// the low-precision timer (faster)
tb_ltimer_ref_t ltimer;
#endif
// the poller data
tb_pollerdata_t pollerdata;
// the poller data pool
tb_fixed_pool_ref_t pollerdata_pool;
}tb_lo_scheduler_io_t, *tb_lo_scheduler_io_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* init io scheduler
*
* @param scheduler the scheduler
*
* @return the io scheduler
*/
tb_lo_scheduler_io_ref_t tb_lo_scheduler_io_init(tb_lo_scheduler_t* scheduler);
/* exit io scheduler
*
* @param scheduler_io the io scheduler
*/
tb_void_t tb_lo_scheduler_io_exit(tb_lo_scheduler_io_ref_t scheduler_io);
/* need io scheduler
*
* ensure the io scheduler has been initialized
*
* @param scheduler the scheduler
*
* @return the io scheduler
*/
tb_lo_scheduler_io_ref_t tb_lo_scheduler_io_need(tb_lo_scheduler_t* scheduler);
/* kill the current io scheduler
*
* @param scheduler_io the io scheduler
*/
tb_void_t tb_lo_scheduler_io_kill(tb_lo_scheduler_io_ref_t scheduler_io);
/* sleep the current coroutine
*
* @param scheduler_io the io scheduler
* @param interval the interval (ms), infinity: -1
*/
tb_void_t tb_lo_scheduler_io_sleep(tb_lo_scheduler_io_ref_t scheduler_io, tb_long_t interval);
/* wait io events
*
* @param scheduler_io the io scheduler
* @param object the poller object
* @param events the waited events
* @param timeout the timeout, infinity: -1
*
* @return suspend coroutine if be tb_true
*/
tb_bool_t tb_lo_scheduler_io_wait(tb_lo_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object, tb_size_t events, tb_long_t timeout);
/* wait process status
*
* @param scheduler_io the io scheduler
* @param object the poller object
* @param timeout the timeout, infinity: -1
*
* @return suspend coroutine if be tb_true
*/
tb_bool_t tb_lo_scheduler_io_wait_proc(tb_lo_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object, tb_long_t timeout);
/*! cancel io events for the given poller
*
* @param scheduler_io the io scheduler
* @param object the poller object
*
* return tb_true or tb_false
*/
tb_bool_t tb_lo_scheduler_io_cancel(tb_lo_scheduler_io_ref_t scheduler_io, tb_poller_object_ref_t object);
/* get the current io scheduler
*
* @return the io scheduler
*/
tb_lo_scheduler_io_ref_t tb_lo_scheduler_io_self(tb_noarg_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/coroutine/impl/stackless/stackless.h 0000664 0000000 0000000 00000001707 14671175054 0023374 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file coroutine.h
*
*/
#ifndef TB_COROUTINE_IMPL_STACKLESS_H
#define TB_COROUTINE_IMPL_STACKLESS_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "coroutine.h"
#include "scheduler.h"
#include "scheduler_io.h"
#endif
tbox-1.7.6/src/tbox/coroutine/lock.c 0000664 0000000 0000000 00000003445 14671175054 0017367 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file lock.h
* @ingroup coroutine
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "lock"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "lock.h"
#include "semaphore.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_co_lock_ref_t tb_co_lock_init()
{
// init lock
return (tb_co_lock_ref_t)tb_co_semaphore_init(1);
}
tb_void_t tb_co_lock_exit(tb_co_lock_ref_t self)
{
// exit lock
tb_co_semaphore_exit((tb_co_semaphore_ref_t)self);
}
tb_void_t tb_co_lock_enter(tb_co_lock_ref_t self)
{
// enter lock
tb_co_semaphore_wait((tb_co_semaphore_ref_t)self, -1);
}
tb_bool_t tb_co_lock_enter_try(tb_co_lock_ref_t self)
{
// try to enter lock
return tb_co_semaphore_wait((tb_co_semaphore_ref_t)self, 0) > 0;
}
tb_void_t tb_co_lock_leave(tb_co_lock_ref_t self)
{
// leave lock
tb_co_semaphore_post((tb_co_semaphore_ref_t)self, 1);
}
tbox-1.7.6/src/tbox/coroutine/lock.h 0000664 0000000 0000000 00000004061 14671175054 0017367 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file lock.h
* @ingroup coroutine
*
*/
#ifndef TB_COROUTINE_LOCK_H
#define TB_COROUTINE_LOCK_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the coroutine lock ref type
typedef __tb_typeref__(co_lock);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init lock
*
* @return the lock
*/
tb_co_lock_ref_t tb_co_lock_init(tb_noarg_t);
/*! exit lock
*
* @param lock the lock
*/
tb_void_t tb_co_lock_exit(tb_co_lock_ref_t lock);
/*! enter lock
*
* @param lock the lock
*/
tb_void_t tb_co_lock_enter(tb_co_lock_ref_t lock);
/*! try to enter lock
*
* @param lock the lock
*
* @return tb_true or tb_false
*/
tb_bool_t tb_co_lock_enter_try(tb_co_lock_ref_t lock);
/*! leave lock
*
* @param lock the lock
*/
tb_void_t tb_co_lock_leave(tb_co_lock_ref_t lock);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/coroutine/prefix.h 0000664 0000000 0000000 00000001604 14671175054 0017734 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_COROUTINE_PREFIX_H
#define TB_COROUTINE_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/coroutine/scheduler.c 0000664 0000000 0000000 00000015523 14671175054 0020415 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file scheduler.h
* @ingroup scheduler
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "scheduler"
#define TB_TRACE_MODULE_DEBUG (1)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "scheduler.h"
#include "impl/impl.h"
#include "../algorithm/algorithm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
// the self scheduler local
#ifndef __tb_thread_local__
static tb_thread_local_t g_scheduler_self = TB_THREAD_LOCAL_INIT;
#endif
// the global scheduler for the exclusive mode
#ifdef __tb_thread_local__
static __tb_thread_local__ tb_co_scheduler_t* g_scheduler_self_ex = tb_null;
#else
static tb_co_scheduler_t* g_scheduler_self_ex = tb_null;
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_void_t tb_co_scheduler_free(tb_list_entry_head_ref_t coroutines)
{
// check
tb_assert(coroutines);
// free all coroutines
while (tb_list_entry_size(coroutines))
{
// get the next entry from head
tb_list_entry_ref_t entry = tb_list_entry_head(coroutines);
tb_assert(entry);
// remove it from the ready coroutines
tb_list_entry_remove_head(coroutines);
// exit this coroutine
tb_coroutine_exit((tb_coroutine_t*)tb_list_entry0(entry));
}
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_co_scheduler_ref_t tb_co_scheduler_init()
{
// done
tb_bool_t ok = tb_false;
tb_co_scheduler_t* scheduler = tb_null;
do
{
// make scheduler
scheduler = tb_malloc0_type(tb_co_scheduler_t);
tb_assert_and_check_break(scheduler);
// init dead coroutines
tb_list_entry_init(&scheduler->coroutines_dead, tb_coroutine_t, entry, tb_null);
// init ready coroutines
tb_list_entry_init(&scheduler->coroutines_ready, tb_coroutine_t, entry, tb_null);
// init suspend coroutines
tb_list_entry_init(&scheduler->coroutines_suspend, tb_coroutine_t, entry, tb_null);
// init original coroutine
scheduler->original.scheduler = (tb_co_scheduler_ref_t)scheduler;
// init running
scheduler->running = &scheduler->original;
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (scheduler) tb_co_scheduler_exit((tb_co_scheduler_ref_t)scheduler);
scheduler = tb_null;
}
// ok?
return (tb_co_scheduler_ref_t)scheduler;
}
tb_void_t tb_co_scheduler_exit(tb_co_scheduler_ref_t self)
{
// check
tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)self;
tb_assert_and_check_return(scheduler);
// must be stopped
tb_assert(scheduler->stopped);
// exit io scheduler first
if (scheduler->scheduler_io) tb_co_scheduler_io_exit(scheduler->scheduler_io);
scheduler->scheduler_io = tb_null;
// clear running
scheduler->running = tb_null;
// check coroutines
tb_assert(!tb_list_entry_size(&scheduler->coroutines_ready));
tb_assert(!tb_list_entry_size(&scheduler->coroutines_suspend));
// free all dead coroutines
tb_co_scheduler_free(&scheduler->coroutines_dead);
// free all ready coroutines
tb_co_scheduler_free(&scheduler->coroutines_ready);
// free all suspend coroutines
tb_co_scheduler_free(&scheduler->coroutines_suspend);
// exit dead coroutines
tb_list_entry_exit(&scheduler->coroutines_dead);
// exit ready coroutines
tb_list_entry_exit(&scheduler->coroutines_ready);
// exit suspend coroutines
tb_list_entry_exit(&scheduler->coroutines_suspend);
// exit the scheduler
tb_free(scheduler);
}
tb_void_t tb_co_scheduler_kill(tb_co_scheduler_ref_t self)
{
// check
tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)self;
tb_assert_and_check_return(scheduler);
// stop it
scheduler->stopped = tb_true;
// kill the io scheduler
if (scheduler->scheduler_io) tb_co_scheduler_io_kill(scheduler->scheduler_io);
}
tb_void_t tb_co_scheduler_loop(tb_co_scheduler_ref_t self, tb_bool_t exclusive)
{
// check
tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)self;
tb_assert_and_check_return(scheduler);
#ifdef __tb_thread_local__
g_scheduler_self_ex = scheduler;
#else
// is exclusive mode?
if (exclusive) g_scheduler_self_ex = scheduler;
else
{
// init self scheduler local
if (!tb_thread_local_init(&g_scheduler_self, tb_null)) return ;
// update and overide the current scheduler
tb_thread_local_set(&g_scheduler_self, self);
}
#endif
#ifdef TB_CONFIG_OS_WINDOWS
// we need attach poller in the current thread first for iocp/windows
tb_co_scheduler_io_need(scheduler);
#endif
// schedule all ready coroutines
while (tb_list_entry_size(&scheduler->coroutines_ready))
{
// check
tb_assert(tb_coroutine_is_original(scheduler->running));
// get the next entry from head
tb_list_entry_ref_t entry = tb_list_entry_head(&scheduler->coroutines_ready);
tb_assert(entry);
// switch to the next coroutine
tb_co_scheduler_switch(scheduler, (tb_coroutine_t*)tb_list_entry0(entry));
// trace
tb_trace_d("[loop]: ready %lu", tb_list_entry_size(&scheduler->coroutines_ready));
}
// stop it
scheduler->stopped = tb_true;
#ifdef __tb_thread_local__
g_scheduler_self_ex = tb_null;
#else
// is exclusive mode?
if (exclusive) g_scheduler_self_ex = tb_null;
else
{
// clear the current scheduler
tb_thread_local_set(&g_scheduler_self, tb_null);
}
#endif
}
tb_co_scheduler_ref_t tb_co_scheduler_self()
{
// get self scheduler on the current thread
#ifdef __tb_thread_local__
return (tb_co_scheduler_ref_t)g_scheduler_self_ex;
#else
return (tb_co_scheduler_ref_t)(g_scheduler_self_ex? g_scheduler_self_ex : tb_thread_local_get(&g_scheduler_self));
#endif
}
tbox-1.7.6/src/tbox/coroutine/scheduler.h 0000664 0000000 0000000 00000004555 14671175054 0020425 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file scheduler.h
* @ingroup coroutine
*
*/
#ifndef TB_COROUTINE_SCHEDULER_H
#define TB_COROUTINE_SCHEDULER_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the coroutine scheduler ref type
typedef __tb_typeref__(co_scheduler);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init scheduler
*
* @return the scheduler
*/
tb_co_scheduler_ref_t tb_co_scheduler_init(tb_noarg_t);
/*! exit scheduler
*
* @param scheduler the scheduler
*/
tb_void_t tb_co_scheduler_exit(tb_co_scheduler_ref_t scheduler);
/* kill the scheduler
*
* @param scheduler the scheduler
*/
tb_void_t tb_co_scheduler_kill(tb_co_scheduler_ref_t scheduler);
/*! run the scheduler loop
*
* @param schedule the scheduler
* @param exclusive enable exclusive mode, we need ensure only one loop() be called at the same time,
* but it will be faster using thr global scheduler instead of TLS storage
*/
tb_void_t tb_co_scheduler_loop(tb_co_scheduler_ref_t schedule, tb_bool_t exclusive);
/*! get the scheduler of the current coroutine
*
* @return the scheduler
*/
tb_co_scheduler_ref_t tb_co_scheduler_self(tb_noarg_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/coroutine/semaphore.c 0000664 0000000 0000000 00000011457 14671175054 0020424 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file semaphore.h
* @ingroup coroutine
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "semaphore"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "semaphore.h"
#include "coroutine.h"
#include "scheduler.h"
#include "impl/impl.h"
#include "../container/container.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the coroutine semaphore type
typedef struct __tb_co_semaphore_t
{
// the semaphore value
tb_size_t value;
// the waiting coroutines
tb_single_list_entry_head_t waiting;
}tb_co_semaphore_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_co_semaphore_ref_t tb_co_semaphore_init(tb_size_t value)
{
// done
tb_bool_t ok = tb_false;
tb_co_semaphore_t* semaphore = tb_null;
do
{
// make semaphore
semaphore = tb_malloc0_type(tb_co_semaphore_t);
tb_assert_and_check_break(semaphore);
// init value
semaphore->value = value;
// init waiting coroutines
tb_single_list_entry_init(&semaphore->waiting, tb_coroutine_t, rs.single_entry, tb_null);
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (semaphore) tb_co_semaphore_exit((tb_co_semaphore_ref_t)semaphore);
semaphore = tb_null;
}
// ok?
return (tb_co_semaphore_ref_t)semaphore;
}
tb_void_t tb_co_semaphore_exit(tb_co_semaphore_ref_t self)
{
// check
tb_co_semaphore_t* semaphore = (tb_co_semaphore_t*)self;
tb_assert_and_check_return(semaphore);
// check waiting coroutines
tb_assert(!tb_single_list_entry_size(&semaphore->waiting));
// exit waiting coroutines
tb_single_list_entry_exit(&semaphore->waiting);
// exit the semaphore
tb_free(semaphore);
}
tb_void_t tb_co_semaphore_post(tb_co_semaphore_ref_t self, tb_size_t post)
{
// check
tb_co_semaphore_t* semaphore = (tb_co_semaphore_t*)self;
tb_assert_and_check_return(semaphore);
// add the semaphore value
tb_size_t value = semaphore->value + post;
// resume the waiting coroutines
while (value && tb_single_list_entry_size(&semaphore->waiting))
{
// get the next entry from head
tb_single_list_entry_ref_t entry = tb_single_list_entry_head(&semaphore->waiting);
tb_assert_and_check_break(entry);
// remove it from the waiting coroutines
tb_single_list_entry_remove_head(&semaphore->waiting);
// get the waiting coroutine
tb_coroutine_ref_t coroutine = (tb_coroutine_ref_t)tb_single_list_entry(&semaphore->waiting, entry);
// resume this coroutine
tb_coroutine_resume(coroutine, (tb_cpointer_t)tb_true);
// decrease the semaphore value
value--;
}
// update the semaphore value
semaphore->value = value;
}
tb_size_t tb_co_semaphore_value(tb_co_semaphore_ref_t self)
{
// check
tb_co_semaphore_t* semaphore = (tb_co_semaphore_t*)self;
tb_assert_and_check_return_val(semaphore, 0);
// get the semaphore value
return semaphore->value;
}
tb_long_t tb_co_semaphore_wait(tb_co_semaphore_ref_t self, tb_long_t timeout)
{
// check
tb_co_semaphore_t* semaphore = (tb_co_semaphore_t*)self;
tb_assert_and_check_return_val(semaphore, -1);
// attempt to get the semaphore value
tb_long_t ok = 1;
if (semaphore->value) semaphore->value--;
// no semaphore?
else if (timeout)
{
// get the running coroutine
tb_coroutine_t* running = (tb_coroutine_t*)tb_coroutine_self();
tb_assert(running);
// save this coroutine to the waiting coroutines
tb_single_list_entry_insert_tail(&semaphore->waiting, &running->rs.single_entry);
// wait semaphore
ok = (tb_long_t)tb_coroutine_sleep(timeout);
}
// timeout and no waiting
else ok = 0;
// ok?
return ok;
}
tbox-1.7.6/src/tbox/coroutine/semaphore.h 0000664 0000000 0000000 00000004572 14671175054 0020431 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file semaphore.h
* @ingroup coroutine
*
*/
#ifndef TB_COROUTINE_SEMAPHORE_H
#define TB_COROUTINE_SEMAPHORE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the coroutine semaphore ref type
typedef __tb_typeref__(co_semaphore);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init semaphore
*
* @param value the initial semaphore value
*
* @return the semaphore
*/
tb_co_semaphore_ref_t tb_co_semaphore_init(tb_size_t value);
/*! exit semaphore
*
*/
tb_void_t tb_co_semaphore_exit(tb_co_semaphore_ref_t semaphore);
/*! post semaphore
*
* @param semaphore the semaphore
* @param post the post semaphore value
*
*/
tb_void_t tb_co_semaphore_post(tb_co_semaphore_ref_t semaphore, tb_size_t post);
/*! the semaphore value
*
* @param semaphore the semaphore
*
* @return the semaphore value
*/
tb_size_t tb_co_semaphore_value(tb_co_semaphore_ref_t semaphore);
/*! wait semaphore
*
* @param semaphore the semaphore
* @param timeout the timeout
*
* @return ok: 1, timeout: 0, fail: -1
*/
tb_long_t tb_co_semaphore_wait(tb_co_semaphore_ref_t semaphore, tb_long_t timeout);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/coroutine/stackless/ 0000775 0000000 0000000 00000000000 14671175054 0020261 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/coroutine/stackless/core.h 0000664 0000000 0000000 00000013502 14671175054 0021363 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file core.h
* @ingroup coroutine
*
*/
#ifndef TB_COROUTINE_STACKLESS_CORE_H
#define TB_COROUTINE_STACKLESS_CORE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/*
* Copyright (c) 2004-2005, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
// get core from coroutine
#define tb_lo_core(co) ((tb_lo_core_ref_t)(co))
// get core state
#define tb_lo_core_state(co) (tb_lo_core(co)->state)
// set core state
#define tb_lo_core_state_set(co, val) tb_lo_core(co)->state = (val)
#ifdef TB_COMPILER_IS_GCC
/*
* Implementation of local continuations based on the "Labels as
* values" feature of gcc
*
* @author Adam Dunkels
*
* This implementation of local continuations is based on a special
* feature of the GCC C compiler called "labels as values". This
* feature allows assigning pointers with the address of the code
* corresponding to a particular C label.
*
* For more information, see the GCC documentation:
* http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
*/
# define tb_lo_core_init(co) tb_lo_core(co)->branch = tb_null; tb_lo_core(co)->state = TB_STATE_READY
# define tb_lo_core_resume(co) \
if (tb_lo_core(co)->branch) \
{ \
goto *(tb_lo_core(co)->branch); \
} \
else
# define tb_lo_core_record(co) \
do \
{ \
__tb_mconcat_ex__(__tb_lo_core_label, __tb_line__): \
tb_lo_core(co)->branch = &&__tb_mconcat_ex__(__tb_lo_core_label, __tb_line__); \
\
} while(0)
# define tb_lo_core_exit(co) tb_lo_core(co)->branch = tb_null, tb_lo_core(co)->state = TB_STATE_END
#else
/*
* Implementation of local continuations based on switch() statment
*
* @author Adam Dunkels
*
* This implementation of local continuations uses the C switch()
* statement to resume execution of a function somewhere inside the
* function's body. The implementation is based on the fact that
* switch() statements are able to jump directly into the bodies of
* control structures such as if() or while() statmenets.
*
* This implementation borrows heavily from Simon Tatham's coroutines
* implementation in C:
* http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
*
*
*
* WARNING! the implementation using switch() does not work if an
* core_set() is done within another switch() statement!
*/
# define tb_lo_core_init(co) tb_lo_core(co)->branch = 0; tb_lo_core(co)->state = TB_STATE_READY
# define tb_lo_core_resume(co) switch (tb_lo_core(co)->branch) case 0:
# define tb_lo_core_record_(co, label) tb_lo_core(co)->branch = (tb_uint16_t)label; case label:
# define tb_lo_core_exit(co) tb_lo_core(co)->branch = 0, tb_lo_core(co)->state = TB_STATE_END
# ifdef TB_COMPILER_IS_MSVC
# define tb_lo_core_record(co) tb_lo_core_record_(co, __COUNTER__ + 1)
# else
# define tb_lo_core_record(co) tb_lo_core_record_(co, __tb_line__)
# endif
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the core branch type
#ifdef TB_COMPILER_IS_GCC
typedef tb_pointer_t tb_lo_core_branch_t;
#else
typedef tb_uint16_t tb_lo_core_branch_t;
#endif
// the stackless coroutine core type
typedef struct __tb_lo_core_t
{
// the code branch
tb_lo_core_branch_t branch;
/* the state
*
* TB_STATE_READY
* TB_STATE_SUSPEND
* TB_STATE_END
*/
tb_uint8_t state;
}tb_lo_core_t, *tb_lo_core_ref_t;
#endif
tbox-1.7.6/src/tbox/coroutine/stackless/coroutine.c 0000664 0000000 0000000 00000014430 14671175054 0022436 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file coroutine.h
* @ingroup coroutine
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "coroutine"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "coroutine.h"
#include "scheduler.h"
#include "../impl/impl.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
tb_lo_coroutine_t* tb_lo_coroutine_init(tb_lo_scheduler_ref_t scheduler, tb_lo_coroutine_func_t func, tb_cpointer_t priv, tb_lo_coroutine_free_t free)
{
// check
tb_assert_and_check_return_val(scheduler && func, tb_null);
// done
tb_bool_t ok = tb_false;
tb_lo_coroutine_t* coroutine = tb_null;
do
{
// make coroutine
coroutine = tb_malloc0_type(tb_lo_coroutine_t);
tb_assert_and_check_break(coroutine);
// init core
tb_lo_core_init(&coroutine->core);
// save scheduler
coroutine->scheduler = scheduler;
// init function and user private data
coroutine->func = func;
coroutine->priv = priv;
coroutine->free = free;
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (coroutine) tb_lo_coroutine_exit(coroutine);
coroutine = tb_null;
}
// trace
tb_trace_d("init %p", coroutine);
// ok?
return coroutine;
}
tb_bool_t tb_lo_coroutine_reinit(tb_lo_coroutine_t* coroutine, tb_lo_coroutine_func_t func, tb_cpointer_t priv, tb_lo_coroutine_free_t free)
{
// check
tb_assert_and_check_return_val(coroutine && func, tb_false);
tb_assert_and_check_return_val(coroutine->scheduler && tb_lo_core_state(coroutine) == TB_STATE_END, tb_false);
// init core
tb_lo_core_init(&coroutine->core);
// init function and user private data
coroutine->func = func;
coroutine->priv = priv;
coroutine->free = free;
// init rs data
tb_memset(&coroutine->rs, 0, sizeof(coroutine->rs));
// ok
return tb_true;
}
tb_void_t tb_lo_coroutine_exit(tb_lo_coroutine_t* coroutine)
{
// check
tb_assert_and_check_return(coroutine && tb_lo_core_state(coroutine) == TB_STATE_END);
// trace
tb_trace_d("exit: %p", coroutine);
// exit it
tb_free(coroutine);
}
tb_lo_scheduler_ref_t tb_lo_coroutine_scheduler_(tb_lo_coroutine_ref_t self)
{
// check
tb_lo_coroutine_t* coroutine = (tb_lo_coroutine_t*)self;
tb_assert(coroutine);
// get scheduler
return coroutine->scheduler;
}
tb_void_t tb_lo_coroutine_sleep_(tb_lo_coroutine_ref_t self, tb_long_t interval)
{
// check
tb_lo_coroutine_t* coroutine = (tb_lo_coroutine_t*)self;
tb_assert(coroutine);
// get scheduler
tb_lo_scheduler_t* scheduler = (tb_lo_scheduler_t*)coroutine->scheduler;
tb_assert(scheduler);
// init io scheduler first
if (!tb_lo_scheduler_io_need(scheduler)) return ;
// sleep it
tb_lo_scheduler_io_sleep(scheduler->scheduler_io, interval);
}
tb_bool_t tb_lo_coroutine_waitio_(tb_lo_coroutine_ref_t self, tb_poller_object_ref_t object, tb_size_t events, tb_long_t timeout)
{
// check
tb_lo_coroutine_t* coroutine = (tb_lo_coroutine_t*)self;
tb_assert(coroutine);
// get scheduler
tb_lo_scheduler_t* scheduler = (tb_lo_scheduler_t*)coroutine->scheduler;
tb_assert(scheduler);
// init io scheduler first
if (!tb_lo_scheduler_io_need(scheduler)) return tb_false;
// wait it
return tb_lo_scheduler_io_wait(scheduler->scheduler_io, object, events, timeout);
}
#ifndef TB_CONFIG_MICRO_ENABLE
tb_bool_t tb_lo_coroutine_waitproc_(tb_lo_coroutine_ref_t self, tb_poller_object_ref_t object, tb_long_t timeout)
{
// check
tb_lo_coroutine_t* coroutine = (tb_lo_coroutine_t*)self;
tb_assert(coroutine);
// get scheduler
tb_lo_scheduler_t* scheduler = (tb_lo_scheduler_t*)coroutine->scheduler;
tb_assert(scheduler);
// init io scheduler first
if (!tb_lo_scheduler_io_need(scheduler)) return tb_false;
// wait it
return tb_lo_scheduler_io_wait_proc(scheduler->scheduler_io, object, timeout);
}
tb_long_t tb_lo_coroutine_proc_status_(tb_lo_coroutine_ref_t self)
{
// check
tb_lo_coroutine_t* coroutine = (tb_lo_coroutine_t*)self;
tb_assert(coroutine);
// get process status
return coroutine->rs.wait.object_event;
}
#endif
tb_long_t tb_lo_coroutine_waitret_(tb_lo_coroutine_ref_t self)
{
// check
tb_lo_coroutine_t* coroutine = (tb_lo_coroutine_t*)self;
tb_assert(coroutine);
// get wait result
return coroutine->rs.wait.result;
}
tb_void_t tb_lo_coroutine_pass_free_(tb_cpointer_t priv)
{
if (priv) tb_free(priv);
}
tb_pointer_t tb_lo_coroutine_pass1_make_(tb_size_t type_size, tb_cpointer_t value, tb_size_t offset, tb_size_t size)
{
// check
tb_assert(type_size && value && offset + size <= type_size);
// make data
tb_byte_t* data = tb_malloc0_bytes(type_size);
if (data) tb_memcpy(data + offset, value, size);
// ok?
return data;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* public implementation
*/
tb_bool_t tb_lo_coroutine_start(tb_lo_scheduler_ref_t self, tb_lo_coroutine_func_t func, tb_cpointer_t priv, tb_lo_coroutine_free_t free)
{
return tb_lo_scheduler_start((tb_lo_scheduler_t*)self, func, priv, free);
}
tb_void_t tb_lo_coroutine_resume(tb_lo_coroutine_ref_t self)
{
tb_lo_scheduler_resume((tb_lo_scheduler_t*)tb_lo_coroutine_scheduler_(self), (tb_lo_coroutine_t*)self);
}
tbox-1.7.6/src/tbox/coroutine/stackless/coroutine.h 0000664 0000000 0000000 00000032162 14671175054 0022445 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file coroutine.h
* @ingroup coroutine
*
*/
#ifndef TB_COROUTINE_STACKLESS_COROUTINE_H
#define TB_COROUTINE_STACKLESS_COROUTINE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "core.h"
#include "scheduler.h"
#include "../../libc/libc.h"
#include "../../platform/poller.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/// the self coroutine
#define tb_lo_coroutine_self() (co__)
/* enter coroutine
*
* @code
*
// before
tb_lo_coroutine_enter(co)
{
for (i = 0; i < 100; i++)
{
tb_lo_coroutine_yield();
}
}
// after expanding again (init: branch = 0, state = TB_STATE_READY)
tb_lo_coroutine_ref_t co__ = co;
tb_int_t lo_yield_flag__ = 1;
for (; lo_yield_flag__; tb_lo_core(co__)->branch = 0, tb_lo_core(co__)->state = TB_STATE_END, lo_yield_flag__ = 0)
switch (tb_lo_core(co__)->branch)
case 0:
{
for (i = 0; i < 100; i++)
{
lo_yield_flag__ = 0;
tb_lo_core(co__)->branch = __tb_line__; case __tb_line__:;
if (lo_yield_flag__ == 0)
return ;
}
}
// or ..
// after expanding again for gcc label (init: branch = tb_null, state = TB_STATE_READY)
tb_lo_coroutine_ref_t co__ = co;
tb_int_t lo_yield_flag__ = 1;
for (; lo_yield_flag__; tb_lo_core(co__)->branch = tb_null, tb_lo_core(co__)->state = TB_STATE_END, lo_yield_flag__ = 0)
if (tb_lo_core(co)->branch)
{
goto *(tb_lo_core(co)->branch);
}
else
{
for (i = 0; i < 100; i++)
{
lo_yield_flag__ = 0;
do
{
__tb_mconcat_ex__(__tb_lo_core_label, __tb_line__):
tb_lo_core(co)->branch = &&__tb_mconcat_ex__(__tb_lo_core_label, __tb_line__);
} while(0)
if (lo_yield_flag__ == 0)
return ;
}
}
* @endcode
*/
#define tb_lo_coroutine_enter(co) \
tb_lo_coroutine_ref_t co__ = (co); \
tb_int_t lo_yield_flag__ = 1; \
for ( ; lo_yield_flag__; tb_lo_core_exit(tb_lo_coroutine_self()), lo_yield_flag__ = 0) \
tb_lo_core_resume(tb_lo_coroutine_self())
/// yield coroutine
#define tb_lo_coroutine_yield() \
do \
{ \
lo_yield_flag__ = 0; \
tb_lo_core_record(co__); \
if (lo_yield_flag__ == 0) \
return ; \
\
} while(0)
/*! suspend current coroutine
*
* the scheduler will move this coroutine to the suspended coroutines after the function be returned
*
* @code
*
// before
tb_lo_coroutine_enter(co)
{
for (i = 0; i < 100; i++)
{
tb_lo_coroutine_yield();
tb_lo_coroutine_suspend();
}
}
// after expanding again (init: branch = 0, state = TB_STATE_READY)
tb_lo_coroutine_ref_t co__ = co;
tb_int_t lo_yield_flag__ = 1;
for (; lo_yield_flag__; tb_lo_core(co__)->branch = 0, tb_lo_core(co__)->state = TB_STATE_END, lo_yield_flag__ = 0)
switch (tb_lo_core(co__)->branch)
case 0:
{
for (i = 0; i < 100; i++)
{
lo_yield_flag__ = 0;
tb_lo_core(co__)->branch = __tb_line__; case __tb_line__:;
if (lo_yield_flag__ == 0)
return ;
// suspend coroutine
tb_lo_core(co__)->state = TB_STATE_SUSPEND;
tb_lo_core(co__)->branch = __tb_line__; case __tb_line__:;
if (tb_lo_core(co__)->state == TB_STATE_SUSPEND)
return ;
}
}
* @endcode
*/
#define tb_lo_coroutine_suspend() \
do \
{ \
tb_used(&lo_yield_flag__); \
tb_lo_core_state_set(tb_lo_coroutine_self(), TB_STATE_SUSPEND); \
tb_lo_core_record(tb_lo_coroutine_self()); \
if (tb_lo_core_state(tb_lo_coroutine_self()) == TB_STATE_SUSPEND) \
return ; \
\
} while(0)
/// sleep some time
#define tb_lo_coroutine_sleep(interval) \
do \
{ \
if (interval) \
{ \
tb_lo_coroutine_sleep_(tb_lo_coroutine_self(), interval); \
tb_lo_coroutine_suspend(); \
} \
\
} while(0)
/// wait io socket events
#define tb_lo_coroutine_wait_sock(sock_, events, interval) \
do \
{ \
tb_poller_object_t object; \
object.type = TB_POLLER_OBJECT_SOCK; \
object.ref.sock = sock_; \
if (tb_lo_coroutine_waitio_(tb_lo_coroutine_self(), &object, events, interval)) \
{ \
tb_lo_coroutine_suspend(); \
} \
\
} while(0)
/// wait io pipe events
#define tb_lo_coroutine_wait_pipe(pipe_, events, interval) \
do \
{ \
tb_poller_object_t object; \
object.type = TB_POLLER_OBJECT_PIPE; \
object.ref.pipe = pipe_; \
if (tb_lo_coroutine_waitio_(tb_lo_coroutine_self(), &object, events, interval)) \
{ \
tb_lo_coroutine_suspend(); \
} \
\
} while(0)
/// wait process status
#define tb_lo_coroutine_wait_proc(process_, interval) \
do \
{ \
tb_poller_object_t object; \
object.type = TB_POLLER_OBJECT_PROC; \
object.ref.proc = process_; \
if (tb_lo_coroutine_waitproc_(tb_lo_coroutine_self(), &object, interval)) \
{ \
tb_lo_coroutine_suspend(); \
} \
\
} while(0)
/// wait until coroutine be true
#define tb_lo_coroutine_wait_until(cond) \
do \
{ \
tb_used(&lo_yield_flag__); \
tb_lo_core_record(tb_lo_coroutine_self()); \
if (!(cond)) \
return ; \
\
} while(0)
/// wait while coroutine be true
#define tb_lo_coroutine_wait_while(pt, cond) tb_lo_coroutine_wait_until(!(cond))
/// get waited return result
#define tb_lo_coroutine_wait_result() tb_lo_coroutine_waitret_(tb_lo_coroutine_self())
/// get waited exited status of process
#define tb_lo_coroutine_proc_status() tb_lo_coroutine_proc_status_(tb_lo_coroutine_self())
/*! pass the user private data
*
* @code
// start coroutine
tb_lo_coroutine_start(scheduler, coroutine_func, tb_lo_coroutine_pass(tb_xxxx_priv_t));
* @endcode
*
* =>
*
* @code
// start coroutine
tb_lo_coroutine_start(scheduler, coroutine_func, tb_malloc0_type(tb_xxxx_priv_t), tb_lo_coroutine_pass_free_);
* @endcode
*/
#define tb_lo_coroutine_pass(type) tb_malloc0_type(type), tb_lo_coroutine_pass_free_
/*! pass the user private data and init one member
*
* @code
typedef struct __tb_xxxx_priv_t
{
tb_size_t member;
tb_size_t others;
}tb_xxxx_priv_t;
// start coroutine
tb_lo_coroutine_start(scheduler, coroutine_func, tb_lo_coroutine_pass1(tb_xxxx_priv_t, member, value));
* @endcode
*
* =>
*
* @code
tb_xxxx_priv_t* priv = tb_malloc0_type(tb_xxxx_priv_t);
if (priv)
{
priv->member = value;
}
// start coroutine
tb_lo_coroutine_start(scheduler, coroutine_func, priv, tb_lo_coroutine_pass_free_);
* @endcode
*/
#define tb_lo_coroutine_pass1(type, member, value) tb_lo_coroutine_pass1_make_(sizeof(type), &(value), tb_offsetof(type, member), tb_memsizeof(type, member)), tb_lo_coroutine_pass_free_
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* private interfaces
*/
/* get the scheduler of coroutine
*
* @param coroutine the coroutine
*
* @return the scheduler
*/
tb_lo_scheduler_ref_t tb_lo_coroutine_scheduler_(tb_lo_coroutine_ref_t coroutine);
/* sleep the current coroutine
*
* @param coroutine the coroutine
* @param interval the interval (ms), infinity: -1
*/
tb_void_t tb_lo_coroutine_sleep_(tb_lo_coroutine_ref_t coroutine, tb_long_t interval);
/* wait io events
*
* @param coroutine the coroutine
* @param object the poller object
* @param events the waited events
* @param timeout the timeout, infinity: -1
*
* @return suspend coroutine if be tb_true
*/
tb_bool_t tb_lo_coroutine_waitio_(tb_lo_coroutine_ref_t coroutine, tb_poller_object_ref_t object, tb_size_t events, tb_long_t timeout);
/* wait process status
*
* @param coroutine the coroutine
* @param object the poller object
* @param timeout the timeout, infinity: -1
*
* @return suspend coroutine if be tb_true
*/
tb_bool_t tb_lo_coroutine_waitproc_(tb_lo_coroutine_ref_t coroutine, tb_poller_object_ref_t object, tb_long_t timeout);
/* get the waited return results
*
* @param coroutine the coroutine
*
* @return ok or events: > 0, failed: -1, timeout: 0
*/
tb_long_t tb_lo_coroutine_waitret_(tb_lo_coroutine_ref_t coroutine);
/* get the waited process status
*
* @param coroutine the coroutine
*
* @return process status
*/
tb_long_t tb_lo_coroutine_proc_status_(tb_lo_coroutine_ref_t coroutine);
/* free the user private data for pass()
*
* @note only be a wrapper of free() for tb_lo_coroutine_pass()
*
* @param priv the user private data
*/
tb_void_t tb_lo_coroutine_pass_free_(tb_cpointer_t priv);
/* make the user private data for pass1()
*
* @param type_size the data type size
* @param value the value pointer
* @param offset the member offset
* @param size the value size
*
* @return the user private data
*/
tb_pointer_t tb_lo_coroutine_pass1_make_(tb_size_t type_size, tb_cpointer_t value, tb_size_t offset, tb_size_t size);
/* make the user private data for pass2()
*
* @param type_size the data type size
* @param value1 the value1 pointer
* @param offset1 the member1 offset
* @param size1 the value1 size
* @param value2 the value2 pointer
* @param offset2 the member2 offset
* @param size2 the value2 size
*
* @return the user private data
*/
tb_pointer_t tb_lo_coroutine_pass2_make_(tb_size_t type_size, tb_cpointer_t value1, tb_size_t offset1, tb_size_t size1, tb_cpointer_t value2, tb_size_t offset2, tb_size_t size2);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! start coroutine
*
* @code
static tb_void_t switchtask(tb_lo_coroutine_ref_t coroutine, tb_cpointer_t priv)
{
// get count pointer (@note only allow non-status local variables)
tb_size_t* count = (tb_size_t*)priv;
// enter coroutine
tb_lo_coroutine_enter(coroutine);
// @note can not define local variables here
// ...
// loop
while ((*count)--)
{
// yield
tb_lo_coroutine_yield();
}
// leave coroutine
tb_lo_coroutine_leave();
}
tb_int_t main (tb_int_t argc, tb_char_t** argv)
{
// init tbox
if (!tb_init(tb_null, tb_null)) return -1;
// init scheduler
tb_lo_scheduler_ref_t scheduler = tb_lo_scheduler_init();
if (scheduler)
{
// start coroutine
tb_size_t counts[] = {100, 100};
tb_lo_coroutine_start(scheduler, switchtask, &counts[0], tb_null);
tb_lo_coroutine_start(scheduler, switchtask, &counts[1], tb_null);
// run scheduler
tb_lo_scheduler_loop(scheduler);
// exit scheduler
tb_lo_scheduler_exit(scheduler);
}
// exit tbox
tb_exit();
}
* @endcode
*
* @param scheduler the scheduler (can not be null, we can get scheduler of the current coroutine from tb_lo_scheduler_self())
* @param func the coroutine function
* @param priv the passed user private data as the argument of function
* @param free the user private free function
*
* @return tb_true or tb_false
*/
tb_bool_t tb_lo_coroutine_start(tb_lo_scheduler_ref_t scheduler, tb_lo_coroutine_func_t func, tb_cpointer_t priv, tb_lo_coroutine_free_t free);
/*! resume the given coroutine
*
* @param coroutine the coroutine
*/
tb_void_t tb_lo_coroutine_resume(tb_lo_coroutine_ref_t coroutine);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/coroutine/stackless/lock.h 0000664 0000000 0000000 00000003750 14671175054 0021367 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file lock.h
* @ingroup coroutine
*
*/
#ifndef TB_COROUTINE_STACKLESS_LOCK_H
#define TB_COROUTINE_STACKLESS_LOCK_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "semaphore.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/*! init lock
*
* @param lock the lock pointer
*/
#define tb_lo_lock_init(lock) tb_lo_semaphore_init(lock, 1)
/*! exit lock
*
* @param lock the lock pointer
*/
#define tb_lo_lock_exit(lock) tb_lo_semaphore_exit(lock)
/*! enter lock
*
* @param lock the lock pointer
*/
#define tb_lo_lock_enter(lock) tb_lo_semaphore_wait(lock)
/*! try to enter lock
*
* @param lock the lock pointer
*
* @return tb_true or tb_false
*/
#define tb_lo_lock_enter_try(lock) tb_lo_semaphore_wait_try(lock)
/*! leave lock
*
* @param lock the lock pointer
*/
#define tb_lo_lock_leave(lock) tb_lo_semaphore_post(lock, 1)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the stackless lock type
typedef tb_lo_semaphore_t tb_lo_lock_t;
/// the stackless lock ref type
typedef tb_lo_semaphore_ref_t tb_lo_lock_ref_t;
#endif
tbox-1.7.6/src/tbox/coroutine/stackless/prefix.h 0000664 0000000 0000000 00000003125 14671175054 0021730 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_COROUTINE_STACKLESS_PREFIX_H
#define TB_COROUTINE_STACKLESS_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the stackless coroutine ref type
typedef __tb_typeref__(lo_coroutine);
/// the stackless scheduler ref type
typedef __tb_typeref__(lo_scheduler);
/*! the coroutine function type
*
* @param coroutine the coroutine self
* @param priv the user private data from start(.., priv)
*/
typedef tb_void_t (*tb_lo_coroutine_func_t)(tb_lo_coroutine_ref_t coroutine, tb_cpointer_t priv);
/*! the user private data free function type
*
* @param priv the user private data from start(.., priv)
*/
typedef tb_void_t (*tb_lo_coroutine_free_t)(tb_cpointer_t priv);
#endif
tbox-1.7.6/src/tbox/coroutine/stackless/scheduler.c 0000664 0000000 0000000 00000032626 14671175054 0022414 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file scheduler.h
* @ingroup scheduler
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "scheduler"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "scheduler.h"
#include "../impl/impl.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the dead cache maximum count
#if defined(TB_CONFIG_MICRO_ENABLE)
# define TB_SCHEDULER_DEAD_CACHE_MAXN (8)
#elif defined(__tb_small__)
# define TB_SCHEDULER_DEAD_CACHE_MAXN (64)
#else
# define TB_SCHEDULER_DEAD_CACHE_MAXN (256)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
#if !defined(TB_CONFIG_MICRO_ENABLE) && !defined(__tb_thread_local__)
// the self scheduler local
static tb_thread_local_t g_scheduler_self = TB_THREAD_LOCAL_INIT;
#endif
// the global scheduler for the exclusive mode
#ifdef __tb_thread_local__
static __tb_thread_local__ tb_lo_scheduler_t* g_scheduler_self_ex = tb_null;
#else
static tb_lo_scheduler_t* g_scheduler_self_ex = tb_null;
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_void_t tb_lo_scheduler_free(tb_list_entry_head_ref_t coroutines)
{
// check
tb_assert(coroutines);
// free all coroutines
while (tb_list_entry_size(coroutines))
{
// get the next entry from head
tb_list_entry_ref_t entry = tb_list_entry_head(coroutines);
tb_assert(entry);
// remove it from the ready coroutines
tb_list_entry_remove_head(coroutines);
// exit this coroutine
tb_lo_coroutine_exit((tb_lo_coroutine_t*)tb_list_entry(coroutines, entry));
}
}
static tb_void_t tb_lo_scheduler_make_ready(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_t* coroutine)
{
// check
tb_assert(scheduler && coroutine);
// mark ready state
tb_lo_core_state_set(coroutine, TB_STATE_READY);
// insert this coroutine to ready coroutines
if (scheduler->running)
{
// .. -> coroutine(inserted) -> running -> ..
tb_list_entry_insert_prev(&scheduler->coroutines_ready, &scheduler->running->entry, &coroutine->entry);
}
else
{
// .. last -> coroutine(inserted)
tb_list_entry_insert_tail(&scheduler->coroutines_ready, &coroutine->entry);
}
}
static tb_void_t tb_lo_scheduler_make_dead(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_t* coroutine)
{
// check
tb_assert(scheduler && coroutine);
tb_assert(tb_lo_core_state(coroutine) == TB_STATE_END);
// trace
tb_trace_d("finish coroutine(%p)", coroutine);
// free the user private data first
if (coroutine->free) coroutine->free(coroutine->priv);
// remove this coroutine from the ready coroutines
tb_list_entry_remove(&scheduler->coroutines_ready, &coroutine->entry);
// append this coroutine to dead coroutines
tb_list_entry_insert_tail(&scheduler->coroutines_dead, &coroutine->entry);
}
static tb_void_t tb_lo_scheduler_make_suspend(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_t* coroutine)
{
// check
tb_assert(scheduler && coroutine);
tb_assert(tb_lo_core_state(coroutine) == TB_STATE_SUSPEND);
// trace
tb_trace_d("suspend coroutine(%p)", coroutine);
// remove this coroutine from the ready coroutines
tb_list_entry_remove(&scheduler->coroutines_ready, &coroutine->entry);
// append this coroutine to suspend coroutines
tb_list_entry_insert_tail(&scheduler->coroutines_suspend, &coroutine->entry);
}
static __tb_inline__ tb_lo_coroutine_t* tb_lo_scheduler_next_ready(tb_lo_scheduler_t* scheduler)
{
// check
tb_assert(scheduler && tb_list_entry_size(&scheduler->coroutines_ready));
// get the next entry
tb_list_entry_ref_t entry_next = scheduler->running? tb_list_entry_next(&scheduler->running->entry) : tb_list_entry_head(&scheduler->coroutines_ready);
tb_assert(entry_next);
// is list header? skip it and get the first entry
if (entry_next == (tb_list_entry_ref_t)&scheduler->coroutines_ready)
entry_next = tb_list_entry_next(entry_next);
// get the next ready coroutine
return (tb_lo_coroutine_t*)tb_list_entry(&scheduler->coroutines_ready, entry_next);
}
static tb_void_t tb_lo_scheduler_switch(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_t* coroutine)
{
// check
tb_assert(scheduler && coroutine && coroutine->func);
tb_assert(tb_lo_core_state(coroutine) == TB_STATE_READY);
// trace
tb_trace_d("switch to coroutine(%p) from coroutine(%p)", coroutine, scheduler->running);
// mark the given coroutine as running
scheduler->running = coroutine;
// call the coroutine function
coroutine->func((tb_lo_coroutine_ref_t)coroutine, coroutine->priv);
}
tb_bool_t tb_lo_scheduler_start(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_func_t func, tb_cpointer_t priv, tb_lo_coroutine_free_t free)
{
// check
tb_assert(func);
// done
tb_bool_t ok = tb_false;
tb_lo_coroutine_t* coroutine = tb_null;
do
{
// trace
tb_trace_d("start ..");
// get the current scheduler
if (!scheduler) scheduler = (tb_lo_scheduler_t*)tb_lo_scheduler_self_();
tb_assert_and_check_break(scheduler);
// have been stopped? do not continue to start new coroutines
tb_check_break(!scheduler->stopped);
// reuses dead coroutines in init function
if (tb_list_entry_size(&scheduler->coroutines_dead))
{
// get the next entry from head
tb_list_entry_ref_t entry = tb_list_entry_head(&scheduler->coroutines_dead);
tb_assert_and_check_break(entry);
// remove it from the ready coroutines
tb_list_entry_remove_head(&scheduler->coroutines_dead);
// get the dead coroutine
coroutine = (tb_lo_coroutine_t*)tb_list_entry(&scheduler->coroutines_dead, entry);
// reinit this coroutine
tb_lo_coroutine_reinit(coroutine, func, priv, free);
}
// init coroutine
if (!coroutine) coroutine = tb_lo_coroutine_init((tb_lo_scheduler_ref_t)scheduler, func, priv, free);
tb_assert_and_check_break(coroutine);
// ready coroutine
tb_lo_scheduler_make_ready(scheduler, coroutine);
// the dead coroutines is too much? free some coroutines
while (tb_list_entry_size(&scheduler->coroutines_dead) > TB_SCHEDULER_DEAD_CACHE_MAXN)
{
// get the next entry from head
tb_list_entry_ref_t entry = tb_list_entry_head(&scheduler->coroutines_dead);
tb_assert(entry);
// remove it from the ready coroutines
tb_list_entry_remove_head(&scheduler->coroutines_dead);
// exit this coroutine
tb_lo_coroutine_exit((tb_lo_coroutine_t*)tb_list_entry(&scheduler->coroutines_dead, entry));
}
// ok
ok = tb_true;
} while (0);
// trace
tb_trace_d("start %s", ok? "ok" : "no");
// ok?
return ok;
}
tb_void_t tb_lo_scheduler_resume(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_t* coroutine)
{
// check
tb_assert(scheduler && coroutine);
tb_assert(tb_lo_core_state(coroutine) == TB_STATE_SUSPEND);
// remove it from the suspend coroutines
tb_list_entry_remove(&scheduler->coroutines_suspend, &coroutine->entry);
// make it as ready
tb_lo_scheduler_make_ready(scheduler, coroutine);
}
tb_lo_scheduler_ref_t tb_lo_scheduler_self_()
{
// get self scheduler on the current thread
#if defined(TB_CONFIG_MICRO_ENABLE) || defined(__tb_thread_local__)
return (tb_lo_scheduler_ref_t)g_scheduler_self_ex;
#else
return (tb_lo_scheduler_ref_t)(g_scheduler_self_ex? g_scheduler_self_ex : tb_thread_local_get(&g_scheduler_self));
#endif
}
/* //////////////////////////////////////////////////////////////////////////////////////
* public implementation
*/
tb_lo_scheduler_ref_t tb_lo_scheduler_init()
{
// done
tb_bool_t ok = tb_false;
tb_lo_scheduler_t* scheduler = tb_null;
do
{
// make scheduler
scheduler = tb_malloc0_type(tb_lo_scheduler_t);
tb_assert_and_check_break(scheduler);
// init dead coroutines
tb_list_entry_init(&scheduler->coroutines_dead, tb_lo_coroutine_t, entry, tb_null);
// init ready coroutines
tb_list_entry_init(&scheduler->coroutines_ready, tb_lo_coroutine_t, entry, tb_null);
// init suspend coroutines
tb_list_entry_init(&scheduler->coroutines_suspend, tb_lo_coroutine_t, entry, tb_null);
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (scheduler) tb_lo_scheduler_exit((tb_lo_scheduler_ref_t)scheduler);
scheduler = tb_null;
}
// ok?
return (tb_lo_scheduler_ref_t)scheduler;
}
tb_void_t tb_lo_scheduler_exit(tb_lo_scheduler_ref_t self)
{
// check
tb_lo_scheduler_t* scheduler = (tb_lo_scheduler_t*)self;
tb_assert_and_check_return(scheduler);
// must be stopped
tb_assert(scheduler->stopped);
// exit io scheduler first
if (scheduler->scheduler_io) tb_lo_scheduler_io_exit(scheduler->scheduler_io);
scheduler->scheduler_io = tb_null;
// check coroutines
tb_assert(!tb_list_entry_size(&scheduler->coroutines_ready));
tb_assert(!tb_list_entry_size(&scheduler->coroutines_suspend));
// free all dead coroutines
tb_lo_scheduler_free(&scheduler->coroutines_dead);
// free all ready coroutines
tb_lo_scheduler_free(&scheduler->coroutines_ready);
// free all suspend coroutines
tb_lo_scheduler_free(&scheduler->coroutines_suspend);
// exit dead coroutines
tb_list_entry_exit(&scheduler->coroutines_dead);
// exit ready coroutines
tb_list_entry_exit(&scheduler->coroutines_ready);
// exit suspend coroutines
tb_list_entry_exit(&scheduler->coroutines_suspend);
// exit the scheduler
tb_free(scheduler);
}
tb_void_t tb_lo_scheduler_kill(tb_lo_scheduler_ref_t self)
{
// check
tb_lo_scheduler_t* scheduler = (tb_lo_scheduler_t*)self;
tb_assert_and_check_return(scheduler);
// stop it
scheduler->stopped = tb_true;
}
tb_void_t tb_lo_scheduler_loop(tb_lo_scheduler_ref_t self, tb_bool_t exclusive)
{
// check
tb_lo_scheduler_t* scheduler = (tb_lo_scheduler_t*)self;
tb_assert_and_check_return(scheduler);
#ifdef __tb_thread_local__
g_scheduler_self_ex = scheduler;
#else
// is exclusive mode?
if (exclusive) g_scheduler_self_ex = scheduler;
# ifndef TB_CONFIG_MICRO_ENABLE
else
{
// init self scheduler local
if (!tb_thread_local_init(&g_scheduler_self, tb_null)) return ;
// update and overide the current scheduler
tb_thread_local_set(&g_scheduler_self, self);
}
# else
else
{
// trace
tb_trace_e("non-exclusive is not suspported in micro mode!");
}
# endif
#endif
#ifdef TB_CONFIG_OS_WINDOWS
// we need attach poller in the current thread first for iocp/windows
tb_lo_scheduler_io_need(scheduler);
#endif
// schedule all ready coroutines
while (tb_list_entry_size(&scheduler->coroutines_ready) && !scheduler->stopped)
{
// trace
tb_trace_d("[loop]: ready %lu", tb_list_entry_size(&scheduler->coroutines_ready));
// get the next ready coroutine
tb_lo_coroutine_t* coroutine_next = tb_lo_scheduler_next_ready(scheduler);
tb_assert(coroutine_next);
// process the running coroutine
if (scheduler->running)
{
// get the state of running coroutine
tb_size_t state = tb_lo_core_state(scheduler->running);
// mark this coroutine as dead if the running coroutine(root level) have been finished
if (state == TB_STATE_END)
tb_lo_scheduler_make_dead(scheduler, scheduler->running);
// suspend the running coroutine
else if (state == TB_STATE_SUSPEND)
tb_lo_scheduler_make_suspend(scheduler, scheduler->running);
}
// switch to it if the next coroutine (may be running coroutine) is ready
if (tb_lo_core_state(coroutine_next) == TB_STATE_READY)
tb_lo_scheduler_switch(scheduler, coroutine_next);
}
// stop it
scheduler->stopped = tb_true;
#ifdef __tb_thread_local__
g_scheduler_self_ex = tb_null;
#else
// is exclusive mode?
if (exclusive) g_scheduler_self_ex = tb_null;
# ifndef TB_CONFIG_MICRO_ENABLE
else
{
// clear the current scheduler
tb_thread_local_set(&g_scheduler_self, tb_null);
}
# endif
#endif
}
tbox-1.7.6/src/tbox/coroutine/stackless/scheduler.h 0000664 0000000 0000000 00000004401 14671175054 0022407 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file scheduler.h
* @ingroup coroutine
*
*/
#ifndef TB_COROUTINE_STACKLESS_SCHEDULER_H
#define TB_COROUTINE_STACKLESS_SCHEDULER_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/// the self scheduler
#define tb_lo_scheduler_self() tb_lo_coroutine_scheduler_(co__)
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init scheduler
*
* @return the scheduler
*/
tb_lo_scheduler_ref_t tb_lo_scheduler_init(tb_noarg_t);
/*! exit scheduler
*
* @param scheduler the scheduler
*/
tb_void_t tb_lo_scheduler_exit(tb_lo_scheduler_ref_t scheduler);
/* kill the scheduler
*
* @param scheduler the scheduler
*/
tb_void_t tb_lo_scheduler_kill(tb_lo_scheduler_ref_t scheduler);
/*! run the scheduler loop
*
* @param scheduler the scheduler
* @param exclusive enable exclusive mode, we need ensure only one loop() be called at the same time,
* but it will be faster using thr global scheduler instead of TLS storage
*/
tb_void_t tb_lo_scheduler_loop(tb_lo_scheduler_ref_t scheduler, tb_bool_t exclusive);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/coroutine/stackless/semaphore.h 0000664 0000000 0000000 00000004717 14671175054 0022426 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file semaphore.h
* @ingroup coroutine
*
*/
#ifndef TB_COROUTINE_STACKLESS_SEMAPHORE_H
#define TB_COROUTINE_STACKLESS_SEMAPHORE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "coroutine.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/*! init semaphore
*
* @param sem the semaphore pointer
* @param val the initial semaphore value
*/
#define tb_lo_semaphore_init(sem, val) (sem)->value = val
/*! exit semaphore
*
* @param sem the semaphore pointer
*/
#define tb_lo_semaphore_exit(sem) (sem)->value = 0
/*! get semaphore value
*
* @param sem the semaphore pointer
*
* @return the semaphore value
*/
#define tb_lo_semaphore_value(sem) ((sem)->value)
/*! post semaphore
*
* @param sem the semaphore pointer
* @param post the post semaphore value
*/
#define tb_lo_semaphore_post(sem, post) \
do \
{ \
(sem)->value += (post); \
tb_lo_coroutine_yield(); \
\
} while (0)
/*! wait semaphore
*
* @param sem the semaphore pointer
*/
#define tb_lo_semaphore_wait(sem) \
do \
{ \
tb_lo_coroutine_wait_until((sem)->value > 0); \
(sem)->value--; \
\
} while(0)
/*! try to wait semaphore
*
* @param sem the semaphore pointer
*
* @return tb_true or tb_false
*/
#define tb_lo_semaphore_wait_try(sem) (((sem)->value > 0)? (sem)->value-- : 0)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the stackless semaphore type
typedef struct __tb_lo_semaphore_t
{
// the semaphore value
tb_long_t value;
}tb_lo_semaphore_t, *tb_lo_semaphore_ref_t;
#endif
tbox-1.7.6/src/tbox/coroutine/stackless/stackless.h 0000664 0000000 0000000 00000001747 14671175054 0022437 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file stackless.h
* @ingroup coroutine
*
*/
#ifndef TB_COROUTINE_STACKLESS_H
#define TB_COROUTINE_STACKLESS_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "coroutine.h"
#include "scheduler.h"
#include "semaphore.h"
#include "lock.h"
#endif
tbox-1.7.6/src/tbox/database/ 0000775 0000000 0000000 00000000000 14671175054 0016022 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/database/database.h 0000664 0000000 0000000 00000001633 14671175054 0017742 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file database.h
* @defgroup database
*/
#ifndef TB_DATABASE_H
#define TB_DATABASE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "sql.h"
#endif
tbox-1.7.6/src/tbox/database/impl/ 0000775 0000000 0000000 00000000000 14671175054 0016763 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/database/impl/mysql.c 0000664 0000000 0000000 00000160257 14671175054 0020307 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file mysql.c
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "mysql"
#define TB_TRACE_MODULE_DEBUG (1)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include
#include
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the mysql result row type
typedef struct __tb_database_mysql_result_row_t
{
// the iterator
tb_iterator_t itor;
// the row
MYSQL_ROW row;
// the lengths
tb_ulong_t* lengths;
// the col count
tb_size_t count;
// the col value
tb_database_sql_value_t value;
}tb_database_mysql_result_row_t;
// the mysql result type
typedef struct __tb_database_mysql_result_t
{
// the iterator
tb_iterator_t itor;
// the statement
MYSQL_STMT* statement;
// the result
MYSQL_RES* result;
// the fields
MYSQL_FIELD* fields;
// the metadata
MYSQL_RES* metadata;
// the row count
tb_size_t count;
// try loading all?
tb_bool_t try_all;
// the row
tb_database_mysql_result_row_t row;
// the stream
tb_stream_ref_t stream;
}tb_database_mysql_result_t;
// the mysql stream type
typedef struct __tb_database_mysql_stream_impl_t
{
// the statement
MYSQL_STMT* statement;
// the result
MYSQL_BIND* result;
// the offset
tb_size_t offset;
// the column
tb_size_t column;
}tb_database_mysql_stream_impl_t;
// the mysql type
typedef struct __tb_database_mysql_t
{
// the base
tb_database_sql_impl_t base;
// the result
tb_database_mysql_result_t result;
// the database
MYSQL* database;
// the bind list
MYSQL_BIND* bind_list;
// the bind maxn
tb_size_t bind_maxn;
// the bind data
tb_buffer_t bind_data;
}tb_database_mysql_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* declaration
*/
static tb_void_t tb_database_mysql_result_exit(tb_database_sql_impl_t* database, tb_iterator_ref_t result);
/* //////////////////////////////////////////////////////////////////////////////////////
* library implementation
*/
static tb_handle_t tb_database_mysql_library_init(tb_cpointer_t* ppriv)
{
// init it
if (mysql_library_init(0, tb_null, tb_null))
{
// trace
tb_trace_e("init: mysql library failed!");
return tb_null;
}
// ok
return ppriv;
}
static tb_void_t tb_database_mysql_library_exit(tb_handle_t handle, tb_cpointer_t priv)
{
// exit it
mysql_library_end();
}
static tb_handle_t tb_database_mysql_library_load()
{
return tb_singleton_instance(TB_SINGLETON_TYPE_LIBRARY_MYSQL, tb_database_mysql_library_init, tb_database_mysql_library_exit, tb_null, tb_null);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* state implementation
*/
static tb_size_t tb_database_mysql_state_from_errno(tb_size_t errno)
{
// done
tb_size_t state = TB_STATE_DATABASE_UNKNOWN_ERROR;
switch (errno)
{
case ER_NO_DB_ERROR:
case ER_BAD_DB_ERROR:
state = TB_STATE_DATABASE_NO_SUCH_DATABASE;
break;
case ER_NO_SUCH_TABLE:
state = TB_STATE_DATABASE_NO_SUCH_TABLE;
break;
case ER_BAD_FIELD_ERROR:
state = TB_STATE_DATABASE_NO_SUCH_FIELD;
break;
case ER_ACCESS_DENIED_ERROR:
state = TB_STATE_DATABASE_ACCESS_DENIED;
break;
case ER_PARSE_ERROR:
state = TB_STATE_DATABASE_PARSE_ERROR;
break;
case ER_WRONG_VALUE_COUNT_ON_ROW:
state = TB_STATE_DATABASE_VALUE_COUNT_ERROR;
break;
case CR_UNKNOWN_HOST:
state = TB_STATE_DATABASE_UNKNOWN_HOST;
break;
case ER_UNKNOWN_ERROR:
break;
default:
tb_trace_e("unknown errno: %lu", errno);
break;
}
// ok?
return state;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* stream implementation
*/
static tb_bool_t tb_database_mysql_stream_impl_open(tb_stream_ref_t stream)
{
// check
tb_database_mysql_stream_impl_t* impl = (tb_database_mysql_stream_impl_t*)stream;
tb_assert_and_check_return_val(impl && impl->statement, tb_false);
// check result
tb_assert_and_check_return_val(impl->result && impl->result->buffer && impl->result->buffer_length, tb_false);
// ok
return tb_true;
}
static tb_bool_t tb_database_mysql_stream_impl_clos(tb_stream_ref_t stream)
{
// check
tb_database_mysql_stream_impl_t* impl = (tb_database_mysql_stream_impl_t*)stream;
tb_assert_and_check_return_val(impl, tb_false);
// ok
return tb_true;
}
static tb_long_t tb_database_mysql_stream_impl_read(tb_stream_ref_t stream, tb_byte_t* data, tb_size_t size)
{
// check
tb_database_mysql_stream_impl_t* impl = (tb_database_mysql_stream_impl_t*)stream;
tb_assert_and_check_return_val(impl && impl->statement, -1);
// check data and size
tb_check_return_val(data, -1);
tb_check_return_val(size, 0);
// check result
tb_assert_and_check_return_val(impl->result && impl->result->buffer && impl->result->buffer_length, -1);
// the length
tb_size_t length = (tb_size_t)*impl->result->length;
// end?
tb_check_return_val(length && impl->offset < length, -1);
// read data
size = tb_min3(size, (tb_size_t)impl->result->buffer_length, length - impl->offset);
if (size) tb_memcpy(data, impl->result->buffer, size);
// update offset
impl->offset += size;
// fetch column
if (mysql_stmt_fetch_column(impl->statement, impl->result, impl->column, impl->offset))
{
// trace
tb_trace_e("stream: fetch failed at: %lu, error[%d]: %s", impl->column, mysql_stmt_errno(impl->statement), mysql_stmt_error(impl->statement));
return -1;
}
// trace
// tb_trace_d("stream: read: %lu", size);
// ok?
return (tb_long_t)(size);
}
static tb_long_t tb_database_mysql_stream_impl_wait(tb_stream_ref_t stream, tb_size_t wait, tb_long_t timeout)
{
// check
tb_database_mysql_stream_impl_t* impl = (tb_database_mysql_stream_impl_t*)stream;
tb_assert_and_check_return_val(impl, -1);
// ok?
return wait;
}
static tb_bool_t tb_database_mysql_stream_impl_ctrl(tb_stream_ref_t stream, tb_size_t ctrl, tb_va_list_t args)
{
// check
tb_database_mysql_stream_impl_t* impl = (tb_database_mysql_stream_impl_t*)stream;
tb_assert_and_check_return_val(impl, tb_false);
// ctrl
switch (ctrl)
{
case TB_STREAM_CTRL_GET_SIZE:
{
// the psize
tb_hong_t* psize = (tb_hong_t*)tb_va_arg(args, tb_hong_t*);
tb_assert_and_check_return_val(psize && impl->result, tb_false);
// get size
*psize = (tb_hong_t)*impl->result->length;
// ok
return tb_true;
}
default:
break;
}
return tb_false;
}
static tb_stream_ref_t tb_database_mysql_stream_impl_init(MYSQL_STMT* statement, MYSQL_BIND* result, tb_size_t column)
{
// check
tb_assert_and_check_return_val(statement && result, tb_null);
// init stream
tb_stream_ref_t stream = tb_stream_init( TB_STREAM_TYPE_NONE
, sizeof(tb_database_mysql_stream_impl_t)
, 0
, tb_database_mysql_stream_impl_open
, tb_database_mysql_stream_impl_clos
, tb_null
, tb_database_mysql_stream_impl_ctrl
, tb_database_mysql_stream_impl_wait
, tb_database_mysql_stream_impl_read
, tb_null
, tb_null
, tb_null
, tb_null);
tb_assert_and_check_return_val(stream, tb_null);
// init the stream impl
tb_database_mysql_stream_impl_t* impl = (tb_database_mysql_stream_impl_t*)stream;
if (impl)
{
impl->statement = statement;
impl->result = result;
impl->column = column;
}
// ok?
return (tb_stream_ref_t)stream;
}
static tb_bool_t tb_database_mysql_stream_impl_set_value(tb_database_sql_value_t* value, tb_database_mysql_t* mysql, MYSQL_BIND* result, tb_size_t column)
{
// check
tb_assert_and_check_return_val(value && mysql && mysql->result.statement && result, tb_false);
// done
tb_bool_t ok = tb_false;
do
{
// exit the last stream first
if (mysql->result.stream) tb_stream_exit(mysql->result.stream);
mysql->result.stream = tb_null;
// init stream
mysql->result.stream = tb_database_mysql_stream_impl_init(mysql->result.statement, result, column);
tb_assert_and_check_break(mysql->result.stream);
// open stream
if (!tb_stream_open(mysql->result.stream)) break;
// set blob32
tb_database_sql_value_set_blob32(value, tb_null, 0, mysql->result.stream);
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (mysql->result.stream) tb_stream_exit(mysql->result.stream);
mysql->result.stream = tb_null;
}
// ok?
return ok;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* iterator implementation
*/
static tb_size_t tb_database_mysql_result_row_iterator_size(tb_iterator_ref_t iterator)
{
// check
tb_database_mysql_result_t* result = (tb_database_mysql_result_t*)iterator;
tb_assert(result);
// size
return result->count;
}
static tb_size_t tb_database_mysql_result_row_iterator_head(tb_iterator_ref_t iterator)
{
// head
return 0;
}
static tb_size_t tb_database_mysql_result_row_iterator_tail(tb_iterator_ref_t iterator)
{
// check
tb_database_mysql_result_t* result = (tb_database_mysql_result_t*)iterator;
tb_assert(result);
// tail
return result->count;
}
static tb_size_t tb_database_mysql_result_row_iterator_prev(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_database_mysql_result_t* result = (tb_database_mysql_result_t*)iterator;
tb_assert(result);
tb_assert_and_check_return_val(itor && itor <= result->count, result->count);
// load all?
tb_assert_and_check_return_val(result->try_all, result->count);
// prev
return itor - 1;
}
static tb_size_t tb_database_mysql_result_row_iterator_next(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_database_mysql_result_t* result = (tb_database_mysql_result_t*)iterator;
tb_assert(result);
tb_assert_and_check_return_val(itor < result->count, result->count);
// not load all? try fetching it
if (!result->try_all)
{
// fetch statement
if (result->statement)
{
// fetch the row
tb_int_t ok = 0;
if ((ok = mysql_stmt_fetch(result->statement)))
{
// end or error?
if (ok != MYSQL_DATA_TRUNCATED)
{
// error?
if (ok != MYSQL_NO_DATA)
{
// the mysql
tb_database_mysql_t* mysql = (tb_database_mysql_t*)iterator->priv;
// save state
if (mysql) mysql->base.state = tb_database_mysql_state_from_errno(mysql_stmt_errno(result->statement));
// trace
tb_trace_e("statement: fetch row %lu failed, error[%d]: %s", itor, mysql_stmt_errno(result->statement), mysql_stmt_error(result->statement));
}
// end
return result->count;
}
}
}
// fetch result
else
{
// check
tb_assert_and_check_return_val(result->result, result->count);
// fetch the row
result->row.row = mysql_fetch_row(result->result);
tb_check_return_val(result->row.row, result->count);
// fetch the lengths
result->row.lengths = mysql_fetch_lengths(result->result);
tb_assert_and_check_return_val(result->row.lengths, result->count);
}
}
// next
return itor + 1;
}
static tb_pointer_t tb_database_mysql_result_row_iterator_item(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_database_mysql_result_t* result = (tb_database_mysql_result_t*)iterator;
tb_assert_and_check_return_val(result && itor < result->count, tb_null);
// load all?
if (result->try_all)
{
// load statement row
if (result->statement)
{
// seek to the row number
mysql_stmt_data_seek(result->statement, itor);
// fetch the row
tb_int_t ok = 0;
if ((ok = mysql_stmt_fetch(result->statement)))
{
// end or error?
if (ok != MYSQL_DATA_TRUNCATED)
{
// error?
if (ok != MYSQL_NO_DATA)
{
// the mysql
tb_database_mysql_t* mysql = (tb_database_mysql_t*)iterator->priv;
// save state
if (mysql) mysql->base.state = tb_database_mysql_state_from_errno(mysql_stmt_errno(result->statement));
// trace
tb_trace_e("statement: fetch row %lu failed, error[%d]: %s", itor, mysql_stmt_errno(result->statement), mysql_stmt_error(result->statement));
}
return tb_null;
}
}
}
// load result row
else
{
// check
tb_assert_and_check_return_val(result->result, tb_null);
// seek to the row number
mysql_data_seek(result->result, itor);
// fetch the row
result->row.row = mysql_fetch_row(result->result);
tb_assert_and_check_return_val(result->row.row, tb_null);
// fetch the lengths
result->row.lengths = mysql_fetch_lengths(result->result);
tb_assert_and_check_return_val(result->row.lengths, tb_null);
}
}
// the row iterator
return (tb_pointer_t)&result->row;
}
static tb_size_t tb_database_mysql_result_col_iterator_size(tb_iterator_ref_t iterator)
{
// check
tb_database_mysql_result_row_t* row = (tb_database_mysql_result_row_t*)iterator;
tb_assert_and_check_return_val(row, 0);
// size
return row->count;
}
static tb_size_t tb_database_mysql_result_col_iterator_head(tb_iterator_ref_t iterator)
{
// check
tb_database_mysql_result_row_t* row = (tb_database_mysql_result_row_t*)iterator;
tb_assert_and_check_return_val(row, 0);
// head
return 0;
}
static tb_size_t tb_database_mysql_result_col_iterator_tail(tb_iterator_ref_t iterator)
{
// check
tb_database_mysql_result_row_t* row = (tb_database_mysql_result_row_t*)iterator;
tb_assert_and_check_return_val(row, 0);
// tail
return row->count;
}
static tb_size_t tb_database_mysql_result_col_iterator_prev(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_database_mysql_result_row_t* row = (tb_database_mysql_result_row_t*)iterator;
tb_assert_and_check_return_val(row && itor && itor <= row->count, 0);
// prev
return itor - 1;
}
static tb_size_t tb_database_mysql_result_col_iterator_next(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_database_mysql_result_row_t* row = (tb_database_mysql_result_row_t*)iterator;
tb_assert_and_check_return_val(row && itor < row->count, row->count);
// next
return itor + 1;
}
static tb_pointer_t tb_database_mysql_result_col_iterator_item(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_database_mysql_result_row_t* row = (tb_database_mysql_result_row_t*)iterator;
tb_assert_and_check_return_val(row && itor < row->count, tb_null);
// the mysql
tb_database_mysql_t* mysql = (tb_database_mysql_t*)iterator->priv;
tb_assert_and_check_return_val(mysql && mysql->result.fields, tb_null);
// the field
MYSQL_FIELD* field = &mysql->result.fields[itor];
// fetch column from statement
if (mysql->result.statement)
{
// check
tb_assert_and_check_return_val(mysql->bind_list && itor < mysql->bind_maxn, tb_null);
// the result
MYSQL_BIND* result = &mysql->bind_list[itor];
// fetch column
if (mysql_stmt_fetch_column(mysql->result.statement, result, itor, 0))
{
// save state
mysql->base.state = tb_database_mysql_state_from_errno(mysql_stmt_errno(mysql->result.statement));
// trace
tb_trace_e("statement: fetch result failed at: %lu, field_type: %d, error[%d]: %s", itor, field->type, mysql_stmt_errno(mysql->result.statement), mysql_stmt_error(mysql->result.statement));
return tb_null;
}
// init value
tb_database_sql_value_name_set(&row->value, (tb_char_t const*)field->name);
switch (result->buffer_type)
{
case MYSQL_TYPE_STRING:
tb_database_sql_value_set_text(&row->value, (tb_char_t const*)result->buffer, (tb_size_t)*result->length);
break;
case MYSQL_TYPE_LONG:
tb_database_sql_value_set_int32(&row->value, *((tb_int32_t const*)result->buffer));
break;
case MYSQL_TYPE_LONGLONG:
tb_database_sql_value_set_int64(&row->value, *((tb_int64_t const*)result->buffer));
break;
case MYSQL_TYPE_SHORT:
tb_database_sql_value_set_int16(&row->value, *((tb_int16_t const*)result->buffer));
break;
case MYSQL_TYPE_TINY:
tb_database_sql_value_set_int8(&row->value, *((tb_int8_t const*)result->buffer));
break;
case MYSQL_TYPE_INT24:
tb_database_sql_value_set_int32(&row->value, tb_bits_get_s24_ne((tb_byte_t const*)result->buffer));
break;
// note: the field type of text, tinyblob, blob and longblob always be blob
case MYSQL_TYPE_BLOB:
{
// text?
if (field->charsetnr != 63)
{
tb_database_sql_value_set_text(&row->value, (tb_char_t const*)result->buffer, (tb_size_t)*result->length);
}
// blob?
else
{
// blob8?
if ((tb_size_t)*result->length <= TB_MAXU8)
{
tb_database_sql_value_set_blob8(&row->value, (tb_byte_t const*)result->buffer, (tb_size_t)*result->length);
}
// blob16?
else if ((tb_size_t)*result->length <= TB_MAXU16)
{
tb_database_sql_value_set_blob16(&row->value, (tb_byte_t const*)result->buffer, (tb_size_t)*result->length);
}
// blob32?
else
{
tb_database_mysql_stream_impl_set_value(&row->value, mysql, result, itor);
}
}
}
break;
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
tb_database_mysql_stream_impl_set_value(&row->value, mysql, result, itor);
break;
case MYSQL_TYPE_TINY_BLOB:
tb_database_sql_value_set_blob8(&row->value, (tb_byte_t const*)result->buffer, (tb_size_t)*result->length);
break;
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
case MYSQL_TYPE_FLOAT:
tb_database_sql_value_set_float(&row->value, *((tb_float_t const*)result->buffer));
break;
case MYSQL_TYPE_DOUBLE:
tb_database_sql_value_set_double(&row->value, *((tb_double_t const*)result->buffer));
break;
#endif
case MYSQL_TYPE_NULL:
tb_database_sql_value_set_null(&row->value);
break;
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_TIME:
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_YEAR:
case MYSQL_TYPE_SET:
case MYSQL_TYPE_ENUM:
tb_trace_e("statement: fetch result: not supported buffer type: %d", result->buffer_type);
return tb_null;
default:
tb_trace_e("statement: fetch result: unknown buffer type: %d", result->buffer_type);
return tb_null;
}
}
// fetch column from result
else
{
// check
tb_assert_and_check_return_val(row->row && row->lengths, tb_null);
// init value
tb_database_sql_value_name_set(&row->value, (tb_char_t const*)field->name);
tb_database_sql_value_set_text(&row->value, (tb_char_t const*)row->row[itor], (tb_size_t)row->lengths[itor]);
}
// the col item
return (tb_pointer_t)&row->value;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static __tb_inline__ tb_database_mysql_t* tb_database_mysql_cast(tb_database_sql_impl_t* database)
{
// check
tb_assert_and_check_return_val(database && database->type == TB_DATABASE_SQL_TYPE_MYSQL, tb_null);
// cast
return (tb_database_mysql_t*)database;
}
static tb_bool_t tb_database_mysql_open(tb_database_sql_impl_t* database)
{
// check
tb_database_mysql_t* mysql = tb_database_mysql_cast(database);
tb_assert_and_check_return_val(mysql, tb_false);
// done
tb_bool_t ok = tb_false;
tb_char_t const* host = tb_null;
tb_size_t port = 0;
tb_char_t username[64] = {0};
tb_char_t password[64] = {0};
tb_char_t database_sql_name[64] = {0};
do
{
// the database host
host = tb_url_host(&database->url);
tb_assert_and_check_break(host);
// the database port
port = tb_url_port(&database->url);
// the database args
tb_char_t const* args = tb_url_args(&database->url);
if (args)
{
// the args size
tb_size_t argn = tb_strlen(args);
// the database username
tb_char_t const* p = tb_stristr(args, "username=");
if (p)
{
// skip to value
p += 9;
// the value end
tb_char_t const* e = tb_strchr(p, '&');
if (!e) e = args + argn;
// save username
if (p < e) tb_strlcpy(username, p, tb_min((e - p) + 1, sizeof(username)));
}
// the database password
p = tb_stristr(args, "password=");
if (p)
{
// skip to value
p += 9;
// the value end
tb_char_t const* e = tb_strchr(p, '&');
if (!e) e = args + argn;
// save password
if (p < e) tb_strlcpy(password, p, tb_min((e - p) + 1, sizeof(password)));
}
// the database name
p = tb_stristr(args, "database=");
if (p)
{
// skip to value
p += 9;
// the value end
tb_char_t const* e = tb_strchr(p, '&');
if (!e) e = args + argn;
// save database name
if (p < e) tb_strlcpy(database_sql_name, p, tb_min((e - p) + 1, sizeof(database_sql_name)));
}
}
// load mysql library
if (!tb_database_mysql_library_load()) break;
// init mysql database
mysql->database = mysql_init(tb_null);
tb_assert_and_check_break(mysql->database);
// connect it
if (!mysql_real_connect(mysql->database, host, username[0]? username : tb_null, password[0]? password : tb_null, database_sql_name[0]? database_sql_name : tb_null, (tb_uint_t)port, tb_null, 0))
{
// save state
mysql->base.state = tb_database_mysql_state_from_errno(mysql_errno(mysql->database));
// trace
tb_trace_e("open: host: %s failed, error[%d]: %s", host, mysql_errno(mysql->database), mysql_error(mysql->database));
break;
}
// disable auto commit
if (mysql_autocommit(mysql->database, 0))
{
// save state
mysql->base.state = tb_database_mysql_state_from_errno(mysql_errno(mysql->database));
// trace
tb_trace_e("open: disable auto commit failed, error[%d]: %s", mysql_errno(mysql->database), mysql_error(mysql->database));
break;
}
// ok
ok = tb_true;
} while (0);
// trace
tb_trace_d("open: host: %s, port: %lu, username: %s, password: %s, database: %s : %s", host, port, username, password, database_sql_name, ok? "ok" : "no");
// ok?
return ok;
}
static tb_void_t tb_database_mysql_clos(tb_database_sql_impl_t* database)
{
// check
tb_database_mysql_t* mysql = tb_database_mysql_cast(database);
tb_assert_and_check_return(mysql);
// clear bind data
tb_buffer_clear(&mysql->bind_data);
// clear bind list
if (mysql->bind_list && mysql->bind_maxn)
tb_memset(mysql->bind_list, 0, mysql->bind_maxn * sizeof(MYSQL_BIND));
// close database
if (mysql->database) mysql_close(mysql->database);
mysql->database = tb_null;
}
static tb_void_t tb_database_mysql_exit(tb_database_sql_impl_t* database)
{
// check
tb_database_mysql_t* mysql = tb_database_mysql_cast(database);
tb_assert_and_check_return(mysql);
// close it first
tb_database_mysql_clos(database);
// exit bind data
tb_buffer_exit(&mysql->bind_data);
// exit bind list
if (mysql->bind_list) tb_free(mysql->bind_list);
mysql->bind_list = tb_null;
mysql->bind_maxn = 0;
// exit url
tb_url_exit(&database->url);
// exit it
tb_free(mysql);
}
/* begin mysql transaction
*
* @note
* the default storage engine MyIASM do not support transaction
* need enable InnoDB engine and set autocommit=0 if you want to use it
*/
static tb_bool_t tb_database_mysql_begin(tb_database_sql_impl_t* database)
{
// check
tb_database_mysql_t* mysql = tb_database_mysql_cast(database);
tb_assert_and_check_return_val(mysql && mysql->database, tb_false);
// done begin
if (mysql_query(mysql->database, "begin;"))
{
// save state
mysql->base.state = tb_database_mysql_state_from_errno(mysql_errno(mysql->database));
// trace
tb_trace_e("begin: failed, error[%d]: %s", mysql_errno(mysql->database), mysql_error(mysql->database));
return tb_false;
}
// ok
return tb_true;
}
static tb_bool_t tb_database_mysql_commit(tb_database_sql_impl_t* database)
{
// check
tb_database_mysql_t* mysql = tb_database_mysql_cast(database);
tb_assert_and_check_return_val(mysql && mysql->database, tb_false);
// done commit
if (mysql_commit(mysql->database))
{
// save state
mysql->base.state = tb_database_mysql_state_from_errno(mysql_errno(mysql->database));
// trace
tb_trace_e("commit: failed, error[%d]: %s", mysql_errno(mysql->database), mysql_error(mysql->database));
return tb_false;
}
// ok
return tb_true;
}
static tb_bool_t tb_database_mysql_rollback(tb_database_sql_impl_t* database)
{
// check
tb_database_mysql_t* mysql = tb_database_mysql_cast(database);
tb_assert_and_check_return_val(mysql && mysql->database, tb_false);
// done rollback
if (mysql_rollback(mysql->database))
{
// save state
mysql->base.state = tb_database_mysql_state_from_errno(mysql_errno(mysql->database));
// trace
tb_trace_e("rollback: failed, error[%d]: %s", mysql_errno(mysql->database), mysql_error(mysql->database));
return tb_false;
}
// ok
return tb_true;
}
static tb_bool_t tb_database_mysql_done(tb_database_sql_impl_t* database, tb_char_t const* sql)
{
// check
tb_database_mysql_t* mysql = tb_database_mysql_cast(database);
tb_assert_and_check_return_val(mysql && mysql->database && sql, tb_false);
// exit the last result first
tb_database_mysql_result_exit(database, (tb_iterator_ref_t)&mysql->result);
// done query
if (mysql_query(mysql->database, sql))
{
// save state
mysql->base.state = tb_database_mysql_state_from_errno(mysql_errno(mysql->database));
// trace
tb_trace_e("done: sql: %s failed, error[%d]: %s", sql, mysql_errno(mysql->database), mysql_error(mysql->database));
return tb_false;
}
// trace
tb_trace_d("done: sql: %s: ok", sql);
// ok
return tb_true;
}
static tb_void_t tb_database_mysql_result_exit(tb_database_sql_impl_t* database, tb_iterator_ref_t result)
{
// check
tb_database_mysql_result_t* mysql_result = (tb_database_mysql_result_t*)result;
tb_assert_and_check_return(mysql_result);
// exit stream
if (mysql_result->stream) tb_stream_exit(mysql_result->stream);
mysql_result->stream = tb_null;
// exit result
if (mysql_result->result) mysql_free_result(mysql_result->result);
mysql_result->result = tb_null;
mysql_result->fields = tb_null;
// clear result
mysql_result->count = 0;
mysql_result->row.count = 0;
// exit metadata
if (mysql_result->metadata) mysql_free_result(mysql_result->metadata);
mysql_result->metadata = tb_null;
// clear statement
if (mysql_result->statement && mysql_result->try_all)
mysql_stmt_free_result(mysql_result->statement);
mysql_result->statement = tb_null;
// reset try all
mysql_result->try_all = tb_false;
}
static tb_size_t tb_database_mysql_result_type_size(tb_size_t type)
{
// done
tb_size_t size = 0;
switch (type)
{
case MYSQL_TYPE_STRING: size = 8192; break;
case MYSQL_TYPE_LONG: size = 4; break;
case MYSQL_TYPE_LONGLONG: size = 8; break;
case MYSQL_TYPE_SHORT: size = 2; break;
case MYSQL_TYPE_TINY: size = 1; break;
case MYSQL_TYPE_INT24: size = 3; break;
// TODO: for text and tinyblob
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB: size = 65536; break;
case MYSQL_TYPE_TINY_BLOB: size = 256; break;
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
case MYSQL_TYPE_FLOAT: size = 4; break;
case MYSQL_TYPE_DOUBLE: size = 8; break;
#endif
case MYSQL_TYPE_NULL: break;
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_TIME:
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_YEAR:
case MYSQL_TYPE_SET:
case MYSQL_TYPE_ENUM:
tb_trace_e("not supported field type: %d", type);
break;
default:
tb_trace_e("unknown field type: %d", type);
break;
}
// ok?
return size;
}
static tb_size_t tb_database_mysql_result_bind_maxn(tb_database_mysql_t* mysql)
{
// check
tb_assert_and_check_return_val(mysql && mysql->result.statement && mysql->result.fields, 0);
// walk
tb_size_t i = 0;
tb_size_t m = 0;
tb_size_t n = mysql->result.row.count;
for (i = 0; i < n; i++)
{
// += buffer
m += tb_database_mysql_result_type_size(mysql->result.fields[i].type);
// += length
m += sizeof(tb_ulong_t);
// += is_null
m += sizeof(my_bool);
}
// ok?
return m;
}
static tb_bool_t tb_database_mysql_result_bind_data(tb_database_mysql_t* mysql)
{
// check
tb_assert_and_check_return_val(mysql && mysql->result.statement && mysql->result.fields, tb_false);
// done
tb_bool_t ok = tb_false;
do
{
// check
tb_assert_and_check_break(mysql->bind_list && mysql->result.row.count <= mysql->bind_maxn);
// the bind data and maxn
tb_byte_t* bind_data = tb_buffer_data(&mysql->bind_data);
tb_size_t bind_maxn = tb_buffer_maxn(&mysql->bind_data);
tb_assert_and_check_break(bind_data && bind_maxn);
// clear data
tb_memset(bind_data, 0, bind_maxn);
// bind data
tb_size_t i = 0;
tb_size_t n = mysql->result.row.count;
tb_byte_t* p = bind_data;
tb_byte_t* e = bind_data + bind_maxn;
for (i = 0; i < n; i++)
{
// the bind
MYSQL_BIND* bind = &mysql->bind_list[i];
// bind type
bind->buffer_type = mysql->result.fields[i].type;
// bind buffer length
bind->buffer_length = (tb_ulong_t)tb_database_mysql_result_type_size(bind->buffer_type);
// bind buffer
tb_assert_and_check_break(p + bind->buffer_length < e);
bind->buffer = bind->buffer_length? (tb_char_t*)p : tb_null;
p += bind->buffer_length;
// bind is_unsigned
bind->is_unsigned = (mysql->result.fields[i].flags & UNSIGNED_FLAG)? 1 : 0;
// bind length
tb_assert_and_check_break(p + sizeof(tb_ulong_t) < e);
bind->length = (tb_ulong_t*)p;
p += sizeof(tb_ulong_t);
// bind is_null
tb_assert_and_check_break(p + sizeof(my_bool) < e);
bind->is_null = (my_bool*)p;
p += sizeof(my_bool);
}
// check
tb_assert_and_check_break(i == n);
// bind result
if (mysql_stmt_bind_result(mysql->result.statement, mysql->bind_list))
{
// save state
mysql->base.state = tb_database_mysql_state_from_errno(mysql_stmt_errno(mysql->result.statement));
// trace
tb_trace_e("statement: bind result failed, error[%d]: %s", mysql_stmt_errno(mysql->result.statement), mysql_stmt_error(mysql->result.statement));
break;
}
// ok
ok = tb_true;
} while (0);
// ok?
return ok;
}
static tb_bool_t tb_database_mysql_result_bind(tb_database_mysql_t* mysql, tb_bool_t try_all)
{
// check
tb_assert_and_check_return_val(mysql && mysql->result.statement, tb_false);
// done
tb_bool_t ok = tb_false;
do
{
// load the field infos
mysql->result.metadata = mysql_stmt_result_metadata(mysql->result.statement);
tb_check_break(mysql->result.metadata);
// save result col count
mysql->result.row.count = (tb_size_t)mysql_num_fields(mysql->result.metadata);
tb_assert_and_check_break(mysql->result.row.count);
// load result fields
mysql->result.fields = mysql_fetch_fields(mysql->result.metadata);
tb_assert_and_check_break(mysql->result.fields);
// make bind list
if (!mysql->bind_list)
{
mysql->bind_maxn = mysql->result.row.count + 16;
mysql->bind_list = (MYSQL_BIND*)tb_nalloc(mysql->bind_maxn, sizeof(MYSQL_BIND));
}
// grow bind list
else if (mysql->result.row.count > mysql->bind_maxn)
{
mysql->bind_maxn = mysql->result.row.count + 16;
mysql->bind_list = (MYSQL_BIND*)tb_ralloc(mysql->bind_list, mysql->bind_maxn * sizeof(MYSQL_BIND));
}
// check
tb_assert_and_check_break(mysql->bind_list && mysql->result.row.count <= mysql->bind_maxn);
// clear bind list
tb_memset(mysql->bind_list, 0, mysql->bind_maxn * sizeof(MYSQL_BIND));
// compute bind maxn
tb_size_t bind_maxn = tb_database_mysql_result_bind_maxn(mysql);
tb_assert_and_check_break(bind_maxn);
// resize bind data
if (!tb_buffer_resize(&mysql->bind_data, bind_maxn)) break;
// bind result data
if (!tb_database_mysql_result_bind_data(mysql)) break;
// load all?
if (try_all && mysql_stmt_store_result(mysql->result.statement))
{
// save state
mysql->base.state = tb_database_mysql_state_from_errno(mysql_stmt_errno(mysql->result.statement));
// trace
tb_trace_e("statement: load all result failed, error[%d]: %s", mysql_stmt_errno(mysql->result.statement), mysql_stmt_error(mysql->result.statement));
break;
}
// try loading all?
mysql->result.try_all = try_all;
// save result row count
mysql->result.count = try_all? (tb_size_t)mysql_stmt_num_rows(mysql->result.statement) : -1;
// init mode
mysql->result.itor.mode = (try_all? TB_ITERATOR_MODE_RACCESS : TB_ITERATOR_MODE_FORWARD) | TB_ITERATOR_MODE_READONLY;
// ok
ok = tb_true;
} while (0);
// ok?
return ok;
}
static tb_iterator_ref_t tb_database_mysql_result_load(tb_database_sql_impl_t* database, tb_bool_t try_all)
{
// check
tb_database_mysql_t* mysql = tb_database_mysql_cast(database);
tb_assert_and_check_return_val(mysql && mysql->database, tb_null);
// done
tb_bool_t ok = tb_false;
do
{
// load result from statement
if (mysql->result.statement)
{
// bind result
if (!tb_database_mysql_result_bind(mysql, try_all)) break;
// try fetching the first result
if (!try_all)
{
// fetch the first row
tb_int_t ok = 0;
if ((ok = mysql_stmt_fetch(mysql->result.statement)))
{
// end or error?
if (ok != MYSQL_DATA_TRUNCATED)
{
// error?
if (ok != MYSQL_NO_DATA)
{
// save state
mysql->base.state = tb_database_mysql_state_from_errno(mysql_stmt_errno(mysql->result.statement));
// trace
tb_trace_e("statement: fetch row head failed, error[%d]: %s", mysql_stmt_errno(mysql->result.statement), mysql_stmt_error(mysql->result.statement));
}
break;
}
}
}
}
else
{
// load result
mysql->result.result = try_all? mysql_store_result(mysql->database) : mysql_use_result(mysql->database);
tb_check_break(mysql->result.result);
// try fetching the first result
if (!try_all)
{
// fetch the first row
mysql->result.row.row = mysql_fetch_row(mysql->result.result);
tb_check_break(mysql->result.row.row);
// fetch the first lengths
mysql->result.row.lengths = mysql_fetch_lengths(mysql->result.result);
tb_assert_and_check_break(mysql->result.row.lengths);
}
// load result fields
mysql->result.fields = mysql_fetch_fields(mysql->result.result);
tb_assert_and_check_break(mysql->result.fields);
// save result row count
mysql->result.count = try_all? (tb_size_t)mysql_num_rows(mysql->result.result) : -1;
// save result col count
mysql->result.row.count = (tb_size_t)mysql_num_fields(mysql->result.result);
// try loading all?
mysql->result.try_all = try_all;
// init mode
mysql->result.itor.mode = (try_all? TB_ITERATOR_MODE_RACCESS : TB_ITERATOR_MODE_FORWARD) | TB_ITERATOR_MODE_READONLY;
}
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit result
tb_database_mysql_result_exit(database, (tb_iterator_ref_t)&mysql->result);
}
// ok?
return ok? (tb_iterator_ref_t)&mysql->result : tb_null;
}
static tb_database_sql_statement_ref_t tb_database_mysql_statement_init(tb_database_sql_impl_t* database, tb_char_t const* sql)
{
// check
tb_database_mysql_t* mysql = tb_database_mysql_cast(database);
tb_assert_and_check_return_val(mysql && mysql->database && sql, tb_null);
// done
tb_bool_t ok = tb_false;
MYSQL_STMT* statement = tb_null;
do
{
// init statement
statement = mysql_stmt_init(mysql->database);
if (!statement)
{
// save state
mysql->base.state = tb_database_mysql_state_from_errno(mysql_errno(mysql->database));
// trace
tb_trace_e("statement: init: %s failed, error[%d]: %s", sql, mysql_errno(mysql->database), mysql_error(mysql->database));
break;
}
// prepare statement
if (mysql_stmt_prepare(statement, sql, tb_strlen(sql)))
{
// save state
mysql->base.state = tb_database_mysql_state_from_errno(mysql_stmt_errno(statement));
// trace
tb_trace_e("statement: prepare: %s failed, error[%d]: %s", sql, mysql_stmt_errno(statement), mysql_stmt_error(statement));
break;
}
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (statement) mysql_stmt_close(statement);
statement = tb_null;
}
// ok?
return (tb_database_sql_statement_ref_t)statement;
}
static tb_void_t tb_database_mysql_statement_exit(tb_database_sql_impl_t* database, tb_database_sql_statement_ref_t statement)
{
// exit it
if (statement) mysql_stmt_close((MYSQL_STMT*)statement);
}
static tb_bool_t tb_database_mysql_statement_done(tb_database_sql_impl_t* database, tb_database_sql_statement_ref_t statement)
{
// check
tb_database_mysql_t* mysql = tb_database_mysql_cast(database);
tb_assert_and_check_return_val(mysql && mysql->database && statement, tb_false);
// done
tb_bool_t ok = tb_false;
do
{
// exit the last result first
tb_database_mysql_result_exit(database, (tb_iterator_ref_t)&mysql->result);
// done statement
if (mysql_stmt_execute((MYSQL_STMT*)statement))
{
// save state
mysql->base.state = tb_database_mysql_state_from_errno(mysql_stmt_errno((MYSQL_STMT*)statement));
// trace
tb_trace_e("statement: done failed, error[%d]: %s", mysql_stmt_errno((MYSQL_STMT*)statement), mysql_stmt_error((MYSQL_STMT*)statement));
break;
}
// save statement
mysql->result.statement = (MYSQL_STMT*)statement;
// ok
ok = tb_true;
} while (0);
// ok?
return ok;
}
static tb_bool_t tb_database_mysql_statement_bind(tb_database_sql_impl_t* database, tb_database_sql_statement_ref_t statement, tb_database_sql_value_t const* list, tb_size_t size)
{
// check
tb_database_mysql_t* mysql = tb_database_mysql_cast(database);
tb_assert_and_check_return_val(mysql && mysql->database && statement && list && size, tb_false);
// done
tb_bool_t ok = tb_false;
do
{
// check the param count
tb_size_t param_count = mysql_stmt_param_count((MYSQL_STMT*)statement);
tb_assert_and_check_break(size == param_count);
// make bind list
if (!mysql->bind_list)
{
mysql->bind_maxn = size + 16;
mysql->bind_list = (MYSQL_BIND*)tb_nalloc(mysql->bind_maxn, sizeof(MYSQL_BIND));
}
// grow bind list
else if (size > mysql->bind_maxn)
{
mysql->bind_maxn = size + 16;
mysql->bind_list = (MYSQL_BIND*)tb_ralloc(mysql->bind_list, mysql->bind_maxn * sizeof(MYSQL_BIND));
}
// check
tb_assert_and_check_break(mysql->bind_list && size <= mysql->bind_maxn);
// clear bind list
tb_memset(mysql->bind_list, 0, mysql->bind_maxn * sizeof(MYSQL_BIND));
// init bind list
tb_size_t i = 0;
for (i = 0; i < size; i++)
{
// the value
tb_database_sql_value_t const* value = &list[i];
switch (value->type)
{
case TB_DATABASE_SQL_VALUE_TYPE_TEXT:
mysql->bind_list[i].buffer_type = MYSQL_TYPE_STRING;
mysql->bind_list[i].buffer = (tb_char_t*)tb_database_sql_value_text(value);
mysql->bind_list[i].buffer_length = tb_database_sql_value_size(value) + 1;
break;
case TB_DATABASE_SQL_VALUE_TYPE_INT64:
mysql->bind_list[i].buffer_type = MYSQL_TYPE_LONGLONG;
mysql->bind_list[i].buffer = (tb_char_t*)&value->u.i64;
break;
case TB_DATABASE_SQL_VALUE_TYPE_INT32:
mysql->bind_list[i].buffer_type = MYSQL_TYPE_LONG;
mysql->bind_list[i].buffer = (tb_char_t*)&value->u.i32;
break;
case TB_DATABASE_SQL_VALUE_TYPE_INT16:
mysql->bind_list[i].buffer_type = MYSQL_TYPE_SHORT;
mysql->bind_list[i].buffer = (tb_char_t*)&value->u.i16;
break;
case TB_DATABASE_SQL_VALUE_TYPE_INT8:
mysql->bind_list[i].buffer_type = MYSQL_TYPE_TINY;
mysql->bind_list[i].buffer = (tb_char_t*)&value->u.i8;
break;
case TB_DATABASE_SQL_VALUE_TYPE_UINT64:
mysql->bind_list[i].buffer_type = MYSQL_TYPE_LONGLONG;
mysql->bind_list[i].buffer = (tb_char_t*)&value->u.u64;
mysql->bind_list[i].is_unsigned = 1;
break;
case TB_DATABASE_SQL_VALUE_TYPE_UINT32:
mysql->bind_list[i].buffer_type = MYSQL_TYPE_LONG;
mysql->bind_list[i].buffer = (tb_char_t*)&value->u.u32;
mysql->bind_list[i].is_unsigned = 1;
break;
case TB_DATABASE_SQL_VALUE_TYPE_UINT16:
mysql->bind_list[i].buffer_type = MYSQL_TYPE_SHORT;
mysql->bind_list[i].buffer = (tb_char_t*)&value->u.u16;
mysql->bind_list[i].is_unsigned = 1;
break;
case TB_DATABASE_SQL_VALUE_TYPE_UINT8:
mysql->bind_list[i].buffer_type = MYSQL_TYPE_TINY;
mysql->bind_list[i].buffer = (tb_char_t*)&value->u.u8;
mysql->bind_list[i].is_unsigned = 1;
break;
case TB_DATABASE_SQL_VALUE_TYPE_BLOB32:
mysql->bind_list[i].buffer_type = MYSQL_TYPE_LONG_BLOB;
mysql->bind_list[i].buffer = (tb_char_t*)tb_database_sql_value_blob(value);
mysql->bind_list[i].buffer_length = tb_database_sql_value_size(value);
mysql->bind_list[i].length = &mysql->bind_list[i].buffer_length;
break;
case TB_DATABASE_SQL_VALUE_TYPE_BLOB16:
mysql->bind_list[i].buffer_type = MYSQL_TYPE_BLOB;
mysql->bind_list[i].buffer = (tb_char_t*)tb_database_sql_value_blob(value);
mysql->bind_list[i].buffer_length = tb_database_sql_value_size(value);
mysql->bind_list[i].length = &mysql->bind_list[i].buffer_length;
break;
case TB_DATABASE_SQL_VALUE_TYPE_BLOB8:
mysql->bind_list[i].buffer_type = MYSQL_TYPE_TINY_BLOB;
mysql->bind_list[i].buffer = (tb_char_t*)tb_database_sql_value_blob(value);
mysql->bind_list[i].buffer_length = tb_database_sql_value_size(value);
mysql->bind_list[i].length = &mysql->bind_list[i].buffer_length;
break;
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
case TB_DATABASE_SQL_VALUE_TYPE_FLOAT:
mysql->bind_list[i].buffer_type = MYSQL_TYPE_FLOAT;
mysql->bind_list[i].buffer = (tb_char_t*)&value->u.f;
break;
case TB_DATABASE_SQL_VALUE_TYPE_DOUBLE:
mysql->bind_list[i].buffer_type = MYSQL_TYPE_DOUBLE;
mysql->bind_list[i].buffer = (tb_char_t*)&value->u.d;
break;
#endif
case TB_DATABASE_SQL_VALUE_TYPE_NULL:
mysql->bind_list[i].buffer_type = MYSQL_TYPE_NULL;
break;
default:
tb_trace_e("statement: bind: unknown value type: %lu", value->type);
break;
}
}
// bind it
if (mysql_stmt_bind_param((MYSQL_STMT*)statement, mysql->bind_list))
{
// save state
mysql->base.state = tb_database_mysql_state_from_errno(mysql_stmt_errno((MYSQL_STMT*)statement));
// trace
tb_trace_e("statement: bind failed, error[%d]: %s", mysql_stmt_errno((MYSQL_STMT*)statement), mysql_stmt_error((MYSQL_STMT*)statement));
break;
}
// send blob32 data
tb_byte_t data[TB_STREAM_BLOCK_MAXN];
for (i = 0; i < size; i++)
{
// the value
tb_database_sql_value_t const* value = &list[i];
if (value->type == TB_DATABASE_SQL_VALUE_TYPE_BLOB32 && value->u.blob.stream)
{
// trace
tb_trace_d("statement: bind: send: blob: %lld: ..", tb_stream_size(value->u.blob.stream));
// done
while (!tb_stream_beof(value->u.blob.stream))
{
// read it
tb_long_t real = tb_stream_read(value->u.blob.stream, data, sizeof(data));
if (real > 0)
{
// send it
if (mysql_stmt_send_long_data((MYSQL_STMT*)statement, i, (tb_char_t const*)data, real))
{
// save state
mysql->base.state = tb_database_mysql_state_from_errno(mysql_stmt_errno((MYSQL_STMT*)statement));
// trace
tb_trace_e("statement: bind: send blob data failed, error[%d]: %s", mysql_stmt_errno((MYSQL_STMT*)statement), mysql_stmt_error((MYSQL_STMT*)statement));
break;
}
}
else if (!real)
{
// wait
tb_long_t wait = tb_stream_wait(value->u.blob.stream, TB_STREAM_WAIT_READ, tb_stream_timeout(value->u.blob.stream));
tb_assert_and_check_break(wait > 0);
}
else break;
}
}
}
// ok
ok = tb_true;
} while (0);
// ok?
return ok;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_size_t tb_database_mysql_probe(tb_url_ref_t url)
{
// check
tb_assert_and_check_return_val(url, 0);
// done
tb_size_t score = 0;
do
{
// the url arguments
tb_char_t const* args = tb_url_args(url);
if (args)
{
// find the database type
tb_char_t const* ptype = tb_stristr(args, "type=");
if (ptype && !tb_strnicmp(ptype + 5, "mysql", 5))
{
// ok
score = 100;
break;
}
}
// the database port, the default port: 3306
if (tb_url_port(url) == 3306) score += 20;
// is sql url?
if (tb_url_protocol(url) == TB_URL_PROTOCOL_SQL)
score += 5;
} while (0);
// trace
tb_trace_d("probe: %s, score: %lu", tb_url_cstr((tb_url_ref_t)url), score);
// ok?
return score;
}
tb_database_sql_ref_t tb_database_mysql_init(tb_url_ref_t url)
{
// check
tb_assert_and_check_return_val(url, tb_null);
// done
tb_bool_t ok = tb_false;
tb_database_mysql_t* mysql = tb_null;
do
{
// make database
mysql = tb_malloc0_type(tb_database_mysql_t);
tb_assert_and_check_break(mysql);
// init database
mysql->base.type = TB_DATABASE_SQL_TYPE_MYSQL;
mysql->base.open = tb_database_mysql_open;
mysql->base.clos = tb_database_mysql_clos;
mysql->base.exit = tb_database_mysql_exit;
mysql->base.done = tb_database_mysql_done;
mysql->base.begin = tb_database_mysql_begin;
mysql->base.commit = tb_database_mysql_commit;
mysql->base.rollback = tb_database_mysql_rollback;
mysql->base.result_load = tb_database_mysql_result_load;
mysql->base.result_exit = tb_database_mysql_result_exit;
mysql->base.statement_init = tb_database_mysql_statement_init;
mysql->base.statement_exit = tb_database_mysql_statement_exit;
mysql->base.statement_done = tb_database_mysql_statement_done;
mysql->base.statement_bind = tb_database_mysql_statement_bind;
// init row operation
static tb_iterator_op_t row_op =
{
tb_database_mysql_result_row_iterator_size
, tb_database_mysql_result_row_iterator_head
, tb_null
, tb_database_mysql_result_row_iterator_tail
, tb_database_mysql_result_row_iterator_prev
, tb_database_mysql_result_row_iterator_next
, tb_database_mysql_result_row_iterator_item
, tb_null
, tb_null
, tb_null
, tb_null
};
// init col operation
static tb_iterator_op_t col_op =
{
tb_database_mysql_result_col_iterator_size
, tb_database_mysql_result_col_iterator_head
, tb_null
, tb_database_mysql_result_col_iterator_tail
, tb_database_mysql_result_col_iterator_prev
, tb_database_mysql_result_col_iterator_next
, tb_database_mysql_result_col_iterator_item
, tb_null
, tb_null
, tb_null
, tb_null
};
// init result row iterator
mysql->result.itor.mode = TB_ITERATOR_MODE_RACCESS | TB_ITERATOR_MODE_READONLY;
mysql->result.itor.priv = (tb_pointer_t)mysql;
mysql->result.itor.step = 0;
mysql->result.itor.op = &row_op;
// init result col iterator
mysql->result.row.itor.mode = TB_ITERATOR_MODE_RACCESS | TB_ITERATOR_MODE_READONLY;
mysql->result.row.itor.priv = (tb_pointer_t)mysql;
mysql->result.row.itor.step = 0;
mysql->result.row.itor.op = &col_op;
// init url
if (!tb_url_init(&mysql->base.url)) break;
// copy url
tb_url_copy(&mysql->base.url, url);
// init state
mysql->base.state = TB_STATE_OK;
// init bind
if (!tb_buffer_init(&mysql->bind_data)) break;
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit database
if (mysql) tb_database_mysql_exit((tb_database_sql_impl_t*)mysql);
mysql = tb_null;
}
// ok?
return (tb_database_sql_ref_t)mysql;
}
tbox-1.7.6/src/tbox/database/impl/mysql.h 0000664 0000000 0000000 00000003122 14671175054 0020277 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file mysql.h
*/
#ifndef TB_DATABASE_IMPL_MYSQL_H
#define TB_DATABASE_IMPL_MYSQL_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* probe mysql from the url
*
* @param url the database url
*
* @return the score
*/
tb_size_t tb_database_mysql_probe(tb_url_ref_t url);
/* init mysql
*
* @param url the database url
*
* @return the database handle
*/
tb_database_sql_ref_t tb_database_mysql_init(tb_url_ref_t url);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/database/impl/prefix.h 0000664 0000000 0000000 00000006055 14671175054 0020437 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_DATABASE_IMPL_PREFIX_H
#define TB_DATABASE_IMPL_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#include "../sql.h"
#include "sqlite3.h"
#include "mysql.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the database sql impl type
typedef struct __tb_database_sql_impl_t
{
// the url
tb_url_t url;
// the type
tb_size_t type;
// the state
tb_size_t state;
// is opened?
tb_bool_t bopened;
// open
tb_bool_t (*open)(struct __tb_database_sql_impl_t* database);
// clos
tb_void_t (*clos)(struct __tb_database_sql_impl_t* database);
// exit
tb_void_t (*exit)(struct __tb_database_sql_impl_t* database);
// done
tb_bool_t (*done)(struct __tb_database_sql_impl_t* database, tb_char_t const* sql);
// begin
tb_bool_t (*begin)(struct __tb_database_sql_impl_t* database);
// commit
tb_bool_t (*commit)(struct __tb_database_sql_impl_t* database);
// rollback
tb_bool_t (*rollback)(struct __tb_database_sql_impl_t* database);
// load result
tb_iterator_ref_t (*result_load)(struct __tb_database_sql_impl_t* database, tb_bool_t try_all);
// exit result
tb_void_t (*result_exit)(struct __tb_database_sql_impl_t* database, tb_iterator_ref_t result);
// statement init
tb_database_sql_statement_ref_t (*statement_init)(struct __tb_database_sql_impl_t* database, tb_char_t const* sql);
// statement exit
tb_void_t (*statement_exit)(struct __tb_database_sql_impl_t* database, tb_database_sql_statement_ref_t statement);
// statement done
tb_bool_t (*statement_done)(struct __tb_database_sql_impl_t* database, tb_database_sql_statement_ref_t statement);
// statement bind
tb_bool_t (*statement_bind)(struct __tb_database_sql_impl_t* database, tb_database_sql_statement_ref_t statement, tb_database_sql_value_t const* list, tb_size_t size);
}tb_database_sql_impl_t;
#endif
tbox-1.7.6/src/tbox/database/impl/sqlite3.c 0000664 0000000 0000000 00000074153 14671175054 0020525 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file sqlite3.c
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "sqlite3"
#define TB_TRACE_MODULE_DEBUG (1)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the sqlite3 result row type
typedef struct __tb_database_sqlite3_result_row_t
{
// the iterator
tb_iterator_t itor;
// the row
tb_size_t row;
// the col count
tb_size_t count;
// the col value
tb_database_sql_value_t value;
}tb_database_sqlite3_result_row_t;
// the sqlite3 result type
typedef struct __tb_database_sqlite3_result_t
{
// the iterator
tb_iterator_t itor;
// the result
tb_char_t** result;
// the statement
sqlite3_stmt* statement;
// the row count
tb_size_t count;
// the row
tb_database_sqlite3_result_row_t row;
}tb_database_sqlite3_result_t;
// the sqlite3 type
typedef struct __tb_database_sqlite3_t
{
// the base
tb_database_sql_impl_t base;
// the database
sqlite3* database;
// the result
tb_database_sqlite3_result_t result;
}tb_database_sqlite3_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* library implementation
*/
static tb_handle_t tb_database_sqlite3_library_init(tb_cpointer_t* ppriv)
{
// init it
tb_int_t ok = SQLITE_OK;
if ((ok = sqlite3_initialize()) != SQLITE_OK)
{
// trace
tb_trace_e("init: sqlite3 library failed, error: %d", ok);
return tb_null;
}
// ok
return ppriv;
}
static tb_void_t tb_database_sqlite3_library_exit(tb_handle_t handle, tb_cpointer_t priv)
{
// exit it
sqlite3_shutdown();
}
static tb_handle_t tb_database_sqlite3_library_load()
{
return tb_singleton_instance(TB_SINGLETON_TYPE_LIBRARY_SQLITE3, tb_database_sqlite3_library_init, tb_database_sqlite3_library_exit, tb_null, tb_null);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* state implementation
*/
static tb_size_t tb_database_sqlite3_state_from_errno(tb_size_t errno)
{
// done
tb_size_t state = TB_STATE_DATABASE_UNKNOWN_ERROR;
switch (errno)
{
case SQLITE_NOTADB:
state = TB_STATE_DATABASE_NO_SUCH_DATABASE;
break;
case SQLITE_PERM:
case SQLITE_AUTH:
state = TB_STATE_DATABASE_ACCESS_DENIED;
break;
case SQLITE_ERROR:
case SQLITE_INTERNAL:
break;
default:
tb_trace_e("unknown errno: %lu", errno);
break;
}
// ok?
return state;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* iterator implementation
*/
static tb_size_t tb_database_sqlite3_result_row_iterator_size(tb_iterator_ref_t iterator)
{
// check
tb_database_sqlite3_result_t* result = (tb_database_sqlite3_result_t*)iterator;
tb_assert(result);
// size
return result->count;
}
static tb_size_t tb_database_sqlite3_result_row_iterator_head(tb_iterator_ref_t iterator)
{
// head
return 0;
}
static tb_size_t tb_database_sqlite3_result_row_iterator_tail(tb_iterator_ref_t iterator)
{
// check
tb_database_sqlite3_result_t* result = (tb_database_sqlite3_result_t*)iterator;
tb_assert(result);
// tail
return result->count;
}
static tb_size_t tb_database_sqlite3_result_row_iterator_prev(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_database_sqlite3_result_t* result = (tb_database_sqlite3_result_t*)iterator;
tb_assert(result);
tb_assert_and_check_return_val(itor && itor <= result->count, result->count);
// cannot be the statement result
tb_assert_and_check_return_val(!result->statement, result->count);
// prev
return itor - 1;
}
static tb_size_t tb_database_sqlite3_result_row_iterator_next(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_database_sqlite3_result_t* result = (tb_database_sqlite3_result_t*)iterator;
tb_assert(result);
tb_assert_and_check_return_val(itor < result->count, result->count);
// statement result?
if (result->statement)
{
// step statement
tb_int_t ok = sqlite3_step(result->statement);
// end?
if (ok != SQLITE_ROW)
{
// reset it
if (SQLITE_OK != sqlite3_reset(result->statement))
{
// the sqlite
tb_database_sqlite3_t* sqlite = (tb_database_sqlite3_t*)iterator->priv;
if (sqlite)
{
// save state
sqlite->base.state = tb_database_sqlite3_state_from_errno(sqlite3_errcode(sqlite->database));
// trace
tb_trace_e("statement: reset failed, error[%d]: %s", sqlite3_errcode(sqlite->database), sqlite3_errmsg(sqlite->database));
}
}
// tail
return result->count;
}
}
// next
return itor + 1;
}
static tb_pointer_t tb_database_sqlite3_result_row_iterator_item(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_database_sqlite3_result_t* result = (tb_database_sqlite3_result_t*)iterator;
tb_assert_and_check_return_val(result && (result->result || result->statement) && itor < result->count, tb_null);
// save the row
result->row.row = itor;
// the row iterator
return (tb_pointer_t)&result->row;
}
static tb_size_t tb_database_sqlite3_result_col_iterator_size(tb_iterator_ref_t iterator)
{
// check
tb_database_sqlite3_result_row_t* row = (tb_database_sqlite3_result_row_t*)iterator;
tb_assert_and_check_return_val(row, 0);
// size
return row->count;
}
static tb_size_t tb_database_sqlite3_result_col_iterator_head(tb_iterator_ref_t iterator)
{
// check
tb_database_sqlite3_result_row_t* row = (tb_database_sqlite3_result_row_t*)iterator;
tb_assert_and_check_return_val(row, 0);
// head
return 0;
}
static tb_size_t tb_database_sqlite3_result_col_iterator_tail(tb_iterator_ref_t iterator)
{
// check
tb_database_sqlite3_result_row_t* row = (tb_database_sqlite3_result_row_t*)iterator;
tb_assert_and_check_return_val(row, 0);
// tail
return row->count;
}
static tb_size_t tb_database_sqlite3_result_col_iterator_prev(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_database_sqlite3_result_row_t* row = (tb_database_sqlite3_result_row_t*)iterator;
tb_assert_and_check_return_val(row && itor && itor <= row->count, 0);
// prev
return itor - 1;
}
static tb_size_t tb_database_sqlite3_result_col_iterator_next(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_database_sqlite3_result_row_t* row = (tb_database_sqlite3_result_row_t*)iterator;
tb_assert_and_check_return_val(row && itor < row->count, row->count);
// next
return itor + 1;
}
static tb_pointer_t tb_database_sqlite3_result_col_iterator_item(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
tb_database_sqlite3_result_row_t* row = (tb_database_sqlite3_result_row_t*)iterator;
tb_assert_and_check_return_val(row && itor < row->count, tb_null);
// the sqlite
tb_database_sqlite3_t* sqlite = (tb_database_sqlite3_t*)iterator->priv;
tb_assert_and_check_return_val(sqlite, tb_null);
// result?
if (sqlite->result.result)
{
// init value
tb_database_sql_value_name_set(&row->value, (tb_char_t const*)sqlite->result.result[itor]);
tb_database_sql_value_set_text(&row->value, (tb_char_t const*)sqlite->result.result[((1 + sqlite->result.row.row) * row->count) + itor], 0);
return (tb_pointer_t)&row->value;
}
// statement result?
else if (sqlite->result.statement)
{
// init name
tb_database_sql_value_name_set(&row->value, sqlite3_column_name(sqlite->result.statement, (tb_int_t)itor));
// init type
tb_size_t type = sqlite3_column_type(sqlite->result.statement, (tb_int_t)itor);
switch (type)
{
case SQLITE_INTEGER:
tb_database_sql_value_set_int32(&row->value, sqlite3_column_int(sqlite->result.statement, (tb_int_t)itor));
break;
case SQLITE_TEXT:
tb_database_sql_value_set_text(&row->value, (tb_char_t const*)sqlite3_column_text(sqlite->result.statement, (tb_int_t)itor), sqlite3_column_bytes(sqlite->result.statement, (tb_int_t)itor));
break;
case SQLITE_FLOAT:
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
tb_database_sql_value_set_double(&row->value, sqlite3_column_double(sqlite->result.statement, (tb_int_t)itor));
break;
#else
// trace
tb_trace1_e("float type is not supported, at col: %lu, please enable float config!", itor);
return tb_null;
#endif
case SQLITE_BLOB:
tb_database_sql_value_set_blob32(&row->value, (tb_byte_t const*)sqlite3_column_blob(sqlite->result.statement, (tb_int_t)itor), sqlite3_column_bytes(sqlite->result.statement, (tb_int_t)itor), tb_null);
break;
case SQLITE_NULL:
tb_database_sql_value_set_null(&row->value);
break;
default:
tb_trace_e("unknown field type: %s, at col: %lu", type, itor);
return tb_null;
}
// ok
return (tb_pointer_t)&row->value;
}
// failed
tb_assert(0);
return tb_null;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static __tb_inline__ tb_database_sqlite3_t* tb_database_sqlite3_cast(tb_database_sql_impl_t* database)
{
// check
tb_assert_and_check_return_val(database && database->type == TB_DATABASE_SQL_TYPE_SQLITE3, tb_null);
// cast
return (tb_database_sqlite3_t*)database;
}
static tb_bool_t tb_database_sqlite3_open(tb_database_sql_impl_t* database)
{
// check
tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database);
tb_assert_and_check_return_val(sqlite, tb_false);
// done
tb_bool_t ok = tb_false;
tb_char_t const* path = tb_null;
do
{
// the database path
path = tb_url_cstr(&database->url);
tb_assert_and_check_break(path);
// load sqlite3 library
if (!tb_database_sqlite3_library_load()) break;
// open database
if (SQLITE_OK != sqlite3_open_v2(path, &sqlite->database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, tb_null) || !sqlite->database)
{
// error
if (sqlite->database)
{
// save state
sqlite->base.state = tb_database_sqlite3_state_from_errno(sqlite3_errcode(sqlite->database));
// trace
tb_trace_e("open: %s failed, error[%d]: %s", path, sqlite3_errcode(sqlite->database), sqlite3_errmsg(sqlite->database));
}
break;
}
// ok
ok = tb_true;
} while (0);
// trace
tb_trace_d("open: %s: %s", path, ok? "ok" : "no");
// ok?
return ok;
}
static tb_void_t tb_database_sqlite3_clos(tb_database_sql_impl_t* database)
{
// check
tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database);
tb_assert_and_check_return(sqlite);
// exit result first if exists
if (sqlite->result.result) sqlite3_free_table(sqlite->result.result);
sqlite->result.result = tb_null;
// close database
if (sqlite->database) sqlite3_close(sqlite->database);
sqlite->database = tb_null;
}
static tb_void_t tb_database_sqlite3_exit(tb_database_sql_impl_t* database)
{
// check
tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database);
tb_assert_and_check_return(sqlite);
// close it first
tb_database_sqlite3_clos(database);
// exit url
tb_url_exit(&database->url);
// exit it
tb_free(sqlite);
}
static tb_bool_t tb_database_sqlite3_begin(tb_database_sql_impl_t* database)
{
// check
tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database);
tb_assert_and_check_return_val(sqlite && sqlite->database, tb_false);
// done commit
if (SQLITE_OK != sqlite3_exec(sqlite->database, "begin;", tb_null, tb_null, tb_null))
{
// save state
sqlite->base.state = tb_database_sqlite3_state_from_errno(sqlite3_errcode(sqlite->database));
// trace
tb_trace_e("begin: failed, error[%d]: %s", sqlite3_errcode(sqlite->database), sqlite3_errmsg(sqlite->database));
return tb_false;
}
// ok
return tb_true;
}
static tb_bool_t tb_database_sqlite3_commit(tb_database_sql_impl_t* database)
{
// check
tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database);
tb_assert_and_check_return_val(sqlite && sqlite->database, tb_false);
// done commit
if (SQLITE_OK != sqlite3_exec(sqlite->database, "commit;", tb_null, tb_null, tb_null))
{
// save state
sqlite->base.state = tb_database_sqlite3_state_from_errno(sqlite3_errcode(sqlite->database));
// trace
tb_trace_e("commit: failed, error[%d]: %s", sqlite3_errcode(sqlite->database), sqlite3_errmsg(sqlite->database));
return tb_false;
}
// ok
return tb_true;
}
static tb_bool_t tb_database_sqlite3_rollback(tb_database_sql_impl_t* database)
{
// check
tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database);
tb_assert_and_check_return_val(sqlite && sqlite->database, tb_false);
// done rollback
if (SQLITE_OK != sqlite3_exec(sqlite->database, "rollback;", tb_null, tb_null, tb_null))
{
// save state
sqlite->base.state = tb_database_sqlite3_state_from_errno(sqlite3_errcode(sqlite->database));
// trace
tb_trace_e("rollback: failed, error[%d]: %s", sqlite3_errcode(sqlite->database), sqlite3_errmsg(sqlite->database));
return tb_false;
}
// ok
return tb_true;
}
static tb_bool_t tb_database_sqlite3_done(tb_database_sql_impl_t* database, tb_char_t const* sql)
{
// check
tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database);
tb_assert_and_check_return_val(sqlite && sqlite->database && sql, tb_false);
// done
tb_bool_t ok = tb_false;
do
{
// exit result first if exists
if (sqlite->result.result) sqlite3_free_table(sqlite->result.result);
sqlite->result.result = tb_null;
// clear the lasr statement first
sqlite->result.statement = tb_null;
// clear the result row count first
sqlite->result.count = 0;
// clear the result col count first
sqlite->result.row.count = 0;
// done sql
tb_int_t row_count = 0;
tb_int_t col_count = 0;
tb_char_t* error = tb_null;
if (SQLITE_OK != sqlite3_get_table(sqlite->database, sql, &sqlite->result.result, &row_count, &col_count, &error))
{
// save state
sqlite->base.state = tb_database_sqlite3_state_from_errno(sqlite3_errcode(sqlite->database));
// trace
tb_trace_e("done: sql: %s failed, error[%d]: %s", sql, sqlite3_errcode(sqlite->database), error);
// exit error
if (error) sqlite3_free(error);
break;
}
// no result?
if (!row_count)
{
// exit result
if (sqlite->result.result) sqlite3_free_table(sqlite->result.result);
sqlite->result.result = tb_null;
// trace
tb_trace_d("done: sql: %s: ok", sql);
// ok
ok = tb_true;
break;
}
// save the result iterator mode
sqlite->result.itor.mode = TB_ITERATOR_MODE_RACCESS | TB_ITERATOR_MODE_READONLY;
// save result row count
sqlite->result.count = row_count;
// save result col count
sqlite->result.row.count = col_count;
// trace
tb_trace_d("done: sql: %s: ok", sql);
// ok
ok = tb_true;
} while (0);
// ok?
return ok;
}
static tb_void_t tb_database_sqlite3_result_exit(tb_database_sql_impl_t* database, tb_iterator_ref_t result)
{
// check
tb_database_sqlite3_result_t* sqlite3_result = (tb_database_sqlite3_result_t*)result;
tb_assert_and_check_return(sqlite3_result);
// exit result
if (sqlite3_result->result) sqlite3_free_table(sqlite3_result->result);
sqlite3_result->result = tb_null;
// clear the statement
sqlite3_result->statement = tb_null;
// clear result
sqlite3_result->count = 0;
sqlite3_result->row.count = 0;
}
static tb_iterator_ref_t tb_database_sqlite3_result_load(tb_database_sql_impl_t* database, tb_bool_t try_all)
{
// check
tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database);
tb_assert_and_check_return_val(sqlite && sqlite->database, tb_null);
// ok?
return (sqlite->result.result || sqlite->result.statement)? (tb_iterator_ref_t)&sqlite->result : tb_null;
}
static tb_void_t tb_database_sqlite3_statement_exit(tb_database_sql_impl_t* database, tb_database_sql_statement_ref_t statement)
{
// exit statement
if (statement) sqlite3_finalize((sqlite3_stmt*)statement);
}
static tb_database_sql_statement_ref_t tb_database_sqlite3_statement_init(tb_database_sql_impl_t* database, tb_char_t const* sql)
{
// check
tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database);
tb_assert_and_check_return_val(sqlite && sqlite->database && sql, tb_null);
// init statement
sqlite3_stmt* statement = tb_null;
if (SQLITE_OK != sqlite3_prepare_v2(sqlite->database, sql, -1, &statement, 0))
{
// save state
sqlite->base.state = tb_database_sqlite3_state_from_errno(sqlite3_errcode(sqlite->database));
// trace
tb_trace_e("statement: init %s failed, error[%d]: %s", sql, sqlite3_errcode(sqlite->database), sqlite3_errmsg(sqlite->database));
}
// ok?
return (tb_database_sql_statement_ref_t)statement;
}
static tb_bool_t tb_database_sqlite3_statement_done(tb_database_sql_impl_t* database, tb_database_sql_statement_ref_t statement)
{
// check
tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database);
tb_assert_and_check_return_val(sqlite && sqlite->database && statement, tb_false);
// done
tb_bool_t ok = tb_false;
do
{
// exit result first if exists
if (sqlite->result.result) sqlite3_free_table(sqlite->result.result);
sqlite->result.result = tb_null;
// clear the last statement first
sqlite->result.statement = tb_null;
// clear the result row count first
sqlite->result.count = 0;
// clear the result col count first
sqlite->result.row.count = 0;
// step statement
tb_int_t result = sqlite3_step((sqlite3_stmt*)statement);
tb_assert_and_check_break(result == SQLITE_DONE || result == SQLITE_ROW);
// exists result?
if (result == SQLITE_ROW)
{
// save the result iterator mode
sqlite->result.itor.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_READONLY;
// save statement for iterating it
sqlite->result.statement = (sqlite3_stmt*)statement;
// save result row count
sqlite->result.count = (tb_size_t)-1;
// save result col count
sqlite->result.row.count = sqlite3_column_count((sqlite3_stmt*)statement);
}
else
{
// reset it
if (SQLITE_OK != sqlite3_reset((sqlite3_stmt*)statement))
{
// save state
sqlite->base.state = tb_database_sqlite3_state_from_errno(sqlite3_errcode(sqlite->database));
// trace
tb_trace_e("statement: reset failed, error[%d]: %s", sqlite3_errcode(sqlite->database), sqlite3_errmsg(sqlite->database));
// failed
break;
}
}
// ok
ok = tb_true;
} while (0);
// ok?
return ok;
}
static tb_void_t tb_database_sqlite3_statement_bind_exit(tb_pointer_t data)
{
// trace
tb_trace_d("bind: exit: %p", data);
// exit it
if (data) tb_free(data);
}
static tb_bool_t tb_database_sqlite3_statement_bind(tb_database_sql_impl_t* database, tb_database_sql_statement_ref_t statement, tb_database_sql_value_t const* list, tb_size_t size)
{
// check
tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database);
tb_assert_and_check_return_val(sqlite && sqlite->database && statement && list && size, tb_false);
// the param count
tb_size_t param_count = (tb_size_t)sqlite3_bind_parameter_count((sqlite3_stmt*)statement);
tb_assert_and_check_return_val(size == param_count, tb_false);
// walk
tb_size_t i = 0;
for (i = 0; i < size; i++)
{
// the value
tb_database_sql_value_t const* value = &list[i];
// done
tb_int_t ok = SQLITE_ERROR;
tb_byte_t* data = tb_null;
switch (value->type)
{
case TB_DATABASE_SQL_VALUE_TYPE_TEXT:
tb_trace_i("sqlite3: test %lu %s", i, value->u.text.data);
ok = sqlite3_bind_text((sqlite3_stmt*)statement, (tb_int_t)(i + 1), value->u.text.data, (tb_int_t)tb_database_sql_value_size(value), tb_null);
break;
case TB_DATABASE_SQL_VALUE_TYPE_INT64:
case TB_DATABASE_SQL_VALUE_TYPE_UINT64:
ok = sqlite3_bind_int64((sqlite3_stmt*)statement, (tb_int_t)(i + 1), tb_database_sql_value_int64(value));
break;
case TB_DATABASE_SQL_VALUE_TYPE_INT32:
case TB_DATABASE_SQL_VALUE_TYPE_INT16:
case TB_DATABASE_SQL_VALUE_TYPE_INT8:
case TB_DATABASE_SQL_VALUE_TYPE_UINT32:
case TB_DATABASE_SQL_VALUE_TYPE_UINT16:
case TB_DATABASE_SQL_VALUE_TYPE_UINT8:
ok = sqlite3_bind_int((sqlite3_stmt*)statement, (tb_int_t)(i + 1), (tb_int_t)tb_database_sql_value_int32(value));
break;
case TB_DATABASE_SQL_VALUE_TYPE_BLOB16:
case TB_DATABASE_SQL_VALUE_TYPE_BLOB8:
ok = sqlite3_bind_blob((sqlite3_stmt*)statement, (tb_int_t)(i + 1), value->u.blob.data, (tb_int_t)value->u.blob.size, tb_null);
break;
case TB_DATABASE_SQL_VALUE_TYPE_BLOB32:
{
if (value->u.blob.stream)
{
// done
do
{
// the stream size
tb_hong_t size = tb_stream_size(value->u.blob.stream);
tb_assert_and_check_break(size >= 0);
// make data
data = tb_malloc0_bytes((tb_size_t)size);
tb_assert_and_check_break(data);
// read data
if (!tb_stream_bread(value->u.blob.stream, data, (tb_size_t)size)) break;
// bind it
ok = sqlite3_bind_blob((sqlite3_stmt*)statement, (tb_int_t)(i + 1), data, (tb_int_t)size, tb_database_sqlite3_statement_bind_exit);
} while (0);
}
else ok = sqlite3_bind_blob((sqlite3_stmt*)statement, (tb_int_t)(i + 1), value->u.blob.data, (tb_int_t)value->u.blob.size, tb_null);
}
break;
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
case TB_DATABASE_SQL_VALUE_TYPE_FLOAT:
case TB_DATABASE_SQL_VALUE_TYPE_DOUBLE:
ok = sqlite3_bind_double((sqlite3_stmt*)statement, (tb_int_t)(i + 1), (tb_double_t)tb_database_sql_value_double(value));
break;
#endif
case TB_DATABASE_SQL_VALUE_TYPE_NULL:
ok = sqlite3_bind_null((sqlite3_stmt*)statement, (tb_int_t)(i + 1));
break;
default:
tb_trace_e("statement: bind: unknown value type: %lu", value->type);
break;
}
// failed?
if (SQLITE_OK != ok)
{
// exit data
if (data) tb_free(data);
data = tb_null;
// save state
sqlite->base.state = tb_database_sqlite3_state_from_errno(sqlite3_errcode(sqlite->database));
// trace
tb_trace_e("statement: bind value[%lu] failed, error[%d]: %s", i, sqlite3_errcode(sqlite->database), sqlite3_errmsg(sqlite->database));
break;
}
}
// ok?
return (i == size)? tb_true : tb_false;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_size_t tb_database_sqlite3_probe(tb_url_ref_t url)
{
// check
tb_assert_and_check_return_val(url, 0);
// done
tb_size_t score = 0;
tb_stream_ref_t stream = tb_null;
do
{
// the url arguments
tb_char_t const* args = tb_url_args(url);
if (args)
{
// find the database type
tb_char_t const* ptype = tb_stristr(args, "type=");
if (ptype && !tb_strnicmp(ptype + 5, "sqlite3", 7))
{
// ok
score = 100;
break;
}
}
// has host or port? no sqlite3
if (tb_url_host(url) || tb_url_port(url)) break;
// the database path
tb_char_t const* path = tb_url_cstr((tb_url_ref_t)url);
tb_assert_and_check_break(path);
// is file?
if (tb_url_protocol(url) == TB_URL_PROTOCOL_FILE) score += 20;
// init stream
stream = tb_stream_init_from_url(path);
tb_assert_and_check_break(stream);
// open stream
if (!tb_stream_open(stream)) break;
// read head
tb_char_t head[16] = {0};
if (!tb_stream_bread(stream, (tb_byte_t*)head, 15)) break;
// is sqlite3?
if (!tb_stricmp(head, "SQLite format 3")) score = 100;
} while (0);
// exit stream
if (stream) tb_stream_exit(stream);
stream = tb_null;
// trace
tb_trace_d("probe: %s, score: %lu", tb_url_cstr((tb_url_ref_t)url), score);
// ok?
return score;
}
tb_database_sql_ref_t tb_database_sqlite3_init(tb_url_ref_t url)
{
// check
tb_assert_and_check_return_val(url, tb_null);
// done
tb_bool_t ok = tb_false;
tb_database_sqlite3_t* sqlite = tb_null;
do
{
// make database
sqlite = tb_malloc0_type(tb_database_sqlite3_t);
tb_assert_and_check_break(sqlite);
// init database
sqlite->base.type = TB_DATABASE_SQL_TYPE_SQLITE3;
sqlite->base.open = tb_database_sqlite3_open;
sqlite->base.clos = tb_database_sqlite3_clos;
sqlite->base.exit = tb_database_sqlite3_exit;
sqlite->base.done = tb_database_sqlite3_done;
sqlite->base.begin = tb_database_sqlite3_begin;
sqlite->base.commit = tb_database_sqlite3_commit;
sqlite->base.rollback = tb_database_sqlite3_rollback;
sqlite->base.result_load = tb_database_sqlite3_result_load;
sqlite->base.result_exit = tb_database_sqlite3_result_exit;
sqlite->base.statement_init = tb_database_sqlite3_statement_init;
sqlite->base.statement_exit = tb_database_sqlite3_statement_exit;
sqlite->base.statement_done = tb_database_sqlite3_statement_done;
sqlite->base.statement_bind = tb_database_sqlite3_statement_bind;
// init row operation
static tb_iterator_op_t row_op =
{
tb_database_sqlite3_result_row_iterator_size
, tb_database_sqlite3_result_row_iterator_head
, tb_null
, tb_database_sqlite3_result_row_iterator_tail
, tb_database_sqlite3_result_row_iterator_prev
, tb_database_sqlite3_result_row_iterator_next
, tb_database_sqlite3_result_row_iterator_item
, tb_null
, tb_null
, tb_null
, tb_null
};
// init col operation
static tb_iterator_op_t col_op =
{
tb_database_sqlite3_result_col_iterator_size
, tb_database_sqlite3_result_col_iterator_head
, tb_null
, tb_database_sqlite3_result_col_iterator_tail
, tb_database_sqlite3_result_col_iterator_prev
, tb_database_sqlite3_result_col_iterator_next
, tb_database_sqlite3_result_col_iterator_item
, tb_null
, tb_null
, tb_null
, tb_null
};
// init result row iterator
sqlite->result.itor.priv = (tb_pointer_t)sqlite;
sqlite->result.itor.step = 0;
sqlite->result.itor.mode = 0;
sqlite->result.itor.op = &row_op;
// init result col iterator
sqlite->result.row.itor.priv = (tb_pointer_t)sqlite;
sqlite->result.row.itor.step = 0;
sqlite->result.row.itor.mode = TB_ITERATOR_MODE_RACCESS | TB_ITERATOR_MODE_READONLY;
sqlite->result.row.itor.op = &col_op;
// init url
if (!tb_url_init(&sqlite->base.url)) break;
// copy url
tb_url_copy(&sqlite->base.url, url);
// init state
sqlite->base.state = TB_STATE_OK;
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit database
if (sqlite) tb_database_sqlite3_exit((tb_database_sql_impl_t*)sqlite);
sqlite = tb_null;
}
// ok?
return (tb_database_sql_ref_t)sqlite;
}
tbox-1.7.6/src/tbox/database/impl/sqlite3.h 0000664 0000000 0000000 00000003170 14671175054 0020521 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file sqlite3.h
*/
#ifndef TB_DATABASE_IMPL_SQLITE3_H
#define TB_DATABASE_IMPL_SQLITE3_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* probe sqlite3 from the url
*
* @param url the database url
*
* @return the score
*/
tb_size_t tb_database_sqlite3_probe(tb_url_ref_t url);
/* init sqlite3
*
* @param url the database url
*
* @return the database handle
*/
tb_database_sql_ref_t tb_database_sqlite3_init(tb_url_ref_t url);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/database/prefix.h 0000664 0000000 0000000 00000001764 14671175054 0017500 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
* @ingroup database
*
*/
#ifndef TB_DATABASE_PREFIX_H
#define TB_DATABASE_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#include "../libc/libc.h"
#include "../network/url.h"
#include "../container/iterator.h"
#endif
tbox-1.7.6/src/tbox/database/sql.c 0000664 0000000 0000000 00000025175 14671175054 0016777 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file sql.c
* @defgroup database
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "database"
#define TB_TRACE_MODULE_DEBUG (1)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "sql.h"
#include "impl/prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_database_sql_ref_t tb_database_sql_init(tb_char_t const* url)
{
// check
tb_assert_and_check_return_val(url, tb_null);
// done
tb_bool_t ok = tb_false;
tb_database_sql_ref_t database = tb_null;
tb_url_t database_url;
do
{
// trace
tb_trace_d("init: %s: ..", url);
// init url
if (!tb_url_init(&database_url)) break;
// make url
if (!tb_url_cstr_set(&database_url, url)) break;
// check protocol
tb_size_t protocol = tb_url_protocol(&database_url);
tb_assert_and_check_break(protocol == TB_URL_PROTOCOL_SQL || protocol == TB_URL_PROTOCOL_FILE);
// the probe func
static tb_size_t (*s_probe[])(tb_url_ref_t) =
{
tb_null
#ifdef TB_CONFIG_PACKAGE_HAVE_MYSQL
, tb_database_mysql_probe
#endif
#ifdef TB_CONFIG_PACKAGE_HAVE_SQLITE3
, tb_database_sqlite3_probe
#endif
};
// the init func
static tb_database_sql_ref_t (*s_init[])(tb_url_ref_t) =
{
tb_null
#ifdef TB_CONFIG_PACKAGE_HAVE_MYSQL
, tb_database_mysql_init
#endif
#ifdef TB_CONFIG_PACKAGE_HAVE_SQLITE3
, tb_database_sqlite3_init
#endif
};
// probe the database type
tb_size_t i = 1;
tb_size_t n = tb_arrayn(s_probe);
tb_size_t s = 0;
tb_size_t m = 0;
for (; i < n; i++)
{
if (s_probe[i])
{
// probe it
tb_size_t score = s_probe[i](&database_url);
if (score > s)
{
// save the max score
s = score;
m = i;
// ok?
if (score == 100) break;
}
}
}
tb_check_break(m < n && s_init[m]);
// init it
database = s_init[m](&database_url);
tb_assert_and_check_break(database);
// trace
tb_trace_d("init: %s: ok", url);
// ok
ok = tb_true;
} while (0);
// exit url
tb_url_exit(&database_url);
// failed?
if (!ok)
{
// trace
tb_trace_d("init: %s: no", url);
// exit database
if (database) tb_database_sql_exit(database);
database = tb_null;
}
// ok?
return database;
}
tb_void_t tb_database_sql_exit(tb_database_sql_ref_t database)
{
// check
tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database;
tb_assert_and_check_return(impl);
// trace
tb_trace_d("exit: ..");
// exit it
if (impl->exit) impl->exit(impl);
// trace
tb_trace_d("exit: ok");
}
tb_size_t tb_database_sql_type(tb_database_sql_ref_t database)
{
// check
tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database;
tb_assert_and_check_return_val(impl, TB_DATABASE_SQL_TYPE_NONE);
// the database type
return impl->type;
}
tb_bool_t tb_database_sql_open(tb_database_sql_ref_t database)
{
// check
tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database;
tb_assert_and_check_return_val(impl && impl->open, tb_false);
// opened?
tb_check_return_val(!impl->bopened, tb_true);
// init state
impl->state = TB_STATE_DATABASE_UNKNOWN_ERROR;
// open it
impl->bopened = impl->open(impl);
// save state
if (impl->bopened) impl->state = TB_STATE_OK;
// ok?
return impl->bopened;
}
tb_void_t tb_database_sql_clos(tb_database_sql_ref_t database)
{
// check
tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database;
tb_assert_and_check_return(impl);
// opened?
tb_check_return(impl->bopened);
// clos it
if (impl->clos) impl->clos(impl);
// closed
impl->bopened = tb_false;
// clear state
impl->state = TB_STATE_OK;
}
tb_size_t tb_database_sql_state(tb_database_sql_ref_t database)
{
// check
tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database;
tb_assert_and_check_return_val(impl, TB_STATE_UNKNOWN_ERROR);
// the state
return impl->state;
}
tb_bool_t tb_database_sql_begin(tb_database_sql_ref_t database)
{
// check
tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database;
tb_assert_and_check_return_val(impl && impl->commit, tb_false);
// init state
impl->state = TB_STATE_DATABASE_UNKNOWN_ERROR;
// opened?
tb_assert_and_check_return_val(impl->bopened, tb_false);
// begin it
tb_bool_t ok = impl->begin(impl);
// save state
if (ok) impl->state = TB_STATE_OK;
// ok?
return ok;
}
tb_bool_t tb_database_sql_commit(tb_database_sql_ref_t database)
{
// check
tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database;
tb_assert_and_check_return_val(impl && impl->commit, tb_false);
// init state
impl->state = TB_STATE_DATABASE_UNKNOWN_ERROR;
// opened?
tb_assert_and_check_return_val(impl->bopened, tb_false);
// commit it
tb_bool_t ok = impl->commit(impl);
// save state
if (ok) impl->state = TB_STATE_OK;
// ok?
return ok;
}
tb_bool_t tb_database_sql_rollback(tb_database_sql_ref_t database)
{
// check
tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database;
tb_assert_and_check_return_val(impl && impl->rollback, tb_false);
// init state
impl->state = TB_STATE_DATABASE_UNKNOWN_ERROR;
// opened?
tb_assert_and_check_return_val(impl->bopened, tb_false);
// rollback it
tb_bool_t ok = impl->rollback(impl);
// save state
if (ok) impl->state = TB_STATE_OK;
// ok?
return ok;
}
tb_bool_t tb_database_sql_done(tb_database_sql_ref_t database, tb_char_t const* sql)
{
// check
tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database;
tb_assert_and_check_return_val(impl && impl->done && sql, tb_false);
// init state
impl->state = TB_STATE_DATABASE_UNKNOWN_ERROR;
// opened?
tb_assert_and_check_return_val(impl->bopened, tb_false);
// done it
tb_bool_t ok = impl->done(impl, sql);
// trace
tb_trace_d("done: sql: %s: %s", sql, ok? "ok" : "no");
// save state
if (ok) impl->state = TB_STATE_OK;
// ok?
return ok;
}
tb_iterator_ref_t tb_database_sql_result_load(tb_database_sql_ref_t database, tb_bool_t ball)
{
// check
tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database;
tb_assert_and_check_return_val(impl && impl->result_load, tb_null);
// init state
impl->state = TB_STATE_DATABASE_UNKNOWN_ERROR;
// opened?
tb_assert_and_check_return_val(impl->bopened, tb_null);
// load it
tb_iterator_ref_t result = impl->result_load(impl, ball);
// save state
if (result) impl->state = TB_STATE_OK;
// ok?
return result;
}
tb_void_t tb_database_sql_result_exit(tb_database_sql_ref_t database, tb_iterator_ref_t result)
{
// check
tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database;
tb_assert_and_check_return(impl && impl->result_exit && result);
// opened?
tb_assert_and_check_return(impl->bopened);
// exit it
impl->result_exit(impl, result);
// clear state
impl->state = TB_STATE_OK;
}
tb_database_sql_statement_ref_t tb_database_sql_statement_init(tb_database_sql_ref_t database, tb_char_t const* sql)
{
// check
tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database;
tb_assert_and_check_return_val(impl && impl->statement_init && sql, tb_null);
// init state
impl->state = TB_STATE_DATABASE_UNKNOWN_ERROR;
// opened?
tb_assert_and_check_return_val(impl->bopened, tb_null);
// init statement
tb_database_sql_statement_ref_t statement = impl->statement_init(impl, sql);
// save state
if (statement) impl->state = TB_STATE_OK;
// ok?
return statement;
}
tb_void_t tb_database_sql_statement_exit(tb_database_sql_ref_t database, tb_database_sql_statement_ref_t statement)
{
// check
tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database;
tb_assert_and_check_return(impl && impl->statement_done && statement);
// opened?
tb_assert_and_check_return(impl->bopened);
// exit statement
impl->statement_exit(impl, statement);
// clear state
impl->state = TB_STATE_OK;
}
tb_bool_t tb_database_sql_statement_done(tb_database_sql_ref_t database, tb_database_sql_statement_ref_t statement)
{
// check
tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database;
tb_assert_and_check_return_val(impl && impl->statement_done && statement, tb_false);
// init state
impl->state = TB_STATE_DATABASE_UNKNOWN_ERROR;
// opened?
tb_assert_and_check_return_val(impl->bopened, tb_false);
// done statement
tb_bool_t ok = impl->statement_done(impl, statement);
// save state
if (ok) impl->state = TB_STATE_OK;
// ok?
return ok;
}
tb_bool_t tb_database_sql_statement_bind(tb_database_sql_ref_t database, tb_database_sql_statement_ref_t statement, tb_database_sql_value_t const* list, tb_size_t size)
{
// check
tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database;
tb_assert_and_check_return_val(impl && impl->statement_bind && statement && list && size, tb_false);
// init state
impl->state = TB_STATE_DATABASE_UNKNOWN_ERROR;
// opened?
tb_assert_and_check_return_val(impl->bopened, tb_false);
// bind statement argument
tb_bool_t ok = impl->statement_bind(impl, statement, list, size);
// save state
if (ok) impl->state = TB_STATE_OK;
// ok?
return ok;
}
tbox-1.7.6/src/tbox/database/sql.h 0000664 0000000 0000000 00000024355 14671175054 0017003 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file sql.h
* @ingroup database
*/
#ifndef TB_DATABASE_SQL_H
#define TB_DATABASE_SQL_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "value.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the sql database type enum
typedef enum __tb_database_sql_type_e
{
TB_DATABASE_SQL_TYPE_NONE = 0
, TB_DATABASE_SQL_TYPE_MYSQL = 1
, TB_DATABASE_SQL_TYPE_SQLITE3 = 2
}tb_database_sql_type_e;
/// the database sql ref type
typedef __tb_typeref__(database_sql);
/// the database sql statement ref type
typedef __tb_typeref__(database_sql_statement);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init sql database
*
* @param url the database url
* "sql://localhost/?type=mysql&username=xxxx&password=xxxx"
* "sql://localhost:3306/?type=mysql&username=xxxx&password=xxxx&database=xxxx"
* "sql:///home/file.sqlitedb?type=sqlite3"
* "/home/file.sqlite3"
* "file:///home/file.sqlitedb"
* "C://home/file.sqlite3"
*
* @return the database
*/
tb_database_sql_ref_t tb_database_sql_init(tb_char_t const* url);
/*! exit database
*
* @param database the database handle
*/
tb_void_t tb_database_sql_exit(tb_database_sql_ref_t database);
/*! the database type
*
* @param database the database handle
*
* @return the database type
*/
tb_size_t tb_database_sql_type(tb_database_sql_ref_t database);
/*! open database
*
* @code
tb_database_sql_ref_t database = tb_database_sql_init("sql://localhost/?type=mysql&username=xxxx&password=xxxx");
if (database)
{
// open it
if (tb_database_sql_open(database))
{
// done it
// ...
// close it
tb_database_sql_clos(database);
}
tb_database_sql_exit(database);
}
* @endcode
*
* @param database the database handle
*
* @return tb_true or tb_false
*/
tb_bool_t tb_database_sql_open(tb_database_sql_ref_t database);
/*! clos database
*
* @param database the database handle
*/
tb_void_t tb_database_sql_clos(tb_database_sql_ref_t database);
/*! begin transaction
*
* @param database the database handle
*
* @return tb_true or tb_false
*/
tb_bool_t tb_database_sql_begin(tb_database_sql_ref_t database);
/*! commit transaction
*
* @param database the database handle
*
* @return tb_true or tb_false
*/
tb_bool_t tb_database_sql_commit(tb_database_sql_ref_t database);
/*! rollback transaction
*
* @param database the database handle
*
* @return tb_true or tb_false
*/
tb_bool_t tb_database_sql_rollback(tb_database_sql_ref_t database);
/*! the database state
*
* @param database the database handle
*
* @return the database state
*/
tb_size_t tb_database_sql_state(tb_database_sql_ref_t database);
/*! done database
*
* @code
*
* // done sql
* if (!tb_database_sql_done(database, "select * from table"))
* {
* // trace
* tb_trace_e("done sql failed, error: %s", tb_state_cstr(tb_database_sql_state(database)));
* return ;
* }
*
* // load result
* // ..
*
* @endcode
*
* @param database the database handle
* @param sql the sql command
*
* @return tb_true or tb_false
*/
tb_bool_t tb_database_sql_done(tb_database_sql_ref_t database, tb_char_t const* sql);
/*! load the database result
*
* @code
*
// done sql
// ..
// load result
tb_iterator_ref_t result = tb_database_sql_result_load(database, tb_true);
if (result)
{
// walk result
tb_for_all_if (tb_iterator_ref_t, row, result, row)
{
// walk values
tb_for_all_if (tb_database_sql_value_t*, value, row, value)
{
tb_trace_i("name: %s, data: %s, at: %lux%lu", tb_database_sql_value_name(value), tb_database_sql_value_text(value), row_itor, item_itor);
}
}
// exit result
tb_database_sql_result_exit(result);
}
// load result
tb_iterator_ref_t result = tb_database_sql_result_load(database, tb_false);
if (result)
{
// walk result
tb_for_all_if (tb_iterator_ref_t, row, result, row)
{
// field count
tb_trace_i("count: %lu", tb_iterator_size(row));
// id
tb_database_sql_value_t const* id = tb_iterator_item(row, 0);
if (id)
{
tb_trace_i("id: %d", tb_database_sql_value_int32(id));
}
// name
tb_database_sql_value_t const* name = tb_iterator_item(row, 1);
if (name)
{
tb_trace_i("name: %s", tb_database_sql_value_text(name));
}
// blob
tb_database_sql_value_t const* blob = tb_iterator_item(row, 2);
if (blob)
{
// data?
tb_stream_ref_t stream = tb_null;
if (tb_database_sql_value_blob(blob))
{
// trace
tb_trace_i("[data: %p, size: %lu] ", tb_database_sql_value_blob(blob), tb_database_sql_value_size(blob));
}
// stream?
else if ((stream = tb_database_sql_value_blob_stream(blob)))
{
// trace
tb_trace_i("[stream: %p, size: %lld] ", stream, tb_stream_size(stream));
// read stream
// ...
}
// null?
else
{
// trace
tb_trace_i("[%s:null] ", tb_database_sql_value_name(blob));
}
}
}
// exit result
tb_database_sql_result_exit(result);
}
* @endcode
*
* @param database the database handle
* @param try_all try loading all result into memory
*
* @return the database result
*/
tb_iterator_ref_t tb_database_sql_result_load(tb_database_sql_ref_t database, tb_bool_t try_all);
/*! exit the database result
*
* @param database the database handle
* @param result the database result
*/
tb_void_t tb_database_sql_result_exit(tb_database_sql_ref_t database, tb_iterator_ref_t result);
/*! init the database statement
*
* @param database the database handle
* @param sql the sql command
*
* @return the statement handle
*/
tb_database_sql_statement_ref_t tb_database_sql_statement_init(tb_database_sql_ref_t database, tb_char_t const* sql);
/*! exit the database statement
*
* @param database the database handle
* @param statement the statement handle
*/
tb_void_t tb_database_sql_statement_exit(tb_database_sql_ref_t database, tb_database_sql_statement_ref_t statement);
/*! done the database statement
*
* @code
tb_database_sql_statement_ref_t statement = tb_database_sql_statement_init(database, "select * from table where id=?");
if (statement)
{
// bind arguments
tb_database_sql_value_t list[1] = {0};
tb_database_sql_value_set_int32(&list[0], 12345);
if (tb_database_sql_statement_bind(database, statement, list, tb_arrayn(list)))
{
// done statement
if (tb_database_sql_statement_done(database, statement))
{
// load result
// ...
}
}
// exit statement
tb_database_sql_statement_exit(database, statement);
}
* @endcode
*
* @param database the database handle
* @param statement the statement handle
*
* @return tb_true or tb_false
*/
tb_bool_t tb_database_sql_statement_done(tb_database_sql_ref_t database, tb_database_sql_statement_ref_t statement);
/*! bind the database statement argument
*
* @param database the database handle
* @param statement the statement handle
* @param list the argument value list
* @param size the argument value count
*
* @return tb_true or tb_false
*/
tb_bool_t tb_database_sql_statement_bind(tb_database_sql_ref_t database, tb_database_sql_statement_ref_t statement, tb_database_sql_value_t const* list, tb_size_t size);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/database/value.c 0000664 0000000 0000000 00000036450 14671175054 0017312 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file value.c
* @ingroup database
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "value"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "value.h"
#include "../stream/stream.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_database_sql_value_size(tb_database_sql_value_t const* value)
{
// check
tb_assert_and_check_return_val(value, 0);
// done
switch (value->type)
{
case TB_DATABASE_SQL_VALUE_TYPE_TEXT:
if (!value->u.text.hint && value->u.text.data)
{
((tb_database_sql_value_t*)value)->u.text.hint = tb_strlen(value->u.text.data);
}
return value->u.text.hint;
case TB_DATABASE_SQL_VALUE_TYPE_BLOB32:
case TB_DATABASE_SQL_VALUE_TYPE_BLOB16:
case TB_DATABASE_SQL_VALUE_TYPE_BLOB8:
return value->u.blob.size;
case TB_DATABASE_SQL_VALUE_TYPE_INT32:
case TB_DATABASE_SQL_VALUE_TYPE_UINT32:
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
case TB_DATABASE_SQL_VALUE_TYPE_FLOAT:
#endif
return 4;
case TB_DATABASE_SQL_VALUE_TYPE_INT64:
case TB_DATABASE_SQL_VALUE_TYPE_UINT64:
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
case TB_DATABASE_SQL_VALUE_TYPE_DOUBLE:
#endif
return 8;
case TB_DATABASE_SQL_VALUE_TYPE_INT16:
case TB_DATABASE_SQL_VALUE_TYPE_UINT16:
return 2;
case TB_DATABASE_SQL_VALUE_TYPE_INT8:
case TB_DATABASE_SQL_VALUE_TYPE_UINT8:
return 1;
default:
tb_trace_e("unknown type: %lu", value->type);
break;
}
return 0;
}
tb_int8_t tb_database_sql_value_int8(tb_database_sql_value_t const* value)
{
return (tb_int8_t)tb_database_sql_value_int32(value);
}
tb_int16_t tb_database_sql_value_int16(tb_database_sql_value_t const* value)
{
return (tb_int16_t)tb_database_sql_value_int32(value);
}
tb_int32_t tb_database_sql_value_int32(tb_database_sql_value_t const* value)
{
// check
tb_assert_and_check_return_val(value, 0);
// done
switch (value->type)
{
case TB_DATABASE_SQL_VALUE_TYPE_INT32:
return (tb_int32_t)value->u.i32;
case TB_DATABASE_SQL_VALUE_TYPE_INT64:
return (tb_int32_t)value->u.i64;
case TB_DATABASE_SQL_VALUE_TYPE_INT16:
return (tb_int32_t)value->u.i16;
case TB_DATABASE_SQL_VALUE_TYPE_INT8:
return (tb_int32_t)value->u.i8;
case TB_DATABASE_SQL_VALUE_TYPE_UINT32:
return (tb_int32_t)value->u.u32;
case TB_DATABASE_SQL_VALUE_TYPE_UINT64:
return (tb_int32_t)value->u.u64;
case TB_DATABASE_SQL_VALUE_TYPE_UINT16:
return (tb_int32_t)value->u.u16;
case TB_DATABASE_SQL_VALUE_TYPE_UINT8:
return (tb_int32_t)value->u.u8;
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
case TB_DATABASE_SQL_VALUE_TYPE_FLOAT:
return (tb_int32_t)value->u.f;
case TB_DATABASE_SQL_VALUE_TYPE_DOUBLE:
return (tb_int32_t)value->u.d;
#endif
case TB_DATABASE_SQL_VALUE_TYPE_TEXT:
return value->u.text.data? (tb_int32_t)tb_stoi32(value->u.text.data) : 0;
default:
tb_trace_e("unknown number type: %lu", value->type);
break;
}
return 0;
}
tb_int64_t tb_database_sql_value_int64(tb_database_sql_value_t const* value)
{
// check
tb_assert_and_check_return_val(value, 0);
// done
switch (value->type)
{
case TB_DATABASE_SQL_VALUE_TYPE_INT64:
return (tb_int64_t)value->u.i64;
case TB_DATABASE_SQL_VALUE_TYPE_INT32:
return (tb_int64_t)value->u.i32;
case TB_DATABASE_SQL_VALUE_TYPE_INT16:
return (tb_int64_t)value->u.i16;
case TB_DATABASE_SQL_VALUE_TYPE_INT8:
return (tb_int64_t)value->u.i8;
case TB_DATABASE_SQL_VALUE_TYPE_UINT64:
return (tb_int64_t)value->u.u64;
case TB_DATABASE_SQL_VALUE_TYPE_UINT32:
return (tb_int64_t)value->u.u32;
case TB_DATABASE_SQL_VALUE_TYPE_UINT16:
return (tb_int64_t)value->u.u16;
case TB_DATABASE_SQL_VALUE_TYPE_UINT8:
return (tb_int64_t)value->u.u8;
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
case TB_DATABASE_SQL_VALUE_TYPE_FLOAT:
return (tb_int64_t)value->u.f;
case TB_DATABASE_SQL_VALUE_TYPE_DOUBLE:
return (tb_int64_t)value->u.d;
#endif
case TB_DATABASE_SQL_VALUE_TYPE_TEXT:
return value->u.text.data? (tb_int64_t)tb_stoi64(value->u.text.data) : 0;
default:
tb_trace_e("unknown number type: %lu", value->type);
break;
}
return 0;
}
tb_uint8_t tb_database_sql_value_uint8(tb_database_sql_value_t const* value)
{
return (tb_uint8_t)tb_database_sql_value_uint32(value);
}
tb_uint16_t tb_database_sql_value_uint16(tb_database_sql_value_t const* value)
{
return (tb_uint16_t)tb_database_sql_value_uint32(value);
}
tb_uint32_t tb_database_sql_value_uint32(tb_database_sql_value_t const* value)
{
// check
tb_assert_and_check_return_val(value, 0);
// done
switch (value->type)
{
case TB_DATABASE_SQL_VALUE_TYPE_UINT32:
return (tb_uint32_t)value->u.u32;
case TB_DATABASE_SQL_VALUE_TYPE_UINT64:
return (tb_uint32_t)value->u.u64;
case TB_DATABASE_SQL_VALUE_TYPE_UINT16:
return (tb_uint32_t)value->u.u16;
case TB_DATABASE_SQL_VALUE_TYPE_UINT8:
return (tb_uint32_t)value->u.u8;
case TB_DATABASE_SQL_VALUE_TYPE_INT32:
return (tb_uint32_t)value->u.i32;
case TB_DATABASE_SQL_VALUE_TYPE_INT64:
return (tb_uint32_t)value->u.i64;
case TB_DATABASE_SQL_VALUE_TYPE_INT16:
return (tb_uint32_t)value->u.i16;
case TB_DATABASE_SQL_VALUE_TYPE_INT8:
return (tb_uint32_t)value->u.i8;
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
case TB_DATABASE_SQL_VALUE_TYPE_FLOAT:
return (tb_uint32_t)value->u.f;
case TB_DATABASE_SQL_VALUE_TYPE_DOUBLE:
return (tb_uint32_t)value->u.d;
#endif
case TB_DATABASE_SQL_VALUE_TYPE_TEXT:
return value->u.text.data? (tb_uint32_t)tb_stoi32(value->u.text.data) : 0;
default:
tb_trace_e("unknown number type: %lu", value->type);
break;
}
return 0;
}
tb_uint64_t tb_database_sql_value_uint64(tb_database_sql_value_t const* value)
{
// check
tb_assert_and_check_return_val(value, 0);
// done
switch (value->type)
{
case TB_DATABASE_SQL_VALUE_TYPE_UINT64:
return (tb_uint64_t)value->u.u64;
case TB_DATABASE_SQL_VALUE_TYPE_UINT32:
return (tb_uint64_t)value->u.u32;
case TB_DATABASE_SQL_VALUE_TYPE_UINT16:
return (tb_uint64_t)value->u.u16;
case TB_DATABASE_SQL_VALUE_TYPE_UINT8:
return (tb_uint64_t)value->u.u8;
case TB_DATABASE_SQL_VALUE_TYPE_INT64:
return (tb_uint64_t)value->u.i64;
case TB_DATABASE_SQL_VALUE_TYPE_INT32:
return (tb_uint64_t)value->u.i32;
case TB_DATABASE_SQL_VALUE_TYPE_INT16:
return (tb_uint64_t)value->u.i16;
case TB_DATABASE_SQL_VALUE_TYPE_INT8:
return (tb_uint64_t)value->u.i8;
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
case TB_DATABASE_SQL_VALUE_TYPE_FLOAT:
return (tb_uint64_t)value->u.f;
case TB_DATABASE_SQL_VALUE_TYPE_DOUBLE:
return (tb_uint64_t)value->u.d;
#endif
case TB_DATABASE_SQL_VALUE_TYPE_TEXT:
return value->u.text.data? (tb_uint64_t)tb_stou64(value->u.text.data) : 0;
default:
tb_trace_e("unknown number type: %lu", value->type);
break;
}
return 0;
}
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
tb_float_t tb_database_sql_value_float(tb_database_sql_value_t const* value)
{
// check
tb_assert_and_check_return_val(value, 0);
// done
switch (value->type)
{
case TB_DATABASE_SQL_VALUE_TYPE_FLOAT:
return value->u.f;
case TB_DATABASE_SQL_VALUE_TYPE_DOUBLE:
return (tb_float_t)value->u.d;
case TB_DATABASE_SQL_VALUE_TYPE_INT64:
return (tb_float_t)value->u.i64;
case TB_DATABASE_SQL_VALUE_TYPE_INT32:
return (tb_float_t)value->u.i32;
case TB_DATABASE_SQL_VALUE_TYPE_INT16:
return (tb_float_t)value->u.i16;
case TB_DATABASE_SQL_VALUE_TYPE_INT8:
return (tb_float_t)value->u.i8;
case TB_DATABASE_SQL_VALUE_TYPE_UINT64:
return (tb_float_t)value->u.u64;
case TB_DATABASE_SQL_VALUE_TYPE_UINT32:
return (tb_float_t)value->u.u32;
case TB_DATABASE_SQL_VALUE_TYPE_UINT16:
return (tb_float_t)value->u.u16;
case TB_DATABASE_SQL_VALUE_TYPE_UINT8:
return (tb_float_t)value->u.u8;
case TB_DATABASE_SQL_VALUE_TYPE_TEXT:
return value->u.text.data? tb_stof(value->u.text.data) : 0;
default:
tb_trace_e("unknown number type: %lu", value->type);
break;
}
return 0;
}
tb_double_t tb_database_sql_value_double(tb_database_sql_value_t const* value)
{
// check
tb_assert_and_check_return_val(value, 0);
// done
switch (value->type)
{
case TB_DATABASE_SQL_VALUE_TYPE_FLOAT:
return (tb_double_t)value->u.f;
case TB_DATABASE_SQL_VALUE_TYPE_DOUBLE:
return value->u.d;
case TB_DATABASE_SQL_VALUE_TYPE_INT64:
return (tb_double_t)value->u.i64;
case TB_DATABASE_SQL_VALUE_TYPE_INT32:
return (tb_double_t)value->u.i32;
case TB_DATABASE_SQL_VALUE_TYPE_INT16:
return (tb_double_t)value->u.i16;
case TB_DATABASE_SQL_VALUE_TYPE_INT8:
return (tb_double_t)value->u.i8;
case TB_DATABASE_SQL_VALUE_TYPE_UINT64:
return (tb_double_t)value->u.u64;
case TB_DATABASE_SQL_VALUE_TYPE_UINT32:
return (tb_double_t)value->u.u32;
case TB_DATABASE_SQL_VALUE_TYPE_UINT16:
return (tb_double_t)value->u.u16;
case TB_DATABASE_SQL_VALUE_TYPE_UINT8:
return (tb_double_t)value->u.u8;
case TB_DATABASE_SQL_VALUE_TYPE_TEXT:
return value->u.text.data? tb_stod(value->u.text.data) : 0;
default:
tb_trace_e("unknown number type: %lu", value->type);
break;
}
return 0;
}
#endif
tb_void_t tb_database_sql_value_set_null(tb_database_sql_value_t* value)
{
// check
tb_assert_and_check_return(value);
// init null
value->type = TB_DATABASE_SQL_VALUE_TYPE_NULL;
}
tb_void_t tb_database_sql_value_set_int8(tb_database_sql_value_t* value, tb_int8_t number)
{
// check
tb_assert_and_check_return(value);
// init number
value->type = TB_DATABASE_SQL_VALUE_TYPE_INT8;
value->u.i8 = number;
}
tb_void_t tb_database_sql_value_set_int16(tb_database_sql_value_t* value, tb_int16_t number)
{
// check
tb_assert_and_check_return(value);
// init number
value->type = TB_DATABASE_SQL_VALUE_TYPE_INT16;
value->u.i16 = number;
}
tb_void_t tb_database_sql_value_set_int32(tb_database_sql_value_t* value, tb_int32_t number)
{
// check
tb_assert_and_check_return(value);
// init number
value->type = TB_DATABASE_SQL_VALUE_TYPE_INT32;
value->u.i32 = number;
}
tb_void_t tb_database_sql_value_set_int64(tb_database_sql_value_t* value, tb_int64_t number)
{
// check
tb_assert_and_check_return(value);
// init number
value->type = TB_DATABASE_SQL_VALUE_TYPE_INT64;
value->u.i64 = number;
}
tb_void_t tb_database_sql_value_set_uint8(tb_database_sql_value_t* value, tb_uint8_t number)
{
// check
tb_assert_and_check_return(value);
// init number
value->type = TB_DATABASE_SQL_VALUE_TYPE_INT8;
value->u.u8 = number;
}
tb_void_t tb_database_sql_value_set_uint16(tb_database_sql_value_t* value, tb_uint16_t number)
{
// check
tb_assert_and_check_return(value);
// init number
value->type = TB_DATABASE_SQL_VALUE_TYPE_INT16;
value->u.u16 = number;
}
tb_void_t tb_database_sql_value_set_uint32(tb_database_sql_value_t* value, tb_uint32_t number)
{
// check
tb_assert_and_check_return(value);
// init number
value->type = TB_DATABASE_SQL_VALUE_TYPE_INT32;
value->u.u32 = number;
}
tb_void_t tb_database_sql_value_set_uint64(tb_database_sql_value_t* value, tb_uint64_t number)
{
// check
tb_assert_and_check_return(value);
// init number
value->type = TB_DATABASE_SQL_VALUE_TYPE_INT64;
value->u.u64 = number;
}
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
tb_void_t tb_database_sql_value_set_float(tb_database_sql_value_t* value, tb_float_t number)
{
// check
tb_assert_and_check_return(value);
// init number
value->type = TB_DATABASE_SQL_VALUE_TYPE_FLOAT;
value->u.f = number;
}
tb_void_t tb_database_sql_value_set_double(tb_database_sql_value_t* value, tb_double_t number)
{
// check
tb_assert_and_check_return(value);
// init number
value->type = TB_DATABASE_SQL_VALUE_TYPE_DOUBLE;
value->u.d = number;
}
#endif
tb_void_t tb_database_sql_value_set_text(tb_database_sql_value_t* value, tb_char_t const* text, tb_size_t hint)
{
// check
tb_assert_and_check_return(value);
// init text
value->type = TB_DATABASE_SQL_VALUE_TYPE_TEXT;
value->u.text.data = text;
value->u.text.hint = hint;
}
tb_void_t tb_database_sql_value_set_blob8(tb_database_sql_value_t* value, tb_byte_t const* data, tb_size_t size)
{
// check
tb_assert_and_check_return(value);
// init blob
value->type = TB_DATABASE_SQL_VALUE_TYPE_BLOB8;
value->u.blob.data = data;
value->u.blob.size = size;
value->u.blob.stream = tb_null;
// check size
tb_assert(tb_database_sql_value_size(value) <= TB_MAXU8);
}
tb_void_t tb_database_sql_value_set_blob16(tb_database_sql_value_t* value, tb_byte_t const* data, tb_size_t size)
{
// check
tb_assert_and_check_return(value);
// init blob
value->type = TB_DATABASE_SQL_VALUE_TYPE_BLOB16;
value->u.blob.data = data;
value->u.blob.size = size;
value->u.blob.stream = tb_null;
// check size
tb_assert(tb_database_sql_value_size(value) <= TB_MAXU16);
}
tb_void_t tb_database_sql_value_set_blob32(tb_database_sql_value_t* value, tb_byte_t const* data, tb_size_t size, tb_stream_ref_t stream)
{
// check
tb_assert_and_check_return(value);
// check stream
tb_hong_t stream_size = 0;
if (stream)
{
// must be opened
tb_assert_and_check_return(tb_stream_is_opened(stream));
// the stream size
stream_size = tb_stream_size(stream);
tb_assert_and_check_return(stream_size >= 0 && stream_size < TB_MAXS32);
}
// init blob
value->type = TB_DATABASE_SQL_VALUE_TYPE_BLOB32;
value->u.blob.data = data;
value->u.blob.size = data? size : (tb_size_t)stream_size;
value->u.blob.stream = stream;
// check size
tb_assert(tb_database_sql_value_size(value) <= TB_MAXU32);
}
tbox-1.7.6/src/tbox/database/value.h 0000664 0000000 0000000 00000031345 14671175054 0017315 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file value.h
* @ingroup database
*
*/
#ifndef TB_DATABASE_SQL_VALUE_H
#define TB_DATABASE_SQL_VALUE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../stream/stream.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the sql database value type enum
typedef enum __tb_database_sql_value_type_e
{
TB_DATABASE_SQL_VALUE_TYPE_NULL = 0
, TB_DATABASE_SQL_VALUE_TYPE_INT8 = 1
, TB_DATABASE_SQL_VALUE_TYPE_INT16 = 2
, TB_DATABASE_SQL_VALUE_TYPE_INT32 = 3
, TB_DATABASE_SQL_VALUE_TYPE_INT64 = 4
, TB_DATABASE_SQL_VALUE_TYPE_UINT8 = 5
, TB_DATABASE_SQL_VALUE_TYPE_UINT16 = 6
, TB_DATABASE_SQL_VALUE_TYPE_UINT32 = 7
, TB_DATABASE_SQL_VALUE_TYPE_UINT64 = 8
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
, TB_DATABASE_SQL_VALUE_TYPE_FLOAT = 13
, TB_DATABASE_SQL_VALUE_TYPE_DOUBLE = 14
#endif
, TB_DATABASE_SQL_VALUE_TYPE_BLOB8 = 9
, TB_DATABASE_SQL_VALUE_TYPE_BLOB16 = 10
, TB_DATABASE_SQL_VALUE_TYPE_BLOB32 = 11
, TB_DATABASE_SQL_VALUE_TYPE_TEXT = 12
}tb_database_sql_value_type_e;
/// the sql database value type
typedef struct __tb_database_sql_value_t
{
/// the type
tb_size_t type;
/// the name
tb_char_t const* name;
/// the data
union
{
// int
tb_int8_t i8;
tb_int16_t i16;
tb_int32_t i32;
tb_int64_t i64;
// uint
tb_uint8_t u8;
tb_uint16_t u16;
tb_uint32_t u32;
tb_uint64_t u64;
// float
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
tb_float_t f;
tb_double_t d;
#endif
// blob
struct
{
tb_byte_t const* data;
tb_size_t size;
// the stream for blob32
tb_stream_ref_t stream;
} blob;
// text
struct
{
tb_char_t const* data;
tb_size_t hint;
} text;
}u;
}tb_database_sql_value_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the value data size
*
* @param value the value
*
* @return the value data size
*/
tb_size_t tb_database_sql_value_size(tb_database_sql_value_t const* value);
/*! the int8 value
*
* @param value the value
*
* @return the int8 value
*/
tb_int8_t tb_database_sql_value_int8(tb_database_sql_value_t const* value);
/*! the int16 value
*
* @param value the value
*
* @return the int16 value
*/
tb_int16_t tb_database_sql_value_int16(tb_database_sql_value_t const* value);
/*! the int32 value
*
* @param value the value
*
* @return the int32 value
*/
tb_int32_t tb_database_sql_value_int32(tb_database_sql_value_t const* value);
/*! the int64 value
*
* @param value the value
*
* @return the int64 value
*/
tb_int64_t tb_database_sql_value_int64(tb_database_sql_value_t const* value);
/*! the uint8 value
*
* @param value the value
*
* @return the uint8 value
*/
tb_uint8_t tb_database_sql_value_uint8(tb_database_sql_value_t const* value);
/*! the uint16 value
*
* @param value the value
*
* @return the uint16 value
*/
tb_uint16_t tb_database_sql_value_uint16(tb_database_sql_value_t const* value);
/*! the uint32 value
*
* @param value the value
*
* @return the uint32 value
*/
tb_uint32_t tb_database_sql_value_uint32(tb_database_sql_value_t const* value);
/*! the uint64 value
*
* @param value the value
*
* @return the uint64 value
*/
tb_uint64_t tb_database_sql_value_uint64(tb_database_sql_value_t const* value);
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
/*! the float value
*
* @param value the value
*
* @return the float value
*/
tb_float_t tb_database_sql_value_float(tb_database_sql_value_t const* value);
/*! the double value
*
* @param value the value
*
* @return the double value
*/
tb_double_t tb_database_sql_value_double(tb_database_sql_value_t const* value);
#endif
/*! set the null value
*
* @param value the value
*/
tb_void_t tb_database_sql_value_set_null(tb_database_sql_value_t* value);
/*! set the int8 value
*
* @param value the value
* @param number the number
*/
tb_void_t tb_database_sql_value_set_int8(tb_database_sql_value_t* value, tb_int8_t number);
/*! set the int16 value
*
* @param value the value
* @param number the number
*/
tb_void_t tb_database_sql_value_set_int16(tb_database_sql_value_t* value, tb_int16_t number);
/*! set the int32 value
*
* @param value the value
* @param number the number
*/
tb_void_t tb_database_sql_value_set_int32(tb_database_sql_value_t* value, tb_int32_t number);
/*! set the int64 value
*
* @param value the value
* @param number the number
*/
tb_void_t tb_database_sql_value_set_int64(tb_database_sql_value_t* value, tb_int64_t number);
/*! set the uint8 value
*
* @param value the value
* @param number the number
*/
tb_void_t tb_database_sql_value_set_uint8(tb_database_sql_value_t* value, tb_uint8_t number);
/*! set the uint16 value
*
* @param value the value
* @param number the number
*/
tb_void_t tb_database_sql_value_set_uint16(tb_database_sql_value_t* value, tb_uint16_t number);
/*! set the uint32 value
*
* @param value the value
* @param number the number
*/
tb_void_t tb_database_sql_value_set_uint32(tb_database_sql_value_t* value, tb_uint32_t number);
/*! set the uint64 value
*
* @param value the value
* @param number the number
*/
tb_void_t tb_database_sql_value_set_uint64(tb_database_sql_value_t* value, tb_uint64_t number);
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
/*! set the float value
*
* @param value the value
* @param number the number
*/
tb_void_t tb_database_sql_value_set_float(tb_database_sql_value_t* value, tb_float_t number);
/*! set the double value
*
* @param value the value
* @param number the number
*/
tb_void_t tb_database_sql_value_set_double(tb_database_sql_value_t* value, tb_double_t number);
#endif
/*! set the text value
*
* @param value the value
* @param text the text data
* @param hint the text size hint
*/
tb_void_t tb_database_sql_value_set_text(tb_database_sql_value_t* value, tb_char_t const* text, tb_size_t hint);
/*! set the blob8 value
*
* @param value the value
* @param data the blob data
* @param size the blob size
*/
tb_void_t tb_database_sql_value_set_blob8(tb_database_sql_value_t* value, tb_byte_t const* data, tb_size_t size);
/*! set the blob16 value
*
* @param value the value
* @param data the blob data
* @param size the blob size
*/
tb_void_t tb_database_sql_value_set_blob16(tb_database_sql_value_t* value, tb_byte_t const* data, tb_size_t size);
/*! set the blob32 value
*
* @param value the value
* @param data the blob data
* @param size the blob size
* @param stream the stream, using it if data == null
*/
tb_void_t tb_database_sql_value_set_blob32(tb_database_sql_value_t* value, tb_byte_t const* data, tb_size_t size, tb_stream_ref_t stream);
/* //////////////////////////////////////////////////////////////////////////////////////
* inlines
*/
/// the value is null?
static __tb_inline_force__ tb_bool_t tb_database_sql_value_is_null(tb_database_sql_value_t const* value)
{
return (value && value->type == TB_DATABASE_SQL_VALUE_TYPE_NULL)? tb_true : tb_false;
}
/// the value is text?
static __tb_inline_force__ tb_bool_t tb_database_sql_value_is_text(tb_database_sql_value_t const* value)
{
return (value && value->type == TB_DATABASE_SQL_VALUE_TYPE_TEXT)? tb_true : tb_false;
}
/// the value is blob?
static __tb_inline_force__ tb_bool_t tb_database_sql_value_is_blob(tb_database_sql_value_t const* value)
{
return ( value
&& ( value->type == TB_DATABASE_SQL_VALUE_TYPE_BLOB32
|| value->type == TB_DATABASE_SQL_VALUE_TYPE_BLOB16
|| value->type == TB_DATABASE_SQL_VALUE_TYPE_BLOB8))? tb_true : tb_false;
}
/// the value is blob32?
static __tb_inline_force__ tb_bool_t tb_database_sql_value_is_blob32(tb_database_sql_value_t const* value)
{
return (value && value->type == TB_DATABASE_SQL_VALUE_TYPE_BLOB32)? tb_true : tb_false;
}
/// the value is integer?
static __tb_inline_force__ tb_bool_t tb_database_sql_value_is_integer(tb_database_sql_value_t const* value)
{
return (value && value->type >= TB_DATABASE_SQL_VALUE_TYPE_INT8 && value->type <= TB_DATABASE_SQL_VALUE_TYPE_UINT64)? tb_true : tb_false;
}
/// the value is float?
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
static __tb_inline_force__ tb_bool_t tb_database_sql_value_is_float(tb_database_sql_value_t const* value)
{
return ( value
&& ( value->type == TB_DATABASE_SQL_VALUE_TYPE_FLOAT
|| value->type == TB_DATABASE_SQL_VALUE_TYPE_DOUBLE))? tb_true : tb_false;
}
#endif
/// the value is number?
static __tb_inline_force__ tb_bool_t tb_database_sql_value_is_number(tb_database_sql_value_t const* value)
{
return (value && value->type >= TB_DATABASE_SQL_VALUE_TYPE_INT8 && value->type < TB_DATABASE_SQL_VALUE_TYPE_BLOB8)? tb_true : tb_false;
}
/// the value type
static __tb_inline_force__ tb_size_t tb_database_sql_value_type(tb_database_sql_value_t const* value)
{
// check
tb_assert_and_check_return_val(value, TB_DATABASE_SQL_VALUE_TYPE_NULL);
// the type
return value->type;
}
/// the value name
static __tb_inline_force__ tb_char_t const* tb_database_sql_value_name(tb_database_sql_value_t const* value)
{
// check
tb_assert_and_check_return_val(value, tb_null);
// the name
return value->name;
}
/// the value text data
static __tb_inline_force__ tb_char_t const* tb_database_sql_value_text(tb_database_sql_value_t const* value)
{
// check
tb_assert_and_check_return_val(value, tb_null);
// is text?
if (tb_database_sql_value_is_text(value))
return value->u.text.data;
// is blob?
else if (tb_database_sql_value_is_blob(value))
return (tb_char_t const*)value->u.blob.data;
// is null?
else if (tb_database_sql_value_is_null(value))
return tb_null;
// trace
tb_trace_e("not text value type: %lu", value->type);
return tb_null;
}
/// the value blob data
static __tb_inline_force__ tb_byte_t const* tb_database_sql_value_blob(tb_database_sql_value_t const* value)
{
// check
tb_assert_and_check_return_val(value, tb_null);
// is blob?
if (tb_database_sql_value_is_blob(value))
return value->u.blob.data;
// is text?
else if (tb_database_sql_value_is_text(value))
return (tb_byte_t const*)value->u.text.data;
// is null?
else if (tb_database_sql_value_is_null(value))
return tb_null;
// trace
tb_trace_e("not blob value type: %lu", value->type);
return tb_null;
}
/// the value blob stream
static __tb_inline_force__ tb_stream_ref_t tb_database_sql_value_blob_stream(tb_database_sql_value_t const* value)
{
// the blob stream
return tb_database_sql_value_is_blob(value)? value->u.blob.stream : tb_null;
}
/// set the value name
static __tb_inline_force__ tb_void_t tb_database_sql_value_name_set(tb_database_sql_value_t* value, tb_char_t const* name)
{
// check
tb_assert_and_check_return(value);
// set the name
value->name = name;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/hash/ 0000775 0000000 0000000 00000000000 14671175054 0015201 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/hash/adler32.c 0000664 0000000 0000000 00000010224 14671175054 0016600 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* Jean-loup Gailly
* Mark Adler
*/
/*! This is a modified version based on adler32.c from the zlib library by ruki
*
* @file adler32.c
* @ingroup hash
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "adler32.h"
#ifdef TB_CONFIG_PACKAGE_HAVE_ZLIB
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// largest prime smaller than 65536
#define BASE (65521)
// NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
#define NMAX (5552)
// dot
#define DO1(data, i) {adler += (data)[i]; sum2 += adler;}
#define DO2(data, i) DO1(data, i); DO1(data, i + 1);
#define DO4(data, i) DO2(data, i); DO2(data, i + 2);
#define DO8(data, i) DO4(data, i); DO4(data, i + 4);
#define DO16(data) DO8(data, 0); DO8(data, 8);
// mod
#define MOD(a) (a) %= BASE
#define MOD28(a) (a) %= BASE
#define MOD63(a) (a) %= BASE
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_uint32_t tb_adler32_make(tb_byte_t const* data, tb_size_t size, tb_uint32_t seed)
{
#ifdef TB_CONFIG_PACKAGE_HAVE_ZLIB
return adler32(seed, data, (tb_uint_t)size);
#else
// split adler-32 into component sums
tb_uint32_t adler = seed;
tb_size_t sum2 = (adler >> 16) & 0xffff; adler &= 0xffff;
// in case user likes doing a byte at a time, keep it fast
if (size == 1)
{
adler += data[0];
if (adler >= BASE) adler -= BASE;
sum2 += adler;
if (sum2 >= BASE) sum2 -= BASE;
// ok?
return (tb_uint32_t)(adler | (sum2 << 16));
}
// initial adler-32 value (deferred check for size == 1 speed)
tb_check_return_val(data, 1);
// in case short lengths are provided, keep it somewhat fast
if (size < 16)
{
// done
while (size--)
{
adler += *data++;
sum2 += adler;
}
if (adler >= BASE) adler -= BASE;
// only added so many BASE's
MOD28(sum2);
// ok?
return (tb_uint32_t)(adler | (sum2 << 16));
}
// do length NMAX blocks -- requires just one modulo operation
tb_size_t n;
while (size >= NMAX)
{
size -= NMAX;
// NMAX is divisible by 16
n = NMAX / 16;
do
{
// 16 sums unrolled
DO16(data);
data += 16;
} while (--n);
MOD(adler);
MOD(sum2);
}
// do remaining bytes (less than NMAX, still just one modulo)
if (size)
{
// avoid modulos if none remaining
while (size >= 16)
{
size -= 16;
DO16(data);
data += 16;
}
while (size--)
{
adler += *data++;
sum2 += adler;
}
MOD(adler);
MOD(sum2);
}
// return recombined sums
return (tb_uint32_t)(adler | (sum2 << 16));
#endif
}
tb_uint32_t tb_adler32_make_from_cstr(tb_char_t const* cstr, tb_uint32_t seed)
{
// check
tb_assert_and_check_return_val(cstr, 0);
// make it
return tb_adler32_make((tb_byte_t const*)cstr, tb_strlen(cstr) + 1, seed);
}
tbox-1.7.6/src/tbox/hash/adler32.h 0000664 0000000 0000000 00000003413 14671175054 0016607 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file adler32.h
* @ingroup hash
*
*/
#ifndef TB_HASH_ADLER32_H
#define TB_HASH_ADLER32_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! make adler32 hash
*
* @param data the data
* @param size the size
* @param seed uses this seed if be non-zero
*
* @return the adler32 value
*/
tb_uint32_t tb_adler32_make(tb_byte_t const* data, tb_size_t size, tb_uint32_t seed);
/*! make adler32 hash from c-string
*
* @param cstr the c-string
* @param seed uses this seed if be non-zero
*
* @return the adler32 value
*/
tb_uint32_t tb_adler32_make_from_cstr(tb_char_t const* cstr, tb_uint32_t seed);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/hash/ap.c 0000664 0000000 0000000 00000003146 14671175054 0015751 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file ap.c
* @ingroup hash
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "ap.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_ap_make(tb_byte_t const* data, tb_size_t size, tb_size_t seed)
{
// check
tb_assert_and_check_return_val(data && size, 0);
// init value
tb_size_t v = 0xAAAAAAAA;
if (seed) v ^= seed;
// generate it
tb_size_t i = 0;
tb_byte_t const* p = data;
for (i = 0; i < size; i++, p++)
{
v ^= (!(i & 1)) ? ((v << 7) ^ ((*p) * (v >> 3))) : (~(((v << 11) + (*p)) ^ (v >> 5)));
}
return v;
}
tb_size_t tb_ap_make_from_cstr(tb_char_t const* cstr, tb_size_t seed)
{
// check
tb_assert_and_check_return_val(cstr, 0);
// make it
return tb_ap_make((tb_byte_t const*)cstr, tb_strlen(cstr) + 1, seed);
}
tbox-1.7.6/src/tbox/hash/ap.h 0000664 0000000 0000000 00000003331 14671175054 0015752 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file ap.h
* @ingroup hash
*
*/
#ifndef TB_HASH_AP_H
#define TB_HASH_AP_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! make ap hash
*
* @param data the data
* @param size the size
* @param seed uses this seed if be non-zero
*
* @return the ap value
*/
tb_size_t tb_ap_make(tb_byte_t const* data, tb_size_t size, tb_size_t seed);
/*! make ap hash from c-string
*
* @param cstr the c-string
* @param seed uses this seed if be non-zero
*
* @return the ap value
*/
tb_size_t tb_ap_make_from_cstr(tb_char_t const* cstr, tb_size_t seed);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/hash/arch/ 0000775 0000000 0000000 00000000000 14671175054 0016116 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/hash/arch/arm/ 0000775 0000000 0000000 00000000000 14671175054 0016675 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/hash/arch/arm/crc32.S 0000664 0000000 0000000 00000014253 14671175054 0017742 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-2020, TBOOX Open Source Group.
*
* @author ruki
* @file crc32.S
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
/* tb_uint32_t tb_crc32_make_asm(tb_uint32_t crc, tb_byte_t const* data, tb_size_t size, tb_uint32_t const* table);
*
* @param crc r0
* @param data r1
* @param size r2
* @param table r3
*
* @return crc, r0
*/
function tb_crc32_make_asm, export=1
// enter
mov ip, sp
stmfd sp!, {r4-r9, sl, fp, ip, lr, pc}
sub fp, ip, #4
// calc crc for the odd address
label odd // while (1) {
ands r4, r1, #3 // if (!(ib & 0x3)) goto even;
beq even
subs r2, r2, #1 // if (--in < 0) goto end;
blt end
// calc: crc = table[(*ib++ ^ crc) & 0xff] ^ (crc >> 8)
ldrb r4, [r1], #1 // r4 = *ib++
eor r4, r0, r4 // r4 ^= crc
and r4, r4, #255 // r4 &= 0xff
ldr r4, [r3, r4, lsl #2] // r4 = table[r4]
eor r0, r4, r0, lsr #8 // crc = r4 ^ (crc >> 8)
b odd // }
label evenloop
// ib[0-7] => r4-r9, sl, ip, ib += 8 * sizeof(uint32)
ldmia r1!, {r4 - r9, sl, ip}
// calc: for r4
eor lr, r0, r4 // calc: crc = table[((r4 >> 0) ^ crc) & 0xff] ^ (crc >> 8)
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
eor lr, r0, r4, lsr #8 // calc: crc = table[((r4 >> 8) ^ crc) & 0xff] ^ (crc >> 8)
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
eor lr, r0, r4, lsr #16 // calc: crc = table[((r4 >> 16) ^ crc) & 0xff] ^ (crc >> 8)
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
eor lr, r0, r4, lsr #24 // calc: crc = table[((r4 >> 24) ^ crc) & 0xff] ^ (crc >> 8)
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
// calc: for r5
eor lr, r0, r5
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
eor lr, r0, r5, lsr #8
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
eor lr, r0, r5, lsr #16
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
eor lr, r0, r5, lsr #24
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
// calc: for r6
eor lr, r0, r6
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
eor lr, r0, r6, lsr #8
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
eor lr, r0, r6, lsr #16
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
eor lr, r0, r6, lsr #24
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
// calc: for r7
eor lr, r0, r7
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
eor lr, r0, r7, lsr #8
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
eor lr, r0, r7, lsr #16
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
eor lr, r0, r7, lsr #24
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
// calc: for r8
eor lr, r0 ,r8
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
eor lr, r0 ,r8, lsr #8
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
eor lr, r0 ,r8, lsr #16
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
eor lr, r0 ,r8, lsr #24
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
// calc: for r9
eor lr, r0 ,r9
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
eor lr, r0 ,r9, lsr #8
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
eor lr, r0 ,r9, lsr #16
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
eor lr, r0 ,r9, lsr #24
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
// calc: for sl
eor lr, r0, sl
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
eor lr, r0, sl, lsr #8
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
eor lr, r0, sl, lsr #16
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
eor lr, r0, sl, lsr #24
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
// calc: for ip
eor lr, r0, ip
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
eor lr, r0, ip, lsr #8
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
eor lr, r0, ip, lsr #16
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
eor lr, r0, ip, lsr #24
and lr, lr, #255
ldr lr, [r3, lr, lsl #2]
eor r0, lr, r0, lsr #8
label even
// in -= 32; if (in >= 0) goto evenloop;
subs r2, r2, #32
bge evenloop
// left: in += 32; if (in < 0) goto end;
adds r2, r2, #32
ble end
// calc: the left data crc
label left // do {
ldrb r4, [r1], #1 // calc: crc = table[(*ib++ ^ crc) & 0xff] ^ (crc >> 8)
eor r4, r0, r4
and r4, r4, #255
ldr r4, [r3, r4, lsl #2]
eor r0, r4, r0, lsr #8
subs r2, r2, #1 // } while (--in)
bne left
label end
// leave
ldmea fp, {r4 - r9, sl, fp, sp, pc}
endfunc
tbox-1.7.6/src/tbox/hash/arch/crc32.S 0000664 0000000 0000000 00000002012 14671175054 0017151 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-2020, TBOOX Open Source Group.
*
* @author ruki
* @file crc32.S
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../../prefix/prefix.S"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_ARCH_ARM) && !defined(TB_ARCH_ARM64)
# include "arm/crc32.S"
#endif
tbox-1.7.6/src/tbox/hash/bkdr.c 0000664 0000000 0000000 00000002754 14671175054 0016277 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file bkdr.c
* @ingroup hash
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "bkdr.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_bkdr_make(tb_byte_t const* data, tb_size_t size, tb_size_t seed)
{
// check
tb_assert_and_check_return_val(data && size, 0);
// init value
tb_size_t value = 0;
if (seed) value = value * 131313 + seed;
// generate it
while (size--) value = (value * 131313) + (*data++);
return value;
}
tb_size_t tb_bkdr_make_from_cstr(tb_char_t const* cstr, tb_size_t seed)
{
// check
tb_assert_and_check_return_val(cstr, 0);
// make it
return tb_bkdr_make((tb_byte_t const*)cstr, tb_strlen(cstr) + 1, seed);
}
tbox-1.7.6/src/tbox/hash/bkdr.h 0000664 0000000 0000000 00000003353 14671175054 0016300 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file bkdr.h
* @ingroup hash
*
*/
#ifndef TB_HASH_BKDR_H
#define TB_HASH_BKDR_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! make bkdr hash
*
* @param data the data
* @param size the size
* @param seed uses this seed if be non-zero
*
* @return the bkdr value
*/
tb_size_t tb_bkdr_make(tb_byte_t const* data, tb_size_t size, tb_size_t seed);
/*! make bkdr hash from c-string
*
* @param cstr the c-string
* @param seed uses this seed if be non-zero
*
* @return the bkdr value
*/
tb_size_t tb_bkdr_make_from_cstr(tb_char_t const* cstr, tb_size_t seed);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/hash/blizzard.c 0000664 0000000 0000000 00000005342 14671175054 0017172 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file blizzard.c
* @ingroup hash
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "blizzard.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_blizzard_make(tb_byte_t const* data, tb_size_t size, tb_size_t seed)
{
// check
tb_assert_and_check_return_val(data && size, 0);
// init value
tb_size_t value = seed;
// generate it
while (size--) value = (*data++) + (value << 6) + (value << 16) - value;
return value;
// make table
static tb_size_t s_make = 0;
static tb_size_t s_table[1280];
if (!s_make)
{
tb_size_t i = 0;
tb_size_t index1 = 0;
tb_size_t index2 = 0;
tb_size_t seed0 = 0x00100001;
for (index1 = 0; index1 < 0x100; index1++)
{
for (index2 = index1, i = 0; i < 5; i++, index2 += 0x100)
{
seed0 = (seed0 * 125 + 3) % 0x2aaaab; tb_size_t temp1 = (seed0 & 0xffff) << 0x10;
seed0 = (seed0 * 125 + 3) % 0x2aaaab; tb_size_t temp2 = (seed0 & 0xffff);
s_table[index2] = (temp1 | temp2);
}
}
// ok
s_make = 1;
}
// init value
tb_size_t seed1 = 0x7fed7fed;
tb_size_t seed2 = 0Xeeeeeeee;
if (seed)
{
seed1 = s_table[(1 << 8) + seed] ^ (seed1 + seed2);
seed2 = seed + seed1 + seed2 + (seed2 << 5) + 3;
}
// done
tb_size_t byte = 0;
while (size--)
{
// get one byte
byte = *data++;
// 0 << 8: hash type: 0
// 1 << 8: hash type: 1
// 2 << 8: hash type: 2
seed1 = s_table[(1 << 8) + byte] ^ (seed1 + seed2);
seed2 = byte + seed1 + seed2 + (seed2 << 5) + 3;
}
// ok
return seed1;
}
tb_size_t tb_blizzard_make_from_cstr(tb_char_t const* cstr, tb_size_t seed)
{
// check
tb_assert_and_check_return_val(cstr, 0);
// make it
return tb_blizzard_make((tb_byte_t const*)cstr, tb_strlen(cstr) + 1, seed);
}
tbox-1.7.6/src/tbox/hash/blizzard.h 0000664 0000000 0000000 00000003476 14671175054 0017205 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file blizzard.h
* @ingroup hash
*
*/
#ifndef TB_HASH_BLIZZARD_H
#define TB_HASH_BLIZZARD_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! make blizzard hash
*
* Blizzard One-Way Hash algorithm from MPQ
*
* @param data the data
* @param size the size
* @param seed uses this seed if be non-zero
*
* @return the blizzard value
*/
tb_size_t tb_blizzard_make(tb_byte_t const* data, tb_size_t size, tb_size_t seed);
/*! make blizzard hash from c-string
*
* @param cstr the c-string
* @param seed uses this seed if be non-zero
*
* @return the blizzard value
*/
tb_size_t tb_blizzard_make_from_cstr(tb_char_t const* cstr, tb_size_t seed);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/hash/crc16.c 0000664 0000000 0000000 00000015053 14671175054 0016267 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file crc16.c
* @ingroup hash
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "crc16.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
// the crc16(ANSI) table
tb_uint16_t const g_crc16_table[] =
{
0x0000, 0x0580, 0x0f80, 0x0a00, 0x1b80, 0x1e00, 0x1400, 0x1180
, 0x3380, 0x3600, 0x3c00, 0x3980, 0x2800, 0x2d80, 0x2780, 0x2200
, 0x6380, 0x6600, 0x6c00, 0x6980, 0x7800, 0x7d80, 0x7780, 0x7200
, 0x5000, 0x5580, 0x5f80, 0x5a00, 0x4b80, 0x4e00, 0x4400, 0x4180
, 0xc380, 0xc600, 0xcc00, 0xc980, 0xd800, 0xdd80, 0xd780, 0xd200
, 0xf000, 0xf580, 0xff80, 0xfa00, 0xeb80, 0xee00, 0xe400, 0xe180
, 0xa000, 0xa580, 0xaf80, 0xaa00, 0xbb80, 0xbe00, 0xb400, 0xb180
, 0x9380, 0x9600, 0x9c00, 0x9980, 0x8800, 0x8d80, 0x8780, 0x8200
, 0x8381, 0x8601, 0x8c01, 0x8981, 0x9801, 0x9d81, 0x9781, 0x9201
, 0xb001, 0xb581, 0xbf81, 0xba01, 0xab81, 0xae01, 0xa401, 0xa181
, 0xe001, 0xe581, 0xef81, 0xea01, 0xfb81, 0xfe01, 0xf401, 0xf181
, 0xd381, 0xd601, 0xdc01, 0xd981, 0xc801, 0xcd81, 0xc781, 0xc201
, 0x4001, 0x4581, 0x4f81, 0x4a01, 0x5b81, 0x5e01, 0x5401, 0x5181
, 0x7381, 0x7601, 0x7c01, 0x7981, 0x6801, 0x6d81, 0x6781, 0x6201
, 0x2381, 0x2601, 0x2c01, 0x2981, 0x3801, 0x3d81, 0x3781, 0x3201
, 0x1001, 0x1581, 0x1f81, 0x1a01, 0x0b81, 0x0e01, 0x0401, 0x0181
, 0x0383, 0x0603, 0x0c03, 0x0983, 0x1803, 0x1d83, 0x1783, 0x1203
, 0x3003, 0x3583, 0x3f83, 0x3a03, 0x2b83, 0x2e03, 0x2403, 0x2183
, 0x6003, 0x6583, 0x6f83, 0x6a03, 0x7b83, 0x7e03, 0x7403, 0x7183
, 0x5383, 0x5603, 0x5c03, 0x5983, 0x4803, 0x4d83, 0x4783, 0x4203
, 0xc003, 0xc583, 0xcf83, 0xca03, 0xdb83, 0xde03, 0xd403, 0xd183
, 0xf383, 0xf603, 0xfc03, 0xf983, 0xe803, 0xed83, 0xe783, 0xe203
, 0xa383, 0xa603, 0xac03, 0xa983, 0xb803, 0xbd83, 0xb783, 0xb203
, 0x9003, 0x9583, 0x9f83, 0x9a03, 0x8b83, 0x8e03, 0x8403, 0x8183
, 0x8002, 0x8582, 0x8f82, 0x8a02, 0x9b82, 0x9e02, 0x9402, 0x9182
, 0xb382, 0xb602, 0xbc02, 0xb982, 0xa802, 0xad82, 0xa782, 0xa202
, 0xe382, 0xe602, 0xec02, 0xe982, 0xf802, 0xfd82, 0xf782, 0xf202
, 0xd002, 0xd582, 0xdf82, 0xda02, 0xcb82, 0xce02, 0xc402, 0xc182
, 0x4382, 0x4602, 0x4c02, 0x4982, 0x5802, 0x5d82, 0x5782, 0x5202
, 0x7002, 0x7582, 0x7f82, 0x7a02, 0x6b82, 0x6e02, 0x6402, 0x6182
, 0x2002, 0x2582, 0x2f82, 0x2a02, 0x3b82, 0x3e02, 0x3402, 0x3182
, 0x1382, 0x1602, 0x1c02, 0x1982, 0x0802, 0x0d82, 0x0782, 0x0202
};
// the crc16(CCITT) table
tb_uint16_t const g_crc16_ccitt_table[] =
{
0x0000, 0x2110, 0x4220, 0x6330, 0x8440, 0xa550, 0xc660, 0xe770
, 0x0881, 0x2991, 0x4aa1, 0x6bb1, 0x8cc1, 0xadd1, 0xcee1, 0xeff1
, 0x3112, 0x1002, 0x7332, 0x5222, 0xb552, 0x9442, 0xf772, 0xd662
, 0x3993, 0x1883, 0x7bb3, 0x5aa3, 0xbdd3, 0x9cc3, 0xfff3, 0xdee3
, 0x6224, 0x4334, 0x2004, 0x0114, 0xe664, 0xc774, 0xa444, 0x8554
, 0x6aa5, 0x4bb5, 0x2885, 0x0995, 0xeee5, 0xcff5, 0xacc5, 0x8dd5
, 0x5336, 0x7226, 0x1116, 0x3006, 0xd776, 0xf666, 0x9556, 0xb446
, 0x5bb7, 0x7aa7, 0x1997, 0x3887, 0xdff7, 0xfee7, 0x9dd7, 0xbcc7
, 0xc448, 0xe558, 0x8668, 0xa778, 0x4008, 0x6118, 0x0228, 0x2338
, 0xccc9, 0xedd9, 0x8ee9, 0xaff9, 0x4889, 0x6999, 0x0aa9, 0x2bb9
, 0xf55a, 0xd44a, 0xb77a, 0x966a, 0x711a, 0x500a, 0x333a, 0x122a
, 0xfddb, 0xdccb, 0xbffb, 0x9eeb, 0x799b, 0x588b, 0x3bbb, 0x1aab
, 0xa66c, 0x877c, 0xe44c, 0xc55c, 0x222c, 0x033c, 0x600c, 0x411c
, 0xaeed, 0x8ffd, 0xeccd, 0xcddd, 0x2aad, 0x0bbd, 0x688d, 0x499d
, 0x977e, 0xb66e, 0xd55e, 0xf44e, 0x133e, 0x322e, 0x511e, 0x700e
, 0x9fff, 0xbeef, 0xdddf, 0xfccf, 0x1bbf, 0x3aaf, 0x599f, 0x788f
, 0x8891, 0xa981, 0xcab1, 0xeba1, 0x0cd1, 0x2dc1, 0x4ef1, 0x6fe1
, 0x8010, 0xa100, 0xc230, 0xe320, 0x0450, 0x2540, 0x4670, 0x6760
, 0xb983, 0x9893, 0xfba3, 0xdab3, 0x3dc3, 0x1cd3, 0x7fe3, 0x5ef3
, 0xb102, 0x9012, 0xf322, 0xd232, 0x3542, 0x1452, 0x7762, 0x5672
, 0xeab5, 0xcba5, 0xa895, 0x8985, 0x6ef5, 0x4fe5, 0x2cd5, 0x0dc5
, 0xe234, 0xc324, 0xa014, 0x8104, 0x6674, 0x4764, 0x2454, 0x0544
, 0xdba7, 0xfab7, 0x9987, 0xb897, 0x5fe7, 0x7ef7, 0x1dc7, 0x3cd7
, 0xd326, 0xf236, 0x9106, 0xb016, 0x5766, 0x7676, 0x1546, 0x3456
, 0x4cd9, 0x6dc9, 0x0ef9, 0x2fe9, 0xc899, 0xe989, 0x8ab9, 0xaba9
, 0x4458, 0x6548, 0x0678, 0x2768, 0xc018, 0xe108, 0x8238, 0xa328
, 0x7dcb, 0x5cdb, 0x3feb, 0x1efb, 0xf98b, 0xd89b, 0xbbab, 0x9abb
, 0x754a, 0x545a, 0x376a, 0x167a, 0xf10a, 0xd01a, 0xb32a, 0x923a
, 0x2efd, 0x0fed, 0x6cdd, 0x4dcd, 0xaabd, 0x8bad, 0xe89d, 0xc98d
, 0x267c, 0x076c, 0x645c, 0x454c, 0xa23c, 0x832c, 0xe01c, 0xc10c
, 0x1fef, 0x3eff, 0x5dcf, 0x7cdf, 0x9baf, 0xbabf, 0xd98f, 0xf89f
, 0x176e, 0x367e, 0x554e, 0x745e, 0x932e, 0xb23e, 0xd10e, 0xf01e
};
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_uint16_t tb_crc16_make(tb_byte_t const* data, tb_size_t size, tb_uint16_t seed)
{
// check
tb_assert_and_check_return_val(data, 0);
// init value
tb_uint32_t crc = seed;
// done
tb_byte_t const* ie = data + size;
tb_uint16_t const* pt = (tb_uint16_t const*)g_crc16_table;
while (data < ie) crc = pt[((tb_uint8_t)crc) ^ *data++] ^ (crc >> 8);
// ok?
return (tb_uint16_t)crc;
}
tb_uint16_t tb_crc16_make_from_cstr(tb_char_t const* cstr, tb_uint16_t seed)
{
// check
tb_assert_and_check_return_val(cstr, 0);
// make it
return tb_crc16_make((tb_byte_t const*)cstr, tb_strlen(cstr) + 1, seed);
}
tb_uint16_t tb_crc16_ccitt_make(tb_byte_t const* data, tb_size_t size, tb_uint16_t seed)
{
// check
tb_assert_and_check_return_val(data, 0);
// init value
tb_uint16_t crc = seed;
// done
tb_byte_t const* ie = data + size;
tb_uint16_t const* pt = (tb_uint16_t const*)g_crc16_ccitt_table;
while (data < ie) crc = pt[((tb_uint8_t)crc) ^ *data++] ^ (crc >> 8);
// ok?
return crc;
}
tb_uint16_t tb_crc16_ccitt_make_from_cstr(tb_char_t const* cstr, tb_uint16_t seed)
{
// check
tb_assert_and_check_return_val(cstr, 0);
// make it
return tb_crc16_ccitt_make((tb_byte_t const*)cstr, tb_strlen(cstr) + 1, seed);
}
tbox-1.7.6/src/tbox/hash/crc16.h 0000664 0000000 0000000 00000005020 14671175054 0016265 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file crc16.h
* @ingroup hash
*
*/
#ifndef TB_HASH_CRC16_H
#define TB_HASH_CRC16_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// encode value
#define tb_crc16_make_value(mode, crc, value) tb_crc16_make(mode, crc, (tb_byte_t const*)&(value), sizeof(value))
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! make crc16 (ANSI)
*
* @param data the input data
* @param size the input size
* @param seed uses this seed if be non-zero
*
* @return the crc value
*/
tb_uint16_t tb_crc16_make(tb_byte_t const* data, tb_size_t size, tb_uint16_t seed);
/*! make crc16 (ANSI) for cstr
*
* @param cstr the input cstr
* @param seed uses this seed if be non-zero
*
* @return the crc value
*/
tb_uint16_t tb_crc16_make_from_cstr(tb_char_t const* cstr, tb_uint16_t seed);
/*! make crc16 (CCITT)
*
* @param data the input data
* @param size the input size
* @param seed uses this seed if be non-zero
*
* @return the crc value
*/
tb_uint16_t tb_crc16_ccitt_make(tb_byte_t const* data, tb_size_t size, tb_uint16_t seed);
/*! make crc16 (CCITT) for cstr
*
* @param cstr the input cstr
* @param seed uses this seed if be non-zero
*
* @return the crc value
*/
tb_uint16_t tb_crc16_ccitt_make_from_cstr(tb_char_t const* cstr, tb_uint16_t seed);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/hash/crc32.c 0000664 0000000 0000000 00000022067 14671175054 0016270 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file crc32.c
* @ingroup hash
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "crc32.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* declaration
*/
#if defined(TB_ARCH_ARM) && !defined(TB_ARCH_ARM64)
tb_uint32_t tb_crc32_make_asm(tb_uint32_t crc32, tb_byte_t const* data, tb_size_t size, tb_uint32_t const table[]);
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
// the crc32(IEEE) table
tb_uint32_t const g_crc32_table[] =
{
0x00000000, 0xb71dc104, 0x6e3b8209, 0xd926430d, 0xdc760413, 0x6b6bc517
, 0xb24d861a, 0x0550471e, 0xb8ed0826, 0x0ff0c922, 0xd6d68a2f, 0x61cb4b2b
, 0x649b0c35, 0xd386cd31, 0x0aa08e3c, 0xbdbd4f38, 0x70db114c, 0xc7c6d048
, 0x1ee09345, 0xa9fd5241, 0xacad155f, 0x1bb0d45b, 0xc2969756, 0x758b5652
, 0xc836196a, 0x7f2bd86e, 0xa60d9b63, 0x11105a67, 0x14401d79, 0xa35ddc7d
, 0x7a7b9f70, 0xcd665e74, 0xe0b62398, 0x57abe29c, 0x8e8da191, 0x39906095
, 0x3cc0278b, 0x8bdde68f, 0x52fba582, 0xe5e66486, 0x585b2bbe, 0xef46eaba
, 0x3660a9b7, 0x817d68b3, 0x842d2fad, 0x3330eea9, 0xea16ada4, 0x5d0b6ca0
, 0x906d32d4, 0x2770f3d0, 0xfe56b0dd, 0x494b71d9, 0x4c1b36c7, 0xfb06f7c3
, 0x2220b4ce, 0x953d75ca, 0x28803af2, 0x9f9dfbf6, 0x46bbb8fb, 0xf1a679ff
, 0xf4f63ee1, 0x43ebffe5, 0x9acdbce8, 0x2dd07dec, 0x77708634, 0xc06d4730
, 0x194b043d, 0xae56c539, 0xab068227, 0x1c1b4323, 0xc53d002e, 0x7220c12a
, 0xcf9d8e12, 0x78804f16, 0xa1a60c1b, 0x16bbcd1f, 0x13eb8a01, 0xa4f64b05
, 0x7dd00808, 0xcacdc90c, 0x07ab9778, 0xb0b6567c, 0x69901571, 0xde8dd475
, 0xdbdd936b, 0x6cc0526f, 0xb5e61162, 0x02fbd066, 0xbf469f5e, 0x085b5e5a
, 0xd17d1d57, 0x6660dc53, 0x63309b4d, 0xd42d5a49, 0x0d0b1944, 0xba16d840
, 0x97c6a5ac, 0x20db64a8, 0xf9fd27a5, 0x4ee0e6a1, 0x4bb0a1bf, 0xfcad60bb
, 0x258b23b6, 0x9296e2b2, 0x2f2bad8a, 0x98366c8e, 0x41102f83, 0xf60dee87
, 0xf35da999, 0x4440689d, 0x9d662b90, 0x2a7bea94, 0xe71db4e0, 0x500075e4
, 0x892636e9, 0x3e3bf7ed, 0x3b6bb0f3, 0x8c7671f7, 0x555032fa, 0xe24df3fe
, 0x5ff0bcc6, 0xe8ed7dc2, 0x31cb3ecf, 0x86d6ffcb, 0x8386b8d5, 0x349b79d1
, 0xedbd3adc, 0x5aa0fbd8, 0xeee00c69, 0x59fdcd6d, 0x80db8e60, 0x37c64f64
, 0x3296087a, 0x858bc97e, 0x5cad8a73, 0xebb04b77, 0x560d044f, 0xe110c54b
, 0x38368646, 0x8f2b4742, 0x8a7b005c, 0x3d66c158, 0xe4408255, 0x535d4351
, 0x9e3b1d25, 0x2926dc21, 0xf0009f2c, 0x471d5e28, 0x424d1936, 0xf550d832
, 0x2c769b3f, 0x9b6b5a3b, 0x26d61503, 0x91cbd407, 0x48ed970a, 0xfff0560e
, 0xfaa01110, 0x4dbdd014, 0x949b9319, 0x2386521d, 0x0e562ff1, 0xb94beef5
, 0x606dadf8, 0xd7706cfc, 0xd2202be2, 0x653deae6, 0xbc1ba9eb, 0x0b0668ef
, 0xb6bb27d7, 0x01a6e6d3, 0xd880a5de, 0x6f9d64da, 0x6acd23c4, 0xddd0e2c0
, 0x04f6a1cd, 0xb3eb60c9, 0x7e8d3ebd, 0xc990ffb9, 0x10b6bcb4, 0xa7ab7db0
, 0xa2fb3aae, 0x15e6fbaa, 0xccc0b8a7, 0x7bdd79a3, 0xc660369b, 0x717df79f
, 0xa85bb492, 0x1f467596, 0x1a163288, 0xad0bf38c, 0x742db081, 0xc3307185
, 0x99908a5d, 0x2e8d4b59, 0xf7ab0854, 0x40b6c950, 0x45e68e4e, 0xf2fb4f4a
, 0x2bdd0c47, 0x9cc0cd43, 0x217d827b, 0x9660437f, 0x4f460072, 0xf85bc176
, 0xfd0b8668, 0x4a16476c, 0x93300461, 0x242dc565, 0xe94b9b11, 0x5e565a15
, 0x87701918, 0x306dd81c, 0x353d9f02, 0x82205e06, 0x5b061d0b, 0xec1bdc0f
, 0x51a69337, 0xe6bb5233, 0x3f9d113e, 0x8880d03a, 0x8dd09724, 0x3acd5620
, 0xe3eb152d, 0x54f6d429, 0x7926a9c5, 0xce3b68c1, 0x171d2bcc, 0xa000eac8
, 0xa550add6, 0x124d6cd2, 0xcb6b2fdf, 0x7c76eedb, 0xc1cba1e3, 0x76d660e7
, 0xaff023ea, 0x18ede2ee, 0x1dbda5f0, 0xaaa064f4, 0x738627f9, 0xc49be6fd
, 0x09fdb889, 0xbee0798d, 0x67c63a80, 0xd0dbfb84, 0xd58bbc9a, 0x62967d9e
, 0xbbb03e93, 0x0cadff97, 0xb110b0af, 0x060d71ab, 0xdf2b32a6, 0x6836f3a2
, 0x6d66b4bc, 0xda7b75b8, 0x035d36b5, 0xb440f7b1
};
// the crc32(IEEE LE) table
tb_uint32_t const g_crc32_le_table[] =
{
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f
, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988
, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2
, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7
, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9
, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172
, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c
, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59
, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423
, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924
, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106
, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433
, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d
, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e
, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950
, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65
, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7
, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0
, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa
, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f
, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81
, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a
, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84
, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1
, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb
, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc
, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e
, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b
, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55
, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236
, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28
, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d
, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f
, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38
, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242
, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777
, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69
, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2
, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc
, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9
, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693
, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94
, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_uint32_t tb_crc32_make_impl(tb_uint32_t crc32, tb_byte_t const* data, tb_size_t size, tb_uint32_t const table[])
{
// done
#if defined(TB_ARCH_ARM) && !defined(TB_ARCH_ARM64)
crc32 = tb_crc32_make_asm(crc32, data, size, (tb_uint32_t const*)table);
#else
tb_byte_t const* ie = data + size;
tb_uint32_t const* pt = (tb_uint32_t const*)table;
while (data < ie) crc32 = pt[((tb_uint8_t)crc32) ^ *data++] ^ (crc32 >> 8);
#endif
// ok
return crc32;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_uint32_t tb_crc32_make(tb_byte_t const* data, tb_size_t size, tb_uint32_t seed)
{
// check
tb_assert_and_check_return_val(data, 0);
// calculate it
return tb_crc32_make_impl(seed, data, size, g_crc32_table);
}
tb_uint32_t tb_crc32_make_from_cstr(tb_char_t const* cstr, tb_uint32_t seed)
{
// check
tb_assert_and_check_return_val(cstr, 0);
// make it
return tb_crc32_make((tb_byte_t const*)cstr, tb_strlen(cstr) + 1, seed);
}
tb_uint32_t tb_crc32_le_make(tb_byte_t const* data, tb_size_t size, tb_uint32_t seed)
{
// check
tb_assert_and_check_return_val(data, 0);
// calculate it
return tb_crc32_make_impl(seed, data, size, g_crc32_le_table);
}
tb_uint32_t tb_crc32_le_make_from_cstr(tb_char_t const* cstr, tb_uint32_t seed)
{
// check
tb_assert_and_check_return_val(cstr, 0);
// make it
return tb_crc32_le_make((tb_byte_t const*)cstr, tb_strlen(cstr) + 1, seed);
}
tbox-1.7.6/src/tbox/hash/crc32.h 0000664 0000000 0000000 00000005016 14671175054 0016270 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file crc32.h
* @ingroup hash
*
*/
#ifndef TB_HASH_CRC32_H
#define TB_HASH_CRC32_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// encode value
#define tb_crc32_make_value(mode, crc, value) tb_crc32_make(mode, crc, (tb_byte_t const*)&(value), sizeof(value))
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! make crc32 (IEEE)
*
* @param data the input data
* @param size the input size
* @param seed uses this seed if be non-zero
*
* @return the crc value
*/
tb_uint32_t tb_crc32_make(tb_byte_t const* data, tb_size_t size, tb_uint32_t seed);
/*! make crc32 (IEEE) for cstr
*
* @param cstr the input cstr
* @param seed uses this seed if be non-zero
*
* @return the crc value
*/
tb_uint32_t tb_crc32_make_from_cstr(tb_char_t const* cstr, tb_uint32_t seed);
/*! make crc32 (IEEE LE)
*
* @param data the input data
* @param size the input size
* @param seed uses this seed if be non-zero
*
* @return the crc value
*/
tb_uint32_t tb_crc32_le_make(tb_byte_t const* data, tb_size_t size, tb_uint32_t seed);
/*! make crc32 (IEEE LE) for cstr
*
* @param cstr the input cstr
* @param seed uses this seed if be non-zero
*
* @return the crc value
*/
tb_uint32_t tb_crc32_le_make_from_cstr(tb_char_t const* cstr, tb_uint32_t seed);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/hash/crc8.c 0000664 0000000 0000000 00000006412 14671175054 0016207 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file crc8.c
* @ingroup hash
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "crc8.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
// the crc8(ANSI) table
tb_uint8_t const g_crc8_table[] =
{
0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31
, 0x24, 0x23, 0x2a, 0x2d, 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65
, 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, 0xe0, 0xe7, 0xee, 0xe9
, 0xfc, 0xfb, 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd
, 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, 0xa6, 0xa1
, 0xb4, 0xb3, 0xba, 0xbd, 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2
, 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, 0xb7, 0xb0, 0xb9, 0xbe
, 0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a
, 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 0x1f, 0x18, 0x11, 0x16
, 0x03, 0x04, 0x0d, 0x0a, 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42
, 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, 0x89, 0x8e, 0x87, 0x80
, 0x95, 0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4
, 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 0xc1, 0xc6, 0xcf, 0xc8
, 0xdd, 0xda, 0xd3, 0xd4, 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c
, 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, 0x19, 0x1e, 0x17, 0x10
, 0x05, 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34
, 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f
, 0x6a, 0x6d, 0x64, 0x63, 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b
, 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, 0xae, 0xa9, 0xa0, 0xa7
, 0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83
, 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef
, 0xfa, 0xfd, 0xf4, 0xf3
};
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_uint8_t tb_crc8_make(tb_byte_t const* data, tb_size_t size, tb_uint8_t seed)
{
// check
tb_assert_and_check_return_val(data, 0);
// init value
tb_uint32_t crc = seed;
// done
tb_byte_t const* ie = data + size;
tb_uint8_t const* pt = (tb_uint8_t const*)g_crc8_table;
while (data < ie) crc = pt[((tb_uint8_t)crc) ^ *data++] ^ (crc >> 8);
// ok?
return (tb_uint8_t)crc;
}
tb_uint8_t tb_crc8_make_from_cstr(tb_char_t const* cstr, tb_uint8_t seed)
{
// check
tb_assert_and_check_return_val(cstr, 0);
// make it
return tb_crc8_make((tb_byte_t const*)cstr, tb_strlen(cstr) + 1, seed);
}
tbox-1.7.6/src/tbox/hash/crc8.h 0000664 0000000 0000000 00000003745 14671175054 0016222 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file crc8.h
* @ingroup hash
*
*/
#ifndef TB_HASH_CRC8_H
#define TB_HASH_CRC8_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// encode value
#define tb_crc8_make_value(mode, crc, value) tb_crc8_make(mode, crc, (tb_byte_t const*)&(value), sizeof(value))
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! make crc8 (ATM)
*
* @param data the input data
* @param size the input size
* @param seed uses this seed if be non-zero
*
* @return the crc value
*/
tb_uint8_t tb_crc8_make(tb_byte_t const* data, tb_size_t size, tb_uint8_t seed);
/*! make crc8 (ATM) for cstr
*
* @param cstr the input cstr
* @param seed uses this seed if be non-zero
*
* @return the crc value
*/
tb_uint8_t tb_crc8_make_from_cstr(tb_char_t const* cstr, tb_uint8_t seed);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/hash/djb2.c 0000664 0000000 0000000 00000002747 14671175054 0016200 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file djb2.c
* @ingroup hash
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "djb2.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_djb2_make(tb_byte_t const* data, tb_size_t size, tb_size_t seed)
{
// check
tb_assert_and_check_return_val(data && size, 0);
// init value
tb_size_t value = 5381;
if (seed) value = value * 33 + seed;
// generate it
while (size--) value = (value * 33) + (*data++);
return value;
}
tb_size_t tb_djb2_make_from_cstr(tb_char_t const* cstr, tb_size_t seed)
{
// check
tb_assert_and_check_return_val(cstr, 0);
// make it
return tb_djb2_make((tb_byte_t const*)cstr, tb_strlen(cstr) + 1, seed);
}
tbox-1.7.6/src/tbox/hash/djb2.h 0000664 0000000 0000000 00000003433 14671175054 0016176 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file djb2.h
* @ingroup hash
*
*/
#ifndef TB_HASH_DJB2_H
#define TB_HASH_DJB2_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! make djb2 hash
*
* see http://www.cse.yorku.ca/~oz/hash.html
*
* @param data the data
* @param size the size
* @param seed uses this seed if be non-zero
*
* @return the djb2 value
*/
tb_size_t tb_djb2_make(tb_byte_t const* data, tb_size_t size, tb_size_t seed);
/*! make djb2 hash from c-string
*
* @param cstr the c-string
* @param seed uses this seed if be non-zero
*
* @return the djb2 value
*/
tb_size_t tb_djb2_make_from_cstr(tb_char_t const* cstr, tb_size_t seed);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/hash/fnv32.c 0000664 0000000 0000000 00000004742 14671175054 0016312 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author alexyer, ruki
* @file fnv32.c
* @ingroup hash
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "fnv32.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the pnv32 prime and offset basis
#define TB_FNV32_PRIME (16777619)
#define TB_FNV32_OFFSET_BASIS (2166136261)
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_uint32_t tb_fnv32_make(tb_byte_t const* data, tb_size_t size, tb_uint32_t seed)
{
// check
tb_assert_and_check_return_val(data && size, 0);
// init value
tb_uint32_t value = TB_FNV32_OFFSET_BASIS;
if (seed) value = (value * TB_FNV32_PRIME) ^ seed;
// generate it
while (size)
{
value *= TB_FNV32_PRIME;
value ^= (tb_uint32_t)*data++;
size--;
}
return value;
}
tb_uint32_t tb_fnv32_make_from_cstr(tb_char_t const* cstr, tb_uint32_t seed)
{
// check
tb_assert_and_check_return_val(cstr, 0);
// make it
return tb_fnv32_make((tb_byte_t const*)cstr, tb_strlen(cstr) + 1, seed);
}
tb_uint32_t tb_fnv32_1a_make(tb_byte_t const* data, tb_size_t size, tb_uint32_t seed)
{
// check
tb_assert_and_check_return_val(data && size, 0);
// init value
tb_uint32_t value = TB_FNV32_OFFSET_BASIS;
if (seed) value = (value * TB_FNV32_PRIME) ^ seed;
// generate it
while (size)
{
value ^= (tb_uint32_t)*data++;
value *= TB_FNV32_PRIME;
size--;
}
return value;
}
tb_uint32_t tb_fnv32_1a_make_from_cstr(tb_char_t const* cstr, tb_uint32_t seed)
{
// check
tb_assert_and_check_return_val(cstr, 0);
// make it
return tb_fnv32_1a_make((tb_byte_t const*)cstr, tb_strlen(cstr) + 1, seed);
}
tbox-1.7.6/src/tbox/hash/fnv32.h 0000664 0000000 0000000 00000004424 14671175054 0016314 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author alexyer, ruki
* @file fnv32.h
* @ingroup hash
*
*/
#ifndef TB_HASH_FNV32_H
#define TB_HASH_FNV32_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! make fnv32 hash
*
* @param data the data
* @param size the size
* @param seed uses this seed if be non-zero
*
* @return the fnv32 value
*/
tb_uint32_t tb_fnv32_make(tb_byte_t const* data, tb_size_t size, tb_uint32_t seed);
/*! make fnv32 hash from c-string
*
* @param cstr the c-string
* @param seed uses this seed if be non-zero
*
* @return the fnv32 value
*/
tb_uint32_t tb_fnv32_make_from_cstr(tb_char_t const* cstr, tb_uint32_t seed);
/*! make fnv32(1a) hash
*
* @param data the data
* @param size the size
* @param seed uses this seed if be non-zero
*
* @return the fnv32 value
*/
tb_uint32_t tb_fnv32_1a_make(tb_byte_t const* data, tb_size_t size, tb_uint32_t seed);
/*! make fnv32(1a) hash from c-string
*
* @param cstr the c-string
* @param seed uses this seed if be non-zero
*
* @return the fnv32 value
*/
tb_uint32_t tb_fnv32_1a_make_from_cstr(tb_char_t const* cstr, tb_uint32_t seed);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/hash/fnv64.c 0000664 0000000 0000000 00000004767 14671175054 0016326 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author alexyer, ruki
* @file fnv64.c
* @ingroup hash
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "fnv64.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the pnv64 prime and offset basis
#define TB_FNV64_PRIME (1099511628211ULL)
#define TB_FNV64_OFFSET_BASIS (14695981039346656037ULL)
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_uint64_t tb_fnv64_make(tb_byte_t const* data, tb_size_t size, tb_uint64_t seed)
{
// check
tb_assert_and_check_return_val(data && size, 0);
// init value
tb_uint64_t value = TB_FNV64_OFFSET_BASIS;
if (seed) value = (value * TB_FNV64_PRIME) ^ seed;
// generate it
while (size)
{
value *= TB_FNV64_PRIME;
value ^= (tb_uint64_t)*data++;
size--;
}
return value;
}
tb_uint64_t tb_fnv64_make_from_cstr(tb_char_t const* cstr, tb_uint64_t seed)
{
// check
tb_assert_and_check_return_val(cstr, 0);
// make it
return tb_fnv64_make((tb_byte_t const*)cstr, tb_strlen(cstr) + 1, seed);
}
tb_uint64_t tb_fnv64_1a_make(tb_byte_t const* data, tb_size_t size, tb_uint64_t seed)
{
// check
tb_assert_and_check_return_val(data && size, 0);
// init value
tb_uint64_t value = TB_FNV64_OFFSET_BASIS;
if (seed) value = (value * TB_FNV64_PRIME) ^ seed;
// generate it
while (size)
{
value ^= (tb_uint64_t)*data++;
value *= TB_FNV64_PRIME;
size--;
}
return value;
}
tb_uint64_t tb_fnv64_1a_make_from_cstr(tb_char_t const* cstr, tb_uint64_t seed)
{
// check
tb_assert_and_check_return_val(cstr, 0);
// make it
return tb_fnv64_1a_make((tb_byte_t const*)cstr, tb_strlen(cstr) + 1, seed);
}
tbox-1.7.6/src/tbox/hash/fnv64.h 0000664 0000000 0000000 00000004424 14671175054 0016321 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author alexyer, ruki
* @file fnv64.h
* @ingroup hash
*
*/
#ifndef TB_HASH_FNV64_H
#define TB_HASH_FNV64_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! make fnv64 hash
*
* @param data the data
* @param size the size
* @param seed uses this seed if be non-zero
*
* @return the fnv64 value
*/
tb_uint64_t tb_fnv64_make(tb_byte_t const* data, tb_size_t size, tb_uint64_t seed);
/*! make fnv64 hash from c-string
*
* @param cstr the c-string
* @param seed uses this seed if be non-zero
*
* @return the fnv64 value
*/
tb_uint64_t tb_fnv64_make_from_cstr(tb_char_t const* cstr, tb_uint64_t seed);
/*! make fnv64(1a) hash
*
* @param data the data
* @param size the size
* @param seed uses this seed if be non-zero
*
* @return the fnv64 value
*/
tb_uint64_t tb_fnv64_1a_make(tb_byte_t const* data, tb_size_t size, tb_uint64_t seed);
/*! make fnv64(1a) hash from c-string
*
* @param cstr the c-string
* @param seed uses this seed if be non-zero
*
* @return the fnv64 value
*/
tb_uint64_t tb_fnv64_1a_make_from_cstr(tb_char_t const* cstr, tb_uint64_t seed);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/hash/hash.h 0000664 0000000 0000000 00000002242 14671175054 0016275 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file hash.h
* @defgroup hash
*
*/
#ifndef TB_HASH_H
#define TB_HASH_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "ap.h"
#include "rs.h"
#include "sha.h"
#include "md5.h"
#include "uuid.h"
#include "djb2.h"
#include "sdbm.h"
#include "bkdr.h"
#include "crc8.h"
#include "crc16.h"
#include "crc32.h"
#include "fnv32.h"
#include "fnv64.h"
#include "murmur.h"
#include "adler32.h"
#include "blizzard.h"
#endif
tbox-1.7.6/src/tbox/hash/md5.c 0000664 0000000 0000000 00000030222 14671175054 0016031 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file md5.c
* @ingroup hash
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "md5.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// TB_MD5_F, TB_MD5_G and TB_MD5_H are basic MD5 functions: selection, majority, parity
#define TB_MD5_F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define TB_MD5_G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define TB_MD5_H(x, y, z) ((x) ^ (y) ^ (z))
#define TB_MD5_I(x, y, z) ((y) ^ ((x) | (~z)))
// TB_MD5_ROTATE_LEFT rotates x left n bits */
#define TB_MD5_ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
// TB_MD5_FF, TB_MD5_GG, TB_MD5_HH, and TB_MD5_II transformations for rounds 1, 2, 3, and 4
// Rotation is separate from addition to prevent recomputation
#define TB_MD5_FF(a, b, c, d, x, s, ac) {(a) += TB_MD5_F ((b), (c), (d)) + (x) + (tb_uint32_t)(ac); (a) = TB_MD5_ROTATE_LEFT ((a), (s)); (a) += (b); }
#define TB_MD5_GG(a, b, c, d, x, s, ac) {(a) += TB_MD5_G ((b), (c), (d)) + (x) + (tb_uint32_t)(ac); (a) = TB_MD5_ROTATE_LEFT ((a), (s)); (a) += (b); }
#define TB_MD5_HH(a, b, c, d, x, s, ac) {(a) += TB_MD5_H ((b), (c), (d)) + (x) + (tb_uint32_t)(ac); (a) = TB_MD5_ROTATE_LEFT ((a), (s)); (a) += (b); }
#define TB_MD5_II(a, b, c, d, x, s, ac) {(a) += TB_MD5_I ((b), (c), (d)) + (x) + (tb_uint32_t)(ac); (a) = TB_MD5_ROTATE_LEFT ((a), (s)); (a) += (b); }
// Constants for transformation
#define TB_MD5_S11 7 // Round 1
#define TB_MD5_S12 12
#define TB_MD5_S13 17
#define TB_MD5_S14 22
#define TB_MD5_S21 5 // Round 2
#define TB_MD5_S22 9
#define TB_MD5_S23 14
#define TB_MD5_S24 20
#define TB_MD5_S31 4 // Round 3
#define TB_MD5_S32 11
#define TB_MD5_S33 16
#define TB_MD5_S34 23
#define TB_MD5_S41 6 // Round 4
#define TB_MD5_S42 10
#define TB_MD5_S43 15
#define TB_MD5_S44 21
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
/* Padding */
static tb_byte_t g_md5_padding[64] =
{
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* //////////////////////////////////////////////////////////////////////////////////////
* implementaion
*/
// basic md5 step. the sp based on ip
static tb_void_t tb_md5_transform(tb_uint32_t* sp, tb_uint32_t* ip)
{
// check
tb_assert_and_check_return(sp && ip);
// init
tb_uint32_t a = sp[0], b = sp[1], c = sp[2], d = sp[3];
// round 1
TB_MD5_FF ( a, b, c, d, ip[ 0], TB_MD5_S11, (tb_uint32_t) 3614090360u); /* 1 */
TB_MD5_FF ( d, a, b, c, ip[ 1], TB_MD5_S12, (tb_uint32_t) 3905402710u); /* 2 */
TB_MD5_FF ( c, d, a, b, ip[ 2], TB_MD5_S13, (tb_uint32_t) 606105819u); /* 3 */
TB_MD5_FF ( b, c, d, a, ip[ 3], TB_MD5_S14, (tb_uint32_t) 3250441966u); /* 4 */
TB_MD5_FF ( a, b, c, d, ip[ 4], TB_MD5_S11, (tb_uint32_t) 4118548399u); /* 5 */
TB_MD5_FF ( d, a, b, c, ip[ 5], TB_MD5_S12, (tb_uint32_t) 1200080426u); /* 6 */
TB_MD5_FF ( c, d, a, b, ip[ 6], TB_MD5_S13, (tb_uint32_t) 2821735955u); /* 7 */
TB_MD5_FF ( b, c, d, a, ip[ 7], TB_MD5_S14, (tb_uint32_t) 4249261313u); /* 8 */
TB_MD5_FF ( a, b, c, d, ip[ 8], TB_MD5_S11, (tb_uint32_t) 1770035416u); /* 9 */
TB_MD5_FF ( d, a, b, c, ip[ 9], TB_MD5_S12, (tb_uint32_t) 2336552879u); /* 10 */
TB_MD5_FF ( c, d, a, b, ip[10], TB_MD5_S13, (tb_uint32_t) 4294925233u); /* 11 */
TB_MD5_FF ( b, c, d, a, ip[11], TB_MD5_S14, (tb_uint32_t) 2304563134u); /* 12 */
TB_MD5_FF ( a, b, c, d, ip[12], TB_MD5_S11, (tb_uint32_t) 1804603682u); /* 13 */
TB_MD5_FF ( d, a, b, c, ip[13], TB_MD5_S12, (tb_uint32_t) 4254626195u); /* 14 */
TB_MD5_FF ( c, d, a, b, ip[14], TB_MD5_S13, (tb_uint32_t) 2792965006u); /* 15 */
TB_MD5_FF ( b, c, d, a, ip[15], TB_MD5_S14, (tb_uint32_t) 1236535329u); /* 16 */
// round 2
TB_MD5_GG ( a, b, c, d, ip[ 1], TB_MD5_S21, (tb_uint32_t) 4129170786u); /* 17 */
TB_MD5_GG ( d, a, b, c, ip[ 6], TB_MD5_S22, (tb_uint32_t) 3225465664u); /* 18 */
TB_MD5_GG ( c, d, a, b, ip[11], TB_MD5_S23, (tb_uint32_t) 643717713u); /* 19 */
TB_MD5_GG ( b, c, d, a, ip[ 0], TB_MD5_S24, (tb_uint32_t) 3921069994u); /* 20 */
TB_MD5_GG ( a, b, c, d, ip[ 5], TB_MD5_S21, (tb_uint32_t) 3593408605u); /* 21 */
TB_MD5_GG ( d, a, b, c, ip[10], TB_MD5_S22, (tb_uint32_t) 38016083u); /* 22 */
TB_MD5_GG ( c, d, a, b, ip[15], TB_MD5_S23, (tb_uint32_t) 3634488961u); /* 23 */
TB_MD5_GG ( b, c, d, a, ip[ 4], TB_MD5_S24, (tb_uint32_t) 3889429448u); /* 24 */
TB_MD5_GG ( a, b, c, d, ip[ 9], TB_MD5_S21, (tb_uint32_t) 568446438u); /* 25 */
TB_MD5_GG ( d, a, b, c, ip[14], TB_MD5_S22, (tb_uint32_t) 3275163606u); /* 26 */
TB_MD5_GG ( c, d, a, b, ip[ 3], TB_MD5_S23, (tb_uint32_t) 4107603335u); /* 27 */
TB_MD5_GG ( b, c, d, a, ip[ 8], TB_MD5_S24, (tb_uint32_t) 1163531501u); /* 28 */
TB_MD5_GG ( a, b, c, d, ip[13], TB_MD5_S21, (tb_uint32_t) 2850285829u); /* 29 */
TB_MD5_GG ( d, a, b, c, ip[ 2], TB_MD5_S22, (tb_uint32_t) 4243563512u); /* 30 */
TB_MD5_GG ( c, d, a, b, ip[ 7], TB_MD5_S23, (tb_uint32_t) 1735328473u); /* 31 */
TB_MD5_GG ( b, c, d, a, ip[12], TB_MD5_S24, (tb_uint32_t) 2368359562u); /* 32 */
// round 3
TB_MD5_HH ( a, b, c, d, ip[ 5], TB_MD5_S31, (tb_uint32_t) 4294588738u); /* 33 */
TB_MD5_HH ( d, a, b, c, ip[ 8], TB_MD5_S32, (tb_uint32_t) 2272392833u); /* 34 */
TB_MD5_HH ( c, d, a, b, ip[11], TB_MD5_S33, (tb_uint32_t) 1839030562u); /* 35 */
TB_MD5_HH ( b, c, d, a, ip[14], TB_MD5_S34, (tb_uint32_t) 4259657740u); /* 36 */
TB_MD5_HH ( a, b, c, d, ip[ 1], TB_MD5_S31, (tb_uint32_t) 2763975236u); /* 37 */
TB_MD5_HH ( d, a, b, c, ip[ 4], TB_MD5_S32, (tb_uint32_t) 1272893353u); /* 38 */
TB_MD5_HH ( c, d, a, b, ip[ 7], TB_MD5_S33, (tb_uint32_t) 4139469664u); /* 39 */
TB_MD5_HH ( b, c, d, a, ip[10], TB_MD5_S34, (tb_uint32_t) 3200236656u); /* 40 */
TB_MD5_HH ( a, b, c, d, ip[13], TB_MD5_S31, (tb_uint32_t) 681279174u); /* 41 */
TB_MD5_HH ( d, a, b, c, ip[ 0], TB_MD5_S32, (tb_uint32_t) 3936430074u); /* 42 */
TB_MD5_HH ( c, d, a, b, ip[ 3], TB_MD5_S33, (tb_uint32_t) 3572445317u); /* 43 */
TB_MD5_HH ( b, c, d, a, ip[ 6], TB_MD5_S34, (tb_uint32_t) 76029189u); /* 44 */
TB_MD5_HH ( a, b, c, d, ip[ 9], TB_MD5_S31, (tb_uint32_t) 3654602809u); /* 45 */
TB_MD5_HH ( d, a, b, c, ip[12], TB_MD5_S32, (tb_uint32_t) 3873151461u); /* 46 */
TB_MD5_HH ( c, d, a, b, ip[15], TB_MD5_S33, (tb_uint32_t) 530742520u); /* 47 */
TB_MD5_HH ( b, c, d, a, ip[ 2], TB_MD5_S34, (tb_uint32_t) 3299628645u); /* 48 */
// round 4
TB_MD5_II ( a, b, c, d, ip[ 0], TB_MD5_S41, (tb_uint32_t) 4096336452u); /* 49 */
TB_MD5_II ( d, a, b, c, ip[ 7], TB_MD5_S42, (tb_uint32_t) 1126891415u); /* 50 */
TB_MD5_II ( c, d, a, b, ip[14], TB_MD5_S43, (tb_uint32_t) 2878612391u); /* 51 */
TB_MD5_II ( b, c, d, a, ip[ 5], TB_MD5_S44, (tb_uint32_t) 4237533241u); /* 52 */
TB_MD5_II ( a, b, c, d, ip[12], TB_MD5_S41, (tb_uint32_t) 1700485571u); /* 53 */
TB_MD5_II ( d, a, b, c, ip[ 3], TB_MD5_S42, (tb_uint32_t) 2399980690u); /* 54 */
TB_MD5_II ( c, d, a, b, ip[10], TB_MD5_S43, (tb_uint32_t) 4293915773u); /* 55 */
TB_MD5_II ( b, c, d, a, ip[ 1], TB_MD5_S44, (tb_uint32_t) 2240044497u); /* 56 */
TB_MD5_II ( a, b, c, d, ip[ 8], TB_MD5_S41, (tb_uint32_t) 1873313359u); /* 57 */
TB_MD5_II ( d, a, b, c, ip[15], TB_MD5_S42, (tb_uint32_t) 4264355552u); /* 58 */
TB_MD5_II ( c, d, a, b, ip[ 6], TB_MD5_S43, (tb_uint32_t) 2734768916u); /* 59 */
TB_MD5_II ( b, c, d, a, ip[13], TB_MD5_S44, (tb_uint32_t) 1309151649u); /* 60 */
TB_MD5_II ( a, b, c, d, ip[ 4], TB_MD5_S41, (tb_uint32_t) 4149444226u); /* 61 */
TB_MD5_II ( d, a, b, c, ip[11], TB_MD5_S42, (tb_uint32_t) 3174756917u); /* 62 */
TB_MD5_II ( c, d, a, b, ip[ 2], TB_MD5_S43, (tb_uint32_t) 718787259u); /* 63 */
TB_MD5_II ( b, c, d, a, ip[ 9], TB_MD5_S44, (tb_uint32_t) 3951481745u); /* 64 */
sp[0] += a;
sp[1] += b;
sp[2] += c;
sp[3] += d;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
// set pseudo_rand to zero for rfc md5 implementation
tb_void_t tb_md5_init(tb_md5_t* md5, tb_uint32_t pseudo_rand)
{
// check
tb_assert_and_check_return(md5);
// init
md5->i[0] = md5->i[1] = (tb_uint32_t)0;
// load magic initialization constants
md5->sp[0] = (tb_uint32_t)0x67452301 + (pseudo_rand * 11);
md5->sp[1] = (tb_uint32_t)0xefcdab89 + (pseudo_rand * 71);
md5->sp[2] = (tb_uint32_t)0x98badcfe + (pseudo_rand * 37);
md5->sp[3] = (tb_uint32_t)0x10325476 + (pseudo_rand * 97);
}
tb_void_t tb_md5_spak(tb_md5_t* md5, tb_byte_t const* data, tb_size_t size)
{
// check
tb_assert_and_check_return(md5 && data);
// init
tb_uint32_t ip[16];
tb_size_t i = 0, ii = 0;
// compute number of bytes mod 64
tb_int_t mdi = (tb_int_t)((md5->i[0] >> 3) & 0x3F);
// update number of bits
if ((md5->i[0] + ((tb_uint32_t)size << 3)) < md5->i[0]) md5->i[1]++;
md5->i[0] += ((tb_uint32_t)size << 3);
md5->i[1] += ((tb_uint32_t)size >> 29);
while (size--)
{
// add new character to buffer, increment mdi
md5->ip[mdi++] = *data++;
// transform if necessary
if (mdi == 0x40)
{
for (i = 0, ii = 0; i < 16; i++, ii += 4)
{
ip[i] = (((tb_uint32_t)md5->ip[ii + 3]) << 24)
| (((tb_uint32_t)md5->ip[ii + 2]) << 16)
| (((tb_uint32_t)md5->ip[ii + 1]) << 8)
| ((tb_uint32_t)md5->ip[ii]);
}
tb_md5_transform(md5->sp, ip);
mdi = 0;
}
}
}
tb_void_t tb_md5_exit(tb_md5_t* md5, tb_byte_t* data, tb_size_t size)
{
// check
tb_assert_and_check_return(md5 && data);
// init
tb_uint32_t ip[16];
tb_int_t mdi = 0;
tb_size_t i = 0;
tb_size_t ii = 0;
tb_size_t pad_n = 0;
// save number of bits
ip[14] = md5->i[0];
ip[15] = md5->i[1];
// compute number of bytes mod 64
mdi = (tb_int_t)((md5->i[0] >> 3) & 0x3F);
// pad out to 56 mod 64
pad_n = (mdi < 56) ? (56 - mdi) : (120 - mdi);
tb_md5_spak (md5, g_md5_padding, pad_n);
// append length ip bits and transform
for (i = 0, ii = 0; i < 14; i++, ii += 4)
{
ip[i] = (((tb_uint32_t)md5->ip[ii + 3]) << 24)
| (((tb_uint32_t)md5->ip[ii + 2]) << 16)
| (((tb_uint32_t)md5->ip[ii + 1]) << 8)
| ((tb_uint32_t)md5->ip[ii]);
}
tb_md5_transform (md5->sp, ip);
// store buffer ip data
for (i = 0, ii = 0; i < 4; i++, ii += 4)
{
md5->data[ii] = (tb_byte_t)( md5->sp[i] & 0xff);
md5->data[ii+1] = (tb_byte_t)((md5->sp[i] >> 8) & 0xff);
md5->data[ii+2] = (tb_byte_t)((md5->sp[i] >> 16) & 0xff);
md5->data[ii+3] = (tb_byte_t)((md5->sp[i] >> 24) & 0xff);
}
// output
tb_memcpy(data, md5->data, 16);
}
tb_size_t tb_md5_make(tb_byte_t const* ib, tb_size_t in, tb_byte_t* ob, tb_size_t on)
{
// check
tb_assert_and_check_return_val(ib && in && ob && on >= 16, 0);
// init
tb_md5_t md5;
tb_md5_init(&md5, 0);
// spank
tb_md5_spak(&md5, ib, in);
// exit
tb_md5_exit(&md5, ob, on);
// ok
return 16;
}
tbox-1.7.6/src/tbox/hash/md5.h 0000664 0000000 0000000 00000005062 14671175054 0016042 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file md5.h
* @ingroup hash
*
*/
#ifndef TB_HASH_MD5_H
#define TB_HASH_MD5_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// data structure for md5 (message data) computation
typedef struct __tb_md5_t
{
tb_uint32_t i[2]; //!< number of _bits_ handled mod 2^64
tb_uint32_t sp[4]; //!< scratch buffer
tb_byte_t ip[64]; //!< input buffer
tb_byte_t data[16]; //!< actual data after tb_md5_exit call
}tb_md5_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init md5
*
* @param md5 the md5
* @param pseudo_rand the pseudo rand
*/
tb_void_t tb_md5_init(tb_md5_t* md5, tb_uint32_t pseudo_rand);
/*! exit md5
*
* @param md5 the md5
* @param data the data
* @param size the size
*/
tb_void_t tb_md5_exit(tb_md5_t* md5, tb_byte_t* data, tb_size_t size);
/*! spak md5
*
* @param md5 the md5
* @param data the data
* @param size the size
*/
tb_void_t tb_md5_spak(tb_md5_t* md5, tb_byte_t const* data, tb_size_t size);
/*! make md5
*
* @param ib the input data
* @param in the input size
* @param ob the output data
* @param on the output size
*
* @return the real size
*/
tb_size_t tb_md5_make(tb_byte_t const* ib, tb_size_t in, tb_byte_t* ob, tb_size_t on);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/hash/murmur.c 0000664 0000000 0000000 00000003011 14671175054 0016667 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file murmur.c
* @ingroup hash
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "murmur.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_murmur_make(tb_byte_t const* data, tb_size_t size, tb_size_t seed)
{
// check
tb_assert_and_check_return_val(data && size, 0);
// init value
tb_size_t value = seed;
// generate it
while (size--)
{
value ^= (*data++);
value *= 0x5bd1e995;
value ^= value >> 15;
}
return value;
}
tb_size_t tb_murmur_make_from_cstr(tb_char_t const* cstr, tb_size_t seed)
{
// check
tb_assert_and_check_return_val(cstr, 0);
// make it
return tb_murmur_make((tb_byte_t const*)cstr, tb_strlen(cstr) + 1, seed);
}
tbox-1.7.6/src/tbox/hash/murmur.h 0000664 0000000 0000000 00000003461 14671175054 0016705 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file murmur.h
* @ingroup hash
*
*/
#ifndef TB_HASH_MURMUR_H
#define TB_HASH_MURMUR_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! make murmur hash
*
* one-byte-at-a-time hash based on Murmur's mix
*
* @param data the data
* @param size the size
* @param seed uses this seed if be non-zero
*
* @return the murmur value
*/
tb_size_t tb_murmur_make(tb_byte_t const* data, tb_size_t size, tb_size_t seed);
/*! make murmur hash from c-string
*
* @param cstr the c-string
* @param seed uses this seed if be non-zero
*
* @return the murmur value
*/
tb_size_t tb_murmur_make_from_cstr(tb_char_t const* cstr, tb_size_t seed);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/hash/prefix.h 0000664 0000000 0000000 00000001624 14671175054 0016652 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_HASH_PREFIX_H
#define TB_HASH_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#include "../libc/libc.h"
#endif
tbox-1.7.6/src/tbox/hash/rs.c 0000664 0000000 0000000 00000003013 14671175054 0015766 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file rs.c
* @ingroup hash
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "rs.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_rs_make(tb_byte_t const* data, tb_size_t size, tb_size_t seed)
{
// check
tb_assert_and_check_return_val(data && size, 0);
// init value
tb_size_t value = seed;
// generate it
tb_size_t b = 378551;
tb_size_t a = 63689;
while (size--)
{
value = value * a + (*data++);
a = a * b;
}
return value;
}
tb_size_t tb_rs_make_from_cstr(tb_char_t const* cstr, tb_size_t seed)
{
// check
tb_assert_and_check_return_val(cstr, 0);
// make it
return tb_rs_make((tb_byte_t const*)cstr, tb_strlen(cstr) + 1, seed);
}
tbox-1.7.6/src/tbox/hash/rs.h 0000664 0000000 0000000 00000003331 14671175054 0015776 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file rs.h
* @ingroup hash
*
*/
#ifndef TB_HASH_RS_H
#define TB_HASH_RS_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! make rs hash
*
* @param data the data
* @param size the size
* @param seed uses this seed if be non-zero
*
* @return the rs value
*/
tb_size_t tb_rs_make(tb_byte_t const* data, tb_size_t size, tb_size_t seed);
/*! make rs hash from c-string
*
* @param cstr the c-string
* @param seed uses this seed if be non-zero
*
* @return the rs value
*/
tb_size_t tb_rs_make_from_cstr(tb_char_t const* cstr, tb_size_t seed);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/hash/sdbm.c 0000664 0000000 0000000 00000002726 14671175054 0016301 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file sdbm.c
* @ingroup hash
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "sdbm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_sdbm_make(tb_byte_t const* data, tb_size_t size, tb_size_t seed)
{
// check
tb_assert_and_check_return_val(data && size, 0);
// init value
tb_size_t value = seed;
// generate it
while (size--) value = (*data++) + (value << 6) + (value << 16) - value;
return value;
}
tb_size_t tb_sdbm_make_from_cstr(tb_char_t const* cstr, tb_size_t seed)
{
// check
tb_assert_and_check_return_val(cstr, 0);
// make it
return tb_sdbm_make((tb_byte_t const*)cstr, tb_strlen(cstr) + 1, seed);
}
tbox-1.7.6/src/tbox/hash/sdbm.h 0000664 0000000 0000000 00000003353 14671175054 0016303 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file sdbm.h
* @ingroup hash
*
*/
#ifndef TB_HASH_SDBM_H
#define TB_HASH_SDBM_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! make sdbm hash
*
* @param data the data
* @param size the size
* @param seed uses this seed if be non-zero
*
* @return the sdbm value
*/
tb_size_t tb_sdbm_make(tb_byte_t const* data, tb_size_t size, tb_size_t seed);
/*! make sdbm hash from c-string
*
* @param cstr the c-string
* @param seed uses this seed if be non-zero
*
* @return the sdbm value
*/
tb_size_t tb_sdbm_make_from_cstr(tb_char_t const* cstr, tb_size_t seed);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/hash/sha.c 0000664 0000000 0000000 00000027435 14671175054 0016133 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file sha.c
* @ingroup hash
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "sha.h"
#include "../utils/bits.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// rol
#define TB_SHA_ROL(v, b) (((v) << (b)) | ((v) >> (32 - (b))))
// (TB_SHA_R0 + TB_SHA_R1), TB_SHA_R2, TB_SHA_R3, TB_SHA_R4 are the different operations used in SHA1
#define TB_SHA_BLK0(i) (block[i] = tb_bits_be_to_ne_u32(((tb_uint32_t const*)buffer)[i]))
#define TB_SHA_BLK(i) (block[i] = TB_SHA_ROL(block[i - 3] ^ block[i - 8] ^ block[i - 14] ^ block[i - 16], 1))
#define TB_SHA_R0(v, w, x, y, z, i) z += ((w & (x ^ y)) ^ y) + TB_SHA_BLK0(i) + 0x5a827999 + TB_SHA_ROL(v, 5); w = TB_SHA_ROL(w, 30);
#define TB_SHA_R1(v, w, x, y, z, i) z += ((w &(x ^ y)) ^ y) + TB_SHA_BLK(i) + 0x5a827999 + TB_SHA_ROL(v, 5); w = TB_SHA_ROL(w, 30);
#define TB_SHA_R2(v, w, x, y, z, i) z += (w ^ x ^ y) + TB_SHA_BLK(i) + 0x6ed9eba1 + TB_SHA_ROL(v, 5); w = TB_SHA_ROL(w, 30);
#define TB_SHA_R3(v, w, x, y, z, i) z += (((w | x) & y) | (w & x)) + TB_SHA_BLK(i) + 0x8f1bbcdc + TB_SHA_ROL(v, 5); w = TB_SHA_ROL(w, 30);
#define TB_SHA_R4(v, w, x, y, z, i) z += (w ^ x ^ y) + TB_SHA_BLK(i) + 0xca62c1d6 + TB_SHA_ROL(v, 5); w = TB_SHA_ROL(w, 30);
#define TB_SHA_CH(x,y,z) (((x) & ((y) ^ (z))) ^ (z))
#define TB_SHA_MAJ(x,y,z) ((((x) | (y)) & (z)) | ((x) & (y)))
#define TB_SHA_SIGMA0_256(x) (TB_SHA_ROL((x), 30) ^ TB_SHA_ROL((x), 19) ^ TB_SHA_ROL((x), 10))
#define TB_SHA_SIGMA1_256(x) (TB_SHA_ROL((x), 26) ^ TB_SHA_ROL((x), 21) ^ TB_SHA_ROL((x), 7))
#define TB_SHA_SIGMA0_256_(x) (TB_SHA_ROL((x), 25) ^ TB_SHA_ROL((x), 14) ^ ((x) >> 3))
#define TB_SHA_SIGMA1_256_(x) (TB_SHA_ROL((x), 15) ^ TB_SHA_ROL((x), 13) ^ ((x) >> 10))
#define TB_SHA_BLK_(i) (block[i] = block[i - 16] + TB_SHA_SIGMA0_256_(block[i - 15]) + TB_SHA_SIGMA1_256_(block[i - 2]) + block[i - 7])
// round256
#define TB_SHA_ROUND256(a,b,c,d,e,f,g,h) \
T1 += (h) + TB_SHA_SIGMA1_256(e) + TB_SHA_CH((e), (f), (g)) + g_sha_k256[i]; \
(d) += T1; \
(h) = T1 + TB_SHA_SIGMA0_256(a) + TB_SHA_MAJ((a), (b), (c)); \
i++
// round256(0, 15)
#define TB_SHA_ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \
T1 = TB_SHA_BLK0(i); \
TB_SHA_ROUND256(a,b,c,d,e,f,g,h)
// round256(16, 63)
#define TB_SHA_ROUND256_16_TO_63(a,b,c,d,e,f,g,h) \
T1 = TB_SHA_BLK_(i); \
TB_SHA_ROUND256(a,b,c,d,e,f,g,h)
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
static tb_uint32_t const g_sha_k256[64] =
{
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_void_t tb_sha_transform_sha1(tb_uint32_t state[5], tb_byte_t const buffer[64])
{
// init
tb_uint32_t block[80];
tb_uint32_t a = state[0];
tb_uint32_t b = state[1];
tb_uint32_t c = state[2];
tb_uint32_t d = state[3];
tb_uint32_t e = state[4];
#ifdef __tb_small__
// done
tb_size_t i = 0;
for (i = 0; i < 80; i++)
{
tb_int_t t;
if (i < 16) t = tb_bits_be_to_ne_u32(((tb_uint32_t*)buffer)[i]);
else t = TB_SHA_ROL(block[i - 3] ^ block[i - 8] ^ block[i - 14] ^ block[i - 16], 1);
block[i] = t;
t += e + TB_SHA_ROL(a, 5);
if (i < 40)
{
if (i < 20) t += ((b & (c ^ d)) ^ d) + 0x5a827999;
else t += ( b ^ c ^ d) + 0x6ED9EBA1;
}
else
{
if (i < 60) t += (((b | c) & d) | (b & c)) + 0x8f1bbcdc;
else t += ( b ^ c ^ d) + 0xca62c1d6;
}
e = d;
d = c;
c = TB_SHA_ROL(b, 30);
b = a;
a = t;
}
#else
// done
tb_size_t i = 0;
for (i = 0; i < 15; i += 5)
{
TB_SHA_R0(a, b, c, d, e, 0 + i);
TB_SHA_R0(e, a, b, c, d, 1 + i);
TB_SHA_R0(d, e, a, b, c, 2 + i);
TB_SHA_R0(c, d, e, a, b, 3 + i);
TB_SHA_R0(b, c, d, e, a, 4 + i);
}
TB_SHA_R0(a, b, c, d, e, 15);
TB_SHA_R1(e, a, b, c, d, 16);
TB_SHA_R1(d, e, a, b, c, 17);
TB_SHA_R1(c, d, e, a, b, 18);
TB_SHA_R1(b, c, d, e, a, 19);
for (i = 20; i < 40; i += 5)
{
TB_SHA_R2(a, b, c, d, e, 0 + i);
TB_SHA_R2(e, a, b, c, d, 1 + i);
TB_SHA_R2(d, e, a, b, c, 2 + i);
TB_SHA_R2(c, d, e, a, b, 3 + i);
TB_SHA_R2(b, c, d, e, a, 4 + i);
}
for (; i < 60; i += 5)
{
TB_SHA_R3(a, b, c, d, e, 0 + i);
TB_SHA_R3(e, a, b, c, d, 1 + i);
TB_SHA_R3(d, e, a, b, c, 2 + i);
TB_SHA_R3(c, d, e, a, b, 3 + i);
TB_SHA_R3(b, c, d, e, a, 4 + i);
}
for (; i < 80; i += 5)
{
TB_SHA_R4(a, b, c, d, e, 0 + i);
TB_SHA_R4(e, a, b, c, d, 1 + i);
TB_SHA_R4(d, e, a, b, c, 2 + i);
TB_SHA_R4(c, d, e, a, b, 3 + i);
TB_SHA_R4(b, c, d, e, a, 4 + i);
}
#endif
// update state
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
}
static tb_void_t tb_sha_transform_sha2(tb_uint32_t* state, tb_byte_t const buffer[64])
{
// init
tb_uint32_t T1;
tb_uint32_t block[64];
tb_uint32_t a = state[0];
tb_uint32_t b = state[1];
tb_uint32_t c = state[2];
tb_uint32_t d = state[3];
tb_uint32_t e = state[4];
tb_uint32_t f = state[5];
tb_uint32_t g = state[6];
tb_uint32_t h = state[7];
#ifdef __tb_small__
// done
tb_uint32_t T2;
tb_size_t i = 0;
for (i = 0; i < 64; i++)
{
if (i < 16) T1 = TB_SHA_BLK0(i);
else T1 = TB_SHA_BLK_(i);
T1 += h + TB_SHA_SIGMA1_256(e) + TB_SHA_CH(e, f, g) + g_sha_k256[i];
T2 = TB_SHA_SIGMA0_256(a) + TB_SHA_MAJ(a, b, c);
h = g;
g = f;
f = e;
e = d + T1;
d = c;
c = b;
b = a;
a = T1 + T2;
}
#else
// done
tb_size_t i = 0;
for (i = 0; i < 16; )
{
TB_SHA_ROUND256_0_TO_15(a, b, c, d, e, f, g, h);
TB_SHA_ROUND256_0_TO_15(h, a, b, c, d, e, f, g);
TB_SHA_ROUND256_0_TO_15(g, h, a, b, c, d, e, f);
TB_SHA_ROUND256_0_TO_15(f, g, h, a, b, c, d, e);
TB_SHA_ROUND256_0_TO_15(e, f, g, h, a, b, c, d);
TB_SHA_ROUND256_0_TO_15(d, e, f, g, h, a, b, c);
TB_SHA_ROUND256_0_TO_15(c, d, e, f, g, h, a, b);
TB_SHA_ROUND256_0_TO_15(b, c, d, e, f, g, h, a);
}
for ( ; i < 64; )
{
TB_SHA_ROUND256_16_TO_63(a, b, c, d, e, f, g, h);
TB_SHA_ROUND256_16_TO_63(h, a, b, c, d, e, f, g);
TB_SHA_ROUND256_16_TO_63(g, h, a, b, c, d, e, f);
TB_SHA_ROUND256_16_TO_63(f, g, h, a, b, c, d, e);
TB_SHA_ROUND256_16_TO_63(e, f, g, h, a, b, c, d);
TB_SHA_ROUND256_16_TO_63(d, e, f, g, h, a, b, c);
TB_SHA_ROUND256_16_TO_63(c, d, e, f, g, h, a, b);
TB_SHA_ROUND256_16_TO_63(b, c, d, e, f, g, h, a);
}
#endif
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
state[5] += f;
state[6] += g;
state[7] += h;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_void_t tb_sha_init(tb_sha_t* sha, tb_size_t mode)
{
// check
tb_assert_and_check_return(sha);
// init sha
tb_memset(sha, 0, sizeof(tb_sha_t));
// done
sha->digest_len = (mode >> 5) & 0xff;
switch (mode)
{
case TB_SHA_MODE_SHA1_160:
sha->state[0] = 0x67452301;
sha->state[1] = 0xefcdab89;
sha->state[2] = 0x98badcfe;
sha->state[3] = 0x10325476;
sha->state[4] = 0xc3d2e1f0;
sha->transform = tb_sha_transform_sha1;
break;
case TB_SHA_MODE_SHA2_224:
sha->state[0] = 0xc1059ed8;
sha->state[1] = 0x367cd507;
sha->state[2] = 0x3070dd17;
sha->state[3] = 0xf70e5939;
sha->state[4] = 0xffc00b31;
sha->state[5] = 0x68581511;
sha->state[6] = 0x64f98fa7;
sha->state[7] = 0xbefa4fa4;
sha->transform = tb_sha_transform_sha2;
break;
case TB_SHA_MODE_SHA2_256:
sha->state[0] = 0x6a09e667;
sha->state[1] = 0xbb67ae85;
sha->state[2] = 0x3c6ef372;
sha->state[3] = 0xa54ff53a;
sha->state[4] = 0x510e527f;
sha->state[5] = 0x9b05688c;
sha->state[6] = 0x1f83d9ab;
sha->state[7] = 0x5be0cd19;
sha->transform = tb_sha_transform_sha2;
break;
default:
tb_assert(0);
break;
}
sha->count = 0;
}
tb_void_t tb_sha_exit(tb_sha_t* sha, tb_byte_t* data, tb_size_t size)
{
// check
tb_assert_and_check_return(sha && data);
// the count
tb_hize_t count = tb_bits_be_to_ne_u64(sha->count << 3);
// spak
tb_sha_spak(sha, (tb_byte_t const*)"\200", 1);
while ((sha->count & 63) != 56) tb_sha_spak(sha, (tb_byte_t const*)"", 1);
tb_sha_spak(sha, (tb_byte_t*)&count, 8);
// done
tb_uint32_t i = 0;
tb_uint32_t n = sha->digest_len;
tb_assert((n << 2) <= size);
for (i = 0; i < n; i++) tb_bits_set_u32_be(data + (i << 2), sha->state[i]);
}
tb_void_t tb_sha_spak(tb_sha_t* sha, tb_byte_t const* data, tb_size_t size)
{
// check
tb_assert_and_check_return(sha && data);
// update count
tb_uint32_t j = (tb_uint32_t)sha->count & 63;
sha->count += size;
// done
tb_uint32_t i;
#ifdef __tb_small__
for (i = 0; i < size; i++)
{
sha->buffer[j++] = data[i];
if (64 == j)
{
sha->transform(sha->state, sha->buffer);
j = 0;
}
}
#else
if ((j + size) > 63)
{
tb_memcpy(&sha->buffer[j], data, (i = 64 - j));
sha->transform(sha->state, sha->buffer);
for (; i + 63 < size; i += 64)
sha->transform(sha->state, &data[i]);
j = 0;
}
else i = 0;
tb_memcpy(&sha->buffer[j], &data[i], size - i);
#endif
}
tb_size_t tb_sha_make(tb_size_t mode, tb_byte_t const* ib, tb_size_t in, tb_byte_t* ob, tb_size_t on)
{
// check
tb_assert_and_check_return_val(ib && in && ob && on >= 16, 0);
// init
tb_sha_t sha;
tb_sha_init(&sha, mode);
// spank
tb_sha_spak(&sha, ib, in);
// exit
tb_sha_exit(&sha, ob, on);
// ok?
return (sha.digest_len << 2);
}
tbox-1.7.6/src/tbox/hash/sha.h 0000664 0000000 0000000 00000005554 14671175054 0016136 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file sha.h
* @ingroup hash
*
*/
#ifndef TB_HASH_SHA_H
#define TB_HASH_SHA_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// data structure for sha (message data) computation
typedef struct __tb_sha_t
{
tb_uint8_t digest_len; //!< digest length in 32-bit words
tb_hize_t count; //!< number of bytes in buffer
tb_uint8_t buffer[64]; //!< 512-bit buffer of input values used in hash updating
tb_uint32_t state[8]; //!< current hash value
tb_void_t (*transform)(tb_uint32_t *state, tb_uint8_t const buffer[64]);
}tb_sha_t;
// the sha mode type
typedef enum __tb_sha_mode_t
{
TB_SHA_MODE_SHA1_160 = 160
, TB_SHA_MODE_SHA2_224 = 224
, TB_SHA_MODE_SHA2_256 = 256
}tb_sha_mode_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init sha
*
* @param sha the sha
* @param mode the mode
*/
tb_void_t tb_sha_init(tb_sha_t* sha, tb_size_t mode);
/*! exit sha
*
* @param sha the sha
* @param data the data
* @param size the size
*/
tb_void_t tb_sha_exit(tb_sha_t* sha, tb_byte_t* data, tb_size_t size);
/*! spak sha
*
* @param sha the sha
* @param data the data
* @param size the size
*/
tb_void_t tb_sha_spak(tb_sha_t* sha, tb_byte_t const* data, tb_size_t size);
/*! make sha
*
* @param mode the mode
* @param ib the input data
* @param ip the input size
* @param ob the output data
* @param on the output size
*
* @return the real size
*/
tb_size_t tb_sha_make(tb_size_t mode, tb_byte_t const* ib, tb_size_t ip, tb_byte_t* ob, tb_size_t on);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/hash/uuid.c 0000664 0000000 0000000 00000010056 14671175054 0016315 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file uuid.c
* @ingroup hash
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "uuid.h"
#include "md5.h"
#include "../libc/libc.h"
#include "../math/math.h"
#include "../utils/utils.h"
#include "../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
// http://xorshift.di.unimi.it/xorshift128plus.c
static tb_uint64_t tb_uuid4_xorshift128plus(tb_uint64_t* s)
{
tb_uint64_t s1 = s[0];
tb_uint64_t const s0 = s[1];
s[0] = s0;
s1 ^= s1 << 23;
s[1] = s1 ^ s0 ^ (s1 >> 18) ^ (s0 >> 5);
return s[1] + s0;
}
static tb_bool_t tb_uuid4_generate(tb_byte_t uuid[16], tb_uint64_t seed[2])
{
// init seed data
union { tb_byte_t b[16]; tb_uint64_t word[2]; } s;
s.word[0] = tb_uuid4_xorshift128plus(seed);
s.word[1] = tb_uuid4_xorshift128plus(seed);
/* generate uuid
*
* t: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
* xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx
*/
tb_int_t i = 0;
tb_int_t n = 0;
tb_int_t t = 0;
tb_int_t c1 = 0;
tb_int_t c2 = 0;
for (t = 0; t < 32; t++)
{
n = s.b[i >> 1];
n = (i & 1) ? (n >> 4) : (n & 0xf);
if (t == 16) // y
{
c2 = (n & 0x3) + 8;
i++;
}
else if (t == 12) c2 = 4; // 4
else // x
{
c2 = n;
i++;
}
if (t & 1) uuid[t >> 1] = (tb_byte_t)(c1 * 16 + c2);
c1 = c2;
}
return tb_true;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_uuid_make(tb_byte_t uuid[16], tb_char_t const* name)
{
return tb_uuid4_make(uuid, name);
}
tb_char_t const* tb_uuid_make_cstr(tb_char_t uuid_cstr[37], tb_char_t const* name)
{
return tb_uuid4_make_cstr(uuid_cstr, name);
}
tb_bool_t tb_uuid4_make(tb_byte_t uuid[16], tb_char_t const* name)
{
// check
tb_assert_and_check_return_val(uuid, tb_false);
// init seed
tb_uint64_t seed[2];
if (name)
{
tb_assert_static(sizeof(seed) == 16);
tb_md5_make((tb_byte_t const*)name, tb_strlen(name), (tb_byte_t*)seed, 16);
}
else
{
// disable pseudo random
tb_random_reset(tb_false);
seed[0] = (tb_uint64_t)tb_random();
seed[1] = (tb_uint64_t)tb_random();
}
// generate uuid v4
return tb_uuid4_generate(uuid, seed);
}
tb_char_t const* tb_uuid4_make_cstr(tb_char_t uuid_cstr[37], tb_char_t const* name)
{
// check
tb_assert_and_check_return_val(uuid_cstr, tb_null);
// make uuid bytes
tb_byte_t uuid[16];
if (!tb_uuid4_make(uuid, name)) return tb_null;
// make uuid string
tb_long_t size = tb_snprintf( uuid_cstr
, 37
, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X"
, uuid[0], uuid[1], uuid[2], uuid[3]
, uuid[4], uuid[5]
, uuid[6], uuid[7]
, uuid[8], uuid[9]
, uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
tb_assert_and_check_return_val(size == 36, tb_null);
// end
uuid_cstr[36] = '\0';
// ok
return uuid_cstr;
}
tbox-1.7.6/src/tbox/hash/uuid.h 0000664 0000000 0000000 00000005626 14671175054 0016331 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file uuid.h
* @ingroup hash
*
*/
#ifndef TB_HASH_UUID_H
#define TB_HASH_UUID_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! make an uuid
*
* @param uuid the uuid output buffer
* @param name we only generate it using a simple hashing function for speed if name is supplied
*
* @return tb_true or tb_false
*/
tb_bool_t tb_uuid_make(tb_byte_t uuid[16], tb_char_t const* name);
/*! make an uuid string
*
* @param uuid_cstr the uuid output c-string
* @param name we only generate it using a simple hashing function for speed if name is supplied
*
* @return the uuid c-string or tb_null
*/
tb_char_t const* tb_uuid_make_cstr(tb_char_t uuid_cstr[37], tb_char_t const* name);
/*! make an uuid (version 4)
*
* A version 4 UUID is defined in RFC 4122: 128 randomly-generated bits with six bits at certain positions set to particular values. For example,
*
* AA97B177-9383-4934-8543-0F91A7A02836
* ^ ^
* 1 2
* The digit at position 1 above is always "4" and the digit at position 2 is always one of "8", "9", "A" or "B".
*
* @see
* - https://www.cryptosys.net/pki/uuid-rfc4122.html
* - https://tools.ietf.org/html/rfc4122
*
* @param uuid the uuid output buffer
* @param name we only generate it using a simple hashing function for speed if name is supplied
*
* @return tb_true or tb_false
*/
tb_bool_t tb_uuid4_make(tb_byte_t uuid[16], tb_char_t const* name);
/*! make an uuid string (version 4)
*
* @param uuid_cstr the uuid output c-string
* @param name we only generate it using a simple hashing function for speed if name is supplied
*
* @return the uuid c-string or tb_null
*/
tb_char_t const* tb_uuid4_make_cstr(tb_char_t uuid_cstr[37], tb_char_t const* name);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/libc/ 0000775 0000000 0000000 00000000000 14671175054 0015167 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/libc/impl/ 0000775 0000000 0000000 00000000000 14671175054 0016130 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/libc/impl/impl.h 0000664 0000000 0000000 00000001604 14671175054 0017243 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file libc.h
* @ingroup libc
*
*/
#ifndef TB_LIBC_IMPL_H
#define TB_LIBC_IMPL_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "libc.h"
#endif
tbox-1.7.6/src/tbox/libc/impl/libc.c 0000664 0000000 0000000 00000002231 14671175054 0017203 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file libc.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "libc.h"
#include "../stdio/printf_object.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_libc_init_env()
{
return tb_true;
}
tb_void_t tb_libc_exit_env()
{
#ifndef TB_CONFIG_MICRO_ENABLE
// exit the printf format
tb_printf_object_exit();
#endif
}
tbox-1.7.6/src/tbox/libc/impl/libc.h 0000664 0000000 0000000 00000002655 14671175054 0017222 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file libc.h
* @ingroup libc
*
*/
#ifndef TB_LIBC_IMPL_LIBC_H
#define TB_LIBC_IMPL_LIBC_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* init libc environment
*
* @return tb_true or tb_false
*/
tb_bool_t tb_libc_init_env(tb_noarg_t);
/* exit libc environment
*/
tb_void_t tb_libc_exit_env(tb_noarg_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/libc/impl/prefix.h 0000664 0000000 0000000 00000001603 14671175054 0017576 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_LIBC_IMPL_PREFIX_H
#define TB_LIBC_IMPL_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/libc/libc.h 0000664 0000000 0000000 00000001741 14671175054 0016254 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file libc.h
* @defgroup libc
*
*/
#ifndef TB_LIBC_H
#define TB_LIBC_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "misc/misc.h"
#include "stdio/stdio.h"
#include "stdlib/stdlib.h"
#include "string/string.h"
#endif
tbox-1.7.6/src/tbox/libc/misc/ 0000775 0000000 0000000 00000000000 14671175054 0016122 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/libc/misc/ctype.h 0000664 0000000 0000000 00000003666 14671175054 0017432 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file ctype.h
* @ingroup libc
*
*/
#ifndef TB_LIBC_CTYPE_H
#define TB_LIBC_CTYPE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// is
#define tb_isspace(x) (((x) == 0x20) || ((x) > 0x8 && (x) < 0xe))
#define tb_isgraph(x) ((x) > 0x1f && (x) < 0x7f)
#define tb_isalpha(x) (((x) > 0x40 && (x) < 0x5b) || ((x) > 0x60 && (x) < 0x7b))
#define tb_isupper(x) ((x) > 0x40 && (x) < 0x5b)
#define tb_islower(x) ((x) > 0x60 && (x) < 0x7b)
#define tb_isascii(x) ((x) >= 0x0 && (x) < 0x80)
#define tb_isdigit(x) ((x) > 0x2f && (x) < 0x3a)
#define tb_isdigit2(x) ((x) == '0' || (x) == '1')
#define tb_isdigit8(x) (((x) > 0x2f && (x) < 0x38))
#define tb_isdigit10(x) (tb_isdigit(x))
#define tb_isdigit16(x) (((x) > 0x2f && (x) < 0x3a) || ((x) > 0x40 && (x) < 0x47) || ((x) > 0x60 && (x) < 0x67))
// to lower & upper
#define tb_tolower(x) (tb_isupper(x)? (x) + 0x20 : (x))
#define tb_toupper(x) (tb_islower(x)? (x) - 0x20 : (x))
#endif
tbox-1.7.6/src/tbox/libc/misc/limits.h 0000664 0000000 0000000 00000001776 14671175054 0017607 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file limits.h
* @ingroup libc
*
*/
#ifndef TB_LIBC_MISC_LIMITS_H
#define TB_LIBC_MISC_LIMITS_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#endif
tbox-1.7.6/src/tbox/libc/misc/misc.h 0000664 0000000 0000000 00000001732 14671175054 0017231 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file misc.h
* @ingroup libc
*
*/
#ifndef TB_LIBC_MISC_H
#define TB_LIBC_MISC_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "ctype.h"
#include "stdarg.h"
#include "limits.h"
#include "./time/time.h"
#endif
tbox-1.7.6/src/tbox/libc/misc/prefix.h 0000664 0000000 0000000 00000001604 14671175054 0017571 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_LIBC_MISC_PREFIX_H
#define TB_LIBC_MISC_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/libc/misc/stdarg.h 0000664 0000000 0000000 00000003516 14671175054 0017564 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file stdarg.h
* @ingroup libc
*
*/
#ifndef TB_LIBC_MISC_STDARG_H
#define TB_LIBC_MISC_STDARG_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../../prefix.h"
#ifndef TB_COMPILER_IS_GCC
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_COMPILER_IS_GCC
# define tb_va_start(v, l) __builtin_va_start(v, l)
# define tb_va_end(v) __builtin_va_end(v)
# define tb_va_arg(v, l) __builtin_va_arg(v, l)
# define tb_va_copy(v, c) __builtin_va_copy(v, c)
#else
# define tb_va_start(v, l) va_start(v, l)
# define tb_va_end(v) va_end(v)
# define tb_va_arg(v, l) va_arg(v, l)
# ifndef va_copy
# define tb_va_copy(v, c) ((v) = (c))
# else
# define tb_va_copy(v, c) va_copy(v, c)
# endif
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
#ifdef TB_COMPILER_IS_GCC
typedef __builtin_va_list tb_va_list_t;
#else
typedef va_list tb_va_list_t;
#endif
#endif
tbox-1.7.6/src/tbox/libc/misc/time/ 0000775 0000000 0000000 00000000000 14671175054 0017060 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/libc/misc/time/gmmktime.c 0000664 0000000 0000000 00000002632 14671175054 0021041 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file gmmktime.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "time.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_time_t tb_gmmktime(tb_tm_t const* tm)
{
// check
tb_assert_and_check_return_val(tm, -1);
// done
tb_long_t y = tm->year;
tb_long_t m = tm->month;
tb_long_t d = tm->mday;
if (m < 3)
{
m += 12;
y--;
}
tb_time_t time = 86400 * (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 719469);
time += 3600 * tm->hour;
time += 60 * tm->minute;
time += tm->second;
// time
return time;
}
tbox-1.7.6/src/tbox/libc/misc/time/gmtime.c 0000664 0000000 0000000 00000003137 14671175054 0020512 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file gmtime.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "time.h"
#ifdef TB_CONFIG_LIBC_HAVE_GMTIME
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_bool_t tb_gmtime(tb_time_t time, tb_tm_t* tm)
{
#ifdef TB_CONFIG_LIBC_HAVE_GMTIME
// gmtime
time_t t = (time_t)time;
struct tm* ptm = gmtime(&t);
if (ptm && tm)
{
tm->second = ptm->tm_sec;
tm->minute = ptm->tm_min;
tm->hour = ptm->tm_hour;
tm->mday = ptm->tm_mday;
tm->month = ptm->tm_mon + 1;
tm->year = ptm->tm_year + 1900;
tm->week = ptm->tm_wday;
tm->yday = ptm->tm_yday;
tm->isdst = ptm->tm_isdst;
}
// ok?
return ptm? tb_true : tb_false;
#else
tb_trace_noimpl();
return tb_false;
#endif
}
tbox-1.7.6/src/tbox/libc/misc/time/localtime.c 0000664 0000000 0000000 00000003234 14671175054 0021177 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file localtime.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "time.h"
#ifdef TB_CONFIG_LIBC_HAVE_LOCALTIME
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_bool_t tb_localtime(tb_time_t time, tb_tm_t* tm)
{
#ifdef TB_CONFIG_LIBC_HAVE_LOCALTIME
// localtime
time_t t = (time_t)time;
struct tm* ptm = localtime(&t);
if (ptm && tm)
{
tm->second = ptm->tm_sec;
tm->minute = ptm->tm_min;
tm->hour = ptm->tm_hour;
tm->mday = ptm->tm_mday;
tm->month = ptm->tm_mon + 1;
tm->year = ptm->tm_year + 1900;
tm->week = ptm->tm_wday;
tm->yday = ptm->tm_yday;
tm->isdst = ptm->tm_isdst;
}
// ok?
return ptm? tb_true : tb_false;
#else
// GMT+8 for beijing.china.
time += 8 * 3600;
return tb_gmtime(time, tm);
#endif
}
tbox-1.7.6/src/tbox/libc/misc/time/mktime.c 0000664 0000000 0000000 00000003341 14671175054 0020513 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file mktime.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "time.h"
#ifdef TB_CONFIG_LIBC_HAVE_MKTIME
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_time_t tb_mktime(tb_tm_t const* tm)
{
// check
tb_assert_and_check_return_val(tm, -1);
#ifdef TB_CONFIG_LIBC_HAVE_MKTIME
// init
struct tm t = {0};
t.tm_sec = (tb_int_t)tm->second;
t.tm_min = (tb_int_t)tm->minute;
t.tm_hour = (tb_int_t)tm->hour;
t.tm_mday = (tb_int_t)tm->mday;
t.tm_mon = (tb_int_t)tm->month - 1;
t.tm_year = (tb_int_t)(tm->year > 1900? tm->year - 1900 : tm->year);
t.tm_wday = (tb_int_t)tm->week;
t.tm_yday = (tb_int_t)tm->yday;
t.tm_isdst = (tb_int_t)tm->isdst;
// mktime
return (tb_time_t)mktime(&t);
#else
// GMT+8 for beijing.china.
tb_time_t time = tb_gmmktime(tm);
return time >= 8 * 3600? time - 8 * 3600: -1;
#endif
}
tbox-1.7.6/src/tbox/libc/misc/time/prefix.h 0000664 0000000 0000000 00000001640 14671175054 0020527 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_LIBC_MISC_TIME_PREFIX_H
#define TB_LIBC_MISC_TIME_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#include "type.h"
#endif
tbox-1.7.6/src/tbox/libc/misc/time/time.c 0000664 0000000 0000000 00000002150 14671175054 0020160 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file time.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "time.h"
#include "../../../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_time_t tb_time()
{
// time
tb_timeval_t tv = {0};
return tb_gettimeofday(&tv, tb_null)? tv.tv_sec : (tb_time_t)-1;
}
tbox-1.7.6/src/tbox/libc/misc/time/time.h 0000664 0000000 0000000 00000004337 14671175054 0020176 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file time.h
* @ingroup libc
*
*/
#ifndef TB_LIBC_MISC_TIME_H
#define TB_LIBC_MISC_TIME_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the time as the number of seconds since the epoch, 1970-01-01 00:00:00 +0000 (utc)
*
* @return the returned time or -1
*/
tb_time_t tb_time(tb_noarg_t);
/*! the gmt time
*
* @param time the time value
* @param tm the gmt time pointer
*
* @return tb_true or tb_false
*/
tb_bool_t tb_gmtime(tb_time_t time, tb_tm_t* tm);
/*! the local time
*
* @param time the time value
* @param tm the local time pointer
*
* @return tb_true or tb_false
*/
tb_bool_t tb_localtime(tb_time_t time, tb_tm_t* tm);
/*! make the time value from the local time
*
* @param tm the time
*
* @return the time value
*/
tb_time_t tb_mktime(tb_tm_t const* tm);
/*! make the time value from the gmt time
*
* @param tm the time
*
* @return the time value
*/
tb_time_t tb_gmmktime(tb_tm_t const* tm);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/libc/misc/time/type.h 0000664 0000000 0000000 00000002362 14671175054 0020215 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file type.h
*
*/
#ifndef TB_LIBC_MISC_TIME_TYPE_H
#define TB_LIBC_MISC_TIME_TYPE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the tm type
typedef struct __tb_tm_t
{
tb_long_t second;
tb_long_t minute;
tb_long_t hour;
tb_long_t mday;
tb_long_t month;
tb_long_t year;
tb_long_t week;
tb_long_t yday;
tb_long_t isdst;
}tb_tm_t;
#endif
tbox-1.7.6/src/tbox/libc/prefix.h 0000664 0000000 0000000 00000001711 14671175054 0016635 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_LIBC_PREFIX_H
#define TB_LIBC_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#include "./misc/ctype.h"
#include "./misc/limits.h"
#include "./misc/stdarg.h"
#endif
tbox-1.7.6/src/tbox/libc/stdio/ 0000775 0000000 0000000 00000000000 14671175054 0016311 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/libc/stdio/getchar.c 0000664 0000000 0000000 00000002322 14671175054 0020071 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* TArch is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* TArch 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with TArch;
* If not, see http://www.gnu.org/licenses/
*
* Copyright (C) 2009-present, ruki All rights reserved.
*
* @author ruki
* @file getchar.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "stdio.h"
#include "../../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_int_t tb_getchar()
{
tb_char_t ch;
return tb_stdfile_getc(tb_stdfile_input(), &ch)? (tb_int_t)ch : TB_EOF;
}
tbox-1.7.6/src/tbox/libc/stdio/prefix.h 0000664 0000000 0000000 00000002023 14671175054 0017754 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_LIBC_STDIO_PREFIX_H
#define TB_LIBC_STDIO_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// eof
#define TB_EOF (-1)
#endif
tbox-1.7.6/src/tbox/libc/stdio/printf.c 0000664 0000000 0000000 00000002616 14671175054 0017764 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* TArch is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* TArch 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with TArch;
* If not, see http://www.gnu.org/licenses/
*
* Copyright (C) 2009-present, ruki All rights reserved.
*
* @author ruki
* @file printf.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "stdio.h"
#include "../../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_long_t tb_printf(tb_char_t const* format, ...)
{
// check
tb_check_return_val(format, 0);
// format line
tb_long_t size = 0;
tb_char_t line[8192] = {0};
tb_vsnprintf_format(line, sizeof(line) - 1, format, &size);
// print it
tb_print(line);
// ok?
return size;
}
tbox-1.7.6/src/tbox/libc/stdio/printf_object.c 0000664 0000000 0000000 00000011056 14671175054 0021310 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file printf_object.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "printf_object"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../string/string.h"
#include "../../algorithm/algorithm.h"
#include "../../container/container.h"
#include "printf_object.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the printf object entry type
typedef struct __tb_printf_object_entry_t
{
// the format name
tb_char_t const* name;
// the format func
tb_printf_object_func_t func;
}tb_printf_object_entry_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
// the entry list
static tb_printf_object_entry_t* g_list = tb_null;
// the entry size
static tb_size_t g_size = 0;
// the entry maxn
static tb_size_t g_maxn = 16;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_long_t tb_printf_object_comp(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t data)
{
// the entry
tb_printf_object_entry_t* entry = (tb_printf_object_entry_t*)item;
tb_assert(entry && data);
// comp
return tb_strcmp(entry->name, (tb_char_t const*)data);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_void_t tb_printf_object_register(tb_char_t const* name, tb_printf_object_func_t func)
{
// check
tb_assert_and_check_return(name && g_maxn);
tb_assert_and_check_return(tb_strlen(name) < TB_PRINTF_OBJECT_NAME_MAXN);
// init entries
if (!g_list) g_list = tb_nalloc_type(g_maxn, tb_printf_object_entry_t);
tb_assert_and_check_return(g_list);
// full? grow it
if (g_size >= g_maxn)
{
// update maxn
g_maxn = g_size + 16;
// resize list
g_list = (tb_printf_object_entry_t*)tb_ralloc(g_list, g_maxn * sizeof(tb_printf_object_entry_t));
tb_assert_and_check_return(g_list);
}
// find it
tb_size_t i = 0;
tb_size_t n = g_size;
tb_long_t r = -1;
for (i = 0; i < n; i++) if ((r = tb_strcmp(name, g_list[i].name)) <= 0) break;
// same? update it
if (!r) g_list[i].func = func;
else
{
// move it for inserting
if (i < n) tb_memmov(g_list + i + 1, g_list + i, (n - i) * sizeof(tb_printf_object_entry_t));
// register it
g_list[i].name = name;
g_list[i].func = func;
// update size
g_size++;
}
}
tb_printf_object_func_t tb_printf_object_find(tb_char_t const* name)
{
// check
tb_assert_and_check_return_val(g_list && name, tb_null);
// init the iterator
tb_array_iterator_t array_iterator;
tb_iterator_ref_t iterator = tb_array_iterator_init_mem(&array_iterator, g_list, g_size, sizeof(tb_printf_object_entry_t));
tb_assert_and_check_return_val(iterator, tb_null);
// find it
tb_size_t itor = tb_binary_find_all_if(iterator, tb_printf_object_comp, name);
tb_check_return_val(itor != tb_iterator_tail(iterator), tb_null);
// ok?
return itor < g_size? g_list[itor].func : tb_null;
}
tb_void_t tb_printf_object_exit()
{
// exit list
if (g_list) tb_free(g_list);
g_list = tb_null;
// exit size
g_size = 0;
g_maxn = 0;
}
#ifdef __tb_debug__
tb_void_t tb_printf_object_dump(tb_noarg_t)
{
// check
tb_assert_and_check_return(g_list);
// trace
tb_trace_i("");
// done
tb_size_t i = 0;
tb_size_t n = g_size;
for (i = 0; i < n; i++)
{
// trace
tb_trace_i("format: %s", g_list[i].name);
}
}
#endif
tbox-1.7.6/src/tbox/libc/stdio/printf_object.h 0000664 0000000 0000000 00000006474 14671175054 0021325 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file printf_object.h
* @ingroup libc
*
*/
#ifndef TB_LIBC_STDIO_PRINTF_OBJECT_H
#define TB_LIBC_STDIO_PRINTF_OBJECT_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/// the printf object name maxn
#define TB_PRINTF_OBJECT_NAME_MAXN (16)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/*! the printf object func type
*
* @param object the printf object
* @param cstr the string buffer
* @param maxn the string buffer maxn
*
* @return the real string size
*/
typedef tb_long_t (*tb_printf_object_func_t)(tb_cpointer_t object, tb_char_t* cstr, tb_size_t maxn);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! register the printf object func
*
* @note non thread-safe
*
* @param name the format name
* @param func the format func
*
* @code
static tb_long_t tb_printf_object_ipv4(tb_cpointer_t object, tb_char_t* cstr, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(object && cstr && maxn, -1);
// the ipv4
tb_ipv4_ref_t ipv4 = (tb_ipv4_ref_t)object;
// format
tb_long_t size = tb_snprintf(cstr, maxn - 1, "%u.%u.%u.%u", ipv4->u8[0], ipv4->u8[1], ipv4->u8[2], ipv4->u8[3]);
if (size >= 0) cstr[size] = '\0';
// ok?
return size;
}
// register the "ipv4" printf object func
tb_printf_object_register("ipv4", tb_printf_object_ipv4);
// init ipv4
tb_ipv4_t ipv4;
tb_ipv4_cstr_set(&ipv4, "127.0.0.1");
// trace ipv4, output: "ipv4: 127.0.0.1"
tb_trace_i("ipv4: %{ipv4}", &ipv4);
* @endcode
*/
tb_void_t tb_printf_object_register(tb_char_t const* name, tb_printf_object_func_t func);
/*! find the printf object func from the given format name
*
* @param name the format name
*
* @return the format func
*/
tb_printf_object_func_t tb_printf_object_find(tb_char_t const* name);
/*! exit the printf object
*/
tb_void_t tb_printf_object_exit(tb_noarg_t);
#ifdef __tb_debug__
/*! dump the printf object
*/
tb_void_t tb_printf_object_dump(tb_noarg_t);
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/libc/stdio/putchar.c 0000664 0000000 0000000 00000002313 14671175054 0020122 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* TArch is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* TArch 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with TArch;
* If not, see http://www.gnu.org/licenses/
*
* Copyright (C) 2009-present, ruki All rights reserved.
*
* @author ruki
* @file putchar.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "stdio.h"
#include "../../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_int_t tb_putchar(tb_int_t ch)
{
return tb_stdfile_putc(tb_stdfile_input(), (tb_char_t)ch)? ch : TB_EOF;
}
tbox-1.7.6/src/tbox/libc/stdio/puts.c 0000664 0000000 0000000 00000002447 14671175054 0017457 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* TArch is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* TArch 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with TArch;
* If not, see http://www.gnu.org/licenses/
*
* Copyright (C) 2009-present, ruki All rights reserved.
*
* @author ruki
* @file puts.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "stdio.h"
#include "../string/string.h"
#include "../../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_long_t tb_puts(tb_char_t const* string)
{
// check
tb_check_return_val(string, 0);
// print it
tb_printl(string);
// ok?
return tb_strlen(string);
}
tbox-1.7.6/src/tbox/libc/stdio/snprintf.c 0000664 0000000 0000000 00000002327 14671175054 0020324 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* TArch is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* TArch 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with TArch;
* If not, see http://www.gnu.org/licenses/
*
* Copyright (C) 2009-present, ruki All rights reserved.
*
* @author ruki
* @file snprintf.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "stdio.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_long_t tb_snprintf(tb_char_t* s, tb_size_t n, tb_char_t const* fmt, ...)
{
tb_long_t ret = 0;
tb_vsnprintf_format(s, n, fmt, &ret);
return ret;
}
tbox-1.7.6/src/tbox/libc/stdio/sprintf.c 0000664 0000000 0000000 00000002320 14671175054 0020137 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* TArch is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* TArch 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with TArch;
* If not, see http://www.gnu.org/licenses/
*
* Copyright (C) 2009-present, ruki All rights reserved.
*
* @author ruki
* @file sprintf.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "stdio.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_long_t tb_sprintf(tb_char_t* s, tb_char_t const* fmt, ...)
{
tb_long_t ret = 0;
tb_vsnprintf_format(s, TB_MAXU16, fmt, &ret);
return ret;
}
tbox-1.7.6/src/tbox/libc/stdio/stdio.h 0000664 0000000 0000000 00000022150 14671175054 0017604 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file stdio.h
* @ingroup libc
*
*/
#ifndef TB_LIBC_STDIO_H
#define TB_LIBC_STDIO_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "printf_object.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// vsnprintf format
#define tb_vsnprintf_format(s, n, format, r) \
do \
{ \
tb_long_t __tb_ret = 0; \
tb_va_list_t __tb_varg_list; \
tb_va_start(__tb_varg_list, format); \
__tb_ret = tb_vsnprintf(s, (n), format, __tb_varg_list); \
tb_va_end(__tb_varg_list); \
if (__tb_ret >= 0) s[__tb_ret] = '\0'; \
*r = __tb_ret > 0? __tb_ret : 0; \
\
} while (0)
// vswprintf format
#define tb_vswprintf_format(s, n, format, r) \
do \
{ \
tb_long_t __tb_ret = 0; \
tb_va_list_t __tb_varg_list; \
tb_va_start(__tb_varg_list, format); \
__tb_ret = tb_vswprintf(s, (n), format, __tb_varg_list); \
tb_va_end(__tb_varg_list); \
if (__tb_ret >= 0) s[__tb_ret] = L'\0'; \
*r = __tb_ret > 0? __tb_ret : 0; \
\
} while (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! returns the next character from the standard input (stdin).
*
* @returns the next character or TB_EOF
*/
tb_int_t tb_getchar(tb_noarg_t);
/*! writes a character to the standard output (stdout).
*
* @returns the character written is returned, or TB_EOF
*/
tb_int_t tb_putchar(tb_int_t ch);
/*! puts
*
* @param string the string
*
* @return the real size
*/
tb_long_t tb_puts(tb_char_t const* string);
/*! wputs
*
* @param string the string
*
* @return the real size
*/
tb_long_t tb_wputs(tb_wchar_t const* string);
/*! printf
*
* @param format the format string
*
* @return the real size
*
* - format: %[flags][width][.precision][qualifier]type
*
* - flags:
* - default: right-justified, left-pad the output with spaces until the required length of output is attained.
* If combined with '0' (see below),
* it will cause the sign to become a space when positive,
* but the remaining characters will be zero-padded
* - -: left-justified, e.g. %-d
* - +: denote the sign '+' or '-' of a number
* - 0: use 0 instead of spaces to left-fill a fixed-length field
* - #: add prefix or suffix
* - %#o => add prefix: 0...
* - %#x => add prefix: 0x...
* - %#X => add prefix: 0X...
* - %#b => add prefix: 0b...
* - %#B => add prefix: 0B...
* - %#f => add prefix: 0f...
* - %#F => add prefix: 0F...
*
* - width:
* - n: n = 1, 2, 3, ..., fill spaces
* - 0n: n = 1, 2, 3, ..., fill 0
* - *: causes printf to pad the output until it is n characters wide,
* where n is an integer value stored in the a function argument just preceding
* that represented by the modified type.
* e.g. printf("%*d", 5, 10) will result in "10" being printed with a width of 5.
*
* - .precision:
* - .n: for non-integral numeric types, causes the decimal portion of the output to be expressed in at least number digits.
* for the string type, causes the output to be truncated at number characters.
* if the precision is zero, nothing is printed for the corresponding argument.
* - *: same as the above, but uses an integer value in the intaken argument to
* determine the number of decimal places or maximum string length.
* e.g. printf("%.*s", 3, "abcdef") will result in "abc" being printed.
*
* - qualifier:
* - h: short integer or single double-point
* - l: long integer or double double-point
* - I8: 8-bit integer
* - I16: 16-bit integer
* - I32: 32-bit integer
* - I64/ll: 64-bit integer
*
* @note support h, l, I8, I16, I32, I64, ll
*
* - type(e.g. %d %x %u %% ...):
* - d, i: print an int as a signed decimal number.
* '%d' and '%i' are synonymous for output, but are different when used with scanf() for input.
* - u: print decimal unsigned int.
* - o: print an unsigned int in octal.
* - x/X: print an unsigned int as a hexadecimal number. 'x' uses lower-case letters and 'X' uses upper-case.
* - b/B: print an unsigned binary interger
* - e/E: print a double value in standard form ([-]d.ddd e[+/-]ddd).
* An E conversion uses the letter E (rather than e) to introduce the exponent.
* The exponent always contains at least two digits; if the value is zero, the exponent is 00.
* e.g. 3.141593e+00
* - f/F: Print a double in normal (fixed-point) notation.
* 'f' and 'F' only differs in how the strings for an infinite number or NaN are printed
* ('inf', 'infinity' and 'nan' for 'f', 'INF', 'INFINITY' and 'NAN' for 'F').
* - g/G: print a double in either normal or exponential notation, whichever is more appropriate for its magnitude.
* 'g' uses lower-case letters, 'G' uses upper-case letters.
* This type differs slightly from fixed-point notation in
* that insignificant zeroes to the right of the decimal point are not included.
* Also, the decimal point is not included on whole numbers.
* - c: print a char (character).
* - s: print a character string
* - p: print a void * (pointer to void) in an implementation-defined format.
* - n: print nothing, but write number of characters successfully written so far into an integer pointer parameter.
* - %: %
*
* @note support d, i, u, o, u, x/X, b/B, f/F, c, s
* @note not support e/E, g/G, p, n
*
* @code
* tb_printf("|hello world|\n");
* tb_printf("|%-10s|%%|%10s|\n", "hello", "world");
* tb_printf("|%#2c|%2.5c|%*c|\n", 'A', 'B', 5, 'C');
* tb_printf("|%#2d|%#8.3o|%*.*d|\n", -56, 56, 10, 5, 56);
* tb_printf("|%#-8.5x|%#2.9X|\n", 0x1f, 0x1f);
* tb_printf("|%#-8.5b|%#2.9B|\n", 0x1f, 0x1f);
* tb_printf("|%-6Id|%5I8u|%#I64x|%#llx|\n", 256, 255, (tb_int64_t)0x8fffffffffff, (tb_int64_t)0x8fffffffffff);
* tb_printf("|%lf|\n", -3.1415926535897932384626433832795);
* tb_printf("|%lf|%lf|%lf|\n", 3.14, 0, -0);
* tb_printf("|%0.9f|\n", 3.1415926535897932384626433832795);
* tb_printf("|%16.9f|\n", 3.1415926535897932384626433832795);
* tb_printf("|%016.9f|\n", 3.14159);
* tb_printf("|%lf|\n", 1.0 / 6.0);
* tb_printf("|%lf|\n", 0.0003141596);
* tb_printf("|%F|\n", tb_float_to_fixed(3.1415));
* tb_printf("|%{object_name}|\n", object);
* @endcode
*/
tb_long_t tb_printf(tb_char_t const* format, ...);
/*! wprintf
*
* @param format the format string
*
* @return the real size
*/
tb_long_t tb_wprintf(tb_wchar_t const* format, ...);
/*! sprintf
*
* @param s the string data
* @param format the format string
*
* @return the real size
*/
tb_long_t tb_sprintf(tb_char_t* s, tb_char_t const* format, ...);
/*! snprintf
*
* @param s the string data
* @param n the string size
* @param format the format string
*
* @return the real size
*/
tb_long_t tb_snprintf(tb_char_t* s, tb_size_t n, tb_char_t const* format, ...);
/*! vsnprintf
*
* @param s the string data
* @param n the string size
* @param format the format string
* @param args the arguments
*
* @return the real size
*/
tb_long_t tb_vsnprintf(tb_char_t* s, tb_size_t n, tb_char_t const* format, tb_va_list_t args);
/*! swprintf
*
* @param s the string data
* @param n the string size
* @param format the format string
*
* @return the real size
*/
tb_long_t tb_swprintf(tb_wchar_t* s, tb_size_t n, tb_wchar_t const* format, ...);
/*! vswprintf
*
* @param s the string data
* @param n the string size
* @param format the format string
* @param args the arguments
*
* @return the real size
*/
tb_long_t tb_vswprintf(tb_wchar_t* s, tb_size_t n, tb_wchar_t const* format, tb_va_list_t args);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/libc/stdio/swprintf.c 0000664 0000000 0000000 00000002331 14671175054 0020330 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* TArch is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* TArch 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with TArch;
* If not, see http://www.gnu.org/licenses/
*
* Copyright (C) 2009-present, ruki All rights reserved.
*
* @author ruki
* @file swprintf.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "stdio.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_long_t tb_swprintf(tb_wchar_t* s, tb_size_t n, tb_wchar_t const* fmt, ...)
{
tb_long_t ret = 0;
tb_vswprintf_format(s, n, fmt, &ret);
return ret;
}
tbox-1.7.6/src/tbox/libc/stdio/vsnprintf.c 0000664 0000000 0000000 00000073021 14671175054 0020511 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file vsnprintf.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "stdio.h"
#include "../../math/math.h"
#include "../../libm/libm.h"
#include "../../utils/utils.h"
#include "../string/string.h"
#include "printf_object.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the printf type
typedef enum __tb_printf_type_t
{
TB_PRINTF_TYPE_NONE = 0
, TB_PRINTF_TYPE_INT = 1
, TB_PRINTF_TYPE_CHAR = 2
, TB_PRINTF_TYPE_CHAR_PERCENT = 3
, TB_PRINTF_TYPE_FLOAT = 4
, TB_PRINTF_TYPE_DOUBLE = 5
, TB_PRINTF_TYPE_STRING = 6
, TB_PRINTF_TYPE_WIDTH = 7
, TB_PRINTF_TYPE_PRECISION = 8
, TB_PRINTF_TYPE_OBJECT = 9
, TB_PRINTF_TYPE_INVALID = 10
}tb_printf_type_t;
// the printf extra info
typedef enum __tb_printf_extra_t
{
TB_PRINTF_EXTRA_NONE = 0
, TB_PRINTF_EXTRA_SIGNED = 1 // signed integer for %d %i
, TB_PRINTF_EXTRA_UPPER = 2 // upper case for %X %B
, TB_PRINTF_EXTRA_PERCENT = 4 // percent char: %
, TB_PRINTF_EXTRA_EXP = 8 // exponent form: [-]d.ddd e[+/-]ddd
}tb_printf_extra_t;
// printf length qualifier
typedef enum __tb_printf_qual_t
{
TB_PRINTF_QUAL_NONE = 0
, TB_PRINTF_QUAL_H = 1
, TB_PRINTF_QUAL_L = 2
, TB_PRINTF_QUAL_LL = 3
, TB_PRINTF_QUAL_I8 = 4
, TB_PRINTF_QUAL_I16 = 5
, TB_PRINTF_QUAL_I32 = 6
, TB_PRINTF_QUAL_I64 = 7
}tb_printf_qual_t;
// printf flag type
typedef enum __tb_printf_flag_t
{
TB_PRINTF_FLAG_NONE = 0
, TB_PRINTF_FLAG_PLUS = 1 // +: denote the sign '+' or '-' of a number
, TB_PRINTF_FLAG_LEFT = 2 // -: left-justified
, TB_PRINTF_FLAG_ZERO = 4 // 0: fill 0 instead of spaces
, TB_PRINTF_FLAG_PFIX = 8 // #: add prefix
}tb_printf_flag_t;
// printf entry
typedef struct __tb_printf_entry_t
{
// format type
tb_uint8_t type;
// extra info
tb_uint8_t extra;
// flag
tb_uint8_t flags;
// qualifier
tb_uint8_t qual;
// field width
tb_int_t width;
// precision
tb_int_t precision;
// base: 2 8 10 16
tb_int_t base;
// the object name
tb_char_t object[TB_PRINTF_OBJECT_NAME_MAXN];
}tb_printf_entry_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_int_t tb_skip_atoi(tb_char_t const** s)
{
tb_int_t i = 0;
while (tb_isdigit(**s)) i = i * 10 + *((*s)++) - '0';
return i;
}
static tb_char_t* tb_printf_object(tb_char_t* pb, tb_char_t* pe, tb_printf_entry_t e, tb_cpointer_t object)
{
#ifndef TB_CONFIG_MICRO_ENABLE
// find the object func
tb_printf_object_func_t func = tb_printf_object_find(e.object);
if (func)
{
// printf it
tb_long_t size = func(object, pb, pe - pb);
if (size >= 0) pb += size;
else
{
// invalid
if (pb < pe) *pb++ = 'i';
if (pb < pe) *pb++ = 'n';
if (pb < pe) *pb++ = 'v';
if (pb < pe) *pb++ = 'a';
if (pb < pe) *pb++ = 'l';
if (pb < pe) *pb++ = 'i';
if (pb < pe) *pb++ = 'd';
}
}
else
{
// null
if (pb < pe) *pb++ = 'n';
if (pb < pe) *pb++ = 'u';
if (pb < pe) *pb++ = 'l';
if (pb < pe) *pb++ = 'l';
}
#else
if (pb < pe) *pb++ = '%';
if (pb < pe) *pb++ = '{';
#endif
// ok?
return pb;
}
static tb_char_t* tb_printf_string(tb_char_t* pb, tb_char_t* pe, tb_printf_entry_t e, tb_char_t const* s)
{
// done
if (s)
{
// get length
tb_long_t n = tb_strnlen(s, e.precision);
// fill space at left side, e.g. " abcd"
if (!(e.flags & TB_PRINTF_FLAG_LEFT))
{
while (n < e.width--)
if (pb < pe) *pb++ = ' ';
}
// copy string
tb_int_t i = 0;
for (i = 0; i < n; ++i)
if (pb < pe) *pb++ = *s++;
// fill space at right side, e.g. "abcd "
while (n < e.width--)
if (pb < pe) *pb++ = ' ';
}
else
{
// null
if (pb < pe) *pb++ = 'n';
if (pb < pe) *pb++ = 'u';
if (pb < pe) *pb++ = 'l';
if (pb < pe) *pb++ = 'l';
}
return pb;
}
static tb_char_t* tb_printf_int64(tb_char_t* pb, tb_char_t* pe, tb_printf_entry_t e, tb_uint64_t num)
{
// digits table
static tb_char_t const* digits_table = "0123456789ABCDEF";
// max: 64-bit binary decimal
tb_char_t digits[64] = {0};
tb_int_t digit_i = 0;
// lowercase mask, e.g. 'F' | 0x20 => 'f'
tb_int_t lomask = (e.extra & TB_PRINTF_EXTRA_UPPER)? 0x0 : 0x20;
// sign: + -
tb_char_t sign = 0;
if (e.extra & TB_PRINTF_EXTRA_SIGNED)
{
if ((tb_int64_t)num < 0)
{
sign = '-';
--e.width;
num = (tb_uint64_t)(-(tb_int64_t)num);
}
else if (e.flags & TB_PRINTF_FLAG_PLUS)
{
sign = '+';
--e.width;
}
}
// convert num => digits string in reverse order
if (num == 0) digits[digit_i++] = '0';
else
{
#if 0
do
{
digits[digit_i++] = digits_table[num % e.base] | lomask;
num /= e.base;
}
while (num);
#else
if (e.base != 10)
{
tb_int_t shift_bits = 4;
if (e.base == 8) shift_bits--;
else if (e.base == 2) shift_bits -= 3;
do
{
digits[digit_i++] = digits_table[(tb_uint8_t)num & (e.base - 1)] | lomask;
num >>= shift_bits;
}
while (num);
}
else
{
do
{
digits[digit_i++] = digits_table[num % e.base] | lomask;
num /= e.base;
}
while (num);
}
#endif
}
// adjust precision
if (digit_i > e.precision)
e.precision = digit_i;
// fill spaces at left side, e.g. " 0x0"
e.width -= e.precision;
if (!(e.flags & (TB_PRINTF_FLAG_LEFT + TB_PRINTF_FLAG_ZERO)))
{
while (--e.width >= 0)
if (pb < pe) *pb++ = ' ';
}
// append sign: + / -
if (sign && (pb < pe)) *pb++ = sign;
// append prefix: 0x..., 0X..., 0b..., 0B...
if (e.flags & TB_PRINTF_FLAG_PFIX)
{
switch (e.base)
{
case 16:
{
if (pb + 1 < pe)
{
*pb++ = '0';
*pb++ = 'X' | lomask;
e.width -= 2;
}
break;
}
case 8:
{
if (pb < pe)
{
*pb++ = '0';
--e.width;
}
break;
}
case 2:
{
if (pb + 1 < pe)
{
*pb++ = '0';
*pb++ = 'B' | lomask;
e.width -= 2;
}
break;
}
default:
break;
}
}
// fill 0 or spaces, e.g. "0x ff"
if (!(e.flags & TB_PRINTF_FLAG_LEFT))
{
tb_char_t c = (e.flags & TB_PRINTF_FLAG_ZERO)? '0' : ' ';
while (--e.width >= 0)
if (pb < pe) *pb++ = c;
}
// fill 0 if precision is larger, e.g. "0x000ff"
while (digit_i <= --e.precision)
if (pb < pe) *pb++ = '0';
// append digits
while (--digit_i >= 0)
if (pb < pe) *pb++ = digits[digit_i];
// trailing space padding for left-justified flags, e.g. "0xff "
while (--e.width >= 0)
if (pb < pe) *pb++ = ' ';
return pb;
}
static tb_char_t* tb_printf_int32(tb_char_t* pb, tb_char_t* pe, tb_printf_entry_t e, tb_uint32_t num)
{
// digits table
static tb_char_t const* digits_table = "0123456789ABCDEF";
// max: 64-bit binary decimal
tb_char_t digits[64] = {0};
tb_int_t digit_i = 0;
// lowercase mask, e.g. 'F' | 0x20 => 'f'
tb_int_t lomask = (e.extra & TB_PRINTF_EXTRA_UPPER)? 0x0 : 0x20;
// sign: + -
tb_char_t sign = 0;
if (e.extra & TB_PRINTF_EXTRA_SIGNED)
{
if ((tb_int32_t)num < 0)
{
sign = '-';
--e.width;
num = (tb_uint32_t)(-(tb_int32_t)num);
}
else if (e.flags & TB_PRINTF_FLAG_PLUS)
{
sign = '+';
--e.width;
}
}
// convert num => digits string in reverse order
if (num == 0) digits[digit_i++] = '0';
else
{
#if 0
do
{
digits[digit_i++] = digits_table[num % e.base] | lomask;
num /= e.base;
}
while (num);
#else
if (e.base != 10)
{
tb_int_t shift_bits = 4;
if (e.base == 8) shift_bits--;
else if (e.base == 2) shift_bits -= 3;
do
{
digits[digit_i++] = digits_table[(tb_uint8_t)num & (e.base - 1)] | lomask;
num >>= shift_bits;
}
while (num);
}
else
{
do
{
digits[digit_i++] = digits_table[num % e.base] | lomask;
num /= e.base;
}
while (num);
}
#endif
}
// adjust precision
if (digit_i > e.precision)
e.precision = digit_i;
// fill spaces at left side, e.g. " 0x0"
e.width -= e.precision;
if (!(e.flags & (TB_PRINTF_FLAG_LEFT + TB_PRINTF_FLAG_ZERO)))
{
while (--e.width >= 0)
if (pb < pe) *pb++ = ' ';
}
// append sign: + / -
if (sign && (pb < pe)) *pb++ = sign;
// append prefix: 0x..., 0X..., 0b..., 0B...
if (e.flags & TB_PRINTF_FLAG_PFIX)
{
switch (e.base)
{
case 16:
{
if (pb + 1 < pe)
{
*pb++ = '0';
*pb++ = 'X' | lomask;
e.width -= 2;
}
break;
}
case 8:
{
if (pb < pe)
{
*pb++ = '0';
--e.width;
}
break;
}
case 2:
{
if (pb + 1 < pe)
{
*pb++ = '0';
*pb++ = 'B' | lomask;
e.width -= 2;
}
break;
}
default:
break;
}
}
// fill 0 or spaces, e.g. "0x ff"
if (!(e.flags & TB_PRINTF_FLAG_LEFT))
{
tb_char_t c = (e.flags & TB_PRINTF_FLAG_ZERO)? '0' : ' ';
while (--e.width >= 0)
if (pb < pe) *pb++ = c;
}
// fill 0 if precision is larger, e.g. "0x000ff"
while (digit_i <= --e.precision)
if (pb < pe) *pb++ = '0';
// append digits
while (--digit_i >= 0)
if (pb < pe) *pb++ = digits[digit_i];
// trailing space padding for left-justified flags, e.g. "0xff "
while (--e.width >= 0)
if (pb < pe) *pb++ = ' ';
return pb;
}
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
static tb_char_t* tb_printf_float(tb_char_t* pb, tb_char_t* pe, tb_printf_entry_t e, tb_float_t num)
{
// digits
tb_char_t ints[32] = {0};
tb_char_t decs[32] = {0};
tb_int_t ints_i = 0, decs_i = 0;
// for inf nan
if (tb_isinff(num))
{
if (pb < pe && num < 0) *pb++ = '-';
if (pb < pe) *pb++ = (e.extra & TB_PRINTF_EXTRA_UPPER)? 'I' : 'i';
if (pb < pe) *pb++ = (e.extra & TB_PRINTF_EXTRA_UPPER)? 'N' : 'n';
if (pb < pe) *pb++ = (e.extra & TB_PRINTF_EXTRA_UPPER)? 'F' : 'f';
return pb;
}
else if (tb_isnanf(num))
{
if (pb < pe) *pb++ = (e.extra & TB_PRINTF_EXTRA_UPPER)? 'N' : 'n';
if (pb < pe) *pb++ = (e.extra & TB_PRINTF_EXTRA_UPPER)? 'A' : 'a';
if (pb < pe) *pb++ = (e.extra & TB_PRINTF_EXTRA_UPPER)? 'N' : 'n';
return pb;
}
// sign: + -
tb_char_t sign = 0;
if (e.extra & TB_PRINTF_EXTRA_SIGNED)
{
if (num < 0)
{
sign = '-';
--e.width;
}
else if (e.flags & TB_PRINTF_FLAG_PLUS)
{
sign = '+';
--e.width;
}
}
// adjust sign
if (num < 0) num = -num;
// default precision: 6
if (e.precision <= 0) e.precision = 6;
// round? i.dddddddd5 => i.ddddddde
tb_uint32_t p = 1;
tb_size_t n = e.precision;
while (n--) p *= 10;
if (((tb_uint32_t)(num * p * 10) % 10) > 4)
num += 1.0f / (tb_float_t)p;
// get integer & decimal
tb_int32_t integer = (tb_int32_t)num;
tb_float_t decimal = num - integer;
// convert integer => digits string in reverse order
if (integer == 0) ints[ints_i++] = '0';
else
{
if (integer < 0) integer = -integer;
do
{
ints[ints_i++] = (integer % 10) + '0';
integer /= 10;
}
while (integer);
}
// convert decimal => digits string in positive order
if (decimal == 0) decs[decs_i++] = '0';
else
{
tb_long_t d = (tb_long_t)(decimal * 10);
do
{
decs[decs_i++] = (tb_char_t)(d + (tb_long_t)'0');
decimal = decimal * 10 - d;
d = (tb_long_t)(decimal * 10);
}
while (decs_i < e.precision);
}
// adjust precision
if (decs_i > e.precision)
decs_i = e.precision;
// fill spaces at left side, e.g. " 0.31415926"
e.width -= (tb_int_t)(ints_i + 1 + e.precision);
if (!(e.flags & (TB_PRINTF_FLAG_LEFT + TB_PRINTF_FLAG_ZERO)))
{
while (--e.width >= 0)
if (pb < pe) *pb++ = ' ';
}
// append sign: + / -
if (sign && (pb < pe)) *pb++ = sign;
// fill 0 or spaces, e.g. "00003.1415926"
if (!(e.flags & TB_PRINTF_FLAG_LEFT))
{
tb_char_t c = (e.flags & TB_PRINTF_FLAG_ZERO)? '0' : ' ';
while (--e.width >= 0)
if (pb < pe) *pb++ = c;
}
// append integer
while (--ints_i >= 0)
if (pb < pe) *pb++ = ints[ints_i];
// append .
if (pb < pe) *pb++ = '.';
// append decimal
tb_int_t decs_n = decs_i;
while (--decs_i >= 0)
if (pb < pe) *pb++ = decs[decs_n - decs_i - 1];
// fill 0 if precision is larger, e.g. "0.3140000"
while (decs_n <= --e.precision)
if (pb < pe) *pb++ = '0';
// trailing space padding for left-justified flags, e.g. "0.31415926 "
while (--e.width >= 0)
if (pb < pe) *pb++ = ' ';
return pb;
}
static tb_char_t* tb_printf_double(tb_char_t* pb, tb_char_t* pe, tb_printf_entry_t e, tb_double_t num)
{
// digits
tb_char_t ints[64] = {0};
tb_char_t decs[64] = {0};
tb_int_t ints_i = 0, decs_i = 0;
// for inf nan
if (tb_isinf(num))
{
if (pb < pe && num < 0) *pb++ = '-';
if (pb < pe) *pb++ = (e.extra & TB_PRINTF_EXTRA_UPPER)? 'I' : 'i';
if (pb < pe) *pb++ = (e.extra & TB_PRINTF_EXTRA_UPPER)? 'N' : 'n';
if (pb < pe) *pb++ = (e.extra & TB_PRINTF_EXTRA_UPPER)? 'F' : 'f';
return pb;
}
else if (tb_isnan(num))
{
if (pb < pe) *pb++ = (e.extra & TB_PRINTF_EXTRA_UPPER)? 'N' : 'n';
if (pb < pe) *pb++ = (e.extra & TB_PRINTF_EXTRA_UPPER)? 'A' : 'a';
if (pb < pe) *pb++ = (e.extra & TB_PRINTF_EXTRA_UPPER)? 'N' : 'n';
return pb;
}
// sign: + -
tb_char_t sign = 0;
if (e.extra & TB_PRINTF_EXTRA_SIGNED)
{
if (num < 0)
{
sign = '-';
--e.width;
}
else if (e.flags & TB_PRINTF_FLAG_PLUS)
{
sign = '+';
--e.width;
}
}
// adjust sign
if (num < 0) num = -num;
// default precision: 6
if (e.precision <= 0) e.precision = 6;
// round? i.dddddddd5 => i.ddddddde
tb_uint64_t p = 1;
tb_size_t n = e.precision;
while (n--) p *= 10;
if (((tb_uint64_t)(num * p * 10) % 10) > 4)
num += 1. / (tb_double_t)p;
// get integer & decimal
tb_int64_t integer = (tb_int64_t)num;
tb_double_t decimal = num - integer;
// convert integer => digits string in reverse order
if (integer == 0) ints[ints_i++] = '0';
else
{
if (integer < 0) integer = -integer;
do
{
ints[ints_i++] = (integer % 10) + '0';
integer /= 10;
}
while (integer);
}
// convert decimal => digits string in positive order
if (decimal == 0) decs[decs_i++] = '0';
else
{
tb_long_t d = (tb_long_t)(decimal * 10);
do
{
decs[decs_i++] = (tb_char_t)(d + (tb_long_t)'0');
decimal = decimal * 10 - d;
d = (tb_long_t)(decimal * 10);
}
while (decs_i < e.precision);
}
// adjust precision
if (decs_i > e.precision)
decs_i = e.precision;
// fill spaces at left side, e.g. " 0.31415926"
e.width -= (tb_int_t)(ints_i + 1 + e.precision);
if (!(e.flags & (TB_PRINTF_FLAG_LEFT + TB_PRINTF_FLAG_ZERO)))
{
while (--e.width >= 0)
if (pb < pe) *pb++ = ' ';
}
// append sign: + / -
if (sign && (pb < pe)) *pb++ = sign;
// fill 0 or spaces, e.g. "00003.1415926"
if (!(e.flags & TB_PRINTF_FLAG_LEFT))
{
tb_char_t c = (e.flags & TB_PRINTF_FLAG_ZERO)? '0' : ' ';
while (--e.width >= 0)
if (pb < pe) *pb++ = c;
}
// append integer
while (--ints_i >= 0)
if (pb < pe) *pb++ = ints[ints_i];
// append .
if (pb < pe) *pb++ = '.';
// append decimal
tb_int_t decs_n = decs_i;
while (--decs_i >= 0)
if (pb < pe) *pb++ = decs[decs_n - decs_i - 1];
// fill 0 if precision is larger, e.g. "0.3140000"
while (decs_n <= --e.precision)
if (pb < pe) *pb++ = '0';
// trailing space padding for left-justified flags, e.g. "0.31415926 "
while (--e.width >= 0)
if (pb < pe) *pb++ = ' ';
return pb;
}
#endif
// get a printf format entry
static tb_int_t tb_printf_entry(tb_char_t const* fmt, tb_printf_entry_t* e)
{
tb_char_t const* p = fmt;
// get field width for *
if (e->type == TB_PRINTF_TYPE_WIDTH)
{
if (e->width < 0)
{
e->width = -e->width;
e->flags |= TB_PRINTF_FLAG_LEFT;
}
e->type = TB_PRINTF_TYPE_NONE;
goto get_precision;
}
// get precision for *
if (e->type == TB_PRINTF_TYPE_PRECISION)
{
if (e->precision < 0) e->precision = 0;
e->type = TB_PRINTF_TYPE_NONE;
goto get_qualifier;
}
// default type
e->type = TB_PRINTF_TYPE_NONE;
// goto %
for (; *p; ++p)
if (*p == '%') break;
// return non-format string
if (p != fmt || !*p)
return (tb_int_t)(p - fmt);
// skip %
++p;
// get flags
e->flags = TB_PRINTF_FLAG_NONE;
while (1)
{
tb_bool_t is_found = tb_true;
switch (*p)
{
case '+': e->flags |= TB_PRINTF_FLAG_PLUS; break;
case '-': e->flags |= TB_PRINTF_FLAG_LEFT; break;
case '0': e->flags |= TB_PRINTF_FLAG_ZERO; break;
case '#': e->flags |= TB_PRINTF_FLAG_PFIX; break;
default: is_found = tb_false; break;
}
if (is_found == tb_false) break;
else ++p;
}
// get field width
e->width = -1;
if (tb_isdigit(*p)) e->width = tb_skip_atoi(&p);
else if (*p == '*')
{
// it's the next argument
e->type = TB_PRINTF_TYPE_WIDTH;
return (tb_int_t)(++p - fmt);
}
get_precision:
// get precision
e->precision = -1;
if (*p == '.')
{
++p;
if (tb_isdigit(*p))
{
e->precision = tb_skip_atoi(&p);
if (e->precision < 0) e->precision = 0;
}
else if (*p == '*')
{
// it's the next argument
e->type = TB_PRINTF_TYPE_PRECISION;
return (tb_int_t)(++p - fmt);
}
}
get_qualifier:
// get length qualifier
e->qual = TB_PRINTF_QUAL_NONE;
switch (*p)
{
// short & long => int
case 'h':
e->qual = TB_PRINTF_QUAL_H;
++p;
break;
case 'l':
e->qual = TB_PRINTF_QUAL_L;
++p;
if (*p == 'l')
{
e->qual = TB_PRINTF_QUAL_LL;
++p;
}
break;
case 'I':
{
++p;
tb_int_t n = tb_skip_atoi(&p);
switch (n)
{
case 8: e->qual = TB_PRINTF_QUAL_I8; break;
case 16: e->qual = TB_PRINTF_QUAL_I16; break;
case 32: e->qual = TB_PRINTF_QUAL_I32; break;
case 64: e->qual = TB_PRINTF_QUAL_I64; break;
default: break;
}
break;
}
case 'z':
switch (sizeof(tb_size_t))
{
case 1: e->qual = TB_PRINTF_QUAL_I8; break;
case 2: e->qual = TB_PRINTF_QUAL_I16; break;
case 4: e->qual = TB_PRINTF_QUAL_I32; break;
case 8: e->qual = TB_PRINTF_QUAL_I64; break;
default: break;
}
++p;
break;
default:
e->qual = TB_PRINTF_QUAL_NONE;
break;
}
// get base & type
e->base = -1;
e->type = TB_PRINTF_TYPE_INVALID;
e->extra = TB_PRINTF_EXTRA_NONE;
switch (*p)
{
case 's':
e->type = TB_PRINTF_TYPE_STRING;
return (tb_int_t)(++p - fmt);
case '%':
e->extra |= TB_PRINTF_EXTRA_PERCENT;
case 'c':
e->type = TB_PRINTF_TYPE_CHAR;
return (tb_int_t)(++p - fmt);
case 'd':
case 'i':
e->extra |= TB_PRINTF_EXTRA_SIGNED;
case 'u':
e->base = 10;
e->type = TB_PRINTF_TYPE_INT;
break;
case 'X':
e->extra |= TB_PRINTF_EXTRA_UPPER;
case 'x':
e->base = 16;
e->type = TB_PRINTF_TYPE_INT;
break;
case 'P':
e->extra |= TB_PRINTF_EXTRA_UPPER;
case 'p':
e->base = 16;
e->type = TB_PRINTF_TYPE_INT;
e->flags |= TB_PRINTF_FLAG_PFIX;
#if TB_CPU_BITSIZE == 64
e->qual = TB_PRINTF_QUAL_I64;
#endif
break;
case 'o':
e->base = 8;
e->type = TB_PRINTF_TYPE_INT;
break;
case 'B':
e->extra |= TB_PRINTF_EXTRA_UPPER;
case 'b':
e->base = 2;
e->type = TB_PRINTF_TYPE_INT;
break;
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
case 'F':
e->extra |= TB_PRINTF_EXTRA_UPPER;
case 'f':
e->type = TB_PRINTF_TYPE_FLOAT;
e->extra |= TB_PRINTF_EXTRA_SIGNED;
break;
case 'E':
e->extra |= TB_PRINTF_EXTRA_UPPER;
case 'e':
e->type = TB_PRINTF_TYPE_FLOAT;
e->extra |= TB_PRINTF_EXTRA_SIGNED;
e->extra |= TB_PRINTF_EXTRA_EXP;
break;
#endif
case '{':
{
#ifdef TB_CONFIG_MICRO_ENABLE
e->type = TB_PRINTF_TYPE_OBJECT;
#else
// get the object name
++p;
tb_size_t indx = 0;
tb_size_t maxn = tb_arrayn(e->object);
while (*p && *p != '}' && indx < maxn - 1) e->object[indx++] = *p++;
e->object[indx] = '\0';
// save the object type
e->type = *p == '}'? TB_PRINTF_TYPE_OBJECT : TB_PRINTF_TYPE_INVALID;
#endif
}
break;
default:
e->type = TB_PRINTF_TYPE_INVALID;
return (tb_int_t)(p - fmt);
}
return (tb_int_t)(++p - fmt);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_long_t tb_vsnprintf(tb_char_t* s, tb_size_t n, tb_char_t const* fmt, tb_va_list_t args)
{
// check
if (!n || !s || !fmt) return 0;
// init start and end pointer
tb_char_t* pb = s;
tb_char_t* pe = s + n - 1;
#if 0
// pe must be larger than pb
if (pe < pb)
{
pe = ((tb_char_t*)-1);
n = (tb_size_t)(pe - pb);
}
#endif
// parse format
tb_printf_entry_t e = {0};
tb_int_t en = 0;
while (*fmt)
{
tb_char_t const* ofmt = fmt;
// get an entry
en = tb_printf_entry(fmt, &e);
fmt += en;
switch (e.type)
{
// copy it if none type
case TB_PRINTF_TYPE_NONE:
{
tb_int_t copy_n = en;
if (pb < pe)
{
if (copy_n > pe - pb) copy_n = (tb_int_t)(pe - pb);
tb_memcpy(pb, ofmt, copy_n);
pb += copy_n;
}
break;
}
// get a character for %c
case TB_PRINTF_TYPE_CHAR:
{
// char: %
if (e.extra & TB_PRINTF_EXTRA_PERCENT)
{
if (pb < pe) *pb++ = '%';
}
// char: %c
else
{
// fill space at left side, e.g. " a"
if (!(e.flags & TB_PRINTF_FLAG_LEFT))
{
while (--e.width > 0)
{
if (pb < pe) *pb++ = ' ';
}
}
if (pb < pe) *pb++ = (tb_char_t)tb_va_arg(args, tb_int_t);
// fill space at right side, e.g. "a "
while (--e.width > 0)
{
if (pb < pe) *pb++ = ' ';
}
}
break;
}
// get field width for *
case TB_PRINTF_TYPE_WIDTH:
e.width = tb_va_arg(args, tb_int_t);
break;
// get precision for *
case TB_PRINTF_TYPE_PRECISION:
e.precision = tb_va_arg(args, tb_int_t);
break;
// get string for %s
case TB_PRINTF_TYPE_STRING:
{
pb = tb_printf_string(pb, pe, e, tb_va_arg(args, tb_char_t const*));
break;
}
// get an integer for %d %u %x ...
case TB_PRINTF_TYPE_INT:
{
if ( e.qual == TB_PRINTF_QUAL_I64
#if TB_CPU_BIT64
|| e.qual == TB_PRINTF_QUAL_L
#endif
|| e.qual == TB_PRINTF_QUAL_LL)
pb = tb_printf_int64(pb, pe, e, tb_va_arg(args, tb_uint64_t));
else
{
tb_uint32_t num = 0;
if (e.extra & TB_PRINTF_EXTRA_SIGNED)
{
switch (e.qual)
{
case TB_PRINTF_QUAL_I8: num = (tb_int8_t)tb_va_arg(args, tb_int_t); break;
case TB_PRINTF_QUAL_I16: num = (tb_int16_t)tb_va_arg(args, tb_int_t); break;
case TB_PRINTF_QUAL_I32: num = (tb_int32_t)tb_va_arg(args, tb_int32_t); break;
default: num = tb_va_arg(args, tb_int_t); break;
}
}
else
{
switch (e.qual)
{
case TB_PRINTF_QUAL_I8: num = (tb_uint8_t)tb_va_arg(args, tb_uint_t); break;
case TB_PRINTF_QUAL_I16: num = (tb_uint16_t)tb_va_arg(args, tb_uint_t); break;
case TB_PRINTF_QUAL_I32: num = tb_va_arg(args, tb_uint32_t); break;
default: num = tb_va_arg(args, tb_uint_t); break;
}
}
pb = tb_printf_int32(pb, pe, e, num);
}
break;
}
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
case TB_PRINTF_TYPE_FLOAT:
{
// double?
if (e.qual == TB_PRINTF_QUAL_L)
{
tb_double_t num = tb_va_arg(args, tb_double_t);
pb = tb_printf_double(pb, pe, e, num);
}
// float?
else
{
tb_float_t num = (tb_float_t)tb_va_arg(args, tb_double_t);
pb = tb_printf_float(pb, pe, e, num);
}
break;
}
#endif
// get object for %{object_name}
case TB_PRINTF_TYPE_OBJECT:
{
pb = tb_printf_object(pb, pe, e, tb_va_arg(args, tb_cpointer_t));
break;
}
case TB_PRINTF_TYPE_INVALID:
{
if (pb < pe) *pb++ = '%';
break;
}
default:
break;
}
}
// end
if (pb < s + n) *pb = '\0';
// the trailing null byte doesn't count towards the total
return (pb - s);
}
tbox-1.7.6/src/tbox/libc/stdio/vswprintf.c 0000664 0000000 0000000 00000073457 14671175054 0020537 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file vswprintf.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "stdio.h"
#include "../../math/math.h"
#include "../../libm/libm.h"
#include "../../utils/utils.h"
#include "../string/string.h"
#include "printf_object.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the printf type
typedef enum __tb_printf_type_t
{
TB_PRINTF_TYPE_NONE = 0
, TB_PRINTF_TYPE_INT = 1
, TB_PRINTF_TYPE_CHAR = 2
, TB_PRINTF_TYPE_CHAR_PERCENT = 3
, TB_PRINTF_TYPE_FLOAT = 4
, TB_PRINTF_TYPE_DOUBLE = 5
, TB_PRINTF_TYPE_STRING = 6
, TB_PRINTF_TYPE_WIDTH = 7
, TB_PRINTF_TYPE_PRECISION = 8
, TB_PRINTF_TYPE_OBJECT = 9
, TB_PRINTF_TYPE_INVALID = 10
}tb_printf_type_t;
// the printf extra info
typedef enum __tb_printf_extra_t
{
TB_PRINTF_EXTRA_NONE = 0
, TB_PRINTF_EXTRA_SIGNED = 1 // signed integer for %d %i
, TB_PRINTF_EXTRA_UPPER = 2 // upper case for %X %B
, TB_PRINTF_EXTRA_PERCENT = 4 // percent char: %
, TB_PRINTF_EXTRA_EXP = 8 // exponent form: [-]d.ddd e[+/-]ddd
}tb_printf_extra_t;
// printf length qualifier
typedef enum __tb_printf_qual_t
{
TB_PRINTF_QUAL_NONE = 0
, TB_PRINTF_QUAL_H = 1
, TB_PRINTF_QUAL_L = 2
, TB_PRINTF_QUAL_LL = 3
, TB_PRINTF_QUAL_I8 = 4
, TB_PRINTF_QUAL_I16 = 5
, TB_PRINTF_QUAL_I32 = 6
, TB_PRINTF_QUAL_I64 = 7
}tb_printf_qual_t;
// printf flag type
typedef enum __tb_printf_flag_t
{
TB_PRINTF_FLAG_NONE = 0
, TB_PRINTF_FLAG_PLUS = 1 // +: denote the sign '+' or '-' of a number
, TB_PRINTF_FLAG_LEFT = 2 // -: left-justified
, TB_PRINTF_FLAG_ZERO = 4 // 0: fill 0 instead of spaces
, TB_PRINTF_FLAG_PFIX = 8 // #: add prefix
}tb_printf_flag_t;
// printf entry
typedef struct __tb_printf_entry_t
{
// format type
tb_uint8_t type;
// extra info
tb_uint8_t extra;
// flag
tb_uint8_t flags;
// qualifier
tb_uint8_t qual;
// field width
tb_int_t width;
// precision
tb_int_t precision;
// base: 2 8 10 16
tb_int_t base;
// the object name
tb_wchar_t object[TB_PRINTF_OBJECT_NAME_MAXN];
}tb_printf_entry_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_int_t tb_skip_atoi(tb_wchar_t const** s)
{
tb_int_t i = 0;
while (tb_isdigit(**s)) i = i * 10 + *((*s)++) - L'0';
return i;
}
static tb_wchar_t* tb_printf_object(tb_wchar_t* pb, tb_wchar_t* pe, tb_printf_entry_t e, tb_cpointer_t object)
{
// the object name
tb_char_t data[1024] = {0};
tb_wtoa(data, e.object, tb_arrayn(data));
// find the object func
tb_printf_object_func_t func = tb_printf_object_find(data);
if (func)
{
// printf it
tb_long_t size = func(object, data, tb_arrayn(data) - 1);
if (size >= 0)
{
// end
data[size] = '\0';
// atow
size = tb_atow(pb, data, pe - pb);
if (size != -1) pb += size;
}
else
{
// invalid
if (pb < pe) *pb++ = L'i';
if (pb < pe) *pb++ = L'n';
if (pb < pe) *pb++ = L'v';
if (pb < pe) *pb++ = L'a';
if (pb < pe) *pb++ = L'l';
if (pb < pe) *pb++ = L'i';
if (pb < pe) *pb++ = L'd';
}
}
else
{
// null
if (pb < pe) *pb++ = L'n';
if (pb < pe) *pb++ = L'u';
if (pb < pe) *pb++ = L'l';
if (pb < pe) *pb++ = L'l';
}
return pb;
}
static tb_wchar_t* tb_printf_string(tb_wchar_t* pb, tb_wchar_t* pe, tb_printf_entry_t e, tb_wchar_t const* s)
{
// done
if (s)
{
// get length
tb_long_t n = tb_wcsnlen(s, e.precision);
// fill space at left side, e.g. " abcd"
if (!(e.flags & TB_PRINTF_FLAG_LEFT))
{
while (n < e.width--)
if (pb < pe) *pb++ = L' ';
}
// copy string
tb_int_t i = 0;
for (i = 0; i < n; ++i)
if (pb < pe) *pb++ = *s++;
// fill space at right side, e.g. "abcd "
while (n < e.width--)
if (pb < pe) *pb++ = L' ';
}
else
{
// null
if (pb < pe) *pb++ = L'n';
if (pb < pe) *pb++ = L'u';
if (pb < pe) *pb++ = L'l';
if (pb < pe) *pb++ = L'l';
}
return pb;
}
static tb_wchar_t* tb_printf_int64(tb_wchar_t* pb, tb_wchar_t* pe, tb_printf_entry_t e, tb_uint64_t num)
{
// digits table
static tb_wchar_t const* digits_table = (tb_wchar_t const*)L"0123456789ABCDEF";
// max: 64-bit binary decimal
tb_wchar_t digits[64] = {0};
tb_int_t digit_i = 0;
// lowercase mask, e.g. 'F' | 0x20 => 'f'
tb_int_t lomask = (e.extra & TB_PRINTF_EXTRA_UPPER)? 0x0 : 0x20;
// sign: + -
tb_wchar_t sign = 0;
if (e.extra & TB_PRINTF_EXTRA_SIGNED)
{
if ((tb_int64_t)num < 0)
{
sign = L'-';
--e.width;
num = (tb_uint64_t)(-(tb_int64_t)num);
}
else if (e.flags & TB_PRINTF_FLAG_PLUS)
{
sign = L'+';
--e.width;
}
}
// convert num => digits string in reverse order
if (num == 0) digits[digit_i++] = L'0';
else
{
#if 0
do
{
digits[digit_i++] = digits_table[num % e.base] | lomask;
num /= e.base;
}
while (num);
#else
if (e.base != 10)
{
tb_int_t shift_bits = 4;
if (e.base == 8) shift_bits--;
else if (e.base == 2) shift_bits -= 3;
do
{
digits[digit_i++] = digits_table[(tb_uint8_t)num & (e.base - 1)] | lomask;
num >>= shift_bits;
}
while (num);
}
else
{
do
{
digits[digit_i++] = digits_table[num % e.base] | lomask;
num /= e.base;
}
while (num);
}
#endif
}
// adjust precision
if (digit_i > e.precision)
e.precision = digit_i;
// fill spaces at left side, e.g. " 0x0"
e.width -= e.precision;
if (!(e.flags & (TB_PRINTF_FLAG_LEFT + TB_PRINTF_FLAG_ZERO)))
{
while (--e.width >= 0)
if (pb < pe) *pb++ = L' ';
}
// append sign: + / -
if (sign && (pb < pe)) *pb++ = sign;
// append prefix: 0x..., 0X..., 0b..., 0B...
if (e.flags & TB_PRINTF_FLAG_PFIX)
{
switch (e.base)
{
case 16:
{
if (pb + 1 < pe)
{
*pb++ = L'0';
*pb++ = L'X' | lomask;
e.width -= 2;
}
break;
}
case 8:
{
if (pb < pe)
{
*pb++ = L'0';
--e.width;
}
break;
}
case 2:
{
if (pb + 1 < pe)
{
*pb++ = L'0';
*pb++ = L'B' | lomask;
e.width -= 2;
}
break;
}
default:
break;
}
}
// fill 0 or spaces, e.g. "0x ff"
if (!(e.flags & TB_PRINTF_FLAG_LEFT))
{
tb_wchar_t c = (e.flags & TB_PRINTF_FLAG_ZERO)? L'0' : L' ';
while (--e.width >= 0)
if (pb < pe) *pb++ = c;
}
// fill 0 if precision is larger, e.g. "0x000ff"
while (digit_i <= --e.precision)
if (pb < pe) *pb++ = L'0';
// append digits
while (--digit_i >= 0)
if (pb < pe) *pb++ = digits[digit_i];
// trailing space padding for left-justified flags, e.g. "0xff "
while (--e.width >= 0)
if (pb < pe) *pb++ = L' ';
return pb;
}
static tb_wchar_t* tb_printf_int32(tb_wchar_t* pb, tb_wchar_t* pe, tb_printf_entry_t e, tb_uint32_t num)
{
// digits table
static tb_wchar_t const* digits_table = (tb_wchar_t const*)L"0123456789ABCDEF";
// max: 64-bit binary decimal
tb_wchar_t digits[64] = {0};
tb_int_t digit_i = 0;
// lowercase mask, e.g. 'F' | 0x20 => 'f'
tb_int_t lomask = (e.extra & TB_PRINTF_EXTRA_UPPER)? 0x0 : 0x20;
// sign: + -
tb_wchar_t sign = 0;
if (e.extra & TB_PRINTF_EXTRA_SIGNED)
{
if ((tb_int32_t)num < 0)
{
sign = L'-';
--e.width;
num = (tb_uint32_t)(-(tb_int32_t)num);
}
else if (e.flags & TB_PRINTF_FLAG_PLUS)
{
sign = L'+';
--e.width;
}
}
// convert num => digits string in reverse order
if (num == 0) digits[digit_i++] = L'0';
else
{
#if 0
do
{
digits[digit_i++] = digits_table[num % e.base] | lomask;
num /= e.base;
}
while (num);
#else
if (e.base != 10)
{
tb_int_t shift_bits = 4;
if (e.base == 8) shift_bits--;
else if (e.base == 2) shift_bits -= 3;
do
{
digits[digit_i++] = digits_table[(tb_uint8_t)num & (e.base - 1)] | lomask;
num >>= shift_bits;
}
while (num);
}
else
{
do
{
digits[digit_i++] = digits_table[num % e.base] | lomask;
num /= e.base;
}
while (num);
}
#endif
}
// adjust precision
if (digit_i > e.precision)
e.precision = digit_i;
// fill spaces at left side, e.g. " 0x0"
e.width -= e.precision;
if (!(e.flags & (TB_PRINTF_FLAG_LEFT + TB_PRINTF_FLAG_ZERO)))
{
while (--e.width >= 0)
if (pb < pe) *pb++ = L' ';
}
// append sign: + / -
if (sign && (pb < pe)) *pb++ = sign;
// append prefix: 0x..., 0X..., 0b..., 0B...
if (e.flags & TB_PRINTF_FLAG_PFIX)
{
switch (e.base)
{
case 16:
{
if (pb + 1 < pe)
{
*pb++ = L'0';
*pb++ = L'X' | lomask;
e.width -= 2;
}
break;
}
case 8:
{
if (pb < pe)
{
*pb++ = L'0';
--e.width;
}
break;
}
case 2:
{
if (pb + 1 < pe)
{
*pb++ = L'0';
*pb++ = L'B' | lomask;
e.width -= 2;
}
break;
}
default:
break;
}
}
// fill 0 or spaces, e.g. "0x ff"
if (!(e.flags & TB_PRINTF_FLAG_LEFT))
{
tb_wchar_t c = (e.flags & TB_PRINTF_FLAG_ZERO)? L'0' : L' ';
while (--e.width >= 0)
if (pb < pe) *pb++ = c;
}
// fill 0 if precision is larger, e.g. "0x000ff"
while (digit_i <= --e.precision)
if (pb < pe) *pb++ = L'0';
// append digits
while (--digit_i >= 0)
if (pb < pe) *pb++ = digits[digit_i];
// trailing space padding for left-justified flags, e.g. "0xff "
while (--e.width >= 0)
if (pb < pe) *pb++ = L' ';
return pb;
}
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
static tb_wchar_t* tb_printf_float(tb_wchar_t* pb, tb_wchar_t* pe, tb_printf_entry_t e, tb_float_t num)
{
// digits
tb_wchar_t ints[32] = {0};
tb_wchar_t decs[32] = {0};
tb_int_t ints_i = 0, decs_i = 0;
// for inf nan
if (tb_isinff(num))
{
if (pb < pe && num < 0) *pb++ = L'-';
if (pb < pe) *pb++ = (e.extra & TB_PRINTF_EXTRA_UPPER)? L'I' : L'i';
if (pb < pe) *pb++ = (e.extra & TB_PRINTF_EXTRA_UPPER)? L'N' : L'n';
if (pb < pe) *pb++ = (e.extra & TB_PRINTF_EXTRA_UPPER)? L'F' : L'f';
return pb;
}
else if (tb_isnanf(num))
{
if (pb < pe) *pb++ = (e.extra & TB_PRINTF_EXTRA_UPPER)? L'N' : L'n';
if (pb < pe) *pb++ = (e.extra & TB_PRINTF_EXTRA_UPPER)? L'A' : L'a';
if (pb < pe) *pb++ = (e.extra & TB_PRINTF_EXTRA_UPPER)? L'N' : L'n';
return pb;
}
// sign: + -
tb_wchar_t sign = 0;
if (e.extra & TB_PRINTF_EXTRA_SIGNED)
{
if (num < 0)
{
sign = L'-';
--e.width;
}
else if (e.flags & TB_PRINTF_FLAG_PLUS)
{
sign = L'+';
--e.width;
}
}
// adjust sign
if (num < 0) num = -num;
// default precision: 6
if (e.precision <= 0) e.precision = 6;
// round? i.dddddddd5 => i.ddddddde
tb_uint32_t p = 1;
tb_size_t n = e.precision;
while (n--) p *= 10;
if (((tb_uint32_t)(num * p * 10) % 10) > 4)
num += 1.0f / (tb_float_t)p;
// get integer & decimal
tb_int32_t integer = (tb_int32_t)num;
tb_float_t decimal = num - integer;
// convert integer => digits string in reverse order
if (integer == 0) ints[ints_i++] = L'0';
else
{
if (integer < 0) integer = -integer;
do
{
ints[ints_i++] = (integer % 10) + L'0';
integer /= 10;
}
while (integer);
}
// convert decimal => digits string in positive order
if (decimal == 0) decs[decs_i++] = L'0';
else
{
tb_long_t d = (tb_long_t)(decimal * 10);
do
{
decs[decs_i++] = (tb_wchar_t)(d + (tb_long_t)L'0');
decimal = decimal * 10 - d;
d = (tb_long_t)(decimal * 10);
}
while (decs_i < e.precision);
}
// adjust precision
if (decs_i > e.precision)
decs_i = e.precision;
// fill spaces at left side, e.g. " 0.31415926"
e.width -= ints_i + 1 + e.precision;
if (!(e.flags & (TB_PRINTF_FLAG_LEFT + TB_PRINTF_FLAG_ZERO)))
{
while (--e.width >= 0)
if (pb < pe) *pb++ = L' ';
}
// append sign: + / -
if (sign && (pb < pe)) *pb++ = sign;
// fill 0 or spaces, e.g. "00003.1415926"
if (!(e.flags & TB_PRINTF_FLAG_LEFT))
{
tb_wchar_t c = (e.flags & TB_PRINTF_FLAG_ZERO)? L'0' : L' ';
while (--e.width >= 0)
if (pb < pe) *pb++ = c;
}
// append integer
while (--ints_i >= 0)
if (pb < pe) *pb++ = ints[ints_i];
// append .
if (pb < pe) *pb++ = L'.';
// append decimal
tb_int_t decs_n = decs_i;
while (--decs_i >= 0)
if (pb < pe) *pb++ = decs[decs_n - decs_i - 1];
// fill 0 if precision is larger, e.g. "0.3140000"
while (decs_n <= --e.precision)
if (pb < pe) *pb++ = L'0';
// trailing space padding for left-justified flags, e.g. "0.31415926 "
while (--e.width >= 0)
if (pb < pe) *pb++ = L' ';
return pb;
}
static tb_wchar_t* tb_printf_double(tb_wchar_t* pb, tb_wchar_t* pe, tb_printf_entry_t e, tb_double_t num)
{
// digits
tb_wchar_t ints[64] = {0};
tb_wchar_t decs[64] = {0};
tb_int_t ints_i = 0, decs_i = 0;
// for inf nan
if (tb_isinf(num))
{
if (pb < pe && num < 0) *pb++ = L'-';
if (pb < pe) *pb++ = (e.extra & TB_PRINTF_EXTRA_UPPER)? L'I' : L'i';
if (pb < pe) *pb++ = (e.extra & TB_PRINTF_EXTRA_UPPER)? L'N' : L'n';
if (pb < pe) *pb++ = (e.extra & TB_PRINTF_EXTRA_UPPER)? L'F' : L'f';
return pb;
}
else if (tb_isnan(num))
{
if (pb < pe) *pb++ = (e.extra & TB_PRINTF_EXTRA_UPPER)? L'N' : L'n';
if (pb < pe) *pb++ = (e.extra & TB_PRINTF_EXTRA_UPPER)? L'A' : L'a';
if (pb < pe) *pb++ = (e.extra & TB_PRINTF_EXTRA_UPPER)? L'N' : L'n';
return pb;
}
// sign: + -
tb_wchar_t sign = 0;
if (e.extra & TB_PRINTF_EXTRA_SIGNED)
{
if (num < 0)
{
sign = L'-';
--e.width;
}
else if (e.flags & TB_PRINTF_FLAG_PLUS)
{
sign = L'+';
--e.width;
}
}
// adjust sign
if (num < 0) num = -num;
// default precision: 6
if (e.precision <= 0) e.precision = 6;
// round? i.dddddddd5 => i.ddddddde
tb_uint64_t p = 1;
tb_size_t n = e.precision;
while (n--) p *= 10;
if (((tb_uint64_t)(num * p * 10) % 10) > 4)
num += 1. / (tb_double_t)p;
// get integer & decimal
tb_int64_t integer = (tb_int64_t)num;
tb_double_t decimal = num - integer;
// convert integer => digits string in reverse order
if (integer == 0) ints[ints_i++] = L'0';
else
{
if (integer < 0) integer = -integer;
do
{
ints[ints_i++] = (integer % 10) + L'0';
integer /= 10;
}
while (integer);
}
// convert decimal => digits string in positive order
if (decimal == 0) decs[decs_i++] = L'0';
else
{
tb_long_t d = (tb_long_t)(decimal * 10);
do
{
decs[decs_i++] = (tb_wchar_t)(d + (tb_long_t)L'0');
decimal = decimal * 10 - d;
d = (tb_long_t)(decimal * 10);
}
while (decs_i < e.precision);
}
// adjust precision
if (decs_i > e.precision)
decs_i = e.precision;
// fill spaces at left side, e.g. " 0.31415926"
e.width -= ints_i + 1 + e.precision;
if (!(e.flags & (TB_PRINTF_FLAG_LEFT + TB_PRINTF_FLAG_ZERO)))
{
while (--e.width >= 0)
if (pb < pe) *pb++ = L' ';
}
// append sign: + / -
if (sign && (pb < pe)) *pb++ = sign;
// fill 0 or spaces, e.g. "00003.1415926"
if (!(e.flags & TB_PRINTF_FLAG_LEFT))
{
tb_wchar_t c = (e.flags & TB_PRINTF_FLAG_ZERO)? L'0' : L' ';
while (--e.width >= 0)
if (pb < pe) *pb++ = c;
}
// append integer
while (--ints_i >= 0)
if (pb < pe) *pb++ = ints[ints_i];
// append .
if (pb < pe) *pb++ = L'.';
// append decimal
tb_int_t decs_n = decs_i;
while (--decs_i >= 0)
if (pb < pe) *pb++ = decs[decs_n - decs_i - 1];
// fill 0 if precision is larger, e.g. "0.3140000"
while (decs_n <= --e.precision)
if (pb < pe) *pb++ = L'0';
// trailing space padding for left-justified flags, e.g. "0.31415926 "
while (--e.width >= 0)
if (pb < pe) *pb++ = L' ';
return pb;
}
#endif
// get a printf format entry
static tb_int_t tb_printf_entry(tb_wchar_t const* fmt, tb_printf_entry_t* e)
{
tb_wchar_t const* p = fmt;
// get field width for *
if (e->type == TB_PRINTF_TYPE_WIDTH)
{
if (e->width < 0)
{
e->width = -e->width;
e->flags |= TB_PRINTF_FLAG_LEFT;
}
e->type = TB_PRINTF_TYPE_NONE;
goto get_precision;
}
// get precision for *
if (e->type == TB_PRINTF_TYPE_PRECISION)
{
if (e->precision < 0) e->precision = 0;
e->type = TB_PRINTF_TYPE_NONE;
goto get_qualifier;
}
// default type
e->type = TB_PRINTF_TYPE_NONE;
// goto %
for (; *p; ++p)
{
if (*p == L'%') break;
}
// return non-format string
if (p != fmt || !*p)
return (tb_int_t)(p - fmt);
// skip %
++p;
// get flags
e->flags = TB_PRINTF_FLAG_NONE;
while (1)
{
tb_bool_t is_found = tb_true;
switch (*p)
{
case L'+': e->flags |= TB_PRINTF_FLAG_PLUS; break;
case L'-': e->flags |= TB_PRINTF_FLAG_LEFT; break;
case L'0': e->flags |= TB_PRINTF_FLAG_ZERO; break;
case L'#': e->flags |= TB_PRINTF_FLAG_PFIX; break;
default: is_found = tb_false; break;
}
if (is_found == tb_false) break;
else ++p;
}
// get field width
e->width = -1;
if (tb_isdigit(*p)) e->width = tb_skip_atoi(&p);
else if (*p == L'*')
{
// it's the next argument
e->type = TB_PRINTF_TYPE_WIDTH;
return (tb_int_t)(++p - fmt);
}
get_precision:
// get precision
e->precision = -1;
if (*p == '.')
{
++p;
if (tb_isdigit(*p))
{
e->precision = tb_skip_atoi(&p);
if (e->precision < 0) e->precision = 0;
}
else if (*p == L'*')
{
// it's the next argument
e->type = TB_PRINTF_TYPE_PRECISION;
return (tb_int_t)(++p - fmt);
}
}
get_qualifier:
// get length qualifier
e->qual = TB_PRINTF_QUAL_NONE;
switch (*p)
{
// short & long => int
case L'h':
e->qual = TB_PRINTF_QUAL_H;
++p;
break;
case L'l':
e->qual = TB_PRINTF_QUAL_L;
++p;
if (*p == L'l')
{
e->qual = TB_PRINTF_QUAL_LL;
++p;
}
break;
case L'I':
{
++p;
tb_int_t n = tb_skip_atoi(&p);
switch (n)
{
case 8: e->qual = TB_PRINTF_QUAL_I8; break;
case 16: e->qual = TB_PRINTF_QUAL_I16; break;
case 32: e->qual = TB_PRINTF_QUAL_I32; break;
case 64: e->qual = TB_PRINTF_QUAL_I64; break;
default: break;
}
break;
}
case L'z':
switch (sizeof(tb_size_t))
{
case 1: e->qual = TB_PRINTF_QUAL_I8; break;
case 2: e->qual = TB_PRINTF_QUAL_I16; break;
case 4: e->qual = TB_PRINTF_QUAL_I32; break;
case 8: e->qual = TB_PRINTF_QUAL_I64; break;
default: break;
}
++p;
break;
default:
e->qual = TB_PRINTF_QUAL_NONE;
break;
}
// get base & type
e->base = -1;
e->type = TB_PRINTF_TYPE_INVALID;
e->extra = TB_PRINTF_EXTRA_NONE;
switch (*p)
{
case L's':
e->type = TB_PRINTF_TYPE_STRING;
return (tb_int_t)(++p - fmt);
case L'%':
e->extra |= TB_PRINTF_EXTRA_PERCENT;
case L'c':
e->type = TB_PRINTF_TYPE_CHAR;
return (tb_int_t)(++p - fmt);
case L'd':
case L'i':
e->extra |= TB_PRINTF_EXTRA_SIGNED;
case L'u':
e->base = 10;
e->type = TB_PRINTF_TYPE_INT;
break;
case L'X':
e->extra |= TB_PRINTF_EXTRA_UPPER;
case L'x':
e->base = 16;
e->type = TB_PRINTF_TYPE_INT;
break;
case L'P':
e->extra |= TB_PRINTF_EXTRA_UPPER;
case L'p':
e->base = 16;
e->type = TB_PRINTF_TYPE_INT;
e->flags |= TB_PRINTF_FLAG_PFIX;
#if TB_CPU_BITSIZE == 64
e->qual = TB_PRINTF_QUAL_I64;
#endif
break;
case L'o':
e->base = 8;
e->type = TB_PRINTF_TYPE_INT;
break;
case L'B':
e->extra |= TB_PRINTF_EXTRA_UPPER;
case L'b':
e->base = 2;
e->type = TB_PRINTF_TYPE_INT;
break;
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
case L'F':
e->extra |= TB_PRINTF_EXTRA_UPPER;
case L'f':
e->type = TB_PRINTF_TYPE_FLOAT;
e->extra |= TB_PRINTF_EXTRA_SIGNED;
break;
case L'E':
e->extra |= TB_PRINTF_EXTRA_UPPER;
case L'e':
e->type = TB_PRINTF_TYPE_FLOAT;
e->extra |= TB_PRINTF_EXTRA_SIGNED;
e->extra |= TB_PRINTF_EXTRA_EXP;
break;
#endif
case L'{':
{
// get the object name
++p;
tb_size_t indx = 0;
tb_size_t maxn = tb_arrayn(e->object);
while (*p && *p != L'}' && indx < maxn - 1) e->object[indx++] = *p++;
e->object[indx] = L'\0';
// save the object type
e->type = *p == L'}'? TB_PRINTF_TYPE_OBJECT : TB_PRINTF_TYPE_INVALID;
}
break;
default:
e->type = TB_PRINTF_TYPE_INVALID;
return (tb_int_t)(p - fmt);
}
return (tb_int_t)(++p - fmt);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_long_t tb_vswprintf(tb_wchar_t* s, tb_size_t n, tb_wchar_t const* fmt, tb_va_list_t args)
{
// check
if (!n || !s || !fmt) return 0;
// init start and end pointer
tb_wchar_t* pb = s;
tb_wchar_t* pe = s + n - 1;
#if 0
// pe must be larger than pb
if (pe < pb)
{
pe = ((tb_wchar_t*)-1);
n = (tb_size_t)(pe - pb);
}
#endif
// parse format
tb_printf_entry_t e = {0};
tb_int_t en = 0;
while (*fmt)
{
tb_wchar_t const* ofmt = fmt;
// get an entry
en = tb_printf_entry(fmt, &e);
fmt += en;
switch (e.type)
{
// copy it if none type
case TB_PRINTF_TYPE_NONE:
{
tb_int_t copy_n = en;
if (pb < pe)
{
if (copy_n > pe - pb) copy_n = (tb_int_t)(pe - pb);
tb_memcpy(pb, ofmt, copy_n * sizeof(tb_wchar_t));
pb += copy_n;
}
break;
}
// get a character for %c
case TB_PRINTF_TYPE_CHAR:
{
// char: %
if (e.extra & TB_PRINTF_EXTRA_PERCENT)
{
if (pb < pe) *pb++ = L'%';
}
// char: %c
else
{
// fill space at left side, e.g. " a"
if (!(e.flags & TB_PRINTF_FLAG_LEFT))
{
while (--e.width > 0)
{
if (pb < pe) *pb++ = L' ';
}
}
if (pb < pe) *pb++ = (tb_wchar_t)tb_va_arg(args, tb_int_t);
// fill space at right side, e.g. "a "
while (--e.width > 0)
{
if (pb < pe) *pb++ = L' ';
}
}
break;
}
// get field width for *
case TB_PRINTF_TYPE_WIDTH:
e.width = tb_va_arg(args, tb_int_t);
break;
// get precision for *
case TB_PRINTF_TYPE_PRECISION:
e.precision = tb_va_arg(args, tb_int_t);
break;
// get string for %s
case TB_PRINTF_TYPE_STRING:
{
pb = tb_printf_string(pb, pe, e, tb_va_arg(args, tb_wchar_t const*));
break;
}
// get an integer for %d %u %x ...
case TB_PRINTF_TYPE_INT:
{
if ( e.qual == TB_PRINTF_QUAL_I64
#if TB_CPU_BIT64
|| e.qual == TB_PRINTF_QUAL_L
#endif
|| e.qual == TB_PRINTF_QUAL_LL)
pb = tb_printf_int64(pb, pe, e, tb_va_arg(args, tb_uint64_t));
else
{
tb_uint32_t num = 0;
if (e.extra & TB_PRINTF_EXTRA_SIGNED)
{
switch (e.qual)
{
case TB_PRINTF_QUAL_I8: num = (tb_int8_t)tb_va_arg(args, tb_int_t); break;
case TB_PRINTF_QUAL_I16: num = (tb_int16_t)tb_va_arg(args, tb_int_t); break;
case TB_PRINTF_QUAL_I32: num = tb_va_arg(args, tb_int32_t); break;
default: num = tb_va_arg(args, tb_int_t); break;
}
}
else
{
switch (e.qual)
{
case TB_PRINTF_QUAL_I8: num = (tb_uint8_t)tb_va_arg(args, tb_uint_t); break;
case TB_PRINTF_QUAL_I16: num = (tb_uint16_t)tb_va_arg(args, tb_uint_t); break;
case TB_PRINTF_QUAL_I32: num = tb_va_arg(args, tb_uint32_t); break;
default: num = tb_va_arg(args, tb_uint_t); break;
}
}
pb = tb_printf_int32(pb, pe, e, num);
}
break;
}
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
case TB_PRINTF_TYPE_FLOAT:
{
// double?
if (e.qual == TB_PRINTF_QUAL_L)
{
tb_double_t num = tb_va_arg(args, tb_double_t);
pb = tb_printf_double(pb, pe, e, num);
}
// float?
else
{
tb_float_t num = (tb_float_t)tb_va_arg(args, tb_double_t);
pb = tb_printf_float(pb, pe, e, num);
}
break;
}
#endif
// get object for %{object_name}
case TB_PRINTF_TYPE_OBJECT:
{
pb = tb_printf_object(pb, pe, e, tb_va_arg(args, tb_cpointer_t));
break;
}
case TB_PRINTF_TYPE_INVALID:
{
if (pb < pe) *pb++ = L'%';
break;
}
default:
break;
}
}
// end
if (pb < s + n) *pb = L'\0';
// the trailing null byte doesn't count towards the total
return (pb - s);
}
tbox-1.7.6/src/tbox/libc/stdio/wprintf.c 0000664 0000000 0000000 00000003132 14671175054 0020145 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* TArch is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* TArch 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with TArch;
* If not, see http://www.gnu.org/licenses/
*
* Copyright (C) 2009-present, ruki All rights reserved.
*
* @author ruki
* @file wprintf.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "stdio.h"
#include "../libc.h"
#include "../../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_long_t tb_wprintf(tb_wchar_t const* format, ...)
{
// check
tb_check_return_val(format, 0);
// format line
tb_long_t size = 0;
tb_wchar_t line[8192] = {0};
tb_vswprintf_format(line, 8191, format, &size);
if (size >= 0 && size < 8192) line[size] = L'\0';
// wtoa
tb_char_t text[8192] = {0};
size = tb_wtoa(text, line, 8191);
tb_assert_and_check_return_val(size != -1, 0);
// print it
tb_print(text);
// ok?
return size;
}
tbox-1.7.6/src/tbox/libc/stdio/wputs.c 0000664 0000000 0000000 00000002661 14671175054 0017644 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* TArch is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* TArch 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with TArch;
* If not, see http://www.gnu.org/licenses/
*
* Copyright (C) 2009-present, ruki All rights reserved.
*
* @author ruki
* @file wputs.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "stdio.h"
#include "../libc.h"
#include "../../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_long_t tb_wputs(tb_wchar_t const* string)
{
// check
tb_check_return_val(string, 0);
// wtoa
tb_char_t line[8192] = {0};
tb_long_t size = tb_wtoa(line, string, 8191);
tb_assert_and_check_return_val(size != -1, 0);
// print it
tb_printl(line);
// ok?
return tb_wcslen(string);
}
tbox-1.7.6/src/tbox/libc/stdlib/ 0000775 0000000 0000000 00000000000 14671175054 0016450 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/libc/stdlib/mbstowcs.c 0000664 0000000 0000000 00000005627 14671175054 0020467 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file mbstowcs.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "stdlib.h"
#ifdef TB_CONFIG_LIBC_HAVE_MBSTOWCS
# include "setlocale.h"
# include
#endif
#ifdef TB_CONFIG_MODULE_HAVE_CHARSET
# include "../../charset/charset.h"
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// select the implementation of mbstowcs
#ifdef TB_CONFIG_FORCE_UTF8
# if defined(TB_CONFIG_MODULE_HAVE_CHARSET)
# define TB_MBSTOWCS_IMPL_CHARSET
# elif defined(TB_CONFIG_LIBC_HAVE_MBSTOWCS)
# define TB_MBSTOWCS_IMPL_LIBC
# endif
#else
# if defined(TB_CONFIG_LIBC_HAVE_MBSTOWCS)
# define TB_MBSTOWCS_IMPL_LIBC
# elif defined(TB_CONFIG_MODULE_HAVE_CHARSET)
# define TB_MBSTOWCS_IMPL_CHARSET
# endif
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#ifdef TB_MBSTOWCS_IMPL_LIBC
inline static tb_size_t tb_mbstowcs_libc(tb_wchar_t* s1, tb_char_t const* s2, tb_size_t n)
{
// set local locale
tb_setlocale();
// convert it
n = mbstowcs(s1, s2, n);
// set default locale
tb_resetlocale();
// ok
return n;
}
#endif
#ifdef TB_MBSTOWCS_IMPL_CHARSET
inline static tb_size_t tb_mbstowcs_charset(tb_wchar_t* s1, tb_char_t const* s2, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s1 && s2, 0);
// init
tb_size_t e = (sizeof(tb_wchar_t) == 4) ? TB_CHARSET_TYPE_UTF32 : TB_CHARSET_TYPE_UTF16;
tb_long_t r = tb_charset_conv_cstr(TB_CHARSET_TYPE_UTF8, e | TB_CHARSET_TYPE_LE, s2,
(tb_byte_t*)s1, n * sizeof(tb_wchar_t));
if (r > 0) r /= sizeof(tb_wchar_t);
// strip
if (r >= 0) s1[r] = L'\0';
// ok?
return r >= 0 ? r : -1;
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_size_t tb_mbstowcs(tb_wchar_t* s1, tb_char_t const* s2, tb_size_t n)
{
#if defined(TB_MBSTOWCS_IMPL_CHARSET)
return tb_mbstowcs_charset(s1, s2, n);
#elif defined(TB_MBSTOWCS_IMPL_LIBC)
return tb_mbstowcs_libc(s1, s2, n);
#else
tb_trace_noimpl();
return -1;
#endif
}
tbox-1.7.6/src/tbox/libc/stdlib/prefix.h 0000664 0000000 0000000 00000001607 14671175054 0020122 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_LIBC_STDLIB_PREFIX_H
#define TB_LIBC_STDLIB_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/libc/stdlib/random.c 0000664 0000000 0000000 00000002127 14671175054 0020076 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file random.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "stdlib.h"
#include "../../math/math.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_void_t tb_srandom(tb_size_t seed)
{
tb_random_seed(seed);
}
tb_long_t tb_random()
{
return tb_random_value();
}
tbox-1.7.6/src/tbox/libc/stdlib/setlocale.h 0000664 0000000 0000000 00000005607 14671175054 0020604 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author OpportunityLiu
* @file setlocale.h
* @ingroup libc
*
*/
#ifndef TB_LIBC_STDLIB_SETLOCALE_H
#define TB_LIBC_STDLIB_SETLOCALE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#ifdef TB_CONFIG_LIBC_HAVE_SETLOCALE
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_CONFIG_LIBC_HAVE_SETLOCALE
# ifdef TB_CONFIG_FORCE_UTF8
# if defined(TB_CONFIG_OS_WINDOWS)
# define tb_setlocale() \
do \
{ \
if (!setlocale(LC_ALL, ".65001")) \
{ \
tb_trace_w("failed to setlocale to utf-8"); \
setlocale(LC_ALL, ""); \
} \
} while (0)
# else
# define tb_setlocale() \
do \
{ \
if (!(setlocale(LC_ALL, "C.UTF-8") || \
setlocale(LC_ALL, "en_US.UTF-8") || \
setlocale(LC_ALL, "zh_CN.UTF-8"))) \
{ \
tb_trace_w("failed to setlocale to utf-8"); \
setlocale(LC_ALL, ""); \
} \
} while (0)
# endif
# else
# define tb_setlocale() setlocale(LC_ALL, "")
# endif
# define tb_resetlocale() setlocale(LC_ALL, "C")
#else
# define tb_setlocale() ((void)0)
# define tb_resetlocale() ((void)0)
#endif
#endif tbox-1.7.6/src/tbox/libc/stdlib/stdlib.c 0000664 0000000 0000000 00000035423 14671175054 0020104 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file stdlib.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "stdlib.h"
#include "../../libm/libm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_uint64_t tb_s2tou64(tb_char_t const* s)
{
// check
tb_assert_and_check_return_val(s, 0);
// skip space
while (tb_isspace(*s)) s++;
// has sign?
tb_int_t sign = 0;
if (*s == '-')
{
sign = 1;
s++;
}
// skip '+'
else if (*s == '+') s++;
// skip "0b"
if (s[0] == '0' && (s[1] == 'b' || s[1] == 'B'))
s += 2;
// skip '0'
while ((*s) == '0') s++;
// compute number
tb_uint64_t val = 0;
while (*s)
{
tb_char_t ch = *s;
if (tb_isdigit2(ch))
val = (val << 1) + (ch - '0');
else break;
s++;
}
// is negative number?
if (sign) val = ~val + 1;
// the value
return val;
}
tb_uint64_t tb_s8tou64(tb_char_t const* s)
{
// check
tb_assert_and_check_return_val(s, 0);
// skip space
while (tb_isspace(*s)) s++;
// has sign?
tb_int_t sign = 0;
if (*s == '-')
{
sign = 1;
s++;
}
// skip '+'
else if (*s == '+') s++;
// skip '0'
while ((*s) == '0') s++;
// compute number
tb_uint64_t val = 0;
while (*s)
{
tb_char_t ch = *s;
if (tb_isdigit8(ch))
val = (val << 3) + (ch - '0');
else break;
s++;
}
// is negative number?
if (sign) val = ~val + 1;
// the value
return val;
}
tb_uint64_t tb_s10tou64(tb_char_t const* s)
{
// check
tb_assert_and_check_return_val(s, 0);
// skip space
while (tb_isspace(*s)) s++;
// has sign?
tb_int_t sign = 0;
if (*s == '-')
{
sign = 1;
s++;
}
// skip '+'
else if (*s == '+') s++;
// skip '0'
while ((*s) == '0') s++;
// compute number
tb_uint64_t val = 0;
while (*s)
{
tb_char_t ch = *s;
if (tb_isdigit10(ch))
val = val * 10 + (ch - '0');
else break;
s++;
}
// is negative number?
if (sign) val = ~val + 1;
// the value
return val;
}
tb_uint64_t tb_s16tou64(tb_char_t const* s)
{
// check
tb_assert_and_check_return_val(s, 0);
// skip space
while (tb_isspace(*s)) s++;
// has sign?
tb_int_t sign = 0;
if (*s == '-')
{
sign = 1;
s++;
}
// skip '+'
else if (*s == '+') s++;
// skip "0x"
if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
s += 2;
// skip '0'
while ((*s) == '0') s++;
// compute number
tb_uint64_t val = 0;
while (*s)
{
tb_char_t ch = *s;
if (tb_isdigit10(ch))
val = (val << 4) + (ch - '0');
else if (ch > ('a' - 1) && ch < ('f' + 1))
val = (val << 4) + (ch - 'a') + 10;
else if (ch > ('A' - 1) && ch < ('F' + 1))
val = (val << 4) + (ch - 'A') + 10;
else break;
s++;
}
// is negative number?
if (sign) val = ~val + 1;
// the value
return val;
}
tb_uint64_t tb_stou64(tb_char_t const* s)
{
// check
tb_assert_and_check_return_val(s, 0);
// skip space
tb_char_t const* p = s;
while (tb_isspace(*p)) p++;
// has sign?
if (*p == '-' || *p == '+') p++;
// is hex?
if (*p++ == '0')
{
if (*p == 'x' || *p == 'X')
return tb_s16tou64(s);
else if (*p == 'b' || *p == 'B')
return tb_s2tou64(s);
else return tb_s8tou64(s);
}
else return tb_s10tou64(s);
}
tb_uint64_t tb_sbtou64(tb_char_t const* s, tb_int_t base)
{
// check
tb_assert_and_check_return_val(s, 0);
// the convect functions
static tb_uint64_t (*s_conv[])(tb_char_t const*) =
{
tb_null
, tb_null
, tb_s2tou64
, tb_null
, tb_null
, tb_null
, tb_null
, tb_null
, tb_s8tou64
, tb_null
, tb_s10tou64
, tb_null
, tb_null
, tb_null
, tb_null
, tb_null
, tb_s16tou64
};
tb_assert_and_check_return_val(base < tb_arrayn(s_conv) && s_conv[base], 0);
// convect it
return s_conv[base](s);
}
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
tb_double_t tb_s2tod(tb_char_t const* s)
{
// check
tb_assert_and_check_return_val(s, 0);
// skip space
while (tb_isspace(*s)) s++;
// has sign?
tb_int_t sign = 0;
if (*s == '-')
{
sign = 1;
s++;
}
// skip '+'
else if (*s == '+') s++;
// nan?
if (s[0] == 'n' && s[1] == 'a' && s[2] == 'n')
return TB_NAN;
// inf or -inf?
if (s[0] == 'i' && s[1] == 'n' && s[2] == 'f')
return sign? -TB_INF : TB_INF;
// skip "0b"
if (s[0] == '0' && (s[1] == 'b' || s[1] == 'B'))
s += 2;
// compute double: lhs.rhs
tb_int_t dec = 0;
tb_uint64_t lhs = 0;
tb_double_t rhs = 0.;
tb_int_t zeros = 0;
tb_int8_t decimals[256];
tb_int8_t* d = decimals;
tb_int8_t* e = decimals + 256;
while (*s)
{
tb_char_t ch = *s;
// is the part of decimal?
if (ch == '.')
{
if (!dec)
{
dec = 1;
s++;
continue ;
}
else break;
}
// parse integer & decimal
if (tb_isdigit2(ch))
{
// save decimals
if (dec)
{
if (d < e)
{
if (ch != '0')
{
// fill '0'
while (zeros--) *d++ = 0;
zeros = 0;
// save decimal
*d++ = ch - '0';
}
else zeros++;
}
}
else lhs = (lhs << 1) + (ch - '0');
}
else break;
s++;
}
tb_assert(d <= decimals + 256);
// compute decimal
while (d-- > decimals) rhs = (rhs + *d) / 2;
// merge
return (sign? ((tb_double_t)lhs + rhs) * -1. : ((tb_double_t)lhs + rhs));
}
tb_double_t tb_s8tod(tb_char_t const* s)
{
// check
tb_assert_and_check_return_val(s, 0);
// skip space
while (tb_isspace(*s)) s++;
// has sign?
tb_int_t sign = 0;
if (*s == '-')
{
sign = 1;
s++;
}
// skip '+'
else if (*s == '+') s++;
// nan?
if (s[0] == 'n' && s[1] == 'a' && s[2] == 'n')
return TB_NAN;
// inf or -inf?
if (s[0] == 'i' && s[1] == 'n' && s[2] == 'f')
return sign? -TB_INF : TB_INF;
// skip '0'
while ((*s) == '0') s++;
// compute double: lhs.rhs
tb_int_t dec = 0;
tb_uint64_t lhs = 0;
tb_double_t rhs = 0.;
tb_int_t zeros = 0;
tb_int8_t decimals[256];
tb_int8_t* d = decimals;
tb_int8_t* e = decimals + 256;
while (*s)
{
tb_char_t ch = *s;
// is the part of decimal?
if (ch == '.')
{
if (!dec)
{
dec = 1;
s++;
continue ;
}
else break;
}
// parse integer & decimal
if (tb_isdigit8(ch))
{
// save decimals
if (dec)
{
if (d < e)
{
if (ch != '0')
{
// fill '0'
while (zeros--) *d++ = 0;
zeros = 0;
// save decimal
*d++ = ch - '0';
}
else zeros++;
}
}
else lhs = (lhs << 3) + (ch - '0');
}
else break;
s++;
}
// check
tb_assert_and_check_return_val(d <= decimals + 256, 0);
// compute decimal
while (d-- > decimals) rhs = (rhs + *d) / 8;
// merge
return (sign? ((tb_double_t)lhs + rhs) * -1. : ((tb_double_t)lhs + rhs));
}
tb_double_t tb_s10tod(tb_char_t const* s)
{
// check
tb_assert_and_check_return_val(s, 0);
// skip space
while (tb_isspace(*s)) s++;
// has sign?
tb_int_t sign = 0;
if (*s == '-')
{
sign = 1;
s++;
}
// skip '+'
else if (*s == '+') s++;
// nan?
if (s[0] == 'n' && s[1] == 'a' && s[2] == 'n')
return TB_NAN;
// inf or -inf?
if (s[0] == 'i' && s[1] == 'n' && s[2] == 'f')
return sign? -TB_INF : TB_INF;
// skip '0'
while ((*s) == '0') s++;
// compute double: lhs.rhs
tb_int_t dec = 0;
tb_uint64_t lhs = 0;
tb_double_t rhs = 0.;
tb_int_t zeros = 0;
tb_int8_t decimals[256];
tb_int8_t* d = decimals;
tb_int8_t* e = decimals + 256;
while (*s)
{
tb_char_t ch = *s;
// is the part of decimal?
if (ch == '.')
{
if (!dec)
{
dec = 1;
s++;
continue ;
}
else break;
}
// parse integer & decimal
if (tb_isdigit10(ch))
{
// save decimals
if (dec)
{
if (d < e)
{
if (ch != '0')
{
// fill '0'
while (zeros--) *d++ = 0;
zeros = 0;
// save decimal
*d++ = ch - '0';
}
else zeros++;
}
}
else lhs = lhs * 10 + (ch - '0');
}
else break;
s++;
}
// check
tb_assert_and_check_return_val(d <= decimals + 256, 0);
// compute decimal
while (d-- > decimals) rhs = (rhs + *d) / 10;
// merge
return (sign? ((tb_double_t)lhs + rhs) * -1. : ((tb_double_t)lhs + rhs));
}
tb_double_t tb_s16tod(tb_char_t const* s)
{
// check
tb_assert_and_check_return_val(s, 0);
// skip space
while (tb_isspace(*s)) s++;
// has sign?
tb_int_t sign = 0;
if (*s == '-')
{
sign = 1;
s++;
}
// skip '+'
else if (*s == '+') s++;
// nan?
if (s[0] == 'n' && s[1] == 'a' && s[2] == 'n')
return TB_NAN;
// inf or -inf?
if (s[0] == 'i' && s[1] == 'n' && s[2] == 'f')
return sign? -TB_INF : TB_INF;
// skip "0x"
if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
s += 2;
// compute double: lhs.rhs
tb_int_t dec = 0;
tb_uint64_t lhs = 0;
tb_double_t rhs = 0.;
tb_int_t zeros = 0;
tb_int8_t decimals[256];
tb_int8_t* d = decimals;
tb_int8_t* e = decimals + 256;
while (*s)
{
tb_char_t ch = *s;
// is the part of decimal?
if (ch == '.')
{
if (!dec)
{
dec = 1;
s++;
continue ;
}
else break;
}
// parse integer & decimal
if (tb_isdigit10(ch))
{
// save decimals
if (dec)
{
if (d < e)
{
if (ch != '0')
{
// fill '0'
while (zeros--) *d++ = 0;
zeros = 0;
// save decimal
*d++ = ch - '0';
}
else zeros++;
}
}
else lhs = (lhs << 4) + (ch - '0');
}
else if (ch > ('a' - 1) && ch < ('f' + 1))
{
// save decimals
if (dec)
{
if (d < e)
{
if (ch != '0')
{
// fill '0'
while (zeros--) *d++ = 0;
zeros = 0;
// save decimal
*d++ = (ch - 'a') + 10;
}
else zeros++;
}
}
else lhs = (lhs << 4) + (ch - 'a') + 10;
}
else if (ch > ('A' - 1) && ch < ('F' + 1))
{
// save decimals
if (dec)
{
if (d < e)
{
if (ch != '0')
{
// fill '0'
while (zeros--) *d++ = 0;
zeros = 0;
// save decimal
*d++ = (ch - 'A') + 10;
}
else zeros++;
}
}
else lhs = (lhs << 4) + (ch - 'A') + 10;
}
else break;
s++;
}
// check
tb_assert_and_check_return_val(d <= decimals + 256, 0);
// compute decimal
while (d-- > decimals) rhs = (rhs + *d) / 16;
// merge
return (sign? ((tb_double_t)lhs + rhs) * -1. : ((tb_double_t)lhs + rhs));
}
tb_double_t tb_stod(tb_char_t const* s)
{
// check
tb_assert_and_check_return_val(s, 0);
// skip space
tb_char_t const* p = s;
while (tb_isspace(*p)) p++;
// has sign?
if (*p == '-' || *p == '+') p++;
// is hex?
if (*p++ == '0')
{
if (*p == 'x' || *p == 'X')
return tb_s16tod(s);
else if (*p == 'b' || *p == 'B')
return tb_s2tod(s);
else return tb_s8tod(s);
}
else return tb_s10tod(s);
}
tb_double_t tb_sbtod(tb_char_t const* s, tb_int_t base)
{
// check
tb_assert_and_check_return_val(s, 0);
// the convect functions
static tb_double_t (*s_conv[])(tb_char_t const*) =
{
tb_null
, tb_null
, tb_s2tod
, tb_null
, tb_null
, tb_null
, tb_null
, tb_null
, tb_s8tod
, tb_null
, tb_s10tod
, tb_null
, tb_null
, tb_null
, tb_null
, tb_null
, tb_s16tod
};
tb_assert_and_check_return_val(base < tb_arrayn(s_conv) && s_conv[base], 0);
// convect it
return s_conv[base](s);
}
#endif
tbox-1.7.6/src/tbox/libc/stdlib/stdlib.h 0000664 0000000 0000000 00000016365 14671175054 0020115 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file stdlib.h
* @ingroup libc
*
*/
#ifndef TB_LIBC_STDLIB_H
#define TB_LIBC_STDLIB_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// for uint32
#define tb_s2tou32(s) ((tb_uint32_t)tb_s2tou64(s))
#define tb_s8tou32(s) ((tb_uint32_t)tb_s8tou64(s))
#define tb_s10tou32(s) ((tb_uint32_t)tb_s10tou64(s))
#define tb_s16tou32(s) ((tb_uint32_t)tb_s16tou64(s))
#define tb_stou32(s) ((tb_uint32_t)tb_stou64(s))
#define tb_sbtou32(s, b) ((tb_uint32_t)tb_sbtou64(s, b))
// for int32
#define tb_s2toi32(s) ((tb_int32_t)tb_s2tou64(s))
#define tb_s8toi32(s) ((tb_int32_t)tb_s8tou64(s))
#define tb_s10toi32(s) ((tb_int32_t)tb_s10tou64(s))
#define tb_s16toi32(s) ((tb_int32_t)tb_s16tou64(s))
#define tb_stoi32(s) ((tb_int32_t)tb_stou64(s))
#define tb_sbtoi32(s, b) ((tb_int32_t)tb_sbtou64(s, b))
// for int64
#define tb_s2toi64(s) ((tb_int64_t)tb_s2tou64(s))
#define tb_s8toi64(s) ((tb_int64_t)tb_s8tou64(s))
#define tb_s10toi64(s) ((tb_int64_t)tb_s10tou64(s))
#define tb_s16toi64(s) ((tb_int64_t)tb_s16tou64(s))
#define tb_stoi64(s) ((tb_int64_t)tb_stou64(s))
#define tb_sbtoi64(s, b) ((tb_int64_t)tb_sbtou64(s, b))
// for float
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
# define tb_s2tof(s) ((tb_float_t)tb_s2tod(s))
# define tb_s8tof(s) ((tb_float_t)tb_s8tod(s))
# define tb_s10tof(s) ((tb_float_t)tb_s10tod(s))
# define tb_s16tof(s) ((tb_float_t)tb_s16tod(s))
# define tb_stof(s) ((tb_float_t)tb_stod(s))
# define tb_sbtof(s, b) ((tb_float_t)tb_sbtod(s, b))
#endif
// for porting libc
#define tb_atoi(s) tb_s10toi32(s)
#define tb_atoll(s) tb_s10toi64(s)
#define tb_strtol(s, e, b) tb_sbtoi32(s, b)
#define tb_strtoll(s, e, b) tb_sbtoi64(s, b)
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
# define tb_atof(s) tb_s10tod(s)
# define tb_strtof(s, e) tb_s10tof(s)
# define tb_strtod(s, e) tb_s10tod(s)
#endif
#if TB_CPU_BIT64
# define tb_atol(s) (tb_long_t)tb_s10toi64(s)
#else
# define tb_atol(s) (tb_long_t)tb_s10toi32(s)
#endif
// atow
#define tb_atow(s1, s2, n) tb_mbstowcs(s1, s2, n)
// wtoa
#define tb_wtoa(s1, s2, n) tb_wcstombs(s1, s2, n)
// rand
#define tb_rand() (tb_int_t)tb_random()
#define tb_srand(seed) tb_srandom(seed)
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! convert the binary string to uint64
*
*
* .e.g
*
* "1001" => 9
* "0b1001" => 9
*
*
* @param s the string
*
* @return the uint64 number
*/
tb_uint64_t tb_s2tou64(tb_char_t const* s);
/*! convert the octal string to uint64
*
*
* .e.g
*
* "11" => 9
* "011" => 9
*
*
* @param s the string
*
* @return the uint64 number
*/
tb_uint64_t tb_s8tou64(tb_char_t const* s);
/*! convert the decimal string to uint64
*
* .e.g "9" => 9
*
* @param s the string
*
* @return the uint64 number
*/
tb_uint64_t tb_s10tou64(tb_char_t const* s);
/*! convert the hex string to uint64
*
*
* .e.g
*
* "9" => 9
* "0x9" => 9
*
*
* @param s the string
*
* @return the uint64 number
*/
tb_uint64_t tb_s16tou64(tb_char_t const* s);
/*! auto convert string to uint64
*
*
* .e.g
*
* "0b1001" => 9
* "011" => 9
* "9" => 9
* "0x9" => 9
*
*
* @param s the string
*
* @return the uint64 number
*/
tb_uint64_t tb_stou64(tb_char_t const* s);
/*! convert string to uint64 using the given base number
*
* @param s the string
*
* @return the uint64 number
*/
tb_uint64_t tb_sbtou64(tb_char_t const* s, tb_int_t base);
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
/*! convert the binary string to double
*
*
* .e.g
*
* "1001" => 9
* "0b1001" => 9
*
*
* @param s the string
*
* @return the double number
*/
tb_double_t tb_s2tod(tb_char_t const* s);
/*! convert the binary string to double
*
*
* .e.g
*
* "11" => 9
* "011" => 9
*
*
* @param s the string
*
* @return the double number
*/
tb_double_t tb_s8tod(tb_char_t const* s);
/*! convert the decimal string to double
*
* .e.g "9" => 9
*
* @param s the string
*
* @return the double number
*/
tb_double_t tb_s10tod(tb_char_t const* s);
/*! convert the hex string to double
*
*
* .e.g
*
* "9" => 9
* "0x9" => 9
*
*
* @param s the string
*
* @return the double number
*/
tb_double_t tb_s16tod(tb_char_t const* s);
/*! auto convert string to double
*
*
* .e.g
*
* "0b1001" => 9
* "011" => 9
* "9" => 9
* "0x9" => 9
*
*
* @param s the string
*
* @return the double number
*/
tb_double_t tb_stod(tb_char_t const* s);
/*! convert string to double using the given base number
*
* @param s the string
*
* @return the double number
*/
tb_double_t tb_sbtod(tb_char_t const* s, tb_int_t base);
#endif
/*! mbstowcs, convert string to wstring
*
* @param s1 the wstring data
* @param s2 the string data
* @param n the string length
*
* @return the wstring length
*/
tb_size_t tb_mbstowcs(tb_wchar_t* s1, tb_char_t const* s2, tb_size_t n);
/*! wcstombs, convert wstring to string
*
* @param s1 the string data
* @param s2 the wstring data
* @param n the wstring length
*
* @return the string length
*/
tb_size_t tb_wcstombs(tb_char_t* s1, tb_wchar_t const* s2, tb_size_t n);
/*! update random seed
*
* @param seed the random seed
*/
tb_void_t tb_srandom(tb_size_t seed);
/*! generate the random with range: [0, max)
*
* @return the random value
*/
tb_long_t tb_random(tb_noarg_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/libc/stdlib/wcstombs.c 0000664 0000000 0000000 00000005675 14671175054 0020472 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcstombs.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "stdlib.h"
#ifdef TB_CONFIG_LIBC_HAVE_WCSTOMBS
# include "setlocale.h"
# include
#endif
#ifdef TB_CONFIG_MODULE_HAVE_CHARSET
# include "../../charset/charset.h"
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// select the implementation of wcstombs
#ifdef TB_CONFIG_FORCE_UTF8
# if defined(TB_CONFIG_MODULE_HAVE_CHARSET)
# define TB_WCSTOMBS_IMPL_CHARSET
# elif defined(TB_CONFIG_LIBC_HAVE_WCSTOMBS)
# define TB_WCSTOMBS_IMPL_LIBC
# endif
#else
# if defined(TB_CONFIG_LIBC_HAVE_WCSTOMBS)
# define TB_WCSTOMBS_IMPL_LIBC
# elif defined(TB_CONFIG_MODULE_HAVE_CHARSET)
# define TB_WCSTOMBS_IMPL_CHARSET
# endif
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#ifdef TB_WCSTOMBS_IMPL_LIBC
inline static tb_size_t tb_wcstombs_libc(tb_char_t* s1, tb_wchar_t const* s2, tb_size_t n)
{
// set local locale
tb_setlocale();
// convert it
n = wcstombs(s1, s2, n);
// set default locale
tb_resetlocale();
// ok
return n;
}
#endif
#ifdef TB_WCSTOMBS_IMPL_CHARSET
inline static tb_size_t tb_wcstombs_charset(tb_char_t* s1, tb_wchar_t const* s2, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s1 && s2, 0);
// init
tb_long_t r = 0;
tb_size_t l = tb_wcslen(s2);
// atow
if (l)
{
tb_size_t e = (sizeof(tb_wchar_t) == 4)? TB_CHARSET_TYPE_UTF32 : TB_CHARSET_TYPE_UTF16;
r = tb_charset_conv_data(e | TB_CHARSET_TYPE_LE, TB_CHARSET_TYPE_UTF8, (tb_byte_t const*)s2, l * sizeof(tb_wchar_t), (tb_byte_t*)s1, n);
}
// strip
if (r >= 0) s1[r] = '\0';
// ok?
return r > 0? r : -1;
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_size_t tb_wcstombs(tb_char_t* s1, tb_wchar_t const* s2, tb_size_t n)
{
#if defined(TB_WCSTOMBS_IMPL_CHARSET)
return tb_wcstombs_charset(s1, s2, n);
#elif defined(TB_WCSTOMBS_IMPL_LIBC)
return tb_wcstombs_libc(s1, s2, n);
#else
tb_trace_noimpl();
return -1;
#endif
}
tbox-1.7.6/src/tbox/libc/string/ 0000775 0000000 0000000 00000000000 14671175054 0016475 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/libc/string/impl/ 0000775 0000000 0000000 00000000000 14671175054 0017436 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/libc/string/impl/arm/ 0000775 0000000 0000000 00000000000 14671175054 0020215 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/libc/string/impl/arm/memcmp.c 0000664 0000000 0000000 00000002336 14671175054 0021643 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file memcmp.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
//# define TB_LIBC_STRING_IMPL_MEMCMP
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if 0//def TB_ASSEMBLER_IS_GAS
static tb_long_t tb_memcmp_impl(tb_cpointer_t s1, tb_cpointer_t s2, tb_size_t n)
{
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/arm/memcpy.c 0000664 0000000 0000000 00000002456 14671175054 0021662 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file memcpy.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
//# define TB_LIBC_STRING_IMPL_MEMCPY
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if 0 //def TB_ASSEMBLER_IS_GAS
static tb_pointer_t tb_memcpy_impl(tb_pointer_t s1, tb_cpointer_t s2, tb_size_t n)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
return tb_null;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/arm/memmov.c 0000664 0000000 0000000 00000002450 14671175054 0021662 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file memmov.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
//# define TB_LIBC_STRING_IMPL_MEMMOV
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#ifdef TB_ASSEMBLER_IS_GAS
static tb_pointer_t tb_memmov_impl(tb_pointer_t s1, tb_cpointer_t s2, tb_size_t n)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
return tb_null;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/arm/memset.c 0000664 0000000 0000000 00000025526 14671175054 0021665 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file memset.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#if defined(TB_ASSEMBLER_IS_GAS) && !defined(TB_ARCH_ARM_THUMB) && !defined(TB_ARCH_ARM64)
# define TB_LIBC_STRING_IMPL_MEMSET_U8
# define TB_LIBC_STRING_IMPL_MEMSET_U16
# define TB_LIBC_STRING_IMPL_MEMSET_U32
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#ifdef TB_LIBC_STRING_IMPL_MEMSET_U8
static __tb_inline__ tb_void_t tb_memset_impl_u8_opt_v1(tb_byte_t* s, tb_byte_t c, tb_size_t n)
{
// cache line: 16-bytes
__tb_asm__ __tb_volatile__
(
" tst %2, #3\n" //!< align by 4-bytes, if (s & 0x3) *s = c, s++, n--
" strneb %1, [%2], #1\n"
" subne %0, %0, #1\n"
" tst %2, #3\n" //!< align by 4-bytes, if (s & 0x3) *s = c, s++, n--
" strneb %1, [%2], #1\n"
" subne %0, %0, #1\n"
" tst %2, #3\n" //!< align by 4-bytes, if (s & 0x3) *s = c, s++, n--
" strneb %1, [%2], #1\n"
" subne %0, %0, #1\n"
" orr %1, %1, %1, lsl #8\n" //!< c |= c << 8, expand to 16-bits
" orr %1, %1, %1, lsl #16\n" //!< c |= c << 16, expand to 32-bits
" mov r3, %1\n" //!< for storing data by 4x32bits
" mov r4, %1\n"
" mov r5, %1\n"
"1:\n" //!< fill data by cache line n
" subs %0, %0, #16\n" //!< n -= 16[x8bits] and update cpsr, assume 16-bytes cache lines
" stmhsia %2!, {%1, r3, r4, r5}\n" //!< storing data by 4x32bits = 16[x8bits], cond: hs (if >= 0), ia: s++
" bhs 1b\n" //!< goto 1b if hs (>= 0)
" add %0, %0, #16\n" //!< fill the left data, n = left n (< 16[x8bits])
" movs %0, %0, lsl #29\n" //!< 1, 11100000000000000000000000000000
" stmcsia %2!, {r4, r5}\n" //!< store 2x32bits, cond: cs (if carry bit == 1, >= 8[x8bits])
" strmi r3, [%2], #4\n" //!< store 32bits, cond: mi (if negative bit == 1, >=4[x8bits])
" movs %0, %0, lsl #2\n" //!< 1, 10000000000000000000000000000000
" strcsh %1, [%2], #2\n" //!< store 16bits, cond: cs (if carry bit == 1, >= 2[x8bits])
" strmib r3, [%2]\n" //!< store 8bits, cond: cs (if negative bit == 1, >= 1[x8bits])
: : "r" (n), "r" (c), "r" (s)
: "r3", "r4", "r5"
);
}
#endif
#ifdef TB_LIBC_STRING_IMPL_MEMSET_U8
static tb_pointer_t tb_memset_impl(tb_pointer_t s, tb_byte_t c, tb_size_t n)
{
tb_assert_and_check_return_val(s, tb_null);
if (!n) return s;
// align: 3 + cache: 16
if (n > 19) tb_memset_impl_u8_opt_v1(s, c, n);
else
{
__tb_register__ tb_byte_t* p = s;
__tb_register__ tb_byte_t b = c;
while (n--) *p++ = b;
}
return s;
}
#endif
#ifdef TB_LIBC_STRING_IMPL_MEMSET_U16
static __tb_inline__ tb_void_t tb_memset_u16_impl_opt_v1(tb_uint16_t* s, tb_uint16_t c, tb_size_t n)
{
// cache line: 16-bytes
__tb_asm__ __tb_volatile__
(
" tst %2, #3\n" //!< align by 4-bytes, if (s & 0x3) *((tb_uint16_t*)s) = c, s += 2, n--
" strneh %1, [%2], #2\n"
" subne %0, %0, #1\n"
" orr %1, %1, %1, lsl #16\n" //!< c |= c << 16, expand to 32-bits
" mov r3, %1\n" //!< for storing data by 4x32bits
" mov r4, %1\n"
" mov r5, %1\n"
"1:\n" //!< fill data by cache line n
" subs %0, %0, #8\n" //!< n -= 4x2[x16bits] and update cpsr, assume 16-bytes cache lines
" stmhsia %2!, {%1, r3, r4, r5}\n" //!< storing data by 4x32bits = 8[x16bits], cond: hs (if >= 0), ia: s++
" bhs 1b\n" //!< goto 1b if hs (>= 0)
" add %0, %0, #8\n" //!< fill the left data, n = left n (< 8[x16bits])
" movs %0, %0, lsl #30\n" //!< 1, 11000000000000000000000000000000
" stmcsia %2!, {r4, r5}\n" //!< store 2x32bits, cond: cs (if carry bit == 1, >= 4[x16bits])
" strmi r3, [%2], #4\n" //!< store 32bits, cond: mi (if negative bit == 1, >=2[x16bits])
" movs %0, %0, lsl #2\n" //!< 1, 00000000000000000000000000000000
" strcsh %1, [%2]\n" //!< store 16bits, cond: cs (if carry bit == 1, >= [x16bits])
: : "r" (n), "r" (c), "r" (s)
: "r3", "r4", "r5"
);
}
static __tb_inline__ tb_void_t tb_memset_u16_impl_opt_v2(tb_uint16_t* s, tb_uint16_t c, tb_size_t n)
{
// cache line: 32-bytes
__tb_asm__ __tb_volatile__
(
" tst %2, #3\n" //!< align by 4-bytes, if (s & 0x3) *((tb_uint16_t*)s) = c, s += 2, n--
" strneh %1, [%2], #2\n"
" subne %0, %0, #1\n"
" orr %1, %1, %1, lsl #16\n" //!< c |= c << 16, expand to 32-bits
" mov r3, %1\n" //!< for storing data by 8x32bits
" mov r4, %1\n"
" mov r5, %1\n"
"1:\n" //!< fill data by cache line n
" subs %0, %0, #16\n" //!< n -= 8x2[x16bits] and update cpsr, assume 32-bytes cache lines
" stmhsia %2!, {%1, r3, r4, r5}\n" //!< storing data by 8x32bits = 16[x16bits], cond: hs (if >= 0), ia: s++
" stmhsia %2!, {%1, r3, r4, r5}\n"
" bhs 1b\n" //!< goto 1b if hs (>= 0)
" add %0, %0, #16\n" //!< fill the left data, n = left n (< 16[x16bits])
" movs %0, %0, lsl #29\n" //!< 1, 11100000000000000000000000000000
" stmcsia %2!, {%1, r3, r4, r5}\n" //!< store 4x32bits, cond: cs (if carry bit == 1, >= 8[x16bits])
" stmmiia %2!, {r4, r5}\n" //!< store 2x32bits, cond: mi (if negative bit == 1, >=4[x16bits])
" movs %0, %0, lsl #2\n" //!< 1, 10000000000000000000000000000000
" strcs %1, [%2], #4\n" //!< store 32bits, cond: cs (if carry bit == 1, >= 2[x16bits])
" strmih r3, [%2]\n" //!< store 16bits, cond: cs (if negative bit == 1, >= [x16bits])
: : "r" (n), "r" (c), "r" (s)
: "r3", "r4", "r5"
);
}
#endif
#ifdef TB_LIBC_STRING_IMPL_MEMSET_U16
static tb_pointer_t tb_memset_u16_impl(tb_pointer_t s, tb_uint16_t c, tb_size_t n)
{
tb_assert_and_check_return_val(s, tb_null);
// align by 2-bytes
tb_assert(!(((tb_size_t)s) & 0x1));
if (!n) return s;
if (n > 8) tb_memset_u16_impl_opt_v1(s, c, n);
else
{
__tb_register__ tb_uint16_t* p = s;
__tb_register__ tb_uint16_t b = c;
while (n--) *p++ = b;
}
return s;
}
#endif
#ifdef TB_LIBC_STRING_IMPL_MEMSET_U32
static __tb_inline__ tb_void_t tb_memset_u32_impl_opt_v1(tb_uint32_t* s, tb_uint32_t c, tb_size_t n)
{
// cache line: 16-bytes
__tb_asm__ __tb_volatile__
(
" mov r3, %1\n" //!< for storing data by 4x32bits
" mov r4, %1\n"
" mov r5, %1\n"
"1:\n" //!< fill data by cache line n
" subs %0, %0, #4\n" //!< n -= 4[x32bits] and update cpsr, assume 16-bytes cache lines
" stmhsia %2!, {%1, r3, r4, r5}\n" //!< storing data by 4x32bits, cond: hs (if >= 0), ia: s++
" bhs 1b\n" //!< goto 1b if hs (>= 0)
" add %0, %0, #4\n" //!< fill the left data, n = left n (< 4[x32bits])
" movs %0, %0, lsl #31\n" //!< 1, 1000000000000000000000000000000
" stmcsia %2!, {r4, r5}\n" //!< store 2x32bits, cond: cs (if carry bit == 1, >= 2[x32bits])
" strmi r3, [%2]\n" //!< store 32bits, cond: mi (if negative bit == 1, >= [x32bits])
: : "r" (n), "r" (c), "r" (s)
: "r3", "r4", "r5"
);
}
static __tb_inline__ tb_void_t tb_memset_u32_impl_opt_v2(tb_uint32_t* s, tb_uint32_t c, tb_size_t n)
{
// cache line: 32-bytes
__tb_asm__ __tb_volatile__
(
" mov r3, %1\n" //!< for storing data by 4x32bits
" mov r4, %1\n"
" mov r5, %1\n"
"1:\n" //!< fill data by cache line n
" subs %0, %0, #8\n" //!< n -= 8[x16bits] and update cpsr, assume 32-bytes cache lines
" stmhsia %2!, {%1, r3, r4, r5}\n" //!< storing data by 8x32bits, cond: hs (if >= 0), ia: s++
" stmhsia %2!, {%1, r3, r4, r5}\n"
" bhs 1b\n" //!< goto 1b if hs (>= 0)
" add %0, %0, #8\n" //!< fill the left data, n = left n (< 8[x32bits])
" movs %0, %0, lsl #30\n" //!< 1, 1100000000000000000000000000000
" stmcsia %2!, {%1, r3, r4, r5}\n" //!< store 4x32bits, cond: cs (if carry bit == 1, >= 4[x32bits])
" stmmiia %2!, {r4, r5}\n" //!< store 2x32bits, cond: mi (if negative bit == 1, >=2[x32bits])
" movs %0, %0, lsl #2\n" //!< 1, 00000000000000000000000000000000
" strcs %1, [%2]\n" //!< store 32bits, cond: cs (if carry bit == 1, >= [x32bits])
: : "r" (n), "r" (c), "r" (s)
: "r3", "r4", "r5"
);
}
#endif
#ifdef TB_LIBC_STRING_IMPL_MEMSET_U32
static tb_pointer_t tb_memset_u32_impl(tb_pointer_t s, tb_uint32_t c, tb_size_t n)
{
tb_assert_and_check_return_val(s, tb_null);
// align by 4-bytes
tb_assert(!(((tb_size_t)s) & 0x3));
if (!n) return s;
if (n > 4) tb_memset_u32_impl_opt_v1(s, c, n);
else
{
__tb_register__ tb_uint32_t* p = s;
__tb_register__ tb_uint32_t b = c;
while (n--) *p++ = b;
}
return s;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/arm/prefix.h 0000664 0000000 0000000 00000001632 14671175054 0021665 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_LIBC_STRING_IMPL_ARM_PREFIX_H
#define TB_LIBC_STRING_IMPL_ARM_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/libc/string/impl/arm/strcmp.c 0000664 0000000 0000000 00000003257 14671175054 0021700 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strcmp.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
# define TB_LIBC_STRING_IMPL_STRCMP
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#ifdef TB_ASSEMBLER_IS_GAS
static tb_long_t tb_strcmp_impl(tb_char_t const* s1, tb_char_t const* s2)
{
tb_assert_and_check_return_val(s1 && s2, 0);
if (s1 == s2) return 0;
__tb_register__ tb_long_t r = 0;
__tb_asm__ __tb_volatile__
(
"1:\n"
"ldrb r2, [%1], #1\n"
"ldrb r3, [%2], #1\n"
"cmp r2, #1\n"
"cmpcs r2, r3\n" // r2 == r3? if r2 >= 1
"beq 1b\n"
"sub %0, r2, r3" // r = r2 - r3 if r2 != r3
: "=r"(r)
: "r"(s1), "r"(s2)
: "memory"
);
return r;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/arm/strcpy.c 0000664 0000000 0000000 00000002435 14671175054 0021711 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strcpy.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
//# define TB_LIBC_STRING_IMPL_STRCPY
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if 0//def TB_ASSEMBLER_IS_GAS
static tb_char_t* tb_strcpy_impl(tb_char_t* s1, tb_char_t const* s2)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
return tb_null;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/arm/strlcpy.c 0000664 0000000 0000000 00000002440 14671175054 0022061 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strncpy.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
//# define TB_LIBC_STRING_IMPL_STRLCPY
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if 0//def TB_ASSEMBLER_IS_GAS
static tb_size_t tb_strlcpy_impl(tb_char_t* s1, tb_char_t const* s2, tb_size_t n)
{
tb_assert_and_check_return_val(s1 && s2, 0);
return 0;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/arm/strlen.c 0000664 0000000 0000000 00000006306 14671175054 0021675 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strlen.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
# define TB_LIBC_STRING_IMPL_STRLEN
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#ifdef TB_ASSEMBLER_IS_GAS
static tb_size_t tb_strlen_impl(tb_char_t const* s)
{
tb_assert_and_check_return_val(s, 0);
__tb_register__ tb_size_t n;
__tb_asm__ __tb_volatile__
(
" bic r2, %1, #0x3\n" //!< align address by 4-bytes
" ldr r3, [r2], #4\n" //!< get the first dword after alignment
" ands %1, %1, #0x3\n" //!< left bytes
" rsb %0, %1, #0x0\n" //!< n = -left
" beq 1f\n" //!< goto aligned handler
#ifdef TB_WORDS_BIGENDIAN
" orr r3, r3, #0xff000000\n"
" subs %1, %1, #1\n"
" orrgt r3, r3, #0x00ff0000\n"
" subs %1, %1, #1\n"
" orrgt r3, r3, #0x0000ff00\n"
#else
" orr r3, r3, #0x000000ff\n" //!< fill 0xff
" subs %1, %1, #1\n" //!< left--
" orrgt r3, r3, #0x0000ff00\n" //!< continue to fill 0xff if left > 0
" subs %1, %1, #1\n" //!< left--
" orrgt r3, r3, #0x00ff0000\n" //!< continue to fill 0xff if left > 0
#endif
"1:\n" //!< align handler
" tst r3, #0x000000ff\n"
" tstne r3, #0x0000ff00\n"
" tstne r3, #0x00ff0000\n"
" tstne r3, #0xff000000\n"
" addne %0, %0, #4\n"
" ldrne r3, [r2], #4\n" //!< n += 4, get the next dword if the dword is not 0
" bne 1b\n"
#ifdef TB_WORDS_BIGENDIAN
" tst r3, #0xff000000\n"
" addne %0, %0, #1\n"
" tstne r3, #0x00ff0000\n"
" addne %0, %0, #1\n"
" tstne r3, #0x0000ff00\n"
" addne %0, %0, #1\n"
#else
" tst r3, #0x000000ff\n" //!< handle the last dword
" addne %0, %0, #1\n"
" tstne r3, #0x0000ff00\n"
" addne %0, %0, #1\n"
" tstne r3, #0x00ff0000\n"
" addne %0, %0, #1\n"
#endif
: "=r"(n)
: "r"(s), "0"(0)
: "r2", "r3"
);
return n;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/arm/strncmp.c 0000664 0000000 0000000 00000002447 14671175054 0022056 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strncmp.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#if 0//def TB_ASSEMBLER_IS_GAS
# define TB_LIBC_STRING_IMPL_STRNCMP
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if 0//def TB_ASSEMBLER_IS_GAS
static tb_long_t tb_strncmp_impl(tb_char_t const* s1, tb_char_t const* s2, tb_size_t n)
{
tb_assert_and_check_return_val(s1 && s2, 0);
return 0;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/arm/strncpy.c 0000664 0000000 0000000 00000002455 14671175054 0022071 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strncpy.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
//# define TB_LIBC_STRING_IMPL_STRNCPY
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if 0//def TB_ASSEMBLER_IS_GAS
static tb_char_t* tb_strncpy_impl(tb_char_t* s1, tb_char_t const* s2, tb_size_t n)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
return tb_null;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/arm/strnlen.c 0000664 0000000 0000000 00000002437 14671175054 0022054 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strnlen.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
//# define TB_LIBC_STRING_IMPL_STRNLEN
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if 0//def TB_ASSEMBLER_IS_GAS
static tb_size_t tb_strnlen_impl(tb_char_t const* s, tb_size_t n)
{
tb_assert_and_check_return_val(s, 0);
if (!n) return 0;
return 0;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/prefix.h 0000664 0000000 0000000 00000001622 14671175054 0021105 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_LIBC_STRING_IMPL_PREFIX_H
#define TB_LIBC_STRING_IMPL_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/libc/string/impl/sh4/ 0000775 0000000 0000000 00000000000 14671175054 0020134 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/libc/string/impl/sh4/memcmp.c 0000664 0000000 0000000 00000002340 14671175054 0021555 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file memcmp.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
//# define TB_LIBC_STRING_IMPL_MEMCMP
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if 0//def TB_ASSEMBLER_IS_GAS
static tb_long_t tb_memcmp_impl(tb_cpointer_t s1, tb_cpointer_t s2, tb_size_t n)
{
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/sh4/memcpy.c 0000664 0000000 0000000 00000002744 14671175054 0021601 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file memcpy.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#if 1//def TB_ASSEMBLER_IS_GAS
# define TB_LIBC_STRING_IMPL_MEMCPY
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if 1
static tb_pointer_t tb_memcpy_impl(tb_pointer_t s1, tb_cpointer_t s2, tb_size_t n)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
return memcpy(s1, s2, n);
}
#elif defined(TB_ASSEMBLER_IS_GAS)
static tb_pointer_t tb_memcpy_impl(tb_pointer_t s1, tb_cpointer_t s2, tb_size_t n)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
return tb_null;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/sh4/memmov.c 0000664 0000000 0000000 00000002744 14671175054 0021607 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file memmov.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#if 1//def TB_ASSEMBLER_IS_GAS
# define TB_LIBC_STRING_IMPL_MEMMOV
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if 1
static tb_pointer_t tb_memmov_impl(tb_pointer_t s1, tb_cpointer_t s2, tb_size_t n)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
return memmove(s1, s2, n);
}
#elif defined(TB_ASSEMBLER_IS_GAS)
static tb_pointer_t tb_memmov_impl(tb_pointer_t s1, tb_cpointer_t s2, tb_size_t n)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
return tb_null;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/sh4/memset.c 0000664 0000000 0000000 00000020617 14671175054 0021600 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file memset.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define TB_LIBC_STRING_IMPL_MEMSET_U8
#if defined(TB_ASSEMBLER_IS_GAS)
# define TB_LIBC_STRING_IMPL_MEMSET_U16
# define TB_LIBC_STRING_IMPL_MEMSET_U32
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#ifdef TB_ASSEMBLER_IS_GAS
static __tb_inline__ tb_void_t tb_memset_impl_u8_opt_v1(tb_byte_t* s, tb_byte_t c, tb_size_t n)
{
}
#endif
#ifdef TB_LIBC_STRING_IMPL_MEMSET_U8
static tb_pointer_t tb_memset_impl(tb_pointer_t s, tb_byte_t c, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s, tb_null);
if (!n) return s;
# if 1
memset(s, c, n);
# elif defined(TB_ASSEMBLER_IS_GAS)
tb_memset_impl_u8_opt_v1(s, (tb_byte_t)c, n);
# else
# error
# endif
return s;
}
#endif
#ifdef TB_ASSEMBLER_IS_GAS
static __tb_inline__ tb_void_t tb_memset_u16_impl_opt_v1(tb_uint16_t* s, tb_uint16_t c, tb_size_t n)
{
/* align by 4-bytes */
if (((tb_size_t)s) & 0x3)
{
*((tb_uint16_t*)s) = c;
s += 2;
n--;
}
tb_size_t l = n & 0x3;
s += (n << 1);
if (!l)
{
n >>= 2;
__tb_asm__ __tb_volatile__
(
"1:\n\t"
"dt %0\n\t" /* i--, i > 0? T = 0 : 1 */
"mov.w %1,@-%2\n\t" /* *--s = c */
"mov.w %1,@-%2\n\t" /* *--s = c */
"mov.w %1,@-%2\n\t" /* *--s = c */
"mov.w %1,@-%2\n\t" /* *--s = c */
"bf 1b\n\t" /* if T == 0 goto label 1: */
: /* no output registers */
: "r" (n), "r" (c), "r" (s) /* constraint: register */
);
}
else if (n >= 4)
{
n >>= 2;
__tb_asm__ __tb_volatile__
(
"1:\n\t" /* fill left data */
"dt %3\n\t"
"mov.w %1,@-%2\n\t"
"bf 1b\n\t"
"2:\n\t" /* fill aligned data by 4 */
"dt %0\n\t" /* i--, i > 0? T = 0 : 1 */
"mov.w %1,@-%2\n\t" /* *--s = c */
"mov.w %1,@-%2\n\t" /* *--s = c */
"mov.w %1,@-%2\n\t" /* *--s = c */
"mov.w %1,@-%2\n\t" /* *--s = c */
"bf 2b\n\t" /* if T == 0 goto label 1: */
: /* no output registers */
: "r" (n), "r" (c), "r" (s), "r" (l) /* constraint: register */
);
}
else
{
__tb_asm__ __tb_volatile__
(
"1:\n\t"
"dt %0\n\t" /* i--, i > 0? T = 0 : 1 */
"mov.w %1,@-%2\n\t" /* *--s = c */
"bf 1b\n\t" /* if T == 0 goto label 1: */
: /* no output registers */
: "r" (n), "r" (c), "r" (s) /* constraint: register */
);
}
}
static __tb_inline__ tb_void_t tb_memset_u16_impl_opt_v2(tb_uint16_t* s, tb_uint16_t c, tb_size_t n)
{
/* align by 4-bytes */
if (((tb_size_t)s) & 0x3)
{
*((tb_uint16_t*)s) = c;
s += 2;
n--;
}
s += n << 1;
__tb_asm__ __tb_volatile__
(
"1:\n\t"
"dt %0\n\t" /* i--, i > 0? T = 0 : 1 */
"mov.w %1,@-%2\n\t" /* *--s = c */
"bf 1b\n\t" /* if T == 0 goto label 1: */
: /* no output registers */
: "r" (n), "r" (c), "r" (s) /* constraint: register */
);
}
#endif
#ifdef TB_LIBC_STRING_IMPL_MEMSET_U16
static tb_pointer_t tb_memset_u16_impl(tb_pointer_t s, tb_uint16_t c, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s, tb_null);
// align by 2-bytes
tb_assert(!(((tb_size_t)s) & 0x1));
if (!n) return s;
# if defined(TB_ASSEMBLER_IS_GAS)
tb_memset_u16_impl_opt_v1(s, c, n);
# else
# error
# endif
return s;
}
#endif
#ifdef TB_ASSEMBLER_IS_GAS
static __tb_inline__ tb_void_t tb_memset_u32_impl_opt_v1(tb_uint32_t* s, tb_uint32_t c, tb_size_t n)
{
tb_size_t l = n & 0x3;
s += (n << 2);
if (!l)
{
n >>= 2;
__tb_asm__ __tb_volatile__
(
"1:\n\t"
"dt %0\n\t" /* i--, i > 0? T = 0 : 1 */
"mov.l %1,@-%2\n\t" /* *--s = c */
"mov.l %1,@-%2\n\t" /* *--s = c */
"mov.l %1,@-%2\n\t" /* *--s = c */
"mov.l %1,@-%2\n\t" /* *--s = c */
"bf 1b\n\t" /* if T == 0 goto label 1: */
: /* no output registers */
: "r" (n), "r" (c), "r" (s) /* constraint: register */
);
}
else
{
__tb_asm__ __tb_volatile__
(
"1:\n\t"
"dt %0\n\t" /* i--, i > 0? T = 0 : 1 */
"mov.l %1,@-%2\n\t" /* *--s = c */
"bf 1b\n\t" /* if T == 0 goto label 1: */
: /* no output registers */
: "r" (n), "r" (c), "r" (s) /* constraint: register */
);
}
}
static __tb_inline__ tb_void_t tb_memset_u32_impl_opt_v2(tb_uint32_t* s, tb_uint32_t c, tb_size_t n)
{
tb_size_t l = n & 0x3;
s += (n << 2);
if (!l)
{
n >>= 2;
__tb_asm__ __tb_volatile__
(
"1:\n\t"
"dt %0\n\t" /* i--, i > 0? T = 0 : 1 */
"mov.l %1,@-%2\n\t" /* *--s = c */
"mov.l %1,@-%2\n\t" /* *--s = c */
"mov.l %1,@-%2\n\t" /* *--s = c */
"mov.l %1,@-%2\n\t" /* *--s = c */
"bf 1b\n\t" /* if T == 0 goto label 1: */
: /* no output registers */
: "r" (n), "r" (c), "r" (s) /* constraint: register */
);
}
else if (n >= 4) /* fixme */
{
n >>= 2;
__tb_asm__ __tb_volatile__
(
"1:\n\t" /* fill the left data */
"dt %3\n\t"
"mov.l %1,@-%2\n\t"
"bf 1b\n\t"
"2:\n\t" /* fill aligned data by 4 */
"dt %0\n\t" /* i--, i > 0? T = 0 : 1 */
"mov.l %1,@-%2\n\t" /* *--s = c */
"mov.l %1,@-%2\n\t" /* *--s = c */
"mov.l %1,@-%2\n\t" /* *--s = c */
"mov.l %1,@-%2\n\t" /* *--s = c */
"bf 2b\n\t" /* if T == 0 goto label 1: */
: /* no output registers */
: "r" (n), "r" (c), "r" (s), "r" (l) /* constraint: register */
);
}
else
{
__tb_asm__ __tb_volatile__
(
"1:\n\t"
"dt %0\n\t" /* i--, i > 0? T = 0 : 1 */
"mov.l %1,@-%2\n\t" /* *--s = c */
"bf 1b\n\t" /* if T == 0 goto label 1: */
: /* no output registers */
: "r" (n), "r" (c), "r" (s) /* constraint: register */
);
}
}
static __tb_inline__ tb_void_t tb_memset_u32_impl_opt_v3(tb_uint32_t* s, tb_uint32_t c, tb_size_t n)
{
s += n << 2;
__tb_asm__ __tb_volatile__
(
"1:\n\t"
"dt %0\n\t" /* i--, i > 0? T = 0 : 1 */
"mov.l %1,@-%2\n\t" /* *--s = c */
"bf 1b\n\t" /* if T == 0 goto label 1: */
: /* no output registers */
: "r" (n), "r" (c), "r" (s) /* constraint: register */
);
}
#endif
#ifdef TB_LIBC_STRING_IMPL_MEMSET_U32
static tb_pointer_t tb_memset_u32_impl(tb_pointer_t s, tb_uint32_t c, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s, tb_null);
// align by 4-bytes
tb_assert(!(((tb_size_t)s) & 0x3));
if (!n) return s;
# if defined(TB_ASSEMBLER_IS_GAS)
tb_memset_u32_impl_opt_v1(s, c, n);
# else
# error
# endif
return s;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/sh4/prefix.h 0000664 0000000 0000000 00000001632 14671175054 0021604 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_LIBC_STRING_IMPL_SH4_PREFIX_H
#define TB_LIBC_STRING_IMPL_SH4_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/libc/string/impl/sh4/strcmp.c 0000664 0000000 0000000 00000002427 14671175054 0021615 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strcmp.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
//# define TB_LIBC_STRING_IMPL_STRCMP
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if 0//def TB_ASSEMBLER_IS_GAS
static tb_long_t tb_strcmp_impl(tb_char_t const* s1, tb_char_t const* s2)
{
tb_assert_and_check_return_val(s1 && s2, 0);
return 0;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/sh4/strcpy.c 0000664 0000000 0000000 00000002435 14671175054 0021630 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strcpy.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
//# define TB_LIBC_STRING_IMPL_STRCPY
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if 0//def TB_ASSEMBLER_IS_GAS
static tb_char_t* tb_strcpy_impl(tb_char_t* s1, tb_char_t const* s2)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
return tb_null;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/sh4/strlen.c 0000664 0000000 0000000 00000002371 14671175054 0021612 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strlen.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
//# define TB_LIBC_STRING_IMPL_STRLEN
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if 0//def TB_ASSEMBLER_IS_GAS
static tb_size_t tb_strlen_impl(tb_char_t const* s)
{
tb_assert_and_check_return_val(s, 0);
return 0;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/sh4/strncmp.c 0000664 0000000 0000000 00000002447 14671175054 0021775 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strncmp.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#if 0//def TB_ASSEMBLER_IS_GAS
# define TB_LIBC_STRING_IMPL_STRNCMP
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if 0//def TB_ASSEMBLER_IS_GAS
static tb_long_t tb_strncmp_impl(tb_char_t const* s1, tb_char_t const* s2, tb_size_t n)
{
tb_assert_and_check_return_val(s1 && s2, 0);
return 0;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/sh4/strncpy.c 0000664 0000000 0000000 00000002455 14671175054 0022010 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strncpy.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
//# define TB_LIBC_STRING_IMPL_STRNCPY
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if 0//def TB_ASSEMBLER_IS_GAS
static tb_char_t* tb_strncpy_impl(tb_char_t* s1, tb_char_t const* s2, tb_size_t n)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
return tb_null;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/sh4/strnlen.c 0000664 0000000 0000000 00000002437 14671175054 0021773 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strnlen.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
//# define TB_LIBC_STRING_IMPL_STRNLEN
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if 0//def TB_ASSEMBLER_IS_GAS
static tb_size_t tb_strnlen_impl(tb_char_t const* s, tb_size_t n)
{
tb_assert_and_check_return_val(s, 0);
if (!n) return 0;
return 0;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/x86/ 0000775 0000000 0000000 00000000000 14671175054 0020063 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/libc/string/impl/x86/memcmp.c 0000664 0000000 0000000 00000002337 14671175054 0021512 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file memcmp.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
//# define TB_LIBC_STRING_IMPL_MEMCMP
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if 0//def TB_ASSEMBLER_IS_GAS
static tb_long_t tb_memcmp_impl(tb_cpointer_t s1, tb_cpointer_t s2, tb_size_t n)
{
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/x86/memcpy.c 0000664 0000000 0000000 00000003423 14671175054 0021523 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file memcpy.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
# define TB_LIBC_STRING_IMPL_MEMCPY
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#ifdef TB_ASSEMBLER_IS_GAS
static tb_pointer_t tb_memcpy_impl(tb_pointer_t s1, tb_cpointer_t s2, tb_size_t n)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
tb_long_t d0, d1, d2;
__tb_asm__ __tb_volatile__
(
" rep; movsl\n"
" movl %4, %%ecx\n"
" andl $3, %%ecx\n"
/* jz is optional. avoids "rep; movsb" with ecx == 0,
* but adds a branch, which is currently (2008) faster */
" jz 1f\n"
" rep; movsb\n"
"1:\n"
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
: "0" (n / 4), "g" (n), "1" ((tb_size_t)s1), "2" ((tb_size_t)s2)
: "memory"
);
return s1;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/x86/memmov.c 0000664 0000000 0000000 00000003532 14671175054 0021532 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file memmov.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
# define TB_LIBC_STRING_IMPL_MEMMOV
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#ifdef TB_ASSEMBLER_IS_GAS
static tb_pointer_t tb_memmov_impl(tb_pointer_t s1, tb_cpointer_t s2, tb_size_t n)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
tb_long_t eax, ecx, esi, edi;
__tb_asm__ __tb_volatile__
(
" movl %%eax, %%edi\n"
" cmpl %%esi, %%eax\n"
" je 2f\n" /* (optional) s2 == s1 -> NOP */
" jb 1f\n" /* s2 > s1 -> simple copy */
" leal -1(%%esi,%%ecx), %%esi\n"
" leal -1(%%eax,%%ecx), %%edi\n"
" std\n"
"1: rep; movsb\n"
" cld\n"
"2:\n"
: "=&c" (ecx), "=&S" (esi), "=&a" (eax), "=&D" (edi)
: "0" (n), "1" (s2), "2" (s1)
: "memory"
);
return (tb_pointer_t)eax;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/x86/memset.c 0000664 0000000 0000000 00000016247 14671175054 0021533 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file memset.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#ifdef TB_ARCH_SSE2
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#if (defined(TB_ASSEMBLER_IS_GAS) && TB_CPU_BIT32) || \
defined(TB_ARCH_SSE2)
# define TB_LIBC_STRING_IMPL_MEMSET_U8
# define TB_LIBC_STRING_IMPL_MEMSET_U16
# define TB_LIBC_STRING_IMPL_MEMSET_U32
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_ASSEMBLER_IS_GAS) && TB_CPU_BIT32
static __tb_inline__ tb_void_t tb_memset_impl_u8_opt_v1(tb_byte_t* s, tb_byte_t c, tb_size_t n)
{
tb_size_t edi;
__tb_asm__ __tb_volatile__
(
// note: the address not align by 4-bytes, but it is also fast.
" cld\n"
" mov %2, %%ecx\n"
" shr $2, %%ecx\n" //!< n >>= 2
" jz 1f\n" //!< goto fill the left bytes if n < 4
" movzx %%al, %%eax\n" //!< 3 bytes, or: and $0xff, %%eax - 5 bytes
" imul $0x01010101, %%eax\n" //!< 6 bytes
" rep; stosl\n" //!< fill 4-bytes
"1: and $3, %2\n" //!< left = n & 0x3
" jz 9f\n" //!< goto end if left == 0
"2:\n"
" mov %2, %%ecx\n"
" rep stosb\n" //!< fill the left bytes (3-bytes)
"9:\n"
: "=&D" (edi)
: "a" (c), "r" (n), "0" (s)
: "memory", "ecx"
);
}
#endif
#ifdef TB_ARCH_SSE2
static __tb_inline__ tb_void_t tb_memset_impl_u8_opt_v2(tb_byte_t* s, tb_byte_t c, tb_size_t n)
{
if (n >= 64)
{
// aligned by 16-bytes
for (; ((tb_size_t)s) & 0x0f; --n) *s++ = c;
// l = n % 64
tb_size_t l = n & 0x3f; n = (n - l) >> 6;
// fill 4 x 16 bytes
__m128i* d = (__m128i*)(s);
__m128i v = _mm_set1_epi8(c);
while (n)
{
_mm_store_si128(d++, v);
_mm_store_si128(d++, v);
_mm_store_si128(d++, v);
_mm_store_si128(d++, v);
--n;
}
s = (tb_byte_t*)(d);
n = l;
}
while (n--) *s++ = c;
}
#endif
#ifdef TB_LIBC_STRING_IMPL_MEMSET_U8
static tb_pointer_t tb_memset_impl(tb_pointer_t s, tb_byte_t c, tb_size_t n)
{
tb_assert_and_check_return_val(s, tb_null);
if (!n) return s;
# if defined(TB_ASSEMBLER_IS_GAS) && TB_CPU_BIT32
tb_memset_impl_u8_opt_v1(s, c, n);
# elif defined(TB_ARCH_SSE2)
tb_memset_impl_u8_opt_v2(s, c, n);
# else
# error
# endif
return s;
}
#endif
#if defined(TB_ASSEMBLER_IS_GAS) && TB_CPU_BIT32
static __tb_inline__ tb_void_t tb_memset_u16_impl_opt_v1(tb_uint16_t* s, tb_uint16_t c, tb_size_t n)
{
// align by 4-bytes
if (((tb_size_t)s) & 0x3)
{
*s++ = c;
--n;
}
__tb_asm__ __tb_volatile__
(
"cld\n\t" // clear the direction bit, s++, not s--
"rep stosw" // *s++ = ax
: // no output registers
: "c" (n), "a" (c), "D" (s) // ecx = n, eax = c, edi = s
);
}
#endif
#ifdef TB_ARCH_SSE2
static __tb_inline__ tb_void_t tb_memset_u16_impl_opt_v2(tb_uint16_t* s, tb_uint16_t c, tb_size_t n)
{
if (n >= 32)
{
// aligned by 16-bytes
for (; ((tb_size_t)s) & 0x0f; --n) *s++ = c;
// l = n % 32
tb_size_t l = n & 0x1f; n = (n - l) >> 5;
// fill 4 x 16 bytes
__m128i* d = (__m128i*)(s);
__m128i v = _mm_set1_epi16(c);
while (n)
{
_mm_store_si128(d++, v);
_mm_store_si128(d++, v);
_mm_store_si128(d++, v);
_mm_store_si128(d++, v);
--n;
}
s = (tb_uint16_t*)(d);
n = l;
}
while (n--) *s++ = c;
}
#endif
#ifdef TB_LIBC_STRING_IMPL_MEMSET_U16
static tb_pointer_t tb_memset_u16_impl(tb_pointer_t s, tb_uint16_t c, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s, tb_null);
// align by 2-bytes
tb_assert(!(((tb_size_t)s) & 0x1));
if (!n) return s;
# if (defined(TB_ASSEMBLER_IS_GAS) && TB_CPU_BIT32) && \
defined(TB_ARCH_SSE2)
if (n < 2049) tb_memset_u16_impl_opt_v2(s, c, n);
else tb_memset_u16_impl_opt_v1(s, c, n);
# elif defined(TB_ASSEMBLER_IS_GAS) && TB_CPU_BIT32
tb_memset_u16_impl_opt_v1(s, c, n);
# elif defined(TB_ARCH_SSE2)
tb_memset_u16_impl_opt_v2(s, c, n);
# else
# error
# endif
return s;
}
#endif
#if defined(TB_ASSEMBLER_IS_GAS) && TB_CPU_BIT32
static __tb_inline__ tb_void_t tb_memset_u32_impl_opt_v1(tb_uint32_t* s, tb_uint32_t c, tb_size_t n)
{
__tb_asm__ __tb_volatile__
(
"cld\n\t" // clear the direction bit, s++, not s--
"rep stosl" // *s++ = eax
: // no output registers
: "c" (n), "a" (c), "D" (s) // ecx = n, eax = c, edi = s
);
}
#endif
#ifdef TB_ARCH_SSE2
static __tb_inline__ tb_void_t tb_memset_u32_impl_opt_v2(tb_uint32_t* s, tb_uint32_t c, tb_size_t n)
{
if (n >= 16)
{
// aligned by 16-bytes
for (; ((tb_size_t)s) & 0x0f; --n) *s++ = c;
// l = n % 16
tb_size_t l = n & 0x0f; n = (n - l) >> 4;
// fill 4 x 16 bytes
__m128i* d = (__m128i*)(s);
__m128i v = _mm_set1_epi32(c);
while (n)
{
_mm_store_si128(d++, v);
_mm_store_si128(d++, v);
_mm_store_si128(d++, v);
_mm_store_si128(d++, v);
--n;
}
s = (tb_uint32_t*)(d);
n = l;
}
while (n--) *s++ = c;
}
#endif
#ifdef TB_LIBC_STRING_IMPL_MEMSET_U32
static tb_pointer_t tb_memset_u32_impl(tb_pointer_t s, tb_uint32_t c, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s, tb_null);
// align by 4-bytes
tb_assert(!(((tb_size_t)s) & 0x3));
if (!n) return s;
# if (defined(TB_ASSEMBLER_IS_GAS) && TB_CPU_BIT32) && \
defined(TB_ARCH_SSE2)
if (n < 2049) tb_memset_u32_impl_opt_v2(s, c, n);
else tb_memset_u32_impl_opt_v1(s, c, n);
# elif defined(TB_ASSEMBLER_IS_GAS) && TB_CPU_BIT32
tb_memset_u32_impl_opt_v1(s, c, n);
# elif defined(TB_ARCH_SSE2)
tb_memset_u32_impl_opt_v2(s, c, n);
# else
# error
# endif
return s;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/x86/prefix.h 0000664 0000000 0000000 00000001632 14671175054 0021533 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_LIBC_STRING_IMPL_x86_PREFIX_H
#define TB_LIBC_STRING_IMPL_x86_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/libc/string/impl/x86/strcmp.c 0000664 0000000 0000000 00000003374 14671175054 0021546 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strcmp.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
//# define TB_LIBC_STRING_IMPL_STRCMP
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if 0//def TB_ASSEMBLER_IS_GAS
static tb_long_t tb_strcmp_impl(tb_char_t const* s1, tb_char_t const* s2)
{
tb_assert_and_check_return_val(s1 && s2, 0);
// FIXME: return is -1, 0, 1
tb_size_t d0, d1;
tb_size_t r;
__tb_asm__ __tb_volatile__
(
"1:\n"
" lodsb\n"
" scasb\n"
" jne 2f\n"
" testb %%al, %%al\n"
" jne 1b\n"
" xorl %%eax, %%eax\n"
" jmp 3f\n"
"2:\n"
" sbbl %%eax, %%eax\n"
" orb $1, %%al\n"
"3:"
: "=a" (r), "=&S" (d0), "=&D" (d1)
: "1" (s1), "2" (s2)
: "memory"
);
return r;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/x86/strcpy.c 0000664 0000000 0000000 00000004124 14671175054 0021554 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strcpy.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
//# define TB_LIBC_STRING_IMPL_STRCPY
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if 0//def TB_ASSEMBLER_IS_GAS
static tb_char_t* tb_strcpy_impl(tb_char_t* s1, tb_char_t const* s2)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
tb_size_t edi, esi, eax;
__tb_asm__ __tb_volatile__
(
// align?
"1:\n"
" movl (%%esi), %%eax\n" // lodsl is too slower, why?
" add $4, %%esi\n"
" movl %%eax, %%edx\n"
" testb %%dl, %%dl\n"
" je 2f\n"
" shr $8, %%edx\n"
" testb %%dl, %%dl\n"
" je 2f\n"
" shr $8, %%edx\n"
" testb %%dl, %%dl\n"
" je 2f\n"
" shr $8, %%edx\n"
" testb %%dl, %%dl\n"
" je 2f\n"
" stosl\n"
" jmp 1b\n"
"2:\n"
" stosb\n"
" testb %%al, %%al\n"
" je 3f\n"
" shr $8, %%eax\n"
" jmp 2b\n"
"3:\n"
: "=&S" (esi), "=&D" (edi)
: "0" (s2), "1" (s1)
: "memory", "eax", "edx"
);
return s1;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/x86/strlcpy.c 0000664 0000000 0000000 00000003275 14671175054 0021736 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strlcpy.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
//# define TB_LIBC_STRING_IMPL_STRLCPY
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if 0//def TB_ASSEMBLER_IS_GAS
static tb_size_t tb_strlcpy_impl(tb_char_t* s1, tb_char_t const* s2, tb_size_t n)
{
tb_assert_and_check_return_val(s1 && s2, 0);
tb_size_t d0, d1, d2, d3;
__tb_asm__ __tb_volatile__
(
"1:\n"
" decl %2\n"
" js 2f\n"
" lodsb\n"
" stosb\n"
" testb %%al, %%al\n"
" jne 1b\n"
" rep\n"
" stosb\n"
"2:"
: "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3)
: "0" (s2), "1" (s1), "2" (n)
: "memory"
);
// FIXME
//return s1;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/x86/strlen.c 0000664 0000000 0000000 00000003517 14671175054 0021544 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strlen.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
//# define TB_LIBC_STRING_IMPL_STRLEN
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if 0//def TB_ASSEMBLER_IS_GAS
static tb_size_t tb_strlen_impl(tb_char_t const* s)
{
tb_assert_and_check_return_val(s, 0);
#if 0
__tb_register__ tb_size_t r = 0;
__tb_asm__ __tb_volatile__
(
"repne\n"
"scasb\n"
"notl %0\n"
"decl %0"
: "=c" (r)
: "D" (s), "a" (0), "0" (0xffffffffu)
: "memory"
);
return r;
#else
__tb_register__ tb_size_t r = 0;
__tb_asm__ __tb_volatile__
(
" movl %1, %0\n"
" decl %0\n"
"1:\n"
" incl %0\n"
" cmpb $0, (%0)\n"
" jne 1b\n"
" subl %1, %0"
: "=a" (r)
: "d" (s)
: "memory"
);
return r;
#endif
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/x86/strncmp.c 0000664 0000000 0000000 00000003535 14671175054 0021723 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strncmp.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#if 0//def TB_ASSEMBLER_IS_GAS
# define TB_LIBC_STRING_IMPL_STRNCMP
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if 0//def TB_ASSEMBLER_IS_GAS
static tb_long_t tb_strncmp_impl(tb_char_t const* s1, tb_char_t const* s2, tb_size_t n)
{
tb_assert_and_check_return_val(s1 && s2, 0);
if (s1 == s2 || !n) return 0;
tb_size_t r;
tb_size_t d0, d1, d2;
__tb_asm__ __tb_volatile__
(
"1:\n"
" decl %3\n"
" js 2f\n"
" lodsb\n"
" scasb\n"
" jne 3f\n"
" testb %%al,%%al\n"
" jne 1b\n"
"2:\n"
" xorl %%eax,%%eax\n"
" jmp 4f\n"
"3:\n"
" sbbl %%eax,%%eax\n"
" orb $1,%%al\n"
"4:"
: "=a" (r), "=&S" (d0), "=&D" (d1), "=&c" (d2)
: "1" (s1), "2" (s2), "3" (n)
: "memory"
);
return r;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/x86/strncpy.c 0000664 0000000 0000000 00000003265 14671175054 0021737 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strncpy.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
//# define TB_LIBC_STRING_IMPL_STRNCPY
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if 0//def TB_ASSEMBLER_IS_GAS
static tb_char_t* tb_strncpy_impl(tb_char_t* s1, tb_char_t const* s2, tb_size_t n)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
tb_size_t d0, d1, d2, d3;
__tb_asm__ __tb_volatile__
(
"1:\n"
" decl %2\n"
" js 2f\n"
" lodsb\n"
" stosb\n"
" testb %%al, %%al\n"
" jne 1b\n"
" rep\n"
" stosb\n"
"2:"
: "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3)
: "0" (s2), "1" (s1), "2" (n)
: "memory"
);
return s1;
}
#endif
tbox-1.7.6/src/tbox/libc/string/impl/x86/strnlen.c 0000664 0000000 0000000 00000003311 14671175054 0021712 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strnlen.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
//# define TB_LIBC_STRING_IMPL_STRNLEN
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if 0//def TB_ASSEMBLER_IS_GAS
static tb_size_t tb_strnlen_impl(tb_char_t const* s, tb_size_t n)
{
tb_assert_and_check_return_val(s, 0);
if (!n) return 0;
__tb_register__ tb_size_t r = 0;
__tb_asm__ __tb_volatile__
(
" movl %1, %0\n"
" decl %0\n"
"1:\n"
" incl %0\n"
" test %2, %2\n"
" je 2f\n"
" decl %2\n"
" cmpb $0, (%0)\n"
" jne 1b\n"
"2:\n"
" subl %1, %0"
: "=a" (r)
: "d" (s), "c"(n)
: "memory"
);
return r;
}
#endif
tbox-1.7.6/src/tbox/libc/string/memcmp.c 0000664 0000000 0000000 00000006052 14671175054 0020122 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file memcmp.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#include "../../memory/impl/prefix.h"
#ifndef TB_CONFIG_LIBC_HAVE_MEMCMP
# if defined(TB_ARCH_x86)
# include "impl/x86/memcmp.c"
# elif defined(TB_ARCH_ARM)
# include "impl/arm/memcmp.c"
# elif defined(TB_ARCH_SH4)
# include "impl/sh4/memcmp.c"
# endif
#else
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_LIBC_HAVE_MEMCMP)
static tb_long_t tb_memcmp_impl(tb_cpointer_t s1, tb_cpointer_t s2, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s1 && s2, 0);
// done
return memcmp(s1, s2, n);
}
#elif !defined(TB_LIBC_STRING_IMPL_MEMCMP)
static tb_long_t tb_memcmp_impl(tb_cpointer_t s1, tb_cpointer_t s2, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s1 && s2, 0);
// equal or empty?
if (s1 == s2 || !n) return 0;
// done
tb_long_t r = 0;
tb_byte_t const* p1 = (tb_byte_t const *)s1;
tb_byte_t const* p2 = (tb_byte_t const *)s2;
while (n-- && ((r = ((tb_long_t)(*p1++)) - *p2++) == 0)) ;
return r;
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_long_t tb_memcmp_(tb_cpointer_t s1, tb_cpointer_t s2, tb_size_t n)
{
// done
return tb_memcmp_impl(s1, s2, n);
}
tb_long_t tb_memcmp(tb_cpointer_t s1, tb_cpointer_t s2, tb_size_t n)
{
// check
#ifdef __tb_debug__
{
// overflow?
tb_size_t n1 = tb_pool_data_size(s1);
if (n1 && n > n1)
{
tb_trace_i("[memcmp]: [overflow]: [%p, %lu] ?= [%p, %lu]", s2, n, s1, n1);
tb_backtrace_dump("[memcmp]: [overflow]: ", tb_null, 10);
tb_pool_data_dump(s1, tb_true, "\t[malloc]: [from]: ");
tb_abort();
}
// overflow?
tb_size_t n2 = tb_pool_data_size(s2);
if (n2 && n > n2)
{
tb_trace_i("[memcmp]: [overflow]: [%p, %lu(%lu)] ?= [%p, %lu]", s2, n, n2, s1, n1);
tb_backtrace_dump("[memcmp]: [overflow]: ", tb_null, 10);
tb_pool_data_dump(s2, tb_true, "\t[malloc]: [from]: ");
tb_abort();
}
}
#endif
// done
return tb_memcmp_impl(s1, s2, n);
}
tbox-1.7.6/src/tbox/libc/string/memcpy.c 0000664 0000000 0000000 00000007634 14671175054 0020145 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file memcpy.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#include "../../memory/impl/prefix.h"
#ifndef TB_CONFIG_LIBC_HAVE_MEMCPY
# if defined(TB_ARCH_x86)
# include "impl/x86/memcpy.c"
# elif defined(TB_ARCH_ARM)
# include "impl/arm/memcpy.c"
# elif defined(TB_ARCH_SH4)
# include "impl/sh4/memcpy.c"
# endif
#else
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_LIBC_HAVE_MEMCPY)
static tb_pointer_t tb_memcpy_impl(tb_pointer_t s1, tb_cpointer_t s2, tb_size_t n)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
return memcpy(s1, s2, n);
}
#elif !defined(TB_LIBC_STRING_IMPL_MEMCPY)
static tb_pointer_t tb_memcpy_impl(tb_pointer_t s1, tb_cpointer_t s2, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s1 && s2, tb_null);
#ifdef __tb_small__
__tb_register__ tb_byte_t* p1 = (tb_byte_t*)s1;
__tb_register__ tb_byte_t const* p2 = (tb_byte_t const*)s2;
if (p1 == p2 || !n) return s1;
while (n--) *p1++ = *p2++;
return s1;
#else
__tb_register__ tb_byte_t* p1 = (tb_byte_t*)s1;
__tb_register__ tb_byte_t const* p2 = (tb_byte_t const*)s2;
if (p1 == p2 || !n) return s1;
tb_size_t l = n & 0x3; n = (n - l) >> 2;
while (n--)
{
p1[0] = p2[0];
p1[1] = p2[1];
p1[2] = p2[2];
p1[3] = p2[3];
p1 += 4;
p2 += 4;
}
while (l--) *p1++ = *p2++;
return s1;
#endif /* __tb_small__ */
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_pointer_t tb_memcpy_(tb_pointer_t s1, tb_cpointer_t s2, tb_size_t n)
{
// done
return tb_memcpy_impl(s1, s2, n);
}
tb_pointer_t tb_memcpy(tb_pointer_t s1, tb_cpointer_t s2, tb_size_t n)
{
// check
#ifdef __tb_debug__
{
// overflow dst?
tb_size_t n1 = tb_pool_data_size(s1);
if (n1 && n > n1)
{
tb_trace_i("[memcpy]: [overflow]: [%p, %lu] => [%p, %lu]", s2, n, s1, n1);
tb_backtrace_dump("[memcpy]: [overflow]: [dst]: ", tb_null, 10);
tb_pool_data_dump(s1, tb_true, "\t[malloc]: [from]: ");
tb_abort();
}
// overflow src?
tb_size_t n2 = tb_pool_data_size(s2);
if (n2 && n > n2)
{
tb_trace_i("[memcpy]: [overflow]: [%p, %lu(%lu)] => [%p, %lu]", s2, n, n2, s1, n1);
tb_backtrace_dump("[memcpy]: [overflow]: [src] ", tb_null, 10);
tb_pool_data_dump(s2, tb_true, "\t[malloc]: [from]: ");
tb_abort();
}
// overlap?
if (((tb_byte_t*)s2 >= (tb_byte_t*)s1 && (tb_byte_t*)s2 < (tb_byte_t*)s1 + n)
|| ((tb_byte_t*)s1 >= (tb_byte_t*)s2 && (tb_byte_t*)s1 < (tb_byte_t*)s2 + n))
{
tb_trace_i("[memcpy]: [overlap]: [%p, %lu] => [%p, %lu]", s2, n, s1, n);
tb_backtrace_dump("[memcpy]: [overlap]: ", tb_null, 10);
tb_pool_data_dump(s1, tb_true, "\t[malloc]: [from]: ");
tb_abort();
}
}
#endif
// done
return tb_memcpy_impl(s1, s2, n);
}
tbox-1.7.6/src/tbox/libc/string/memdup.c 0000664 0000000 0000000 00000003521 14671175054 0020131 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file memdup.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#include "../../memory/impl/prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_pointer_t tb_memdup_(tb_cpointer_t s, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s, tb_null);
// done
__tb_register__ tb_pointer_t p = tb_malloc(n);
if (p) tb_memcpy_(p, s, n);
return p;
}
tb_pointer_t tb_memdup(tb_cpointer_t s, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s, tb_null);
// check
#ifdef __tb_debug__
{
// overflow?
tb_size_t size = tb_pool_data_size(s);
if (size && n > size)
{
tb_trace_i("[memdup]: [overflow]: [%p, %lu] from [%p, %lu]", s, n, s, size);
tb_backtrace_dump("[memdup]: [overflow]: ", tb_null, 10);
tb_pool_data_dump(s, tb_true, "\t[malloc]: [from]: ");
tb_abort();
}
}
#endif
// done
__tb_register__ tb_pointer_t p = tb_malloc(n);
if (p) tb_memcpy(p, s, n);
return p;
}
tbox-1.7.6/src/tbox/libc/string/memmem.c 0000664 0000000 0000000 00000004657 14671175054 0020132 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file memmem.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#include "../../memory/impl/prefix.h"
#ifdef TB_CONFIG_LIBC_HAVE_MEMMEM
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_LIBC_HAVE_MEMMEM)
static tb_pointer_t tb_memmem_impl(tb_cpointer_t s1, tb_size_t n1, tb_cpointer_t s2, tb_size_t n2)
{
// check
tb_assert_and_check_return_val(s1 && s2, tb_null);
// done
return memmem(s1, n1, s2, n2);
}
#elif !defined(TB_LIBC_STRING_IMPL_MEMMEM)
static tb_pointer_t tb_memmem_impl(tb_cpointer_t s1, tb_size_t n1, tb_cpointer_t s2, tb_size_t n2)
{
// check
tb_assert_and_check_return_val(s1 && s2, tb_null);
// find empty data?
if (!n2) return (tb_pointer_t)s1;
// done
if (n1 >= n2)
{
tb_size_t n = 0;
tb_byte_t const* ph = (tb_byte_t const*)s1;
tb_byte_t const* pn = (tb_byte_t const*)s2;
tb_byte_t const* plast = ph + (n1 - n2);
do
{
n = 0;
while (ph[n] == pn[n])
{
// found?
if (++n == n2) return (tb_pointer_t)ph;
}
} while (++ph <= plast);
}
// not found?
return tb_null;
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_pointer_t tb_memmem_(tb_cpointer_t s1, tb_size_t n1, tb_cpointer_t s2, tb_size_t n2)
{
// done
return tb_memmem_impl(s1, n1, s2, n2);
}
tb_pointer_t tb_memmem(tb_cpointer_t s1, tb_size_t n1, tb_cpointer_t s2, tb_size_t n2)
{
// check
#ifdef __tb_debug__
// TODO
#endif
// done
return tb_memmem_impl(s1, n1, s2, n2);
}
tbox-1.7.6/src/tbox/libc/string/memmov.c 0000664 0000000 0000000 00000006162 14671175054 0020146 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file memmov.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#include "../../memory/impl/prefix.h"
#ifndef TB_CONFIG_LIBC_HAVE_MEMMOVE
# if defined(TB_ARCH_x86)
# include "impl/x86/memmov.c"
# elif defined(TB_ARCH_ARM)
# include "impl/arm/memmov.c"
# elif defined(TB_ARCH_SH4)
# include "impl/sh4/memmov.c"
# endif
#else
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_LIBC_HAVE_MEMMOVE)
static tb_pointer_t tb_memmov_impl(tb_pointer_t s1, tb_cpointer_t s2, tb_size_t n)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
return memmove(s1, s2, n);
}
#elif !defined(TB_LIBC_STRING_IMPL_MEMMOV)
static tb_pointer_t tb_memmov_impl(tb_pointer_t s1, tb_cpointer_t s2, tb_size_t n)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
__tb_register__ tb_byte_t* s = (tb_byte_t*)s1;
__tb_register__ tb_byte_t const* p = (tb_byte_t const*)s2;
if (p >= s)
{
while (n)
{
*s++ = *p++;
--n;
}
}
else
{
while (n)
{
--n;
s[n] = p[n];
}
}
return s1;
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_pointer_t tb_memmov_(tb_pointer_t s1, tb_cpointer_t s2, tb_size_t n)
{
// done
return tb_memmov_impl(s1, s2, n);
}
tb_pointer_t tb_memmov(tb_pointer_t s1, tb_cpointer_t s2, tb_size_t n)
{
// check
#ifdef __tb_debug__
{
// overflow dst?
tb_size_t n1 = tb_pool_data_size(s1);
if (n1 && n > n1)
{
tb_trace_i("[memmov]: [overflow]: [%p, %lu] => [%p, %lu]", s2, n, s1, n1);
tb_backtrace_dump("[memmov]: [overflow]: ", tb_null, 10);
tb_pool_data_dump(s1, tb_true, "\t[malloc]: [from]: ");
tb_abort();
}
// overflow src?
tb_size_t n2 = tb_pool_data_size(s2);
if (n2 && n > n2)
{
tb_trace_i("[memmov]: [overflow]: [%p, %lu] => [%p, %lu]", s2, n, s1, n1);
tb_backtrace_dump("[memmov]: [overflow]: ", tb_null, 10);
tb_pool_data_dump(s2, tb_true, "\t[malloc]: [from]: ");
tb_abort();
}
}
#endif
// done
return tb_memmov_impl(s1, s2, n);
}
tbox-1.7.6/src/tbox/libc/string/memset.c 0000664 0000000 0000000 00000017670 14671175054 0020146 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file memset.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#include "../../utils/utils.h"
#include "../../memory/impl/prefix.h"
#ifndef TB_CONFIG_LIBC_HAVE_MEMSET
# if defined(TB_ARCH_x86)
# include "impl/x86/memset.c"
# elif defined(TB_ARCH_x64)
# include "impl/x86/memset.c"
# elif defined(TB_ARCH_ARM)
# include "impl/arm/memset.c"
# elif defined(TB_ARCH_SH4)
# include "impl/sh4/memset.c"
# endif
#else
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_LIBC_HAVE_MEMSET)
static tb_pointer_t tb_memset_impl(tb_pointer_t s, tb_byte_t c, tb_size_t n)
{
tb_assert_and_check_return_val(s, tb_null);
return memset(s, c, n);
}
#elif !defined(TB_LIBC_STRING_IMPL_MEMSET_U8)
static tb_pointer_t tb_memset_impl(tb_pointer_t s, tb_byte_t c, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s, tb_null);
// no size?
tb_check_return_val(n, s);
// init
__tb_register__ tb_byte_t* p = (tb_byte_t*)s;
// done
#ifdef __tb_small__
while (n--) *p++ = c;
#else
tb_size_t l = n & 0x3; n = (n - l) >> 2;
while (n--)
{
p[0] = c;
p[1] = c;
p[2] = c;
p[3] = c;
p += 4;
}
while (l--) *p++ = c;
#endif
return s;
}
#endif
#if !defined(TB_LIBC_STRING_IMPL_MEMSET_U16) && !defined(TB_CONFIG_MICRO_ENABLE)
static tb_pointer_t tb_memset_u16_impl(tb_pointer_t s, tb_uint16_t c, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s, tb_null);
// no size?
tb_check_return_val(n, s);
// must be aligned by 2-bytes
tb_assert(!(((tb_size_t)s) & 0x1));
// init
__tb_register__ tb_uint16_t* p = (tb_uint16_t*)s;
// done
#ifdef __tb_small__
while (n--) *p++ = c;
#else
tb_size_t l = n & 0x3; n = (n - l) >> 2;
while (n--)
{
p[0] = c;
p[1] = c;
p[2] = c;
p[3] = c;
p += 4;
}
while (l--) *p++ = c;
#endif
// ok?
return s;
}
#endif
#if !defined(TB_LIBC_STRING_IMPL_MEMSET_U24) && !defined(TB_CONFIG_MICRO_ENABLE)
static tb_pointer_t tb_memset_u24_impl(tb_pointer_t s, tb_uint32_t c, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s, tb_null);
// no size?
tb_check_return_val(n, s);
// init
__tb_register__ tb_byte_t* p = (tb_byte_t*)s;
__tb_register__ tb_byte_t* e = p + (n * 3);
// done
#ifdef __tb_small__
for (; p < e; p += 3) tb_bits_set_u24_ne(p, c);
#else
tb_size_t l = n & 0x3; n -= l;
while (p < e)
{
tb_bits_set_u24_ne(p + 0, c);
tb_bits_set_u24_ne(p + 3, c);
tb_bits_set_u24_ne(p + 6, c);
tb_bits_set_u24_ne(p + 9, c);
p += 12;
}
while (l--)
{
tb_bits_set_u24_ne(p, c);
p += 3;
}
#endif
// ok?
return s;
}
#endif
#if !defined(TB_LIBC_STRING_IMPL_MEMSET_U32) && !defined(TB_CONFIG_MICRO_ENABLE)
static tb_pointer_t tb_memset_u32_impl(tb_pointer_t s, tb_uint32_t c, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s, tb_null);
// no size?
tb_check_return_val(n, s);
// must be aligned by 4-bytes
tb_assert(!(((tb_size_t)s) & 0x3));
// init
__tb_register__ tb_uint32_t* p = (tb_uint32_t*)s;
// done
#ifdef __tb_small__
while (n--) *p++ = c;
#else
tb_size_t l = n & 0x3; n = (n - l) >> 2;
while (n--)
{
p[0] = c;
p[1] = c;
p[2] = c;
p[3] = c;
p += 4;
}
while (l--) *p++ = c;
#endif
// ok?
return s;
}
#endif
#if !defined(TB_LIBC_STRING_IMPL_MEMSET_U64) && !defined(TB_CONFIG_MICRO_ENABLE)
static tb_pointer_t tb_memset_u64_impl(tb_pointer_t s, tb_uint64_t c, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s, tb_null);
// no size?
tb_check_return_val(n, s);
// must be aligned by 8-bytes
tb_assert(!(((tb_size_t)s) & 0x7));
// init
__tb_register__ tb_uint64_t* p = (tb_uint64_t*)s;
// done
#ifdef __tb_small__
while (n--) *p++ = c;
#else
tb_size_t l = n & 0x3; n = (n - l) >> 2;
while (n--)
{
p[0] = c;
p[1] = c;
p[2] = c;
p[3] = c;
p += 4;
}
while (l--) *p++ = c;
#endif
// ok?
return s;
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_pointer_t tb_memset_(tb_pointer_t s, tb_byte_t c, tb_size_t n)
{
// done
return tb_memset_impl(s, c, n);
}
tb_pointer_t tb_memset(tb_pointer_t s, tb_byte_t c, tb_size_t n)
{
// check
#ifdef __tb_debug__
{
// overflow?
tb_size_t size = tb_pool_data_size(s);
if (size && n > size)
{
tb_trace_i("[memset]: [overflow]: [%#x x %lu] => [%p, %lu]", c, n, s, size);
tb_backtrace_dump("[memset]: [overflow]: ", tb_null, 10);
tb_pool_data_dump(s, tb_true, "\t[malloc]: [from]: ");
tb_abort();
}
}
#endif
// done
return tb_memset_impl(s, c, n);
}
#ifndef TB_CONFIG_MICRO_ENABLE
tb_pointer_t tb_memset_u16(tb_pointer_t s, tb_uint16_t c, tb_size_t n)
{
// check
#ifdef __tb_debug__
{
// overflow?
tb_size_t size = tb_pool_data_size(s);
if (size && (n << 1) > size)
{
tb_trace_i("[memset_u16]: [overflow]: [%#x x %lu x 2] => [%p, %lu]", c, n, s, size);
tb_backtrace_dump("[memset_u16]: [overflow]: ", tb_null, 10);
tb_pool_data_dump(s, tb_true, "\t[malloc]: [from]: ");
tb_abort();
}
}
#endif
// done
return tb_memset_u16_impl(s, c, n);
}
tb_pointer_t tb_memset_u24(tb_pointer_t s, tb_uint32_t c, tb_size_t n)
{
// check
#ifdef __tb_debug__
{
// overflow?
tb_size_t size = tb_pool_data_size(s);
if (size && (n * 3) > size)
{
tb_trace_i("[memset_u24]: [overflow]: [%#x x %lu x 3] => [%p, %lu]", c, n, s, size);
tb_pool_data_dump(s, tb_true, "\t[malloc]: [from]: ");
tb_abort();
}
}
#endif
// done
return tb_memset_u24_impl(s, c, n);
}
tb_pointer_t tb_memset_u32(tb_pointer_t s, tb_uint32_t c, tb_size_t n)
{
// check
#ifdef __tb_debug__
{
// overflow?
tb_size_t size = tb_pool_data_size(s);
if (size && (n << 2) > size)
{
tb_trace_i("[memset_u32]: [overflow]: [%#x x %lu x 4] => [%p, %lu]", c, n, s, size);
tb_backtrace_dump("[memset_u32]: [overflow]: ", tb_null, 10);
tb_pool_data_dump(s, tb_true, "\t[malloc]: [from]: ");
tb_abort();
}
}
#endif
// done
return tb_memset_u32_impl(s, c, n);
}
tb_pointer_t tb_memset_u64(tb_pointer_t s, tb_uint64_t c, tb_size_t n)
{
// check
#ifdef __tb_debug__
{
// overflow?
tb_size_t size = tb_pool_data_size(s);
if (size && (n << 3) > size)
{
tb_trace_i("[memset_u64]: [overflow]: [%#llx x %lu x 4] => [%p, %lu]", c, n, s, size);
tb_backtrace_dump("[memset_u64]: [overflow]: ", tb_null, 10);
tb_pool_data_dump(s, tb_true, "\t[malloc]: [from]: ");
tb_abort();
}
}
#endif
// done
return tb_memset_u64_impl(s, c, n);
}
#endif
tbox-1.7.6/src/tbox/libc/string/prefix.h 0000664 0000000 0000000 00000001610 14671175054 0020141 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_LIBC_STRING_PREFIX_H
#define TB_LIBC_STRING_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/libc/string/strcat.c 0000664 0000000 0000000 00000002633 14671175054 0020145 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strcat.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#ifdef TB_CONFIG_LIBC_HAVE_STRCAT
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
#ifdef TB_CONFIG_LIBC_HAVE_STRCAT
tb_char_t* tb_strcat(tb_char_t* s1, tb_char_t const* s2)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
return strcat(s1, s2);
}
#else
tb_char_t* tb_strcat(tb_char_t* s1, tb_char_t const* s2)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
__tb_register__ tb_char_t* s = s1;
while (*s++); --s;
while (!(*s++ = *s2++));
return s1;
}
#endif
tbox-1.7.6/src/tbox/libc/string/strchr.c 0000664 0000000 0000000 00000002562 14671175054 0020153 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strchr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#ifdef TB_CONFIG_LIBC_HAVE_STRCHR
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
#ifdef TB_CONFIG_LIBC_HAVE_STRCHR
tb_char_t* tb_strchr(tb_char_t const* s, tb_char_t c)
{
tb_assert(s);
return (tb_char_t*)strchr(s, c);
}
#else
tb_char_t* tb_strchr(tb_char_t const* s, tb_char_t c)
{
tb_assert_and_check_return_val(s, tb_null);
while (*s)
{
if (*s == c) return (tb_char_t* )s;
s++;
}
return tb_null;
}
#endif
tbox-1.7.6/src/tbox/libc/string/strcmp.c 0000664 0000000 0000000 00000004106 14671175054 0020152 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strcmp.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#ifndef TB_CONFIG_LIBC_HAVE_STRCMP
# if defined(TB_ARCH_x86)
# include "impl/x86/strcmp.c"
# elif defined(TB_ARCH_ARM)
# include "impl/arm/strcmp.c"
# elif defined(TB_ARCH_SH4)
# include "impl/sh4/strcmp.c"
# endif
#else
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_LIBC_HAVE_STRCMP)
static tb_long_t tb_strcmp_impl(tb_char_t const* s1, tb_char_t const* s2)
{
if (s1 == s2) return 0;
tb_assert_and_check_return_val(s1 && s2, -1);
return strcmp(s1, s2);
}
#elif !defined(TB_LIBC_STRING_IMPL_STRCMP)
static tb_long_t tb_strcmp_impl(tb_char_t const* s1, tb_char_t const* s2)
{
if (s1 == s2) return 0;
tb_assert_and_check_return_val(s1 && s2, -1);
tb_long_t r = 0;
while (((r = ((tb_long_t)(*((tb_byte_t *)s1))) - *((tb_byte_t *)s2++)) == 0) && *s1++);
return r;
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_long_t tb_strcmp(tb_char_t const* s1, tb_char_t const* s2)
{
#ifdef __tb_debug__
{
// check overflow?
tb_strlen(s1);
tb_strlen(s2);
}
#endif
return tb_strcmp_impl(s1, s2);
}
tbox-1.7.6/src/tbox/libc/string/strcpy.c 0000664 0000000 0000000 00000005321 14671175054 0020166 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strcpy.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#include "../../memory/impl/prefix.h"
#ifndef TB_CONFIG_LIBC_HAVE_STRCPY
# if defined(TB_ARCH_x86)
# include "impl/x86/strcpy.c"
# elif defined(TB_ARCH_ARM)
# include "impl/arm/strcpy.c"
# elif defined(TB_ARCH_SH4)
# include "impl/sh4/strcpy.c"
# endif
#else
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_LIBC_HAVE_STRCPY)
static tb_char_t* tb_strcpy_impl(tb_char_t* s1, tb_char_t const* s2)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
return strcpy(s1, s2);
}
#elif !defined(TB_LIBC_STRING_IMPL_STRCPY)
static tb_char_t* tb_strcpy_impl(tb_char_t* s1, tb_char_t const* s2)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
__tb_register__ tb_char_t* s = s1;
if (s1 == s2) return s;
#if 1
tb_memcpy(s1, s2, tb_strlen(s2) + 1);
#elif defined(__tb_small__)
while ((*s++ = *s2++)) ;
#else
while (1)
{
if (!(s1[0] = s2[0])) break;
if (!(s1[1] = s2[1])) break;
if (!(s1[2] = s2[2])) break;
if (!(s1[3] = s2[3])) break;
s1 += 4;
s2 += 4;
}
#endif
return s;
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_char_t* tb_strcpy(tb_char_t* s1, tb_char_t const* s2)
{
// check
#ifdef __tb_debug__
{
// overflow dst?
tb_size_t n2 = tb_strlen(s2);
// strcpy overflow?
tb_size_t n1 = tb_pool_data_size(s1);
if (n1 && n2 + 1 > n1)
{
tb_trace_i("[strcpy]: [overflow]: [%p, %lu] => [%p, %lu]", s2, n2, s1, n1);
tb_backtrace_dump("[strcpy]: [overflow]: ", tb_null, 10);
tb_pool_data_dump(s2, tb_true, "\t[malloc]: [from]: ");
tb_abort();
}
}
#endif
// done
return tb_strcpy_impl(s1, s2);
}
tbox-1.7.6/src/tbox/libc/string/strdup.c 0000664 0000000 0000000 00000002456 14671175054 0020171 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strdup.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_char_t* tb_strdup(tb_char_t const* s)
{
// check
tb_assert_and_check_return_val(s, tb_null);
// make
__tb_register__ tb_size_t n = tb_strlen(s);
__tb_register__ tb_char_t* p = tb_malloc_cstr(n + 1);
tb_assert_and_check_return_val(p, tb_null);
// copy
tb_memcpy(p, s, n);
// end
p[n] = '\0';
// ok
return p;
}
tbox-1.7.6/src/tbox/libc/string/strichr.c 0000664 0000000 0000000 00000002456 14671175054 0020326 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strichr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_char_t* tb_strichr(tb_char_t const* s, tb_char_t c)
{
// check
tb_assert_and_check_return_val(s, tb_null);
// init
tb_byte_t const* p = (tb_byte_t const*)s;
tb_byte_t b = tb_tolower((tb_byte_t)c);
// find
while (*p)
{
if (tb_tolower(*p) == b) return (tb_char_t*)p;
p++;
}
return tb_null;
}
tbox-1.7.6/src/tbox/libc/string/stricmp.c 0000664 0000000 0000000 00000003704 14671175054 0020326 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file stricmp.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#ifdef TB_CONFIG_LIBC_HAVE_STRCASECMP
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#ifdef TB_CONFIG_LIBC_HAVE_STRCASECMP
static tb_long_t tb_stricmp_impl(tb_char_t const* s1, tb_char_t const* s2)
{
if (s1 == s2) return 0;
tb_assert_and_check_return_val(s1 && s2, -1);
#ifdef TB_COMPILER_IS_MSVC
return _stricmp(s1, s2);
#else
return strcasecmp(s1, s2);
#endif
}
#else
static tb_long_t tb_stricmp_impl(tb_char_t const* s1, tb_char_t const* s2)
{
if (s1 == s2) return 0;
tb_assert_and_check_return_val(s1 && s2, -1);
tb_long_t r = 0;
while (((s1 == s2) || !(r = ((tb_long_t)(tb_tolower(*((tb_byte_t* )s1)))) - tb_tolower(*((tb_byte_t* )s2)))) && (++s2, *s1++));
return r;
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_long_t tb_stricmp(tb_char_t const* s1, tb_char_t const* s2)
{
#ifdef __tb_debug__
{
// check overflow?
tb_strlen(s1);
tb_strlen(s2);
}
#endif
return tb_stricmp_impl(s1, s2);
}
tbox-1.7.6/src/tbox/libc/string/string.h 0000664 0000000 0000000 00000015750 14671175054 0020164 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file string.h
* @ingroup libc
*
*/
#ifndef TB_LIBC_STRING_H
#define TB_LIBC_STRING_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// memset_ptr
#if TB_CPU_BIT64
# define tb_memset_ptr(s, p, n) tb_memset_u64(s, (tb_uint64_t)(p), n)
#else
# define tb_memset_ptr(s, p, n) tb_memset_u32(s, (tb_uint32_t)(p), n)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
// memset
tb_pointer_t tb_memset(tb_pointer_t s, tb_byte_t c, tb_size_t n);
tb_pointer_t tb_memset_(tb_pointer_t s, tb_byte_t c, tb_size_t n);
tb_pointer_t tb_memset_u16(tb_pointer_t s, tb_uint16_t c, tb_size_t n);
tb_pointer_t tb_memset_u24(tb_pointer_t s, tb_uint32_t c, tb_size_t n);
tb_pointer_t tb_memset_u32(tb_pointer_t s, tb_uint32_t c, tb_size_t n);
tb_pointer_t tb_memset_u64(tb_pointer_t s, tb_uint64_t c, tb_size_t n);
// memdup
tb_pointer_t tb_memdup(tb_cpointer_t s, tb_size_t n);
tb_pointer_t tb_memdup_(tb_cpointer_t s, tb_size_t n);
// memcpy
tb_pointer_t tb_memcpy(tb_pointer_t s1, tb_cpointer_t s2, tb_size_t n);
tb_pointer_t tb_memcpy_(tb_pointer_t s1, tb_cpointer_t s2, tb_size_t n);
// memmov
tb_pointer_t tb_memmov(tb_pointer_t s1, tb_cpointer_t s2, tb_size_t n);
tb_pointer_t tb_memmov_(tb_pointer_t s1, tb_cpointer_t s2, tb_size_t n);
// memcmp
tb_long_t tb_memcmp(tb_cpointer_t s1, tb_cpointer_t s2, tb_size_t n);
tb_long_t tb_memcmp_(tb_cpointer_t s1, tb_cpointer_t s2, tb_size_t n);
// memmem
tb_pointer_t tb_memmem(tb_cpointer_t s1, tb_size_t n1, tb_cpointer_t s2, tb_size_t n2);
tb_pointer_t tb_memmem_(tb_cpointer_t s1, tb_size_t n1, tb_cpointer_t s2, tb_size_t n2);
// strlen
tb_size_t tb_strlen(tb_char_t const* s);
tb_size_t tb_strnlen(tb_char_t const* s, tb_size_t n);
// strdup
tb_char_t* tb_strdup(tb_char_t const* s);
tb_char_t* tb_strndup(tb_char_t const* s, tb_size_t n);
// strcat
tb_char_t* tb_strcat(tb_char_t* s1, tb_char_t const* s2);
tb_char_t* tb_strncat(tb_char_t* s1, tb_char_t const* s2, tb_size_t n);
// strcpy
tb_char_t* tb_strcpy(tb_char_t* s1, tb_char_t const* s2);
tb_char_t* tb_strncpy(tb_char_t* s1, tb_char_t const* s2, tb_size_t n);
tb_size_t tb_strlcpy(tb_char_t* s1, tb_char_t const* s2, tb_size_t n);
// strcmp
tb_long_t tb_strcmp(tb_char_t const* s1, tb_char_t const* s2);
tb_long_t tb_strncmp(tb_char_t const* s1, tb_char_t const* s2, tb_size_t n);
tb_long_t tb_stricmp(tb_char_t const* s1, tb_char_t const* s2);
tb_long_t tb_strnicmp(tb_char_t const* s1, tb_char_t const* s2, tb_size_t n);
// strchr
tb_char_t* tb_strchr(tb_char_t const* s, tb_char_t c);
tb_char_t* tb_strichr(tb_char_t const* s, tb_char_t c);
tb_char_t* tb_strnchr(tb_char_t const* s, tb_size_t n, tb_char_t c);
tb_char_t* tb_strnichr(tb_char_t const* s, tb_size_t n, tb_char_t c);
// strrchr
tb_char_t* tb_strrchr(tb_char_t const* s, tb_char_t c);
tb_char_t* tb_strirchr(tb_char_t const* s, tb_char_t c);
tb_char_t* tb_strnrchr(tb_char_t const* s, tb_size_t n, tb_char_t c);
tb_char_t* tb_strnirchr(tb_char_t const* s, tb_size_t n, tb_char_t c);
// strstr
tb_char_t* tb_strstr(tb_char_t const* s1, tb_char_t const* s2);
tb_char_t* tb_stristr(tb_char_t const* s1, tb_char_t const* s2);
tb_char_t* tb_strnstr(tb_char_t const* s1, tb_size_t n1, tb_char_t const* s2);
tb_char_t* tb_strnistr(tb_char_t const* s1, tb_size_t n1, tb_char_t const* s2);
// strrstr
tb_char_t* tb_strrstr(tb_char_t const* s1, tb_char_t const* s2);
tb_char_t* tb_strirstr(tb_char_t const* s1, tb_char_t const* s2);
tb_char_t* tb_strnrstr(tb_char_t const* s1, tb_size_t n1, tb_char_t const* s2);
tb_char_t* tb_strnirstr(tb_char_t const* s1, tb_size_t n1, tb_char_t const* s2);
// wcslen
tb_size_t tb_wcslen(tb_wchar_t const* s);
tb_size_t tb_wcsnlen(tb_wchar_t const* s, tb_size_t n);
// wcsdup
tb_wchar_t* tb_wcsdup(tb_wchar_t const* s);
tb_wchar_t* tb_wcsndup(tb_wchar_t const* s, tb_size_t n);
// wcscat
tb_wchar_t* tb_wcscat(tb_wchar_t* s1, tb_wchar_t const* s2);
tb_wchar_t* tb_wcsncat(tb_wchar_t* s1, tb_wchar_t const* s2, tb_size_t n);
// wcscpy
tb_wchar_t* tb_wcscpy(tb_wchar_t* s1, tb_wchar_t const* s2);
tb_wchar_t* tb_wcsncpy(tb_wchar_t* s1, tb_wchar_t const* s2, tb_size_t n);
tb_size_t tb_wcslcpy(tb_wchar_t* s1, tb_wchar_t const* s2, tb_size_t n);
// wcscmp
tb_long_t tb_wcscmp(tb_wchar_t const* s1, tb_wchar_t const* s2);
tb_long_t tb_wcsncmp(tb_wchar_t const* s1, tb_wchar_t const* s2, tb_size_t n);
tb_long_t tb_wcsicmp(tb_wchar_t const* s1, tb_wchar_t const* s2);
tb_long_t tb_wcsnicmp(tb_wchar_t const* s1, tb_wchar_t const* s2, tb_size_t n);
// wcschr
tb_wchar_t* tb_wcschr(tb_wchar_t const* s, tb_wchar_t c);
tb_wchar_t* tb_wcsichr(tb_wchar_t const* s, tb_wchar_t c);
// wcsrchr
tb_wchar_t* tb_wcsrchr(tb_wchar_t const* s, tb_wchar_t c);
tb_wchar_t* tb_wcsirchr(tb_wchar_t const* s, tb_wchar_t c);
tb_wchar_t* tb_wcsnrchr(tb_wchar_t const* s, tb_size_t n, tb_wchar_t c);
tb_wchar_t* tb_wcsnirchr(tb_wchar_t const* s, tb_size_t n, tb_wchar_t c);
// wcsstr
tb_wchar_t* tb_wcsstr(tb_wchar_t const* s1, tb_wchar_t const* s2);
tb_wchar_t* tb_wcsistr(tb_wchar_t const* s1, tb_wchar_t const* s2);
// wcsrstr
tb_wchar_t* tb_wcsrstr(tb_wchar_t const* s1, tb_wchar_t const* s2);
tb_wchar_t* tb_wcsirstr(tb_wchar_t const* s1, tb_wchar_t const* s2);
tb_wchar_t* tb_wcsnrstr(tb_wchar_t const* s1, tb_size_t n, tb_wchar_t const* s2);
tb_wchar_t* tb_wcsnirstr(tb_wchar_t const* s1, tb_size_t n, tb_wchar_t const* s2);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/libc/string/strirchr.c 0000664 0000000 0000000 00000002131 14671175054 0020476 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strirchr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_char_t* tb_strirchr(tb_char_t const* s, tb_char_t c)
{
tb_assert_and_check_return_val(s, tb_null);
return tb_strnirchr(s, tb_strlen(s), c);
}
tbox-1.7.6/src/tbox/libc/string/strirstr.c 0000664 0000000 0000000 00000002146 14671175054 0020540 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strirstr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_char_t* tb_strirstr(tb_char_t const* s1, tb_char_t const* s2)
{
tb_assert_and_check_return_val(s1, tb_null);
return tb_strnirstr(s1, tb_strlen(s1), s2);
}
tbox-1.7.6/src/tbox/libc/string/stristr.c 0000664 0000000 0000000 00000003511 14671175054 0020353 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file stristr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#ifdef TB_CONFIG_LIBC_HAVE_STRCASESTR
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
#ifdef TB_CONFIG_LIBC_HAVE_STRCASESTR
tb_char_t* tb_stristr(tb_char_t const* s1, tb_char_t const* s2)
{
// check
tb_assert_and_check_return_val(s1 && s2, tb_null);
return strcasestr(s1, s2);
}
#else
tb_char_t* tb_stristr(tb_char_t const* s1, tb_char_t const* s2)
{
// check
tb_assert_and_check_return_val(s1 && s2, tb_null);
// init
__tb_register__ tb_char_t const* s = s1;
__tb_register__ tb_char_t const* p = s2;
// done
do
{
if (!*p) return (tb_char_t* )s1;
if ((*p == *s) || (tb_tolower(*((tb_byte_t*)p)) == tb_tolower(*((tb_byte_t*)s))))
{
++p;
++s;
}
else
{
p = s2;
if (!*s) return tb_null;
s = ++s1;
}
} while (1);
// no found
return tb_null;
}
#endif
tbox-1.7.6/src/tbox/libc/string/strlcpy.c 0000664 0000000 0000000 00000006740 14671175054 0020350 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strlcpy.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#include "../../memory/impl/prefix.h"
#ifndef TB_CONFIG_LIBC_HAVE_STRLCPY
# if defined(TB_ARCH_x86)
# include "impl/x86/strlcpy.c"
# elif defined(TB_ARCH_ARM)
# include "impl/arm/strlcpy.c"
# endif
#else
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/* suppress warning as error for clang compiler temporarily:
*
* implicit declaration of function 'strlcpy' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
*
* TODO: need improve xmake to check this interface more correctly.
*/
#if defined(TB_CONFIG_LIBC_HAVE_STRLCPY) && defined(TB_COMPILER_IS_CLANG)
# undef TB_CONFIG_LIBC_HAVE_STRLCPY
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_LIBC_HAVE_STRLCPY)
static tb_size_t tb_strlcpy_impl(tb_char_t* s1, tb_char_t const* s2, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s1 && s2, 0);
// copy it
return strlcpy(s1, s2, n);
}
#elif !defined(TB_LIBC_STRING_IMPL_STRLCPY)
/* copy s2 to s1 of size n
*
* - at most n - 1 characters will be copied.
* - always null terminates (unless n == 0).
*
* returns strlen(s2); if retval >= n, truncation occurred.
*/
static tb_size_t tb_strlcpy_impl(tb_char_t* s1, tb_char_t const* s2, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s1 && s2, 0);
// init
tb_char_t* d = s1;
tb_char_t const* s = s2;
tb_size_t m = n;
// copy as many bytes as will fit
if (m != 0 && --m != 0)
{
do
{
if ((*d++ = *s++) == 0) break;
} while (--m != 0);
}
// not enough room in dst, add null and traverse rest of src
if (m == 0)
{
if (n != 0) *d = '\0';
while (*s++) ;
}
// count does not include null
return (s - s2 - 1);
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_size_t tb_strlcpy(tb_char_t* s1, tb_char_t const* s2, tb_size_t n)
{
// check
#ifdef __tb_debug__
{
// overflow dst?
tb_size_t n2 = tb_strlen(s2);
// strlcpy overflow?
tb_size_t n1 = tb_pool_data_size(s1);
if (n1 && tb_min(n2 + 1, n) > n1)
{
tb_trace_i("[strlcpy]: [overflow]: [%p, %lu] => [%p, %lu]", s2, tb_min(n2 + 1, n), s1, n1);
tb_backtrace_dump("[strlcpy]: [overflow]: ", tb_null, 10);
tb_pool_data_dump(s2, tb_true, "\t[malloc]: [from]: ");
tb_abort();
}
}
#endif
// done
return tb_strlcpy_impl(s1, s2, n);
}
tbox-1.7.6/src/tbox/libc/string/strlen.c 0000664 0000000 0000000 00000005137 14671175054 0020156 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strlen.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#include "../../memory/impl/prefix.h"
#ifndef TB_CONFIG_LIBC_HAVE_STRLEN
# if defined(TB_ARCH_x86)
# include "impl/x86/strlen.c"
# elif defined(TB_ARCH_ARM)
# include "impl/arm/strlen.c"
# elif defined(TB_ARCH_SH4)
# include "impl/sh4/strlen.c"
# endif
#else
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_LIBC_HAVE_STRLEN)
static tb_size_t tb_strlen_impl(tb_char_t const* s)
{
tb_assert_and_check_return_val(s, 0);
return strlen(s);
}
#elif !defined(TB_LIBC_STRING_IMPL_STRLEN)
static tb_size_t tb_strlen_impl(tb_char_t const* s)
{
// check
tb_assert_and_check_return_val(s, 0);
__tb_register__ tb_char_t const* p = s;
#ifdef __tb_small__
while (*p) p++;
return (p - s);
#else
while (1)
{
if (!p[0]) return (p - s + 0);
if (!p[1]) return (p - s + 1);
if (!p[2]) return (p - s + 2);
if (!p[3]) return (p - s + 3);
p += 4;
}
return 0;
#endif
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_size_t tb_strlen(tb_char_t const* s)
{
// check
#ifdef __tb_debug__
{
// overflow?
tb_size_t size = tb_pool_data_size(s);
if (size)
{
// no '\0'?
tb_size_t real = tb_strnlen(s, size);
if (s[real])
{
tb_trace_i("[strlen]: [overflow]: [%p, %lu]", s, size);
tb_backtrace_dump("[strlen]: [overflow]: ", tb_null, 10);
tb_pool_data_dump(s, tb_true, "\t[malloc]: [from]: ");
tb_abort();
}
}
}
#endif
// done
return tb_strlen_impl(s);
}
tbox-1.7.6/src/tbox/libc/string/strncat.c 0000664 0000000 0000000 00000002763 14671175054 0020327 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strncat.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#ifdef TB_CONFIG_LIBC_HAVE_STRNCAT
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
#ifdef TB_CONFIG_LIBC_HAVE_STRNCAT
tb_char_t* tb_strncat(tb_char_t* s1, tb_char_t const* s2, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s1 && s2, tb_null);
// append it
return strncat(s1, s2, n);
}
#else
tb_char_t* tb_strncat(tb_char_t* s1, tb_char_t const* s2, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s1 && s2, tb_null);
// append it
tb_char_t* s = s1;
while (*s++); --s;
while (n-- && !(*s++ = *s2++));
return s1;
}
#endif
tbox-1.7.6/src/tbox/libc/string/strnchr.c 0000664 0000000 0000000 00000002343 14671175054 0020326 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strchr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_char_t* tb_strnchr(tb_char_t const* s, tb_size_t n, tb_char_t c)
{
// check
tb_assert_and_check_return_val(s, tb_null);
// find
tb_char_t const* e = s + n;
while (s < e && *s)
{
if (*s == c) return (tb_char_t* )s;
s++;
}
return tb_null;
}
tbox-1.7.6/src/tbox/libc/string/strncmp.c 0000664 0000000 0000000 00000004042 14671175054 0020327 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strncmp.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#ifndef TB_CONFIG_LIBC_HAVE_STRNCMP
# if defined(TB_ARCH_x86)
# include "impl/x86/strncmp.c"
# elif defined(TB_ARCH_ARM)
# include "impl/arm/strncmp.c"
# elif defined(TB_ARCH_SH4)
# include "impl/sh4/strncmp.c"
# endif
#else
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_LIBC_HAVE_STRNCMP)
static tb_long_t tb_strncmp_impl(tb_char_t const* s1, tb_char_t const* s2, tb_size_t n)
{
if (s1 == s2 || !n) return 0;
tb_assert_and_check_return_val(s1 && s2, -1);
return strncmp(s1, s2, n);
}
#elif !defined(TB_LIBC_STRING_IMPL_STRNCMP)
static tb_long_t tb_strncmp_impl(tb_char_t const* s1, tb_char_t const* s2, tb_size_t n)
{
if (s1 == s2 || !n) return 0;
tb_assert_and_check_return_val(s1 && s2, -1);
tb_long_t r = 0;
while (n-- && ((r = ((tb_long_t)(*((tb_byte_t *)s1))) - *((tb_byte_t *)s2++)) == 0) && *s1++);
return r;
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_long_t tb_strncmp(tb_char_t const* s1, tb_char_t const* s2, tb_size_t n)
{
return tb_strncmp_impl(s1, s2, n);
}
tbox-1.7.6/src/tbox/libc/string/strncpy.c 0000664 0000000 0000000 00000005124 14671175054 0020345 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strncpy.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#include "../../memory/impl/prefix.h"
#ifndef TB_CONFIG_LIBC_HAVE_STRNCPY
# if defined(TB_ARCH_x86)
# include "impl/x86/strncpy.c"
# elif defined(TB_ARCH_ARM)
# include "impl/arm/strncpy.c"
# elif defined(TB_ARCH_SH4)
# include "impl/sh4/strncpy.c"
# endif
#else
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_LIBC_HAVE_STRNCPY)
static tb_char_t* tb_strncpy_impl(tb_char_t* s1, tb_char_t const* s2, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s1 && s2, tb_null);
// copy it
return strncpy(s1, s2, n);
}
#elif !defined(TB_LIBC_STRING_IMPL_STRNCPY)
static tb_char_t* tb_strncpy_impl(tb_char_t* s1, tb_char_t const* s2, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s1 && s2, s1);
// no size or same?
tb_check_return_val(n && s1 != s2, s1);
// copy it
tb_char_t* s = s1;
while (n)
{
if ((*s = *s2)) s2++;
++s;
--n;
}
return s1;
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_char_t* tb_strncpy(tb_char_t* s1, tb_char_t const* s2, tb_size_t n)
{
// check
#ifdef __tb_debug__
{
// overflow dst?
tb_strlen(s2);
// strncpy overflow?
tb_size_t n1 = tb_pool_data_size(s1);
if (n1 && n + 1 > n1)
{
tb_trace_i("[strncpy]: [overflow]: [%p, %lu] => [%p, %lu]", s2, n, s1, n1);
tb_backtrace_dump("[strncpy]: [overflow]: ", tb_null, 10);
tb_pool_data_dump(s2, tb_true, "\t[malloc]: [from]: ");
tb_abort();
}
}
#endif
// done
return tb_strncpy_impl(s1, s2, n);
}
tbox-1.7.6/src/tbox/libc/string/strndup.c 0000664 0000000 0000000 00000002404 14671175054 0020340 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strndup.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_char_t* tb_strndup(tb_char_t const* s, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s, tb_null);
// done
n = tb_strnlen(s, n);
__tb_register__ tb_char_t* p = tb_malloc_cstr(n + 1);
if (p)
{
tb_memcpy(p, s, n);
p[n] = '\0';
}
return p;
}
tbox-1.7.6/src/tbox/libc/string/strnichr.c 0000664 0000000 0000000 00000002547 14671175054 0020505 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strichr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_char_t* tb_strnichr(tb_char_t const* s, tb_size_t n, tb_char_t c)
{
// check
tb_assert_and_check_return_val(s, tb_null);
// init
tb_byte_t const* p = (tb_byte_t const*)s;
tb_byte_t const* e = p + n;
tb_byte_t b = tb_tolower((tb_byte_t)c);
// find
while (p < e && *p)
{
if (tb_tolower(*p) == b) return (tb_char_t*)p;
p++;
}
return tb_null;
}
tbox-1.7.6/src/tbox/libc/string/strnicmp.c 0000664 0000000 0000000 00000003637 14671175054 0020511 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strnicmp.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#ifdef TB_CONFIG_LIBC_HAVE_STRNCASECMP
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#ifdef TB_CONFIG_LIBC_HAVE_STRNCASECMP
static tb_long_t tb_strnicmp_impl(tb_char_t const* s1, tb_char_t const* s2, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s1 && s2, 0);
# ifdef TB_COMPILER_IS_MSVC
return _strnicmp(s1, s2, n);
# else
return strncasecmp(s1, s2, n);
# endif
}
#else
static tb_long_t tb_strnicmp_impl(tb_char_t const* s1, tb_char_t const* s2, tb_size_t n)
{
tb_assert_and_check_return_val(s1 && s2, 0);
if (s1 == s2 || !n) return 0;
tb_long_t r = 0;
while (n && ((s1 == s2) || !(r = ((tb_long_t)(tb_tolower(*((tb_byte_t*)s1)))) - tb_tolower(*((tb_byte_t*)s2)))) && (--n, ++s2, *s1++));
return r;
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_long_t tb_strnicmp(tb_char_t const* s1, tb_char_t const* s2, tb_size_t n)
{
// done
return tb_strnicmp_impl(s1, s2, n);
}
tbox-1.7.6/src/tbox/libc/string/strnirchr.c 0000664 0000000 0000000 00000002524 14671175054 0020662 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strnirchr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_char_t* tb_strnirchr(tb_char_t const* s, tb_size_t n, tb_char_t c)
{
// check
tb_assert_and_check_return_val(s, tb_null);
// done
tb_byte_t const* p = (tb_byte_t const*)s + n - 1;
tb_byte_t b = tb_tolower((tb_byte_t)c);
while (p >= (tb_byte_t const*)s && *p)
{
if (tb_tolower(*p) == b) return (tb_char_t*)p;
p--;
}
return tb_null;
}
tbox-1.7.6/src/tbox/libc/string/strnirstr.c 0000664 0000000 0000000 00000002163 14671175054 0020715 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strnirstr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_char_t* tb_strnirstr(tb_char_t const* s1, tb_size_t n1, tb_char_t const* s2)
{
tb_assert_and_check_return_val(s1, tb_null);
tb_trace_noimpl();
return tb_null;
}
tbox-1.7.6/src/tbox/libc/string/strnistr.c 0000664 0000000 0000000 00000003244 14671175054 0020534 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strnistr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_char_t* tb_strnistr(tb_char_t const* s1, tb_size_t n1, tb_char_t const* s2)
{
// check
tb_assert_and_check_return_val(s1 && s2 && n1, tb_null);
// init
__tb_register__ tb_char_t const* s = s1;
__tb_register__ tb_char_t const* p = s2;
__tb_register__ tb_size_t n = n1;
// done
do
{
if (!*p) return (tb_char_t* )s1;
if (n && ((*p == *s) || (tb_tolower(*((tb_byte_t*)p)) == tb_tolower(*((tb_byte_t*)s)))))
{
++p;
++s;
--n;
}
else
{
p = s2;
if (!*s || !n) return tb_null;
s = ++s1;
n = --n1;
}
} while (1);
// no found
return tb_null;
}
tbox-1.7.6/src/tbox/libc/string/strnlen.c 0000664 0000000 0000000 00000005676 14671175054 0020344 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strnlen.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#include "../../memory/impl/prefix.h"
#ifndef TB_CONFIG_LIBC_HAVE_STRNLEN
# if defined(TB_ARCH_x86)
# include "impl/x86/strnlen.c"
# elif defined(TB_ARCH_ARM)
# include "impl/arm/strnlen.c"
# elif defined(TB_ARCH_SH4)
# include "impl/sh4/strnlen.c"
# endif
#else
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_LIBC_HAVE_STRNLEN)
static tb_size_t tb_strnlen_impl(tb_char_t const* s, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s, 0);
#ifdef TB_CONFIG_OS_ANDROID
/* fix the bug for android
*
* return -1 if n == (tb_uint32_t)-1
*/
return strnlen(s, (tb_uint16_t)n);
#else
return strnlen(s, n);
#endif
}
#elif !defined(TB_LIBC_STRING_IMPL_STRNLEN)
static tb_size_t tb_strnlen_impl(tb_char_t const* s, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s, 0);
if (!n) return 0;
__tb_register__ tb_char_t const* p = s;
#ifdef __tb_small__
while (n-- && *p) ++p;
return p - s;
#else
tb_size_t l = n & 0x3; n = (n - l) >> 2;
while (n--)
{
if (!p[0]) return (p - s + 0);
if (!p[1]) return (p - s + 1);
if (!p[2]) return (p - s + 2);
if (!p[3]) return (p - s + 3);
p += 4;
}
while (l-- && *p) ++p;
return p - s;
#endif
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_size_t tb_strnlen(tb_char_t const* s, tb_size_t n)
{
// check
#ifdef __tb_debug__
{
// overflow?
tb_size_t size = tb_pool_data_size(s);
if (size)
{
// no '\0'?
tb_size_t real = tb_strnlen_impl(s, size);
if (s[real])
{
tb_trace_i("[strnlen]: [overflow]: [%p, %lu]", s, size);
tb_backtrace_dump("[strnlen]: [overflow]: ", tb_null, 10);
tb_pool_data_dump(s, tb_true, "\t[malloc]: [from]: ");
tb_abort();
}
}
}
#endif
// done
return tb_strnlen_impl(s, n);
}
tbox-1.7.6/src/tbox/libc/string/strnrchr.c 0000664 0000000 0000000 00000002354 14671175054 0020512 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strnrchr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_char_t* tb_strnrchr(tb_char_t const* s, tb_size_t n, tb_char_t c)
{
// check
tb_assert_and_check_return_val(s, tb_null);
// done
tb_char_t const* p = s + n - 1;
while (p >= s && *p)
{
if (*p == c) return (tb_char_t*)p;
p--;
}
return tb_null;
}
tbox-1.7.6/src/tbox/libc/string/strnrstr.c 0000664 0000000 0000000 00000002161 14671175054 0020542 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strnrstr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_char_t* tb_strnrstr(tb_char_t const* s1, tb_size_t n1, tb_char_t const* s2)
{
tb_assert_and_check_return_val(s1, tb_null);
tb_trace_noimpl();
return tb_null;
}
tbox-1.7.6/src/tbox/libc/string/strnstr.c 0000664 0000000 0000000 00000003145 14671175054 0020363 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strnstr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_char_t* tb_strnstr(tb_char_t const* s1, tb_size_t n1, tb_char_t const* s2)
{
// check
tb_assert_and_check_return_val(s1 && s2 && n1, tb_null);
// init
__tb_register__ tb_char_t const* s = s1;
__tb_register__ tb_char_t const* p = s2;
__tb_register__ tb_size_t n = n1;
// done
do
{
if (!*p) return (tb_char_t *)s1;
if (n && *p == *s)
{
++p;
++s;
--n;
}
else
{
p = s2;
if (!*s || !n) return tb_null;
s = ++s1;
n = --n1;
}
} while (1);
// no found
return tb_null;
}
tbox-1.7.6/src/tbox/libc/string/strrchr.c 0000664 0000000 0000000 00000002476 14671175054 0020341 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strrchr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#ifdef TB_CONFIG_LIBC_HAVE_STRRCHR
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#ifdef TB_CONFIG_LIBC_HAVE_STRRCHR
tb_char_t* tb_strrchr(tb_char_t const* s, tb_char_t c)
{
tb_assert(s);
return (tb_char_t*)strrchr(s, c);
}
#else
tb_char_t* tb_strrchr(tb_char_t const* s, tb_char_t c)
{
tb_assert_and_check_return_val(s, tb_null);
return tb_strnrchr(s, tb_strlen(s), c);
}
#endif
tbox-1.7.6/src/tbox/libc/string/strrstr.c 0000664 0000000 0000000 00000002143 14671175054 0020364 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strrstr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_char_t* tb_strrstr(tb_char_t const* s1, tb_char_t const* s2)
{
tb_assert_and_check_return_val(s1, tb_null);
return tb_strnrstr(s1, tb_strlen(s1), s2);
}
tbox-1.7.6/src/tbox/libc/string/strstr.c 0000664 0000000 0000000 00000003363 14671175054 0020207 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file strstr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#ifdef TB_CONFIG_LIBC_HAVE_STRSTR
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
#ifdef TB_CONFIG_LIBC_HAVE_STRSTR
tb_char_t* tb_strstr(tb_char_t const* s1, tb_char_t const* s2)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
return (tb_char_t*)strstr(s1, s2);
}
#else
tb_char_t* tb_strstr(tb_char_t const* s1, tb_char_t const* s2)
{
// check
tb_assert_and_check_return_val(s1 && s2, tb_null);
// init
__tb_register__ tb_char_t const* s = s1;
__tb_register__ tb_char_t const* p = s2;
// done
do
{
if (!*p) return (tb_char_t *)s1;
if (*p == *s)
{
++p;
++s;
}
else
{
p = s2;
if (!*s) return tb_null;
s = ++s1;
}
} while (1);
// no found
return tb_null;
}
#endif
tbox-1.7.6/src/tbox/libc/string/wcscat.c 0000664 0000000 0000000 00000002674 14671175054 0020136 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcscat.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#ifdef TB_CONFIG_LIBC_HAVE_WCSCAT
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
#ifdef TB_CONFIG_LIBC_HAVE_WCSCAT
tb_wchar_t* tb_wcscat(tb_wchar_t* s1, tb_wchar_t const* s2)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
return wcscat(s1, s2);
}
#else
tb_wchar_t* tb_wcscat(tb_wchar_t* s1, tb_wchar_t const* s2)
{
// check
tb_assert_and_check_return_val(s1 && s2, tb_null);
// done
__tb_register__ tb_wchar_t* s = s1;
while (*s) s++; --s;
while (!(*s++ = *s2++));
return s1;
}
#endif
tbox-1.7.6/src/tbox/libc/string/wcschr.c 0000664 0000000 0000000 00000002624 14671175054 0020136 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcschr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#ifdef TB_CONFIG_LIBC_HAVE_WCSCHR
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
#ifdef TB_CONFIG_LIBC_HAVE_WCSCHR
tb_wchar_t* tb_wcschr(tb_wchar_t const* s, tb_wchar_t c)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
return wcschr(s1, c);
}
#else
tb_wchar_t* tb_wcschr(tb_wchar_t const* s, tb_wchar_t c)
{
tb_assert_and_check_return_val(s, tb_null);
while (*s)
{
if (*s == c) return (tb_wchar_t* )s;
s++;
}
return tb_null;
}
#endif
tbox-1.7.6/src/tbox/libc/string/wcscmp.c 0000664 0000000 0000000 00000003042 14671175054 0020134 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcscmp.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#ifdef TB_CONFIG_LIBC_HAVE_WCSCMP
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
#ifdef TB_CONFIG_LIBC_HAVE_WCSCMP
tb_long_t tb_wcscmp(tb_wchar_t const* s1, tb_wchar_t const* s2)
{
tb_assert_and_check_return_val(s1 && s2, 0);
return wcscmp(s1, s2);
}
#else
tb_long_t tb_wcscmp(tb_wchar_t const* s1, tb_wchar_t const* s2)
{
// check
tb_assert_and_check_return_val(s1 && s2, 0);
tb_check_return_val(s1 != s2, 0);
// done
while (*((tb_wchar_t *)s1) == *((tb_wchar_t *)s2))
{
if (!*s1++) return 0;
++s2;
}
return (*((tb_wchar_t *)s1) < *((tb_wchar_t *)s2)) ? -1 : 1;
}
#endif
tbox-1.7.6/src/tbox/libc/string/wcscpy.c 0000664 0000000 0000000 00000003350 14671175054 0020152 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcscpy.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#ifdef TB_CONFIG_LIBC_HAVE_WCSCPY
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
#ifdef TB_CONFIG_LIBC_HAVE_WCSCPY
tb_wchar_t* tb_wcscpy(tb_wchar_t* s1, tb_wchar_t const* s2)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
return wcscpy(s1, s2);
}
#else
tb_wchar_t* tb_wcscpy(tb_wchar_t* s1, tb_wchar_t const* s2)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
__tb_register__ tb_wchar_t* s = s1;
if (s1 == s2) return s;
#if 1
tb_memcpy(s1, s2, (tb_wcslen(s2) + 1) * sizeof(tb_wchar_t));
#elif defined(__tb_small__)
while ((*s++ = *s2++)) ;
#else
while (1)
{
if (!(s1[0] = s2[0])) break;
if (!(s1[1] = s2[1])) break;
if (!(s1[2] = s2[2])) break;
if (!(s1[3] = s2[3])) break;
s1 += 4;
s2 += 4;
}
#endif
return s;
}
#endif
tbox-1.7.6/src/tbox/libc/string/wcsdup.c 0000664 0000000 0000000 00000002471 14671175054 0020152 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcsdup.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_wchar_t* tb_wcsdup(tb_wchar_t const* s)
{
// check
tb_assert_and_check_return_val(s, tb_null);
// done
__tb_register__ tb_size_t n = tb_wcslen(s);
__tb_register__ tb_wchar_t* p = (tb_wchar_t*)tb_malloc((n + 1) * sizeof(tb_wchar_t));
if (p)
{
tb_memcpy(p, s, n * sizeof(tb_wchar_t));
p[n] = L'\0';
}
return p;
}
tbox-1.7.6/src/tbox/libc/string/wcsichr.c 0000664 0000000 0000000 00000002425 14671175054 0020306 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcsichr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_wchar_t* tb_wcsichr(tb_wchar_t const* s, tb_wchar_t c)
{
// check
tb_assert_and_check_return_val(s, tb_null);
// init
tb_wchar_t const* p = s;
tb_wchar_t b = tb_tolower(c);
// find
while (*p)
{
if (tb_tolower(*p) == b) return (tb_wchar_t*)p;
p++;
}
return tb_null;
}
tbox-1.7.6/src/tbox/libc/string/wcsicmp.c 0000664 0000000 0000000 00000003251 14671175054 0020307 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcsicmp.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#ifdef TB_CONFIG_LIBC_HAVE_WCSCASECMP
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
#ifdef TB_CONFIG_LIBC_HAVE_WCSCASECMP
tb_long_t tb_wcsicmp(tb_wchar_t const* s1, tb_wchar_t const* s2)
{
// check
tb_assert_and_check_return_val(s1 && s2, 0);
# ifdef TB_COMPILER_IS_MSVC
return _wcsicmp(s1, s2);
# else
return wcscasecmp(s1, s2);
# endif
}
#else
tb_long_t tb_wcsicmp(tb_wchar_t const* s1, tb_wchar_t const* s2)
{
// check
tb_assert_and_check_return_val(s1 && s2, 0);
tb_check_return_val(s1 != s2, 0);
// done
while ((*s1 == *s2) || (tb_tolower(*s1) == tb_tolower(*s2)))
{
if (!*s1++) return 0;
++s2;
}
return (((tb_wchar_t)tb_tolower(*s1)) < ((tb_wchar_t)tb_tolower(*s2))) ? -1 : 1;
}
#endif
tbox-1.7.6/src/tbox/libc/string/wcsirchr.c 0000664 0000000 0000000 00000002134 14671175054 0020465 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcsirchr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_wchar_t* tb_wcsirchr(tb_wchar_t const* s, tb_wchar_t c)
{
tb_assert_and_check_return_val(s, tb_null);
return tb_wcsnirchr(s, tb_wcslen(s), c);
}
tbox-1.7.6/src/tbox/libc/string/wcsirstr.c 0000664 0000000 0000000 00000002151 14671175054 0020520 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcsirstr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_wchar_t* tb_wcsirstr(tb_wchar_t const* s1, tb_wchar_t const* s2)
{
tb_assert_and_check_return_val(s1, tb_null);
return tb_wcsnirstr(s1, tb_wcslen(s1), s2);
}
tbox-1.7.6/src/tbox/libc/string/wcsistr.c 0000664 0000000 0000000 00000003427 14671175054 0020345 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcsistr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#ifdef TB_CONFIG_LIBC_HAVE_WCSCASESTR
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
#ifdef TB_CONFIG_LIBC_HAVE_WCSCASESTR
tb_wchar_t* tb_wcsistr(tb_wchar_t const* s1, tb_wchar_t const* s2)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
return wcscasestr(s1, s2);
}
#else
tb_wchar_t* tb_wcsistr(tb_wchar_t const* s1, tb_wchar_t const* s2)
{
// check
tb_assert_and_check_return_val(s1 && s2, tb_null);
// init
__tb_register__ tb_wchar_t const* s = s1;
__tb_register__ tb_wchar_t const* p = s2;
// done
do
{
if (!*p) return (tb_wchar_t* )s1;
if ((*p == *s) || (tb_tolower(*p) == tb_tolower(*s)))
{
++p;
++s;
}
else
{
p = s2;
if (!*s) return tb_null;
s = ++s1;
}
} while (1);
return tb_null;
}
#endif
tbox-1.7.6/src/tbox/libc/string/wcslcpy.c 0000664 0000000 0000000 00000003371 14671175054 0020331 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcslcpy.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#ifdef TB_CONFIG_LIBC_HAVE_WCSLCPY
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
#ifdef TB_CONFIG_LIBC_HAVE_WCSLCPY
tb_size_t tb_wcslcpy(tb_wchar_t* s1, tb_wchar_t const* s2, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s1 && s2, 0);
return wcslcpy(s1, s2, n);
}
#else
tb_size_t tb_wcslcpy(tb_wchar_t* s1, tb_wchar_t const* s2, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s1 && s2, 0);
// no size or same?
tb_check_return_val(n && s1 != s2, tb_wcslen(s1));
// copy
#if 0
tb_wchar_t const* s = s2; --n;
while (*s1 = *s2)
{
if (n)
{
--n;
++s1;
}
++s2;
}
return s2 - s;
#else
tb_size_t sn = tb_wcslen(s2);
tb_memcpy(s1, s2, tb_min(sn + 1, n) * sizeof(tb_wchar_t));
return tb_min(sn, n);
#endif
}
#endif
tbox-1.7.6/src/tbox/libc/string/wcslen.c 0000664 0000000 0000000 00000003075 14671175054 0020141 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcslen.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#ifdef TB_CONFIG_LIBC_HAVE_WCSLEN
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
#ifdef TB_CONFIG_LIBC_HAVE_WCSLEN
tb_size_t tb_wcslen(tb_wchar_t const* s)
{
tb_assert_and_check_return_val(s, 0);
return wcslen(s);
}
#else
tb_size_t tb_wcslen(tb_wchar_t const* s)
{
tb_assert_and_check_return_val(s, 0);
__tb_register__ tb_wchar_t const* p = s;
#ifdef __tb_small__
while (*p) p++;
return (p - s);
#else
while (1)
{
if (!p[0]) return (p - s + 0);
if (!p[1]) return (p - s + 1);
if (!p[2]) return (p - s + 2);
if (!p[3]) return (p - s + 3);
p += 4;
}
return 0;
#endif
}
#endif
tbox-1.7.6/src/tbox/libc/string/wcsncat.c 0000664 0000000 0000000 00000002746 14671175054 0020314 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcsncat.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#ifdef TB_CONFIG_LIBC_HAVE_WCSNCAT
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
#ifdef TB_CONFIG_LIBC_HAVE_WCSNCAT
tb_wchar_t* tb_wcsncat(tb_wchar_t* s1, tb_wchar_t const* s2, tb_size_t n)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
return wcsncat(s1, s2, n);
}
#else
tb_wchar_t* tb_wcsncat(tb_wchar_t* s1, tb_wchar_t const* s2, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s1 && s2, tb_null);
// done
__tb_register__ tb_wchar_t* s = s1;
while (*s) s++; --s;
while (n-- && !(*s++ = *s2++));
return s1;
}
#endif
tbox-1.7.6/src/tbox/libc/string/wcsncmp.c 0000664 0000000 0000000 00000002511 14671175054 0020312 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcsncmp.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_long_t tb_wcsncmp(tb_wchar_t const* s1, tb_wchar_t const* s2, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s1 && s2, 0);
tb_check_return_val(s1 != s2 && n, 0);
// done
while (n && (*((tb_wchar_t *)s1) == *((tb_wchar_t *)s2)))
{
if (!*s1++) return 0;
++s2;
--n;
}
return n? (*((tb_wchar_t *)s1) - *((tb_wchar_t *)s2)) : 0;
}
tbox-1.7.6/src/tbox/libc/string/wcsncpy.c 0000664 0000000 0000000 00000003442 14671175054 0020332 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcsncpy.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#ifdef TB_CONFIG_LIBC_HAVE_WCSNCPY
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
#ifdef TB_CONFIG_LIBC_HAVE_WCSNCPY
tb_wchar_t* tb_wcsncpy(tb_wchar_t* s1, tb_wchar_t const* s2, tb_size_t n)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
return wcsncpy(s1, s2, n);
}
#else
tb_wchar_t* tb_wcsncpy(tb_wchar_t* s1, tb_wchar_t const* s2, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s1 && s2, s1);
// no size or same?
tb_check_return_val(n && s1 != s2, s1);
// copy
#if 0
tb_wchar_t* s = s1;
while (n)
{
if (*s = *s2) s2++;
++s;
--n;
}
return s1;
#else
tb_size_t sn = tb_wcslen(s2);
tb_size_t cn = tb_min(sn, n);
tb_size_t fn = sn < n? n - sn : 0;
tb_memcpy(s1, s2, cn * sizeof(tb_wchar_t));
if (fn) tb_memset(s1 + cn, 0, fn * sizeof(tb_wchar_t));
return s1;
#endif
}
#endif
tbox-1.7.6/src/tbox/libc/string/wcsndup.c 0000664 0000000 0000000 00000002474 14671175054 0020333 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcsndup.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_wchar_t* tb_wcsndup(tb_wchar_t const* s, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s, tb_null);
// done
n = tb_wcsnlen(s, n);
__tb_register__ tb_wchar_t* p = (tb_wchar_t*)tb_malloc((n + 1) * sizeof(tb_wchar_t));
if (p)
{
tb_memcpy(p, s, n * sizeof(tb_wchar_t));
p[n] = L'\0';
}
return p;
}
tbox-1.7.6/src/tbox/libc/string/wcsnicmp.c 0000664 0000000 0000000 00000003355 14671175054 0020472 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcsnicmp.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#ifdef TB_CONFIG_LIBC_HAVE_WCSNCASECMP
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
#ifdef TB_CONFIG_LIBC_HAVE_WCSNCASECMP
tb_long_t tb_wcsnicmp(tb_wchar_t const* s1, tb_wchar_t const* s2, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s1 && s2, 0);
# ifdef TB_COMPILER_IS_MSVC
return _wcsnicmp(s1, s2, n);
# else
return wcsncasecmp(s1, s2, n);
# endif
}
#else
tb_long_t tb_wcsnicmp(tb_wchar_t const* s1, tb_wchar_t const* s2, tb_size_t n)
{
// check
tb_assert_and_check_return_val(s1 && s2, 0);
tb_check_return_val(s1 != s2, 0);
// done
while (n && ((*s1 == *s2) || (tb_tolower(*s1) == tb_tolower(*s2))))
{
if (!*s1++) return 0;
++s2;
--n;
}
return n? ((((tb_wchar_t)tb_tolower(*s1)) < ((tb_wchar_t)tb_tolower(*s2))) ? -1 : 1) : 0;
}
#endif
tbox-1.7.6/src/tbox/libc/string/wcsnirchr.c 0000664 0000000 0000000 00000002451 14671175054 0020645 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcsnirchr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_wchar_t* tb_wcsnirchr(tb_wchar_t const* s, tb_size_t n, tb_wchar_t c)
{
// check
tb_assert_and_check_return_val(s, tb_null);
// done
tb_wchar_t const* p = s + n - 1;
tb_wchar_t b = tb_tolower(c);
while (p >= s && *p)
{
if (tb_tolower(*p) == b) return (tb_wchar_t*)p;
p--;
}
return tb_null;
}
tbox-1.7.6/src/tbox/libc/string/wcsnirstr.c 0000664 0000000 0000000 00000002164 14671175054 0020702 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcsnirstr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_wchar_t* tb_wcsnirstr(tb_wchar_t const* s1, tb_size_t n, tb_wchar_t const* s2)
{
tb_assert_and_check_return_val(s1, tb_null);
tb_trace_noimpl();
return tb_null;
}
tbox-1.7.6/src/tbox/libc/string/wcsnlen.c 0000664 0000000 0000000 00000003311 14671175054 0020310 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcsnlen.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#ifdef TB_CONFIG_LIBC_HAVE_WCSNLEN
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
#ifdef TB_CONFIG_LIBC_HAVE_WCSNLEN
tb_size_t tb_wcsnlen(tb_wchar_t const* s, tb_size_t n)
{
tb_assert_and_check_return_val(s, 0);
return wcsnlen(s, n);
}
#else
tb_size_t tb_wcsnlen(tb_wchar_t const* s, tb_size_t n)
{
tb_assert_and_check_return_val(s, 0);
if (!n) return 0;
__tb_register__ tb_wchar_t const* p = s;
#ifdef __tb_small__
while (n-- && *p) ++p;
return p - s;
#else
tb_size_t l = n & 0x3; n = (n - l) >> 2;
while (n--)
{
if (!p[0]) return (p - s + 0);
if (!p[1]) return (p - s + 1);
if (!p[2]) return (p - s + 2);
if (!p[3]) return (p - s + 3);
p += 4;
}
while (l-- && *p) ++p;
return p - s;
#endif
}
#endif
tbox-1.7.6/src/tbox/libc/string/wcsnrchr.c 0000664 0000000 0000000 00000002325 14671175054 0020474 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcsnrchr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_wchar_t* tb_wcsnrchr(tb_wchar_t const* s, tb_size_t n, tb_wchar_t c)
{
tb_assert_and_check_return_val(s, tb_null);
tb_wchar_t const* p = s + n - 1;
while (p >= s && *p)
{
if (*p == c) return (tb_wchar_t*)p;
p--;
}
return tb_null;
}
tbox-1.7.6/src/tbox/libc/string/wcsnrstr.c 0000664 0000000 0000000 00000002163 14671175054 0020530 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcsnrstr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_wchar_t* tb_wcsnrstr(tb_wchar_t const* s1, tb_size_t n, tb_wchar_t const* s2)
{
tb_assert_and_check_return_val(s1, tb_null);
tb_trace_noimpl();
return tb_null;
}
tbox-1.7.6/src/tbox/libc/string/wcsrchr.c 0000664 0000000 0000000 00000002131 14671175054 0020311 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcsrchr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_wchar_t* tb_wcsrchr(tb_wchar_t const* s, tb_wchar_t c)
{
tb_assert_and_check_return_val(s, tb_null);
return tb_wcsnrchr(s, tb_wcslen(s), c);
}
tbox-1.7.6/src/tbox/libc/string/wcsrstr.c 0000664 0000000 0000000 00000002146 14671175054 0020353 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcsrstr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_wchar_t* tb_wcsrstr(tb_wchar_t const* s1, tb_wchar_t const* s2)
{
tb_assert_and_check_return_val(s1, tb_null);
return tb_wcsnrstr(s1, tb_wcslen(s1), s2);
}
tbox-1.7.6/src/tbox/libc/string/wcsstr.c 0000664 0000000 0000000 00000003307 14671175054 0020171 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file wcsstr.c
* @ingroup libc
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "string.h"
#ifdef TB_CONFIG_LIBC_HAVE_WCSSTR
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
#ifdef TB_CONFIG_LIBC_HAVE_WCSSTR
tb_wchar_t* tb_wcsstr(tb_wchar_t const* s1, tb_wchar_t const* s2)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
return (tb_wchar_t*)wcsstr(s1, s2);
}
#else
tb_wchar_t* tb_wcsstr(tb_wchar_t const* s1, tb_wchar_t const* s2)
{
tb_assert_and_check_return_val(s1 && s2, tb_null);
__tb_register__ tb_wchar_t const* s = s1;
__tb_register__ tb_wchar_t const* p = s2;
do
{
if (!*p) return (tb_wchar_t *)s1;
if (*p == *s)
{
++p;
++s;
}
else
{
p = s2;
if (!*s) return tb_null;
s = ++s1;
}
} while (1);
return tb_null;
}
#endif
tbox-1.7.6/src/tbox/libm/ 0000775 0000000 0000000 00000000000 14671175054 0015201 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/libm/acos.c 0000664 0000000 0000000 00000002130 14671175054 0016266 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file acos.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_double_t tb_acos(tb_double_t x)
{
#ifdef TB_CONFIG_LIBM_HAVE_ACOS
return acos(x);
#else
tb_assert(0);
return 0;
#endif
}
tbox-1.7.6/src/tbox/libm/acosf.c 0000664 0000000 0000000 00000002135 14671175054 0016441 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file acosf.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_float_t tb_acosf(tb_float_t x)
{
#ifdef TB_CONFIG_LIBM_HAVE_ACOSF
return acosf(x);
#else
return (tb_float_t)tb_acos(x);
#endif
}
tbox-1.7.6/src/tbox/libm/asin.c 0000664 0000000 0000000 00000002130 14671175054 0016273 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file asin.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_double_t tb_asin(tb_double_t x)
{
#ifdef TB_CONFIG_LIBM_HAVE_ASIN
return asin(x);
#else
tb_assert(0);
return 0;
#endif
}
tbox-1.7.6/src/tbox/libm/asinf.c 0000664 0000000 0000000 00000002135 14671175054 0016446 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file asinf.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_float_t tb_asinf(tb_float_t x)
{
#ifdef TB_CONFIG_LIBM_HAVE_ASINF
return asinf(x);
#else
return (tb_float_t)tb_asin(x);
#endif
}
tbox-1.7.6/src/tbox/libm/atan.c 0000664 0000000 0000000 00000002130 14671175054 0016264 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file atan.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_double_t tb_atan(tb_double_t x)
{
#ifdef TB_CONFIG_LIBM_HAVE_ATAN
return atan(x);
#else
tb_assert(0);
return 0;
#endif
}
tbox-1.7.6/src/tbox/libm/atan2.c 0000664 0000000 0000000 00000002156 14671175054 0016356 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file atan2.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_double_t tb_atan2(tb_double_t y, tb_double_t x)
{
#ifdef TB_CONFIG_LIBM_HAVE_ATAN2
return atan2(y, x);
#else
tb_assert(0);
return 0;
#endif
}
tbox-1.7.6/src/tbox/libm/atan2f.c 0000664 0000000 0000000 00000002157 14671175054 0016525 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file atan2f.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_float_t tb_atan2f(tb_float_t y, tb_float_t x)
{
#ifdef TB_CONFIG_LIBM_HAVE_ATAN2F
return atan2f(y, x);
#else
tb_assert(0);
return 0;
#endif
}
tbox-1.7.6/src/tbox/libm/atanf.c 0000664 0000000 0000000 00000002132 14671175054 0016434 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file atanf.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_float_t tb_atanf(tb_float_t x)
{
#ifdef TB_CONFIG_LIBM_HAVE_ATANF
return atanf(x);
#else
tb_assert(0);
return 0;
#endif
}
tbox-1.7.6/src/tbox/libm/ceil.h 0000664 0000000 0000000 00000002114 14671175054 0016264 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file ceil.h
* @ingroup libm
*
*/
#ifndef TB_LIBM_CEIL_H
#define TB_LIBM_CEIL_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define tb_ceil(x) ((x) > 0? (tb_int32_t)((x) + 0.9999999999) : (tb_int32_t)(x))
#endif
tbox-1.7.6/src/tbox/libm/cos.c 0000664 0000000 0000000 00000002124 14671175054 0016130 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file cos.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_double_t tb_cos(tb_double_t x)
{
#ifdef TB_CONFIG_LIBM_HAVE_COS
return cos(x);
#else
tb_assert(0);
return 0;
#endif
}
tbox-1.7.6/src/tbox/libm/cosf.c 0000664 0000000 0000000 00000002126 14671175054 0016300 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file cosf.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_float_t tb_cosf(tb_float_t x)
{
#ifdef TB_CONFIG_LIBM_HAVE_COSF
return cosf(x);
#else
tb_assert(0);
return 0;
#endif
}
tbox-1.7.6/src/tbox/libm/exp.c 0000664 0000000 0000000 00000002232 14671175054 0016140 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file exp.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_double_t tb_exp(tb_double_t x)
{
#ifdef TB_CONFIG_LIBM_HAVE_EXP
return exp(x);
#else
tb_double_t a = x - (tb_double_t)(tb_long_t)x;
return (tb_expi(((tb_long_t)x)) * tb_exp1(a));
#endif
}
tbox-1.7.6/src/tbox/libm/exp1.c 0000664 0000000 0000000 00000002107 14671175054 0016222 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file exp1.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_double_t tb_exp1(tb_double_t x)
{
tb_assert(x >= -1 && x <= 1);
return (1 + (x) + ((x) * (x)) / 2 + ((x) * (x) * (x)) / 6);
}
tbox-1.7.6/src/tbox/libm/exp1f.c 0000664 0000000 0000000 00000002107 14671175054 0016370 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file exp1f.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_float_t tb_exp1f(tb_float_t x)
{
tb_assert(x >= -1 && x <= 1);
return (1 + (x) + ((x) * (x)) / 2 + ((x) * (x) * (x)) / 6);
}
tbox-1.7.6/src/tbox/libm/expf.c 0000664 0000000 0000000 00000002220 14671175054 0016303 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file expf.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_float_t tb_expf(tb_float_t x)
{
#ifdef TB_CONFIG_LIBM_HAVE_EXPF
return expf(x);
#else
tb_float_t a = x - (tb_long_t)x;
return (tb_expif(((tb_long_t)x)) * tb_exp1f(a));
#endif
}
tbox-1.7.6/src/tbox/libm/expi.c 0000664 0000000 0000000 00000004221 14671175054 0016311 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file expi.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_double_t tb_expi(tb_long_t x)
{
tb_assert(x >= -31 && x <= 31);
// x = [-31, 31]
static tb_double_t table[47] =
{
// [-15, -1]
0.000000
, 0.000001
, 0.000002
, 0.000006
, 0.000017
, 0.000045
, 0.000123
, 0.000335
, 0.000912
, 0.002479
, 0.006738
, 0.018316
, 0.049787
, 0.135335
, 0.367879
// 0
, 1.000000
// [1, 31]
, 2.718282
, 7.389056
, 20.085537
, 54.598150
, 148.413159
, 403.428793
, 1096.633158
, 2980.957987
, 8103.083928
, 22026.465795
, 59874.141715
, 162754.791419
, 442413.392009
, 1202604.284165
, 3269017.372472
, 8886110.520508
, 24154952.753575
, 65659969.137331
, 178482300.963187
, 485165195.409790
, 1318815734.483215
, 3584912846.131592
, 9744803446.248903
, 26489122129.843472
, 72004899337.385880
, 195729609428.838776
, 532048240601.798645
, 1446257064291.475098
, 3931334297144.041992
, 10686474581524.462891
, 29048849665247.425781
};
return table[((x) + 15) & 0x3f];
}
tbox-1.7.6/src/tbox/libm/expif.c 0000664 0000000 0000000 00000004300 14671175054 0016455 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file expif.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_float_t tb_expif(tb_long_t x)
{
tb_assert(x >= -31 && x <= 31);
// x = [-31, 31]
static tb_float_t table[47] =
{
// [-15, -1]
0.000000f
, 0.000001f
, 0.000002f
, 0.000006f
, 0.000017f
, 0.000045f
, 0.000123f
, 0.000335f
, 0.000912f
, 0.002479f
, 0.006738f
, 0.018316f
, 0.049787f
, 0.135335f
, 0.367879f
// 0
, 1.000000f
// [1, 31]
, 2.718282f
, 7.389056f
, 20.085537f
, 54.598150f
, 148.413159f
, 403.428793f
, 1096.633158f
, 2980.957987f
, 8103.083928f
, 22026.465795f
, 59874.141715f
, 162754.791419f
, 442413.392009f
, 1202604.284165f
, 3269017.372472f
, 8886110.520508f
, 24154952.753575f
, 65659969.137331f
, 178482300.963187f
, 485165195.409790f
, 1318815734.483215f
, 3584912846.131592f
, 9744803446.248903f
, 26489122129.843472f
, 72004899337.385880f
, 195729609428.838776f
, 532048240601.798645f
, 1446257064291.475098f
, 3931334297144.041992f
, 10686474581524.462891f
, 29048849665247.425781f
};
return table[((x) + 15) & 0x3f];
}
tbox-1.7.6/src/tbox/libm/fabs.h 0000664 0000000 0000000 00000002011 14671175054 0016257 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file fabs.h
* @ingroup libm
*
*/
#ifndef TB_LIBM_FABS_H
#define TB_LIBM_FABS_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define tb_fabs tb_abs
#endif
tbox-1.7.6/src/tbox/libm/floor.h 0000664 0000000 0000000 00000002123 14671175054 0016471 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file floor.h
* @ingroup libm
*
*/
#ifndef TB_LIBM_FLOOR_H
#define TB_LIBM_FLOOR_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define tb_floor(x) ((x) > 0? (tb_int32_t)(x) : (tb_int32_t)((x) - 0.9999999999))
#endif
tbox-1.7.6/src/tbox/libm/fmod.c 0000664 0000000 0000000 00000002152 14671175054 0016272 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file fmod.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_double_t tb_fmod(tb_double_t x, tb_double_t y)
{
#ifdef TB_CONFIG_LIBM_HAVE_FMOD
return fmod(x, y);
#else
tb_assert(0);
return 0;
#endif
}
tbox-1.7.6/src/tbox/libm/fmodf.c 0000664 0000000 0000000 00000002161 14671175054 0016440 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file fmodf.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_float_t tb_fmodf(tb_float_t x, tb_float_t y)
{
#ifdef TB_CONFIG_LIBM_HAVE_FMODF
return fmodf(x, y);
#else
return (tb_float_t)tb_fmod(x, y);
#endif
}
tbox-1.7.6/src/tbox/libm/idivi8.c 0000664 0000000 0000000 00000012717 14671175054 0016551 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file idivi8.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_uint32_t tb_idivi8(tb_uint32_t x, tb_uint8_t y)
{
/* x * inverse[y] >> 32 == x / y for all 0 <= x <= 16909558 && 2 <= y <= 256 for x > 16909558
* is an overestimate by less than 1 part in 1 << 24
*/
static tb_uint32_t const inverse[257] =
{
0, 4294967295U, 2147483648U, 1431655766, 1073741824, 858993460, 715827883, 613566757
, 536870912, 477218589, 429496730, 390451573, 357913942, 330382100, 306783379, 286331154
, 268435456, 252645136, 238609295, 226050911, 214748365, 204522253, 195225787, 186737709
, 178956971, 171798692, 165191050, 159072863, 153391690, 148102321, 143165577, 138547333
, 134217728, 130150525, 126322568, 122713352, 119304648, 116080198, 113025456, 110127367
, 107374183, 104755300, 102261127, 99882961, 97612894, 95443718, 93368855, 91382283
, 89478486, 87652394, 85899346, 84215046, 82595525, 81037119, 79536432, 78090315
, 76695845, 75350304, 74051161, 72796056, 71582789, 70409300, 69273667, 68174085
, 67108864, 66076420, 65075263, 64103990, 63161284, 62245903, 61356676, 60492498
, 59652324, 58835169, 58040099, 57266231, 56512728, 55778797, 55063684, 54366675
, 53687092, 53024288, 52377650, 51746594, 51130564, 50529028, 49941481, 49367441
, 48806447, 48258060, 47721859, 47197443, 46684428, 46182445, 45691142, 45210183
, 44739243, 44278014, 43826197, 43383509, 42949673, 42524429, 42107523, 41698712
, 41297763, 40904451, 40518560, 40139882, 39768216, 39403370, 39045158, 38693400
, 38347923, 38008561, 37675152, 37347542, 37025581, 36709123, 36398028, 36092163
, 35791395, 35495598, 35204650, 34918434, 34636834, 34359739, 34087043, 33818641
, 33554432, 33294321, 33038210, 32786010, 32537632, 32292988, 32051995, 31814573
, 31580642, 31350127, 31122952, 30899046, 30678338, 30460761, 30246249, 30034737
, 29826162, 29620465, 29417585, 29217465, 29020050, 28825284, 28633116, 28443493
, 28256364, 28071682, 27889399, 27709467, 27531842, 27356480, 27183338, 27012373
, 26843546, 26676816, 26512144, 26349493, 26188825, 26030105, 25873297, 25718368
, 25565282, 25414008, 25264514, 25116768, 24970741, 24826401, 24683721, 24542671
, 24403224, 24265352, 24129030, 23994231, 23860930, 23729102, 23598722, 23469767
, 23342214, 23216040, 23091223, 22967740, 22845571, 22724695, 22605092, 22486740
, 22369622, 22253717, 22139007, 22025474, 21913099, 21801865, 21691755, 21582751
, 21474837, 21367997, 21262215, 21157475, 21053762, 20951060, 20849356, 20748635
, 20648882, 20550083, 20452226, 20355296, 20259280, 20164166, 20069941, 19976593
, 19884108, 19792477, 19701685, 19611723, 19522579, 19434242, 19346700, 19259944
, 19173962, 19088744, 19004281, 18920561, 18837576, 18755316, 18673771, 18592933
, 18512791, 18433337, 18354562, 18276457, 18199014, 18122225, 18046082, 17970575
, 17895698, 17821442, 17747799, 17674763, 17602325, 17530479, 17459217, 17388532
, 17318417, 17248865, 17179870, 17111424, 17043522, 16976156, 16909321, 16843010
, 16777216
};
return ((tb_size_t)((((tb_uint64_t)x) * inverse[y]) >> 32));
}
tbox-1.7.6/src/tbox/libm/ilog2i.c 0000664 0000000 0000000 00000006311 14671175054 0016533 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file ilog2i.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include "../utils/bits.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_uint32_t tb_ilog2i(tb_uint32_t x)
{
#if 0
static tb_uint32_t table[32] =
{
1 // 0
, 2 // 1
, 4 // 2
, 8 // 3
, 16 // 4
, 32 // 5
, 64 // 6
, 128 // 7
, 256 // 8
, 512 // 9
, 1024 // 10
, 2048 // 11
, 4096 // 12
, 8192 // 13
, 16384 // 14
, 32768 // 15
, 65536 // 16
, 131072 // 17
, 262144 // 18
, 524288 // 19
, 1048576 // 20
, 2097152 // 21
, 4194304 // 22
, 8388608 // 23
, 16777216 // 24
, 33554432 // 25
, 67108864 // 26
, 134217728 // 27
, 268435456 // 28
, 536870912 // 29
, 1073741824 // 30
, 2147483648 // 31
};
tb_int_t l = 0;
tb_int_t m = 15;
tb_int_t r = 32;
while ((r - l) > 1)
{
tb_uint32_t v = table[m];
if (x < v) r = m;
else l = m;
m = (l + r) >> 1;
}
return m;
#elif 0
static tb_uint8_t const table[256]=
{
0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
};
tb_size_t n = 0;
if (x & 0xffff0000)
{
x >>= 16;
n += 16;
}
if (x & 0xff00)
{
x >>= 8;
n += 8;
}
n += table[x];
return n;
#else
return (tb_uint32_t)(31 - tb_bits_cl0_u32_be(x | 1));
#endif
}
tbox-1.7.6/src/tbox/libm/impl/ 0000775 0000000 0000000 00000000000 14671175054 0016142 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/libm/impl/impl.h 0000664 0000000 0000000 00000001604 14671175054 0017255 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file libm.h
* @ingroup libm
*
*/
#ifndef TB_LIBM_IMPL_H
#define TB_LIBM_IMPL_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "libm.h"
#endif
tbox-1.7.6/src/tbox/libm/impl/libm.c 0000664 0000000 0000000 00000002024 14671175054 0017227 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file libm.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "libm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_libm_init_env()
{
return tb_true;
}
tb_void_t tb_libm_exit_env()
{
}
tbox-1.7.6/src/tbox/libm/impl/libm.h 0000664 0000000 0000000 00000002655 14671175054 0017246 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file libm.h
* @ingroup libm
*
*/
#ifndef TB_LIBM_IMPL_LIBM_H
#define TB_LIBM_IMPL_LIBM_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* init libm environment
*
* @return tb_true or tb_false
*/
tb_bool_t tb_libm_init_env(tb_noarg_t);
/* exit libm environment
*/
tb_void_t tb_libm_exit_env(tb_noarg_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/libm/impl/prefix.h 0000664 0000000 0000000 00000001603 14671175054 0017610 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_LIBM_IMPL_PREFIX_H
#define TB_LIBM_IMPL_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/libm/inf.h 0000664 0000000 0000000 00000002230 14671175054 0016123 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file inf.h
* @ingroup libm
*
*/
#ifndef TB_LIBM_INF_H
#define TB_LIBM_INF_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "maf.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#if defined(TB_COMPILER_IS_GCC) \
&& TB_COMPILER_VERSION_BE(3, 3)
# define TB_INF (__builtin_inff ())
#else
# define TB_INF TB_MAF
#endif
#endif
tbox-1.7.6/src/tbox/libm/isfin.c 0000664 0000000 0000000 00000002272 14671175054 0016460 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file isfin.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_long_t tb_isfin(tb_double_t x)
{
/* 0 * finite => 0
* 0 * infinity => NaN
* 0 * NaN => NaN
*/
tb_double_t p = x * 0;
// p will either be NaN or 0 now, so we can return (prod == prod) or (0 == prod).
return p == p;
}
tbox-1.7.6/src/tbox/libm/isfinf.c 0000664 0000000 0000000 00000002272 14671175054 0016626 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file isfinf.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_long_t tb_isfinf(tb_float_t x)
{
/* 0 * finite => 0
* 0 * infinity => NaN
* 0 * NaN => NaN
*/
tb_float_t p = x * 0;
// p will either be NaN or 0 now, so we can return (prod == prod) or (0 == prod).
return p == p;
}
tbox-1.7.6/src/tbox/libm/isinf.c 0000664 0000000 0000000 00000002215 14671175054 0016455 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file isinf.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_long_t tb_isinf(tb_double_t x)
{
tb_ieee_double_t e; e.d = x;
tb_int32_t t = e.i.l | ((e.i.h & 0x7fffffff) ^ 0x7ff00000);
t |= -t;
return (tb_long_t)(~(t >> 31) & (e.i.h >> 30));
}
tbox-1.7.6/src/tbox/libm/isinff.c 0000664 0000000 0000000 00000002205 14671175054 0016622 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file isinff.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_long_t tb_isinff(tb_float_t x)
{
tb_ieee_float_t e; e.f = x;
tb_int32_t t = e.i & 0x7fffffff;
t ^= 0x7f800000;
t |= -t;
return (tb_long_t)(~(t >> 31) & (e.i >> 30));
}
tbox-1.7.6/src/tbox/libm/isnan.c 0000664 0000000 0000000 00000002375 14671175054 0016464 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file isnan.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_long_t tb_isnan(tb_double_t x)
{
#if 0
tb_ieee_double_t e; e.d = x;
tb_int32_t t = e.i.h & 0x7fffffff;
t |= (tb_uint32_t)(e.i.l | (tb_uint32_t)(-(tb_int32_t)e.i.l)) >> 31;
t = 0x7ff00000 - t;
return (tb_long_t)(((tb_uint32_t)t) >> 31);
#else
// optimization
return x != x;
#endif
}
tbox-1.7.6/src/tbox/libm/isnanf.c 0000664 0000000 0000000 00000002264 14671175054 0016627 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file isnanf.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_long_t tb_isnanf(tb_float_t x)
{
#if 0
tb_ieee_float_t e; e.f = x;
tb_int32_t t = e.i & 0x7fffffff;
t = 0x7f800000 - t;
return (tb_long_t)(((tb_uint32_t)(t)) >> 31);
#else
// optimization
return x != x;
#endif
}
tbox-1.7.6/src/tbox/libm/isqrti.c 0000664 0000000 0000000 00000021540 14671175054 0016662 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file isqrti.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include "../utils/utils.h"
#include "../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_uint32_t tb_isqrti_impl(tb_uint32_t x)
{
#if 0
// lookup + newton
static tb_uint32_t table[256] =
{
0, 16, 22, 27, 32, 35, 39, 42, 45, 48, 50, 53, 55, 57
, 59, 61, 64, 65, 67, 69, 71, 73, 75, 76, 78, 80, 81, 83
, 84, 86, 87, 89, 90, 91, 93, 94, 96, 97, 98, 99, 101, 102
, 103, 104, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 117, 118
, 119, 120, 121, 122, 123, 124, 125, 126, 128, 128, 129, 130, 131, 132
, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 144, 145
, 146, 147, 148, 149, 150, 150, 151, 152, 153, 154, 155, 155, 156, 157
, 158, 159, 160, 160, 161, 162, 163, 163, 164, 165, 166, 167, 167, 168
, 169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176, 177, 178, 178
, 179, 180, 181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188
, 189, 189, 190, 191, 192, 192, 193, 193, 194, 195, 195, 196, 197, 197
, 198, 199, 199, 200, 201, 201, 202, 203, 203, 204, 204, 205, 206, 206
, 207, 208, 208, 209, 209, 210, 211, 211, 212, 212, 213, 214, 214, 215
, 215, 216, 217, 217, 218, 218, 219, 219, 220, 221, 221, 222, 222, 223
, 224, 224, 225, 225, 226, 226, 227, 227, 228, 229, 229, 230, 230, 231
, 231, 232, 232, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238
, 239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246
, 246, 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253
, 253, 254, 254, 255
};
tb_uint32_t xn;
if (x >= 0x7ffea810) return 0xb504;
if (x >= 0x10000)
{
if (x >= 0x1000000)
{
// lookup table
if (x >= 0x10000000)
{
if (x >= 0x40000000) xn = table[x >> 24] << 8;
else xn = table[x >> 22] << 7;
}
else
{
if (x >= 0x4000000) xn = table[x >> 20] << 6;
else xn = table[x >> 18] << 5;
}
// newton
xn = (xn + 1 + (x / xn)) >> 1;
xn = (xn + 1 + (x / xn)) >> 1;
return (((xn * xn) > x)? --xn : xn);
}
else
{
if (x >= 0x100000)
{
if (x >= 0x400000) xn = table[x >> 16] << 4;
else xn = table[x >> 14] << 3;
}
else
{
if (x >= 0x40000) xn = table[x >> 12] << 2;
else xn = table[x >> 10] << 1;
}
xn = (xn + 1 + (x / xn)) >> 1;
return (((xn * xn) > x)? --xn : xn);
}
}
else
{
if (x >= 0x100)
{
if (x >= 0x1000)
{
if (x >= 0x4000) xn = (table[x >> 8]) + 1;
else xn = (table[x >> 6] >> 1) + 1;
}
else
{
if (x >= 0x400) xn = (table[x >> 4] >> 2) + 1;
else xn = (table[x >> 2] >> 3) + 1;
}
return ((xn * xn) > x)? --xn : xn;
}
else
{
return (table[x] >> 4);
}
}
return ((tb_uint32_t)-1);
#elif 1
static tb_uint8_t const table[256] =
{
0, 16, 23, 28, 32, 36, 40, 43, 46, 48, 51, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 77, 79, 80, 82, 84, 85, 87, 88, 90
, 91, 92, 94, 95, 96, 98, 99, 100, 102, 103, 104, 105, 107, 108, 109, 110, 111, 112, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127
, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 144, 145, 146, 147, 148, 149, 150, 151, 151, 152, 153, 154, 155, 156, 156
, 157, 158, 159, 160, 160, 161, 162, 163, 164, 164, 165, 166, 167, 168, 168, 169, 170, 171, 171, 172, 173, 174, 174, 175, 176, 176, 177, 178, 179, 179, 180, 181
, 182, 182, 183, 184, 184, 185, 186, 186, 187, 188, 188, 189, 190, 190, 191, 192, 192, 193, 194, 194, 195, 196, 196, 197, 198, 198, 199, 200, 200, 201, 202, 202
, 203, 204, 204, 205, 205, 206, 207, 207, 208, 208, 209, 210, 210, 211, 212, 212, 213, 213, 214, 215, 215, 216, 216, 217, 218, 218, 219, 219, 220, 220, 221, 222
, 222, 223, 223, 224, 224, 225, 226, 226, 227, 227, 228, 228, 229, 230, 230, 231, 231, 232, 232, 233, 233, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239, 239
, 240, 240, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 253, 254, 254, 255, 255, 255
};
tb_uint32_t b = 0;
if (x < 255) return (table[x + 1] - 1) >> 4;
else if (x < (1 << 12)) b = table[x >> 4] >> 2;
else if (x < (1 << 14)) b = table[x >> 6] >> 1;
else if (x < (1 << 16)) b = table[x >> 8];
else
{
tb_uint32_t s = tb_ilog2i(x >> 16) >> 1;
tb_uint32_t c = x >> (s + 2);
b = table[c >> (s + 8)];
b = tb_idivi8(c, (tb_uint8_t)b) + (b << s);
}
return (b - (x < b * b));
#elif 0
// lookup bits
tb_uint32_t t;
tb_uint32_t n = 0;
tb_uint32_t b = 0x8000;
tb_uint32_t s = 15;
do
{
if (x >= (t = (((n << 1) + b) << s--)))
{
n += b;
x -= t;
}
}
while (b >>= 1);
return n;
#else
// lookup bits
tb_uint32_t i = 0;
tb_uint32_t r = 0;
tb_uint32_t n = 0;
tb_uint32_t d = 0;
for (i = 0; i < 16; i++)
{
n <<= 1;
r = ((r << 2) + (x >> 30));
x <<= 2;
d = (n << 1) + 1;
if (d <= r)
{
r -= d;
n++;
}
}
return n;
#endif
}
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
static __tb_inline__ tb_uint32_t tb_isqrti_impl_using_sqrt(tb_uint32_t x)
{
return (tb_uint32_t)tb_sqrtf((tb_float_t)x);
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_uint32_t tb_isqrti(tb_uint32_t x)
{
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
// using the sqrt function?
static tb_long_t s_using_sqrt = -1;
// analyze the profile
if (s_using_sqrt < 0)
{
// analyze isqrti
tb_hong_t t1 = tb_uclock();
__tb_volatile__ tb_size_t n1 = 200;
__tb_volatile__ tb_uint32_t v1; tb_used(&v1);
while (n1--)
{
v1 = tb_isqrti_impl((1 << 4) + 3);
v1 = tb_isqrti_impl((1 << 12) + 3);
v1 = tb_isqrti_impl((1 << 20) + 3);
v1 = tb_isqrti_impl((1 << 28) + 3);
}
t1 = tb_uclock() - t1;
// analyze sqrt
tb_hong_t t2 = tb_uclock();
__tb_volatile__ tb_size_t n2 = 200;
__tb_volatile__ tb_uint32_t v2; tb_used(&v2);
while (n2--)
{
v2 = tb_isqrti_impl_using_sqrt((1 << 4) + 3);
v2 = tb_isqrti_impl_using_sqrt((1 << 12) + 3);
v2 = tb_isqrti_impl_using_sqrt((1 << 20) + 3);
v2 = tb_isqrti_impl_using_sqrt((1 << 28) + 3);
}
t2 = tb_uclock() - t2;
// using sqrt?
s_using_sqrt = t2 < t1? 1 : 0;
}
// done
return s_using_sqrt > 0? tb_isqrti_impl_using_sqrt(x) : tb_isqrti_impl(x);
#else
return tb_isqrti_impl(x);
#endif
}
tbox-1.7.6/src/tbox/libm/isqrti64.c 0000664 0000000 0000000 00000007520 14671175054 0017036 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file isqrti.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include "../utils/utils.h"
#include "../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_uint32_t tb_isqrti64_impl(tb_uint64_t x)
{
// compute it fastly for uint32
if (!(x >> 32)) return tb_isqrti((tb_uint32_t)x);
// compute it for uint64
else
{
// done
tb_uint64_t t;
tb_uint64_t n = 0;
tb_uint64_t b = 0x80000000;
tb_uint32_t s = 31;
do
{
if (x >= (t = (((n << 1) + b) << s--)))
{
n += b;
x -= t;
}
}
while (b >>= 1);
// check
tb_assert(!(n >> 32));
// ok
return (tb_uint32_t)n;
}
}
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
static __tb_inline__ tb_uint32_t tb_isqrti64_impl_using_sqrt(tb_uint64_t x)
{
return (!(x >> 32))? (tb_uint32_t)tb_sqrtf((tb_float_t)x) : (tb_uint32_t)tb_sqrt((tb_double_t)x);
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_uint32_t tb_isqrti64(tb_uint64_t x)
{
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
// using the sqrt function?
static tb_long_t s_using_sqrt = -1;
// analyze the profile
if (s_using_sqrt < 0)
{
// analyze isqrti64
tb_hong_t t1 = tb_uclock();
__tb_volatile__ tb_size_t n1 = 100;
__tb_volatile__ tb_uint32_t v1; tb_used(&v1);
while (n1--)
{
v1 = tb_isqrti64_impl((1 << 4) + 3);
v1 = tb_isqrti64_impl((1 << 12) + 3);
v1 = tb_isqrti64_impl((1 << 20) + 3);
v1 = tb_isqrti64_impl((1 << 28) + 3);
v1 = tb_isqrti64_impl((1ULL << 36) + 3);
v1 = tb_isqrti64_impl((1ULL << 42) + 3);
v1 = tb_isqrti64_impl((1ULL << 50) + 3);
v1 = tb_isqrti64_impl((1ULL << 58) + 3);
v1 = tb_isqrti64_impl((1ULL << 60) + 3);
}
t1 = tb_uclock() - t1;
// analyze sqrt
tb_hong_t t2 = tb_uclock();
__tb_volatile__ tb_size_t n2 = 100;
__tb_volatile__ tb_uint32_t v2; tb_used(&v2);
while (n2--)
{
v2 = tb_isqrti64_impl_using_sqrt((1 << 4) + 3);
v2 = tb_isqrti64_impl_using_sqrt((1 << 12) + 3);
v2 = tb_isqrti64_impl_using_sqrt((1 << 20) + 3);
v2 = tb_isqrti64_impl_using_sqrt((1 << 28) + 3);
v2 = tb_isqrti64_impl_using_sqrt((1ULL << 36) + 3);
v2 = tb_isqrti64_impl_using_sqrt((1ULL << 42) + 3);
v2 = tb_isqrti64_impl_using_sqrt((1ULL << 50) + 3);
v2 = tb_isqrti64_impl_using_sqrt((1ULL << 58) + 3);
v2 = tb_isqrti64_impl_using_sqrt((1ULL << 60) + 3);
}
t2 = tb_uclock() - t2;
// using sqrt?
s_using_sqrt = t2 < t1? 1 : 0;
}
// done
return s_using_sqrt > 0? tb_isqrti64_impl_using_sqrt(x) : tb_isqrti64_impl(x);
#else
return tb_isqrti64_impl(x);
#endif
}
tbox-1.7.6/src/tbox/libm/libm.h 0000664 0000000 0000000 00000001571 14671175054 0016301 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file libm.h
* @defgroup libm
*
*/
#ifndef TB_LIBM_H
#define TB_LIBM_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#endif
tbox-1.7.6/src/tbox/libm/log2.c 0000664 0000000 0000000 00000002573 14671175054 0016217 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file log2f.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#if defined(TB_CONFIG_LIBM_HAVE_LOG2) && \
defined(TB_CONFIG_OS_ANDROID) && defined(__ANDROID_API__) && (__ANDROID_API__ < 18)
# undef TB_CONFIG_LIBM_HAVE_LOG2
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_double_t tb_log2(tb_double_t x)
{
#ifdef TB_CONFIG_LIBM_HAVE_LOG2
return log2(x);
#else
return log(x) * 1.44269504088896340736;
#endif
}
tbox-1.7.6/src/tbox/libm/log2f.c 0000664 0000000 0000000 00000002577 14671175054 0016371 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file log2f.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#if defined(TB_CONFIG_LIBM_HAVE_LOG2F) && \
defined(TB_CONFIG_OS_ANDROID) && defined(__ANDROID_API__) && (__ANDROID_API__ < 18)
# undef TB_CONFIG_LIBM_HAVE_LOG2F
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_float_t tb_log2f(tb_float_t x)
{
#ifdef TB_CONFIG_LIBM_HAVE_LOG2F
return log2f(x);
#else
return log(x) * 1.44269504088896340736f;
#endif
}
tbox-1.7.6/src/tbox/libm/maf.h 0000664 0000000 0000000 00000003370 14671175054 0016120 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file maf.h
* @ingroup libm
*
*/
#ifndef TB_LIBM_MAF_H
#define TB_LIBM_MAF_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#if defined(TB_COMPILER_IS_GCC) \
&& TB_COMPILER_VERSION_BE(3, 3)
# define TB_MAF (__builtin_huge_val())
#elif defined(TB_COMPILER_IS_GCC) && TB_COMPILER_VERSION_BE(2, 96)
# define TB_MAF (__extension__ 0x1.0p2047)
#elif defined(TB_COMPILER_IS_GCC)
# define TB_MAF (__extension__ ((union { unsigned __l __attribute__((__mode__(__DI__))); tb_double_t __d; }) { __l: 0x7ff0000000000000ULL }).__d)
#else
typedef union { tb_byte_t __c[8]; tb_double_t __d; } __tb_maf_t;
# ifdef TB_WORDS_BIGENDIAN
# define __tb_maf_bytes { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 }
# else
# define __tb_maf_bytes { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f }
# endif
static __tb_maf_t __tb_maf = { __tb_maf_bytes };
# define TB_MAF (__tb_maf.__d)
#endif
#endif
tbox-1.7.6/src/tbox/libm/math.h 0000664 0000000 0000000 00000006670 14671175054 0016314 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file math.h
* @ingroup libm
*
*/
#ifndef TB_LIBM_MATH_H
#define TB_LIBM_MATH_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
# include "nan.h"
# include "inf.h"
# include "maf.h"
# include "mif.h"
# include "pi.h"
# include "fabs.h"
# include "round.h"
# include "ceil.h"
# include "floor.h"
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
// is infinite?
tb_long_t tb_isinf(tb_double_t x);
tb_long_t tb_isinff(tb_float_t x);
// is finite?
tb_long_t tb_isfin(tb_double_t x);
tb_long_t tb_isfinf(tb_float_t x);
// is nan?
tb_long_t tb_isnan(tb_double_t x);
tb_long_t tb_isnanf(tb_float_t x);
// sqrt
tb_double_t tb_sqrt(tb_double_t x);
tb_float_t tb_sqrtf(tb_float_t x);
// sin
tb_double_t tb_sin(tb_double_t x);
tb_float_t tb_sinf(tb_float_t x);
// cos
tb_double_t tb_cos(tb_double_t x);
tb_float_t tb_cosf(tb_float_t x);
// tan
tb_double_t tb_tan(tb_double_t x);
tb_float_t tb_tanf(tb_float_t x);
// atan
tb_double_t tb_atan(tb_double_t x);
tb_float_t tb_atanf(tb_float_t x);
// exp
tb_double_t tb_exp(tb_double_t x);
tb_float_t tb_expf(tb_float_t x);
// expi
tb_double_t tb_expi(tb_long_t x);
tb_float_t tb_expif(tb_long_t x);
// exp1
tb_double_t tb_exp1(tb_double_t x);
tb_float_t tb_exp1f(tb_float_t x);
// asin
tb_double_t tb_asin(tb_double_t x);
tb_float_t tb_asinf(tb_float_t x);
// acos
tb_double_t tb_acos(tb_double_t x);
tb_float_t tb_acosf(tb_float_t x);
// atan2
tb_double_t tb_atan2(tb_double_t y, tb_double_t x);
tb_float_t tb_atan2f(tb_float_t y, tb_float_t x);
// log2
tb_double_t tb_log2(tb_double_t x);
tb_float_t tb_log2f(tb_float_t x);
// sincos
tb_void_t tb_sincos(tb_double_t x, tb_double_t* s, tb_double_t* c);
tb_void_t tb_sincosf(tb_float_t x, tb_float_t* s, tb_float_t* c);
// pow
tb_double_t tb_pow(tb_double_t x, tb_double_t y);
tb_float_t tb_powf(tb_float_t x, tb_float_t y);
// fmod
tb_double_t tb_fmod(tb_double_t x, tb_double_t y);
tb_float_t tb_fmodf(tb_float_t x, tb_float_t y);
#endif
// ilog2i
tb_uint32_t tb_ilog2i(tb_uint32_t x);
// isqrti
tb_uint32_t tb_isqrti(tb_uint32_t x);
tb_uint32_t tb_isqrti64(tb_uint64_t x);
// idivi8
tb_uint32_t tb_idivi8(tb_uint32_t x, tb_uint8_t y);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/libm/mif.h 0000664 0000000 0000000 00000002026 14671175054 0016125 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file mif.h
* @ingroup libm
*
*/
#ifndef TB_LIBM_MIF_H
#define TB_LIBM_MIF_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "maf.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define TB_MIF (-TB_MAF)
#endif
tbox-1.7.6/src/tbox/libm/nan.h 0000664 0000000 0000000 00000003105 14671175054 0016125 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file nan.h
* @ingroup libm
*
*/
#ifndef TB_LIBM_NAN_H
#define TB_LIBM_NAN_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#if defined(TB_COMPILER_IS_GCC) \
&& TB_COMPILER_VERSION_BE(3, 3)
# define TB_NAN (__builtin_nanf (""))
#elif defined(TB_COMPILER_IS_GCC)
# define TB_NAN (__extension__ ((union { unsigned __l __attribute__ ((__mode__ (__SI__))); tb_float_t __d; }) { __l: 0x7fc00000UL }).__d)
#else
# ifdef TB_WORDS_BIGENDIAN
# define __tb_nan_bytes { 0x7f, 0xc0, 0, 0 }
# else
# define __tb_nan_bytes { 0, 0, 0xc0, 0x7f }
# endif
static union { tb_byte_t __c[4]; tb_float_t __d; } __tb_nan_union = { __tb_nan_bytes };
# define TB_NAN (__tb_nan_union.__d)
#endif
#endif
tbox-1.7.6/src/tbox/libm/pi.h 0000664 0000000 0000000 00000002014 14671175054 0015757 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file pi.h
* @ingroup libm
*
*/
#ifndef TB_LIBM_PI_H
#define TB_LIBM_PI_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define TB_PI (3.141592653589793)
#endif
tbox-1.7.6/src/tbox/libm/pow.c 0000664 0000000 0000000 00000002146 14671175054 0016155 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file pow.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_double_t tb_pow(tb_double_t x, tb_double_t y)
{
#ifdef TB_CONFIG_LIBM_HAVE_POW
return pow(x, y);
#else
tb_assert(0);
return 0;
#endif
}
tbox-1.7.6/src/tbox/libm/powf.c 0000664 0000000 0000000 00000002154 14671175054 0016322 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file powf.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_float_t tb_powf(tb_float_t x, tb_float_t y)
{
#ifdef TB_CONFIG_LIBM_HAVE_POWF
return powf(x, y);
#else
return (tb_float_t)tb_pow(x, y);
#endif
}
tbox-1.7.6/src/tbox/libm/prefix.h 0000664 0000000 0000000 00000003110 14671175054 0016642 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
* @ingroup libm
*
*/
#ifndef TB_LIBM_PREFIX_H
#define TB_LIBM_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
// the ieee float type
typedef union __tb_ieee_float_t
{
tb_float_t f;
tb_uint32_t i;
}tb_ieee_float_t;
// the ieee double type
# ifdef TB_FLOAT_BIGENDIAN
typedef union __tb_ieee_double_t
{
tb_double_t d;
struct
{
tb_uint32_t h;
tb_uint32_t l;
}i;
}tb_ieee_double_t;
# else
typedef union __tb_ieee_double_t
{
tb_double_t d;
struct
{
tb_uint32_t l;
tb_uint32_t h;
}i;
}tb_ieee_double_t;
# endif
#endif
#endif
tbox-1.7.6/src/tbox/libm/round.h 0000664 0000000 0000000 00000002122 14671175054 0016476 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file round.h
* @ingroup libm
*
*/
#ifndef TB_LIBM_ROUND_H
#define TB_LIBM_ROUND_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define tb_round(x) ((x) > 0? (tb_int32_t)((x) + 0.5) : (tb_int32_t)((x) - 0.5))
#endif
tbox-1.7.6/src/tbox/libm/sin.c 0000664 0000000 0000000 00000002124 14671175054 0016135 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file sin.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_double_t tb_sin(tb_double_t x)
{
#ifdef TB_CONFIG_LIBM_HAVE_SIN
return sin(x);
#else
tb_assert(0);
return 0;
#endif
}
tbox-1.7.6/src/tbox/libm/sincos.c 0000664 0000000 0000000 00000002562 14671175054 0016650 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file sincos.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* declaration
*/
#ifdef TB_CONFIG_LIBM_HAVE_SINCOS
extern tb_void_t sincos(tb_double_t x, tb_double_t* s, tb_double_t* c);
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_void_t tb_sincos(tb_double_t x, tb_double_t* s, tb_double_t* c)
{
#ifdef TB_CONFIG_LIBM_HAVE_SINCOS
sincos(x, s, c);
#else
if (s) *s = tb_sin(x);
if (c) *c = tb_cos(x);
#endif
}
tbox-1.7.6/src/tbox/libm/sincosf.c 0000664 0000000 0000000 00000002226 14671175054 0017013 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file sincosf.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_void_t tb_sincosf(tb_float_t x, tb_float_t* s, tb_float_t* c)
{
#ifdef TB_CONFIG_LIBM_HAVE_SINCOSF
sincosf(x, s, c);
#else
if (s) *s = tb_sinf(x);
if (c) *c = tb_cosf(x);
#endif
}
tbox-1.7.6/src/tbox/libm/sinf.c 0000664 0000000 0000000 00000002130 14671175054 0016300 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file sinf.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_float_t tb_sinf(tb_float_t x)
{
#ifdef TB_CONFIG_LIBM_HAVE_SINF
return sinf(x);
#else
return (tb_float_t)tb_sin(x);
#endif
}
tbox-1.7.6/src/tbox/libm/sqrt.c 0000664 0000000 0000000 00000002130 14671175054 0016332 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file sqrt.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_double_t tb_sqrt(tb_double_t x)
{
#ifdef TB_CONFIG_LIBM_HAVE_SQRT
return sqrt(x);
#else
tb_assert(0);
return 0;
#endif
}
tbox-1.7.6/src/tbox/libm/sqrtf.c 0000664 0000000 0000000 00000002135 14671175054 0016505 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file sqrtf.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_float_t tb_sqrtf(tb_float_t x)
{
#ifdef TB_CONFIG_LIBM_HAVE_SQRTF
return sqrtf(x);
#else
return (tb_float_t)tb_sqrt(x);
#endif
}
tbox-1.7.6/src/tbox/libm/tan.c 0000664 0000000 0000000 00000002124 14671175054 0016126 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file tan.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_double_t tb_tan(tb_double_t x)
{
#ifdef TB_CONFIG_LIBM_HAVE_TAN
return tan(x);
#else
tb_assert(0);
return 0;
#endif
}
tbox-1.7.6/src/tbox/libm/tanf.c 0000664 0000000 0000000 00000002130 14671175054 0016271 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file tanf.c
* @ingroup libm
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_float_t tb_tanf(tb_float_t x)
{
#ifdef TB_CONFIG_LIBM_HAVE_TANF
return tanf(x);
#else
return (tb_float_t)tb_tan(x);
#endif
}
tbox-1.7.6/src/tbox/math/ 0000775 0000000 0000000 00000000000 14671175054 0015207 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/math/fixed.h 0000664 0000000 0000000 00000007262 14671175054 0016466 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file fixed.h
* @ingroup math
*
*/
#ifndef TB_MATH_FIXED_H
#define TB_MATH_FIXED_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "fixed6.h"
#include "fixed16.h"
#include "fixed30.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define TB_FIXED_ONE TB_FIXED16_ONE
#define TB_FIXED_HALF TB_FIXED16_HALF
#define TB_FIXED_MAX TB_FIXED16_MAX
#define TB_FIXED_MIN TB_FIXED16_MIN
#define TB_FIXED_NAN TB_FIXED16_NAN
#define TB_FIXED_INF TB_FIXED16_INF
#define TB_FIXED_PI TB_FIXED16_PI
#define TB_FIXED_SQRT2 TB_FIXED16_SQRT2
#define TB_FIXED_NEAR0 TB_FIXED16_NEAR0
// conversion
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
# define tb_fixed_to_float(x) tb_fixed16_to_float(x)
# define tb_float_to_fixed(x) tb_float_to_fixed16(x)
#endif
#define tb_long_to_fixed(x) tb_long_to_fixed16(x)
#define tb_fixed_to_long(x) tb_fixed16_to_long(x)
#define tb_fixed6_to_fixed(x) tb_fixed6_to_fixed16(x)
#define tb_fixed_to_fixed6(x) tb_fixed16_to_fixed6(x)
#define tb_fixed30_to_fixed(x) tb_fixed30_to_fixed16(x)
#define tb_fixed_to_fixed30(x) tb_fixed16_to_fixed30(x)
// round
#define tb_fixed_round(x) tb_fixed16_round(x)
#define tb_fixed_ceil(x) tb_fixed16_ceil(x)
#define tb_fixed_floor(x) tb_fixed16_floor(x)
// nearly equal?
#define tb_fixed_near_eq(x, y) tb_fixed16_near_eq(x, y)
// operations
#define tb_fixed_abs(x) tb_fixed16_abs(x)
#define tb_fixed_avg(x, y) tb_fixed16_avg(x, y)
#define tb_fixed_lsh(x, y) tb_fixed16_lsh(x, y)
#define tb_fixed_rsh(x, y) tb_fixed16_rsh(x, y)
#define tb_fixed_mul(x, y) tb_fixed16_mul(x, y)
#define tb_fixed_div(x, y) tb_fixed16_div(x, y)
#define tb_fixed_imul(x, y) tb_fixed16_imul(x, y)
#define tb_fixed_idiv(x, y) tb_fixed16_idiv(x, y)
#define tb_fixed_imuldiv(x, y, z) tb_fixed16_imuldiv(x, y, z)
#define tb_fixed_imulsub(x, y, z) tb_fixed16_imulsub(x, y, z)
#define tb_fixed_invert(x) tb_fixed16_invert(x)
#define tb_fixed_sqre(x) tb_fixed16_sqre(x)
#define tb_fixed_sqrt(x) tb_fixed16_sqrt(x)
#define tb_fixed_sin(x) tb_fixed16_sin(x)
#define tb_fixed_cos(x) tb_fixed16_cos(x)
#define tb_fixed_sincos(x, s, c) tb_fixed16_sincos(x, s, c)
#define tb_fixed_tan(x) tb_fixed16_tan(x)
#define tb_fixed_asin(x) tb_fixed16_asin(x)
#define tb_fixed_acos(x) tb_fixed16_acos(x)
#define tb_fixed_atan(x) tb_fixed16_atan(x)
#define tb_fixed_atan2(y, x) tb_fixed16_atan2(y, x)
#define tb_fixed_exp(x) tb_fixed16_exp(x)
#define tb_fixed_exp1(x) tb_fixed16_exp1(x)
#define tb_fixed_expi(x) tb_fixed16_expi(x)
#define tb_fixed_ilog2(x) tb_fixed16_ilog2(x)
#endif
tbox-1.7.6/src/tbox/math/fixed16.c 0000664 0000000 0000000 00000020377 14671175054 0016632 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file fixed16.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "fixed16.h"
#include "fixed30.h"
#include "int32.h"
#include "../utils/utils.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
#if 1
static tb_fixed16_t const tb_fixed16_cordic_atan2i_table[30] =
{
0x20000000 // 45.000000
, 0x12e4051d // 26.565051
, 0x9fb385b // 14.036243
, 0x51111d4 // 7.125016
, 0x28b0d43 // 3.576334
, 0x145d7e1 // 1.789911
, 0xa2f61e // 0.895174
, 0x517c55 // 0.447614
, 0x28be53 // 0.223811
, 0x145f2e // 0.111906
, 0xa2f98 // 0.055953
, 0x517cc // 0.027976
, 0x28be6 // 0.013988
, 0x145f3 // 0.006994
, 0xa2f9 // 0.003497
, 0x517c // 0.001749
, 0x28be // 0.000874
, 0x145f // 0.000437
, 0xa2f // 0.000219
, 0x517 // 0.000109
, 0x28b // 0.000055
, 0x145 // 0.000027
, 0xa2 // 0.000014
, 0x51 // 0.000007
, 0x28 // 0.000003
, 0x14 // 0.000002
, 0xa // 0.000001
, 0x5 // 0.000000
, 0x2 // 0.000000
, 0x1 // 0.000000
};
#else
static tb_fixed16_t const tb_fixed16_cordic_atan2i_table[16] =
{
0x1fff9122 // 45.000000
, 0x12e3bf5e // 26.565051
, 0x9fafb14 // 14.036243
, 0x510e816 // 7.125016
, 0x28aeb8c // 3.576334
, 0x145c742 // 1.789911
, 0xa2cf42 // 0.895174
, 0x515342 // 0.447614
, 0x289542 // 0.223811
, 0x143642 // 0.111906
, 0xa06c2 // 0.055953
, 0x4ef02 // 0.027976
, 0x26322 // 0.013988
, 0x11d32 // 0.006994
, 0x7a3a // 0.003497
, 0x28be // 0.001749
};
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
// |angle| < 90 degrees
static tb_void_t tb_fixed16_cordic_rotation(tb_fixed30_t* x0, tb_fixed30_t* y0, tb_fixed16_t z0)
{
tb_int_t i = 0;
tb_fixed16_t atan2i = 0;
tb_fixed16_t z = z0;
tb_fixed30_t x = *x0;
tb_fixed30_t y = *y0;
tb_fixed30_t xi = 0;
tb_fixed30_t yi = 0;
tb_fixed16_t const* patan2i = tb_fixed16_cordic_atan2i_table;
do
{
xi = x >> i;
yi = y >> i;
#if 1
atan2i = *patan2i++;
#elif 0
atan2i = tb_double_to_fixed16(atan(1. / (1 << i)) * (1 << 15) / TB_DOUBLE_PI);
//tb_printf(",\t0x%x\t// %lf\n", atan2i, atan(1. / (1 << i)) * 180 / TB_DOUBLE_PI);
#else
//atan2i = tb_double_to_fixed16(atan(1. / (1 << i))) * 0x28be;
//tb_printf(",\t0x%x\t// %lf\n", atan2i, atan(1. / (1 << i)) * 180 / TB_DOUBLE_PI);
#endif
if (z >= 0)
{
x -= yi;
y += xi;
z -= atan2i;
}
else
{
x += yi;
y -= xi;
z += atan2i;
}
} while (++i < 16);
*x0 = x;
*y0 = y;
}
// |angle| < 90 degrees
static tb_fixed16_t tb_fixed16_cordic_vector_atan2(tb_fixed16_t y0, tb_fixed16_t x0)
{
tb_int_t i = 0;
tb_fixed16_t atan2i = 0;
tb_fixed16_t z = 0;
tb_fixed16_t x = x0;
tb_fixed16_t y = y0;
tb_fixed16_t xi = 0;
tb_fixed16_t yi = 0;
tb_fixed16_t const* patan2i = tb_fixed16_cordic_atan2i_table;
do
{
xi = x >> i;
yi = y >> i;
atan2i = *patan2i++;
if (y < 0)
{
x -= yi;
y += xi;
z -= atan2i;
}
else
{
x += yi;
y -= xi;
z += atan2i;
}
} while (++i < 16);
return z / 0x28be;
}
// |angle| < 90 degrees
static tb_fixed16_t tb_fixed16_cordic_vector_asin(tb_fixed16_t m)
{
tb_int_t i = 0;
tb_fixed16_t atan2i = 0;
tb_fixed16_t z = 0;
tb_fixed16_t x = 0x18bde0bb; // k = 0.607252935
tb_fixed16_t y = 0;
tb_fixed16_t xi = 0;
tb_fixed16_t yi = 0;
tb_fixed16_t const* patan2i = tb_fixed16_cordic_atan2i_table;
do
{
xi = x >> i;
yi = y >> i;
atan2i = *patan2i++;
if (y < m)
{
x -= yi;
y += xi;
z -= atan2i;
}
else
{
x += yi;
y -= xi;
z += atan2i;
}
} while (++i < 16);
return z / 0x28be;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_fixed16_t tb_fixed16_invert_int32(tb_fixed16_t x)
{
// is one?
if (x == TB_FIXED16_ONE) return TB_FIXED16_ONE;
// get sign
tb_int32_t s = tb_int32_get_sign(x);
// abs(x)
x = tb_fixed16_abs(x);
// is infinity?
if (x <= 2) return tb_int32_set_sign(TB_FIXED16_MAX, s);
// normalize
tb_int32_t cl0 = (tb_int32_t)tb_bits_cl0_u32_be(x);
x = x << cl0 >> 16;
// compute 1 / x approximation (0.5 <= x < 1.0)
// (2.90625 (~2.914) - 2 * x) >> 1
tb_uint32_t r = 0x17400 - x;
// newton-raphson iteration:
// x = r * (2 - x * r) = ((r / 2) * (1 - x * r / 2)) * 4
r = ((0x10000 - ((x * r) >> 16)) * r) >> 15;
r = ((0x10000 - ((x * r) >> 16)) * r) >> (30 - cl0);
return tb_int32_set_sign(r, s);
}
tb_void_t tb_fixed16_sincos_int32(tb_fixed16_t x, tb_fixed16_t* s, tb_fixed16_t* c)
{
// (x0, y0) = (k, 0), k = 0.607252935 => fixed30
tb_fixed30_t cos = 0x26dd3b6a;
tb_fixed30_t sin = 0;
/* scale to 65536 degrees from x radians: x * 65536 / (2 * pi)
*
* 90: 0x40000000
* 180: 0x80000000
* 270: 0xc0000000
*/
tb_fixed16_t ang = x * 0x28be;
/* quadrant
*
* 1: 00 ...
* 2: 01 ...
* 3: 10 ...
* 4: 11 ...
*
* quadrant++
*
* 1: 01 ...
* 2: 10 ...
* 3: 11 ...
* 4: 00 ...
*
*/
tb_int_t quadrant = ang >> 30;
quadrant++;
/* quadrant == 2, 3, |angle| < 90
*
* 100 => -100 + 180 => 80
* -200 => 200 + 180 => -20
*/
if (quadrant & 0x2) ang = -ang + 0x80000000;
// rotation
tb_fixed16_cordic_rotation(&cos, &sin, ang);
// result
if (s)
{
// return sin
*s = tb_fixed30_to_fixed16(sin);
}
if (c)
{
// quadrant == 2, 3
if (quadrant & 0x2) cos = -cos;
// return cos
*c = tb_fixed30_to_fixed16(cos);
}
}
// slope angle: [-180, 180]
// the precision will be pool if x, y is too small
tb_fixed16_t tb_fixed16_atan2_int32(tb_fixed16_t y, tb_fixed16_t x)
{
if (!(x | y)) return 0;
// abs
tb_int32_t xs = tb_int32_get_sign(x);
x = tb_fixed30_abs(x);
// quadrant: 1, 4
tb_fixed16_t z = tb_fixed16_cordic_vector_atan2(y, x);
// for quadrant: 2, 3
if (xs)
{
tb_int32_t zs = tb_int32_get_sign(z);
if (y == 0) zs = 0;
tb_fixed16_t pi = tb_int32_set_sign(TB_FIXED16_PI, zs);
z = pi - z;
}
return z;
}
tb_fixed16_t tb_fixed16_asin_int32(tb_fixed16_t x)
{
// abs
tb_int32_t s = tb_int32_get_sign(x);
x = tb_fixed16_abs(x);
if (x >= TB_FIXED16_ONE) return tb_int32_set_sign(TB_FIXED16_PI >> 1, s);
tb_fixed16_t z = tb_fixed16_cordic_vector_asin(x * 0x28be);
return tb_int32_set_sign(z, ~s);
}
// |angle| < 90
// the precision will be pool if x is too large.
tb_fixed16_t tb_fixed16_atan_int32(tb_fixed16_t x)
{
if (!x) return 0;
return tb_fixed16_cordic_vector_atan2(x, TB_FIXED16_ONE);
}
tb_fixed16_t tb_fixed16_exp_int32(tb_fixed16_t x)
{
tb_trace_noimpl();
return 0;
}
tbox-1.7.6/src/tbox/math/fixed16.h 0000664 0000000 0000000 00000033305 14671175054 0016632 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file fixed16.h
* @ingroup math
*
*/
#ifndef TB_MATH_FIXED16_H
#define TB_MATH_FIXED16_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "int32.h"
#include "../libm/libm.h"
#ifdef TB_ARCH_ARM
# include "impl/fixed16_arm.h"
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// constant
#define TB_FIXED16_ONE (1 << 16)
#define TB_FIXED16_HALF (1 << 15)
#define TB_FIXED16_MAX (TB_MAXS32)
#define TB_FIXED16_MIN (TB_MINS32)
#define TB_FIXED16_NAN ((tb_int_t)0x80000000)
#define TB_FIXED16_INF (TB_MAXS32)
#define TB_FIXED16_PI (0x3243f)
#define TB_FIXED16_SQRT2 (92682)
#define TB_FIXED16_NEAR0 (1 << 4)
// conversion
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
# ifndef tb_fixed16_to_float
# define tb_fixed16_to_float(x) ((tb_float_t)((x) * 1.5258789e-5))
# endif
# ifndef tb_float_to_fixed16
# define tb_float_to_fixed16(x) ((tb_fixed16_t)((x) * TB_FIXED16_ONE))
# endif
#endif
#ifdef __tb_debug__
# define tb_long_to_fixed16(x) tb_long_to_fixed16_check(x)
# define tb_fixed16_to_long(x) tb_fixed16_to_long_check(x)
#else
# define tb_long_to_fixed16(x) (tb_fixed16_t)((x) << 16)
# define tb_fixed16_to_long(x) (tb_long_t)((x) >> 16)
#endif
// round
#define tb_fixed16_round(x) (((x) + TB_FIXED16_HALF) >> 16)
// ceil
#define tb_fixed16_ceil(x) (((x) + TB_FIXED16_ONE - 1) >> 16)
// floor
#define tb_fixed16_floor(x) ((x) >> 16)
// abs
#define tb_fixed16_abs(x) tb_abs(x)
// avg
#define tb_fixed16_avg(x, y) (((x) + (y)) >> 1)
// nearly equal?
#define tb_fixed16_near_eq(x, y) (tb_fixed16_abs((x) - (y)) <= TB_FIXED16_NEAR0)
// mul
#ifndef tb_fixed16_mul
# ifdef __tb_debug__
# define tb_fixed16_mul(x, y) tb_fixed16_mul_check(x, y)
# else
# define tb_fixed16_mul(x, y) ((tb_fixed16_t)(((tb_hong_t)(x) * (y)) >> 16))
# endif
#endif
// div
#ifndef tb_fixed16_div
# ifdef __tb_debug__
# define tb_fixed16_div(x, y) tb_fixed16_div_check(x, y)
# else
# define tb_fixed16_div(x, y) ((tb_fixed16_t)((((tb_hong_t)(x)) << 16) / (y)))
# endif
#endif
// imul
#ifndef tb_fixed16_imul
# ifdef __tb_debug__
# define tb_fixed16_imul(x, y) tb_fixed16_imul_check(x, y)
# else
# define tb_fixed16_imul(x, y) ((tb_fixed16_t)((x) * (y)))
# endif
#endif
// idiv
#ifndef tb_fixed16_idiv
# ifdef __tb_debug__
# define tb_fixed16_idiv(x, y) tb_fixed16_idiv_check(x, y)
# else
# define tb_fixed16_idiv(x, y) ((tb_fixed16_t)((x) / (y)))
# endif
#endif
// imuldiv
#ifndef tb_fixed16_imuldiv
# ifdef __tb_debug__
# define tb_fixed16_imuldiv(x, y, z) tb_fixed16_imuldiv_check(x, y, z)
# else
# define tb_fixed16_imuldiv(x, y, z) ((tb_fixed16_t)(((tb_hong_t)(x) * (y)) / (z)))
# endif
#endif
// imulsub
#ifndef tb_fixed16_imulsub
# ifdef __tb_debug__
# define tb_fixed16_imulsub(x, y, z) tb_fixed16_imulsub_check(x, y, z)
# else
# define tb_fixed16_imulsub(x, y, z) ((tb_fixed16_t)(((tb_hong_t)(x) * (y)) - (z)))
# endif
#endif
// lsh
#ifndef tb_fixed16_lsh
# define tb_fixed16_lsh(x, y) ((x) << (y))
#endif
// rsh
#ifndef tb_fixed16_rsh
# define tb_fixed16_rsh(x, y) ((x) >> (y))
#endif
// invert: 1 / x
#ifndef tb_fixed16_invert
# define tb_fixed16_invert(x) tb_fixed16_div(TB_FIXED16_ONE, x)
#endif
// sqre
#ifndef tb_fixed16_sqre
# ifdef __tb_debug__
# define tb_fixed16_sqre(x) tb_fixed16_sqre_check(x)
# else
# define tb_fixed16_sqre(x) ((tb_fixed16_t)(((tb_hong_t)(x) * (x)) >> 16))
# endif
#endif
// sqrt
#ifndef tb_fixed16_sqrt
# define tb_fixed16_sqrt(x) tb_fixed16_sqrt_int32(x)
#endif
// sin
#ifndef tb_fixed16_sin
# ifdef TB_CONFIG_TYPE_HAVE_FLOAT
# define tb_fixed16_sin(x) tb_fixed16_sin_float(x)
# else
# define tb_fixed16_sin(x) tb_fixed16_sin_int32(x)
# endif
#endif
// cos
#ifndef tb_fixed16_cos
# ifdef TB_CONFIG_TYPE_HAVE_FLOAT
# define tb_fixed16_cos(x) tb_fixed16_cos_float(x)
# else
# define tb_fixed16_cos(x) tb_fixed16_cos_int32(x)
# endif
#endif
// sincos
#ifndef tb_fixed16_sincos
# ifdef TB_CONFIG_TYPE_HAVE_FLOAT
# define tb_fixed16_sincos(x, s, c) tb_fixed16_sincos_float(x, s, c)
# else
# define tb_fixed16_sincos(x, s, c) tb_fixed16_sincos_int32(x, s, c)
# endif
#endif
// tan
#ifndef tb_fixed16_tan
# ifdef TB_CONFIG_TYPE_HAVE_FLOAT
# define tb_fixed16_tan(x) tb_fixed16_tan_float(x)
# else
# define tb_fixed16_tan(x) tb_fixed16_tan_int32(x)
# endif
#endif
// asin
#ifndef tb_fixed16_asin
# ifdef TB_CONFIG_TYPE_HAVE_FLOAT
# define tb_fixed16_asin(x) tb_fixed16_asin_float(x)
# else
# define tb_fixed16_asin(x) tb_fixed16_asin_int32(x)
# endif
#endif
// acos
#ifndef tb_fixed16_acos
# ifdef TB_CONFIG_TYPE_HAVE_FLOAT
# define tb_fixed16_acos(x) tb_fixed16_acos_float(x)
# else
# define tb_fixed16_acos(x) tb_fixed16_acos_int32(x)
# endif
#endif
// atan
#ifndef tb_fixed16_atan
# ifdef TB_CONFIG_TYPE_HAVE_FLOAT
# define tb_fixed16_atan(x) tb_fixed16_atan_float(x)
# else
# define tb_fixed16_atan(x) tb_fixed16_atan_int32(x)
# endif
#endif
// atan2
#ifndef tb_fixed16_atan2
# ifdef TB_CONFIG_TYPE_HAVE_FLOAT
# define tb_fixed16_atan2(y, x) tb_fixed16_atan2_float(y, x)
# else
# define tb_fixed16_atan2(y, x) tb_fixed16_atan2_int32(y, x)
# endif
#endif
// exp
#ifndef tb_fixed16_exp
# ifdef TB_CONFIG_TYPE_HAVE_FLOAT
# define tb_fixed16_exp(x) tb_fixed16_exp_float(x)
# else
# define tb_fixed16_exp(x) tb_fixed16_exp_int32(x)
# endif
#endif
#ifndef tb_fixed16_expi
# ifdef TB_CONFIG_TYPE_HAVE_FLOAT
# define tb_fixed16_expi(x) tb_fixed16_expi_float(x)
# else
# define tb_fixed16_expi(x) tb_assert(0)
# endif
#endif
#ifndef tb_fixed16_exp1
# ifdef TB_CONFIG_TYPE_HAVE_FLOAT
# define tb_fixed16_exp1(x) tb_fixed16_exp1_float(x)
# else
# define tb_fixed16_exp1(x) tb_assert(0)
# endif
#endif
// log
#ifndef tb_fixed16_ilog2
# define tb_fixed16_ilog2(x) tb_fixed16_ilog2_int32(x)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! compute the invert of the fixed-point value
*
* @param x the fixed-point x-value
*
* @return the result
*/
tb_fixed16_t tb_fixed16_invert_int32(tb_fixed16_t x);
/*! compute the sin and cos value of the fixed-point value
*
* @param x the fixed-point x-value
* @param s the sin fixed-point value
* @param c the cos fixed-point value
*/
tb_void_t tb_fixed16_sincos_int32(tb_fixed16_t x, tb_fixed16_t* s, tb_fixed16_t* c);
/*! compute the atan2 value of the fixed-point value
*
* @param y the fixed-point y-value
* @param x the fixed-point x-value
*
* @return the result
*/
tb_fixed16_t tb_fixed16_atan2_int32(tb_fixed16_t y, tb_fixed16_t x);
/*! compute the asin value of the fixed-point value
*
* @param x the fixed-point x-value
*
* @return the result
*/
tb_fixed16_t tb_fixed16_asin_int32(tb_fixed16_t x);
/*! compute the atan value of the fixed-point value
*
* @param x the fixed-point x-value
*
* @return the result
*/
tb_fixed16_t tb_fixed16_atan_int32(tb_fixed16_t x);
/*! compute the exp value of the fixed-point value
*
* @param x the fixed-point x-value
*
* @return the result
*/
tb_fixed16_t tb_fixed16_exp_int32(tb_fixed16_t x);
/* //////////////////////////////////////////////////////////////////////////////////////
* inlines
*/
static __tb_inline__ tb_fixed16_t tb_long_to_fixed16_check(tb_long_t x)
{
// check overflow
tb_assert(x == (tb_int16_t)x);
// ok
return (tb_fixed16_t)(x << 16);
}
static __tb_inline__ tb_long_t tb_fixed16_to_long_check(tb_fixed16_t x)
{
// check overflow
tb_assert(x >= TB_FIXED16_MIN && x <= TB_FIXED16_MAX);
// ok
return (x >> 16);
}
static __tb_inline__ tb_fixed16_t tb_fixed16_mul_check(tb_fixed16_t x, tb_fixed16_t y)
{
// done
tb_hong_t v = (((tb_hong_t)x * y) >> 16);
// check overflow
tb_assert(v == (tb_int32_t)v);
// ok
return (tb_fixed16_t)v;
}
static __tb_inline__ tb_fixed16_t tb_fixed16_div_check(tb_fixed16_t x, tb_fixed16_t y)
{
// check
tb_assert(y);
// done
tb_hong_t v = ((((tb_hong_t)x) << 16) / y);
// check overflow
tb_assert(v == (tb_int32_t)v);
// ok
return (tb_fixed16_t)v;
}
static __tb_inline__ tb_fixed16_t tb_fixed16_sqre_check(tb_fixed16_t x)
{
// done
tb_hong_t v = (((tb_hong_t)x * x) >> 16);
// check overflow
tb_assert(v == (tb_int32_t)v);
// ok
return (tb_fixed16_t)v;
}
static __tb_inline__ tb_fixed16_t tb_fixed16_imul_check(tb_fixed16_t x, tb_long_t y)
{
// done
tb_hong_t v = ((tb_hong_t)x * y);
// check overflow
tb_assert(v == (tb_int32_t)v);
// ok
return (tb_fixed16_t)v;
}
static __tb_inline__ tb_fixed16_t tb_fixed16_idiv_check(tb_fixed16_t x, tb_long_t y)
{
// check
tb_assert(y);
// ok
return (tb_fixed16_t)(x / y);
}
static __tb_inline__ tb_fixed16_t tb_fixed16_imuldiv_check(tb_fixed16_t x, tb_long_t y, tb_long_t z)
{
// done
tb_hong_t v = ((tb_hong_t)x * y) / z;
// check overflow
tb_assert(v == (tb_int32_t)v);
// ok
return (tb_fixed16_t)v;
}
static __tb_inline__ tb_fixed16_t tb_fixed16_imulsub_check(tb_fixed16_t x, tb_long_t y, tb_long_t z)
{
// done
tb_hong_t v = ((tb_hong_t)x * y) - z;
// check overflow
tb_assert(v == (tb_int32_t)v);
// ok
return (tb_fixed16_t)v;
}
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
static __tb_inline__ tb_fixed16_t tb_fixed16_sin_float(tb_fixed16_t x)
{
return tb_float_to_fixed16(tb_sinf(tb_fixed16_to_float(x)));
}
static __tb_inline__ tb_fixed16_t tb_fixed16_cos_float(tb_fixed16_t x)
{
return tb_float_to_fixed16(tb_cosf(tb_fixed16_to_float(x)));
}
static __tb_inline__ tb_void_t tb_fixed16_sincos_float(tb_fixed16_t x, tb_fixed16_t* s, tb_fixed16_t* c)
{
tb_float_t sf, cf;
tb_sincosf(tb_fixed16_to_float(x), &sf, &cf);
if (s) *s = tb_float_to_fixed16(sf);
if (s) *c = tb_float_to_fixed16(cf);
}
static __tb_inline__ tb_fixed16_t tb_fixed16_tan_float(tb_fixed16_t x)
{
return tb_float_to_fixed16(tb_tanf(tb_fixed16_to_float(x)));
}
static __tb_inline__ tb_fixed16_t tb_fixed16_asin_float(tb_fixed16_t x)
{
return tb_float_to_fixed16(tb_asinf(tb_fixed16_to_float(x)));
}
static __tb_inline__ tb_fixed16_t tb_fixed16_acos_float(tb_fixed16_t x)
{
return tb_float_to_fixed16(tb_acosf(tb_fixed16_to_float(x)));
}
static __tb_inline__ tb_fixed16_t tb_fixed16_atan_float(tb_fixed16_t x)
{
return tb_float_to_fixed16(tb_atanf(tb_fixed16_to_float(x)));
}
static __tb_inline__ tb_fixed16_t tb_fixed16_atan2_float(tb_fixed16_t y, tb_fixed16_t x)
{
return tb_float_to_fixed16(tb_atan2f(tb_fixed16_to_float(y), tb_fixed16_to_float(x)));
}
static __tb_inline__ tb_fixed16_t tb_fixed16_exp_float(tb_fixed16_t x)
{
return tb_float_to_fixed16(tb_expf(tb_fixed16_to_float(x)));
}
static __tb_inline__ tb_fixed16_t tb_fixed16_exp1_float(tb_fixed16_t x)
{
return tb_float_to_fixed16(tb_exp1f(tb_fixed16_to_float(x)));
}
static __tb_inline__ tb_fixed16_t tb_fixed16_expi_float(tb_long_t x)
{
return tb_float_to_fixed16(tb_expif(x));
}
#endif
static __tb_inline__ tb_fixed16_t tb_fixed16_sqrt_int32(tb_fixed16_t x)
{
tb_assert(x > 0);
return (x > 0? (tb_isqrti(x) << 8) : 0);
}
static __tb_inline__ tb_uint32_t tb_fixed16_ilog2_int32(tb_fixed16_t x)
{
tb_assert(x > 0);
tb_uint32_t lg = tb_ilog2i(x);
return (lg > 16? (lg - 16) : 0);
}
static __tb_inline__ tb_fixed16_t tb_fixed16_sin_int32(tb_fixed16_t x)
{
tb_fixed16_t s = 0;
tb_fixed16_sincos_int32(x, &s, tb_null);
return s;
}
static __tb_inline__ tb_fixed16_t tb_fixed16_cos_int32(tb_fixed16_t x)
{
tb_fixed16_t c = 0;
tb_fixed16_sincos_int32(x, tb_null, &c);
return c;
}
static __tb_inline__ tb_fixed16_t tb_fixed16_tan_int32(tb_fixed16_t x)
{
tb_fixed16_t s = 0;
tb_fixed16_t c = 0;
tb_fixed16_sincos_int32(x, &s, &c);
return tb_fixed16_div(s, c);
}
static __tb_inline__ tb_fixed16_t tb_fixed16_acos_int32(tb_fixed16_t x)
{
// asin + acos = pi / 2
tb_fixed16_t z = tb_fixed16_asin_int32(x);
return ((TB_FIXED16_PI >> 1) - z);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/math/fixed30.h 0000664 0000000 0000000 00000014500 14671175054 0016622 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file fixed30.h
* @ingroup math
*
*/
#ifndef TB_MATH_FIXED30_H
#define TB_MATH_FIXED30_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "int32.h"
#include "../libm/libm.h"
#ifdef TB_ARCH_ARM
# include "impl/fixed16_arm.h"
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// constant
#define TB_FIXED30_ONE (1 << 30)
#define TB_FIXED30_HALF (1 << 29)
#define TB_FIXED30_MAX (TB_MAXS32)
#define TB_FIXED30_MIN (-TB_FIXED30_MAX)
#define TB_FIXED30_NAN ((tb_int_t)0x80000000)
#define TB_FIXED30_INF (TB_MAXS32)
#define TB_FIXED30_SQRT2 (0x5a827999)
// conversion
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
# ifndef tb_fixed30_to_float
# define tb_fixed30_to_float(x) (((x) * 0.00000000093132257f))
# endif
# ifndef tb_float_to_fixed30
# ifdef __tb_debug__
# define tb_float_to_fixed30(x) tb_float_to_fixed30_check(x)
# else
# define tb_float_to_fixed30(x) ((tb_fixed30_t)((x) * TB_FIXED30_ONE))
# endif
# endif
#endif
#ifdef __tb_debug__
# define tb_fixed16_to_fixed30(x) tb_fixed16_to_fixed30_check(x)
#else
# define tb_fixed16_to_fixed30(x) ((x) << 14)
#endif
#define tb_fixed30_to_fixed16(x) ((x) >> 14)
// abs
#define tb_fixed30_abs(x) tb_abs(x)
// avg
#define tb_fixed30_avg(x, y) (((x) + (y)) >> 1)
// mul
#ifndef tb_fixed30_mul
# if 1
# define tb_fixed30_mul(x, y) tb_fixed30_mul_int64(x, y)
# elif defined(TB_CONFIG_TYPE_HAVE_FLOAT)
# define tb_fixed30_mul(x, y) tb_fixed30_mul_float(x, y)
# else
# define tb_fixed30_mul(x, y) tb_fixed30_mul_int32(x, y)
# endif
#endif
// div
#ifndef tb_fixed30_div
# if 1
# define tb_fixed30_div(x, y) tb_fixed30_div_int64(x, y)
# elif defined(TB_CONFIG_TYPE_HAVE_FLOAT)
# define tb_fixed30_div(x, y) tb_fixed30_div_float(x, y)
# else
# define tb_fixed30_div(x, y) tb_int32_div(x, y, 30)
# endif
#endif
// sqre
#ifndef tb_fixed30_sqre
# if 1
# define tb_fixed30_sqre(x) tb_fixed30_sqre_int64(x)
# elif defined(TB_CONFIG_TYPE_HAVE_FLOAT)
# define tb_fixed30_sqre(x) tb_fixed30_sqre_float(x)
# else
# define tb_fixed30_sqre(x) tb_fixed30_sqre_int32(x)
# endif
#endif
// sqrt
#ifndef tb_fixed30_sqrt
# define tb_fixed30_sqrt(x) tb_fixed30_sqrt_int32(x)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* inlines
*/
#ifdef __tb_debug__
# ifdef TB_CONFIG_TYPE_HAVE_FLOAT
static __tb_inline__ tb_fixed30_t tb_float_to_fixed30_check(tb_float_t x)
{
// check overflow, [-2., 2.]
tb_assert(x >= -2. && x <= 2.);
return ((tb_fixed30_t)((x) * TB_FIXED30_ONE));
}
# endif
static __tb_inline__ tb_fixed30_t tb_fixed16_to_fixed30_check(tb_fixed16_t x)
{
// check overflow, [-2, 2]
tb_assert((x >> 16) >= -2 && (x >> 16) <= 2);
return (x << 14);
}
#endif
static __tb_inline__ tb_fixed30_t tb_fixed30_mul_int64(tb_fixed30_t x, tb_fixed30_t y)
{
return (tb_fixed30_t)((tb_hong_t)x * y >> 30);
}
static __tb_inline__ tb_fixed30_t tb_fixed30_div_int64(tb_fixed30_t x, tb_fixed30_t y)
{
tb_assert(y);
return (tb_fixed30_t)((((tb_hong_t)x) << 30) / y);
}
static __tb_inline__ tb_fixed30_t tb_fixed30_sqre_int64(tb_fixed30_t x)
{
return (tb_fixed30_t)((tb_hong_t)x * x >> 30);
}
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
static __tb_inline__ tb_fixed30_t tb_fixed30_mul_float(tb_fixed30_t x, tb_fixed30_t y)
{
tb_float_t f = tb_fixed30_to_float(x) * tb_fixed30_to_float(y);
return tb_float_to_fixed30(f);
}
static __tb_inline__ tb_fixed30_t tb_fixed30_div_float(tb_fixed30_t x, tb_fixed30_t y)
{
tb_assert(y);
return tb_float_to_fixed30((tb_float_t)x / y);
}
static __tb_inline__ tb_fixed30_t tb_fixed30_sqre_float(tb_fixed30_t x)
{
tb_float_t f = tb_fixed30_to_float(x);
f *= f;
return tb_float_to_fixed30(f);
}
#endif
static __tb_inline__ tb_fixed30_t tb_fixed30_mul_int32(tb_fixed30_t x, tb_fixed30_t y)
{
// get sign
tb_int32_t s = tb_int32_get_sign(x ^ y);
x = tb_fixed30_abs(x);
y = tb_fixed30_abs(y);
tb_uint32_t xh = x >> 16;
tb_uint32_t xl = x & 0xffff;
tb_uint32_t yh = y >> 16;
tb_uint32_t yl = y & 0xffff;
tb_uint32_t xyh = xh * yh;
tb_uint32_t xyl = xl * yl;
tb_uint32_t xyhl = xh * yl + xl * yh;
tb_uint32_t lo = xyl + (xyhl << 16);
tb_uint32_t hi = xyh + (xyhl >> 16) + (lo < xyl);
// check overflow
tb_assert(!(hi >> 29));
tb_uint32_t r = (hi << 2) + (lo >> 30);
return tb_int32_set_sign(r, s);
}
static __tb_inline__ tb_fixed30_t tb_fixed30_sqre_int32(tb_fixed30_t x)
{
x = tb_fixed30_abs(x);
tb_uint32_t xh = x >> 16;
tb_uint32_t xl = x & 0xffff;
tb_uint32_t xxh = xh * xh;
tb_uint32_t xxl = xl * xl;
tb_uint32_t xxhl = (xh * xl) << 1;
tb_uint32_t lo = xxl + (xxhl << 16);
tb_uint32_t hi = xxh + (xxhl >> 16) + (lo < xxl);
// check overflow
tb_assert(!(hi >> 29));
return ((hi << 2) + (lo >> 30));
}
static __tb_inline__ tb_fixed30_t tb_fixed30_sqrt_int32(tb_fixed30_t x)
{
tb_assert(x > 0);
return (x > 0? (tb_isqrti(x) << 15) : 0);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/math/fixed6.h 0000664 0000000 0000000 00000011605 14671175054 0016550 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file fixed6.h
* @ingroup math
*
*/
#ifndef TB_MATH_FIXED6_H
#define TB_MATH_FIXED6_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "fixed16.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// constant
#define TB_FIXED6_ONE (64)
#define TB_FIXED6_HALF (32)
#define TB_FIXED6_MAX (TB_MAXS32)
#define TB_FIXED6_MIN (TB_MINS32)
#define TB_FIXED6_NAN ((tb_int_t)0x80000000)
#define TB_FIXED6_INF (TB_MAXS32)
#define TB_FIXED6_PI (0xc9)
#define TB_FIXED6_SQRT2 (0x5a)
#define TB_FIXED6_NEAR0 (0)
// conversion
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
# ifndef tb_fixed6_to_float
# define tb_fixed6_to_float(x) (((x) * 0.015625))
# endif
# ifndef tb_float_to_fixed6
# define tb_float_to_fixed6(x) ((tb_fixed6_t)((x) * TB_FIXED6_ONE))
# endif
#endif
#ifdef __tb_debug__
# define tb_int_to_fixed6(x) tb_long_to_fixed6_check(x)
# define tb_fixed6_to_int(x) tb_fixed6_to_long_check(x)
# define tb_long_to_fixed6(x) tb_long_to_fixed6_check(x)
# define tb_fixed6_to_long(x) tb_fixed6_to_long_check(x)
#else
# define tb_int_to_fixed6(x) (tb_fixed6_t)((x) << 6)
# define tb_fixed6_to_int(x) (tb_int_t)((x) >> 6)
# define tb_long_to_fixed6(x) (tb_fixed6_t)((x) << 6)
# define tb_fixed6_to_long(x) (tb_long_t)((x) >> 6)
#endif
#define tb_fixed6_to_fixed16(x) ((x) << 10)
#define tb_fixed16_to_fixed6(x) ((x) >> 10)
// round
#define tb_fixed6_round(x) (((x) + TB_FIXED6_HALF) >> 6)
// ceil
#define tb_fixed6_ceil(x) (((x) + TB_FIXED6_ONE - 1) >> 6)
// floor
#define tb_fixed6_floor(x) ((x) >> 6)
// abs
#define tb_fixed6_abs(x) tb_abs(x)
// avg
#define tb_fixed6_avg(x, y) (((x) + (y)) >> 1)
// nearly equal?
#define tb_fixed6_near_eq(x, y) (tb_fixed6_abs((x) - (y)) <= TB_FIXED6_NEAR0)
// mul
#ifndef tb_fixed6_mul
# define tb_fixed6_mul(x, y) tb_fixed6_mul_inline(x, y)
#endif
// div
#ifndef tb_fixed6_div
# define tb_fixed6_div(x, y) tb_fixed6_div_inline(x, y)
#endif
// imul
#ifndef tb_fixed6_imul
# define tb_fixed6_imul(x, y) tb_fixed16_imul(x, y)
#endif
// idiv
#ifndef tb_fixed6_idiv
# define tb_fixed6_idiv(x, y) tb_fixed16_idiv(x, y)
#endif
// imuldiv
#ifndef tb_fixed6_imuldiv
# define tb_fixed6_imuldiv(x, y, z) tb_fixed16_imuldiv(x, y, z)
#endif
// imulsub
#ifndef tb_fixed6_imulsub
# define tb_fixed6_imulsub(x, y, z) tb_fixed16_imulsub(x, y, z)
#endif
// lsh
#ifndef tb_fixed6_lsh
# define tb_fixed6_lsh(x, y) tb_fixed16_lsh(x, y)
#endif
// rsh
#ifndef tb_fixed6_rsh
# define tb_fixed6_rsh(x, y) tb_fixed16_rsh(x, y)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* inlines
*/
#ifdef __tb_debug__
static __tb_inline__ tb_fixed6_t tb_long_to_fixed6_check(tb_long_t x)
{
// check overflow
tb_assert(x >= (TB_MINS32 >> 10) && x <= (TB_MAXS32 >> 10));
// ok
return (tb_fixed6_t)(x << 6);
}
static __tb_inline__ tb_long_t tb_fixed6_to_int_check(tb_fixed6_t x)
{
// check overflow
tb_assert(x >= TB_FIXED6_MIN && x <= TB_FIXED6_MAX);
// ok
return (tb_fixed6_t)(x >> 6);
}
#endif
static __tb_inline__ tb_fixed6_t tb_fixed6_mul_inline(tb_fixed6_t x, tb_fixed6_t y)
{
// done
tb_hong_t v = (((tb_hong_t)x * y) >> 6);
// check overflow
tb_assert(v == (tb_int32_t)v);
// ok
return (tb_fixed16_t)v;
}
static __tb_inline__ tb_fixed16_t tb_fixed6_div_inline(tb_fixed6_t x, tb_fixed6_t y)
{
// check
tb_assert(y);
// no overflow? compute it fastly
if (x == (tb_int16_t)x) return (x << 16) / y;
// done
return tb_fixed16_div(x, y);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/math/impl/ 0000775 0000000 0000000 00000000000 14671175054 0016150 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/math/impl/fixed16_arm.h 0000664 0000000 0000000 00000003440 14671175054 0020427 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file fixed16_arm.h
*
*/
#ifndef TB_MATH_IMPL_FIXED16_ARM_H
#define TB_MATH_IMPL_FIXED16_ARM_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
#if 0
# define tb_fixed16_mul(x, y) tb_fixed16_mul_asm(x, y)
#endif
#endif /* TB_ASSEMBLER_IS_GAS */
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
#if defined(TB_ASSEMBLER_IS_GAS) && !defined(TB_ARCH_ARM64)
static __tb_inline__ tb_fixed16_t tb_fixed16_mul_asm(tb_fixed16_t x, tb_fixed16_t y)
{
__tb_register__ tb_fixed16_t t;
__tb_asm__ __tb_volatile__
(
"smull %0, %2, %1, %3 \n" // r64 = (l, h) = x * y
"mov %0, %0, lsr #16 \n" // to fixed16: r64 >>= 16
"orr %0, %0, %2, lsl #16 \n" // x = l = (h << (32 - 16)) | (l >> 16);
: "=r"(x), "=&r"(y), "=r"(t)
: "r"(x), "1"(y)
);
return x;
}
#endif
#endif
tbox-1.7.6/src/tbox/math/impl/fixed30_arm.h 0000664 0000000 0000000 00000003404 14671175054 0020423 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file fixed30_arm.h
*
*/
#ifndef TB_MATH_IMPL_FIXED30_ARM_H
#define TB_MATH_IMPL_FIXED30_ARM_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
#if 0
# define tb_fixed30_mul(x, y) tb_fixed30_mul_asm(x, y)
#endif
#endif /* TB_ASSEMBLER_IS_GAS */
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
#if defined(TB_ASSEMBLER_IS_GAS)
static __tb_inline__ tb_fixed30_t tb_fixed30_mul_asm(tb_fixed30_t x, tb_fixed30_t y)
{
__tb_register__ tb_fixed30_t t;
__tb_asm__ __tb_volatile__
(
"smull %0, %2, %1, %3 \n" // r64 = (l, h) = x * y
"mov %0, %0, lsr #30 \n" // to fixed30: r64 >>= 30
"orr %0, %0, %2, lsl #2 \n" // x = l = (h << (32 - 30)) | (l >> 30);
: "=r"(x), "=&r"(y), "=r"(t)
: "r"(x), "1"(y)
);
return x;
}
#endif
#endif
tbox-1.7.6/src/tbox/math/impl/impl.h 0000664 0000000 0000000 00000001560 14671175054 0017264 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file impl.h
*
*/
#ifndef TB_MATH_IMPL_H
#define TB_MATH_IMPL_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#endif
tbox-1.7.6/src/tbox/math/impl/math.c 0000664 0000000 0000000 00000003655 14671175054 0017256 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file math.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "math.h"
#include "../math.h"
#include "../../libc/libc.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
#ifndef TB_CONFIG_MICRO_ENABLE
static tb_long_t tb_math_printf_format_fixed(tb_cpointer_t object, tb_char_t* cstr, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(cstr && maxn, -1);
// the fixed
tb_fixed_t fixed = (tb_fixed_t)tb_p2s32(object);
// format
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
tb_long_t size = tb_snprintf(cstr, maxn - 1, "%f", tb_fixed_to_float(fixed));
if (size >= 0) cstr[size] = '\0';
#else
tb_long_t size = tb_snprintf(cstr, maxn - 1, "%ld", tb_fixed_to_long(fixed));
if (size >= 0) cstr[size] = '\0';
#endif
// ok?
return size;
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_math_init_env()
{
#ifndef TB_CONFIG_MICRO_ENABLE
// register printf("%{fixed}", fixed);
tb_printf_object_register("fixed", tb_math_printf_format_fixed);
#endif
// ok
return tb_true;
}
tb_void_t tb_math_exit_env()
{
}
tbox-1.7.6/src/tbox/math/impl/math.h 0000664 0000000 0000000 00000002641 14671175054 0017255 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file math.h
*
*/
#ifndef TB_MATH_IMPL_MATH_H
#define TB_MATH_IMPL_MATH_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* init math environment
*
* @return tb_true or tb_false
*/
tb_bool_t tb_math_init_env(tb_noarg_t);
// exit math environment
tb_void_t tb_math_exit_env(tb_noarg_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/math/impl/prefix.h 0000664 0000000 0000000 00000001605 14671175054 0017620 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_MATH_IMPL_PREFIX_H
#define TB_MATH_IMPL_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/math/int32.c 0000664 0000000 0000000 00000005623 14671175054 0016320 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file int32.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "int32.h"
#include "../utils/utils.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_int32_t tb_int32_div(tb_int32_t x, tb_int32_t y, tb_int_t nbits)
{
tb_assert(y);
tb_check_return_val(x, 0);
// get sign
tb_int32_t s = tb_int32_get_sign(x ^ y);
x = tb_abs(x);
y = tb_abs(y);
tb_int_t xbits = (tb_int_t)tb_bits_cl0_u32_be(x) - 1;
tb_int_t ybits = (tb_int_t)tb_bits_cl0_u32_be(y) - 1;
tb_int_t bits = nbits - xbits + ybits;
// underflow?
if (bits < 0) return 0;
// overflow?
if (bits > 31) return tb_int32_set_sign(TB_MAXS32, s);
x <<= xbits;
y <<= ybits;
// do the first one
tb_int32_t r = 0;
if ((x -= y) >= 0) r = 1;
else x += y;
// now fall into our switch statement if there are more bits to compute
if (bits > 0)
{
// make room for the rest of the answer bits
r <<= bits;
switch (bits)
{
#define TB_INT32_DIV_CASE(n) \
case n: \
if ((x = (x << 1) - y) >= 0) \
r |= 1 << (n - 1); else x += y
TB_INT32_DIV_CASE(31); TB_INT32_DIV_CASE(30); TB_INT32_DIV_CASE(29);
TB_INT32_DIV_CASE(28); TB_INT32_DIV_CASE(27); TB_INT32_DIV_CASE(26);
TB_INT32_DIV_CASE(25); TB_INT32_DIV_CASE(24); TB_INT32_DIV_CASE(23);
TB_INT32_DIV_CASE(22); TB_INT32_DIV_CASE(21); TB_INT32_DIV_CASE(20);
TB_INT32_DIV_CASE(19); TB_INT32_DIV_CASE(18); TB_INT32_DIV_CASE(17);
TB_INT32_DIV_CASE(16); TB_INT32_DIV_CASE(15); TB_INT32_DIV_CASE(14);
TB_INT32_DIV_CASE(13); TB_INT32_DIV_CASE(12); TB_INT32_DIV_CASE(11);
TB_INT32_DIV_CASE(10); TB_INT32_DIV_CASE( 9); TB_INT32_DIV_CASE( 8);
TB_INT32_DIV_CASE( 7); TB_INT32_DIV_CASE( 6); TB_INT32_DIV_CASE( 5);
TB_INT32_DIV_CASE( 4); TB_INT32_DIV_CASE( 3); TB_INT32_DIV_CASE( 2);
// we merge these last two together, makes gcc make better arm
default:
TB_INT32_DIV_CASE(1);
}
}
if (r < 0) r = TB_MAXS32;
return tb_int32_set_sign(r, s);
}
tbox-1.7.6/src/tbox/math/int32.h 0000664 0000000 0000000 00000004526 14671175054 0016326 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file int32.h
* @ingroup math
*
*/
#ifndef TB_MATH_INT32_H
#define TB_MATH_INT32_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// sign
#define tb_int32_get_sign(x) tb_int32_get_sign_inline(x)
#define tb_int32_set_sign(x, s) tb_int32_set_sign_inline(x, s)
// bool: is true?
#define tb_int32_nz(x) tb_int32_nz_inline(x)
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
// div
tb_int32_t tb_int32_div(tb_int32_t x, tb_int32_t y, tb_int_t nbits);
/* //////////////////////////////////////////////////////////////////////////////////////
* inline
*/
// return -1 if x < 0, else return 0
static __tb_inline__ tb_int32_t tb_int32_get_sign_inline(tb_int32_t x)
{
tb_int32_t s = ((tb_int32_t)(x) >> 31);
tb_assert((x < 0 && s == -1) || (x >= 0 && !s));
return s;
}
// if s == -1, return -x, else s must be 0, and return x.
static __tb_inline__ tb_int32_t tb_int32_set_sign_inline(tb_int32_t x, tb_int32_t s)
{
tb_assert(s == 0 || s == -1);
return (x ^ s) - s;
}
// non zero, return 1 if x != 0, else return 0
static __tb_inline__ tb_long_t tb_int32_nz_inline(tb_uint32_t x)
{
//return (x? 1 : 0);
return ((x | (0 - x)) >> 31);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/math/math.h 0000664 0000000 0000000 00000001773 14671175054 0016321 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file math.h
* @defgroup math
*
*/
#ifndef TB_MATH_H
#define TB_MATH_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "int32.h"
#include "fixed6.h"
#include "fixed16.h"
#include "fixed30.h"
#include "fixed.h"
#include "random/random.h"
#endif
tbox-1.7.6/src/tbox/math/prefix.h 0000664 0000000 0000000 00000001573 14671175054 0016663 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_MATH_PREFIX_H
#define TB_MATH_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/math/random/ 0000775 0000000 0000000 00000000000 14671175054 0016467 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/math/random/linear.c 0000664 0000000 0000000 00000003516 14671175054 0020112 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file linear.c
* @ingroup math
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "random_linear"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "linear.h"
#include "../../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
// the value
static tb_size_t g_value = 2166136261ul;
// the lock
static tb_spinlock_t g_lock = TB_SPINLOCK_INIT;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_void_t tb_random_linear_seed(tb_size_t seed)
{
// enter
tb_spinlock_enter(&g_lock);
// update value
g_value = seed;
// leave
tb_spinlock_leave(&g_lock);
}
tb_long_t tb_random_linear_value()
{
// enter
tb_spinlock_enter(&g_lock);
// generate the next value
g_value = (g_value * 10807 + 1) & 0xffffffff;
// leave
tb_spinlock_leave(&g_lock);
// ok
return (tb_long_t)g_value;
}
tbox-1.7.6/src/tbox/math/random/linear.h 0000664 0000000 0000000 00000003025 14671175054 0020112 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file linear.h
* @ingroup math
*
*/
#ifndef TB_MATH_RANDOM_LINEAR_H
#define TB_MATH_RANDOM_LINEAR_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! set the linear random seed
*
* @param seed the random seed
*/
tb_void_t tb_random_linear_seed(tb_size_t seed);
/*! generate the linear random value
*
* @return the random value
*/
tb_long_t tb_random_linear_value(tb_noarg_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/math/random/prefix.h 0000664 0000000 0000000 00000001611 14671175054 0020134 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_MATH_RANDOM_PREFIX_H
#define TB_MATH_RANDOM_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/math/random/random.c 0000664 0000000 0000000 00000006540 14671175054 0020120 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file random.c
* @ingroup math
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "random.h"
#include "../../libc/libc.h"
#include "../../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the initial seed
#define TB_RANDOM_SEED_INIT (2166136261ul)
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_LIBC_HAVE_RANDOM) && defined(TB_CONFIG_LIBC_HAVE_SRANDOM)
# include "../../platform/libc/random.c"
#elif defined(TB_CONFIG_OS_WINDOWS) && !defined(TB_COMPILER_IS_MINGW)
# include "../../platform/windows/random.c"
#else
tb_void_t tb_random_seed(tb_size_t seed)
{
tb_random_linear_seed(seed);
}
tb_long_t tb_random_value()
{
return tb_random_linear_value();
}
#endif
tb_void_t tb_random_reset(tb_bool_t pseudo)
{
// init seed
tb_size_t seed = TB_RANDOM_SEED_INIT;
if (!pseudo)
{
// init read
tb_size_t read = 0;
#ifndef TB_CONFIG_OS_WINDOWS
// attempt to read seed from /dev/urandom
tb_file_ref_t file = tb_file_init("/dev/urandom", TB_FILE_MODE_RO);
if (file)
{
// read seed
tb_byte_t* data = (tb_byte_t*)&seed;
while (read < sizeof(tb_size_t))
{
// read it
tb_long_t real = tb_file_read(file, data + read, sizeof(tb_size_t) - read);
tb_assert_and_check_break(real > 0);
// update size
read += real;
}
// exit file
tb_file_exit(file);
}
#endif
// init seed using clock if read failed?
if (read != sizeof(tb_size_t))
{
// get clock
tb_uint64_t clock = (tb_uint64_t)tb_uclock();
// init seed using clock
seed = (tb_size_t)((clock >> 32) ^ clock);
// xor the stack address
seed ^= (tb_size_t)tb_p2u32(&seed);
}
}
// reset seed
tb_random_seed(seed);
}
tb_long_t tb_random_range(tb_long_t begin, tb_long_t end)
{
// check
tb_assert_and_check_return_val(begin < end, begin);
// make range
return (begin + (tb_long_t)((tb_size_t)tb_random_value() % (end - begin)));
}
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
tb_float_t tb_random_rangef(tb_float_t begin, tb_float_t end)
{
// check
tb_assert_and_check_return_val(begin < end, begin);
// the factor
tb_double_t factor = (tb_double_t)tb_random_range(0, TB_MAXS32) / (tb_double_t)TB_MAXS32;
// the value
return (tb_float_t)((end - begin) * factor);
}
#endif
tbox-1.7.6/src/tbox/math/random/random.h 0000664 0000000 0000000 00000004313 14671175054 0020121 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file random.h
*
*/
#ifndef TB_MATH_RANDOM_H
#define TB_MATH_RANDOM_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "linear.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! set the random seed
*
* @param seed the random seed
*/
tb_void_t tb_random_seed(tb_size_t seed);
/*! reset value using the initial seed
*
* @param pseudo reset to the pseudo random?
*/
tb_void_t tb_random_reset(tb_bool_t pseudo);
/*! generate the random value
*
* it will generate a pseudo-random sequence if the seed is not modified manually.
*
* @return the random value
*/
tb_long_t tb_random_value(tb_noarg_t);
/*! generate the random with range: [begin, end)
*
* @param begin the begin value
* @param end the end value
*
* @return the random value
*/
tb_long_t tb_random_range(tb_long_t begin, tb_long_t end);
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
/*! generate the float random with range: [begin, end)
*
* @param begin the begin value
* @param end the end value
*
* @return the random value
*/
tb_float_t tb_random_rangef(tb_float_t begin, tb_float_t end);
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/memory/ 0000775 0000000 0000000 00000000000 14671175054 0015566 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/memory/allocator.c 0000664 0000000 0000000 00000036264 14671175054 0017725 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file allocator.c
* @ingroup memory
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "allocator"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "allocator.h"
#include "impl/impl.h"
#include "../libc/libc.h"
#include "../utils/utils.h"
#include "../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
// the allocator
__tb_extern_c__ tb_allocator_ref_t g_allocator = tb_null;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_allocator_ref_t tb_allocator()
{
return g_allocator;
}
tb_size_t tb_allocator_type(tb_allocator_ref_t allocator)
{
// check
tb_assert_and_check_return_val(allocator, TB_ALLOCATOR_TYPE_DEFAULT);
// get it
return (tb_size_t)allocator->type;
}
tb_pointer_t tb_allocator_malloc_(tb_allocator_ref_t allocator, tb_size_t size __tb_debug_decl__)
{
// check
tb_assert_and_check_return_val(allocator, tb_null);
// enter
tb_bool_t lockit = !(allocator->flag & TB_ALLOCATOR_FLAG_NOLOCK);
if (lockit) tb_spinlock_enter(&allocator->lock);
// malloc it
tb_pointer_t data = tb_null;
if (allocator->malloc) data = allocator->malloc(allocator, size __tb_debug_args__);
else if (allocator->large_malloc) data = allocator->large_malloc(allocator, size, tb_null __tb_debug_args__);
// trace
tb_trace_d("malloc(%lu): %p at %s(): %d, %s", size, data __tb_debug_args__);
// check
tb_assertf(data, "malloc(%lu) failed!", size);
tb_assertf(!(((tb_size_t)data) & (TB_POOL_DATA_ALIGN - 1)), "malloc(%lu): unaligned data: %p", size, data);
// leave
if (lockit) tb_spinlock_leave(&allocator->lock);
// ok?
return data;
}
tb_pointer_t tb_allocator_malloc0_(tb_allocator_ref_t allocator, tb_size_t size __tb_debug_decl__)
{
// check
tb_assert_and_check_return_val(allocator, tb_null);
// malloc it
tb_pointer_t data = tb_allocator_malloc_(allocator, size __tb_debug_args__);
// clear it
if (data) tb_memset_(data, 0, size);
// ok?
return data;
}
tb_pointer_t tb_allocator_nalloc_(tb_allocator_ref_t allocator, tb_size_t item, tb_size_t size __tb_debug_decl__)
{
// check
tb_assert_and_check_return_val(allocator, tb_null);
// nalloc it
return tb_allocator_malloc_(allocator, item * size __tb_debug_args__);
}
tb_pointer_t tb_allocator_nalloc0_(tb_allocator_ref_t allocator, tb_size_t item, tb_size_t size __tb_debug_decl__)
{
// check
tb_assert_and_check_return_val(allocator, tb_null);
// nalloc0 it
tb_pointer_t data = tb_allocator_malloc_(allocator, item * size __tb_debug_args__);
// clear it
if (data) tb_memset_(data, 0, item * size);
// ok?
return data;
}
tb_pointer_t tb_allocator_ralloc_(tb_allocator_ref_t allocator, tb_pointer_t data, tb_size_t size __tb_debug_decl__)
{
// check
tb_assert_and_check_return_val(allocator, tb_null);
// enter
tb_bool_t lockit = !(allocator->flag & TB_ALLOCATOR_FLAG_NOLOCK);
if (lockit) tb_spinlock_enter(&allocator->lock);
// ralloc it
tb_pointer_t data_new = tb_null;
if (allocator->ralloc) data_new = allocator->ralloc(allocator, data, size __tb_debug_args__);
else if (allocator->large_ralloc) data_new = allocator->large_ralloc(allocator, data, size, tb_null __tb_debug_args__);
// trace
tb_trace_d("ralloc(%p, %lu): %p at %s(): %d, %s", data, size, data_new __tb_debug_args__);
// failed? dump it
#ifdef __tb_debug__
if (!data_new)
{
// trace
tb_trace_e("ralloc(%p, %lu) failed! at %s(): %lu, %s", data, size, func_, line_, file_);
// dump data
tb_pool_data_dump((tb_byte_t const*)data, tb_true, "[large_allocator]: [error]: ");
// abort
tb_abort();
}
#endif
// check
tb_assertf(!(((tb_size_t)data_new) & (TB_POOL_DATA_ALIGN - 1)), "ralloc(%lu): unaligned data: %p", size, data);
// leave
if (lockit) tb_spinlock_leave(&allocator->lock);
// ok?
return data_new;
}
tb_bool_t tb_allocator_free_(tb_allocator_ref_t allocator, tb_pointer_t data __tb_debug_decl__)
{
// check
tb_assert_and_check_return_val(allocator, tb_false);
// enter
tb_bool_t lockit = !(allocator->flag & TB_ALLOCATOR_FLAG_NOLOCK);
if (lockit) tb_spinlock_enter(&allocator->lock);
// trace
tb_trace_d("free(%p): at %s(): %d, %s", data __tb_debug_args__);
// free it
tb_bool_t ok = tb_false;
if (allocator->free) ok = allocator->free(allocator, data __tb_debug_args__);
else if (allocator->large_free) ok = allocator->large_free(allocator, data __tb_debug_args__);
// failed? dump it
#ifdef __tb_debug__
if (!ok)
{
// trace
tb_trace_e("free(%p) failed! at %s(): %lu, %s", data, func_, line_, file_);
// dump data
tb_pool_data_dump((tb_byte_t const*)data, tb_true, "[large_allocator]: [error]: ");
// abort
tb_abort();
}
#endif
// leave
if (lockit) tb_spinlock_leave(&allocator->lock);
// ok?
return ok;
}
tb_pointer_t tb_allocator_large_malloc_(tb_allocator_ref_t allocator, tb_size_t size, tb_size_t* real __tb_debug_decl__)
{
// check
tb_assert_and_check_return_val(allocator, tb_null);
// enter
tb_bool_t lockit = !(allocator->flag & TB_ALLOCATOR_FLAG_NOLOCK);
if (lockit) tb_spinlock_enter(&allocator->lock);
// malloc it
tb_pointer_t data = tb_null;
if (allocator->large_malloc) data = allocator->large_malloc(allocator, size, real __tb_debug_args__);
else if (allocator->malloc)
{
// malloc it
if (real) *real = size;
data = allocator->malloc(allocator, size __tb_debug_args__);
}
// trace
tb_trace_d("large_malloc(%lu): %p at %s(): %d, %s", size, data __tb_debug_args__);
// check
tb_assertf(data, "malloc(%lu) failed!", size);
tb_assertf(!(((tb_size_t)data) & (TB_POOL_DATA_ALIGN - 1)), "malloc(%lu): unaligned data: %p", size, data);
tb_assert(!real || *real >= size);
// leave
if (lockit) tb_spinlock_leave(&allocator->lock);
// ok?
return data;
}
tb_pointer_t tb_allocator_large_malloc0_(tb_allocator_ref_t allocator, tb_size_t size, tb_size_t* real __tb_debug_decl__)
{
// check
tb_assert_and_check_return_val(allocator, tb_null);
// malloc it
tb_pointer_t data = tb_allocator_large_malloc_(allocator, size, real __tb_debug_args__);
// clear it
if (data) tb_memset_(data, 0, real? *real : size);
// ok
return data;
}
tb_pointer_t tb_allocator_large_nalloc_(tb_allocator_ref_t allocator, tb_size_t item, tb_size_t size, tb_size_t* real __tb_debug_decl__)
{
// check
tb_assert_and_check_return_val(allocator, tb_null);
// malloc it
return tb_allocator_large_malloc_(allocator, item * size, real __tb_debug_args__);
}
tb_pointer_t tb_allocator_large_nalloc0_(tb_allocator_ref_t allocator, tb_size_t item, tb_size_t size, tb_size_t* real __tb_debug_decl__)
{
// check
tb_assert_and_check_return_val(allocator, tb_null);
// malloc it
tb_pointer_t data = tb_allocator_large_malloc_(allocator, item * size, real __tb_debug_args__);
// clear it
if (data) tb_memset_(data, 0, real? *real : (item * size));
// ok
return data;
}
tb_pointer_t tb_allocator_large_ralloc_(tb_allocator_ref_t allocator, tb_pointer_t data, tb_size_t size, tb_size_t* real __tb_debug_decl__)
{
// check
tb_assert_and_check_return_val(allocator, tb_null);
// enter
tb_bool_t lockit = !(allocator->flag & TB_ALLOCATOR_FLAG_NOLOCK);
if (lockit) tb_spinlock_enter(&allocator->lock);
// ralloc it
tb_pointer_t data_new = tb_null;
if (allocator->large_ralloc) data_new = allocator->large_ralloc(allocator, data, size, real __tb_debug_args__);
else if (allocator->ralloc)
{
// ralloc it
if (real) *real = size;
data_new = allocator->ralloc(allocator, data, size __tb_debug_args__);
}
// trace
tb_trace_d("large_ralloc(%p, %lu): %p at %s(): %d, %s", data, size, data_new __tb_debug_args__);
// failed? dump it
#ifdef __tb_debug__
if (!data_new)
{
// trace
tb_trace_e("ralloc(%p, %lu) failed! at %s(): %lu, %s", data, size, func_, line_, file_);
// dump data
tb_pool_data_dump((tb_byte_t const*)data, tb_true, "[large_allocator]: [error]: ");
// abort
tb_abort();
}
#endif
// check
tb_assert(!real || *real >= size);
tb_assertf(!(((tb_size_t)data_new) & (TB_POOL_DATA_ALIGN - 1)), "ralloc(%lu): unaligned data: %p", size, data);
// leave
if (lockit) tb_spinlock_leave(&allocator->lock);
// ok?
return data_new;
}
tb_bool_t tb_allocator_large_free_(tb_allocator_ref_t allocator, tb_pointer_t data __tb_debug_decl__)
{
// check
tb_assert_and_check_return_val(allocator, tb_false);
// enter
tb_bool_t lockit = !(allocator->flag & TB_ALLOCATOR_FLAG_NOLOCK);
if (lockit) tb_spinlock_enter(&allocator->lock);
// trace
tb_trace_d("large_free(%p): at %s(): %d, %s", data __tb_debug_args__);
// free it
tb_bool_t ok = tb_false;
if (allocator->large_free) ok = allocator->large_free(allocator, data __tb_debug_args__);
else if (allocator->free) ok = allocator->free(allocator, data __tb_debug_args__);
// failed? dump it
#ifdef __tb_debug__
if (!ok)
{
// trace
tb_trace_e("free(%p) failed! at %s(): %lu, %s", data, func_, line_, file_);
// dump data
tb_pool_data_dump((tb_byte_t const*)data, tb_true, "[large_allocator]: [error]: ");
// abort
tb_abort();
}
#endif
// leave
if (lockit) tb_spinlock_leave(&allocator->lock);
// ok?
return ok;
}
tb_pointer_t tb_allocator_align_malloc_(tb_allocator_ref_t allocator, tb_size_t size, tb_size_t align __tb_debug_decl__)
{
// check
tb_assertf(!(align & 3), "invalid alignment size: %lu", align);
tb_check_return_val(!(align & 3), tb_null);
// malloc it
tb_byte_t* data = (tb_byte_t*)tb_allocator_malloc_(allocator, size + align __tb_debug_args__);
tb_check_return_val(data, tb_null);
// the different bytes
tb_byte_t diff = (tb_byte_t)((~(tb_long_t)data) & (align - 1)) + 1;
// adjust the address
data += diff;
// check
tb_assert(!((tb_size_t)data & (align - 1)));
// save the different bytes
data[-1] = diff;
// ok?
return (tb_pointer_t)data;
}
tb_pointer_t tb_allocator_align_malloc0_(tb_allocator_ref_t allocator, tb_size_t size, tb_size_t align __tb_debug_decl__)
{
// malloc it
tb_pointer_t data = tb_allocator_align_malloc_(allocator, size, align __tb_debug_args__);
tb_assert_and_check_return_val(data, tb_null);
// clear it
tb_memset(data, 0, size);
// ok
return data;
}
tb_pointer_t tb_allocator_align_nalloc_(tb_allocator_ref_t allocator, tb_size_t item, tb_size_t size, tb_size_t align __tb_debug_decl__)
{
return tb_allocator_align_malloc_(allocator, item * size, align __tb_debug_args__);
}
tb_pointer_t tb_allocator_align_nalloc0_(tb_allocator_ref_t allocator, tb_size_t item, tb_size_t size, tb_size_t align __tb_debug_decl__)
{
// nalloc it
tb_pointer_t data = tb_allocator_align_nalloc_(allocator, item, size, align __tb_debug_args__);
tb_assert_and_check_return_val(data, tb_null);
// clear it
tb_memset(data, 0, item * size);
// ok
return data;
}
tb_pointer_t tb_allocator_align_ralloc_(tb_allocator_ref_t allocator, tb_pointer_t data, tb_size_t size, tb_size_t align __tb_debug_decl__)
{
// check align
tb_assertf(!(align & 3), "invalid alignment size: %lu", align);
tb_check_return_val(!(align & 3), tb_null);
// ralloc?
tb_byte_t diff = 0;
if (data)
{
// check address
tb_assertf(!((tb_size_t)data & (align - 1)), "invalid address %p", data);
tb_check_return_val(!((tb_size_t)data & (align - 1)), tb_null);
// the different bytes
diff = ((tb_byte_t*)data)[-1];
// adjust the address
data = (tb_byte_t*)data - diff;
// ralloc it
data = tb_allocator_ralloc_(allocator, data, size + align __tb_debug_args__);
tb_check_return_val(data, tb_null);
}
// no data?
else
{
// malloc it directly
data = tb_allocator_malloc_(allocator, size + align __tb_debug_args__);
tb_check_return_val(data, tb_null);
}
// the different bytes
diff = (tb_byte_t)((~(tb_long_t)data) & (align - 1)) + 1;
// adjust the address
data = (tb_byte_t*)data + diff;
// check
tb_assert(!((tb_size_t)data & (align - 1)));
// save the different bytes
((tb_byte_t*)data)[-1] = diff;
// ok?
return data;
}
tb_bool_t tb_allocator_align_free_(tb_allocator_ref_t allocator, tb_pointer_t data __tb_debug_decl__)
{
// check
tb_assert_and_check_return_val(data, tb_false);
tb_assert(!((tb_size_t)data & 3));
// the different bytes
tb_byte_t diff = ((tb_byte_t*)data)[-1];
// adjust the address
data = (tb_byte_t*)data - diff;
// free it
return tb_allocator_free_(allocator, data __tb_debug_args__);
}
tb_void_t tb_allocator_clear(tb_allocator_ref_t allocator)
{
// check
tb_assert_and_check_return(allocator);
// enter
tb_bool_t lockit = !(allocator->flag & TB_ALLOCATOR_FLAG_NOLOCK);
if (lockit) tb_spinlock_enter(&allocator->lock);
// clear it
if (allocator->clear) allocator->clear(allocator);
// leave
if (lockit) tb_spinlock_leave(&allocator->lock);
}
tb_void_t tb_allocator_exit(tb_allocator_ref_t allocator)
{
// check
tb_assert_and_check_return(allocator);
// clear it first
tb_allocator_clear(allocator);
// exit it
if (allocator->exit) allocator->exit(allocator);
}
#ifdef __tb_debug__
tb_void_t tb_allocator_dump(tb_allocator_ref_t allocator)
{
// check
tb_assert_and_check_return(allocator);
// enter
tb_bool_t lockit = !(allocator->flag & TB_ALLOCATOR_FLAG_NOLOCK);
if (lockit) tb_spinlock_enter(&allocator->lock);
// dump it
if (allocator->dump) allocator->dump(allocator);
// leave
if (lockit) tb_spinlock_leave(&allocator->lock);
}
tb_bool_t tb_allocator_have(tb_allocator_ref_t allocator, tb_cpointer_t data)
{
// check
tb_assert_and_check_return_val(allocator, tb_false);
/* have it?
*
* @note cannot use locker and ensure thread safe
*/
return allocator->have? allocator->have(allocator, data) : tb_false;
}
#endif
tbox-1.7.6/src/tbox/memory/allocator.h 0000664 0000000 0000000 00000035036 14671175054 0017726 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file allocator.h
* @ingroup memory
*
*/
#ifndef TB_MEMORY_ALLOCATOR_H
#define TB_MEMORY_ALLOCATOR_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define tb_allocator_malloc(allocator, size) tb_allocator_malloc_(allocator, size __tb_debug_vals__)
#define tb_allocator_malloc0(allocator, size) tb_allocator_malloc0_(allocator, size __tb_debug_vals__)
#define tb_allocator_nalloc(allocator, item, size) tb_allocator_nalloc_(allocator, item, size __tb_debug_vals__)
#define tb_allocator_nalloc0(allocator, item, size) tb_allocator_nalloc0_(allocator, item, size __tb_debug_vals__)
#define tb_allocator_ralloc(allocator, data, size) tb_allocator_ralloc_(allocator, (tb_pointer_t)(data), size __tb_debug_vals__)
#define tb_allocator_free(allocator, data) tb_allocator_free_(allocator, (tb_pointer_t)(data) __tb_debug_vals__)
#define tb_allocator_large_malloc(allocator, size, real) tb_allocator_large_malloc_(allocator, size, real __tb_debug_vals__)
#define tb_allocator_large_malloc0(allocator, size, real) tb_allocator_large_malloc0_(allocator, size, real __tb_debug_vals__)
#define tb_allocator_large_nalloc(allocator, item, size, real) tb_allocator_large_nalloc_(allocator, item, size, real __tb_debug_vals__)
#define tb_allocator_large_nalloc0(allocator, item, size, real) tb_allocator_large_nalloc0_(allocator, item, size, real __tb_debug_vals__)
#define tb_allocator_large_ralloc(allocator, data, size, real) tb_allocator_large_ralloc_(allocator, (tb_pointer_t)(data), size, real __tb_debug_vals__)
#define tb_allocator_large_free(allocator, data) tb_allocator_large_free_(allocator, (tb_pointer_t)(data) __tb_debug_vals__)
#define tb_allocator_align_malloc(allocator, size, align) tb_allocator_align_malloc_(allocator, size, align __tb_debug_vals__)
#define tb_allocator_align_malloc0(allocator, size, align) tb_allocator_align_malloc0_(allocator, size, align __tb_debug_vals__)
#define tb_allocator_align_nalloc(allocator, item, size, align) tb_allocator_align_nalloc_(allocator, item, size, align __tb_debug_vals__)
#define tb_allocator_align_nalloc0(allocator, item, size, align) tb_allocator_align_nalloc0_(allocator, item, size, align __tb_debug_vals__)
#define tb_allocator_align_ralloc(allocator, data, size, align) tb_allocator_align_ralloc_(allocator, (tb_pointer_t)(data), size, align __tb_debug_vals__)
#define tb_allocator_align_free(allocator, data) tb_allocator_align_free_(allocator, (tb_pointer_t)(data) __tb_debug_vals__)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the allocator type enum
typedef enum __tb_allocator_type_e
{
TB_ALLOCATOR_TYPE_NONE = 0
, TB_ALLOCATOR_TYPE_DEFAULT = 1
, TB_ALLOCATOR_TYPE_NATIVE = 2
, TB_ALLOCATOR_TYPE_VIRTUAL = 3
, TB_ALLOCATOR_TYPE_STATIC = 4
, TB_ALLOCATOR_TYPE_LARGE = 5
, TB_ALLOCATOR_TYPE_SMALL = 6
}tb_allocator_type_e;
/// the allocator flag enum
typedef enum __tb_allocator_flag_e
{
TB_ALLOCATOR_FLAG_NONE = 0
, TB_ALLOCATOR_FLAG_NOLOCK = 1
}tb_allocator_flag_e;
/// the allocator type
typedef struct __tb_allocator_t
{
/// the type
tb_uint32_t type : 16;
/// the flag
tb_uint32_t flag : 16;
/// the lock
tb_spinlock_t lock;
/*! malloc data
*
* @param allocator the allocator
* @param size the size
*
* @return the data address
*/
tb_pointer_t (*malloc)(struct __tb_allocator_t* allocator, tb_size_t size __tb_debug_decl__);
/*! realloc data
*
* @param allocator the allocator
* @param data the data address
* @param size the data size
*
* @return the new data address
*/
tb_pointer_t (*ralloc)(struct __tb_allocator_t* allocator, tb_pointer_t data, tb_size_t size __tb_debug_decl__);
/*! free data
*
* @param allocator the allocator
* @param data the data address
*
* @return tb_true or tb_false
*/
tb_bool_t (*free)(struct __tb_allocator_t* allocator, tb_pointer_t data __tb_debug_decl__);
/*! malloc large data
*
* @param allocator the allocator
* @param size the size
* @param real the real allocated size >= size, optional
*
* @return the data address
*/
tb_pointer_t (*large_malloc)(struct __tb_allocator_t* allocator, tb_size_t size, tb_size_t* real __tb_debug_decl__);
/*! realloc large data
*
* @param allocator the allocator
* @param data the data address
* @param size the data size
* @param real the real allocated size >= size, optional
*
* @return the new data address
*/
tb_pointer_t (*large_ralloc)(struct __tb_allocator_t* allocator, tb_pointer_t data, tb_size_t size, tb_size_t* real __tb_debug_decl__);
/*! free large data
*
* @param allocator the allocator
* @param data the data address
*
* @return tb_true or tb_false
*/
tb_bool_t (*large_free)(struct __tb_allocator_t* allocator, tb_pointer_t data __tb_debug_decl__);
/*! clear allocator
*
* @param allocator the allocator
*/
tb_void_t (*clear)(struct __tb_allocator_t* allocator);
/*! exit allocator
*
* @param allocator the allocator
*/
tb_void_t (*exit)(struct __tb_allocator_t* allocator);
#ifdef __tb_debug__
/*! dump allocator
*
* @param allocator the allocator
*/
tb_void_t (*dump)(struct __tb_allocator_t* allocator);
/*! have this given data addess?
*
* @param allocator the allocator
* @param data the data address
*
* @return tb_true or tb_false
*/
tb_bool_t (*have)(struct __tb_allocator_t* allocator, tb_cpointer_t data);
#endif
}tb_allocator_t, *tb_allocator_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the allocator
*
* @return the allocator
*/
tb_allocator_ref_t tb_allocator(tb_noarg_t);
/*! the native allocator
*
* uses system memory directly
*
* @return the allocator
*/
tb_allocator_ref_t tb_allocator_native(tb_noarg_t);
/*! the allocator type
*
* @param allocator the allocator
*
* @return the allocator type
*/
tb_size_t tb_allocator_type(tb_allocator_ref_t allocator);
/*! malloc data
*
* @param allocator the allocator
* @param size the size
*
* @return the data address
*/
tb_pointer_t tb_allocator_malloc_(tb_allocator_ref_t allocator, tb_size_t size __tb_debug_decl__);
/*! malloc data and fill zero
*
* @param allocator the allocator
* @param size the size
*
* @return the data address
*/
tb_pointer_t tb_allocator_malloc0_(tb_allocator_ref_t allocator, tb_size_t size __tb_debug_decl__);
/*! malloc data with the item count
*
* @param allocator the allocator
* @param item the item count
* @param size the item size
*
* @return the data address
*/
tb_pointer_t tb_allocator_nalloc_(tb_allocator_ref_t allocator, tb_size_t item, tb_size_t size __tb_debug_decl__);
/*! malloc data with the item count and fill zero
*
* @param allocator the allocator
* @param item the item count
* @param size the item size
*
* @return the data address
*/
tb_pointer_t tb_allocator_nalloc0_(tb_allocator_ref_t allocator, tb_size_t item, tb_size_t size __tb_debug_decl__);
/*! realloc data
*
* @param allocator the allocator
* @param data the data address
* @param size the data size
*
* @return the new data address
*/
tb_pointer_t tb_allocator_ralloc_(tb_allocator_ref_t allocator, tb_pointer_t data, tb_size_t size __tb_debug_decl__);
/*! free data
*
* @param allocator the allocator
* @param data the data address
*
* @return tb_true or tb_false
*/
tb_bool_t tb_allocator_free_(tb_allocator_ref_t allocator, tb_pointer_t data __tb_debug_decl__);
/*! malloc large data
*
* @param allocator the allocator
* @param size the size
* @param real the real allocated size >= size, optional
*
* @return the data address
*/
tb_pointer_t tb_allocator_large_malloc_(tb_allocator_ref_t allocator, tb_size_t size, tb_size_t* real __tb_debug_decl__);
/*! malloc large data and fill zero
*
* @param allocator the allocator
* @param size the size
* @param real the real allocated size >= size, optional
*
* @return the data address
*/
tb_pointer_t tb_allocator_large_malloc0_(tb_allocator_ref_t allocator, tb_size_t size, tb_size_t* real __tb_debug_decl__);
/*! malloc large data with the item count
*
* @param allocator the allocator
* @param item the item count
* @param size the item size
* @param real the real allocated size >= item * size, optional
*
* @return the data address
*/
tb_pointer_t tb_allocator_large_nalloc_(tb_allocator_ref_t allocator, tb_size_t item, tb_size_t size, tb_size_t* real __tb_debug_decl__);
/*! malloc large data with the item count and fill zero
*
* @param allocator the allocator
* @param item the item count
* @param size the item size
* @param real the real allocated size >= item * size, optional
*
* @return the data address
*/
tb_pointer_t tb_allocator_large_nalloc0_(tb_allocator_ref_t allocator, tb_size_t item, tb_size_t size, tb_size_t* real __tb_debug_decl__);
/*! realloc large data
*
* @param allocator the allocator
* @param data the data address
* @param size the data size
* @param real the real allocated size >= size, optional
*
* @return the new data address
*/
tb_pointer_t tb_allocator_large_ralloc_(tb_allocator_ref_t allocator, tb_pointer_t data, tb_size_t size, tb_size_t* real __tb_debug_decl__);
/*! free large data
*
* @param allocator the allocator
* @param data the data address
*
* @return tb_true or tb_false
*/
tb_bool_t tb_allocator_large_free_(tb_allocator_ref_t allocator, tb_pointer_t data __tb_debug_decl__);
/*! align malloc data
*
* @param allocator the allocator
* @param size the size
* @param align the alignment bytes
*
* @return the data address
*/
tb_pointer_t tb_allocator_align_malloc_(tb_allocator_ref_t allocator, tb_size_t size, tb_size_t align __tb_debug_decl__);
/*! align malloc data and fill zero
*
* @param allocator the allocator
* @param size the size
* @param align the alignment bytes
*
* @return the data address
*/
tb_pointer_t tb_allocator_align_malloc0_(tb_allocator_ref_t allocator, tb_size_t size, tb_size_t align __tb_debug_decl__);
/*! align malloc data with the item count
*
* @param allocator the allocator
* @param item the item count
* @param size the item size
* @param align the alignment bytes
*
* @return the data address
*/
tb_pointer_t tb_allocator_align_nalloc_(tb_allocator_ref_t allocator, tb_size_t item, tb_size_t size, tb_size_t align __tb_debug_decl__);
/*! align malloc data with the item count and fill zero
*
* @param allocator the allocator
* @param item the item count
* @param size the item size
* @param align the alignment bytes
*
* @return the data address
*/
tb_pointer_t tb_allocator_align_nalloc0_(tb_allocator_ref_t allocator, tb_size_t item, tb_size_t size, tb_size_t align __tb_debug_decl__);
/*! align realloc data
*
* @param allocator the allocator
* @param data the data address
* @param size the data size
*
* @return the new data address
*/
tb_pointer_t tb_allocator_align_ralloc_(tb_allocator_ref_t allocator, tb_pointer_t data, tb_size_t size, tb_size_t align __tb_debug_decl__);
/*! align free data
*
* @param allocator the allocator
* @param data the data address
*
* @return tb_true or tb_false
*/
tb_bool_t tb_allocator_align_free_(tb_allocator_ref_t allocator, tb_pointer_t data __tb_debug_decl__);
/*! clear it
*
* @param allocator the allocator
*/
tb_void_t tb_allocator_clear(tb_allocator_ref_t allocator);
/*! exit it
*
* @param allocator the allocator
*/
tb_void_t tb_allocator_exit(tb_allocator_ref_t allocator);
#ifdef __tb_debug__
/*! dump it
*
* @param allocator the allocator
*/
tb_void_t tb_allocator_dump(tb_allocator_ref_t allocator);
/*! have this given data addess?
*
* @param allocator the allocator
* @param data the data address
*
* @return tb_true or tb_false
*/
tb_bool_t tb_allocator_have(tb_allocator_ref_t allocator, tb_cpointer_t data);
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/memory/buffer.c 0000664 0000000 0000000 00000020515 14671175054 0017206 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file buffer.c
* @ingroup memory
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "memory.h"
#include "../libc/libc.h"
#include "../utils/utils.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the maximum grow size of value buffer
#ifdef __tb_small__
# define TB_BUFFER_GROW_SIZE (64)
#else
# define TB_BUFFER_GROW_SIZE (256)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_buffer_init(tb_buffer_ref_t buffer)
{
// check
tb_assert_and_check_return_val(buffer, tb_false);
// init
buffer->data = buffer->buff;
buffer->size = 0;
buffer->maxn = sizeof(buffer->buff);
// ok
return tb_true;
}
tb_void_t tb_buffer_exit(tb_buffer_ref_t buffer)
{
// check
tb_assert_and_check_return(buffer);
// clear it
tb_buffer_clear(buffer);
// exit data
if (buffer->data && buffer->data != buffer->buff) tb_free(buffer->data);
buffer->data = buffer->buff;
// exit size
buffer->size = 0;
buffer->maxn = sizeof(buffer->buff);
}
tb_byte_t* tb_buffer_data(tb_buffer_ref_t buffer)
{
// check
tb_assert_and_check_return_val(buffer, tb_null);
// the buffer data
return buffer->data;
}
tb_size_t tb_buffer_size(tb_buffer_ref_t buffer)
{
// check
tb_assert_and_check_return_val(buffer, 0);
// the buffer size
return buffer->size;
}
tb_size_t tb_buffer_maxn(tb_buffer_ref_t buffer)
{
// check
tb_assert_and_check_return_val(buffer, 0);
// the buffer maxn
return buffer->maxn;
}
tb_void_t tb_buffer_clear(tb_buffer_ref_t buffer)
{
// check
tb_assert_and_check_return(buffer);
// clear it
buffer->size = 0;
}
tb_byte_t* tb_buffer_resize(tb_buffer_ref_t buffer, tb_size_t size)
{
// check
tb_assert_and_check_return_val(buffer && size, tb_null);
// done
tb_bool_t ok = tb_false;
tb_byte_t* buff_data = buffer->data;
tb_size_t buff_size = buffer->size;
tb_size_t buff_maxn = buffer->maxn;
do
{
// check
tb_assert_and_check_break(buff_data);
// using static buffer?
if (buff_data == buffer->buff)
{
// grow?
if (size > buff_maxn)
{
// grow maxn
buff_maxn = tb_align8(size + TB_BUFFER_GROW_SIZE);
tb_assert_and_check_break(size <= buff_maxn);
// grow data
buff_data = tb_malloc_bytes(buff_maxn);
tb_assert_and_check_break(buff_data);
// copy data
tb_memcpy(buff_data, buffer->buff, buff_size);
}
// update the size
buff_size = size;
}
else
{
// grow?
if (size > buff_maxn)
{
// grow maxn
buff_maxn = tb_align8(size + TB_BUFFER_GROW_SIZE);
tb_assert_and_check_break(size <= buff_maxn);
// grow data
buff_data = (tb_byte_t*)tb_ralloc(buff_data, buff_maxn);
tb_assert_and_check_break(buff_data);
}
#if 0
// decrease to the static buffer
else if (size <= sizeof(buffer->buff))
{
// update the maxn
buff_maxn = sizeof(buffer->buff);
// copy data
tb_memcpy(buffer->buff, buff_data, size);
// free data
tb_free(buff_data);
// using the static buffer
buff_data = buffer->buff;
}
#endif
// update the size
buff_size = size;
}
// update the buffer
buffer->data = buff_data;
buffer->size = buff_size;
buffer->maxn = buff_maxn;
// ok
ok = tb_true;
} while (0);
// trace
tb_assertf(ok, "resize buffer failed: %lu => %lu", buff_size, size);
// ok
return ok? (tb_byte_t*)buffer->data : tb_null;
}
tb_byte_t* tb_buffer_memset(tb_buffer_ref_t buffer, tb_byte_t b)
{
return tb_buffer_memnsetp(buffer, 0, b, tb_buffer_size(buffer));
}
tb_byte_t* tb_buffer_memsetp(tb_buffer_ref_t buffer, tb_size_t p, tb_byte_t b)
{
tb_size_t size = tb_buffer_size(buffer);
tb_assert_and_check_return_val(p < size, tb_null);
return tb_buffer_memnsetp(buffer, p, b, size - p);
}
tb_byte_t* tb_buffer_memnset(tb_buffer_ref_t buffer, tb_byte_t b, tb_size_t n)
{
return tb_buffer_memnsetp(buffer, 0, b, n);
}
tb_byte_t* tb_buffer_memnsetp(tb_buffer_ref_t buffer, tb_size_t p, tb_byte_t b, tb_size_t n)
{
// check
tb_assert_and_check_return_val(buffer, tb_null);
// check
tb_check_return_val(n, tb_buffer_data(buffer));
// resize
tb_byte_t* d = tb_buffer_resize(buffer, p + n);
tb_assert_and_check_return_val(d, tb_null);
// memset
tb_memset(d + p, b, n);
// ok?
return d;
}
tb_byte_t* tb_buffer_memcpy(tb_buffer_ref_t buffer, tb_buffer_ref_t b)
{
return tb_buffer_memncpyp(buffer, 0, tb_buffer_data(b), tb_buffer_size(b));
}
tb_byte_t* tb_buffer_memcpyp(tb_buffer_ref_t buffer, tb_size_t p, tb_buffer_ref_t b)
{
return tb_buffer_memncpyp(buffer, p, tb_buffer_data(b), tb_buffer_size(b));
}
tb_byte_t* tb_buffer_memncpy(tb_buffer_ref_t buffer, tb_byte_t const* b, tb_size_t n)
{
return tb_buffer_memncpyp(buffer, 0, b, n);
}
tb_byte_t* tb_buffer_memncpyp(tb_buffer_ref_t buffer, tb_size_t p, tb_byte_t const* b, tb_size_t n)
{
// check
tb_assert_and_check_return_val(buffer && b, tb_null);
// check
tb_check_return_val(n, tb_buffer_data(buffer));
// resize
tb_byte_t* d = tb_buffer_resize(buffer, p + n);
tb_assert_and_check_return_val(d, tb_null);
// copy it
tb_memcpy(d + p, b, n);
// ok
return d;
}
tb_byte_t* tb_buffer_memmov(tb_buffer_ref_t buffer, tb_size_t b)
{
// check
tb_assert_and_check_return_val(b <= tb_buffer_size(buffer), tb_null);
return tb_buffer_memnmovp(buffer, 0, b, tb_buffer_size(buffer) - b);
}
tb_byte_t* tb_buffer_memmovp(tb_buffer_ref_t buffer, tb_size_t p, tb_size_t b)
{
// check
tb_assert_and_check_return_val(b <= tb_buffer_size(buffer), tb_null);
return tb_buffer_memnmovp(buffer, p, b, tb_buffer_size(buffer) - b);
}
tb_byte_t* tb_buffer_memnmov(tb_buffer_ref_t buffer, tb_size_t b, tb_size_t n)
{
return tb_buffer_memnmovp(buffer, 0, b, n);
}
tb_byte_t* tb_buffer_memnmovp(tb_buffer_ref_t buffer, tb_size_t p, tb_size_t b, tb_size_t n)
{
// check
tb_assert_and_check_return_val(buffer && (b + n) <= tb_buffer_size(buffer), tb_null);
// clear?
if (b == tb_buffer_size(buffer))
{
tb_buffer_clear(buffer);
return tb_buffer_data(buffer);
}
// check
tb_check_return_val(p != b && n, tb_buffer_data(buffer));
// resize
tb_byte_t* d = tb_buffer_resize(buffer, p + n);
tb_assert_and_check_return_val(d, tb_null);
// memmov
tb_memmov(d + p, d + b, n);
return d;
}
tb_byte_t* tb_buffer_memcat(tb_buffer_ref_t buffer, tb_buffer_ref_t b)
{
return tb_buffer_memncat(buffer, tb_buffer_data(b), tb_buffer_size(b));
}
tb_byte_t* tb_buffer_memncat(tb_buffer_ref_t buffer, tb_byte_t const* b, tb_size_t n)
{
// check
tb_assert_and_check_return_val(buffer && b, tb_null);
// check
tb_check_return_val(n, tb_buffer_data(buffer));
// is null?
tb_size_t p = tb_buffer_size(buffer);
if (!p) return tb_buffer_memncpy(buffer, b, n);
// resize
tb_byte_t* d = tb_buffer_resize(buffer, p + n);
tb_assert_and_check_return_val(d, tb_null);
// memcat
tb_memcpy(d + p, b, n);
// ok?
return d;
}
tbox-1.7.6/src/tbox/memory/buffer.h 0000664 0000000 0000000 00000015214 14671175054 0017213 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file buffer.h
* @ingroup memory
*
*/
#ifndef TB_MEMORY_BUFFER_H
#define TB_MEMORY_BUFFER_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the buffer type
typedef struct __tb_buffer_t
{
/// the buffer data
tb_byte_t* data;
/// the buffer size
tb_size_t size;
/// the buffer maxn
tb_size_t maxn;
/// the static buffer
#ifdef __tb_small__
tb_byte_t buff[32];
#else
tb_byte_t buff[64];
#endif
}tb_buffer_t, *tb_buffer_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init the buffer
*
* @param buffer the buffer
*
* @return tb_true or tb_false
*/
tb_bool_t tb_buffer_init(tb_buffer_ref_t buffer);
/*! exit the buffer
*
* @param buffer the buffer
*/
tb_void_t tb_buffer_exit(tb_buffer_ref_t buffer);
/*! the buffer data
*
* @param buffer the buffer
*
* @return the buffer data address
*/
tb_byte_t* tb_buffer_data(tb_buffer_ref_t buffer);
/*! the buffer data size
*
* @param buffer the buffer
*
* @return the buffer data size
*/
tb_size_t tb_buffer_size(tb_buffer_ref_t buffer);
/*! the buffer data maxn
*
* @param buffer the buffer
*
* @return the buffer data maxn
*/
tb_size_t tb_buffer_maxn(tb_buffer_ref_t buffer);
/*! clear the buffer
*
* @param buffer the buffer
*/
tb_void_t tb_buffer_clear(tb_buffer_ref_t buffer);
/*! resize the buffer size
*
* @param buffer the buffer
* @param size the new buffer size
*
* @return the buffer data address
*/
tb_byte_t* tb_buffer_resize(tb_buffer_ref_t buffer, tb_size_t size);
/*! memset: b => 0 ... e
*
* @param buffer the buffer
* @param b the filled byte
*
* @return the buffer data address
*/
tb_byte_t* tb_buffer_memset(tb_buffer_ref_t buffer, tb_byte_t b);
/*! memset: b => p ... e
*
* @param buffer the buffer
* @param p the start position
* @param b the filled byte
*
* @return the buffer data address
*/
tb_byte_t* tb_buffer_memsetp(tb_buffer_ref_t buffer, tb_size_t p, tb_byte_t b);
/*! memset: b => 0 ... n
*
* @param buffer the buffer
* @param b the filled byte
* @param n the filled count
*
* @return the buffer data address
*/
tb_byte_t* tb_buffer_memnset(tb_buffer_ref_t buffer, tb_byte_t b, tb_size_t n);
/*! memset: b => p ... n
*
* @param buffer the buffer
* @param p the start position
* @param b the filled byte
* @param n the filled count
*
* @return the buffer data address
*/
tb_byte_t* tb_buffer_memnsetp(tb_buffer_ref_t buffer, tb_size_t p, tb_byte_t b, tb_size_t n);
/*! memcpy: b => 0 ...
*
* @param buffer the buffer
* @param b the copied buffer
*
* @return the buffer data address
*/
tb_byte_t* tb_buffer_memcpy(tb_buffer_ref_t buffer, tb_buffer_ref_t b);
/*! memcpy: b => p ...
*
* @param buffer the buffer
* @param p the start position
* @param b the copied buffer
*
* @return the buffer data address
*/
tb_byte_t* tb_buffer_memcpyp(tb_buffer_ref_t buffer, tb_size_t p, tb_buffer_ref_t b);
/*! memcpy: b ... n => 0 ...
*
* @param buffer the buffer
* @param b the copied buffer
* @param n the copied count
*
* @return the buffer data address
*/
tb_byte_t* tb_buffer_memncpy(tb_buffer_ref_t buffer, tb_byte_t const* b, tb_size_t n);
/*! memcpy: b ... n => p ...
*
* @param buffer the buffer
* @param p the start position
* @param b the copied buffer
* @param n the copied count
*
* @return the buffer data address
*/
tb_byte_t* tb_buffer_memncpyp(tb_buffer_ref_t buffer, tb_size_t p, tb_byte_t const* b, tb_size_t n);
/*! memmov: b ... e => 0 ...
*
* @param buffer the buffer
* @param b the moved start position
*
* @return the buffer data address
*/
tb_byte_t* tb_buffer_memmov(tb_buffer_ref_t buffer, tb_size_t b);
/*! memmov: b ... e => p ...
*
* @param buffer the buffer
* @param p the moved destination position
* @param b the moved start position
*
* @return the buffer data address
*/
tb_byte_t* tb_buffer_memmovp(tb_buffer_ref_t buffer, tb_size_t p, tb_size_t b);
/*! memmov: b ... n => 0 ...
*
* @param buffer the buffer
* @param b the moved start position
* @param n the moved count
*
* @return the buffer data address
*/
tb_byte_t* tb_buffer_memnmov(tb_buffer_ref_t buffer, tb_size_t b, tb_size_t n);
/*! memmov: b ... n => p ...
*
* @param buffer the buffer
* @param p the moved destination position
* @param b the moved start position
* @param n the moved count
*
* @return the buffer data address
*/
tb_byte_t* tb_buffer_memnmovp(tb_buffer_ref_t buffer, tb_size_t p, tb_size_t b, tb_size_t n);
/*! memcat: b +=> e ...
*
* @param buffer the buffer
* @param b the concated buffer
*
* @return the buffer data address
*/
tb_byte_t* tb_buffer_memcat(tb_buffer_ref_t buffer, tb_buffer_ref_t b);
/*! memcat: b ... n +=> e ...
*
* @param buffer the buffer
* @param b the concated buffer
* @param n the concated count
*
* @return the buffer data address
*/
tb_byte_t* tb_buffer_memncat(tb_buffer_ref_t buffer, tb_byte_t const* b, tb_size_t n);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/memory/default_allocator.c 0000664 0000000 0000000 00000027133 14671175054 0021424 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file default_allocator.c
* @ingroup memory
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "allocator"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "allocator.h"
#include "small_allocator.h"
#include "large_allocator.h"
#include "default_allocator.h"
#include "impl/prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the default allocator type
typedef struct __tb_default_allocator_t
{
// the base
tb_allocator_t base;
// the large allocator
tb_allocator_ref_t large_allocator;
// the small allocator
tb_allocator_ref_t small_allocator;
}tb_default_allocator_t, *tb_default_allocator_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_void_t tb_default_allocator_exit(tb_allocator_ref_t self)
{
// check
tb_default_allocator_ref_t allocator = (tb_default_allocator_ref_t)self;
tb_assert_and_check_return(allocator);
// enter
tb_spinlock_enter(&allocator->base.lock);
// exit small allocator
if (allocator->small_allocator) tb_allocator_exit(allocator->small_allocator);
allocator->small_allocator = tb_null;
// leave
tb_spinlock_leave(&allocator->base.lock);
// exit lock
tb_spinlock_exit(&allocator->base.lock);
// exit allocator
if (allocator->large_allocator) tb_allocator_large_free(allocator->large_allocator, allocator);
}
static tb_pointer_t tb_default_allocator_malloc(tb_allocator_ref_t self, tb_size_t size __tb_debug_decl__)
{
// check
tb_default_allocator_ref_t allocator = (tb_default_allocator_ref_t)self;
tb_assert_and_check_return_val(allocator, tb_null);
// check
tb_assert_and_check_return_val(allocator->large_allocator && allocator->small_allocator && size, tb_null);
// done
return size <= TB_SMALL_ALLOCATOR_DATA_MAXN? tb_allocator_malloc_(allocator->small_allocator, size __tb_debug_args__) : tb_allocator_large_malloc_(allocator->large_allocator, size, tb_null __tb_debug_args__);
}
static tb_pointer_t tb_default_allocator_ralloc(tb_allocator_ref_t self, tb_pointer_t data, tb_size_t size __tb_debug_decl__)
{
// check
tb_default_allocator_ref_t allocator = (tb_default_allocator_ref_t)self;
tb_assert_and_check_return_val(allocator, tb_null);
// check
tb_assert_and_check_return_val(allocator && allocator->large_allocator && allocator->small_allocator && size, tb_null);
// done
tb_pointer_t data_new = tb_null;
do
{
// no data?
if (!data)
{
// malloc it directly
data_new = size <= TB_SMALL_ALLOCATOR_DATA_MAXN? tb_allocator_malloc_(allocator->small_allocator, size __tb_debug_args__) : tb_allocator_large_malloc_(allocator->large_allocator, size, tb_null __tb_debug_args__);
break;
}
// the data head
tb_pool_data_head_t* data_head = &(((tb_pool_data_head_t*)data)[-1]);
tb_assertf(data_head->debug.magic == TB_POOL_DATA_MAGIC, "ralloc invalid data: %p", data);
tb_assert_and_check_break(data_head->size);
// small => small
if (data_head->size <= TB_SMALL_ALLOCATOR_DATA_MAXN && size <= TB_SMALL_ALLOCATOR_DATA_MAXN)
data_new = tb_allocator_ralloc_(allocator->small_allocator, data, size __tb_debug_args__);
// small => large
else if (data_head->size <= TB_SMALL_ALLOCATOR_DATA_MAXN)
{
// make the new data
data_new = tb_allocator_large_malloc_(allocator->large_allocator, size, tb_null __tb_debug_args__);
tb_assert_and_check_break(data_new);
// copy the old data
tb_memcpy_(data_new, data, tb_min(data_head->size, size));
// free the old data
tb_allocator_free_(allocator->small_allocator, data __tb_debug_args__);
}
// large => small
else if (size <= TB_SMALL_ALLOCATOR_DATA_MAXN)
{
// make the new data
data_new = tb_allocator_malloc_(allocator->small_allocator, size __tb_debug_args__);
tb_assert_and_check_break(data_new);
// copy the old data
tb_memcpy_(data_new, data, tb_min(data_head->size, size));
// free the old data
tb_allocator_large_free_(allocator->large_allocator, data __tb_debug_args__);
}
// large => large
else data_new = tb_allocator_large_ralloc_(allocator->large_allocator, data, size, tb_null __tb_debug_args__);
} while (0);
// ok?
return data_new;
}
static tb_bool_t tb_default_allocator_free(tb_allocator_ref_t self, tb_pointer_t data __tb_debug_decl__)
{
// check
tb_default_allocator_ref_t allocator = (tb_default_allocator_ref_t)self;
tb_assert_and_check_return_val(allocator, tb_false);
// check
tb_assert_and_check_return_val(allocator->large_allocator && allocator->small_allocator && data, tb_false);
// done
tb_bool_t ok = tb_false;
do
{
// the data head
tb_pool_data_head_t* data_head = &(((tb_pool_data_head_t*)data)[-1]);
tb_assertf(data_head->debug.magic == TB_POOL_DATA_MAGIC, "free invalid data: %p", data);
// free it
ok = (data_head->size <= TB_SMALL_ALLOCATOR_DATA_MAXN)? tb_allocator_free_(allocator->small_allocator, data __tb_debug_args__) : tb_allocator_large_free_(allocator->large_allocator, data __tb_debug_args__);
} while (0);
// ok?
return ok;
}
#ifdef __tb_debug__
static tb_void_t tb_default_allocator_dump(tb_allocator_ref_t self)
{
// check
tb_default_allocator_ref_t allocator = (tb_default_allocator_ref_t)self;
tb_assert_and_check_return(allocator && allocator->small_allocator);
// dump allocator
tb_allocator_dump(allocator->small_allocator);
}
static tb_bool_t tb_default_allocator_have(tb_allocator_ref_t self, tb_cpointer_t data)
{
// check
tb_default_allocator_ref_t allocator = (tb_default_allocator_ref_t)self;
tb_assert_and_check_return_val(allocator && allocator->large_allocator, tb_false);
// have it?
return tb_allocator_have(allocator->large_allocator, data);
}
#endif
static tb_handle_t tb_default_allocator_instance_init(tb_cpointer_t* ppriv)
{
// check
tb_check_return_val(ppriv, tb_null);
// the data and size
tb_value_ref_t tuple = (tb_value_ref_t)*ppriv;
tb_byte_t* data = (tb_byte_t*)tuple[0].ptr;
tb_size_t size = tuple[1].ul;
// clear the private data first
*ppriv = tb_null;
// done
tb_bool_t ok = tb_false;
tb_allocator_ref_t allocator = tb_null;
tb_allocator_ref_t large_allocator = tb_null;
do
{
/* init the page first
*
* because this allocator may be called before tb_init()
*/
if (!tb_page_init()) break ;
/* init the native memory first
*
* because this allocator may be called before tb_init()
*/
if (!tb_native_memory_init()) break ;
// init large allocator
large_allocator = tb_large_allocator_init(data, size);
tb_assert_and_check_break(large_allocator);
// init allocator
allocator = tb_default_allocator_init(large_allocator);
tb_assert_and_check_break(allocator);
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit large allocator
if (large_allocator) tb_allocator_exit(large_allocator);
large_allocator = tb_null;
}
// ok?
return (tb_handle_t)allocator;
}
static tb_void_t tb_default_allocator_instance_exit(tb_handle_t self, tb_cpointer_t priv)
{
// check
tb_default_allocator_ref_t allocator = (tb_default_allocator_ref_t)self;
tb_assert_and_check_return(allocator);
// the large allocator
tb_allocator_ref_t large_allocator = allocator->large_allocator;
tb_assert_and_check_return(large_allocator);
#ifdef __tb_debug__
// dump allocator
if (allocator) tb_allocator_dump((tb_allocator_ref_t)allocator);
#endif
// exit allocator
if (allocator) tb_allocator_exit((tb_allocator_ref_t)allocator);
allocator = tb_null;
#ifdef __tb_debug__
// dump large allocator
tb_allocator_dump(large_allocator);
#endif
// exit large allocator
tb_allocator_exit(large_allocator);
large_allocator = tb_null;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_allocator_ref_t tb_default_allocator(tb_byte_t* data, tb_size_t size)
{
/* init singleton first
*
* because this allocator may be called before tb_init()
*/
if (!tb_singleton_init()) return tb_null;
// init tuple
tb_value_t tuple[2];
tuple[0].ptr = (tb_pointer_t)data;
tuple[1].ul = size;
// get it
return (tb_allocator_ref_t)tb_singleton_instance(TB_SINGLETON_TYPE_DEFAULT_ALLOCATOR, tb_default_allocator_instance_init, tb_default_allocator_instance_exit, tb_null, tuple);
}
tb_allocator_ref_t tb_default_allocator_init(tb_allocator_ref_t large_allocator)
{
// check
tb_assert_and_check_return_val(large_allocator, tb_null);
// done
tb_bool_t ok = tb_false;
tb_default_allocator_ref_t allocator = tb_null;
do
{
// make allocator
allocator = (tb_default_allocator_ref_t)tb_allocator_large_malloc0(large_allocator, sizeof(tb_default_allocator_t), tb_null);
tb_assert_and_check_break(allocator);
// init base
allocator->base.type = TB_ALLOCATOR_TYPE_DEFAULT;
allocator->base.flag = TB_ALLOCATOR_FLAG_NONE;
allocator->base.malloc = tb_default_allocator_malloc;
allocator->base.ralloc = tb_default_allocator_ralloc;
allocator->base.free = tb_default_allocator_free;
allocator->base.exit = tb_default_allocator_exit;
#ifdef __tb_debug__
allocator->base.dump = tb_default_allocator_dump;
allocator->base.have = tb_default_allocator_have;
#endif
// init lock
if (!tb_spinlock_init(&allocator->base.lock)) break;
// init allocator
allocator->large_allocator = large_allocator;
allocator->small_allocator = tb_small_allocator_init(large_allocator);
tb_assert_and_check_break(allocator->small_allocator);
// register lock profiler
#ifdef TB_LOCK_PROFILER_ENABLE
tb_lock_profiler_register(tb_lock_profiler(), (tb_pointer_t)&allocator->base.lock, TB_TRACE_MODULE_NAME);
#endif
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
if (allocator) tb_default_allocator_exit((tb_allocator_ref_t)allocator);
allocator = tb_null;
}
// ok?
return (tb_allocator_ref_t)allocator;
}
tbox-1.7.6/src/tbox/memory/default_allocator.h 0000664 0000000 0000000 00000006436 14671175054 0021434 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file default_allocator.h
* @ingroup memory
*
*/
#ifndef TB_MEMORY_DEFAULT_ALLOCATOR_H
#define TB_MEMORY_DEFAULT_ALLOCATOR_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "allocator.h"
#include "large_allocator.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the global default allocator
*
* @param data the buffer data, uses the native buffer if be null
* @param size the buffer size
*
* @return the allocator
*/
tb_allocator_ref_t tb_default_allocator(tb_byte_t* data, tb_size_t size);
/*! init the default allocator
*
*
*
* ---------------- -------------------------------------------------------
* | native memory | or | data |
* ---------------- -------------------------------------------------------
* | if data be null |
* `---------------------------------------> |
* |
* -----------------------------------------------------------------------------
* | large allocator |
* -----------------------------------------------------------------------------
* | |
* | ---------------------------------------
* | | small allocator |
* | ---------------------------------------
* | |
* -----------------------------------------------------------------------------
* | >3KB | <=3KB |
* |-----------------------------------------------------------------------------|
* | default allocator |
* -----------------------------------------------------------------------------
*
*
*
* @param large_allocator the large allocator, cannot be null
*
* @return the allocator
*/
tb_allocator_ref_t tb_default_allocator_init(tb_allocator_ref_t large_allocator);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/memory/fixed_pool.c 0000664 0000000 0000000 00000054457 14671175054 0020101 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file fixed_pool.c
* @ingroup memory
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "fixed_pool"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "fixed_pool.h"
#include "large_allocator.h"
#include "impl/static_fixed_pool.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the item belong to this slot?
#define tb_fixed_pool_slot_exists(slot, item) (((tb_byte_t*)(item) > (tb_byte_t*)(slot)) && ((tb_byte_t*)(item) < (tb_byte_t*)slot + (slot)->size))
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the fixed pool slot type
typedef struct __tb_fixed_pool_slot_t
{
// the size: sizeof(slot) + data
tb_size_t size;
// the pool
tb_static_fixed_pool_ref_t pool;
// the list entry
tb_list_entry_t entry;
}tb_fixed_pool_slot_t;
// the fixed pool type
typedef struct __tb_fixed_pool_impl_t
{
// the large allocator
tb_allocator_ref_t large_allocator;
// the slot size
tb_size_t slot_size;
// the item size
tb_size_t item_size;
// the item count
tb_size_t item_count;
// the init func
tb_fixed_pool_item_init_func_t func_init;
// the exit func
tb_fixed_pool_item_exit_func_t func_exit;
// the private data
tb_cpointer_t func_priv;
// the current slot
tb_fixed_pool_slot_t* current_slot;
// the partial slot
tb_list_entry_head_t partial_slots;
// the full slot
tb_list_entry_head_t full_slots;
// the slot list
tb_fixed_pool_slot_t** slot_list;
// the slot count
tb_size_t slot_count;
// the slot space
tb_size_t slot_space;
// for small allocator
tb_bool_t for_small;
}tb_fixed_pool_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* declaration
*/
__tb_extern_c__ tb_fixed_pool_ref_t tb_fixed_pool_init_(tb_allocator_ref_t large_allocator, tb_size_t slot_size, tb_size_t item_size, tb_bool_t for_small, tb_fixed_pool_item_init_func_t item_init, tb_fixed_pool_item_exit_func_t item_exit, tb_cpointer_t priv);
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_bool_t tb_fixed_pool_item_exit(tb_pointer_t data, tb_cpointer_t priv)
{
// check
tb_fixed_pool_t* pool = (tb_fixed_pool_t*)priv;
tb_assert(pool && pool->func_exit);
// done exit
pool->func_exit(data, pool->func_priv);
// continue
return tb_true;
}
static tb_void_t tb_fixed_pool_slot_exit(tb_fixed_pool_t* pool, tb_fixed_pool_slot_t* slot)
{
// check
tb_assert_and_check_return(pool && pool->large_allocator && slot);
tb_assert_and_check_return(pool->slot_list && pool->slot_count);
// trace
tb_trace_d("slot[%lu]: exit: size: %lu", pool->item_size, slot->size);
// make the iterator
tb_array_iterator_t array_iterator;
tb_iterator_ref_t iterator = tb_array_iterator_init_ptr(&array_iterator, (tb_pointer_t*)pool->slot_list, pool->slot_count);
tb_assert(iterator);
// find the slot from the slot list
tb_size_t itor = tb_binary_find_all(iterator, (tb_cpointer_t)slot);
tb_assert(itor != tb_iterator_tail(iterator) && itor < pool->slot_count && pool->slot_list[itor]);
tb_check_return(itor != tb_iterator_tail(iterator) && itor < pool->slot_count && pool->slot_list[itor]);
// remove the slot
if (itor + 1 < pool->slot_count) tb_memmov_(pool->slot_list + itor, pool->slot_list + itor + 1, (pool->slot_count - itor - 1) * sizeof(tb_fixed_pool_slot_t*));
// update the slot count
pool->slot_count--;
// exit slot
tb_allocator_large_free(pool->large_allocator, slot);
}
static tb_fixed_pool_slot_t* tb_fixed_pool_slot_init(tb_fixed_pool_t* pool)
{
// check
tb_assert_and_check_return_val(pool && pool->large_allocator && pool->slot_size && pool->item_size, tb_null);
// done
tb_bool_t ok = tb_false;
tb_fixed_pool_slot_t* slot = tb_null;
do
{
#ifdef __tb_debug__
// init patch for checking underflow
tb_size_t patch = 1;
#else
tb_size_t patch = 0;
#endif
// the item space
tb_size_t item_space = sizeof(tb_pool_data_head_t) + pool->item_size + patch;
// the need space
tb_size_t need_space = sizeof(tb_fixed_pool_slot_t) + pool->slot_size * item_space;
// make slot
tb_size_t real_space = 0;
slot = (tb_fixed_pool_slot_t*)tb_allocator_large_malloc(pool->large_allocator, need_space, &real_space);
tb_assert_and_check_break(slot);
tb_assert_and_check_break(real_space > sizeof(tb_fixed_pool_slot_t) + item_space);
// init slot
slot->size = real_space;
slot->pool = tb_static_fixed_pool_init((tb_byte_t*)&slot[1], real_space - sizeof(tb_fixed_pool_slot_t), pool->item_size, pool->for_small);
tb_assert_and_check_break(slot->pool);
// no list?
if (!pool->slot_list)
{
// init the slot list
tb_size_t size = 0;
pool->slot_list = (tb_fixed_pool_slot_t**)tb_allocator_large_nalloc(pool->large_allocator, 64, sizeof(tb_fixed_pool_slot_t*), &size);
tb_assert_and_check_break(pool->slot_list && size);
// init the slot count
pool->slot_count = 0;
// init the slot space
pool->slot_space = size / sizeof(tb_fixed_pool_slot_t*);
tb_assert_and_check_break(pool->slot_space);
}
// no enough space?
else if (pool->slot_count == pool->slot_space)
{
// grow the slot list
tb_size_t size = 0;
pool->slot_list = (tb_fixed_pool_slot_t**)tb_allocator_large_ralloc(pool->large_allocator, pool->slot_list, (pool->slot_space << 1) * sizeof(tb_fixed_pool_slot_t*), &size);
tb_assert_and_check_break(pool->slot_list && size);
// update the slot space
pool->slot_space = size / sizeof(tb_fixed_pool_slot_t*);
tb_assert_and_check_break(pool->slot_space);
}
// check
tb_assert_and_check_break(pool->slot_count < pool->slot_space);
// insert the slot to the slot list in the increasing order (TODO binary search)
tb_size_t i = 0;
tb_size_t n = pool->slot_count;
for (i = 0; i < n; i++) if (slot <= pool->slot_list[i]) break;
if (i < n) tb_memmov_(pool->slot_list + i + 1, pool->slot_list + i, (n - i) * sizeof(tb_fixed_pool_slot_t*));
pool->slot_list[i] = slot;
// update the slot count
pool->slot_count++;
// trace
tb_trace_d("slot[%lu]: init: size: %lu => %lu, item: %lu => %lu", pool->item_size, need_space, real_space, pool->slot_size, tb_static_fixed_pool_maxn(slot->pool));
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (slot) tb_fixed_pool_slot_exit(pool, slot);
slot = tb_null;
}
// ok?
return slot;
}
#if 0
static tb_fixed_pool_slot_t* tb_fixed_pool_slot_find(tb_fixed_pool_t* pool, tb_pointer_t data)
{
// check
tb_assert_and_check_return_val(pool && data, tb_null);
// done
tb_fixed_pool_slot_t* slot = tb_null;
do
{
// belong to the current slot?
if (pool->current_slot && tb_fixed_pool_slot_exists(pool->current_slot, data))
{
slot = pool->current_slot;
break;
}
// find the slot from the partial slots
tb_for_all_if(tb_fixed_pool_slot_t*, partial_slot, tb_list_entry_itor(&pool->partial_slots), partial_slot)
{
// is this?
if (tb_fixed_pool_slot_exists(partial_slot, data))
{
slot = partial_slot;
break;
}
}
// no found?
tb_check_break(!slot);
// find the slot from the full slots
tb_for_all_if(tb_fixed_pool_slot_t*, full_slot, tb_list_entry_itor(&pool->full_slots), full_slot)
{
// is this?
if (tb_fixed_pool_slot_exists(full_slot, data))
{
slot = full_slot;
break;
}
}
} while (0);
// ok?
return slot;
}
#else
static tb_long_t tb_fixed_pool_slot_comp(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t data)
{
// the slot
tb_fixed_pool_slot_t* slot = (tb_fixed_pool_slot_t*)item;
tb_assert(slot);
// comp
return (tb_byte_t*)data < (tb_byte_t*)slot? 1 : ((tb_byte_t*)data >= (tb_byte_t*)slot + slot->size? -1 : 0);
}
static tb_fixed_pool_slot_t* tb_fixed_pool_slot_find(tb_fixed_pool_t* pool, tb_pointer_t data)
{
// check
tb_assert_and_check_return_val(pool && data, tb_null);
// make the iterator
tb_array_iterator_t array_iterator;
tb_iterator_ref_t iterator = tb_array_iterator_init_ptr(&array_iterator, (tb_pointer_t*)pool->slot_list, pool->slot_count);
tb_assert(iterator);
// find it
tb_size_t itor = tb_binary_find_all_if(iterator, tb_fixed_pool_slot_comp, data);
tb_check_return_val(itor != tb_iterator_tail(iterator), tb_null);
// the slot
tb_fixed_pool_slot_t* slot = pool->slot_list[itor];
tb_assert_and_check_return_val(slot, tb_null);
// check
tb_assert(tb_fixed_pool_slot_exists(slot, data));
// ok?
return slot;
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_fixed_pool_ref_t tb_fixed_pool_init_(tb_allocator_ref_t large_allocator, tb_size_t slot_size, tb_size_t item_size, tb_bool_t for_small, tb_fixed_pool_item_init_func_t item_init, tb_fixed_pool_item_exit_func_t item_exit, tb_cpointer_t priv)
{
// check
tb_assert_and_check_return_val(item_size, tb_null);
// done
tb_bool_t ok = tb_false;
tb_fixed_pool_t* pool = tb_null;
do
{
// no allocator? uses the global allocator
if (!large_allocator) large_allocator = tb_allocator();
tb_assert_and_check_break(large_allocator);
// make pool
pool = (tb_fixed_pool_t*)tb_allocator_large_malloc0(large_allocator, sizeof(tb_fixed_pool_t), tb_null);
tb_assert_and_check_break(pool);
// init pool
pool->large_allocator = large_allocator;
pool->slot_size = slot_size? slot_size : (tb_page_size() >> 4);
pool->item_size = item_size;
pool->func_init = item_init;
pool->func_exit = item_exit;
pool->func_priv = priv;
pool->for_small = for_small;
tb_assert_and_check_break(pool->slot_size);
// init partial slots
tb_list_entry_init(&pool->partial_slots, tb_fixed_pool_slot_t, entry, tb_null);
// init full slots
tb_list_entry_init(&pool->full_slots, tb_fixed_pool_slot_t, entry, tb_null);
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (pool) tb_fixed_pool_exit((tb_fixed_pool_ref_t)pool);
pool = tb_null;
}
// ok?
return (tb_fixed_pool_ref_t)pool;
}
tb_fixed_pool_ref_t tb_fixed_pool_init(tb_allocator_ref_t large_allocator, tb_size_t slot_size, tb_size_t item_size, tb_fixed_pool_item_init_func_t item_init, tb_fixed_pool_item_exit_func_t item_exit, tb_cpointer_t priv)
{
return tb_fixed_pool_init_(large_allocator, slot_size, item_size, tb_false, item_init, item_exit, priv);
}
tb_void_t tb_fixed_pool_exit(tb_fixed_pool_ref_t self)
{
// check
tb_fixed_pool_t* pool = (tb_fixed_pool_t*)self;
tb_assert_and_check_return(pool);
// clear it
tb_fixed_pool_clear(self);
// exit the current slot
if (pool->current_slot) tb_fixed_pool_slot_exit(pool, pool->current_slot);
pool->current_slot = tb_null;
// exit the slot list
if (pool->slot_list) tb_allocator_large_free(pool->large_allocator, pool->slot_list);
pool->slot_list = tb_null;
pool->slot_count = 0;
pool->slot_space = 0;
// exit it
tb_allocator_large_free(pool->large_allocator, pool);
}
tb_size_t tb_fixed_pool_size(tb_fixed_pool_ref_t self)
{
// check
tb_fixed_pool_t* pool = (tb_fixed_pool_t*)self;
tb_assert_and_check_return_val(pool, 0);
// the item count
return pool->item_count;
}
tb_size_t tb_fixed_pool_item_size(tb_fixed_pool_ref_t self)
{
// check
tb_fixed_pool_t* pool = (tb_fixed_pool_t*)self;
tb_assert_and_check_return_val(pool, 0);
// the item size
return pool->item_size;
}
tb_void_t tb_fixed_pool_clear(tb_fixed_pool_ref_t self)
{
// check
tb_fixed_pool_t* pool = (tb_fixed_pool_t*)self;
tb_assert_and_check_return(pool);
// exit items
if (pool->func_exit) tb_fixed_pool_walk(self, tb_fixed_pool_item_exit, (tb_pointer_t)pool);
// exit the partial slots
tb_iterator_ref_t partial_iterator = tb_list_entry_itor(&pool->partial_slots);
if (partial_iterator)
{
// walk it
tb_size_t itor = tb_iterator_head(partial_iterator);
while (itor != tb_iterator_tail(partial_iterator))
{
// the slot
tb_fixed_pool_slot_t* slot = (tb_fixed_pool_slot_t*)tb_iterator_item(partial_iterator, itor);
tb_assert_and_check_break(slot);
// check
tb_assert(slot != pool->current_slot);
// save next
tb_size_t next = tb_iterator_next(partial_iterator, itor);
// exit slot
tb_fixed_pool_slot_exit(pool, slot);
// next
itor = next;
}
}
// exit the full slots
tb_iterator_ref_t full_iterator = tb_list_entry_itor(&pool->full_slots);
if (full_iterator)
{
// walk it
tb_size_t itor = tb_iterator_head(full_iterator);
while (itor != tb_iterator_tail(full_iterator))
{
// the slot
tb_fixed_pool_slot_t* slot = (tb_fixed_pool_slot_t*)tb_iterator_item(full_iterator, itor);
tb_assert_and_check_break(slot);
// check
tb_assert(slot != pool->current_slot);
// save next
tb_size_t next = tb_iterator_next(full_iterator, itor);
// exit slot
tb_fixed_pool_slot_exit(pool, slot);
// next
itor = next;
}
}
// clear current slot
if (pool->current_slot && pool->current_slot->pool)
tb_static_fixed_pool_clear(pool->current_slot->pool);
// clear item count
pool->item_count = 0;
// clear partial slots
tb_list_entry_clear(&pool->partial_slots);
// clear full slots
tb_list_entry_clear(&pool->full_slots);
}
tb_pointer_t tb_fixed_pool_malloc_(tb_fixed_pool_ref_t self __tb_debug_decl__)
{
// check
tb_fixed_pool_t* pool = (tb_fixed_pool_t*)self;
tb_assert_and_check_return_val(pool, tb_null);
// done
tb_bool_t ok = tb_false;
tb_pointer_t data = tb_null;
do
{
// no current slot or the current slot is full? update the current slot
if (!pool->current_slot || tb_static_fixed_pool_full(pool->current_slot->pool))
{
// move the current slot to the full slots if exists
if (pool->current_slot) tb_list_entry_insert_tail(&pool->full_slots, &pool->current_slot->entry);
// clear the current slot
pool->current_slot = tb_null;
// attempt to get a slot from the partial slots
if (!tb_list_entry_is_null(&pool->partial_slots))
{
// the head entry
tb_list_entry_ref_t entry = tb_list_entry_head(&pool->partial_slots);
tb_assert_and_check_break(entry);
// the head slot
pool->current_slot = (tb_fixed_pool_slot_t*)tb_list_entry(&pool->partial_slots, entry);
tb_assert_and_check_break(pool->current_slot);
// remove this slot from the partial slots
tb_list_entry_remove(&pool->partial_slots, entry);
}
// make a new slot
else pool->current_slot = tb_fixed_pool_slot_init(pool);
}
// check
tb_assert_and_check_break(pool->current_slot && pool->current_slot->pool);
tb_assert_and_check_break(!tb_static_fixed_pool_full(pool->current_slot->pool));
// make data from the current slot
data = tb_static_fixed_pool_malloc(pool->current_slot->pool __tb_debug_args__);
tb_assert_and_check_break(data);
// done init
if (pool->func_init && !pool->func_init(data, pool->func_priv)) break;
// update the item count
pool->item_count++;
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit data
if (data && pool->current_slot && pool->current_slot->pool)
tb_static_fixed_pool_free(pool->current_slot->pool, data __tb_debug_args__);
data = tb_null;
}
// check
tb_assertf(data, "malloc(%lu) failed!", pool->item_size);
// ok?
return data;
}
tb_pointer_t tb_fixed_pool_malloc0_(tb_fixed_pool_ref_t self __tb_debug_decl__)
{
// check
tb_fixed_pool_t* pool = (tb_fixed_pool_t*)self;
tb_assert_and_check_return_val(pool, tb_null);
// done
tb_pointer_t data = tb_fixed_pool_malloc_(self __tb_debug_args__);
tb_assert_and_check_return_val(data, tb_null);
// clear it
tb_memset_(data, 0, pool->item_size);
// ok
return data;
}
tb_bool_t tb_fixed_pool_free_(tb_fixed_pool_ref_t self, tb_pointer_t data __tb_debug_decl__)
{
// check
tb_fixed_pool_t* pool = (tb_fixed_pool_t*)self;
tb_assert_and_check_return_val(pool, tb_false);
// done
tb_bool_t ok = tb_false;
do
{
// check
tb_assertf_pass_and_check_break(pool->item_count, "double free data: %p", data);
// find the slot
tb_fixed_pool_slot_t* slot = tb_fixed_pool_slot_find(pool, data);
tb_assertf_pass_and_check_break(slot, "the data: %p not belong to pool: %p", data, self);
tb_assert_pass_and_check_break(slot->pool);
// the slot is full?
tb_bool_t full = tb_static_fixed_pool_full(slot->pool);
// done exit
if (pool->func_exit) pool->func_exit(data, pool->func_priv);
// free it
if (!tb_static_fixed_pool_free(slot->pool, data __tb_debug_args__)) break;
// not the current slot?
if (slot != pool->current_slot)
{
// is full? move the slot to the partial slots
if (full)
{
tb_list_entry_remove(&pool->full_slots, &slot->entry);
tb_list_entry_insert_tail(&pool->partial_slots, &slot->entry);
}
// is null? exit the slot
else if (tb_static_fixed_pool_null(slot->pool))
{
tb_list_entry_remove(&pool->partial_slots, &slot->entry);
tb_fixed_pool_slot_exit(pool, slot);
}
}
// update the item count
pool->item_count--;
// ok
ok = tb_true;
} while (0);
// failed? dump it
#ifdef __tb_debug__
if (!ok)
{
// trace
tb_trace_e("free(%p) failed! at %s(): %lu, %s", data, func_, line_, file_);
// dump data
tb_pool_data_dump((tb_byte_t const*)data, tb_true, "[fixed_pool]: [error]: ");
// abort
tb_abort();
}
#endif
// ok?
return ok;
}
tb_void_t tb_fixed_pool_walk(tb_fixed_pool_ref_t self, tb_fixed_pool_item_walk_func_t func, tb_cpointer_t priv)
{
// check
tb_fixed_pool_t* pool = (tb_fixed_pool_t*)self;
tb_assert_and_check_return(pool && func);
// walk the current slot first
if (pool->current_slot && pool->current_slot->pool)
tb_static_fixed_pool_walk(pool->current_slot->pool, func, priv);
// walk the partial slots
tb_for_all_if(tb_fixed_pool_slot_t*, partial_slot, tb_list_entry_itor(&pool->partial_slots), partial_slot && partial_slot->pool)
{
// check
tb_assert(!tb_static_fixed_pool_full(partial_slot->pool));
// walk
tb_static_fixed_pool_walk(partial_slot->pool, func, priv);
}
// walk the full slots
tb_for_all_if(tb_fixed_pool_slot_t*, full_slot, tb_list_entry_itor(&pool->full_slots), full_slot && full_slot->pool)
{
// check
tb_assert(tb_static_fixed_pool_full(full_slot->pool));
// walk
tb_static_fixed_pool_walk(full_slot->pool, func, priv);
}
}
#ifdef __tb_debug__
tb_void_t tb_fixed_pool_dump(tb_fixed_pool_ref_t self)
{
// check
tb_fixed_pool_t* pool = (tb_fixed_pool_t*)self;
tb_assert_and_check_return(pool);
// dump the current slot first
if (pool->current_slot && pool->current_slot->pool)
tb_static_fixed_pool_dump(pool->current_slot->pool);
// dump the partial slots
tb_for_all_if(tb_fixed_pool_slot_t*, partial_slot, tb_list_entry_itor(&pool->partial_slots), partial_slot && partial_slot->pool)
{
// check
tb_assert(!tb_static_fixed_pool_full(partial_slot->pool));
// dump
tb_static_fixed_pool_dump(partial_slot->pool);
}
// dump the full slots
tb_for_all_if(tb_fixed_pool_slot_t*, full_slot, tb_list_entry_itor(&pool->full_slots), full_slot && full_slot->pool)
{
// check
tb_assert(tb_static_fixed_pool_full(full_slot->pool));
// dump
tb_static_fixed_pool_dump(full_slot->pool);
}
}
#endif
tbox-1.7.6/src/tbox/memory/fixed_pool.h 0000664 0000000 0000000 00000017420 14671175054 0020073 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file fixed_pool.h
* @ingroup memory
*
*/
#ifndef TB_MEMORY_FIXED_POOL_H
#define TB_MEMORY_FIXED_POOL_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "large_allocator.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define tb_fixed_pool_malloc(pool) tb_fixed_pool_malloc_(pool __tb_debug_vals__)
#define tb_fixed_pool_malloc0(pool) tb_fixed_pool_malloc0_(pool __tb_debug_vals__)
#define tb_fixed_pool_free(pool, item) tb_fixed_pool_free_(pool, (tb_pointer_t)(item) __tb_debug_vals__)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/*! the fixed pool ref type
*
*
*
* current:
* -----------
* | |
* -------------- |
* | slot |<--
* |--------------|
* ||||||||||||||||
* |--------------|
* | |
* |--------------|
* | |
* |--------------|
* ||||||||||||||||
* |--------------|
* ||||||||||||||||
* |--------------|
* | |
* --------------
*
* partial:
*
* -------------- -------------- --------------
* | slot | <=> | slot | <=> ... <=> | slot |
* |--------------| |--------------| |--------------|
* |||||||||||||||| | | | |
* |--------------| |--------------| |--------------|
* | | |||||||||||||||| | |
* |--------------| |--------------| |--------------|
* | | |||||||||||||||| ||||||||||||||||
* |--------------| |--------------| |--------------|
* |||||||||||||||| |||||||||||||||| | |
* |--------------| |--------------| |--------------|
* |||||||||||||||| | | | |
* |--------------| |--------------| |--------------|
* | | | | ||||||||||||||||
* -------------- -------------- --------------
*
* full:
*
* -------------- -------------- --------------
* | slot | <=> | slot | <=> ... <=> | slot |
* |--------------| |--------------| |--------------|
* |||||||||||||||| |||||||||||||||| ||||||||||||||||
* |--------------| |--------------| |--------------|
* |||||||||||||||| |||||||||||||||| ||||||||||||||||
* |--------------| |--------------| |--------------|
* |||||||||||||||| |||||||||||||||| ||||||||||||||||
* |--------------| |--------------| |--------------|
* |||||||||||||||| |||||||||||||||| ||||||||||||||||
* |--------------| |--------------| |--------------|
* |||||||||||||||| |||||||||||||||| ||||||||||||||||
* |--------------| |--------------| |--------------|
* |||||||||||||||| |||||||||||||||| ||||||||||||||||
* -------------- -------------- --------------
*
* slot:
*
* -------------- ------------------------>|
* | head | |
* |--------------| |
* ||| item | |
* |--------------| |
* ||| item | |
* |--------------| | data
* ||| item | |
* |--------------| |
* | ... | |
* |--------------| |
* ||| item | |
* -------------- ------------------------>|
*
*
*/
typedef __tb_typeref__(fixed_pool);
/// the item init func type
typedef tb_bool_t (*tb_fixed_pool_item_init_func_t)(tb_pointer_t data, tb_cpointer_t priv);
/// the item exit func type
typedef tb_void_t (*tb_fixed_pool_item_exit_func_t)(tb_pointer_t data, tb_cpointer_t priv);
/// the item walk func type
typedef tb_bool_t (*tb_fixed_pool_item_walk_func_t)(tb_pointer_t data, tb_cpointer_t priv);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init fixed pool
*
* @param large_allocator the large allocator, uses the global allocator if be null
* @param slot_size the item count per-slot, using the default size if be zero
* @param item_size the item size
* @param item_init the item init func
* @param item_exit the item exit func
* @param priv the private data
*
* @return the pool
*/
tb_fixed_pool_ref_t tb_fixed_pool_init(tb_allocator_ref_t large_allocator, tb_size_t slot_size, tb_size_t item_size, tb_fixed_pool_item_init_func_t item_init, tb_fixed_pool_item_exit_func_t item_exit, tb_cpointer_t priv);
/*! exit pool
*
* @param pool the pool
*/
tb_void_t tb_fixed_pool_exit(tb_fixed_pool_ref_t pool);
/*! the item count
*
* @param pool the pool
*
* @return the item count
*/
tb_size_t tb_fixed_pool_size(tb_fixed_pool_ref_t pool);
/*! the item size
*
* @param pool the pool
*
* @return the item size
*/
tb_size_t tb_fixed_pool_item_size(tb_fixed_pool_ref_t pool);
/*! clear pool
*
* @param pool the pool
*/
tb_void_t tb_fixed_pool_clear(tb_fixed_pool_ref_t pool);
/*! malloc data
*
* @param pool the pool
*
* @return the data
*/
tb_pointer_t tb_fixed_pool_malloc_(tb_fixed_pool_ref_t pool __tb_debug_decl__);
/*! malloc data and clear it
*
* @param pool the pool
*
* @return the data
*/
tb_pointer_t tb_fixed_pool_malloc0_(tb_fixed_pool_ref_t pool __tb_debug_decl__);
/*! free data
*
* @param pool the pool
* @param data the data
*
* @return tb_true or tb_false
*/
tb_bool_t tb_fixed_pool_free_(tb_fixed_pool_ref_t pool, tb_pointer_t data __tb_debug_decl__);
/*! walk item
*
* @code
tb_bool_t tb_fixed_pool_item_func(tb_pointer_t data, tb_cpointer_t priv)
{
// ok or break
return tb_true;
}
* @endcode
*
* @param pool the pool
* @param func the walk func
* @param priv the private data
*/
tb_void_t tb_fixed_pool_walk(tb_fixed_pool_ref_t pool, tb_fixed_pool_item_walk_func_t func, tb_cpointer_t priv);
#ifdef __tb_debug__
/*! dump pool
*
* @param pool the pool
*/
tb_void_t tb_fixed_pool_dump(tb_fixed_pool_ref_t pool);
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/memory/impl/ 0000775 0000000 0000000 00000000000 14671175054 0016527 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/memory/impl/impl.h 0000664 0000000 0000000 00000001721 14671175054 0017642 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file impl.h
*
*/
#ifndef TB_MEMORY_IMPL_H
#define TB_MEMORY_IMPL_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "memory.h"
#include "native_large_allocator.h"
#include "static_large_allocator.h"
#endif
tbox-1.7.6/src/tbox/memory/impl/memory.c 0000664 0000000 0000000 00000004343 14671175054 0020207 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file memory.c
* @ingroup memory
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "memory"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "memory.h"
#include "../memory.h"
#include "../../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
// the allocator
__tb_extern_c__ extern tb_allocator_ref_t g_allocator;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_memory_init_env(tb_allocator_ref_t allocator)
{
// done
tb_bool_t ok = tb_false;
do
{
// init page
if (!tb_page_init()) break;
// init the native memory
if (!tb_native_memory_init()) break;
// init the allocator
#if defined(TB_CONFIG_MICRO_ENABLE) || \
(defined(__tb_small__) && !defined(__tb_debug__))
g_allocator = allocator? allocator : tb_native_allocator();
#else
g_allocator = allocator? allocator : tb_default_allocator(tb_null, 0);
#endif
tb_assert_and_check_break(g_allocator);
// ok
ok = tb_true;
} while (0);
// failed? exit it
if (!ok) tb_memory_exit_env();
// ok?
return ok;
}
tb_void_t tb_memory_exit_env()
{
// exit the native memory
tb_native_memory_exit();
// exit page
tb_page_exit();
}
tbox-1.7.6/src/tbox/memory/impl/memory.h 0000664 0000000 0000000 00000003035 14671175054 0020211 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file memory.h
* @ingroup memory
*
*/
#ifndef TB_MEMORY_IMPL_MEMORY_H
#define TB_MEMORY_IMPL_MEMORY_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* init memory environment
*
* @param allocator the allocator
*
* @return tb_true or tb_false
*/
tb_bool_t tb_memory_init_env(tb_allocator_ref_t allocator);
// exit memory environment
tb_void_t tb_memory_exit_env(tb_noarg_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/memory/impl/native_large_allocator.c 0000664 0000000 0000000 00000052766 14671175054 0023413 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file native_large_allocator.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "native_large_allocator"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "native_large_allocator.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the native large allocator data size
#define tb_native_large_allocator_data_base(data_head) (&(((tb_pool_data_head_t*)((tb_native_large_data_head_t*)(data_head) + 1))[-1]))
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the native large data head type
typedef __tb_pool_data_aligned__ struct __tb_native_large_data_head_t
{
#ifdef __tb_debug__
// the allocator reference
tb_pointer_t allocator;
#endif
// the entry
tb_list_entry_t entry;
// the data head base
tb_byte_t base[sizeof(tb_pool_data_head_t)];
}__tb_pool_data_aligned__ tb_native_large_data_head_t;
/*! the native large allocator type
*
*
* ----------- ----------- -----------
* ||| data | <=> ||| data | <=> ... <=> ||| data | <=> |
* ----------- ----------- ----------- |
* | |
* `------------------------------------------------------`
*
*/
typedef struct __tb_native_large_allocator_t
{
// the base
tb_allocator_t base;
// the data list
tb_list_entry_head_t data_list;
#ifdef __tb_debug__
// the peak size
tb_size_t peak_size;
// the total size
tb_size_t total_size;
// the real size
tb_size_t real_size;
// the occupied size
tb_size_t occupied_size;
// the malloc count
tb_size_t malloc_count;
// the ralloc count
tb_size_t ralloc_count;
// the free count
tb_size_t free_count;
#endif
}tb_native_large_allocator_t, *tb_native_large_allocator_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
#ifdef __tb_debug__
static tb_void_t tb_native_large_allocator_check_data(tb_native_large_allocator_ref_t allocator, tb_native_large_data_head_t const* data_head)
{
// check
tb_assert_and_check_return(allocator && data_head);
// done
tb_bool_t ok = tb_false;
tb_byte_t const* data = (tb_byte_t const*)&(data_head[1]);
do
{
// the base head
tb_pool_data_head_t* base_head = tb_native_large_allocator_data_base(data_head);
// check
tb_assertf_pass_break(base_head->debug.magic != (tb_uint16_t)~TB_POOL_DATA_MAGIC, "data have been freed: %p", data);
tb_assertf_pass_break(base_head->debug.magic == TB_POOL_DATA_MAGIC, "the invalid data: %p", data);
tb_assertf_pass_break(((tb_byte_t*)data)[base_head->size] == TB_POOL_DATA_PATCH, "data underflow");
// ok
ok = tb_true;
} while (0);
// failed? dump it
#ifdef __tb_debug__
if (!ok)
{
// dump data
tb_pool_data_dump(data, tb_true, "[native_large_allocator]: [error]: ");
// abort
tb_abort();
}
#endif
}
static tb_void_t tb_native_large_allocator_check_last(tb_native_large_allocator_ref_t allocator)
{
// check
tb_assert_and_check_return(allocator);
// non-empty?
if (!tb_list_entry_is_null(&allocator->data_list))
{
// the last entry
tb_list_entry_ref_t data_last = tb_list_entry_last(&allocator->data_list);
tb_assert_and_check_return(data_last);
// check it
tb_native_large_allocator_check_data(allocator, (tb_native_large_data_head_t*)tb_list_entry(&allocator->data_list, data_last));
}
}
static tb_void_t tb_native_large_allocator_check_prev(tb_native_large_allocator_ref_t allocator, tb_native_large_data_head_t const* data_head)
{
// check
tb_assert_and_check_return(allocator && data_head);
// non-empty?
if (!tb_list_entry_is_null(&allocator->data_list))
{
// the prev entry
tb_list_entry_ref_t data_prev = tb_list_entry_prev((tb_list_entry_ref_t)&data_head->entry);
tb_assert_and_check_return(data_prev);
// not tail entry
tb_check_return(data_prev != tb_list_entry_tail(&allocator->data_list));
// check it
tb_native_large_allocator_check_data(allocator, (tb_native_large_data_head_t*)tb_list_entry(&allocator->data_list, data_prev));
}
}
static tb_void_t tb_native_large_allocator_check_next(tb_native_large_allocator_ref_t allocator, tb_native_large_data_head_t const* data_head)
{
// check
tb_assert_and_check_return(allocator && data_head);
// non-empty?
if (!tb_list_entry_is_null(&allocator->data_list))
{
// the next entry
tb_list_entry_ref_t data_next = tb_list_entry_next((tb_list_entry_ref_t)&data_head->entry);
tb_assert_and_check_return(data_next);
// not tail entry
tb_check_return(data_next != tb_list_entry_tail(&allocator->data_list));
// check it
tb_native_large_allocator_check_data(allocator, (tb_native_large_data_head_t*)tb_list_entry(&allocator->data_list, data_next));
}
}
#endif
static tb_pointer_t tb_native_large_allocator_malloc(tb_allocator_ref_t self, tb_size_t size, tb_size_t* real __tb_debug_decl__)
{
// check
tb_native_large_allocator_ref_t allocator = (tb_native_large_allocator_ref_t)self;
tb_assert_and_check_return_val(allocator, tb_null);
// done
#ifdef __tb_debug__
tb_size_t patch = 1; // patch 0xcc
#else
tb_size_t patch = 0;
#endif
tb_bool_t ok = tb_false;
tb_size_t need = sizeof(tb_native_large_data_head_t) + size + patch;
tb_byte_t* data = tb_null;
tb_byte_t* data_real = tb_null;
tb_native_large_data_head_t* data_head = tb_null;
do
{
#ifdef __tb_debug__
// check the last data
tb_native_large_allocator_check_last(allocator);
#endif
// make data
data = (tb_byte_t*)(size >= TB_VIRTUAL_MEMORY_DATA_MINN? tb_virtual_memory_malloc(need) : tb_native_memory_malloc(need));
tb_assert_and_check_break(data);
tb_assert_and_check_break(!(((tb_size_t)data) & 0x1));
// make the real data
data_real = data + sizeof(tb_native_large_data_head_t);
// init the data head
data_head = (tb_native_large_data_head_t*)data;
// the base head
tb_pool_data_head_t* base_head = tb_native_large_allocator_data_base(data_head);
// save the real size
base_head->size = (tb_uint32_t)size;
#ifdef __tb_debug__
base_head->debug.magic = TB_POOL_DATA_MAGIC;
base_head->debug.file = file_;
base_head->debug.func = func_;
base_head->debug.line = (tb_uint16_t)line_;
// save backtrace
tb_pool_data_save_backtrace(&base_head->debug, 5);
// make the dirty data and patch 0xcc for checking underflow
tb_memset_(data_real, TB_POOL_DATA_PATCH, size + patch);
// save allocator reference for checking data range
data_head->allocator = (tb_pointer_t)allocator;
#endif
// save the data to the data_list
tb_list_entry_insert_tail(&allocator->data_list, &data_head->entry);
// save the real size
if (real) *real = size;
#ifdef __tb_debug__
// update the real size
allocator->real_size += size;
// update the occupied size
allocator->occupied_size += need - TB_POOL_DATA_HEAD_DIFF_SIZE - patch;
// update the total size
allocator->total_size += size;
// update the peak size
if (allocator->total_size > allocator->peak_size) allocator->peak_size = allocator->total_size;
// update the malloc count
allocator->malloc_count++;
#endif
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit the data
if (data) tb_native_memory_free(data);
data = tb_null;
data_real = tb_null;
}
// ok?
return (tb_pointer_t)data_real;
}
static tb_pointer_t tb_native_large_allocator_ralloc(tb_allocator_ref_t self, tb_pointer_t data, tb_size_t size, tb_size_t* real __tb_debug_decl__)
{
// check
tb_native_large_allocator_ref_t allocator = (tb_native_large_allocator_ref_t)self;
tb_assert_and_check_return_val(allocator, tb_null);
// done
#ifdef __tb_debug__
tb_size_t patch = 1; // patch 0xcc
#else
tb_size_t patch = 0;
#endif
tb_bool_t ok = tb_false;
tb_bool_t removed = tb_false;
tb_size_t need = sizeof(tb_native_large_data_head_t) + size + patch;
tb_byte_t* data_real = tb_null;
tb_native_large_data_head_t* data_head = tb_null;
do
{
// the data head
data_head = &(((tb_native_large_data_head_t*)data)[-1]);
// the base head
tb_pool_data_head_t* base_head = tb_native_large_allocator_data_base(data_head);
// check
tb_assertf(base_head->debug.magic != (tb_uint16_t)~TB_POOL_DATA_MAGIC, "ralloc freed data: %p", data);
tb_assertf(base_head->debug.magic == TB_POOL_DATA_MAGIC, "ralloc invalid data: %p", data);
tb_assertf(data_head->allocator == (tb_pointer_t)allocator, "the data: %p not belong to allocator: %p", data, allocator);
tb_assertf(((tb_byte_t*)data)[base_head->size] == TB_POOL_DATA_PATCH, "data underflow");
#ifdef __tb_debug__
// check the last data
tb_native_large_allocator_check_last(allocator);
// check the prev data
tb_native_large_allocator_check_prev(allocator, data_head);
// check the next data
tb_native_large_allocator_check_next(allocator, data_head);
// update the real size
allocator->real_size -= base_head->size;
// update the occupied size
allocator->occupied_size -= base_head->size;
// update the total size
allocator->total_size -= base_head->size;
// the previous size
tb_size_t prev_size = base_head->size;
#endif
// remove the data from the data_list
tb_list_entry_remove(&allocator->data_list, &data_head->entry);
removed = tb_true;
// ralloc data
if (size >= TB_VIRTUAL_MEMORY_DATA_MINN)
{
if (base_head->size >= TB_VIRTUAL_MEMORY_DATA_MINN)
data = (tb_byte_t*)tb_virtual_memory_ralloc(data_head, need);
else
{
data = (tb_byte_t*)tb_virtual_memory_malloc(need);
if (data)
{
tb_memcpy_(data, data_head, base_head->size);
tb_native_memory_free(data_head);
}
}
}
else
{
if (base_head->size < TB_VIRTUAL_MEMORY_DATA_MINN)
data = (tb_byte_t*)tb_native_memory_ralloc(data_head, need);
else
{
data = (tb_byte_t*)tb_native_memory_malloc(need);
if (data)
{
tb_memcpy_(data, data_head, base_head->size);
tb_virtual_memory_free(data_head);
}
}
}
tb_assert_and_check_break(data);
tb_assert_and_check_break(!(((tb_size_t)data) & 0x1));
// update the real data
data_real = (tb_byte_t*)data + sizeof(tb_native_large_data_head_t);
// update the data head
data_head = (tb_native_large_data_head_t*)data;
// update the base head
base_head = tb_native_large_allocator_data_base(data_head);
// save the real size
base_head->size = (tb_uint32_t)size;
#ifdef __tb_debug__
base_head->debug.file = file_;
base_head->debug.func = func_;
base_head->debug.line = (tb_uint16_t)line_;
// check
tb_assertf(base_head->debug.magic == TB_POOL_DATA_MAGIC, "ralloc data have been changed: %p", data);
// update backtrace
tb_pool_data_save_backtrace(&base_head->debug, 5);
// make the dirty data
if (size > prev_size) tb_memset_(data_real + prev_size, TB_POOL_DATA_PATCH, size - prev_size);
// patch 0xcc for checking underflow
data_real[size] = TB_POOL_DATA_PATCH;
#endif
// save the data to the data_list
tb_list_entry_insert_tail(&allocator->data_list, &data_head->entry);
removed = tb_false;
// save the real size
if (real) *real = size;
#ifdef __tb_debug__
// update the real size
allocator->real_size += size;
// update the occupied size
allocator->occupied_size += size;
// update the total size
allocator->total_size += size;
// update the peak size
if (allocator->total_size > allocator->peak_size) allocator->peak_size = allocator->total_size;
// update the ralloc count
allocator->ralloc_count++;
#endif
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// restore data to data_list
if (data_head && removed) tb_list_entry_insert_tail(&allocator->data_list, &data_head->entry);
// clear it
data = tb_null;
data_real = tb_null;
}
// ok?
return (tb_pointer_t)data_real;
}
static tb_bool_t tb_native_large_allocator_free(tb_allocator_ref_t self, tb_pointer_t data __tb_debug_decl__)
{
// check
tb_native_large_allocator_ref_t allocator = (tb_native_large_allocator_ref_t)self;
tb_assert_and_check_return_val(allocator && data, tb_false);
// done
tb_bool_t ok = tb_false;
tb_native_large_data_head_t* data_head = tb_null;
do
{
// the data head
data_head = &(((tb_native_large_data_head_t*)data)[-1]);
// the base head
tb_pool_data_head_t* base_head = tb_native_large_allocator_data_base(data_head);
// check
tb_assertf(base_head->debug.magic != (tb_uint16_t)~TB_POOL_DATA_MAGIC, "double free data: %p", data);
tb_assertf(base_head->debug.magic == TB_POOL_DATA_MAGIC, "free invalid data: %p", data);
tb_assertf(data_head->allocator == (tb_pointer_t)allocator, "the data: %p not belong to allocator: %p", data, allocator);
tb_assertf(((tb_byte_t*)data)[base_head->size] == TB_POOL_DATA_PATCH, "data underflow");
#ifdef __tb_debug__
// check the last data
tb_native_large_allocator_check_last(allocator);
// check the prev data
tb_native_large_allocator_check_prev(allocator, data_head);
// check the next data
tb_native_large_allocator_check_next(allocator, data_head);
// for checking double-free
base_head->debug.magic = (tb_uint16_t)~TB_POOL_DATA_MAGIC;
// update the total size
allocator->total_size -= base_head->size;
// update the free count
allocator->free_count++;
#endif
// remove the data from the data_list
tb_list_entry_remove(&allocator->data_list, &data_head->entry);
// free it
if (base_head->size >= TB_VIRTUAL_MEMORY_DATA_MINN)
tb_virtual_memory_free(data_head);
else tb_native_memory_free(data_head);
// ok
ok = tb_true;
} while (0);
// ok?
return ok;
}
static tb_void_t tb_native_large_allocator_clear(tb_allocator_ref_t self)
{
// check
tb_native_large_allocator_ref_t allocator = (tb_native_large_allocator_ref_t)self;
tb_assert_and_check_return(allocator);
// done
do
{
// the iterator
tb_iterator_ref_t iterator = tb_list_entry_itor(&allocator->data_list);
tb_assert_and_check_break(iterator);
// walk it
tb_size_t itor = tb_iterator_head(iterator);
while (itor != tb_iterator_tail(iterator))
{
// the data head
tb_native_large_data_head_t* data_head = (tb_native_large_data_head_t*)tb_iterator_item(iterator, itor);
tb_assert_and_check_break(data_head);
// save next
tb_size_t next = tb_iterator_next(iterator, itor);
// exit data
tb_native_large_allocator_free(self, (tb_pointer_t)&data_head[1] __tb_debug_vals__);
// next
itor = next;
}
} while (0);
// clear info
#ifdef __tb_debug__
allocator->peak_size = 0;
allocator->total_size = 0;
allocator->real_size = 0;
allocator->occupied_size = 0;
allocator->malloc_count = 0;
allocator->ralloc_count = 0;
allocator->free_count = 0;
#endif
}
static tb_void_t tb_native_large_allocator_exit(tb_allocator_ref_t self)
{
// check
tb_native_large_allocator_ref_t allocator = (tb_native_large_allocator_ref_t)self;
tb_assert_and_check_return(allocator);
// exit lock
tb_spinlock_exit(&allocator->base.lock);
// exit it
tb_native_memory_free(allocator);
}
#ifdef __tb_debug__
static tb_void_t tb_native_large_allocator_dump(tb_allocator_ref_t self)
{
// check
tb_native_large_allocator_ref_t allocator = (tb_native_large_allocator_ref_t)self;
tb_assert_and_check_return(allocator);
// trace
tb_trace_i("");
// exit all data_list
tb_for_all_if (tb_native_large_data_head_t*, data_head, tb_list_entry_itor(&allocator->data_list), data_head)
{
// check it
tb_native_large_allocator_check_data(allocator, data_head);
// trace
tb_trace_e("leak: %p", &data_head[1]);
// dump data
tb_pool_data_dump((tb_byte_t const*)&data_head[1], tb_false, "[native_large_allocator]: [error]: ");
}
// trace debug info
tb_trace_i("peak_size: %lu", allocator->peak_size);
tb_trace_i("wast_rate: %llu/10000", allocator->occupied_size? (((tb_hize_t)allocator->occupied_size - allocator->real_size) * 10000) / (tb_hize_t)allocator->occupied_size : 0);
tb_trace_i("free_count: %lu", allocator->free_count);
tb_trace_i("malloc_count: %lu", allocator->malloc_count);
tb_trace_i("ralloc_count: %lu", allocator->ralloc_count);
}
static tb_bool_t tb_native_large_allocator_have(tb_allocator_ref_t self, tb_cpointer_t data)
{
// check
tb_native_large_allocator_ref_t allocator = (tb_native_large_allocator_ref_t)self;
tb_assert_and_check_return_val(allocator, tb_false);
/* always ok for checking memory
*
* TODO: need better implementation for distinguishing it
*/
return tb_true;
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_allocator_ref_t tb_native_large_allocator_init()
{
// done
tb_bool_t ok = tb_false;
tb_native_large_allocator_ref_t allocator = tb_null;
do
{
// check
tb_assert_static(!(sizeof(tb_native_large_data_head_t) & (TB_POOL_DATA_ALIGN - 1)));
// make allocator
allocator = (tb_native_large_allocator_ref_t)tb_native_memory_malloc0(sizeof(tb_native_large_allocator_t));
tb_assert_and_check_break(allocator);
// init base
allocator->base.type = TB_ALLOCATOR_TYPE_LARGE;
allocator->base.flag = TB_ALLOCATOR_FLAG_NONE;
allocator->base.large_malloc = tb_native_large_allocator_malloc;
allocator->base.large_ralloc = tb_native_large_allocator_ralloc;
allocator->base.large_free = tb_native_large_allocator_free;
allocator->base.clear = tb_native_large_allocator_clear;
allocator->base.exit = tb_native_large_allocator_exit;
#ifdef __tb_debug__
allocator->base.dump = tb_native_large_allocator_dump;
allocator->base.have = tb_native_large_allocator_have;
#endif
// init lock
if (!tb_spinlock_init(&allocator->base.lock)) break;
// init data_list
tb_list_entry_init(&allocator->data_list, tb_native_large_data_head_t, entry, tb_null);
// register lock profiler
#ifdef TB_LOCK_PROFILER_ENABLE
tb_lock_profiler_register(tb_lock_profiler(), (tb_pointer_t)&allocator->base.lock, TB_TRACE_MODULE_NAME);
#endif
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (allocator) tb_native_large_allocator_exit((tb_allocator_ref_t)allocator);
allocator = tb_null;
}
// ok?
return (tb_allocator_ref_t)allocator;
}
tbox-1.7.6/src/tbox/memory/impl/native_large_allocator.h 0000664 0000000 0000000 00000002754 14671175054 0023410 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file native_large_allocator.h
*
*/
#ifndef TB_MEMORY_IMPL_NATIVE_LARGE_ALLOCATOR_H
#define TB_MEMORY_IMPL_NATIVE_LARGE_ALLOCATOR_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* init the native large allocator and the allocated data will be aligned by the page size
*
* @return the allocator
*/
tb_allocator_ref_t tb_native_large_allocator_init(tb_noarg_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/memory/impl/prefix.c 0000664 0000000 0000000 00000013223 14671175054 0020171 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../../tbox.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#ifdef __tb_debug__
__tb_no_sanitize_address__ tb_size_t tb_pool_data_size(tb_cpointer_t data)
{
// check
tb_check_return_val(data, 0);
// done
tb_size_t size = 0;
tb_pool_data_head_t* data_head = tb_null;
do
{
// tbox must be running normally
tb_check_break(tb_state() == TB_STATE_OK);
// get global allocator
tb_allocator_ref_t allocator = tb_allocator();
tb_check_break(allocator);
// have this data address?
tb_check_break(tb_allocator_have(allocator, data));
// the data head
data_head = &(((tb_pool_data_head_t*)data)[-1]);
tb_check_break(data_head->debug.magic == TB_POOL_DATA_MAGIC);
// ok
size = data_head->size;
} while (0);
// ok?
return size;
}
tb_void_t tb_pool_data_dump(tb_cpointer_t data, tb_bool_t verbose, tb_char_t const* prefix)
{
// done
tb_pool_data_head_t* data_head = tb_null;
do
{
// no data?
tb_assert_and_check_break(data);
// the data head
data_head = &(((tb_pool_data_head_t*)data)[-1]);
// dump the head info
tb_size_t data_limit = 256;
if (data_head->debug.magic == TB_POOL_DATA_MAGIC)
{
// the data size
tb_size_t data_size = (tb_size_t)data_head->size;
// format the backtrace prefix
tb_char_t backtrace_prefix[256] = {0};
tb_snprintf(backtrace_prefix, sizeof(backtrace_prefix), "%s ", prefix? prefix : "");
// dump backtrace
tb_size_t nframe = 0;
while (nframe < tb_arrayn(data_head->debug.backtrace) && data_head->debug.backtrace[nframe]) nframe++;
tb_trace_i("%sdata: from: %s(): %u, %s", prefix? prefix : "", data_head->debug.func, data_head->debug.line, data_head->debug.file);
tb_backtrace_dump(backtrace_prefix, data_head->debug.backtrace, nframe);
// dump the data info
tb_trace_i("%sdata: %p, size: %lu, patch: %x", prefix? prefix : "", data, data_size, ((tb_byte_t const*)data)[data_size]);
// dump the first 256-bytes data
if (data_size && verbose)
{
// the dump size
tb_size_t dump_size = tb_min(data_size, data_limit);
// dump it
tb_trace_i("%sdata: first %lu-bytes:", prefix? prefix : "", dump_size);
tb_dump_data((tb_byte_t const*)data, dump_size);
// dump the last 256-bytes data
if (data_size > dump_size)
{
// the last data
tb_byte_t const* data_last = tb_max((tb_byte_t const*)data + data_size - data_limit, (tb_byte_t const*)data + dump_size);
// update the dump size
dump_size = (tb_byte_t const*)data + data_size - data_last;
// dump it
tb_trace_i("%sdata: last %lu-bytes:", prefix? prefix : "", dump_size);
tb_dump_data(data_last, dump_size);
}
}
}
// for the public fixed_pool
else if (data_head->debug.magic == TB_POOL_DATA_EMPTY_MAGIC)
{
// format the backtrace prefix
tb_char_t backtrace_prefix[256] = {0};
tb_snprintf(backtrace_prefix, sizeof(backtrace_prefix), "%s ", prefix? prefix : "");
// dump backtrace
tb_size_t nframe = 0;
while (nframe < tb_arrayn(data_head->debug.backtrace) && data_head->debug.backtrace[nframe]) nframe++;
tb_trace_i("%sdata: from: %s(): %u, %s", prefix? prefix : "", data_head->debug.func, data_head->debug.line, data_head->debug.file);
tb_backtrace_dump(backtrace_prefix, data_head->debug.backtrace, nframe);
// dump the data info
tb_trace_i("%sdata: %p, size: fixed", prefix? prefix : "", data);
}
else
{
// dump the data head
tb_trace_i("%sdata: invalid head:", prefix? prefix : "");
tb_dump_data((tb_byte_t const*)data_head, sizeof(tb_pool_data_head_t));
// dump the first 256-bytes data
tb_trace_i("%sdata: first %lu-bytes:", prefix? prefix : "", data_limit);
tb_dump_data((tb_byte_t const*)data, data_limit);
}
} while (0);
}
tb_void_t tb_pool_data_save_backtrace(tb_pool_data_debug_head_t* debug_head, tb_size_t skip_frames)
{
tb_size_t nframe = tb_backtrace_frames(debug_head->backtrace, tb_arrayn(debug_head->backtrace), skip_frames + 2);
if (nframe < tb_arrayn(debug_head->backtrace)) tb_memset_(debug_head->backtrace + nframe, 0, (tb_arrayn(debug_head->backtrace) - nframe) * sizeof(tb_cpointer_t));
}
#endif
tbox-1.7.6/src/tbox/memory/impl/prefix.h 0000664 0000000 0000000 00000010212 14671175054 0020171 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_MEMORY_IMPL_PREFIX_H
#define TB_MEMORY_IMPL_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#include "../allocator.h"
#include "../large_allocator.h"
#include "../../libc/libc.h"
#include "../../math/math.h"
#include "../../utils/utils.h"
#include "../../platform/platform.h"
#include "../../container/container.h"
#include "../../algorithm/algorithm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the pool data magic number
#define TB_POOL_DATA_MAGIC (0xdead)
// the pool data empty magic number
#define TB_POOL_DATA_EMPTY_MAGIC (0xdeaf)
// the pool data patch value
#define TB_POOL_DATA_PATCH (0xcc)
// the pool data size maximum
#define TB_POOL_DATA_SIZE_MAXN (TB_MAXU32)
// the pool data address alignment
#define TB_POOL_DATA_ALIGN TB_CPU_BITBYTE
// the pool data alignment keyword
#define __tb_pool_data_aligned__ __tb_cpu_aligned__
// the pool data head different size for computing the wasted space size
#ifdef __tb_debug__
# define TB_POOL_DATA_HEAD_DIFF_SIZE (sizeof(tb_pool_data_head_t) - sizeof(tb_uint32_t))
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
#ifdef __tb_debug__
// the pool data debug head type
typedef __tb_pool_data_aligned__ struct __tb_pool_data_debug_head_t
{
// the file
tb_char_t const* file;
// the func
tb_char_t const* func;
// the backtrace frames
tb_pointer_t backtrace[16];
// the line
tb_uint16_t line;
/* the magic
*
* @note the address may be not accessed if we place the magic to head.
*/
tb_uint16_t magic;
}__tb_pool_data_aligned__ tb_pool_data_debug_head_t;
#endif
// the pool data head type
typedef struct __tb_pool_data_head_t
{
#ifdef __tb_debug__
// the debug head
tb_pool_data_debug_head_t debug;
#endif
// the size
tb_size_t size;
}tb_pool_data_head_t;
// the pool data empty head type
typedef struct __tb_pool_data_empty_head_t
{
#ifdef __tb_debug__
// the debug head
tb_pool_data_debug_head_t debug;
#endif
}tb_pool_data_empty_head_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
#ifdef __tb_debug__
/* the data size
*
* @param data the data address
*
* @return the data size
*/
tb_size_t tb_pool_data_size(tb_cpointer_t data);
/* dump data info
*
* @param data the data address
* @param verbose dump verbose info?
* @param prefix the prefix info
*/
tb_void_t tb_pool_data_dump(tb_cpointer_t data, tb_bool_t verbose, tb_char_t const* prefix);
/* save backtrace
*
* @param data_head the data head
* @param skip_frames the skiped frame count
*/
tb_void_t tb_pool_data_save_backtrace(tb_pool_data_debug_head_t* debug_head, tb_size_t skip_frames);
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/memory/impl/static_fixed_pool.c 0000664 0000000 0000000 00000057172 14671175054 0022406 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file static_fixed_pool.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "static_fixed_pool"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "static_fixed_pool.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_WORDS_BIGENDIAN
// allocate the index
# define tb_static_fixed_pool_used_set1(used, i) do {(used)[(i) >> 3] |= (0x1 << (7 - ((i) & 7)));} while (0)
// free the index
# define tb_static_fixed_pool_used_set0(used, i) do {(used)[(i) >> 3] &= ~(0x1 << (7 - ((i) & 7)));} while (0)
// the index have been allocated?
# define tb_static_fixed_pool_used_bset(used, i) ((used)[(i) >> 3] & (0x1 << (7 - ((i) & 7))))
// find the first free index
# define tb_static_fixed_pool_find_free(v) tb_bits_fb0_be(v)
#else
// allocate the index
# define tb_static_fixed_pool_used_set1(used, i) do {(used)[(i) >> 3] |= (0x1 << ((i) & 7));} while (0)
// free the index
# define tb_static_fixed_pool_used_set0(used, i) do {(used)[(i) >> 3] &= ~(0x1 << ((i) & 7));} while (0)
// the index have been allocated?
# define tb_static_fixed_pool_used_bset(used, i) ((used)[(i) >> 3] & (0x1 << ((i) & 7)))
// find the first free index
# define tb_static_fixed_pool_find_free(v) tb_bits_fb0_le(v)
#endif
// cache the predicted index
#define tb_static_fixed_pool_cache_pred(pool, i) do { (pool)->pred_index = ((i) >> TB_CPU_SHIFT) + 1; } while (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the static fixed pool type
typedef __tb_pool_data_aligned__ struct __tb_static_fixed_pool_t
{
// the real data address after the used_info info
tb_byte_t* data;
// the data tail
tb_byte_t* tail;
// the used info
tb_byte_t* used_info;
// the used info size
tb_size_t info_size;
// the predict index
tb_size_t pred_index;
// the item size
tb_size_t item_size;
// the item space: head + item_size
tb_size_t item_space;
// the item count
tb_size_t item_count;
// the item maximum count
tb_size_t item_maxn;
// the data head size
tb_uint16_t data_head_size;
// for small allocator?
tb_uint16_t for_small;
#ifdef __tb_debug__
// the peak size
tb_size_t peak_size;
// the total size
tb_size_t total_size;
// the real size
tb_size_t real_size;
// the occupied size
tb_size_t occupied_size;
// the malloc count
tb_size_t malloc_count;
// the free count
tb_size_t free_count;
// the predict failed count
tb_size_t pred_failed;
#endif
}__tb_pool_data_aligned__ tb_static_fixed_pool_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_pool_data_empty_head_t* tb_static_fixed_pool_malloc_pred(tb_static_fixed_pool_t* pool)
{
// check
tb_assert_and_check_return_val(pool, tb_null);
// done
tb_pool_data_empty_head_t* data_head = tb_null;
do
{
// exists the predict index?
tb_check_break(pool->pred_index);
// the predict index
tb_size_t pred_index = pool->pred_index - 1;
tb_assert((pred_index << TB_CPU_SHIFT) < pool->item_maxn);
// the predict data
tb_size_t* data = (tb_size_t*)pool->used_info + pred_index;
// full?
tb_check_break((*data) + 1);
// the free bit index
tb_size_t index = (pred_index << TB_CPU_SHIFT) + tb_static_fixed_pool_find_free(*data);
// out of range?
if (index >= pool->item_maxn)
{
// clear the pred index
pool->pred_index = 0;
break;
}
// check
tb_assert(!tb_static_fixed_pool_used_bset(pool->used_info, index));
// the data head
data_head = (tb_pool_data_empty_head_t*)(pool->data + index * pool->item_space);
// allocate it
tb_static_fixed_pool_used_set1(pool->used_info, index);
// the predict data is full
if (!((*data) + 1))
{
// clear the predict index
pool->pred_index = 0;
// predict the next index
if (index + 1 < pool->item_maxn && !tb_static_fixed_pool_used_bset(pool->used_info, index + 1))
tb_static_fixed_pool_cache_pred(pool, index + 1);
}
} while (0);
#ifdef __tb_debug__
// update the predict failed count
if (!data_head) pool->pred_failed++;
#endif
// ok?
return data_head;
}
#if 1
static tb_pool_data_empty_head_t* tb_static_fixed_pool_malloc_find(tb_static_fixed_pool_t* pool)
{
// check
tb_assert_and_check_return_val(pool, tb_null);
// init
tb_size_t i = 0;
tb_size_t* p = (tb_size_t*)pool->used_info;
tb_size_t* e = (tb_size_t*)(pool->used_info + pool->info_size);
tb_byte_t* d = tb_null;
// check align
tb_assert_and_check_return_val(!(((tb_size_t)p) & (TB_CPU_BITBYTE - 1)), tb_null);
// find the free chunk, item_space * 32|64 items
#ifdef __tb_small__
// while (p < e && *p == 0xffffffff) p++;
// while (p < e && *p == 0xffffffffffffffffL) p++;
while (p < e && !((*p) + 1)) p++;
#else
while (p + 7 < e)
{
if (p[0] + 1) { p += 0; break; }
if (p[1] + 1) { p += 1; break; }
if (p[2] + 1) { p += 2; break; }
if (p[3] + 1) { p += 3; break; }
if (p[4] + 1) { p += 4; break; }
if (p[5] + 1) { p += 5; break; }
if (p[6] + 1) { p += 6; break; }
if (p[7] + 1) { p += 7; break; }
p += 8;
}
while (p < e && !(*p + 1)) p++;
#endif
tb_check_return_val(p < e, tb_null);
// find the free bit index
tb_size_t m = pool->item_maxn;
i = (((tb_byte_t*)p - pool->used_info) << 3) + tb_static_fixed_pool_find_free(*p);
tb_check_return_val(i < m, tb_null);
// allocate it
d = pool->data + i * pool->item_space;
tb_static_fixed_pool_used_set1(pool->used_info, i);
// predict this index if no full?
if ((*p) + 1) tb_static_fixed_pool_cache_pred(pool, i);
// ok?
return (tb_pool_data_empty_head_t*)d;
}
#else
static tb_pool_data_empty_head_t* tb_static_fixed_pool_malloc_find(tb_static_fixed_pool_t* pool)
{
// check
tb_assert_and_check_return_val(pool, tb_null);
// done
tb_size_t i = 0;
tb_size_t m = pool->item_maxn;
tb_byte_t* p = pool->used_info;
tb_byte_t u = *p;
tb_byte_t b = 0;
tb_byte_t* d = tb_null;
for (i = 0; i < m; ++i)
{
// bit
b = i & 0x07;
// u++
if (!b)
{
u = *p++;
// skip the non-free byte
//if (u == 0xff)
if (!(u + 1))
{
i += 7;
continue ;
}
}
// is free?
// if (!tb_static_fixed_pool_used_bset(pool->used_info, i))
if (!(u & (0x01 << b)))
{
// ok
d = pool->data + i * pool->item_space;
// tb_static_fixed_pool_used_set1(pool->used_info, i);
*(p - 1) |= (0x01 << b);
// predict the next block
if (i + 1 < m && !tb_static_fixed_pool_used_bset(pool->used_info, i + 1))
tb_static_fixed_pool_cache_pred(pool, i + 1);
break;
}
}
// ok?
return (tb_pool_data_empty_head_t*)d;
}
#endif
#ifdef __tb_debug__
static tb_void_t tb_static_fixed_pool_check_data(tb_static_fixed_pool_t* pool, tb_pool_data_empty_head_t const* data_head)
{
// check
tb_assert_and_check_return(pool && data_head);
// done
tb_bool_t ok = tb_false;
tb_byte_t const* data = (tb_byte_t const*)data_head + pool->data_head_size;
do
{
// the index
tb_size_t index = ((tb_byte_t*)data_head - pool->data) / pool->item_space;
// check
tb_assertf_pass_break(!(((tb_byte_t*)data_head - pool->data) % pool->item_space), "the invalid data: %p", data);
tb_assertf_pass_break(tb_static_fixed_pool_used_bset(pool->used_info, index), "data have been freed: %p", data);
tb_assertf_pass_break(data_head->debug.magic == (pool->for_small? TB_POOL_DATA_MAGIC : TB_POOL_DATA_EMPTY_MAGIC), "the invalid data: %p", data);
tb_assertf_pass_break(((tb_byte_t*)data)[pool->item_size] == TB_POOL_DATA_PATCH, "data underflow");
// ok
ok = tb_true;
} while (0);
// failed? dump it
if (!ok)
{
// dump data
tb_pool_data_dump(data, tb_true, "[static_fixed_pool]: [error]: ");
// abort
tb_abort();
}
}
static tb_void_t tb_static_fixed_pool_check_next(tb_static_fixed_pool_t* pool, tb_pool_data_empty_head_t const* data_head)
{
// check
tb_assert_and_check_return(pool && data_head);
// the index
tb_size_t index = ((tb_byte_t*)data_head - pool->data) / pool->item_space;
// check the next data
if (index + 1 < pool->item_maxn && tb_static_fixed_pool_used_bset(pool->used_info, index + 1))
tb_static_fixed_pool_check_data(pool, (tb_pool_data_empty_head_t*)((tb_byte_t*)data_head + pool->item_space));
}
static tb_void_t tb_static_fixed_pool_check_prev(tb_static_fixed_pool_t* pool, tb_pool_data_empty_head_t const* data_head)
{
// check
tb_assert_and_check_return(pool && data_head);
// the index
tb_size_t index = ((tb_byte_t*)data_head - pool->data) / pool->item_space;
// check the prev data
if (index && tb_static_fixed_pool_used_bset(pool->used_info, index - 1))
tb_static_fixed_pool_check_data(pool, (tb_pool_data_empty_head_t*)((tb_byte_t*)data_head - pool->item_space));
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_static_fixed_pool_ref_t tb_static_fixed_pool_init(tb_byte_t* data, tb_size_t size, tb_size_t item_size, tb_bool_t for_small)
{
// check
tb_assert_and_check_return_val(data && size && item_size, tb_null);
// align data and size
tb_size_t diff = tb_align((tb_size_t)data, TB_POOL_DATA_ALIGN) - (tb_size_t)data;
tb_assert_and_check_return_val(size > diff + sizeof(tb_static_fixed_pool_t), tb_null);
size -= diff;
data += diff;
// init pool
tb_static_fixed_pool_t* pool = (tb_static_fixed_pool_t*)data;
tb_memset_(pool, 0, sizeof(tb_static_fixed_pool_t));
// for small allocator?
pool->for_small = !!for_small;
pool->data_head_size = for_small? sizeof(tb_pool_data_head_t) : sizeof(tb_pool_data_empty_head_t);
#ifndef __tb_debug__
// fix data alignment, because sizeof(tb_pool_data_empty_head_t) == 1 now.
if (!for_small) pool->data_head_size = 0;
#endif
tb_assert_and_check_return_val(!(pool->data_head_size & (TB_POOL_DATA_ALIGN - 1)), tb_null);
#ifdef __tb_debug__
// init patch for checking underflow
tb_size_t patch = 1;
#else
tb_size_t patch = 0;
#endif
// init the item space
pool->item_space = pool->data_head_size + item_size + patch;
pool->item_space = tb_align(pool->item_space, TB_POOL_DATA_ALIGN);
tb_assert_and_check_return_val(pool->item_space > pool->data_head_size, tb_null);
// init the used info
pool->used_info = (tb_byte_t*)tb_align((tb_size_t)&pool[1], TB_POOL_DATA_ALIGN);
tb_assert_and_check_return_val(data + size > pool->used_info, tb_null);
/* init the item maxn
*
* used_info + maxn * item_space < left
* align8(maxn) / 8 + maxn * item_space < left
* (maxn + 7) / 8 + maxn * item_space < left
* (maxn / 8) + (7 / 8) + maxn * item_space < left
* maxn * (1 / 8 + item_space) < left - (7 / 8)
* maxn < (left - (7 / 8)) / (1 / 8 + item_space)
* maxn < (left * 8 - 7) / (1 + item_space * 8)
*/
pool->item_maxn = (((data + size - pool->used_info) << 3) - 7) / (1 + (pool->item_space << 3));
tb_assert_and_check_return_val(pool->item_maxn, tb_null);
// init the used info size
pool->info_size = tb_align(pool->item_maxn, TB_CPU_BITSIZE) >> 3;
tb_assert_and_check_return_val(pool->info_size && !(pool->info_size & (TB_CPU_BITBYTE - 1)), tb_null);
// clear the used info
tb_memset_(pool->used_info, 0, pool->info_size);
// init data
pool->data = (tb_byte_t*)tb_align((tb_size_t)pool->used_info + pool->info_size, TB_POOL_DATA_ALIGN);
tb_assert_and_check_return_val(data + size > pool->data, tb_null);
tb_assert_and_check_return_val(pool->item_maxn * pool->item_space <= (tb_size_t)(data + size - pool->data + 1), tb_null);
// init data tail
pool->tail = pool->data + pool->item_maxn * pool->item_space;
// init the item size
pool->item_size = item_size;
// init the item count
pool->item_count = 0;
// init the predict index
pool->pred_index = 1;
// trace
tb_trace_d("init: data: %p, size: %lu, head_size: %lu, item_size: %lu, item_maxn: %lu, item_space: %lu", pool->data, size, pool->data - (tb_byte_t*)pool, item_size, pool->item_maxn, pool->item_space);
// ok
return (tb_static_fixed_pool_ref_t)pool;
}
tb_void_t tb_static_fixed_pool_exit(tb_static_fixed_pool_ref_t self)
{
// check
tb_static_fixed_pool_t* pool = (tb_static_fixed_pool_t*)self;
tb_assert_and_check_return(pool);
// clear it
tb_static_fixed_pool_clear(self);
// exit it
tb_memset_(pool, 0, sizeof(tb_static_fixed_pool_t));
}
tb_size_t tb_static_fixed_pool_size(tb_static_fixed_pool_ref_t self)
{
// check
tb_static_fixed_pool_t* pool = (tb_static_fixed_pool_t*)self;
tb_assert_and_check_return_val(pool, 0);
// the item count
return pool->item_count;
}
tb_size_t tb_static_fixed_pool_maxn(tb_static_fixed_pool_ref_t self)
{
// check
tb_static_fixed_pool_t* pool = (tb_static_fixed_pool_t*)self;
tb_assert_and_check_return_val(pool, 0);
// the item maximum count
return pool->item_maxn;
}
tb_bool_t tb_static_fixed_pool_full(tb_static_fixed_pool_ref_t self)
{
// check
tb_static_fixed_pool_t* pool = (tb_static_fixed_pool_t*)self;
tb_assert_and_check_return_val(pool, 0);
// full?
return pool->item_count == pool->item_maxn? tb_true : tb_false;
}
tb_bool_t tb_static_fixed_pool_null(tb_static_fixed_pool_ref_t self)
{
// check
tb_static_fixed_pool_t* pool = (tb_static_fixed_pool_t*)self;
tb_assert_and_check_return_val(pool, 0);
// null?
return !pool->item_count? tb_true : tb_false;
}
tb_void_t tb_static_fixed_pool_clear(tb_static_fixed_pool_ref_t self)
{
// check
tb_static_fixed_pool_t* pool = (tb_static_fixed_pool_t*)self;
tb_assert_and_check_return(pool);
// clear used_info
if (pool->used_info) tb_memset_(pool->used_info, 0, pool->info_size);
// clear size
pool->item_count = 0;
// init the predict index
pool->pred_index = 1;
// clear info
#ifdef __tb_debug__
pool->peak_size = 0;
pool->total_size = 0;
pool->real_size = 0;
pool->occupied_size = 0;
pool->malloc_count = 0;
pool->free_count = 0;
pool->pred_failed = 0;
#endif
}
tb_pointer_t tb_static_fixed_pool_malloc(tb_static_fixed_pool_ref_t self __tb_debug_decl__)
{
// check
tb_static_fixed_pool_t* pool = (tb_static_fixed_pool_t*)self;
tb_assert_and_check_return_val(pool && pool->item_space, tb_null);
// done
tb_pointer_t data = tb_null;
tb_pool_data_empty_head_t* data_head = tb_null;
do
{
// full?
tb_check_break(pool->item_count < pool->item_maxn);
// predict it?
data_head = tb_static_fixed_pool_malloc_pred(pool);
// find it
if (!data_head) data_head = tb_static_fixed_pool_malloc_find(pool);
tb_check_break(data_head);
// the real data
data = (tb_byte_t*)data_head + pool->data_head_size;
// save the real size
if (pool->for_small) ((tb_pool_data_head_t*)data_head)->size = pool->item_size;
// count++
pool->item_count++;
#ifdef __tb_debug__
// init the debug info
data_head->debug.magic = pool->for_small? TB_POOL_DATA_MAGIC : TB_POOL_DATA_EMPTY_MAGIC;
data_head->debug.file = file_;
data_head->debug.func = func_;
data_head->debug.line = (tb_uint16_t)line_;
// save backtrace
tb_pool_data_save_backtrace(&data_head->debug, 6);
// make the dirty data and patch 0xcc for checking underflow
tb_memset_(data, TB_POOL_DATA_PATCH, pool->item_space - pool->data_head_size);
// update the real size
pool->real_size += pool->item_size;
// update the occupied size
pool->occupied_size += pool->item_space - TB_POOL_DATA_HEAD_DIFF_SIZE - 1;
// update the total size
pool->total_size += pool->item_size;
// update the peak size
if (pool->total_size > pool->peak_size) pool->peak_size = pool->total_size;
// update the malloc count
pool->malloc_count++;
// check the prev data
tb_static_fixed_pool_check_prev(pool, data_head);
// check the next data
tb_static_fixed_pool_check_next(pool, data_head);
#endif
} while (0);
// check
tb_assertf(data, "malloc(%lu) failed!", pool->item_size);
tb_assertf(!(((tb_size_t)data) & (TB_POOL_DATA_ALIGN - 1)), "malloc(%lu): unaligned data: %p", pool->item_size, data);
// ok?
return data;
}
tb_bool_t tb_static_fixed_pool_free(tb_static_fixed_pool_ref_t self, tb_pointer_t data __tb_debug_decl__)
{
// check
tb_static_fixed_pool_t* pool = (tb_static_fixed_pool_t*)self;
tb_assert_and_check_return_val(pool && pool->item_space, tb_false);
// done
tb_bool_t ok = tb_false;
tb_pool_data_empty_head_t* data_head = (tb_pool_data_empty_head_t*)((tb_byte_t*)data - pool->data_head_size);
do
{
// the index
tb_size_t index = ((tb_byte_t*)data_head - pool->data) / pool->item_space;
// check
tb_assertf_pass_and_check_break((tb_byte_t*)data_head >= pool->data && (tb_byte_t*)data_head + pool->item_space <= pool->tail, "the data: %p not belong to pool: %p", data, pool);
tb_assertf_pass_break(!(((tb_byte_t*)data_head - pool->data) % pool->item_space), "free the invalid data: %p", data);
tb_assertf_pass_and_check_break(pool->item_count, "double free data: %p", data);
tb_assertf_pass_and_check_break(tb_static_fixed_pool_used_bset(pool->used_info, index), "double free data: %p", data);
tb_assertf_pass_break(data_head->debug.magic == (pool->for_small? TB_POOL_DATA_MAGIC : TB_POOL_DATA_EMPTY_MAGIC), "the invalid data: %p", data);
tb_assertf_pass_break(((tb_byte_t*)data)[pool->item_size] == TB_POOL_DATA_PATCH, "data underflow");
#ifdef __tb_debug__
// check the prev data
tb_static_fixed_pool_check_prev(pool, data_head);
// check the next data
tb_static_fixed_pool_check_next(pool, data_head);
// update the total size
pool->total_size -= pool->item_size;
// update the free count
pool->free_count++;
#endif
// free it
tb_static_fixed_pool_used_set0(pool->used_info, index);
// predict it if no cache
if (!pool->pred_index) tb_static_fixed_pool_cache_pred(pool, index);
// size--
pool->item_count--;
// ok
ok = tb_true;
} while (0);
// failed? dump it
#ifdef __tb_debug__
if (!ok)
{
// trace
tb_trace_e("free(%p) failed! at %s(): %lu, %s", data, func_, line_, file_);
// dump data
tb_pool_data_dump((tb_byte_t const*)data, tb_true, "[static_fixed_pool]: [error]: ");
// abort
tb_abort();
}
#endif
// ok?
return ok;
}
tb_void_t tb_static_fixed_pool_walk(tb_static_fixed_pool_ref_t self, tb_fixed_pool_item_walk_func_t func, tb_cpointer_t priv)
{
// check
tb_static_fixed_pool_t* pool = (tb_static_fixed_pool_t*)self;
tb_assert_and_check_return(pool && pool->item_maxn && pool->item_space && func);
// walk
tb_size_t i = 0;
tb_size_t m = pool->item_maxn;
tb_byte_t* p = pool->used_info;
tb_byte_t* d = pool->data + pool->data_head_size;
tb_byte_t u = *p;
tb_byte_t b = 0;
for (i = 0; i < m; ++i)
{
// bit
b = i & 0x07;
// u++
if (!b)
{
u = *p++;
// this byte is all occupied?
//if (u == 0xff)
if (!(u + 1))
{
// done func
func(d + (i + 0) * pool->item_space, priv);
func(d + (i + 1) * pool->item_space, priv);
func(d + (i + 2) * pool->item_space, priv);
func(d + (i + 3) * pool->item_space, priv);
func(d + (i + 4) * pool->item_space, priv);
func(d + (i + 5) * pool->item_space, priv);
func(d + (i + 6) * pool->item_space, priv);
func(d + (i + 7) * pool->item_space, priv);
// skip this byte and continue it
i += 7;
continue ;
}
}
// is occupied?
// if (tb_static_fixed_pool_used_bset(pool->used_info, i))
if ((u & (0x01 << b)))
{
// done func
func(d + i * pool->item_space, priv);
}
}
}
#ifdef __tb_debug__
tb_void_t tb_static_fixed_pool_dump(tb_static_fixed_pool_ref_t self)
{
// check
tb_static_fixed_pool_t* pool = (tb_static_fixed_pool_t*)self;
tb_assert_and_check_return(pool && pool->used_info);
// dump
tb_size_t index = 0;
for (index = 0; index < pool->item_maxn; ++index)
{
// leak?
if (tb_static_fixed_pool_used_bset(pool->used_info, index))
{
// the data head
tb_pool_data_empty_head_t* data_head = (tb_pool_data_empty_head_t*)(pool->data + index * pool->item_space);
// check it
tb_static_fixed_pool_check_data(pool, data_head);
// the data
tb_byte_t const* data = (tb_byte_t const*)data_head + pool->data_head_size;
// trace
tb_trace_e("leak: %p", data);
// dump data
tb_pool_data_dump(data, tb_false, "[static_fixed_pool]: [error]: ");
}
}
// trace debug info
tb_trace_i("[%lu]: peak_size: %lu, wast_rate: %llu/10000, pred_failed: %lu, item_maxn: %lu, free_count: %lu, malloc_count: %lu"
, pool->item_size
, pool->peak_size
, pool->occupied_size? (((tb_hize_t)pool->occupied_size - pool->real_size) * 10000) / (tb_hize_t)pool->occupied_size : 0
, pool->pred_failed
, pool->item_maxn
, pool->free_count
, pool->malloc_count);
}
#endif
tbox-1.7.6/src/tbox/memory/impl/static_fixed_pool.h 0000664 0000000 0000000 00000010512 14671175054 0022376 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file static_fixed_pool.h
*
*/
#ifndef TB_MEMORY_IMPL_STATIC_FIXED_POOL_H
#define TB_MEMORY_IMPL_STATIC_FIXED_POOL_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../fixed_pool.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/*! the static fixed pool ref type
*
*
* ---------------------------------------------------------------------------
* | head | used | data |
* ---------------------------------------------------------------------------
* |
* pred
*
*/
typedef __tb_typeref__(static_fixed_pool);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init pool
*
* @param data the data address
* @param size the data size
* @param item_size the item size
* @param for_small add data size field at head for the small allocator
*
* @return the pool
*/
tb_static_fixed_pool_ref_t tb_static_fixed_pool_init(tb_byte_t* data, tb_size_t size, tb_size_t item_size, tb_bool_t for_small);
/*! exit pool
*
* @param pool the pool
*/
tb_void_t tb_static_fixed_pool_exit(tb_static_fixed_pool_ref_t pool);
/*! the item count
*
* @param pool the pool
*
* @return the item count
*/
tb_size_t tb_static_fixed_pool_size(tb_static_fixed_pool_ref_t pool);
/*! the item maximum count
*
* @param pool the pool
*
* @return the item maximum count
*/
tb_size_t tb_static_fixed_pool_maxn(tb_static_fixed_pool_ref_t pool);
/*! is full?
*
* @param pool the pool
*
* @return tb_true or tb_false
*/
tb_bool_t tb_static_fixed_pool_full(tb_static_fixed_pool_ref_t pool);
/*! is null?
*
* @param pool the pool
*
* @return tb_true or tb_false
*/
tb_bool_t tb_static_fixed_pool_null(tb_static_fixed_pool_ref_t pool);
/*! clear pool
*
* @param pool the pool
*/
tb_void_t tb_static_fixed_pool_clear(tb_static_fixed_pool_ref_t pool);
/*! malloc data
*
* @param pool the pool
*
* @return the data
*/
tb_pointer_t tb_static_fixed_pool_malloc(tb_static_fixed_pool_ref_t pool __tb_debug_decl__);
/*! free data
*
* @param pool the pool
* @param data the data
*
* @return tb_true or tb_false
*/
tb_bool_t tb_static_fixed_pool_free(tb_static_fixed_pool_ref_t pool, tb_pointer_t data __tb_debug_decl__);
/*! walk data
*
* @code
* tb_bool_t tb_static_fixed_pool_item_func(tb_pointer_t data, tb_cpointer_t priv)
* {
* // ok or break
* return tb_true;
* }
* @endcode
*
* @param pool the pool
* @param func the walk func
* @param priv the walk data
*
*/
tb_void_t tb_static_fixed_pool_walk(tb_static_fixed_pool_ref_t pool, tb_fixed_pool_item_walk_func_t func, tb_cpointer_t priv);
#ifdef __tb_debug__
/*! dump pool
*
* @param pool the pool
*/
tb_void_t tb_static_fixed_pool_dump(tb_static_fixed_pool_ref_t pool);
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/memory/impl/static_large_allocator.c 0000664 0000000 0000000 00000104531 14671175054 0023400 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file static_large_allocator.c
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "static_large_allocator"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "static_large_allocator.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the static large allocator data size
#define tb_static_large_allocator_data_base(data_head) (&(((tb_pool_data_head_t*)((tb_static_large_data_head_t*)(data_head) + 1))[-1]))
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the static large data head type
typedef __tb_pool_data_aligned__ struct __tb_static_large_data_head_t
{
// the data space size: the allocated size + left size
tb_uint32_t space : 31;
// is free?
tb_uint32_t bfree : 1;
/* patch 4 bytes for align(8) for tinycc/x86_64
*
* __tb_aligned__(8) struct doesn't seem to work
*/
#if defined(TB_COMPILER_IS_TINYC) && defined(TB_CPU_BIT64)
tb_uint32_t padding;
#endif
// the data head base
tb_byte_t base[sizeof(tb_pool_data_head_t)];
}__tb_pool_data_aligned__ tb_static_large_data_head_t;
// the static large data pred type
typedef struct __tb_static_large_data_pred_t
{
// the data head
tb_static_large_data_head_t* data_head;
#ifdef __tb_debug__
// the total count
tb_size_t total_count;
// the failed count
tb_size_t failed_count;
#endif
}tb_static_large_data_pred_t;
/*! the static large allocator type
*
*
*
* .e.g page_size == 4KB
*
* --------------------------------------------------------------------------
* | data |
* --------------------------------------------------------------------------
* |
* --------------------------------------------------------------------------
* | head | 4KB | 16KB | 8KB | 128KB | ... | 32KB | ... | 4KB*N |
* --------------------------------------------------------------------------
* | | |
* | `---------------`
* | merge free space when alloc or free
* |
* ------------------------------------------
* | tb_static_large_data_head_t | data space |
* ------------------------------------------
*
* --------------------------------------
* pred: | >0KB : 4KB | > 0*page | 1
* |-----------------------|--------------
* | >4KB : 8KB | > 1*page | 2
* |-----------------------|--------------
* | >8KB : 12-16KB | > 2*page | 3-4
* |-----------------------|--------------
* | >16KB : 20-32KB | > 4*page | 5-8
* |-----------------------|--------------
* | >32KB : 36-64KB | > 8*page | 9-16
* |-----------------------|--------------
* | >64KB : 68-128KB | > 16*page | 17-32
* |-----------------------|--------------
* | >128KB : 132-256KB | > 32*page | 33-64
* |-----------------------|--------------
* | >256KB : 260-512KB | > 64*page | 65 - 128
* |-----------------------|--------------
* | >512KB : 516-1024KB | > 128*page | 129 - 256
* |-----------------------|--------------
* | >1024KB : 1028-...KB | > 256*page | 257 - ..
* --------------------------------------
*
*
*/
typedef __tb_pool_data_aligned__ struct __tb_static_large_allocator_t
{
// the base
tb_allocator_t base;
// the page size
tb_size_t page_size;
// the data size
tb_size_t data_size;
// the data head
tb_static_large_data_head_t* data_head;
// the data tail
tb_static_large_data_head_t* data_tail;
// the data pred
#ifdef TB_CONFIG_MICRO_ENABLE
tb_static_large_data_pred_t data_pred[1];
#else
tb_static_large_data_pred_t data_pred[10];
#endif
#ifdef __tb_debug__
// the peak size
tb_size_t peak_size;
// the total size
tb_size_t total_size;
// the real size
tb_size_t real_size;
// the occupied size
tb_size_t occupied_size;
// the malloc count
tb_size_t malloc_count;
// the ralloc count
tb_size_t ralloc_count;
// the free count
tb_size_t free_count;
#endif
}__tb_pool_data_aligned__ tb_static_large_allocator_t, *tb_static_large_allocator_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* checker implementation
*/
#ifdef __tb_debug__
static tb_void_t tb_static_large_allocator_check_data(tb_static_large_allocator_ref_t allocator, tb_static_large_data_head_t const* data_head)
{
// check
tb_assert_and_check_return(allocator && data_head);
// done
tb_bool_t ok = tb_false;
tb_byte_t const* data = (tb_byte_t const*)&(data_head[1]);
do
{
// the base head
tb_pool_data_head_t* base_head = tb_static_large_allocator_data_base(data_head);
// check
tb_assertf_pass_break(!data_head->bfree, "data have been freed: %p", data);
tb_assertf_pass_break(base_head->debug.magic == TB_POOL_DATA_MAGIC, "the invalid data: %p", data);
tb_assertf_pass_break(((tb_byte_t*)data)[base_head->size] == TB_POOL_DATA_PATCH, "data underflow");
// ok
ok = tb_true;
} while (0);
// failed? dump it
if (!ok)
{
// dump data
tb_pool_data_dump(data, tb_true, "[static_large_allocator]: [error]: ");
// abort
tb_abort();
}
}
static tb_void_t tb_static_large_allocator_check_next(tb_static_large_allocator_ref_t allocator, tb_static_large_data_head_t const* data_head)
{
// check
tb_assert_and_check_return(allocator && data_head);
// check the next data
tb_static_large_data_head_t* next_head = (tb_static_large_data_head_t*)((tb_byte_t*)&(data_head[1]) + data_head->space);
if (next_head < allocator->data_tail && !next_head->bfree)
tb_static_large_allocator_check_data(allocator, next_head);
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* malloc implementation
*/
static __tb_inline__ tb_size_t tb_static_large_allocator_pred_index(tb_static_large_allocator_ref_t allocator, tb_size_t space)
{
#ifndef TB_CONFIG_MICRO_ENABLE
// the size
tb_size_t size = sizeof(tb_static_large_data_head_t) + space;
tb_assert(!(size & (allocator->page_size - 1)));
// the page count
size /= allocator->page_size;
// the pred index
#if 0
tb_size_t indx = tb_ilog2i(tb_align_pow2(size));
#else
// faster
tb_size_t indx = size > 1? (tb_ilog2i((tb_uint32_t)(size - 1)) + 1) : 0;
#endif
if (indx >= tb_arrayn(allocator->data_pred)) indx = tb_arrayn(allocator->data_pred) - 1;
return indx;
#else
return 0;
#endif
}
static __tb_inline__ tb_void_t tb_static_large_allocator_pred_update(tb_static_large_allocator_ref_t allocator, tb_static_large_data_head_t* data_head)
{
// check
tb_assert(allocator && data_head && data_head->bfree);
// cannot be tail
tb_check_return(data_head != allocator->data_tail);
// the pred index
tb_size_t indx = tb_static_large_allocator_pred_index(allocator, data_head->space);
// the pred head
tb_static_large_data_head_t* pred_head = allocator->data_pred[indx].data_head;
// cache this data head
if (!pred_head || data_head->space > pred_head->space) allocator->data_pred[indx].data_head = data_head;
}
static __tb_inline__ tb_void_t tb_static_large_allocator_pred_remove(tb_static_large_allocator_ref_t allocator, tb_static_large_data_head_t* data_head)
{
// check
tb_assert(allocator && data_head);
// the pred index
tb_size_t indx = tb_static_large_allocator_pred_index(allocator, data_head->space);
// clear this data head
if (allocator->data_pred[indx].data_head == data_head) allocator->data_pred[indx].data_head = tb_null;
}
static tb_static_large_data_head_t* tb_static_large_allocator_malloc_find(tb_static_large_allocator_ref_t allocator, tb_static_large_data_head_t* data_head, tb_size_t walk_size, tb_size_t space)
{
// check
tb_assert_and_check_return_val(allocator && data_head && space, tb_null);
// the data tail
tb_static_large_data_head_t* data_tail = allocator->data_tail;
tb_check_return_val(data_head < data_tail, tb_null);
// find the free data
while ((data_head + 1) <= data_tail && walk_size)
{
// the data space size
tb_size_t data_space = data_head->space;
// check the space size
tb_assert(!((sizeof(tb_static_large_data_head_t) + data_space) & (allocator->page_size - 1)));
#ifdef __tb_debug__
// check the data
if (!data_head->bfree) tb_static_large_allocator_check_data(allocator, data_head);
#endif
// allocate if the data is free
if (data_head->bfree)
{
// is enough?
if (data_space >= space)
{
// remove this free data from the pred cache
tb_static_large_allocator_pred_remove(allocator, data_head);
// split it if this free data is too large
if (data_space > sizeof(tb_static_large_data_head_t) + space)
{
// split this free data
tb_static_large_data_head_t* next_head = (tb_static_large_data_head_t*)((tb_byte_t*)(data_head + 1) + space);
next_head->space = data_space - space - sizeof(tb_static_large_data_head_t);
next_head->bfree = 1;
data_head->space = space;
// add next free data to the pred cache
tb_static_large_allocator_pred_update(allocator, next_head);
}
else
{
// the next data head
tb_static_large_data_head_t* next_head = (tb_static_large_data_head_t*)((tb_byte_t*)(data_head + 1) + data_space);
// the next data is free?
if (next_head + 1 < data_tail && next_head->bfree)
{
// add next free data to the pred cache
tb_static_large_allocator_pred_update(allocator, next_head);
}
}
// allocate the data
data_head->bfree = 0;
// return the data head
return data_head;
}
else // attempt to merge next free data if this free data is too small
{
// the next data head
tb_static_large_data_head_t* next_head = (tb_static_large_data_head_t*)((tb_byte_t*)(data_head + 1) + data_space);
// break if doesn't exist next data
tb_check_break(next_head + 1 < data_tail);
// the next data is free?
if (next_head->bfree)
{
// remove next free data from the pred cache
tb_static_large_allocator_pred_remove(allocator, next_head);
// remove this free data from the pred cache
tb_static_large_allocator_pred_remove(allocator, data_head);
// trace
tb_trace_d("malloc: find: merge: %lu", next_head->space);
// merge next data
data_head->space += sizeof(tb_static_large_data_head_t) + next_head->space;
// add this free data to the pred cache
tb_static_large_allocator_pred_update(allocator, data_head);
// continue handle this data
continue ;
}
}
}
// walk_size--
walk_size--;
// skip it if the data is non-free or too small
data_head = (tb_static_large_data_head_t*)((tb_byte_t*)(data_head + 1) + data_space);
}
// failed
return tb_null;
}
static tb_static_large_data_head_t* tb_static_large_allocator_malloc_pred(tb_static_large_allocator_ref_t allocator, tb_size_t space)
{
// check
tb_assert_and_check_return_val(allocator && allocator->data_head, tb_null);
// walk the pred cache
tb_size_t indx = tb_static_large_allocator_pred_index(allocator, space);
tb_size_t size = tb_arrayn(allocator->data_pred);
tb_static_large_data_pred_t* pred = allocator->data_pred;
tb_static_large_data_head_t* data_head = tb_null;
tb_static_large_data_head_t* pred_head = tb_null;
for (; indx < size && !data_head; indx++)
{
// the pred data head
pred_head = pred[indx].data_head;
if (pred_head)
{
// find the free data from the pred data head
data_head = tb_static_large_allocator_malloc_find(allocator, pred_head, 1, space);
#ifdef __tb_debug__
// update the total count
pred[indx].total_count++;
// update the failed count
if (!data_head) pred[indx].failed_count++;
#endif
}
}
// trace
tb_trace_d("malloc: pred: %lu: %s", space, data_head? "ok" : "no");
// ok?
return data_head;
}
static tb_static_large_data_head_t* tb_static_large_allocator_malloc_done(tb_static_large_allocator_ref_t allocator, tb_size_t size, tb_size_t* real __tb_debug_decl__)
{
// check
tb_assert_and_check_return_val(allocator && allocator->data_head, tb_null);
// done
tb_bool_t ok = tb_false;
tb_static_large_data_head_t* data_head = tb_null;
do
{
#ifdef __tb_debug__
// patch 0xcc
tb_size_t patch = 1;
#else
tb_size_t patch = 0;
#endif
// compile the need space for the page alignment
tb_size_t need_space = tb_align(size + patch, allocator->page_size) - sizeof(tb_static_large_data_head_t);
if (size + patch > need_space) need_space = tb_align(size + patch + allocator->page_size, allocator->page_size) - sizeof(tb_static_large_data_head_t);
// attempt to predict the free data first
data_head = tb_static_large_allocator_malloc_pred(allocator, need_space);
if (!data_head)
{
// find the free data from the first data head
data_head = tb_static_large_allocator_malloc_find(allocator, allocator->data_head, -1, need_space);
tb_check_break(data_head);
}
tb_assert(data_head->space >= size + patch);
// the base head
tb_pool_data_head_t* base_head = tb_static_large_allocator_data_base(data_head);
// the real size
tb_size_t size_real = real? (data_head->space - patch) : size;
// save the real size
if (real) *real = size_real;
base_head->size = (tb_uint32_t)size_real;
#ifdef __tb_debug__
// init the debug info
base_head->debug.magic = TB_POOL_DATA_MAGIC;
base_head->debug.file = file_;
base_head->debug.func = func_;
base_head->debug.line = (tb_uint16_t)line_;
// calculate the skip frames
tb_size_t skip_nframe = (tb_allocator() && tb_allocator_type(tb_allocator()) == TB_ALLOCATOR_TYPE_DEFAULT)? 6 : 3;
// save backtrace
tb_pool_data_save_backtrace(&base_head->debug, skip_nframe);
// make the dirty data and patch 0xcc for checking underflow
tb_memset_((tb_pointer_t)&(data_head[1]), TB_POOL_DATA_PATCH, size_real + patch);
// update the real size
allocator->real_size += base_head->size;
// update the occupied size
allocator->occupied_size += sizeof(tb_static_large_data_head_t) + data_head->space - 1 - TB_POOL_DATA_HEAD_DIFF_SIZE;
// update the total size
allocator->total_size += base_head->size;
// update the peak size
if (allocator->total_size > allocator->peak_size) allocator->peak_size = allocator->total_size;
// update the malloc count
allocator->malloc_count++;
#endif
// ok
ok = tb_true;
} while (0);
// trace
tb_trace_d("malloc: %lu: %s", size, ok? "ok" : "no");
// failed? clear it
if (!ok) data_head = tb_null;
// ok?
return data_head;
}
static tb_static_large_data_head_t* tb_static_large_allocator_ralloc_fast(tb_static_large_allocator_ref_t allocator, tb_static_large_data_head_t* data_head, tb_size_t size, tb_size_t* real __tb_debug_decl__)
{
// check
tb_assert_and_check_return_val(allocator && data_head && size, tb_null);
// done
tb_bool_t ok = tb_false;
do
{
// the base head
tb_pool_data_head_t* base_head = tb_static_large_allocator_data_base(data_head);
#ifdef __tb_debug__
// patch 0xcc
tb_size_t patch = 1;
// the prev size
tb_size_t prev_size = base_head->size;
// the prev space
tb_size_t prev_space = data_head->space;
#else
// no patch
tb_size_t patch = 0;
#endif
// compile the need space for the page alignment
tb_size_t need_space = tb_align(size + patch, allocator->page_size) - sizeof(tb_static_large_data_head_t);
if (size + patch > need_space) need_space = tb_align(size + patch + allocator->page_size, allocator->page_size) - sizeof(tb_static_large_data_head_t);
// this data space is not enough?
if (need_space > data_head->space)
{
// attempt to merge the next free data
tb_static_large_data_head_t* data_tail = allocator->data_tail;
tb_static_large_data_head_t* next_head = (tb_static_large_data_head_t*)((tb_byte_t*)&(data_head[1]) + data_head->space);
while (next_head < data_tail && next_head->bfree)
{
// remove next free data from the pred cache
tb_static_large_allocator_pred_remove(allocator, next_head);
// trace
tb_trace_d("ralloc: fast: merge: %lu", next_head->space);
// merge it
data_head->space += sizeof(tb_static_large_data_head_t) + next_head->space;
// the next data head
next_head = (tb_static_large_data_head_t*)((tb_byte_t*)&(data_head[1]) + data_head->space);
}
}
// enough?
tb_check_break(need_space <= data_head->space);
// split it if this data is too large after merging
if (data_head->space > sizeof(tb_static_large_data_head_t) + need_space)
{
// split this free data
tb_static_large_data_head_t* next_head = (tb_static_large_data_head_t*)((tb_byte_t*)(data_head + 1) + need_space);
next_head->space = data_head->space - need_space - sizeof(tb_static_large_data_head_t);
next_head->bfree = 1;
data_head->space = need_space;
// add next free data to the pred cache
tb_static_large_allocator_pred_update(allocator, next_head);
}
// the real size
tb_size_t size_real = real? (data_head->space - patch) : size;
// save the real size
if (real) *real = size_real;
base_head->size = (tb_uint32_t)size_real;
#ifdef __tb_debug__
// init the debug info
base_head->debug.magic = TB_POOL_DATA_MAGIC;
base_head->debug.file = file_;
base_head->debug.func = func_;
base_head->debug.line = (tb_uint16_t)line_;
// calculate the skip frames
tb_size_t skip_nframe = (tb_allocator() && tb_allocator_type(tb_allocator()) == TB_ALLOCATOR_TYPE_DEFAULT)? 6 : 3;
// save backtrace
tb_pool_data_save_backtrace(&base_head->debug, skip_nframe);
// make the dirty data
if (size_real > prev_size) tb_memset_((tb_byte_t*)&(data_head[1]) + prev_size, TB_POOL_DATA_PATCH, size_real - prev_size);
// patch 0xcc for checking underflow
((tb_byte_t*)&(data_head[1]))[size_real] = TB_POOL_DATA_PATCH;
// update the real size
allocator->real_size += size_real;
allocator->real_size -= prev_size;
// update the occupied size
allocator->occupied_size += data_head->space;
allocator->occupied_size -= prev_space;
// update the total size
allocator->total_size += size_real;
allocator->total_size -= prev_size;
// update the peak size
if (allocator->total_size > allocator->peak_size) allocator->peak_size = allocator->total_size;
#endif
// ok
ok = tb_true;
} while (0);
// failed? clear it
if (!ok) data_head = tb_null;
// trace
tb_trace_d("ralloc: fast: %lu: %s", size, ok? "ok" : "no");
// ok?
return data_head;
}
static tb_bool_t tb_static_large_allocator_free(tb_allocator_ref_t self, tb_pointer_t data __tb_debug_decl__)
{
// check
tb_static_large_allocator_ref_t allocator = (tb_static_large_allocator_t*)self;
tb_assert_and_check_return_val(allocator && data, tb_false);
// done
tb_bool_t ok = tb_false;
tb_static_large_data_head_t* data_head = tb_null;
do
{
// the data head
data_head = &(((tb_static_large_data_head_t*)data)[-1]);
#ifdef __tb_debug__
// the base head
tb_pool_data_head_t* base_head = tb_static_large_allocator_data_base(data_head);
#endif
// check
tb_assertf_and_check_break(!data_head->bfree, "double free data: %p", data);
tb_assertf(base_head->debug.magic == TB_POOL_DATA_MAGIC, "free invalid data: %p", data);
tb_assertf_and_check_break(data_head >= allocator->data_head && data_head < allocator->data_tail, "the data: %p not belong to allocator: %p", data, allocator);
tb_assertf(((tb_byte_t*)data)[base_head->size] == TB_POOL_DATA_PATCH, "data underflow");
#ifdef __tb_debug__
// check the next data
tb_static_large_allocator_check_next(allocator, data_head);
// update the total size
allocator->total_size -= base_head->size;
// update the free count
allocator->free_count++;
#endif
// trace
tb_trace_d("free: %lu: %s", base_head->size, ok? "ok" : "no");
// attempt merge the next free data
tb_static_large_data_head_t* next_head = (tb_static_large_data_head_t*)((tb_byte_t*)&(data_head[1]) + data_head->space);
if (next_head < allocator->data_tail && next_head->bfree)
{
// remove next free data from the pred cache
tb_static_large_allocator_pred_remove(allocator, next_head);
// trace
tb_trace_d("free: merge: %lu", next_head->space);
// merge it
data_head->space += sizeof(tb_static_large_data_head_t) + next_head->space;
}
// free it
data_head->bfree = 1;
// add this free data to the pred cache
tb_static_large_allocator_pred_update(allocator, data_head);
// ok
ok = tb_true;
} while (0);
// ok?
return ok;
}
static tb_pointer_t tb_static_large_allocator_malloc(tb_allocator_ref_t self, tb_size_t size, tb_size_t* real __tb_debug_decl__)
{
// check
tb_static_large_allocator_ref_t allocator = (tb_static_large_allocator_t*)self;
tb_assert_and_check_return_val(allocator && size, tb_null);
// done
tb_static_large_data_head_t* data_head = tb_static_large_allocator_malloc_done(allocator, size, real __tb_debug_args__);
// ok
return data_head? (tb_pointer_t)&(data_head[1]) : tb_null;
}
static tb_pointer_t tb_static_large_allocator_ralloc(tb_allocator_ref_t self, tb_pointer_t data, tb_size_t size, tb_size_t* real __tb_debug_decl__)
{
// check
tb_static_large_allocator_ref_t allocator = (tb_static_large_allocator_t*)self;
tb_assert_and_check_return_val(allocator && data && size, tb_null);
// done
tb_bool_t ok = tb_false;
tb_byte_t* data_real = tb_null;
tb_static_large_data_head_t* data_head = tb_null;
tb_static_large_data_head_t* aloc_head = tb_null;
do
{
// the data head
data_head = &(((tb_static_large_data_head_t*)data)[-1]);
#ifdef __tb_debug__
// the base head
tb_pool_data_head_t* base_head = tb_static_large_allocator_data_base(data_head);
#endif
// check
tb_assertf_and_check_break(!data_head->bfree, "ralloc freed data: %p", data);
tb_assertf(base_head->debug.magic == TB_POOL_DATA_MAGIC, "ralloc invalid data: %p", data);
tb_assertf_and_check_break(data_head >= allocator->data_head && data_head < allocator->data_tail, "the data: %p not belong to allocator: %p", data, allocator);
tb_assertf(((tb_byte_t*)data)[base_head->size] == TB_POOL_DATA_PATCH, "data underflow");
#ifdef __tb_debug__
// check the next data
tb_static_large_allocator_check_next(allocator, data_head);
#endif
// attempt to allocate it fastly if enough
aloc_head = tb_static_large_allocator_ralloc_fast(allocator, data_head, size, real __tb_debug_args__);
if (!aloc_head)
{
// allocate it
aloc_head = tb_static_large_allocator_malloc_done(allocator, size, real __tb_debug_args__);
tb_check_break(aloc_head);
// not same?
if (aloc_head != data_head)
{
// copy the real data
tb_memcpy_((tb_pointer_t)&aloc_head[1], data, tb_min(size, (((tb_pool_data_head_t*)(data_head + 1))[-1]).size));
// free the previous data
tb_static_large_allocator_free(self, data __tb_debug_args__);
}
}
// the real data
data_real = (tb_byte_t*)&aloc_head[1];
#ifdef __tb_debug__
// update the ralloc count
allocator->ralloc_count++;
#endif
// ok
ok = tb_true;
} while (0);
// trace
tb_trace_d("ralloc: %lu: %s", size, ok? "ok" : "no");
// failed? clear it
if (!ok) data_real = tb_null;
// ok?
return (tb_pointer_t)data_real;
}
static tb_void_t tb_static_large_allocator_clear(tb_allocator_ref_t self)
{
// check
tb_static_large_allocator_ref_t allocator = (tb_static_large_allocator_t*)self;
tb_assert_and_check_return(allocator && allocator->data_head && allocator->data_size > sizeof(tb_static_large_data_head_t));
// clear it
allocator->data_head->bfree = 1;
allocator->data_head->space = allocator->data_size - sizeof(tb_static_large_data_head_t);
// clear the pred cache
tb_memset_(allocator->data_pred, 0, sizeof(allocator->data_pred));
// add this free data to the pred cache
tb_static_large_allocator_pred_update(allocator, allocator->data_head);
// clear info
#ifdef __tb_debug__
allocator->peak_size = 0;
allocator->total_size = 0;
allocator->real_size = 0;
allocator->occupied_size = 0;
allocator->malloc_count = 0;
allocator->ralloc_count = 0;
allocator->free_count = 0;
#endif
}
static tb_void_t tb_static_large_allocator_exit(tb_allocator_ref_t self)
{
// check
tb_static_large_allocator_ref_t allocator = (tb_static_large_allocator_t*)self;
tb_assert_and_check_return(allocator);
// exit lock
tb_spinlock_exit(&allocator->base.lock);
}
#ifdef __tb_debug__
static tb_void_t tb_static_large_allocator_dump(tb_allocator_ref_t self)
{
// check
tb_static_large_allocator_ref_t allocator = (tb_static_large_allocator_t*)self;
tb_assert_and_check_return(allocator);
// trace
tb_trace_i("");
// the data head
tb_static_large_data_head_t* data_head = allocator->data_head;
tb_assert_and_check_return(data_head);
// the data tail
tb_static_large_data_head_t* data_tail = allocator->data_tail;
tb_assert_and_check_return(data_tail);
// done
tb_size_t frag_count = 0;
while ((data_head + 1) <= data_tail)
{
// non-free?
if (!data_head->bfree)
{
// check it
tb_static_large_allocator_check_data(allocator, data_head);
// trace
tb_trace_e("leak: %p", &data_head[1]);
// dump data
tb_pool_data_dump((tb_byte_t const*)&data_head[1], tb_false, "[static_large_allocator]: [error]: ");
}
// fragment++
frag_count++;
// the next head
data_head = (tb_static_large_data_head_t*)((tb_byte_t*)(data_head + 1) + data_head->space);
}
// trace
tb_trace_i("");
// trace pred info
tb_size_t i = 0;
tb_size_t pred_size = tb_arrayn(allocator->data_pred);
for (i = 0; i < pred_size; i++)
{
// the pred info
tb_static_large_data_pred_t const* pred = &allocator->data_pred[i];
tb_assert_and_check_break(pred);
// trace
tb_trace_i("pred[>%04luKB]: data: %p, space: %lu, total_count: %lu, failed_count: %lu", ((allocator->page_size << (i - 1)) >> 10), pred->data_head? &pred->data_head[1] : tb_null, pred->data_head? pred->data_head->space : 0, pred->total_count, pred->failed_count);
}
// trace
tb_trace_i("");
// trace debug info
tb_trace_i("peak_size: %lu", allocator->peak_size);
tb_trace_i("wast_rate: %llu/10000", allocator->occupied_size? (((tb_hize_t)allocator->occupied_size - allocator->real_size) * 10000) / (tb_hize_t)allocator->occupied_size : 0);
tb_trace_i("frag_count: %lu", frag_count);
tb_trace_i("free_count: %lu", allocator->free_count);
tb_trace_i("malloc_count: %lu", allocator->malloc_count);
tb_trace_i("ralloc_count: %lu", allocator->ralloc_count);
}
static tb_bool_t tb_static_large_allocator_have(tb_allocator_ref_t self, tb_cpointer_t data)
{
// check
tb_static_large_allocator_ref_t allocator = (tb_static_large_allocator_t*)self;
tb_assert_and_check_return_val(allocator, tb_false);
// have it?
return ((tb_byte_t const*)data > (tb_byte_t const*)allocator->data_head && (tb_byte_t const*)data < (tb_byte_t const*)allocator->data_head + allocator->data_size)? tb_true : tb_false;
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_allocator_ref_t tb_static_large_allocator_init(tb_byte_t* data, tb_size_t size, tb_size_t pagesize)
{
// check
tb_assert_and_check_return_val(data && size, tb_null);
tb_assert_static(!(sizeof(tb_static_large_data_head_t) & (TB_POOL_DATA_ALIGN - 1)));
tb_assert_static(!(sizeof(tb_static_large_allocator_t) & (TB_POOL_DATA_ALIGN - 1)));
// align data and size
tb_size_t diff = tb_align((tb_size_t)data, TB_POOL_DATA_ALIGN) - (tb_size_t)data;
tb_assert_and_check_return_val(size > diff + sizeof(tb_static_large_allocator_t), tb_null);
size -= diff;
data += diff;
// init allocator
tb_static_large_allocator_ref_t allocator = (tb_static_large_allocator_t*)data;
tb_memset_(allocator, 0, sizeof(tb_static_large_allocator_t));
// init base
allocator->base.type = TB_ALLOCATOR_TYPE_LARGE;
allocator->base.flag = TB_ALLOCATOR_FLAG_NONE;
allocator->base.large_malloc = tb_static_large_allocator_malloc;
allocator->base.large_ralloc = tb_static_large_allocator_ralloc;
allocator->base.large_free = tb_static_large_allocator_free;
allocator->base.clear = tb_static_large_allocator_clear;
allocator->base.exit = tb_static_large_allocator_exit;
#ifdef __tb_debug__
allocator->base.dump = tb_static_large_allocator_dump;
allocator->base.have = tb_static_large_allocator_have;
#endif
// init lock
if (!tb_spinlock_init(&allocator->base.lock)) return tb_null;
// init page_size
allocator->page_size = pagesize? pagesize : tb_page_size();
// page_size must be larger than sizeof(tb_static_large_data_head_t)
if (allocator->page_size < sizeof(tb_static_large_data_head_t))
allocator->page_size += sizeof(tb_static_large_data_head_t);
// page_size must be aligned
allocator->page_size = tb_align_pow2(allocator->page_size);
tb_assert_and_check_return_val(allocator->page_size, tb_null);
// init data size
allocator->data_size = size - sizeof(tb_static_large_allocator_t);
tb_assert_and_check_return_val(allocator->data_size > allocator->page_size, tb_null);
// align data size
allocator->data_size = tb_align(allocator->data_size - allocator->page_size, allocator->page_size);
tb_assert_and_check_return_val(allocator->data_size > sizeof(tb_static_large_data_head_t), tb_null);
// init data head
allocator->data_head = (tb_static_large_data_head_t*)&allocator[1];
allocator->data_head->bfree = 1;
allocator->data_head->space = allocator->data_size - sizeof(tb_static_large_data_head_t);
tb_assert_and_check_return_val(!((tb_size_t)allocator->data_head & (TB_POOL_DATA_ALIGN - 1)), tb_null);
// add this free data to the pred cache
tb_static_large_allocator_pred_update(allocator, allocator->data_head);
// init data tail
allocator->data_tail = (tb_static_large_data_head_t*)((tb_byte_t*)&allocator->data_head[1] + allocator->data_head->space);
// register lock profiler
#ifdef TB_LOCK_PROFILER_ENABLE
tb_lock_profiler_register(tb_lock_profiler(), (tb_pointer_t)&allocator->base.lock, TB_TRACE_MODULE_NAME);
#endif
// ok
return (tb_allocator_ref_t)allocator;
}
tbox-1.7.6/src/tbox/memory/impl/static_large_allocator.h 0000664 0000000 0000000 00000003211 14671175054 0023376 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file static_large_allocator.h
*/
#ifndef TB_MEMORY_IMPL_STATIC_LARGE_ALLOCATOR_H
#define TB_MEMORY_IMPL_STATIC_LARGE_ALLOCATOR_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* init the large allocator and the allocated data will be aligned by the page size
*
* @param data the allocator data
* @param size the allocator size
* @param pagesize the pagesize
*
* @return the allocator
*/
tb_allocator_ref_t tb_static_large_allocator_init(tb_byte_t* data, tb_size_t size, tb_size_t pagesize);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/memory/large_allocator.c 0000664 0000000 0000000 00000002410 14671175054 0021061 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file large_allocator.c
* @ingroup memory
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "large_allocator.h"
#include "impl/impl.h"
#include "../utils/utils.h"
#include "../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_allocator_ref_t tb_large_allocator_init(tb_byte_t* data, tb_size_t size)
{
// init pool
return (data && size)? tb_static_large_allocator_init(data, size, tb_page_size()) : tb_native_large_allocator_init();
}
tbox-1.7.6/src/tbox/memory/large_allocator.h 0000664 0000000 0000000 00000004267 14671175054 0021102 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file large_allocator.h
* @ingroup memory
*
*/
#ifndef TB_MEMORY_LARGE_ALLOCATOR_H
#define TB_MEMORY_LARGE_ALLOCATOR_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "allocator.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init the large allocator
*
*
*
* ------------------------- ------------------------
* | native memory | | data |
* ------------------------- ------------------------
* | |
* ------------------------- ------------------------
* | native large allocator | | static large allocator |
* ------------------------- ------------------------
* | |
* ------------------------------------------------------
* | large allocator |
* ------------------------------------------------------
*
*
*
* @param data the data, uses the native memory if be null
* @param size the size
*
* @return the allocator
*/
tb_allocator_ref_t tb_large_allocator_init(tb_byte_t* data, tb_size_t size);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/memory/memory.h 0000664 0000000 0000000 00000013776 14671175054 0017265 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file memory.h
* @defgroup memory
*
*/
#ifndef TB_MEMORY_H
#define TB_MEMORY_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "buffer.h"
#include "allocator.h"
#include "fixed_pool.h"
#include "string_pool.h"
#include "queue_buffer.h"
#include "static_buffer.h"
#include "large_allocator.h"
#include "small_allocator.h"
#include "native_allocator.h"
#include "static_allocator.h"
#include "virtual_allocator.h"
#include "default_allocator.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* description
*/
/*!architecture
*
*
*
* ---------------- ------------------------------------------------------- ----------------------
* | native memory | or | data | <- | static allocator |
* ---------------- ------------------------------------------------------- ----------------------
* | if data be null |
* `---------------------------------------> |
* |
* ----------------------------------------------------------------------------- ---------------------- ------ ------
* | large allocator | -> | fixed pool:NB | -> | slot | -> | slot | -> ...
* ----------------------------------------------------------------------------- ---------------------- ------ ------
* | |
* | --------------------------------------- ---------------------- ------ ------
* | | small allocator | -> | fixed pool:16B | -> | slot | -> | slot | -> ...
* | --------------------------------------- |----------------------| ------ ------
* | | | fixed pool:32B | -> ...
* | | |----------------------|
* | | | fixed pool:64B | -> ...
* | | |----------------------|
* | | | fixed pool:96B* | -> ...
* | | |----------------------|
* | | | fixed pool:128B | -> ...
* | | |----------------------|
* | | | fixed pool:192B* | -> ...
* | | |----------------------|
* | | | fixed pool:256B | -> ...
* | | |----------------------|
* | | | fixed pool:384B* | -> ...
* | | |----------------------|
* | | | fixed pool:512B | -> ...
* | | |----------------------|
* | | | fixed pool:1024B | -> ...
* | | |----------------------|
* | | | fixed pool:2048B | -> ...
* | | |----------------------|
* | | | fixed pool:3072B* | -> ...
* | | ----------------------
* | |
* | |
* ------------------------------------------------------------------------------
* | >3KB | <=3KB |
* |------------------------------------------------------------------------------|
* | default allocator |
* ------------------------------------------------------------------------------
* |
* ----------------------
* | string pool |
* ----------------------
*
*
*/
#endif
tbox-1.7.6/src/tbox/memory/native_allocator.c 0000664 0000000 0000000 00000006355 14671175054 0021271 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file native_allocator.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "native_allocator"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "native_allocator.h"
#include "../utils/utils.h"
#include "../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_pointer_t tb_native_allocator_malloc(tb_allocator_ref_t allocator, tb_size_t size __tb_debug_decl__)
{
// trace
tb_trace_d("malloc(%lu) at %s(): %lu, %s", size, func_, line_, file_);
// malloc it
return tb_native_memory_malloc(size);
}
static tb_pointer_t tb_native_allocator_ralloc(tb_allocator_ref_t allocator, tb_pointer_t data, tb_size_t size __tb_debug_decl__)
{
// trace
tb_trace_d("ralloc(%p, %lu) at %s(): %lu, %s", data, size, func_, line_, file_);
// ralloc it
return tb_native_memory_ralloc(data, size);
}
static tb_bool_t tb_native_allocator_free(tb_allocator_ref_t allocator, tb_pointer_t data __tb_debug_decl__)
{
// trace
tb_trace_d("free(%p) at %s(): %lu, %s", data, func_, line_, file_);
// free it
return tb_native_memory_free(data);
}
static tb_bool_t tb_native_allocator_instance_init(tb_handle_t instance, tb_cpointer_t priv)
{
// check
tb_allocator_ref_t allocator = (tb_allocator_ref_t)instance;
tb_check_return_val(allocator, tb_false);
/* init the native memory first
*
* because this allocator may be called before tb_init()
*/
if (!tb_native_memory_init()) return tb_false;
// init allocator
allocator->type = TB_ALLOCATOR_TYPE_NATIVE;
allocator->flag = TB_ALLOCATOR_FLAG_NOLOCK;
allocator->malloc = tb_native_allocator_malloc;
allocator->ralloc = tb_native_allocator_ralloc;
allocator->free = tb_native_allocator_free;
#ifdef __tb_debug__
allocator->dump = tb_null;
allocator->have = tb_null;
#endif
// ok
return tb_true;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_allocator_ref_t tb_native_allocator()
{
// init
static tb_atomic32_t s_inited = 0;
static tb_allocator_t s_allocator = {0};
// init the static instance
tb_singleton_static_init(&s_inited, &s_allocator, tb_native_allocator_instance_init, tb_null);
// ok
return &s_allocator;
}
tbox-1.7.6/src/tbox/memory/native_allocator.h 0000664 0000000 0000000 00000002654 14671175054 0021274 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file native_allocator.h
* @ingroup memory
*
*/
#ifndef TB_MEMORY_NATIVE_ALLOCATOR_H
#define TB_MEMORY_NATIVE_ALLOCATOR_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "allocator.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the global native allocator
*
* @return the allocator
*/
tb_allocator_ref_t tb_native_allocator(tb_noarg_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/memory/prefix.h 0000664 0000000 0000000 00000001575 14671175054 0017244 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_MEMORY_PREFIX_H
#define TB_MEMORY_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/memory/queue_buffer.c 0000664 0000000 0000000 00000020323 14671175054 0020407 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file queue_buffer.c
* @ingroup memory
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "memory.h"
#include "../libc/libc.h"
#include "../utils/utils.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_queue_buffer_init(tb_queue_buffer_ref_t buffer, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(buffer, tb_false);
// init
buffer->data = tb_null;
buffer->head = tb_null;
buffer->size = 0;
buffer->maxn = maxn;
// ok
return tb_true;
}
tb_void_t tb_queue_buffer_exit(tb_queue_buffer_ref_t buffer)
{
if (buffer)
{
if (buffer->data) tb_free(buffer->data);
tb_memset(buffer, 0, sizeof(tb_queue_buffer_t));
}
}
tb_byte_t* tb_queue_buffer_data(tb_queue_buffer_ref_t buffer)
{
// check
tb_assert_and_check_return_val(buffer, tb_null);
// the data
return buffer->data;
}
tb_byte_t* tb_queue_buffer_head(tb_queue_buffer_ref_t buffer)
{
// check
tb_assert_and_check_return_val(buffer, tb_null);
// the head
return buffer->head;
}
tb_byte_t* tb_queue_buffer_tail(tb_queue_buffer_ref_t buffer)
{
// check
tb_assert_and_check_return_val(buffer, tb_null);
// the tail
return buffer->head? buffer->head + buffer->size : tb_null;
}
tb_size_t tb_queue_buffer_size(tb_queue_buffer_ref_t buffer)
{
// check
tb_assert_and_check_return_val(buffer, 0);
// the size
return buffer->size;
}
tb_size_t tb_queue_buffer_maxn(tb_queue_buffer_ref_t buffer)
{
// check
tb_assert_and_check_return_val(buffer, 0);
// the maxn
return buffer->maxn;
}
tb_size_t tb_queue_buffer_left(tb_queue_buffer_ref_t buffer)
{
// check
tb_assert_and_check_return_val(buffer && buffer->size <= buffer->maxn, 0);
// the left
return buffer->maxn - buffer->size;
}
tb_bool_t tb_queue_buffer_full(tb_queue_buffer_ref_t buffer)
{
// check
tb_assert_and_check_return_val(buffer, tb_false);
// is full?
return buffer->size == buffer->maxn? tb_true : tb_false;
}
tb_bool_t tb_queue_buffer_null(tb_queue_buffer_ref_t buffer)
{
// check
tb_assert_and_check_return_val(buffer, tb_false);
// is null?
return buffer->size? tb_false : tb_true;
}
tb_void_t tb_queue_buffer_clear(tb_queue_buffer_ref_t buffer)
{
// check
tb_assert_and_check_return(buffer);
// clear it
buffer->size = 0;
buffer->head = buffer->data;
}
tb_byte_t* tb_queue_buffer_resize(tb_queue_buffer_ref_t buffer, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(buffer && maxn && maxn >= buffer->size, tb_null);
// has data?
if (buffer->data)
{
// move data to head
if (buffer->head != buffer->data)
{
if (buffer->size) tb_memmov(buffer->data, buffer->head, buffer->size);
buffer->head = buffer->data;
}
// realloc
if (maxn > buffer->maxn)
{
// init head
buffer->head = tb_null;
// make data
buffer->data = (tb_byte_t*)tb_ralloc(buffer->data, maxn);
tb_assert_and_check_return_val(buffer->data, tb_null);
// save head
buffer->head = buffer->data;
}
}
// update maxn
buffer->maxn = maxn;
// ok
return buffer->data;
}
tb_long_t tb_queue_buffer_skip(tb_queue_buffer_ref_t buffer, tb_size_t size)
{
// check
tb_assert_and_check_return_val(buffer, -1);
// no data?
tb_check_return_val(buffer->data && buffer->size && size, 0);
tb_assert_and_check_return_val(buffer->head, -1);
// read data
tb_long_t read = buffer->size > size? size : buffer->size;
buffer->head += read;
buffer->size -= read;
// null? reset head
if (!buffer->size) buffer->head = buffer->data;
// ok
return read;
}
tb_long_t tb_queue_buffer_read(tb_queue_buffer_ref_t buffer, tb_byte_t* data, tb_size_t size)
{
// check
tb_assert_and_check_return_val(buffer && data, -1);
// no data?
tb_check_return_val(buffer->data && buffer->size && size, 0);
tb_assert_and_check_return_val(buffer->head, -1);
// read data
tb_long_t read = buffer->size > size? size : buffer->size;
tb_memcpy(data, buffer->head, read);
buffer->head += read;
buffer->size -= read;
// null? reset head
if (!buffer->size) buffer->head = buffer->data;
// ok
return read;
}
tb_long_t tb_queue_buffer_writ(tb_queue_buffer_ref_t buffer, tb_byte_t const* data, tb_size_t size)
{
// check
tb_assert_and_check_return_val(buffer && data && buffer->maxn, -1);
// no data?
if (!buffer->data)
{
// make data
buffer->data = tb_malloc_bytes(buffer->maxn);
tb_assert_and_check_return_val(buffer->data, -1);
// init it
buffer->head = buffer->data;
buffer->size = 0;
}
tb_assert_and_check_return_val(buffer->data && buffer->head, -1);
// full?
tb_size_t left = buffer->maxn - buffer->size;
tb_check_return_val(left, 0);
// attempt to write data in tail directly if the tail space is enough
tb_byte_t* tail = buffer->head + buffer->size;
if (buffer->data + buffer->maxn >= tail + size)
{
tb_memcpy(tail, data, size);
buffer->size += size;
return (tb_long_t)size;
}
// move data to head
if (buffer->head != buffer->data)
{
if (buffer->size) tb_memmov(buffer->data, buffer->head, buffer->size);
buffer->head = buffer->data;
}
// write data
tb_size_t writ = left > size? size : left;
tb_memcpy(buffer->data + buffer->size, data, writ);
buffer->size += writ;
// ok
return writ;
}
tb_byte_t* tb_queue_buffer_pull_init(tb_queue_buffer_ref_t buffer, tb_size_t* size)
{
// check
tb_assert_and_check_return_val(buffer, tb_null);
// no data?
tb_check_return_val(buffer->data && buffer->size, tb_null);
tb_assert_and_check_return_val(buffer->head, tb_null);
// save size
if (size) *size = buffer->size;
// ok
return buffer->head;
}
tb_void_t tb_queue_buffer_pull_exit(tb_queue_buffer_ref_t buffer, tb_size_t size)
{
// check
tb_assert_and_check_return(buffer && buffer->head && size <= buffer->size);
// update
buffer->size -= size;
buffer->head += size;
// null? reset head
if (!buffer->size) buffer->head = buffer->data;
}
tb_byte_t* tb_queue_buffer_push_init(tb_queue_buffer_ref_t buffer, tb_size_t* size)
{
// check
tb_assert_and_check_return_val(buffer && buffer->maxn, tb_null);
// no data?
if (!buffer->data)
{
// make data
buffer->data = tb_malloc_bytes(buffer->maxn);
tb_assert_and_check_return_val(buffer->data, tb_null);
// init
buffer->head = buffer->data;
buffer->size = 0;
}
tb_assert_and_check_return_val(buffer->data && buffer->head, tb_null);
// full?
tb_size_t left = buffer->maxn - buffer->size;
tb_check_return_val(left, tb_null);
// move data to head first, make sure there is enough write space
if (buffer->head != buffer->data)
{
if (buffer->size) tb_memmov(buffer->data, buffer->head, buffer->size);
buffer->head = buffer->data;
}
// save size
if (size) *size = left;
// ok
return buffer->head + buffer->size;
}
tb_void_t tb_queue_buffer_push_exit(tb_queue_buffer_ref_t buffer, tb_size_t size)
{
// check
tb_assert_and_check_return(buffer && buffer->head && buffer->size + size <= buffer->maxn);
// update the size
buffer->size += size;
}
tbox-1.7.6/src/tbox/memory/queue_buffer.h 0000664 0000000 0000000 00000012354 14671175054 0020421 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file queue_buffer.h
* @ingroup memory
*
*/
#ifndef TB_MEMORY_QUEUE_BUFFER_H
#define TB_MEMORY_QUEUE_BUFFER_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the queue buffer type
typedef struct __tb_queue_buffer_t
{
// the buffer data
tb_byte_t* data;
// the buffer head
tb_byte_t* head;
// the buffer size
tb_size_t size;
// the buffer maxn
tb_size_t maxn;
}tb_queue_buffer_t, *tb_queue_buffer_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init buffer
*
* @param buffer the buffer
* @param maxn the buffer maxn
*
* @return tb_true or tb_false
*/
tb_bool_t tb_queue_buffer_init(tb_queue_buffer_ref_t buffer, tb_size_t maxn);
/*! exit buffer
*
* @param buffer the buffer
*/
tb_void_t tb_queue_buffer_exit(tb_queue_buffer_ref_t buffer);
/*! the buffer data
*
* @param buffer the buffer
*
* @return the buffer data
*/
tb_byte_t* tb_queue_buffer_data(tb_queue_buffer_ref_t buffer);
/*! the buffer head
*
* @param buffer the buffer
*
* @return the buffer head
*/
tb_byte_t* tb_queue_buffer_head(tb_queue_buffer_ref_t buffer);
/*! the buffer tail
*
* @param buffer the buffer
*
* @return the buffer tail
*/
tb_byte_t* tb_queue_buffer_tail(tb_queue_buffer_ref_t buffer);
/*! the buffer maxn
*
* @param buffer the buffer
*
* @return the buffer maxn
*/
tb_size_t tb_queue_buffer_maxn(tb_queue_buffer_ref_t buffer);
/*! the buffer size
*
* @param buffer the buffer
*
* @return the buffer size
*/
tb_size_t tb_queue_buffer_size(tb_queue_buffer_ref_t buffer);
/*! the buffer left
*
* @param buffer the buffer
*
* @return the buffer left
*/
tb_size_t tb_queue_buffer_left(tb_queue_buffer_ref_t buffer);
/*! the buffer full?
*
* @param buffer the buffer
*
* @return tb_true or tb_false
*/
tb_bool_t tb_queue_buffer_full(tb_queue_buffer_ref_t buffer);
/*! the buffer null?
*
* @param buffer the buffer
*
* @return tb_true or tb_false
*/
tb_bool_t tb_queue_buffer_null(tb_queue_buffer_ref_t buffer);
/*! clear buffer
*
* @param buffer the buffer
*/
tb_void_t tb_queue_buffer_clear(tb_queue_buffer_ref_t buffer);
/*! resize buffer size
*
* @param buffer the buffer
* @param maxn the buffer maxn
*
* @return the buffer data
*/
tb_byte_t* tb_queue_buffer_resize(tb_queue_buffer_ref_t buffer, tb_size_t maxn);
/*! skip buffer
*
* @param buffer the buffer
* @param size the skiped size
*
* @return the real size
*/
tb_long_t tb_queue_buffer_skip(tb_queue_buffer_ref_t buffer, tb_size_t size);
/*! read buffer
*
* @param buffer the buffer
* @param data the data
* @param size the size
*
* @return the real size
*/
tb_long_t tb_queue_buffer_read(tb_queue_buffer_ref_t buffer, tb_byte_t* data, tb_size_t size);
/*! writ buffer
*
* @param buffer the buffer
* @param data the data
* @param size the size
*
* @return the real size
*/
tb_long_t tb_queue_buffer_writ(tb_queue_buffer_ref_t buffer, tb_byte_t const* data, tb_size_t size);
/*! init pull buffer for reading
*
* @param buffer the buffer
* @param size the size
*
* @return the data
*/
tb_byte_t* tb_queue_buffer_pull_init(tb_queue_buffer_ref_t buffer, tb_size_t* size);
/*! exit pull buffer for reading
*
* @param buffer the buffer
* @param size the size
*/
tb_void_t tb_queue_buffer_pull_exit(tb_queue_buffer_ref_t buffer, tb_size_t size);
/*! init push buffer for writing
*
* @param buffer the buffer
* @param size the size
*
* @return the data
*/
tb_byte_t* tb_queue_buffer_push_init(tb_queue_buffer_ref_t buffer, tb_size_t* size);
/*! exit push buffer for writing
*
* @param buffer the buffer
* @param size the size
*/
tb_void_t tb_queue_buffer_push_exit(tb_queue_buffer_ref_t buffer, tb_size_t size);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/memory/small_allocator.c 0000664 0000000 0000000 00000034172 14671175054 0021111 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file small_allocator.c
* @ingroup memory
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "small_allocator"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "small_allocator.h"
#include "large_allocator.h"
#include "fixed_pool.h"
#include "impl/prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the small allocator type
typedef struct __tb_small_allocator_t
{
// the base
tb_allocator_t base;
// the large allocator
tb_allocator_ref_t large_allocator;
// the fixed pool
tb_fixed_pool_ref_t fixed_pool[12];
}tb_small_allocator_t, *tb_small_allocator_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* declaration
*/
__tb_extern_c__ tb_fixed_pool_ref_t tb_fixed_pool_init_(tb_allocator_ref_t large_allocator, tb_size_t slot_size, tb_size_t item_size, tb_bool_t for_small_allocator, tb_fixed_pool_item_init_func_t item_init, tb_fixed_pool_item_exit_func_t item_exit, tb_cpointer_t priv);
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_fixed_pool_ref_t tb_small_allocator_find_fixed(tb_small_allocator_ref_t allocator, tb_size_t size)
{
// check
tb_assert(allocator && size && size <= TB_SMALL_ALLOCATOR_DATA_MAXN);
// done
tb_fixed_pool_ref_t fixed_pool = tb_null;
do
{
// the fixed pool index
tb_size_t index = 0;
tb_size_t space = 0;
if (size > 64 && size < 193)
{
if (size < 97)
{
index = 3;
space = 96;
}
else if (size > 128)
{
index = 5;
space = 192;
}
else
{
index = 4;
space = 128;
}
}
else if (size > 192 && size < 513)
{
if (size < 257)
{
index = 6;
space = 256;
}
else if (size > 384)
{
index = 8;
space = 512;
}
else
{
index = 7;
space = 384;
}
}
else if (size < 65)
{
if (size < 17)
{
index = 0;
space = 16;
}
else if (size > 32)
{
index = 2;
space = 64;
}
else
{
index = 1;
space = 32;
}
}
else
{
if (size < 1025)
{
index = 9;
space = 1024;
}
else if (size > 2048)
{
index = 11;
space = 3072;
}
else
{
index = 10;
space = 2048;
}
}
// trace
tb_trace_d("find: size: %lu => index: %lu, space: %lu", size, index, space);
// make fixed pool if not exists
if (!allocator->fixed_pool[index]) allocator->fixed_pool[index] = tb_fixed_pool_init_(allocator->large_allocator, 0, space, tb_true, tb_null, tb_null, tb_null);
tb_assert_and_check_break(allocator->fixed_pool[index]);
// ok
fixed_pool = allocator->fixed_pool[index];
} while (0);
// ok?
return fixed_pool;
}
#ifdef __tb_debug__
static tb_bool_t tb_small_allocator_item_check(tb_pointer_t data, tb_cpointer_t priv)
{
// check
tb_fixed_pool_ref_t fixed_pool = (tb_fixed_pool_ref_t)priv;
tb_assert(fixed_pool && data);
// done
tb_bool_t ok = tb_false;
do
{
// the data head
tb_pool_data_head_t* data_head = &(((tb_pool_data_head_t*)data)[-1]);
tb_assertf(data_head->debug.magic == TB_POOL_DATA_MAGIC, "invalid data: %p", data);
// the data space
tb_size_t space = tb_fixed_pool_item_size(fixed_pool);
tb_assert_and_check_break(space >= data_head->size);
// check underflow
tb_assertf(space == data_head->size || ((tb_byte_t*)data)[data_head->size] == TB_POOL_DATA_PATCH, "data underflow");
// ok
ok = tb_true;
} while (0);
// continue?
return ok;
}
#endif
static tb_void_t tb_small_allocator_exit(tb_allocator_ref_t self)
{
// check
tb_small_allocator_ref_t allocator = (tb_small_allocator_ref_t)self;
tb_assert_and_check_return(allocator && allocator->large_allocator);
// enter
tb_spinlock_enter(&allocator->base.lock);
// exit fixed pool
tb_size_t i = 0;
tb_size_t n = tb_arrayn(allocator->fixed_pool);
for (i = 0; i < n; i++)
{
// exit it
if (allocator->fixed_pool[i]) tb_fixed_pool_exit(allocator->fixed_pool[i]);
allocator->fixed_pool[i] = tb_null;
}
// leave
tb_spinlock_leave(&allocator->base.lock);
// exit lock
tb_spinlock_exit(&allocator->base.lock);
// exit pool
tb_allocator_large_free(allocator->large_allocator, allocator);
}
static tb_void_t tb_small_allocator_clear(tb_allocator_ref_t self)
{
// check
tb_small_allocator_ref_t allocator = (tb_small_allocator_ref_t)self;
tb_assert_and_check_return(allocator && allocator->large_allocator);
// clear fixed pool
tb_size_t i = 0;
tb_size_t n = tb_arrayn(allocator->fixed_pool);
for (i = 0; i < n; i++)
{
// clear it
if (allocator->fixed_pool[i]) tb_fixed_pool_clear(allocator->fixed_pool[i]);
}
}
static tb_pointer_t tb_small_allocator_malloc(tb_allocator_ref_t self, tb_size_t size __tb_debug_decl__)
{
// check
tb_small_allocator_ref_t allocator = (tb_small_allocator_ref_t)self;
tb_assert_and_check_return_val(allocator && allocator->large_allocator && size, tb_null);
tb_assert_and_check_return_val(size <= TB_SMALL_ALLOCATOR_DATA_MAXN, tb_null);
// done
tb_pointer_t data = tb_null;
do
{
// the fixed pool
tb_fixed_pool_ref_t fixed_pool = tb_small_allocator_find_fixed(allocator, size);
tb_assert_and_check_break(fixed_pool);
// done
data = tb_fixed_pool_malloc_(fixed_pool __tb_debug_args__);
tb_assert_and_check_break(data);
// the data head
tb_pool_data_head_t* data_head = &(((tb_pool_data_head_t*)data)[-1]);
tb_assert(data_head->debug.magic == TB_POOL_DATA_MAGIC);
#ifdef __tb_debug__
// fill the patch bytes
if (data_head->size > size) tb_memset_((tb_byte_t*)data + size, TB_POOL_DATA_PATCH, data_head->size - size);
#endif
// update size
data_head->size = size;
} while (0);
// check
tb_assertf(data, "malloc(%lu) failed!", size);
// ok?
return data;
}
static tb_pointer_t tb_small_allocator_ralloc(tb_allocator_ref_t self, tb_pointer_t data, tb_size_t size __tb_debug_decl__)
{
// check
tb_small_allocator_ref_t allocator = (tb_small_allocator_ref_t)self;
tb_assert_and_check_return_val(allocator && allocator->large_allocator && data && size, tb_null);
tb_assert_and_check_return_val(size <= TB_SMALL_ALLOCATOR_DATA_MAXN, tb_null);
// done
tb_pointer_t data_new = tb_null;
do
{
// the old data head
tb_pool_data_head_t* data_head_old = &(((tb_pool_data_head_t*)data)[-1]);
tb_assertf(data_head_old->debug.magic == TB_POOL_DATA_MAGIC, "ralloc invalid data: %p", data);
// the old fixed pool
tb_fixed_pool_ref_t fixed_pool_old = tb_small_allocator_find_fixed(allocator, data_head_old->size);
tb_assert_and_check_break(fixed_pool_old);
// the old data space
tb_size_t space_old = tb_fixed_pool_item_size(fixed_pool_old);
tb_assert_and_check_break(space_old >= data_head_old->size);
// check underflow
tb_assertf(space_old == data_head_old->size || ((tb_byte_t*)data)[data_head_old->size] == TB_POOL_DATA_PATCH, "data underflow");
// the new fixed pool
tb_fixed_pool_ref_t fixed_pool_new = tb_small_allocator_find_fixed(allocator, size);
tb_assert_and_check_break(fixed_pool_new);
// same space?
if (fixed_pool_old == fixed_pool_new)
{
#ifdef __tb_debug__
// fill the patch bytes
if (data_head_old->size > size) tb_memset_((tb_byte_t*)data + size, TB_POOL_DATA_PATCH, data_head_old->size - size);
#endif
// only update size
data_head_old->size = size;
// ok
data_new = data;
break;
}
// make the new data
data_new = tb_fixed_pool_malloc_(fixed_pool_new __tb_debug_args__);
tb_assert_and_check_break(data_new);
// the new data head
tb_pool_data_head_t* data_head_new = &(((tb_pool_data_head_t*)data_new)[-1]);
tb_assert(data_head_new->debug.magic == TB_POOL_DATA_MAGIC);
#ifdef __tb_debug__
// fill the patch bytes
if (data_head_new->size > size) tb_memset_((tb_byte_t*)data_new + size, TB_POOL_DATA_PATCH, data_head_new->size - size);
#endif
// update size
data_head_new->size = size;
// copy the old data
tb_memcpy_(data_new, data, tb_min(data_head_old->size, size));
// free the old data
tb_fixed_pool_free_(fixed_pool_old, data __tb_debug_args__);
} while (0);
// ok
return data_new;
}
static tb_bool_t tb_small_allocator_free(tb_allocator_ref_t self, tb_pointer_t data __tb_debug_decl__)
{
// check
tb_small_allocator_ref_t allocator = (tb_small_allocator_ref_t)self;
tb_assert_and_check_return_val(allocator && allocator->large_allocator && data, tb_false);
// done
tb_bool_t ok = tb_false;
do
{
// the data head
tb_pool_data_head_t* data_head = &(((tb_pool_data_head_t*)data)[-1]);
tb_assertf(data_head->debug.magic == TB_POOL_DATA_MAGIC, "free invalid data: %p", data);
// the fixed pool
tb_fixed_pool_ref_t fixed_pool = tb_small_allocator_find_fixed(allocator, data_head->size);
tb_assert_and_check_break(fixed_pool);
// the data space
tb_size_t space = tb_fixed_pool_item_size(fixed_pool);
tb_assert_and_check_break(space >= data_head->size);
// check underflow
tb_assertf(space == data_head->size || ((tb_byte_t*)data)[data_head->size] == TB_POOL_DATA_PATCH, "data underflow");
// done
ok = tb_fixed_pool_free_(fixed_pool, data __tb_debug_args__);
} while (0);
// ok?
return ok;
}
#ifdef __tb_debug__
static tb_void_t tb_small_allocator_dump(tb_allocator_ref_t self)
{
// check
tb_small_allocator_ref_t allocator = (tb_small_allocator_ref_t)self;
tb_assert_and_check_return(allocator && allocator->large_allocator);
// trace
tb_trace_i("");
// dump fixed pool
tb_size_t i = 0;
tb_size_t n = tb_arrayn(allocator->fixed_pool);
for (i = 0; i < n; i++)
{
// exists?
if (allocator->fixed_pool[i])
{
// check it
tb_fixed_pool_walk(allocator->fixed_pool[i], tb_small_allocator_item_check, (tb_cpointer_t)allocator->fixed_pool[i]);
// dump it
tb_fixed_pool_dump(allocator->fixed_pool[i]);
}
}
}static tb_bool_t tb_small_allocator_have(tb_allocator_ref_t self, tb_cpointer_t data)
{
// check
tb_small_allocator_ref_t allocator = (tb_small_allocator_ref_t)self;
tb_assert_and_check_return_val(allocator && allocator->large_allocator, tb_false);
// have it?
return tb_allocator_have(allocator->large_allocator, data);
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_allocator_ref_t tb_small_allocator_init(tb_allocator_ref_t large_allocator)
{
// done
tb_bool_t ok = tb_false;
tb_small_allocator_ref_t allocator = tb_null;
do
{
// no allocator? uses the global allocator
if (!large_allocator) large_allocator = tb_allocator();
tb_assert_and_check_break(large_allocator);
// make allocator
allocator = (tb_small_allocator_ref_t)tb_allocator_large_malloc0(large_allocator, sizeof(tb_small_allocator_t), tb_null);
tb_assert_and_check_break(allocator);
// init large allocator
allocator->large_allocator = large_allocator;
// init base
allocator->base.type = TB_ALLOCATOR_TYPE_SMALL;
allocator->base.flag = TB_ALLOCATOR_FLAG_NONE;
allocator->base.malloc = tb_small_allocator_malloc;
allocator->base.ralloc = tb_small_allocator_ralloc;
allocator->base.free = tb_small_allocator_free;
allocator->base.clear = tb_small_allocator_clear;
allocator->base.exit = tb_small_allocator_exit;
#ifdef __tb_debug__
allocator->base.dump = tb_small_allocator_dump;
allocator->base.have = tb_small_allocator_have;
#endif
// init lock
if (!tb_spinlock_init(&allocator->base.lock)) break;
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
if (allocator) tb_small_allocator_exit((tb_allocator_ref_t)allocator);
allocator = tb_null;
}
// ok?
return (tb_allocator_ref_t)allocator;
}
tbox-1.7.6/src/tbox/memory/small_allocator.h 0000664 0000000 0000000 00000005515 14671175054 0021115 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file small_allocator.h
* @ingroup memory
*
*/
#ifndef TB_MEMORY_SMALL_ALLOCATOR_H
#define TB_MEMORY_SMALL_ALLOCATOR_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "large_allocator.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/// the data size maximum
#define TB_SMALL_ALLOCATOR_DATA_MAXN (3072)
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init the small allocator only for size <=3KB
*
*
*
* --------------------------------------
* | fixed pool: 16B | 1-16B |
* |--------------------------------------|
* | fixed pool: 32B | 17-32B |
* |--------------------------------------|
* | fixed pool: 64B | 33-64B |
* |--------------------------------------|
* | fixed pool: 96B* | 65-96B* |
* |--------------------------------------|
* | fixed pool: 128B | 97-128B |
* |--------------------------------------|
* | fixed pool: 192B* | 129-192B* |
* |--------------------------------------|
* | fixed pool: 256B | 193-256B |
* |--------------------------------------|
* | fixed pool: 384B* | 257-384B* |
* |--------------------------------------|
* | fixed pool: 512B | 385-512B |
* |--------------------------------------|
* | fixed pool: 1024B | 513-1024B |
* |--------------------------------------|
* | fixed pool: 2048B | 1025-2048B |
* |--------------------------------------|
* | fixed pool: 3072B* | 2049-3072B* |
* --------------------------------------
*
*
*
* @param large_allocator the large allocator, uses the global allocator if be null
*
* @return the pool
*/
tb_allocator_ref_t tb_small_allocator_init(tb_allocator_ref_t large_allocator);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/memory/static_allocator.c 0000664 0000000 0000000 00000005457 14671175054 0021274 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file static_allocator.c
* @ingroup memory
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "static_allocator.h"
#include "impl/impl.h"
#include "../utils/utils.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_handle_t tb_static_allocator_instance_init(tb_cpointer_t* ppriv)
{
// check
tb_check_return_val(ppriv, tb_null);
// the data and size
tb_value_ref_t tuple = (tb_value_ref_t)*ppriv;
tb_byte_t* data = (tb_byte_t*)tuple[0].ptr;
tb_size_t size = tuple[1].ul;
tb_assert_and_check_return_val(data && size, tb_null);
// ok?
return (tb_handle_t)tb_static_allocator_init(data, size);
}
static tb_void_t tb_static_allocator_instance_exit(tb_handle_t self, tb_cpointer_t priv)
{
// check
tb_allocator_ref_t allocator = (tb_allocator_ref_t)self;
tb_assert_and_check_return(allocator);
// dump allocator
#ifdef __tb_debug__
if (allocator) tb_allocator_dump(allocator);
#endif
// exit allocator
if (allocator) tb_allocator_exit(allocator);
allocator= tb_null;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_allocator_ref_t tb_static_allocator(tb_byte_t* data, tb_size_t size)
{
/* init singleton first
*
* because this allocator may be called before tb_init()
*/
if (!tb_singleton_init()) return tb_null;
// init tuple
tb_value_t tuple[2];
tuple[0].ptr = (tb_pointer_t)data;
tuple[1].ul = size;
// get it
return (tb_allocator_ref_t)tb_singleton_instance(TB_SINGLETON_TYPE_STATIC_ALLOCATOR, tb_static_allocator_instance_init, tb_static_allocator_instance_exit, tb_null, tuple);
}
tb_allocator_ref_t tb_static_allocator_init(tb_byte_t* data, tb_size_t size)
{
// init it
tb_allocator_ref_t allocator = tb_static_large_allocator_init(data, size, 8);
tb_assert_and_check_return_val(allocator, tb_null);
// init type
allocator->type = TB_ALLOCATOR_TYPE_STATIC;
// ok
return allocator;
}
tbox-1.7.6/src/tbox/memory/static_allocator.h 0000664 0000000 0000000 00000004567 14671175054 0021302 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file static_allocator.h
* @ingroup memory
*
*/
#ifndef TB_MEMORY_STATIC_ALLOCATOR_H
#define TB_MEMORY_STATIC_ALLOCATOR_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "allocator.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the global static allocator
*
* @note
* this allocator may be called before tb_init()
*
* @param data the allocator data
* @param size the allocator size
*
* @return the allocator
*/
tb_allocator_ref_t tb_static_allocator(tb_byte_t* data, tb_size_t size);
/*! init the static allocator
*
*
*
* -----------------------------------------------------
* | data |
* -----------------------------------------------------
* |
* -----------------------------------------------------
* | static allocator |
* -----------------------------------------------------
*
*
*
* @param data the allocator data
* @param size the allocator size
*
* @return the allocator
*/
tb_allocator_ref_t tb_static_allocator_init(tb_byte_t* data, tb_size_t size);
/*! exit the allocator
*
* @param allocator the allocator
*/
tb_void_t tb_static_allocator_exit(tb_allocator_ref_t allocator);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/memory/static_buffer.c 0000664 0000000 0000000 00000015232 14671175054 0020555 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file static_buffer.c
* @ingroup memory
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "memory.h"
#include "../libc/libc.h"
#include "../utils/utils.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the maximum grow size of value buffer
#ifdef __tb_small__
# define TB_STATIC_BUFFER_GROW_SIZE (64)
#else
# define TB_STATIC_BUFFER_GROW_SIZE (256)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_static_buffer_init(tb_static_buffer_ref_t buffer, tb_byte_t* data, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(buffer, tb_false);
// init
buffer->size = 0;
buffer->data = data;
buffer->maxn = maxn;
// ok
return tb_true;
}
tb_void_t tb_static_buffer_exit(tb_static_buffer_ref_t buffer)
{
// exit it
if (buffer)
{
buffer->data = tb_null;
buffer->size = 0;
buffer->maxn = 0;
}
}
tb_byte_t* tb_static_buffer_data(tb_static_buffer_ref_t buffer)
{
// check
tb_assert_and_check_return_val(buffer, tb_null);
// the buffer data
return buffer->data;
}
tb_size_t tb_static_buffer_size(tb_static_buffer_ref_t buffer)
{
// check
tb_assert_and_check_return_val(buffer, 0);
// the buffer size
return buffer->size;
}
tb_size_t tb_static_buffer_maxn(tb_static_buffer_ref_t buffer)
{
// check
tb_assert_and_check_return_val(buffer, 0);
// the buffer maxn
return buffer->maxn;
}
tb_void_t tb_static_buffer_clear(tb_static_buffer_ref_t buffer)
{
// check
tb_assert_and_check_return(buffer);
// clear it
buffer->size = 0;
}
tb_byte_t* tb_static_buffer_resize(tb_static_buffer_ref_t buffer, tb_size_t size)
{
// check
tb_assert_and_check_return_val(buffer && buffer->data && size <= buffer->maxn, tb_null);
// resize
buffer->size = size;
// ok
return buffer->data;
}
tb_byte_t* tb_static_buffer_memset(tb_static_buffer_ref_t buffer, tb_byte_t b)
{
return tb_static_buffer_memnsetp(buffer, 0, b, tb_static_buffer_size(buffer));
}
tb_byte_t* tb_static_buffer_memsetp(tb_static_buffer_ref_t buffer, tb_size_t p, tb_byte_t b)
{
return tb_static_buffer_memnsetp(buffer, p, b, tb_static_buffer_size(buffer));
}
tb_byte_t* tb_static_buffer_memnset(tb_static_buffer_ref_t buffer, tb_byte_t b, tb_size_t n)
{
return tb_static_buffer_memnsetp(buffer, 0, b, n);
}
tb_byte_t* tb_static_buffer_memnsetp(tb_static_buffer_ref_t buffer, tb_size_t p, tb_byte_t b, tb_size_t n)
{
// check
tb_assert_and_check_return_val(buffer, tb_null);
// check
tb_check_return_val(n, tb_static_buffer_data(buffer));
// resize
tb_byte_t* d = tb_static_buffer_resize(buffer, p + n);
tb_assert_and_check_return_val(d, tb_null);
// memset
tb_memset(d + p, b, n);
// ok?
return d;
}
tb_byte_t* tb_static_buffer_memcpy(tb_static_buffer_ref_t buffer, tb_static_buffer_ref_t b)
{
return tb_static_buffer_memncpyp(buffer, 0, tb_static_buffer_data(b), tb_static_buffer_size(b));
}
tb_byte_t* tb_static_buffer_memcpyp(tb_static_buffer_ref_t buffer, tb_size_t p, tb_static_buffer_ref_t b)
{
return tb_static_buffer_memncpyp(buffer, p, tb_static_buffer_data(b), tb_static_buffer_size(b));
}
tb_byte_t* tb_static_buffer_memncpy(tb_static_buffer_ref_t buffer, tb_byte_t const* b, tb_size_t n)
{
return tb_static_buffer_memncpyp(buffer, 0, b, n);
}
tb_byte_t* tb_static_buffer_memncpyp(tb_static_buffer_ref_t buffer, tb_size_t p, tb_byte_t const* b, tb_size_t n)
{
// check
tb_assert_and_check_return_val(buffer && b, tb_null);
// check
tb_check_return_val(n, tb_static_buffer_data(buffer));
// resize
tb_byte_t* d = tb_static_buffer_resize(buffer, p + n);
tb_assert_and_check_return_val(d, tb_null);
// memcpy
tb_memcpy(d + p, b, n);
// ok?
return d;
}
tb_byte_t* tb_static_buffer_memmov(tb_static_buffer_ref_t buffer, tb_size_t b)
{
// check
tb_assert_and_check_return_val(b <= tb_static_buffer_size(buffer), tb_null);
return tb_static_buffer_memnmovp(buffer, 0, b, tb_static_buffer_size(buffer) - b);
}
tb_byte_t* tb_static_buffer_memmovp(tb_static_buffer_ref_t buffer, tb_size_t p, tb_size_t b)
{
// check
tb_assert_and_check_return_val(b <= tb_static_buffer_size(buffer), tb_null);
return tb_static_buffer_memnmovp(buffer, p, b, tb_static_buffer_size(buffer) - b);
}
tb_byte_t* tb_static_buffer_memnmov(tb_static_buffer_ref_t buffer, tb_size_t b, tb_size_t n)
{
return tb_static_buffer_memnmovp(buffer, 0, b, n);
}
tb_byte_t* tb_static_buffer_memnmovp(tb_static_buffer_ref_t buffer, tb_size_t p, tb_size_t b, tb_size_t n)
{
// check
tb_assert_and_check_return_val(buffer && (b + n) <= tb_static_buffer_size(buffer), tb_null);
// clear?
if (b == tb_static_buffer_size(buffer))
{
tb_static_buffer_clear(buffer);
return tb_static_buffer_data(buffer);
}
// check
tb_check_return_val(p != b && n, tb_static_buffer_data(buffer));
// resize
tb_byte_t* d = tb_static_buffer_resize(buffer, p + n);
tb_assert_and_check_return_val(d, tb_null);
// memmov
tb_memmov(d + p, d + b, n);
// ok?
return d;
}
tb_byte_t* tb_static_buffer_memcat(tb_static_buffer_ref_t buffer, tb_static_buffer_ref_t b)
{
return tb_static_buffer_memncat(buffer, tb_static_buffer_data(b), tb_static_buffer_size(b));
}
tb_byte_t* tb_static_buffer_memncat(tb_static_buffer_ref_t buffer, tb_byte_t const* b, tb_size_t n)
{
// check
tb_assert_and_check_return_val(buffer && b, tb_null);
// check
tb_check_return_val(n, tb_static_buffer_data(buffer));
// is null?
tb_size_t p = tb_static_buffer_size(buffer);
if (!p) return tb_static_buffer_memncpy(buffer, b, n);
// resize
tb_byte_t* d = tb_static_buffer_resize(buffer, p + n);
tb_assert_and_check_return_val(d, tb_null);
// memcat
tb_memcpy(d + p, b, n);
// ok?
return d;
}
tbox-1.7.6/src/tbox/memory/static_buffer.h 0000664 0000000 0000000 00000016174 14671175054 0020570 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file static_buffer.h
* @ingroup memory
*
*/
#ifndef TB_MEMORY_STATIC_BUFFER_H
#define TB_MEMORY_STATIC_BUFFER_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the static buffer type
typedef struct __tb_static_buffer_t
{
// the buffer data
tb_byte_t* data;
// the buffer size
tb_size_t size;
// the buffer maxn
tb_size_t maxn;
}tb_static_buffer_t, *tb_static_buffer_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init the static buffer
*
* @param buffer the static buffer
* @param data the data
* @param maxn the data maxn
*
* @return tb_true or tb_false
*/
tb_bool_t tb_static_buffer_init(tb_static_buffer_ref_t buffer, tb_byte_t* data, tb_size_t maxn);
/*! exit the static buffer
*
* @param buffer the static buffer
*/
tb_void_t tb_static_buffer_exit(tb_static_buffer_ref_t buffer);
/*! the buffer data
*
* @param buffer the static buffer
*
* @return the buffer data address
*/
tb_byte_t* tb_static_buffer_data(tb_static_buffer_ref_t buffer);
/*! the buffer data size
*
* @param buffer the static buffer
*
* @return the buffer data size
*/
tb_size_t tb_static_buffer_size(tb_static_buffer_ref_t buffer);
/*! the buffer data maxn
*
* @param buffer the static buffer
*
* @return the buffer data maxn
*/
tb_size_t tb_static_buffer_maxn(tb_static_buffer_ref_t buffer);
/*! clear the buffer
*
* @param buffer the static buffer
*/
tb_void_t tb_static_buffer_clear(tb_static_buffer_ref_t buffer);
/*! resize the buffer size
*
* @param buffer the static buffer
* @param size the new buffer size
*
* @return the buffer data address
*/
tb_byte_t* tb_static_buffer_resize(tb_static_buffer_ref_t buffer, tb_size_t size);
/*! memset: b => 0 ... e
*
* @param buffer the static buffer
* @param b the filled byte
*
* @return the buffer data address
*/
tb_byte_t* tb_static_buffer_memset(tb_static_buffer_ref_t buffer, tb_byte_t b);
/*! memset: b => p ... e
*
* @param buffer the static buffer
* @param p the start position
* @param b the filled byte
*
* @return the buffer data address
*/
tb_byte_t* tb_static_buffer_memsetp(tb_static_buffer_ref_t buffer, tb_size_t p, tb_byte_t b);
/*! memset: b => 0 ... n
*
* @param buffer the static buffer
* @param b the filled byte
* @param n the filled count
*
* @return the buffer data address
*/
tb_byte_t* tb_static_buffer_memnset(tb_static_buffer_ref_t buffer, tb_byte_t b, tb_size_t n);
/*! memset: b => p ... n
*
* @param buffer the static buffer
* @param p the start position
* @param b the filled byte
* @param n the filled count
*
* @return the buffer data address
*/
tb_byte_t* tb_static_buffer_memnsetp(tb_static_buffer_ref_t buffer, tb_size_t p, tb_byte_t b, tb_size_t n);
/*! memcpy: b => 0 ...
*
* @param buffer the static buffer
* @param b the copied buffer
*
* @return the buffer data address
*/
tb_byte_t* tb_static_buffer_memcpy(tb_static_buffer_ref_t buffer, tb_static_buffer_ref_t b);
/*! memcpy: b => p ...
*
* @param buffer the static buffer
* @param p the start position
* @param b the copied buffer
*
* @return the buffer data address
*/
tb_byte_t* tb_static_buffer_memcpyp(tb_static_buffer_ref_t buffer, tb_size_t p, tb_static_buffer_ref_t b);
/*! memcpy: b ... n => 0 ...
*
* @param buffer the static buffer
* @param b the copied buffer
* @param n the copied count
*
* @return the buffer data address
*/
tb_byte_t* tb_static_buffer_memncpy(tb_static_buffer_ref_t buffer, tb_byte_t const* b, tb_size_t n);
/*! memcpy: b ... n => p ...
*
* @param buffer the static buffer
* @param p the start position
* @param b the copied buffer
* @param n the copied count
*
* @return the buffer data address
*/
tb_byte_t* tb_static_buffer_memncpyp(tb_static_buffer_ref_t buffer, tb_size_t p, tb_byte_t const* b, tb_size_t n);
/*! memmov: b ... e => 0 ...
*
* @param buffer the static buffer
* @param b the moved start position
*
* @return the buffer data address
*/
tb_byte_t* tb_static_buffer_memmov(tb_static_buffer_ref_t buffer, tb_size_t b);
/*! memmov: b ... e => p ...
*
* @param buffer the static buffer
* @param p the moved destination position
* @param b the moved start position
*
* @return the buffer data address
*/
tb_byte_t* tb_static_buffer_memmovp(tb_static_buffer_ref_t buffer, tb_size_t p, tb_size_t b);
/*! memmov: b ... n => 0 ...
*
* @param buffer the static buffer
* @param b the moved start position
* @param n the moved count
*
* @return the buffer data address
*/
tb_byte_t* tb_static_buffer_memnmov(tb_static_buffer_ref_t buffer, tb_size_t b, tb_size_t n);
/*! memmov: b ... n => p ...
*
* @param buffer the static buffer
* @param p the moved destination position
* @param b the moved start position
* @param n the moved count
*
* @return the buffer data address
*/
tb_byte_t* tb_static_buffer_memnmovp(tb_static_buffer_ref_t buffer, tb_size_t p, tb_size_t b, tb_size_t n);
/*! memcat: b +=> e ...
*
* @param buffer the static buffer
* @param b the concated buffer
*
* @return the buffer data address
*/
tb_byte_t* tb_static_buffer_memcat(tb_static_buffer_ref_t buffer, tb_static_buffer_ref_t b);
/*! memcat: b ... n +=> e ...
*
* @param buffer the static buffer
* @param b the concated buffer
* @param n the concated count
*
* @return the buffer data address
*/
tb_byte_t* tb_static_buffer_memncat(tb_static_buffer_ref_t buffer, tb_byte_t const* b, tb_size_t n);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/memory/string_pool.c 0000664 0000000 0000000 00000013341 14671175054 0020273 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file string_pool.c
* @ingroup memory
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "string_pool"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "allocator.h"
#include "memory.h"
#include "../libc/libc.h"
#include "../utils/utils.h"
#include "../platform/platform.h"
#include "../container/container.h"
#include "../algorithm/algorithm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the string pool type
typedef struct __tb_string_pool_t
{
// the cache
tb_hash_map_ref_t cache;
}tb_string_pool_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_string_pool_ref_t tb_string_pool_init(tb_bool_t bcase)
{
// done
tb_bool_t ok = tb_false;
tb_string_pool_t* pool = tb_null;
do
{
// make pool
pool = tb_malloc0_type(tb_string_pool_t);
tb_assert_and_check_break(pool);
// init hash
pool->cache = tb_hash_map_init(0, tb_element_str(bcase), tb_element_size());
tb_assert_and_check_break(pool->cache);
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (pool) tb_string_pool_exit((tb_string_pool_ref_t)pool);
pool = tb_null;
}
// ok?
return (tb_string_pool_ref_t)pool;
}
tb_void_t tb_string_pool_exit(tb_string_pool_ref_t self)
{
// check
tb_string_pool_t* pool = (tb_string_pool_t*)self;
tb_assert_and_check_return(pool);
// exit cache
if (pool->cache) tb_hash_map_exit(pool->cache);
pool->cache = tb_null;
// exit it
tb_free(pool);
}
tb_void_t tb_string_pool_clear(tb_string_pool_ref_t self)
{
// check
tb_string_pool_t* pool = (tb_string_pool_t*)self;
tb_assert_and_check_return(pool);
// clear cache
if (pool->cache) tb_hash_map_clear(pool->cache);
}
tb_char_t const* tb_string_pool_insert(tb_string_pool_ref_t self, tb_char_t const* data)
{
// check
tb_string_pool_t* pool = (tb_string_pool_t*)self;
tb_assert_and_check_return_val(pool && data, tb_null);
// done
tb_char_t const* cstr = tb_null;
if (pool->cache)
{
// exists?
tb_size_t itor;
tb_hash_map_item_ref_t item = tb_null;
if ( ((itor = tb_hash_map_find(pool->cache, data)) != tb_iterator_tail(pool->cache))
&& (item = (tb_hash_map_item_ref_t)tb_iterator_item(pool->cache, itor)))
{
// refn
tb_size_t refn = (tb_size_t)item->data;
// refn++
if (refn) tb_iterator_copy(pool->cache, itor, (tb_pointer_t)(refn + 1));
// no refn? remove it
else
{
// assert
tb_assert(0);
// del it
tb_iterator_remove(pool->cache, itor);
item = tb_null;
}
}
// no item? insert it
if (!item)
{
// insert it
if ((itor = tb_hash_map_insert(pool->cache, data, (tb_pointer_t)1)) != tb_iterator_tail(pool->cache))
item = (tb_hash_map_item_ref_t)tb_iterator_item(pool->cache, itor);
}
// save the cstr
if (item) cstr = (tb_char_t const*)item->name;
}
// ok?
return cstr;
}
tb_void_t tb_string_pool_remove(tb_string_pool_ref_t self, tb_char_t const* data)
{
// check
tb_string_pool_t* pool = (tb_string_pool_t*)self;
tb_assert_and_check_return(pool && data);
// done
tb_hash_map_item_ref_t item = tb_null;
if (pool->cache)
{
// exists?
tb_size_t itor;
if ( ((itor = tb_hash_map_find(pool->cache, data)) != tb_iterator_tail(pool->cache))
&& (item = (tb_hash_map_item_ref_t)tb_iterator_item(pool->cache, itor)))
{
// refn
tb_size_t refn = (tb_size_t)item->data;
// refn--
if (refn > 1) tb_iterator_copy(pool->cache, itor, (tb_pointer_t)(refn - 1));
// del it
else tb_iterator_remove(pool->cache, itor);
}
}
}
tb_bool_t tb_string_pool_has(tb_string_pool_ref_t self, tb_char_t const* data)
{
// check
tb_string_pool_t* pool = (tb_string_pool_t*)self;
tb_assert_and_check_return_val(pool && data, tb_false);
if (pool->cache)
{
tb_size_t itor = tb_hash_map_find(pool->cache, data);
return itor != tb_iterator_tail(pool->cache);
}
return tb_false;
}
#ifdef __tb_debug__
tb_void_t tb_string_pool_dump(tb_string_pool_ref_t self)
{
// check
tb_string_pool_t* pool = (tb_string_pool_t*)self;
tb_assert_and_check_return(pool && pool->cache);
// dump cache
tb_for_all_if (tb_hash_map_item_ref_t, item, pool->cache, item)
{
// trace
tb_trace_i("item: refn: %lu, cstr: %s", (tb_size_t)item->data, item->name);
}
}
#endif
tbox-1.7.6/src/tbox/memory/string_pool.h 0000664 0000000 0000000 00000005773 14671175054 0020312 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file string_pool.h
* @ingroup memory
*
*/
#ifndef TB_MEMORY_STRING_POOL_H
#define TB_MEMORY_STRING_POOL_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the string pool ref type
typedef __tb_typeref__(string_pool);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init string pool for small, readonly and repeat strings
*
* readonly, strip repeat strings and decrease memory fragmens
*
* @param bcase is case?
*
* @return the string pool
*/
tb_string_pool_ref_t tb_string_pool_init(tb_bool_t bcase);
/*! exit the string pool
*
* @param pool the string pool
*/
tb_void_t tb_string_pool_exit(tb_string_pool_ref_t pool);
/*! clear the string pool
*
* @param pool the string pool
*/
tb_void_t tb_string_pool_clear(tb_string_pool_ref_t pool);
/*! insert string to the pool and increase the reference count
*
* @param pool the string pool
* @param data the string data
*
* @return the string data
*/
tb_char_t const* tb_string_pool_insert(tb_string_pool_ref_t pool, tb_char_t const* data);
/*! remove string from the pool if the reference count be zero
*
* @param pool the string pool
* @param data the string data
*/
tb_void_t tb_string_pool_remove(tb_string_pool_ref_t pool, tb_char_t const* data);
/*! has this string?
*
* @param pool the string pool
* @param data the string data
*
* @return tb_true or tb_false
*/
tb_bool_t tb_string_pool_has(tb_string_pool_ref_t pool, tb_char_t const* data);
#ifdef __tb_debug__
/*! dump the string pool
*
* @param pool the string pool
*/
tb_void_t tb_string_pool_dump(tb_string_pool_ref_t pool);
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/memory/virtual_allocator.c 0000664 0000000 0000000 00000006134 14671175054 0021464 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file virtual_allocator.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "virtual_allocator"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "virtual_allocator.h"
#include "../utils/utils.h"
#include "../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_pointer_t tb_virtual_allocator_malloc(tb_allocator_ref_t allocator, tb_size_t size __tb_debug_decl__)
{
// trace
tb_trace_d("vmalloc(%lu) at %s(): %lu, %s", size, func_, line_, file_);
// malloc it
return tb_virtual_memory_malloc(size);
}
static tb_pointer_t tb_virtual_allocator_ralloc(tb_allocator_ref_t allocator, tb_pointer_t data, tb_size_t size __tb_debug_decl__)
{
// trace
tb_trace_d("vralloc(%p, %lu) at %s(): %lu, %s", data, size, func_, line_, file_);
// ralloc it
return tb_virtual_memory_ralloc(data, size);
}
static tb_bool_t tb_virtual_allocator_free(tb_allocator_ref_t allocator, tb_pointer_t data __tb_debug_decl__)
{
// trace
tb_trace_d("vfree(%p) at %s(): %lu, %s", data, func_, line_, file_);
// free it
return tb_virtual_memory_free(data);
}
static tb_bool_t tb_virtual_allocator_instance_init(tb_handle_t instance, tb_cpointer_t priv)
{
// check
tb_allocator_ref_t allocator = (tb_allocator_ref_t)instance;
tb_check_return_val(allocator, tb_false);
// init allocator
allocator->type = TB_ALLOCATOR_TYPE_VIRTUAL;
allocator->flag = TB_ALLOCATOR_FLAG_NOLOCK;
allocator->malloc = tb_virtual_allocator_malloc;
allocator->ralloc = tb_virtual_allocator_ralloc;
allocator->free = tb_virtual_allocator_free;
#ifdef __tb_debug__
allocator->dump = tb_null;
allocator->have = tb_null;
#endif
// ok
return tb_true;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_allocator_ref_t tb_virtual_allocator()
{
// init
static tb_atomic32_t s_inited = 0;
static tb_allocator_t s_allocator = {0};
// init the static instance
tb_singleton_static_init(&s_inited, &s_allocator, tb_virtual_allocator_instance_init, tb_null);
// ok
return &s_allocator;
}
tbox-1.7.6/src/tbox/memory/virtual_allocator.h 0000664 0000000 0000000 00000002661 14671175054 0021472 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file virtual_allocator.h
* @ingroup memory
*
*/
#ifndef TB_MEMORY_VIRTUAL_ALLOCATOR_H
#define TB_MEMORY_VIRTUAL_ALLOCATOR_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "allocator.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the global virtual allocator
*
* @return the allocator
*/
tb_allocator_ref_t tb_virtual_allocator(tb_noarg_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/micro.lua 0000664 0000000 0000000 00000010351 14671175054 0016072 0 ustar 00root root 0000000 0000000 -- add target
target("tbox")
-- make as a static library
set_kind("static")
-- add defines
add_defines("__tb_prefix__=\"tbox\"")
-- set the auto-generated config.h
set_configdir("$(buildir)/$(plat)/$(arch)/$(mode)")
add_configfiles("tbox.config.h.in")
-- add include directories
add_includedirs("..", {public = true})
add_includedirs("$(buildir)/$(plat)/$(arch)/$(mode)", {public = true})
-- add the header files for installing
add_headerfiles("../(tbox/**.h)|**/impl/**.h")
add_headerfiles("../(tbox/prefix/**/prefix.S)")
add_headerfiles("../(tbox/math/impl/*.h)")
add_headerfiles("../(tbox/utils/impl/*.h)")
add_headerfiles("$(buildir)/$(plat)/$(arch)/$(mode)/tbox.config.h", {prefixdir = "tbox"})
-- add options
add_options("info", "float", "wchar", "micro", "coroutine")
-- add the source files
add_files("tbox.c")
add_files("libc/string/memset.c")
add_files("libc/string/memmov.c")
add_files("libc/string/memcpy.c")
add_files("libc/string/memcmp.c")
add_files("libc/string/strstr.c")
add_files("libc/string/strdup.c")
add_files("libc/string/strlen.c")
add_files("libc/string/strnlen.c")
add_files("libc/string/strcmp.c")
add_files("libc/string/strncmp.c")
add_files("libc/string/stricmp.c")
add_files("libc/string/strnicmp.c")
add_files("libc/string/strlcpy.c")
add_files("libc/string/strncpy.c")
add_files("libc/stdio/vsnprintf.c")
add_files("libc/stdio/snprintf.c")
add_files("libc/stdio/printf.c")
add_files("libc/stdlib/stdlib.c")
add_files("libc/impl/libc.c")
add_files("libm/impl/libm.c")
add_files("math/impl/math.c")
add_files("utils/used.c")
add_files("utils/bits.c")
add_files("utils/trace.c")
add_files("utils/singleton.c")
add_files("memory/allocator.c")
add_files("memory/native_allocator.c")
add_files("memory/static_allocator.c")
add_files("memory/fixed_pool.c")
add_files("memory/impl/static_fixed_pool.c")
add_files("memory/impl/static_large_allocator.c")
add_files("memory/impl/memory.c")
add_files("network/ipv4.c")
add_files("network/ipv6.c")
add_files("network/unixaddr.c")
add_files("network/ipaddr.c")
add_files("network/impl/network.c")
add_files("platform/page.c")
add_files("platform/time.c")
add_files("platform/file.c")
add_files("platform/path.c")
add_files("platform/sched.c")
add_files("platform/print.c")
add_files("platform/thread.c")
add_files("platform/socket.c")
add_files("platform/addrinfo.c")
add_files("platform/poller.c")
add_files("platform/mutex.c")
add_files("platform/semaphore.c")
add_files("platform/native_memory.c")
add_files("platform/impl/platform.c")
add_files("platform/impl/pollerdata.c")
add_files("container/iterator.c")
add_files("container/list_entry.c")
add_files("container/single_list_entry.c")
add_files("container/array_iterator.c")
add_files("algorithm/binary_find.c")
add_files("algorithm/binary_find_if.c")
-- add the source files for debug mode
if is_mode("debug") then
add_files("utils/dump.c")
add_files("memory/impl/prefix.c")
add_files("platform/backtrace.c")
end
-- add the source files for float
if has_config("float") then
add_files("libm/isinf.c")
add_files("libm/isinff.c")
add_files("libm/isnan.c")
add_files("libm/isnanf.c")
end
-- add the source for the windows
if is_os("windows") then
add_files("libc/stdlib/mbstowcs.c")
add_files("platform/dynamic.c")
add_files("platform/atomic64.c")
add_files("platform/windows/pipe.c")
add_files("platform/windows/windows.c")
add_files("platform/windows/interface/ws2_32.c")
add_files("platform/windows/interface/mswsock.c")
add_files("platform/windows/interface/kernel32.c")
if is_mode("debug") then
add_files("platform/windows/interface/dbghelp.c")
end
end
-- add the source files for coroutine
if has_config("coroutine") then
add_files("coroutine/stackless/*.c")
add_files("coroutine/impl/stackless/*.c")
end
-- check interfaces
on_config("check_interfaces")
tbox-1.7.6/src/tbox/network/ 0000775 0000000 0000000 00000000000 14671175054 0015747 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/network/cookies.c 0000664 0000000 0000000 00000055043 14671175054 0017556 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file cookies.c
* @ingroup network
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "cookies"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "cookies.h"
#include "impl/http/date.h"
#include "url.h"
#include "../libc/libc.h"
#include "../math/math.h"
#include "../utils/utils.h"
#include "../string/string.h"
#include "../platform/platform.h"
#include "../algorithm/algorithm.h"
#include "../container/container.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the cookies entry type
typedef struct __tb_cookies_entry_t
{
// the domain
tb_char_t const* domain;
// the path
tb_char_t const* path;
// the name
tb_char_t const* name;
// the value
tb_char_t const* value;
// the expires
tb_time_t expires;
// the max-age, default: 1 and storage: 0
tb_uint32_t maxage : 30;
// storage cookies to file? remove it immediately if maxage == 0 and storage: 0
tb_uint32_t storage : 1;
// is secure?
tb_uint32_t secure : 1;
}tb_cookies_entry_t, *tb_cookies_entry_ref_t;
// the cookies type
typedef struct __tb_cookies_t
{
// the lock
tb_spinlock_t lock;
// the string element
tb_element_t string_element;
// the string pool
tb_string_pool_ref_t string_pool;
// the cookie pool, key: "domain+path+name"
tb_hash_set_ref_t cookie_pool;
}tb_cookies_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_bool_t tb_cookies_get_domain_and_path_from_url(tb_char_t const* url, tb_char_t* pdomain, tb_size_t ndomain, tb_char_t* ppath, tb_size_t npath, tb_bool_t* psecure)
{
// check
tb_assert_and_check_return_val(url && pdomain && ndomain && ppath && npath && psecure, tb_false);
// get url pointer
tb_char_t const* p = url;
tb_char_t const* e = url + tb_strlen(url);
tb_assert_and_check_return_val(p < e, tb_false);
// skip "http://"
if (p + 7 < e && !tb_strnicmp(p, "http://", 7))
{
p += 7;
}
// skip "https://"
else if (p + 8 < e && !tb_strnicmp(p, "https://", 8))
{
p += 8;
*psecure = tb_true;
}
// skip www
if (p + 3 < e && !tb_strnicmp(p, "www", 3)) p += 3;
// skip .
if (p + 1 < e && *p == '.') p++;
// get domain
tb_char_t* pb = (tb_char_t*)pdomain;
tb_char_t* pe = (tb_char_t*)pdomain + ndomain - 1;
while (p < e && pb < pe && *p && *p != '/' && *p != ':') *pb++ = *p++;
*pb = '\0';
// trace
tb_trace_d("domain: %s", pdomain);
// skip port
if (*p && *p == ':') for (p++; p < e && *p && *p != '/'; p++) ;
// get path
pb = ppath;
pe = ppath + npath - 1;
while (p < e && pb < pe && *p && *p != '?') *pb++ = *p++;
*pb = '\0';
// no path?
if (!*ppath)
{
*ppath++ = '/';
*ppath = '\0';
}
// trace
tb_trace_d("path: %s", ppath);
// ok?
return *pdomain? tb_true : tb_false;
}
static tb_bool_t tb_cookies_is_child_domain(tb_char_t const* parent, tb_char_t const* child)
{
// check
tb_assert_and_check_return_val(parent && child, tb_false);
// init
tb_char_t const* pb = parent;
tb_char_t const* cb = child;
tb_size_t pn = tb_strlen(pb);
tb_size_t cn = tb_strlen(cb);
tb_assert_and_check_return_val(pn && cn, tb_false);
// is child?
tb_size_t n = 0;
tb_char_t const* pe = pb + pn - 1;
tb_char_t const* ce = cb + cn - 1;
for (; pe >= pb && ce >= cb && *pe == *ce; pe--, ce--)
{
if (*ce == '.') n++;
}
// ok?
return (pe < pb && n >= 1 && (ce < cb || *ce == '.'))? tb_true : tb_false;
}
static tb_bool_t tb_cookies_is_child_path(tb_char_t const* parent, tb_char_t const* child)
{
// check
tb_assert_and_check_return_val(parent && child, tb_false);
// parent is root?
if (parent[0] == '/' && !parent[1]) return tb_true;
// is child?
tb_char_t const* p = parent;
tb_char_t const* c = child;
tb_size_t n = tb_strlen(parent);
while (n-- && *p && *c && *p++ == *c++) ;
// ok?
return (!*p && (!*c || *c == '/'))? tb_true : tb_false;
}
static tb_void_t tb_cookies_entry_exit(tb_cookies_t* cookies, tb_cookies_entry_ref_t entry)
{
// check
tb_assert_and_check_return(cookies && entry);
// exit domain
if (entry->domain) tb_string_pool_remove(cookies->string_pool, entry->domain);
entry->domain = tb_null;
// exit path
if (entry->path) tb_string_pool_remove(cookies->string_pool, entry->path);
entry->path = tb_null;
// exit name
if (entry->name) tb_string_pool_remove(cookies->string_pool, entry->name);
entry->name = tb_null;
// exit value
if (entry->value) tb_string_pool_remove(cookies->string_pool, entry->value);
entry->value = tb_null;
}
static tb_void_t tb_cookies_entry_free(tb_element_ref_t element, tb_pointer_t buff)
{
// check
tb_cookies_entry_ref_t entry = (tb_cookies_entry_ref_t)buff;
tb_assert_and_check_return(element && entry);
// the cookies
tb_cookies_t* cookies = (tb_cookies_t*)element->priv;
tb_assert_and_check_return(cookies && cookies->string_pool);
// exit it
tb_cookies_entry_exit(cookies, entry);
}
static tb_size_t tb_cookies_entry_hash(tb_element_ref_t element, tb_cpointer_t data, tb_size_t mask, tb_size_t index)
{
// check
tb_cookies_entry_ref_t entry = (tb_cookies_entry_ref_t)data;
tb_assert_and_check_return_val(element && entry && entry->domain, 0);
// the cookies
tb_cookies_t* cookies = (tb_cookies_t*)element->priv;
tb_assert_and_check_return_val(cookies && cookies->string_element.hash, 0);
// compute the three hash values
tb_size_t v0 = cookies->string_element.hash(&cookies->string_element, entry->domain, mask, index);
tb_size_t v1 = entry->path? cookies->string_element.hash(&cookies->string_element, entry->path, mask, index) : 0;
tb_size_t v2 = entry->name? cookies->string_element.hash(&cookies->string_element, entry->name, mask, index) : 0;
// the hash value
return (v0 ^ v1 ^ v2) & mask;
}
static tb_long_t tb_cookies_entry_comp(tb_element_ref_t element, tb_cpointer_t ldata, tb_cpointer_t rdata)
{
// check
tb_cookies_entry_ref_t lentry = (tb_cookies_entry_ref_t)ldata;
tb_cookies_entry_ref_t rentry = (tb_cookies_entry_ref_t)rdata;
tb_assert_and_check_return_val(lentry && lentry->domain, 0);
tb_assert_and_check_return_val(rentry && rentry->domain, 0);
// compare domain
tb_long_t ok = tb_strcmp(lentry->domain, rentry->domain);
tb_check_return_val(!ok, ok);
// compare domain
ok = tb_strcmp(lentry->path? lentry->path : "", rentry->path? rentry->path : "");
tb_check_return_val(!ok, ok);
// compare name
return tb_strcmp(lentry->name? lentry->name : "", rentry->name? rentry->name : "");
}
static tb_bool_t tb_cookies_entry_init(tb_cookies_t* cookies, tb_cookies_entry_ref_t entry, tb_char_t const* domain, tb_char_t const* path, tb_bool_t secure, tb_char_t const* value)
{
// check
tb_assert_and_check_return_val(cookies && cookies->string_pool && entry && value, tb_false);
// init maxage: -1
entry->maxage = 1;
entry->storage = 0;
// done
tb_char_t const* p = value;
tb_char_t const* b = tb_null;
tb_char_t const* v = tb_null;
tb_char_t data[4096] = {0};
while (1)
{
// key=value; or value;
if (!*p || *p == ';')
{
// end?
tb_check_break(b);
// trace
tb_trace_d("entry: %s => %s", b? b : "", v? v : "");
// done value
if (!tb_strnicmp(b, "expires", 7))
{
// must have value
tb_assert_and_check_return_val(v, tb_false);
// make expires time
entry->expires = tb_http_date_from_cstr(v, p - v);
}
else if (!tb_strnicmp(b, "max-age", 7))
{
// must have value
tb_assert_and_check_return_val(v, tb_false);
// the maxage
tb_long_t maxage = tb_stoi32(v);
// storage to file?
entry->storage = maxage > 0? 1 : 0;
// save maxage
entry->maxage = tb_abs(maxage);
}
else if (!tb_strnicmp(b, "domain", 6))
{
// must have value
tb_assert_and_check_return_val(v, tb_false);
// save value
tb_assert_and_check_return_val(p - v < sizeof(data), tb_false);
if (v < p)
{
tb_strncpy(data, v, p - v); data[p - v] = '\0';
entry->domain = tb_string_pool_insert(cookies->string_pool, data[0] == '.'? data + 1 : data);
}
}
else if (!tb_strnicmp(b, "path", 4))
{
// must have value
tb_assert_and_check_return_val(v, tb_false);
// save value
tb_assert_and_check_return_val(p - v < sizeof(data), tb_false);
if (v < p)
{
tb_strncpy(data, v, p - v); data[p - v] = '\0';
entry->path = tb_string_pool_insert(cookies->string_pool, data);
}
}
else if (!tb_strnicmp(b, "version", 7))
{
// must have value
tb_assert_and_check_return_val(v, tb_false);
}
else if (!tb_strnicmp(b, "secure", 6)) entry->secure = 1;
// ignore it
else if (!tb_strnicmp(b, "HttpOnly", 8)) ;
// key=value
else if (v)
{
// must have value
tb_assert_and_check_return_val(v > b, tb_false);
// save name
tb_assert_and_check_return_val(v - b - 1 < sizeof(data), tb_false);
tb_strncpy(data, b, v - b - 1); data[v - b - 1] = '\0';
entry->name = tb_string_pool_insert(cookies->string_pool, data);
tb_assert_and_check_return_val(entry->name, tb_false);
// save value
tb_assert_and_check_return_val(p - v < sizeof(data), tb_false);
if (v < p)
{
tb_strncpy(data, v, p - v); data[p - v] = '\0';
entry->value = tb_string_pool_insert(cookies->string_pool, data);
tb_assert_and_check_return_val(entry->value, tb_false);
}
// trace
tb_trace_d("set %s=%s", entry->name, entry->value? entry->value : "");
}
// next key-value pair
if (*p)
{
b = tb_null;
v = tb_null;
p++;
}
// end
else break;
}
// skip space for name
else if (!b && !v && *p == ' ') p++;
// point to name
else if (!b && *p) b = p++;
// point to value
else if (!v && *p == '=') v = ++p;
// next
else p++;
}
// domain not exists? using the given domain
if (!entry->domain && domain)
{
// the domain size
tb_size_t n = tb_strlen(domain);
// skip www
if (n > 3 && !tb_strnicmp(domain, "www", 3))
{
domain += 3;
n -= 3;
}
// skip .
if (n && *domain == '.') domain++;
// save domain
entry->domain = tb_string_pool_insert(cookies->string_pool, domain);
}
if (!entry->domain)
{
// trace
tb_trace_e("no domain for value: %s", value);
return tb_false;
}
// path not exists? using the given path
if (!entry->path) entry->path = tb_string_pool_insert(cookies->string_pool, path? path : "/");
tb_assert_and_check_return_val(entry->path, tb_false);
// no secure? using the given secure value
if (!entry->secure && secure) entry->secure = 1;
// ok
return tb_true;
}
static tb_bool_t tb_cookies_entry_walk(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value)
{
// check
tb_value_t* tuple = (tb_value_t*)value;
tb_assert(item && tuple);
// the entry
tb_cookies_entry_ref_t entry = (tb_cookies_entry_ref_t)item;
tb_assert(entry && entry->domain);
// the domain
tb_char_t const* domain = tuple[0].cstr;
// the path
tb_char_t const* path = tuple[1].cstr;
// the secure
tb_size_t secure = tuple[2].ul;
// the value of key
tb_string_ref_t kvalue = (tb_string_ref_t)tuple[3].ptr;
tb_assert(kvalue);
// expired?
if (entry->expires && tb_cache_time() >= entry->expires)
{
// trace
tb_trace_d("expired: %s%s%s: %s = %s", entry->secure? "https://" : "http://", entry->domain, entry->path? entry->path : "", entry->name? entry->name : "", entry->value? entry->value : "");
// remove it
return tb_true;
}
// this cookies is at domain/path?
if ( tb_cookies_is_child_domain(entry->domain, domain)
&& entry->path && entry->name
&& tb_cookies_is_child_path(entry->path, path)
&& entry->secure == secure)
{
// append "key=value; "
tb_string_cstrfcat(kvalue, "%s=%s; ", entry->name, entry->value? entry->value : "");
}
// continue
return tb_false;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* instance implementation
*/
static tb_handle_t tb_cookies_instance_init(tb_cpointer_t* ppriv)
{
return (tb_handle_t)tb_cookies_init();
}
static tb_void_t tb_cookies_instance_exit(tb_handle_t cookies, tb_cpointer_t priv)
{
// dump it
#ifdef __tb_debug__
tb_cookies_dump((tb_cookies_ref_t)cookies);
#endif
// exit it
tb_cookies_exit((tb_cookies_ref_t)cookies);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interface implementation
*/
tb_cookies_ref_t tb_cookies()
{
return (tb_cookies_ref_t)tb_singleton_instance(TB_SINGLETON_TYPE_COOKIES, tb_cookies_instance_init, tb_cookies_instance_exit, tb_null, tb_null);
}
tb_cookies_ref_t tb_cookies_init()
{
// done
tb_bool_t ok = tb_false;
tb_cookies_t* cookies = tb_null;
do
{
// make cookies
cookies = tb_malloc0_type(tb_cookies_t);
tb_assert_and_check_break(cookies);
// init lock
if (!tb_spinlock_init(&cookies->lock)) break;
// init string pool
cookies->string_pool = tb_string_pool_init(tb_true);
tb_assert_and_check_break(cookies->string_pool);
// init cookie pool
tb_element_t element = tb_element_mem(sizeof(tb_cookies_entry_t), tb_cookies_entry_free, cookies);
element.hash = tb_cookies_entry_hash;
element.comp = tb_cookies_entry_comp;
cookies->cookie_pool = tb_hash_set_init(TB_HASH_SET_BUCKET_SIZE_MICRO, element);
tb_assert_and_check_break(cookies->cookie_pool);
// init string element
cookies->string_element = tb_element_str(tb_true);
// register lock profiler
#ifdef TB_LOCK_PROFILER_ENABLE
tb_lock_profiler_register(tb_lock_profiler(), (tb_pointer_t)&cookies->lock, TB_TRACE_MODULE_NAME);
#endif
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit cookies
if (cookies) tb_cookies_exit((tb_cookies_ref_t)cookies);
cookies = tb_null;
}
// ok?
return (tb_cookies_ref_t)cookies;
}
tb_void_t tb_cookies_exit(tb_cookies_ref_t self)
{
// check
tb_cookies_t* cookies = (tb_cookies_t*)self;
tb_assert_and_check_return(cookies);
// enter
tb_spinlock_enter(&cookies->lock);
// exit cookie pool
if (cookies->cookie_pool) tb_hash_set_exit(cookies->cookie_pool);
cookies->cookie_pool = tb_null;
// exit string pool
if (cookies->string_pool) tb_string_pool_exit(cookies->string_pool);
cookies->string_pool = tb_null;
// leave
tb_spinlock_leave(&cookies->lock);
// exit lock
tb_spinlock_exit(&cookies->lock);
// exit it
tb_free(cookies);
}
tb_void_t tb_cookies_clear(tb_cookies_ref_t self)
{
// check
tb_cookies_t* cookies = (tb_cookies_t*)self;
tb_assert_and_check_return(cookies);
// enter
tb_spinlock_enter(&cookies->lock);
// clear cookie pool
if (cookies->cookie_pool) tb_hash_set_clear(cookies->cookie_pool);
// clear string pool
if (cookies->string_pool) tb_string_pool_clear(cookies->string_pool);
// leave
tb_spinlock_leave(&cookies->lock);
}
tb_bool_t tb_cookies_set(tb_cookies_ref_t self, tb_char_t const* domain, tb_char_t const* path, tb_bool_t secure, tb_char_t const* value)
{
// check
tb_cookies_t* cookies = (tb_cookies_t*)self;
tb_assert_and_check_return_val(cookies, tb_false);
// enter
tb_spinlock_enter(&cookies->lock);
// done
tb_bool_t ok = tb_false;
tb_cookies_entry_t entry = {0};
do
{
// check
tb_assert_and_check_break(cookies->string_pool && cookies->cookie_pool);
// init entry
if (!tb_cookies_entry_init(cookies, &entry, domain, path, secure, value)) break;
// maxage is zero? remove it
if (!entry.maxage && !entry.storage)
{
// remove it
tb_hash_set_remove(cookies->cookie_pool, &entry);
// exit it
tb_cookies_entry_exit(cookies, &entry);
}
// set entry
else tb_hash_set_insert(cookies->cookie_pool, &entry);
// storage to file?
if (entry.storage)
{
// TODO
tb_trace1_w("not supports storaging cookies to file now!");
}
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
tb_cookies_entry_exit(cookies, &entry);
}
// leave
tb_spinlock_leave(&cookies->lock);
// ok?
return ok;
}
tb_bool_t tb_cookies_set_from_url(tb_cookies_ref_t self, tb_char_t const* url, tb_char_t const* value)
{
// check
tb_cookies_t* cookies = (tb_cookies_t*)self;
tb_assert_and_check_return_val(cookies, tb_false);
// get domain and path from the given url
tb_bool_t secure = tb_false;
tb_char_t domain[256] = {0};
tb_char_t path[TB_PATH_MAXN] = {0};
if (tb_cookies_get_domain_and_path_from_url(url, domain, sizeof(domain) - 1, path, sizeof(path) - 1, &secure))
{
// trace
tb_trace_d("domain: %s, path: %s, secure: %s", domain, path, secure? "ok" : "no");
// set it with domain and path
return tb_cookies_set(self, domain, path, secure, value);
}
// try to set it without domain and path
return tb_cookies_set(self, tb_null, tb_null, tb_false, value);
}
tb_char_t const* tb_cookies_get(tb_cookies_ref_t self, tb_char_t const* domain, tb_char_t const* path, tb_bool_t secure, tb_string_ref_t value)
{
// check
tb_cookies_t* cookies = (tb_cookies_t*)self;
tb_assert_and_check_return_val(cookies && domain && value, tb_null);
// clear value first
tb_string_clear(value);
// enter
tb_spinlock_enter(&cookies->lock);
// done
tb_bool_t ok = tb_false;
do
{
// check
tb_assert_and_check_break(cookies->string_pool && cookies->cookie_pool);
// no path? using the root path
if (!path || !path[0]) path = "/";
// skip '.'
if (*domain == '.') domain++;
// spak the cached time
tb_cache_time_spak();
// get the matched values
tb_value_t tuple[4];
tuple[0].cstr = domain;
tuple[1].cstr = path;
tuple[2].ul = secure? 1 : 0;
tuple[3].ptr = value;
tb_remove_if(cookies->cookie_pool, tb_cookies_entry_walk, tuple);
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok) tb_string_clear(value);
// leave
tb_spinlock_leave(&cookies->lock);
// ok?
return tb_string_size(value)? tb_string_cstr(value) : tb_null;
}
tb_char_t const* tb_cookies_get_from_url(tb_cookies_ref_t self, tb_char_t const* url, tb_string_ref_t value)
{
// check
tb_cookies_t* cookies = (tb_cookies_t*)self;
tb_assert_and_check_return_val(cookies && value, tb_null);
// get domain and path from the given url
tb_bool_t secure = tb_false;
tb_char_t domain[256] = {0};
tb_char_t path[TB_PATH_MAXN] = {0};
if (!tb_cookies_get_domain_and_path_from_url(url, domain, sizeof(domain) - 1, path, sizeof(path) - 1, &secure)) return tb_null;
// trace
tb_trace_d("domain: %s, path: %s, secure: %s", domain, path, secure? "ok" : "no");
// get it from domain and path
return tb_cookies_get(self, domain, path, secure, value);
}
#ifdef __tb_debug__
tb_void_t tb_cookies_dump(tb_cookies_ref_t self)
{
// check
tb_cookies_t* cookies = (tb_cookies_t*)self;
tb_assert_and_check_return(cookies && cookies->cookie_pool);
// enter
tb_spinlock_enter(&cookies->lock);
// dump
tb_trace_i("");
tb_trace_i("cookie: size: %lu", tb_hash_set_size(cookies->cookie_pool));
tb_for_all_if (tb_cookies_entry_ref_t, entry, cookies->cookie_pool, entry)
{
// the entry
tb_assert_and_check_continue(entry->domain);
// the date
tb_tm_t date = {0};
tb_gmtime(entry->expires, &date);
// trace
tb_trace_i("%s%s%s: %s = %s, expires: %04ld-%02ld-%02ld %02ld:%02ld:%02ld GMT, week: %d", entry->secure? "https://" : "http://", entry->domain, entry->path? entry->path : "", entry->name? entry->name : "", entry->value? entry->value : "", date.year, date.month, date.mday, date.hour, date.minute, date.second, date.week);
}
// leave
tb_spinlock_leave(&cookies->lock);
}
#endif
tbox-1.7.6/src/tbox/network/cookies.h 0000664 0000000 0000000 00000033212 14671175054 0017555 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file cookies.h
* @ingroup network
*
*/
#ifndef TB_NETWORK_HTTP_COOKIES_H
#define TB_NETWORK_HTTP_COOKIES_H
/* //////////////////////////////////////////////////////////////////////////////////////
* INTRODUCTION
* Cookies are a general mechanism which server side connections (such as CGI scripts)
* can use to both store and retrieve information on the client side of the connection.
* The addition of a simple, persistent, client-side state significantly extends the capabilities
* of Web-based client/server applications.
*
* OVERVIEW
* A server, when returning an HTTP object to a client, may also send a piece of state information
* which the client will store. Included in that state object is a description of the range of
* URLs for which that state is valid. Any future HTTP requests made by the client which fall
* in that range will include a transmittal of the current value of the state object from the client back to the server.
* The state object is called a cookie, for no compelling reason.
* This simple mechanism provides a powerful new tool which enables a host of new types of applications to
* be written for web-based environments. Shopping applications can now store information about the currently
* selected items, for fee services can send back registration information and free the client from
* retyping a user-id on next connection, sites can store per-user preferences on the client,
* and have the client supply those preferences every time that site is connected to.
*
* SPECIFICATION
* A cookie is introduced to the client by including a Set-Cookie header as part of an HTTP response,
* typically this will be generated by a CGI script.
* Syntax of the Set-Cookie HTTP Response Header
* This is the format a CGI script would use to add to the HTTP headers a new piece of data which is to be stored
* by the client for later retrieval.
* Set-Cookie: NAME=VALUE; expires=DATE;
* path=PATH; domain=DOMAIN_NAME; secure
*
* NAME=VALUE
* This string is a sequence of characters excluding semi-colon, comma and white space.
* If there is a need to place such data in the name or value, some encoding method such as URL style %XX encoding
* is recommended, though no encoding is defined or required.
* This is the only required attribute on the Set-Cookie header.
*
* expires=DATE
* The expires attribute specifies a date string that defines the valid life time of that cookie.
* Once the expiration date has been reached, the cookie will no longer be stored or given out.
* The date string is formatted as:
*
* Wdy, DD-Mon-YYYY HH:MM:SS GMT
* This is based on RFC 822, RFC 850, RFC 1036, and RFC 1123, with the variations that the only legal time zone
* is GMT and the separators between the elements of the date must be dashes.
* expires is an optional attribute. If not specified, the cookie will expire when the user's session ends.
*
* Note: There is a bug in Netscape Navigator version 1.1 and earlier. Only cookies whose path attribute
* is set explicitly to "/" will be properly saved between sessions if they have an expires attribute.
*
*
* domain=DOMAIN_NAME
* When searching the cookie list for valid cookies, a comparison of the domain attributes of the cookie
* is made with the Internet domain name of the host from which the URL will be fetched. If there is a tail match,
* then the cookie will go through path matching to see if it should be sent.
* "Tail matching" means that domain attribute is matched against the tail of the fully qualified domain name
* of the host. A domain attribute of "acme.com" would match host names "anvil.acme.com" as well as
* "shipping.crate.acme.com".
* Only hosts within the specified domain can set a cookie for a domain and domains must have at least two (2)
* or three (3) periods in them to prevent domains of the form: ".com", ".edu", and "va.us".
* Any domain that fails within one of the seven special top level domains listed below only require two periods.
* Any other domain requires at least three. The seven special top level domains are:
* "COM", "EDU", "NET", "ORG", "GOV", "MIL", and "INT".
*
* The default value of domain is the host name of the server which generated the cookie response.
*
*
* path=PATH
* The path attribute is used to specify the subset of URLs in a domain for which the cookie is valid.
* If a cookie has already passed domain matching, then the pathname component of the URL is compared with
* the path attribute, and if there is a match, the cookie is considered valid and is sent along with the URL request.
* The path "/foo" would match "/foobar" and "/foo/bar.html". The path "/" is the most general path.
* If the path is not specified, it as assumed to be the same path as the document being described
* by the header which contains the cookie.
*
*
* secure
* If a cookie is marked secure, it will only be transmitted if the communications channel with the host
* is a secure one. Currently this means that secure cookies will only be sent to HTTPS (HTTP over SSL) servers.
* If secure is not specified, a cookie is considered safe to be sent in the clear over unsecured channels.
*
* max-age
* A positive valueindicates that the cookie will expire after that many seconds have passed.
* Note that the value is the maximum age when the cookie will expire, not the cookie's current age.
* A negative value means that the cookie is not stored persistently and will be deleted when the Web browser exits.
* A zero value causes the cookie to be deleted.
* The default value is -1
*
* Syntax of the Cookie HTTP Request Header
* When requesting a URL from an HTTP server, the browser will match the URL against all cookies
* and if any of them match, a line containing the name/value pairs of all matching cookies will be included
* in the HTTP request. Here is the format of that line:
* Cookie: NAME1=OPAQUE_STRING1; NAME2=OPAQUE_STRING2 ...
*
* Additional Notes
* Multiple Set-Cookie headers can be issued in a single server response.
*
* Instances of the same path and name will overwrit each other, with the latest instance taking precedence.
* Instances of the same path but different names will add additional mappings.
*
* Setting the path to a higher-level value does not override other more specific path mappings.
* If there are multiple matches for a given cookie name, but with separate paths,
* all the matching cookies will be sent. (See examples below.)
*
* The expires header lets the client know when it is safe to purge the mapping but the client is not required to do so.
* A client may also delete a cookie before it's expiration date arrives if the number of cookies exceeds
* its internal limits.
*
* When sending cookies to a server, all cookies with a more specific path mapping should be sent before cookies
* with less specific path mappings. For example, a cookie "name1=foo" with a path mapping of "/" should be
* sent after a cookie "name1=foo2" with a path mapping of "/bar" if they are both to be sent.
*
* There are limitations on the number of cookies that a client can store at any one time.
* This is a specification of the minimum number of cookies that a client should be prepared to receive and store.
* 300 total cookies
* 4 kilobytes per cookie, where the name and the OPAQUE_STRING combine to form the 4 kilobyte limit.
* 20 cookies per server or domain. (note that completely specified hosts and domains are treated as
* separate entities and have a 20 cookie limitation for each, not combined)
* Servers should not expect clients to be able to exceed these limits. When the 300 cookie limit
* or the 20 cookie per server limit is exceeded, clients should delete the least recently used cookie.
* When a cookie larger than 4 kilobytes is encountered the cookie should be trimmed to fit,
* but the name should remain intact as long as it is less than 4 kilobytes.
*
* If a CGI script wishes to delete a cookie, it can do so by returning a cookie with the same name,
* and an expires time which is in the past. The path and name must match exactly in order for the expiring cookie
* to replace the valid cookie. This requirement makes it difficult for anyone but the originator of a cookie
* to delete a cookie.
*
* When caching HTTP, as a proxy server might do, the Set-cookie response header should never be cached.
*
* If a proxy server receives a response which contains a Set-cookie header,
* it should propagate the Set-cookie header to the client, regardless of whether the response was 304 (Not Modified)
* or 200 (OK).
* Similarly, if a client request contains a Cookie: header, it should be forwarded through a proxy,
* even if the conditional If-modified-since request is being made.
*
* EXAMPLES
* Here are some sample exchanges which are designed to illustrate the use of cookies.
* First Example transaction sequence:
* Client requests a document, and receives in the response:
* Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/; expires=Wednesday, 09-Nov-99 23:12:40 GMT
* When client requests a URL in path "/" on this server, it sends:
* Cookie: CUSTOMER=WILE_E_COYOTE
* Client requests a document, and receives in the response:
* Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/
* When client requests a URL in path "/" on this server, it sends:
* Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001
* Client receives:
* Set-Cookie: SHIPPING=FEDEX; path=/foo
* When client requests a URL in path "/" on this server, it sends:
* Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001
* When client requests a URL in path "/foo" on this server, it sends:
* Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001; SHIPPING=FEDEX
* Second Example transaction sequence:
* Assume all mappings from above have been cleared.
*
* Client receives:
* Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/
* When client requests a URL in path "/" on this server, it sends:
* Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001
* Client receives:
* Set-Cookie: PART_NUMBER=RIDING_ROCKET_0023; path=/ammo
* When client requests a URL in path "/ammo" on this server, it sends:
* Cookie: PART_NUMBER=RIDING_ROCKET_0023; PART_NUMBER=ROCKET_LAUNCHER_0001
* NOTE: There are two name/value pairs named "PART_NUMBER" due to the inheritance of the "/" mapping
* in addition to the "/ammo" mapping.
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../string/string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the cookies ref type
typedef __tb_typeref__(cookies);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the cookies instances
*
* @return the cookies
*/
tb_cookies_ref_t tb_cookies(tb_noarg_t);
/*! init cookies
*
* @return the cookies
*/
tb_cookies_ref_t tb_cookies_init(tb_noarg_t);
/*! exit cookies
*
* @param cookies the cookies
*/
tb_void_t tb_cookies_exit(tb_cookies_ref_t cookies);
/*! set cookies from the given domain and path
*
* @param cookies the cookies
* @param domain the domain, .e.g .xxx.com or xxx.com and compatible www.xxx.com
* @param path the path, .e.g /root/path
* @param secure is secure?
* @param value the value
*
* @return tb_true or tb_false
*/
tb_bool_t tb_cookies_set(tb_cookies_ref_t cookies, tb_char_t const* domain, tb_char_t const* path, tb_bool_t secure, tb_char_t const* value);
/*! set cookies from the given url
*
* @param cookies the cookies
* @param url the url
* @param value the value
*
* @return tb_true or tb_false
*/
tb_bool_t tb_cookies_set_from_url(tb_cookies_ref_t cookies, tb_char_t const* url, tb_char_t const* value);
/*! get cookies from the given domain and path
*
* @param cookies the cookies
* @param domain the domain, .e.g .xxx.com or xxx.com and compatible www.xxx.com
* @param path the path, .e.g /root/path
* @param secure is secure?
* @param value the cookies value
*
* @return the cookies data
*/
tb_char_t const* tb_cookies_get(tb_cookies_ref_t cookies, tb_char_t const* domain, tb_char_t const* path, tb_bool_t secure, tb_string_ref_t value);
/*! get cookies from the given url
*
* @param cookies the cookies
* @param url the url
* @param value the cookies value
*
* @return the cookies data
*/
tb_char_t const* tb_cookies_get_from_url(tb_cookies_ref_t cookies, tb_char_t const* url, tb_string_ref_t value);
/*! clear cookies
*
* @param cookies the cookies
*/
tb_void_t tb_cookies_clear(tb_cookies_ref_t cookies);
#ifdef __tb_debug__
/*! dump cookies
*
* @param cookies the cookies
*/
tb_void_t tb_cookies_dump(tb_cookies_ref_t cookies);
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/network/dns/ 0000775 0000000 0000000 00000000000 14671175054 0016533 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/network/dns/cache.c 0000664 0000000 0000000 00000015711 14671175054 0017747 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file cache.c
* @ingroup network
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "dns_cache"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "cache.h"
#include "../../platform/platform.h"
#include "../../container/container.h"
#include "../../algorithm/algorithm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the cache maxn
#ifdef __tb_small__
# define TB_DNS_CACHE_MAXN (64)
#else
# define TB_DNS_CACHE_MAXN (256)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the dns cache type
typedef struct __tb_dns_cache_t
{
// the hash
tb_hash_map_ref_t hash;
// the times
tb_hize_t times;
// the expired
tb_size_t expired;
}tb_dns_cache_t;
// the dns cache addr type
typedef struct __tb_dns_cache_addr_t
{
// the addr
tb_ipaddr_t addr;
// the time
tb_size_t time;
}tb_dns_cache_addr_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
// the lock
static tb_spinlock_t g_lock = TB_SPINLOCK_INIT;
// the cache
static tb_dns_cache_t g_cache = {0};
/* //////////////////////////////////////////////////////////////////////////////////////
* helper
*/
static __tb_inline__ tb_size_t tb_dns_cache_now()
{
return (tb_size_t)(tb_cache_time_spak() / 1000);
}
static tb_bool_t tb_dns_cache_clear(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value)
{
// check
tb_assert(item);
// the dns cache address
tb_dns_cache_addr_t const* caddr = (tb_dns_cache_addr_t const*)((tb_hash_map_item_ref_t)item)->data;
tb_assert(caddr);
// is expired?
tb_bool_t ok = tb_false;
if (caddr->time < g_cache.expired)
{
// remove it
ok = tb_true;
// trace
tb_trace_d("del: %s => %{ipaddr}, time: %u, size: %u", (tb_char_t const*)item->name, &caddr->addr, caddr->time, tb_hash_map_size(g_cache.hash));
// update times
tb_assert(g_cache.times >= caddr->time);
g_cache.times -= caddr->time;
}
// ok?
return ok;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_dns_cache_init()
{
// enter
tb_spinlock_enter(&g_lock);
// done
tb_bool_t ok = tb_false;
do
{
// init hash
if (!g_cache.hash) g_cache.hash = tb_hash_map_init(tb_align8(tb_isqrti(TB_DNS_CACHE_MAXN) + 1), tb_element_str(tb_false), tb_element_mem(sizeof(tb_dns_cache_addr_t), tb_null, tb_null));
tb_assert_and_check_break(g_cache.hash);
// ok
ok = tb_true;
} while (0);
// leave
tb_spinlock_leave(&g_lock);
// failed? exit it
if (!ok) tb_dns_cache_exit();
// ok?
return ok;
}
tb_void_t tb_dns_cache_exit()
{
// enter
tb_spinlock_enter(&g_lock);
// exit hash
if (g_cache.hash) tb_hash_map_exit(g_cache.hash);
g_cache.hash = tb_null;
// exit times
g_cache.times = 0;
// exit expired
g_cache.expired = 0;
// leave
tb_spinlock_leave(&g_lock);
}
tb_bool_t tb_dns_cache_get(tb_char_t const* name, tb_ipaddr_ref_t addr)
{
// check
tb_assert_and_check_return_val(name && addr, tb_false);
// trace
tb_trace_d("get: %s", name);
// is addr?
tb_check_return_val(!tb_ipaddr_ip_cstr_set(addr, name, TB_IPADDR_FAMILY_NONE), tb_true);
// is localhost?
if (!tb_stricmp(name, "localhost"))
{
// save address
tb_ipaddr_ip_cstr_set(addr, "127.0.0.1", TB_IPADDR_FAMILY_IPV4);
// ok
return tb_true;
}
// clear address
tb_ipaddr_clear(addr);
// enter
tb_spinlock_enter(&g_lock);
// done
tb_bool_t ok = tb_false;
do
{
// check
tb_assert_and_check_break(g_cache.hash);
// get the host address
tb_dns_cache_addr_t* caddr = (tb_dns_cache_addr_t*)tb_hash_map_get(g_cache.hash, name);
tb_check_break(caddr);
// trace
tb_trace_d("get: %s => %{ipaddr}, time: %u => %u, size: %u", name, &caddr->addr, caddr->time, tb_dns_cache_now(), tb_hash_map_size(g_cache.hash));
// update time
tb_assert_and_check_break(g_cache.times >= caddr->time);
g_cache.times -= caddr->time;
caddr->time = tb_dns_cache_now();
g_cache.times += caddr->time;
// save address
tb_ipaddr_copy(addr, &caddr->addr);
// ok
ok = tb_true;
} while (0);
// leave
tb_spinlock_leave(&g_lock);
// ok?
return ok;
}
tb_void_t tb_dns_cache_set(tb_char_t const* name, tb_ipaddr_ref_t addr)
{
// check
tb_assert_and_check_return(name && addr);
// check address
tb_assert(!tb_ipaddr_ip_is_empty(addr));
// trace
tb_trace_d("set: %s => %{ipaddr}", name, addr);
// init addr
tb_dns_cache_addr_t caddr;
caddr.time = tb_dns_cache_now();
tb_ipaddr_copy(&caddr.addr, addr);
// enter
tb_spinlock_enter(&g_lock);
// done
do
{
// check
tb_assert_and_check_break(g_cache.hash);
// remove the expired items if full
if (tb_hash_map_size(g_cache.hash) >= TB_DNS_CACHE_MAXN)
{
// the expired time
g_cache.expired = ((tb_size_t)(g_cache.times / tb_hash_map_size(g_cache.hash)) + 1);
// check
tb_assert_and_check_break(g_cache.expired);
// trace
tb_trace_d("expired: %lu", g_cache.expired);
// remove the expired times
tb_remove_if(g_cache.hash, tb_dns_cache_clear, tb_null);
}
// check
tb_assert_and_check_break(tb_hash_map_size(g_cache.hash) < TB_DNS_CACHE_MAXN);
// save addr
tb_hash_map_insert(g_cache.hash, name, &caddr);
// update times
g_cache.times += caddr.time;
// trace
tb_trace_d("set: %s => %{ipaddr}, time: %u, size: %u", name, &caddr.addr, caddr.time, tb_hash_map_size(g_cache.hash));
} while (0);
// leave
tb_spinlock_leave(&g_lock);
}
tbox-1.7.6/src/tbox/network/dns/cache.h 0000664 0000000 0000000 00000003600 14671175054 0017746 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file cache.h
* @ingroup network
*
*/
#ifndef TB_NETWORK_DNS_CACHE_H
#define TB_NETWORK_DNS_CACHE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init the cache list
*
* not using ctime default
*
* @return tb_true or tb_false
*/
tb_bool_t tb_dns_cache_init(tb_noarg_t);
/// exit the cache list
tb_void_t tb_dns_cache_exit(tb_noarg_t);
/*! get addr from cache
*
* @param name the host name
* @param addr the host addr
*
* @return tb_true or tb_false
*/
tb_bool_t tb_dns_cache_get(tb_char_t const* name, tb_ipaddr_ref_t addr);
/*! set addr to cache
*
* @param name the host name
* @param addr the host addr
*/
tb_void_t tb_dns_cache_set(tb_char_t const* name, tb_ipaddr_ref_t addr);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/network/dns/dns.h 0000664 0000000 0000000 00000001706 14671175054 0017474 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file dns.h
* @ingroup network
*
*/
#ifndef TB_NETWORK_DNS_H
#define TB_NETWORK_DNS_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "cache.h"
#include "server.h"
#include "looker.h"
#endif
tbox-1.7.6/src/tbox/network/dns/looker.c 0000664 0000000 0000000 00000052227 14671175054 0020202 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file looker.c
* @ingroup network
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "dns_looker"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "looker.h"
#include "cache.h"
#include "server.h"
#include "../../string/string.h"
#include "../../memory/memory.h"
#include "../../network/network.h"
#include "../../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the dns looker timeout
#define TB_DNS_LOOKER_TIMEOUT (5000)
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
// the dns looker step enum
typedef enum __tb_dns_looker_step_e
{
TB_DNS_LOOKER_STEP_NONE = 0
, TB_DNS_LOOKER_STEP_REQT = 1
, TB_DNS_LOOKER_STEP_RESP = 2
, TB_DNS_LOOKER_STEP_NEVT = 4
}tb_dns_looker_step_e;
// the dns looker type
typedef struct __tb_dns_looker_t
{
// the name
tb_static_string_t name;
// the request and response packet
tb_static_buffer_t rpkt;
// the size for recv and send packet
tb_size_t size;
// the iterator
tb_size_t itor;
// the step
tb_size_t step;
// the tryn
tb_size_t tryn;
// the socket
tb_socket_ref_t sock;
// the socket family
tb_uint8_t family;
// the server list
tb_ipaddr_t list[2];
// the server maxn
tb_size_t maxn;
// the data
tb_byte_t data[TB_DNS_NAME_MAXN + TB_DNS_RPKT_MAXN];
}tb_dns_looker_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_long_t tb_dns_looker_reqt(tb_dns_looker_t* looker)
{
// check
tb_check_return_val(!(looker->step & TB_DNS_LOOKER_STEP_REQT), 1);
// format it first if the request is null
if (!tb_static_buffer_size(&looker->rpkt))
{
// check size
tb_assert_and_check_return_val(!looker->size, -1);
// format query
tb_static_stream_t stream;
tb_byte_t rpkt[TB_DNS_RPKT_MAXN];
tb_size_t size = 0;
tb_byte_t* p = tb_null;
tb_static_stream_init(&stream, rpkt, TB_DNS_RPKT_MAXN);
// identification number
tb_static_stream_writ_u16_be(&stream, TB_DNS_HEADER_MAGIC);
/* 0x2104: 0 0000 001 0000 0000
*
* tb_uint16_t qr :1; // query/response flag
* tb_uint16_t opcode :4; // purpose of message
* tb_uint16_t aa :1; // authoritive answer
* tb_uint16_t tc :1; // truncated message
* tb_uint16_t rd :1; // recursion desired
* tb_uint16_t ra :1; // recursion available
* tb_uint16_t z :1; // its z! reserved
* tb_uint16_t ad :1; // authenticated data
* tb_uint16_t cd :1; // checking disabled
* tb_uint16_t rcode :4; // response code
*
* this is a query
* this is a standard query
* not authoritive answer
* not truncated
* recursion desired
*
* recursion not available! hey we dont have it (lol)
*
*/
#if 1
tb_static_stream_writ_u16_be(&stream, 0x0100);
#else
tb_static_stream_writ_u1(&stream, 0); // this is a query
tb_static_stream_writ_ubits32(&stream, 0, 4); // this is a standard query
tb_static_stream_writ_u1(&stream, 0); // not authoritive answer
tb_static_stream_writ_u1(&stream, 0); // not truncated
tb_static_stream_writ_u1(&stream, 1); // recursion desired
tb_static_stream_writ_u1(&stream, 0); // recursion not available! hey we dont have it (lol)
tb_static_stream_writ_u1(&stream, 0);
tb_static_stream_writ_u1(&stream, 0);
tb_static_stream_writ_u1(&stream, 0);
tb_static_stream_writ_ubits32(&stream, 0, 4);
#endif
/* we have only one question
*
* tb_uint16_t question; // number of question entries
* tb_uint16_t answer; // number of answer entries
* tb_uint16_t authority; // number of authority entries
* tb_uint16_t resource; // number of resource entries
*
*/
tb_static_stream_writ_u16_be(&stream, 1);
tb_static_stream_writ_u16_be(&stream, 0);
tb_static_stream_writ_u16_be(&stream, 0);
tb_static_stream_writ_u16_be(&stream, 0);
// set questions, see as tb_dns_question_t
// name + question1 + question2 + ...
tb_static_stream_writ_u8(&stream, '.');
p = (tb_byte_t*)tb_static_stream_writ_cstr(&stream, tb_static_string_cstr(&looker->name));
// only one question now.
tb_static_stream_writ_u16_be(&stream, 1); // we are requesting the ipv4 address
tb_static_stream_writ_u16_be(&stream, 1); // it's internet (lol)
// encode dns name
if (!p || !tb_dns_encode_name((tb_char_t*)p - 1)) return -1;
// size
size = tb_static_stream_offset(&stream);
tb_assert_and_check_return_val(size, -1);
// copy
tb_static_buffer_memncpy(&looker->rpkt, rpkt, size);
}
// data && size
tb_byte_t const* data = tb_static_buffer_data(&looker->rpkt);
tb_size_t size = tb_static_buffer_size(&looker->rpkt);
// check
tb_assert_and_check_return_val(data && size && looker->size < size, -1);
// try get addr from the dns list
tb_ipaddr_ref_t addr = tb_null;
if (looker->maxn && looker->itor && looker->itor <= looker->maxn)
addr = &looker->list[looker->itor - 1];
// check
tb_assert_and_check_return_val(addr && !tb_ipaddr_is_empty(addr), -1);
// family have been changed? reinit socket
if (tb_ipaddr_family(addr) != looker->family)
{
// exit the previous socket
if (looker->sock) tb_socket_exit(looker->sock);
// init a new socket for the family
looker->sock = tb_socket_init(TB_SOCKET_TYPE_UDP, tb_ipaddr_family(addr));
tb_assert_and_check_return_val(looker->sock, -1);
// update the new family
looker->family = (tb_uint8_t)tb_ipaddr_family(addr);
}
// need wait if no data
looker->step &= ~TB_DNS_LOOKER_STEP_NEVT;
// trace
tb_trace_d("request: try %{ipaddr}", addr);
// send request
while (looker->size < size)
{
// writ data
tb_long_t writ = tb_socket_usend(looker->sock, addr, data + looker->size, size - looker->size);
tb_assert_and_check_return_val(writ >= 0, -1);
// no data?
if (!writ)
{
// abort?
tb_check_return_val(!looker->size && !looker->tryn, -1);
// tryn++
looker->tryn++;
// continue
return 0;
}
else looker->tryn = 0;
// update size
looker->size += writ;
}
// finish it
looker->step |= TB_DNS_LOOKER_STEP_REQT;
looker->tryn = 0;
// reset rpkt
looker->size = 0;
tb_static_buffer_clear(&looker->rpkt);
// ok
tb_trace_d("request: ok");
return 1;
}
static tb_bool_t tb_dns_looker_resp_done(tb_dns_looker_t* looker, tb_ipaddr_ref_t addr)
{
// the rpkt and size
tb_byte_t const* rpkt = tb_static_buffer_data(&looker->rpkt);
tb_size_t size = tb_static_buffer_size(&looker->rpkt);
tb_assert_and_check_return_val(rpkt && size >= TB_DNS_HEADER_SIZE, tb_false);
// init stream
tb_static_stream_t stream;
tb_static_stream_init(&stream, (tb_byte_t*)rpkt, size);
// init header
tb_dns_header_t header;
header.id = tb_static_stream_read_u16_be(&stream); tb_static_stream_skip(&stream, 2);
header.question = tb_static_stream_read_u16_be(&stream);
header.answer = tb_static_stream_read_u16_be(&stream);
header.authority = tb_static_stream_read_u16_be(&stream);
header.resource = tb_static_stream_read_u16_be(&stream);
// trace
tb_trace_d("response: size: %u", size);
tb_trace_d("response: id: 0x%04x", header.id);
tb_trace_d("response: question: %d", header.question);
tb_trace_d("response: answer: %d", header.answer);
tb_trace_d("response: authority: %d", header.authority);
tb_trace_d("response: resource: %d", header.resource);
tb_trace_d("");
// check header
tb_assert_and_check_return_val(header.id == TB_DNS_HEADER_MAGIC, tb_false);
// skip questions, only one question now.
// name + question1 + question2 + ...
tb_assert_and_check_return_val(header.question == 1, tb_false);
#if 1
tb_static_stream_skip_cstr(&stream);
tb_static_stream_skip(&stream, 4);
#else
tb_char_t* name = tb_static_stream_read_cstr(&stream);
//name = tb_dns_decode_name(name);
tb_assert_and_check_return_val(name, tb_false);
tb_static_stream_skip(&stream, 4);
tb_trace_d("response: name: %s", name);
#endif
// decode answers
tb_size_t i = 0;
tb_size_t found = 0;
for (i = 0; i < header.answer; i++)
{
// decode answer
tb_dns_answer_t answer;
tb_trace_d("response: answer: %d", i);
// decode dns name
tb_char_t const* name = tb_dns_decode_name(&stream, answer.name); tb_used(name);
tb_trace_d("response: name: %s", name);
// decode resource
answer.res.type = tb_static_stream_read_u16_be(&stream);
answer.res.class_ = tb_static_stream_read_u16_be(&stream);
answer.res.ttl = tb_static_stream_read_u32_be(&stream);
answer.res.size = tb_static_stream_read_u16_be(&stream);
tb_trace_d("response: type: %d", answer.res.type);
tb_trace_d("response: class: %d", answer.res.class_);
tb_trace_d("response: ttl: %d", answer.res.ttl);
tb_trace_d("response: size: %d", answer.res.size);
// is ipv4?
if (answer.res.type == 1)
{
// get ipv4
tb_byte_t b1 = tb_static_stream_read_u8(&stream);
tb_byte_t b2 = tb_static_stream_read_u8(&stream);
tb_byte_t b3 = tb_static_stream_read_u8(&stream);
tb_byte_t b4 = tb_static_stream_read_u8(&stream);
// trace
tb_trace_d("response: ipv4: %u.%u.%u.%u", b1, b2, b3, b4);
// save the first ip
if (!found)
{
// save it
if (addr)
{
// init ipv4
tb_ipv4_t ipv4;
ipv4.u8[0] = b1;
ipv4.u8[1] = b2;
ipv4.u8[2] = b3;
ipv4.u8[3] = b4;
// save ipv4
tb_ipaddr_ipv4_set(addr, &ipv4);
}
// found it
found = 1;
// trace
tb_trace_d("response: ");
break;
}
}
else
{
// decode rdata
answer.rdata = (tb_byte_t*)tb_dns_decode_name(&stream, answer.name);
// trace
tb_trace_d("response: alias: %s", answer.rdata? (tb_char_t const*)answer.rdata : "");
}
// trace
tb_trace_d("response: ");
}
// found it?
tb_check_return_val(found, tb_false);
#if 0
// decode authorities
for (i = 0; i < header.authority; i++)
{
// decode answer
tb_dns_answer_t answer;
tb_trace_d("response: authority: %d", i);
// decode dns name
tb_char_t* name = tb_dns_decode_name(&stream, answer.name);
tb_trace_d("response: name: %s", name? name : "");
// decode resource
answer.res.type = tb_static_stream_read_u16_be(&stream);
answer.res.class_ = tb_static_stream_read_u16_be(&stream);
answer.res.ttl = tb_static_stream_read_u32_be(&stream);
answer.res.size = tb_static_stream_read_u16_be(&stream);
tb_trace_d("response: type: %d", answer.res.type);
tb_trace_d("response: class: %d", answer.res.class_);
tb_trace_d("response: ttl: %d", answer.res.ttl);
tb_trace_d("response: size: %d", answer.res.size);
// is ipv4?
if (answer.res.type == 1)
{
tb_byte_t b1 = tb_static_stream_read_u8(&stream);
tb_byte_t b2 = tb_static_stream_read_u8(&stream);
tb_byte_t b3 = tb_static_stream_read_u8(&stream);
tb_byte_t b4 = tb_static_stream_read_u8(&stream);
tb_trace_d("response: ipv4: %u.%u.%u.%u", b1, b2, b3, b4);
}
else
{
// decode data
answer.rdata = tb_dns_decode_name(&stream, answer.name);
tb_trace_d("response: server: %s", answer.rdata? answer.rdata : "");
}
tb_trace_d("response: ");
}
for (i = 0; i < header.resource; i++)
{
// decode answer
tb_dns_answer_t answer;
tb_trace_d("response: resource: %d", i);
// decode dns name
tb_char_t* name = tb_dns_decode_name(&stream, answer.name);
tb_trace_d("response: name: %s", name? name : "");
// decode resource
answer.res.type = tb_static_stream_read_u16_be(&stream);
answer.res.class_ = tb_static_stream_read_u16_be(&stream);
answer.res.ttl = tb_static_stream_read_u32_be(&stream);
answer.res.size = tb_static_stream_read_u16_be(&stream);
tb_trace_d("response: type: %d", answer.res.type);
tb_trace_d("response: class: %d", answer.res.class_);
tb_trace_d("response: ttl: %d", answer.res.ttl);
tb_trace_d("response: size: %d", answer.res.size);
// is ipv4?
if (answer.res.type == 1)
{
tb_byte_t b1 = tb_static_stream_read_u8(&stream);
tb_byte_t b2 = tb_static_stream_read_u8(&stream);
tb_byte_t b3 = tb_static_stream_read_u8(&stream);
tb_byte_t b4 = tb_static_stream_read_u8(&stream);
tb_trace_d("response: ipv4: %u.%u.%u.%u", b1, b2, b3, b4);
}
else
{
// decode data
answer.rdata = tb_dns_decode_name(&stream, answer.name);
tb_trace_d("response: alias: %s", answer.rdata? answer.rdata : "");
}
tb_trace_d("response: ");
}
#endif
// ok
return tb_true;
}
static tb_long_t tb_dns_looker_resp(tb_dns_looker_t* looker, tb_ipaddr_ref_t addr)
{
// check
tb_check_return_val(!(looker->step & TB_DNS_LOOKER_STEP_RESP), 1);
// need wait if no data
looker->step &= ~TB_DNS_LOOKER_STEP_NEVT;
// recv response data
tb_size_t size = tb_static_buffer_size(&looker->rpkt);
tb_size_t maxn = tb_static_buffer_maxn(&looker->rpkt);
tb_byte_t* data = tb_static_buffer_data(&looker->rpkt);
while (size < maxn)
{
// read data
tb_long_t read = tb_socket_urecv(looker->sock, tb_null, data + size, maxn - size);
tb_assert_and_check_return_val(read >= 0, -1);
// no data?
if (!read)
{
// end? read x, read 0
tb_check_break(!tb_static_buffer_size(&looker->rpkt));
// abort? read 0, read 0
tb_check_return_val(!looker->tryn, -1);
// tryn++
looker->tryn++;
// continue
return 0;
}
else looker->tryn = 0;
// update buffer size
tb_static_buffer_resize(&looker->rpkt, size + read);
size = tb_static_buffer_size(&looker->rpkt);
}
// done
if (!tb_dns_looker_resp_done(looker, addr)) return -1;
// check
tb_assert_and_check_return_val(tb_static_string_size(&looker->name) && !tb_ipaddr_ip_is_empty(addr), -1);
// save address to cache
tb_dns_cache_set(tb_static_string_cstr(&looker->name), addr);
// finish it
looker->step |= TB_DNS_LOOKER_STEP_RESP;
looker->tryn = 0;
// reset rpkt
looker->size = 0;
tb_static_buffer_clear(&looker->rpkt);
// ok
tb_trace_d("response: ok");
return 1;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_dns_looker_ref_t tb_dns_looker_init(tb_char_t const* name)
{
// check
tb_assert_and_check_return_val(name, tb_null);
// must be not address
tb_assert(!tb_ipaddr_ip_cstr_set(tb_null, name, TB_IPADDR_FAMILY_NONE));
// done
tb_bool_t ok = tb_false;
tb_dns_looker_t* looker = tb_null;
do
{
// make looker
looker = tb_malloc0_type(tb_dns_looker_t);
tb_assert_and_check_return_val(looker, tb_null);
// dump server
// tb_dns_server_dump();
// get the dns server list
looker->maxn = tb_dns_server_get(looker->list);
tb_check_break(looker->maxn && looker->maxn <= tb_arrayn(looker->list));
// init name
if (!tb_static_string_init(&looker->name, (tb_char_t*)looker->data, TB_DNS_NAME_MAXN)) break;
tb_static_string_cstrcpy(&looker->name, name);
// init rpkt
if (!tb_static_buffer_init(&looker->rpkt, looker->data + TB_DNS_NAME_MAXN, TB_DNS_RPKT_MAXN)) break;
// init family
looker->family = TB_IPADDR_FAMILY_IPV4;
// init sock
looker->sock = tb_socket_init(TB_SOCKET_TYPE_UDP, looker->family);
tb_assert_and_check_break(looker->sock);
// init itor
looker->itor = 1;
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (looker) tb_dns_looker_exit((tb_dns_looker_ref_t)looker);
looker = tb_null;
}
// ok?
return (tb_dns_looker_ref_t)looker;
}
tb_long_t tb_dns_looker_spak(tb_dns_looker_ref_t self, tb_ipaddr_ref_t addr)
{
// check
tb_dns_looker_t* looker = (tb_dns_looker_t*)self;
tb_assert_and_check_return_val(looker && addr, -1);
// init
tb_long_t r = -1;
do
{
// request
r = tb_dns_looker_reqt(looker);
tb_check_break(r > 0);
// response
r = tb_dns_looker_resp(looker, addr);
tb_check_break(r > 0);
} while (0);
// failed?
if (r < 0)
{
// next
if (looker->itor + 1 <= looker->maxn) looker->itor++;
else looker->itor = 0;
// has next?
if (looker->itor)
{
// reset step, no event now, need not wait
looker->step = TB_DNS_LOOKER_STEP_NONE | TB_DNS_LOOKER_STEP_NEVT;
// reset rpkt
looker->size = 0;
tb_static_buffer_clear(&looker->rpkt);
// continue
r = 0;
}
}
// ok?
return r;
}
tb_long_t tb_dns_looker_wait(tb_dns_looker_ref_t self, tb_long_t timeout)
{
// check
tb_dns_looker_t* looker = (tb_dns_looker_t*)self;
tb_assert_and_check_return_val(looker && looker->sock, -1);
// has io event?
tb_size_t e = TB_SOCKET_EVENT_NONE;
if (!(looker->step & TB_DNS_LOOKER_STEP_NEVT))
{
if (!(looker->step & TB_DNS_LOOKER_STEP_REQT)) e = TB_SOCKET_EVENT_SEND;
else if (!(looker->step & TB_DNS_LOOKER_STEP_RESP)) e = TB_SOCKET_EVENT_RECV;
}
// need wait?
tb_long_t r = 0;
if (e)
{
// trace
tb_trace_d("waiting %p ..", looker->sock);
// wait
r = tb_socket_wait(looker->sock, e, timeout);
// fail or timeout?
tb_check_return_val(r > 0, r);
}
// ok?
return r;
}
tb_void_t tb_dns_looker_exit(tb_dns_looker_ref_t self)
{
// the looker
tb_dns_looker_t* looker = (tb_dns_looker_t*)self;
if (looker)
{
// exit sock
if (looker->sock) tb_socket_exit(looker->sock);
looker->sock = tb_null;
// exit it
tb_free(looker);
}
}
tb_bool_t tb_dns_looker_done(tb_char_t const* name, tb_ipaddr_ref_t addr)
{
// check
tb_assert_and_check_return_val(name && addr, tb_false);
// try to lookup it from cache first
if (tb_dns_cache_get(name, addr)) return tb_true;
// init looker
tb_dns_looker_ref_t looker = tb_dns_looker_init(name);
tb_check_return_val(looker, tb_false);
// spak
tb_long_t r = -1;
while (!(r = tb_dns_looker_spak(looker, addr)))
{
// wait
r = tb_dns_looker_wait(looker, TB_DNS_LOOKER_TIMEOUT);
tb_assert_and_check_break(r >= 0);
}
// exit
tb_dns_looker_exit(looker);
// ok
return r > 0? tb_true : tb_false;
}
tbox-1.7.6/src/tbox/network/dns/looker.h 0000664 0000000 0000000 00000004745 14671175054 0020211 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file looker.h
* @ingroup network
*
*/
#ifndef TB_NETWORK_DNS_LOOKER_H
#define TB_NETWORK_DNS_LOOKER_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the dns looker type
typedef __tb_typeref__(dns_looker);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init for looking ipv4 from the host name, non-block
*
* @param name the host name
*
* @return the looker handle
*/
tb_dns_looker_ref_t tb_dns_looker_init(tb_char_t const* name);
/*! spak the looker
*
* @param looker the looker
* @param addr the address
*
* @return 1: ok, 0: continue: -1: failed
*/
tb_long_t tb_dns_looker_spak(tb_dns_looker_ref_t looker, tb_ipaddr_ref_t addr);
/*! wait the looker
*
* @param looker the looker
* @param timeout the timeout
*
* @return 1: ok, 0: continue: -1: failed
*/
tb_long_t tb_dns_looker_wait(tb_dns_looker_ref_t looker, tb_long_t timeout);
/*! exit the looker
*
* @param looker the looker
*/
tb_void_t tb_dns_looker_exit(tb_dns_looker_ref_t looker);
/*! lookup address from the host name, block
*
* try to look it from cache first
*
* @param name the host name
* @param addr the address
*
* @return tb_true or tb_false
*/
tb_bool_t tb_dns_looker_done(tb_char_t const* name, tb_ipaddr_ref_t addr);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/network/dns/prefix.h 0000664 0000000 0000000 00000011723 14671175054 0020205 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_NETWORK_DNS_PREFIX_H
#define TB_NETWORK_DNS_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#include "../ipaddr.h"
#include "../../utils/utils.h"
#include "../../stream/static_stream.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the protocol header
#define TB_DNS_HEADER_SIZE (12)
#define TB_DNS_HEADER_MAGIC (0xbeef)
// the protocol port
#define TB_DNS_HOST_PORT (53)
// the name maximum size
#define TB_DNS_NAME_MAXN (256)
// the rpkt maximum size
#define TB_DNS_RPKT_MAXN (TB_DNS_HEADER_SIZE + TB_DNS_NAME_MAXN + 256)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the dns header type
typedef struct __tb_dns_header_t
{
tb_uint16_t id; // identification number
tb_uint16_t qr :1; // query/response flag
tb_uint16_t opcode :4; // purpose of message
tb_uint16_t aa :1; // authoritive answer
tb_uint16_t tc :1; // truncated message
tb_uint16_t rd :1; // recursion desired
tb_uint16_t ra :1; // recursion available
tb_uint16_t z :1; // its z! reserved
tb_uint16_t ad :1; // authenticated data
tb_uint16_t cd :1; // checking disabled
tb_uint16_t rcode :4; // response code
tb_uint16_t question; // number of question entries
tb_uint16_t answer; // number of answer entries
tb_uint16_t authority; // number of authority entries
tb_uint16_t resource; // number of resource entries
}tb_dns_header_t;
// the dns question type
typedef struct __tb_dns_question_t
{
tb_uint16_t type;
tb_uint16_t class_;
}tb_dns_question_t;
// the dns resource type
typedef struct __tb_dns_resource_t
{
tb_uint16_t type;
tb_uint16_t class_;
tb_uint32_t ttl;
tb_uint16_t size;
}tb_dns_resource_t;
// the dns answer type
typedef struct __tb_dns_answer_t
{
tb_char_t name[TB_DNS_NAME_MAXN];
tb_dns_resource_t res;
tb_byte_t const* rdata;
}tb_dns_answer_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* inlines
*/
// size + data, e.g. .www.google.com => 3www6google3com
static __tb_inline__ tb_char_t const* tb_dns_encode_name(tb_char_t* name)
{
tb_assert_and_check_return_val(name && name[0] == '.', tb_null);
// encode
tb_byte_t n = 0;
tb_char_t* b = name;
tb_char_t* p = name + 1;
while (*p)
{
if (*p == '.')
{
//*b = '0' + n;
*b = (tb_char_t)n;
n = 0;
b = p;
}
else n++;
p++;
}
//*b = '0' + n;
*b = n;
// ok
return name;
}
static __tb_inline__ tb_char_t const* tb_dns_decode_name_impl(tb_char_t const* sb, tb_char_t const* se, tb_char_t const* ps, tb_char_t** pd)
{
tb_char_t const* p = ps;
tb_char_t* q = *pd;
while (p < se)
{
tb_byte_t c = *p++;
if (!c) break;
// is pointer? 11xxxxxx xxxxxxxx
else if (c >= 0xc0)
{
tb_uint16_t pos = c;
pos &= ~0xc0;
pos <<= 8;
pos |= *p++;
tb_dns_decode_name_impl(sb, se, sb + pos, &q);
break;
}
// is ascii? 00xxxxxx
else
{
while (c--) *q++ = *p++;
*q++ = '.';
}
}
*pd = q;
return p;
}
static __tb_inline__ tb_char_t const* tb_dns_decode_name(tb_static_stream_ref_t sstream, tb_char_t* name)
{
tb_char_t* q = name;
tb_char_t* p = (tb_char_t*)tb_dns_decode_name_impl((tb_char_t const*)tb_static_stream_beg(sstream), (tb_char_t const*)tb_static_stream_end(sstream), (tb_char_t const*)tb_static_stream_pos(sstream), &q);
if (p)
{
tb_assert(q - name < TB_DNS_NAME_MAXN);
if (q > name && *(q - 1) == '.') *--q = '\0';
tb_static_stream_goto(sstream, (tb_byte_t*)p);
return name;
}
else return tb_null;
}
#endif
tbox-1.7.6/src/tbox/network/dns/server.c 0000664 0000000 0000000 00000034152 14671175054 0020212 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file server.c
* @ingroup network
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "dns_server"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "server.h"
#include "../../utils/utils.h"
#include "../../stream/stream.h"
#include "../../network/network.h"
#include "../../platform/platform.h"
#include "../../container/container.h"
#include "../../algorithm/algorithm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the dns server test timeout
#define TB_DNS_SERVER_TEST_TIMEOUT (500)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the dns server type
typedef struct __tb_dns_server_t
{
// the rate
tb_size_t rate;
// the addr
tb_ipaddr_t addr;
}tb_dns_server_t, *tb_dns_server_ref_t;
// the dns server list type
typedef struct __tb_dns_server_list_t
{
// is sorted?
tb_bool_t sort;
// the server list
tb_vector_ref_t list;
}tb_dns_server_list_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
// the lock
static tb_spinlock_t g_lock = TB_SPINLOCK_INIT;
// the server list
static tb_dns_server_list_t g_list = {0};
/* //////////////////////////////////////////////////////////////////////////////////////
* server
*/
static tb_long_t tb_dns_server_comp(tb_element_ref_t element, tb_cpointer_t litem, tb_cpointer_t ritem)
{
// check
tb_assert(litem && ritem);
// the rate
tb_size_t lrate = ((tb_dns_server_t const*)litem)->rate;
tb_size_t rrate = ((tb_dns_server_t const*)ritem)->rate;
// comp
return (lrate > rrate? 1 : (lrate < rrate? -1 : 0));
}
static tb_long_t tb_dns_server_test(tb_ipaddr_ref_t addr)
{
// check
tb_assert_and_check_return_val(addr && !tb_ipaddr_is_empty(addr), -1);
// done
tb_static_stream_t sstream;
tb_byte_t rpkt[TB_DNS_RPKT_MAXN];
tb_size_t size = 0;
tb_long_t rate = -1;
tb_socket_ref_t sock = tb_null;
do
{
// trace
tb_trace_d("test: %{ipaddr}: ..", addr);
// init sock
sock = tb_socket_init(TB_SOCKET_TYPE_UDP, tb_ipaddr_family(addr));
tb_assert_and_check_break(sock);
// init stream
tb_static_stream_init(&sstream, rpkt, TB_DNS_RPKT_MAXN);
// identification number
tb_static_stream_writ_u16_be(&sstream, TB_DNS_HEADER_MAGIC);
/* 0x2104: 0 0000 001 0000 0000
*
* tb_uint16_t qr :1; // query/response flag
* tb_uint16_t opcode :4; // purpose of message
* tb_uint16_t aa :1; // authoritive answer
* tb_uint16_t tc :1; // truncated message
* tb_uint16_t rd :1; // recursion desired
* tb_uint16_t ra :1; // recursion available
* tb_uint16_t z :1; // its z! reserved
* tb_uint16_t ad :1; // authenticated data
* tb_uint16_t cd :1; // checking disabled
* tb_uint16_t rcode :4; // response code
*
* this is a query
* this is a standard query
* not authoritive answer
* not truncated
* recursion desired
*
* recursion not available! hey we dont have it (lol)
*
*/
#if 1
tb_static_stream_writ_u16_be(&sstream, 0x0100);
#else
tb_static_stream_writ_u1(&sstream, 0); // this is a query
tb_static_stream_writ_ubits32(&sstream, 0, 4); // this is a standard query
tb_static_stream_writ_u1(&sstream, 0); // not authoritive answer
tb_static_stream_writ_u1(&sstream, 0); // not truncated
tb_static_stream_writ_u1(&sstream, 1); // recursion desired
tb_static_stream_writ_u1(&sstream, 0); // recursion not available! hey we dont have it (lol)
tb_static_stream_writ_u1(&sstream, 0);
tb_static_stream_writ_u1(&sstream, 0);
tb_static_stream_writ_u1(&sstream, 0);
tb_static_stream_writ_ubits32(&sstream, 0, 4);
#endif
/* we have only one question
*
* tb_uint16_t question; // number of question entries
* tb_uint16_t answer; // number of answer entries
* tb_uint16_t authority; // number of authority entries
* tb_uint16_t resource; // number of resource entries
*
*/
tb_static_stream_writ_u16_be(&sstream, 1);
tb_static_stream_writ_u16_be(&sstream, 0);
tb_static_stream_writ_u16_be(&sstream, 0);
tb_static_stream_writ_u16_be(&sstream, 0);
// set questions, see as tb_dns_question_t
// name + question1 + question2 + ...
tb_static_stream_writ_u8(&sstream, 3);
tb_static_stream_writ_u8(&sstream, 'w');
tb_static_stream_writ_u8(&sstream, 'w');
tb_static_stream_writ_u8(&sstream, 'w');
tb_static_stream_writ_u8(&sstream, 5);
tb_static_stream_writ_u8(&sstream, 't');
tb_static_stream_writ_u8(&sstream, 'b');
tb_static_stream_writ_u8(&sstream, 'o');
tb_static_stream_writ_u8(&sstream, 'o');
tb_static_stream_writ_u8(&sstream, 'x');
tb_static_stream_writ_u8(&sstream, 3);
tb_static_stream_writ_u8(&sstream, 'o');
tb_static_stream_writ_u8(&sstream, 'r');
tb_static_stream_writ_u8(&sstream, 'g');
tb_static_stream_writ_u8(&sstream, '\0');
// only one question now.
tb_static_stream_writ_u16_be(&sstream, 1); // we are requesting the ipv4 address
tb_static_stream_writ_u16_be(&sstream, 1); // it's internet (lol)
// size
size = tb_static_stream_offset(&sstream);
tb_assert_and_check_break(size);
// init time
tb_hong_t time = tb_cache_time_spak();
// se/nd request
tb_size_t writ = 0;
tb_bool_t fail = tb_false;
while (writ < size)
{
// writ data
tb_long_t real = tb_socket_usend(sock, addr, rpkt + writ, size - writ);
// trace
tb_trace_d("writ %ld", real);
// check
tb_check_break_state(real >= 0, fail, tb_true);
// no data?
if (!real)
{
// abort?
tb_check_break_state(!writ, fail, tb_true);
// wait
real = tb_socket_wait(sock, TB_SOCKET_EVENT_SEND, TB_DNS_SERVER_TEST_TIMEOUT);
// fail or timeout?
tb_check_break_state(real > 0, fail, tb_true);
}
else writ += real;
}
// failed?
tb_check_break(!fail);
// only recv id & answer, 8 bytes
tb_long_t read = 0;
while (read < 8)
{
// read data
tb_long_t r = tb_socket_urecv(sock, tb_null, rpkt + read, TB_DNS_RPKT_MAXN - read);
// trace
tb_trace_d("read %ld", r);
// check
tb_check_break(r >= 0);
// no data?
if (!r)
{
// end?
tb_check_break(!read);
// wait
r = tb_socket_wait(sock, TB_SOCKET_EVENT_RECV, TB_DNS_SERVER_TEST_TIMEOUT);
// trace
tb_trace_d("wait %ld", r);
// fail or timeout?
tb_check_break(r > 0);
}
else read += r;
}
// check
tb_check_break(read >= 8);
// check protocol
tb_size_t id = tb_bits_get_u16_be(rpkt);
tb_check_break(id == TB_DNS_HEADER_MAGIC);
// check answer
tb_size_t answer = tb_bits_get_u16_be(rpkt + 6);
tb_check_break(answer > 0);
// rate
rate = (tb_long_t)(tb_cache_time_spak() - time);
// ok
tb_trace_d("test: %{ipaddr} ok, rate: %u", addr, rate);
} while (0);
// exit sock
tb_socket_exit(sock);
// ok
return rate;
}
static tb_bool_t tb_dns_server_rate(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value)
{
// the server
tb_bool_t ok = tb_false;
tb_dns_server_ref_t server = (tb_dns_server_ref_t)item;
if (server && !server->rate)
{
// done
tb_bool_t done = tb_false;
do
{
// the server rate
tb_long_t rate = tb_dns_server_test(&server->addr);
tb_check_break(rate >= 0);
// save the server rate
server->rate = rate;
// ok
done = tb_true;
} while (0);
// failed? remove it
if (!done) ok = tb_true;
}
// ok?
return ok;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_dns_server_init()
{
// enter
tb_spinlock_enter(&g_lock);
// done
tb_bool_t ok = tb_false;
do
{
// init list
if (!g_list.list)
{
g_list.list = tb_vector_init(8, tb_element_mem(sizeof(tb_dns_server_t), tb_null, tb_null));
g_list.sort = tb_false;
}
tb_assert_and_check_break(g_list.list);
// ok
ok = tb_true;
} while (0);
// leave
tb_spinlock_leave(&g_lock);
// failed? exit it
if (!ok) tb_dns_server_exit();
// ok?
return ok;
}
tb_void_t tb_dns_server_exit()
{
// enter
tb_spinlock_enter(&g_lock);
// exit list
if (g_list.list) tb_vector_exit(g_list.list);
g_list.list = tb_null;
// exit sort
g_list.sort = tb_false;
// leave
tb_spinlock_leave(&g_lock);
}
tb_void_t tb_dns_server_dump()
{
// enter
tb_spinlock_enter(&g_lock);
// dump list
if (g_list.list)
{
// trace
tb_trace_i("============================================================");
tb_trace_i("list: %u servers", tb_vector_size(g_list.list));
// walk
tb_size_t i = 0;
tb_size_t n = tb_vector_size(g_list.list);
for (; i < n; i++)
{
tb_dns_server_t const* server = (tb_dns_server_t const*)tb_iterator_item(g_list.list, i);
if (server)
{
// trace
tb_trace_i("server: %{ipaddr}, rate: %u", &server->addr, server->rate);
}
}
}
// leave
tb_spinlock_leave(&g_lock);
}
tb_void_t tb_dns_server_sort()
{
// enter
tb_spinlock_enter(&g_lock);
// done
tb_vector_ref_t list = tb_null;
do
{
// check
tb_assert_and_check_break(g_list.list);
// need sort?
tb_check_break(!g_list.sort);
// init element
tb_element_t element = tb_element_mem(sizeof(tb_dns_server_t), tb_null, tb_null);
element.comp = tb_dns_server_comp;
// init list
list = tb_vector_init(8, element);
tb_assert_and_check_break(list);
// copy list
tb_vector_copy(list, g_list.list);
} while (0);
/* sort ok, only done once sort
* using the unsorted server list at the other thread if the sort have been not finished
*/
g_list.sort = tb_true;
// leave
tb_spinlock_leave(&g_lock);
// need sort?
tb_check_return(list);
// rate list and remove no-rate servers
tb_remove_if(list, tb_dns_server_rate, tb_null);
// sort list
tb_sort_all(list, tb_null);
// enter
tb_spinlock_enter(&g_lock);
// save the sorted server list
if (tb_vector_size(list)) tb_vector_copy(g_list.list, list);
else
{
// no faster server? using the previous server list
tb_trace_w("no faster server");
}
// leave
tb_spinlock_leave(&g_lock);
// exit list
tb_vector_exit(list);
}
tb_size_t tb_dns_server_get(tb_ipaddr_t addr[2])
{
// check
tb_assert_and_check_return_val(addr, 0);
// sort first
tb_dns_server_sort();
// enter
tb_spinlock_enter(&g_lock);
// done
tb_size_t ok = 0;
do
{
// check
tb_assert_and_check_break(g_list.list && g_list.sort);
// init
tb_size_t i = 0;
tb_size_t n = tb_min(tb_vector_size(g_list.list), 2);
tb_assert_and_check_break(n <= 2);
// done
for (; i < n; i++)
{
// the dns server
tb_dns_server_t const* server = (tb_dns_server_t const*)tb_iterator_item(g_list.list, i);
if (server)
{
// save addr
addr[ok++] = server->addr;
}
}
} while (0);
// leave
tb_spinlock_leave(&g_lock);
// trace
tb_assertf(ok, "no server!");
// ok?
return ok;
}
tb_void_t tb_dns_server_add(tb_char_t const* addr)
{
// check
tb_assert_and_check_return(addr);
// init first
tb_dns_server_init();
// enter
tb_spinlock_enter(&g_lock);
// done
do
{
// check
tb_assert_and_check_break(g_list.list);
// init server
tb_dns_server_t server = {0};
if (!tb_ipaddr_set(&server.addr, addr, TB_DNS_HOST_PORT, TB_IPADDR_FAMILY_NONE)) break;
// add server
tb_vector_insert_tail(g_list.list, &server);
// need sort it again
g_list.sort = tb_false;
} while (0);
// leave
tb_spinlock_leave(&g_lock);
}
tbox-1.7.6/src/tbox/network/dns/server.h 0000664 0000000 0000000 00000003706 14671175054 0020220 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file server.h
* @ingroup network
*
*/
#ifndef TB_NETWORK_DNS_SERVER_H
#define TB_NETWORK_DNS_SERVER_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init the server list
*
* @return tb_true or tb_false
*/
tb_bool_t tb_dns_server_init(tb_noarg_t);
/// exit the server list
tb_void_t tb_dns_server_exit(tb_noarg_t);
/// dump the server list
tb_void_t tb_dns_server_dump(tb_noarg_t);
/// sort the server list by the response speed
tb_void_t tb_dns_server_sort(tb_noarg_t);
/*! get the server
*
* @param addr the server address list, addr[0] is the fastest
*
* @return the server size
*/
tb_size_t tb_dns_server_get(tb_ipaddr_t addr[2]);
/*! add the server
*
* @param addr the server address
*/
tb_void_t tb_dns_server_add(tb_char_t const* addr);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/network/http.c 0000664 0000000 0000000 00000075225 14671175054 0017105 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file http.c
* @ingroup network
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "http"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "http.h"
#include "impl/http/date.h"
#include "impl/http/option.h"
#include "impl/http/status.h"
#include "impl/http/method.h"
#include "../zip/zip.h"
#include "../libc/libc.h"
#include "../math/math.h"
#include "../utils/utils.h"
#include "../string/string.h"
#include "../stream/stream.h"
#include "../platform/platform.h"
#include "../algorithm/algorithm.h"
#include "../container/container.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the http type
typedef struct __tb_http_t
{
// the option
tb_http_option_t option;
// the status
tb_http_status_t status;
// the stream
tb_stream_ref_t stream;
// the sstream for sock
tb_stream_ref_t sstream;
// the cstream for chunked
tb_stream_ref_t cstream;
// the zstream for gzip/deflate
tb_stream_ref_t zstream;
// the head
tb_hash_map_ref_t head;
// is opened?
tb_bool_t bopened;
// the request data
tb_string_t request;
// the cookies
tb_string_t cookies;
// the request/response data for decreasing stack size
tb_char_t data[8192];
}tb_http_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_bool_t tb_http_connect(tb_http_t* http)
{
// check
tb_assert_and_check_return_val(http && http->stream, tb_false);
// done
tb_bool_t ok = tb_false;
do
{
// the host is changed?
tb_bool_t host_changed = tb_true;
tb_char_t const* host_old = tb_null;
tb_char_t const* host_new = tb_url_host(&http->option.url);
tb_stream_ctrl(http->stream, TB_STREAM_CTRL_GET_HOST, &host_old);
if (host_old && host_new && !tb_stricmp(host_old, host_new)) host_changed = tb_false;
// trace
tb_trace_d("connect: host: %s", host_changed? "changed" : "keep");
// set url and timeout
if (!tb_stream_ctrl(http->stream, TB_STREAM_CTRL_SET_URL, tb_url_cstr(&http->option.url))) break;
if (!tb_stream_ctrl(http->stream, TB_STREAM_CTRL_SET_TIMEOUT, http->option.timeout)) break;
// reset keep-alive and close socket first before connecting anthor host
if (host_changed && !tb_stream_ctrl(http->stream, TB_STREAM_CTRL_SOCK_KEEP_ALIVE, tb_false)) break;
// dump option
#if defined(__tb_debug__) && TB_TRACE_MODULE_DEBUG
tb_http_option_dump(&http->option);
#endif
// trace
tb_trace_d("connect: ..");
// clear status
tb_http_status_cler(&http->status, host_changed);
// open stream
if (!tb_stream_open(http->stream)) break;
// ok
ok = tb_true;
} while (0);
// failed? save state
if (!ok) http->status.state = tb_stream_state(http->stream);
// trace
tb_trace_d("connect: %s, state: %s", ok? "ok" : "failed", tb_state_cstr(http->status.state));
// ok?
return ok;
}
static tb_bool_t tb_http_request_post(tb_size_t state, tb_hize_t offset, tb_hong_t size, tb_hize_t save, tb_size_t rate, tb_cpointer_t priv)
{
// check
tb_http_t* http = (tb_http_t*)priv;
tb_assert_and_check_return_val(http && http->stream, tb_false);
// trace
tb_trace_d("post: percent: %llu%%, size: %lu, state: %s", size > 0? (offset * 100 / size) : 0, save, tb_state_cstr(state));
// done func
if (http->option.post_func && !http->option.post_func(state, offset, size, save, rate, http->option.post_priv))
return tb_false;
// ok?
return tb_true;
}
static tb_bool_t tb_http_request(tb_http_t* http)
{
// check
tb_assert_and_check_return_val(http && http->stream, tb_false);
// done
tb_bool_t ok = tb_false;
tb_stream_ref_t pstream = tb_null;
tb_hong_t post_size = 0;
do
{
// clear line data
tb_string_clear(&http->request);
// init the head value
tb_static_string_t value;
if (!tb_static_string_init(&value, http->data, sizeof(http->data))) break;
// init method
tb_char_t const* method = tb_http_method_cstr(http->option.method);
tb_assert_and_check_break(method);
// init path
tb_char_t const* path = tb_url_path(&http->option.url);
tb_assert_and_check_break(path);
// init args
tb_char_t const* args = tb_url_args(&http->option.url);
// init host
tb_char_t const* host = tb_url_host(&http->option.url);
tb_assert_and_check_break(host);
tb_hash_map_insert(http->head, "Host", host);
// init accept
tb_hash_map_insert(http->head, "Accept", "*/*");
// init connection
tb_hash_map_insert(http->head, "Connection", http->status.balived? "keep-alive" : "close");
// init cookies
tb_bool_t cookie = tb_false;
if (http->option.cookies)
{
// set cookie
if (tb_cookies_get(http->option.cookies, host, path, tb_url_ssl(&http->option.url), &http->cookies))
{
tb_hash_map_insert(http->head, "Cookie", tb_string_cstr(&http->cookies));
cookie = tb_true;
}
}
// no cookie? remove it
if (!cookie) tb_hash_map_remove(http->head, "Cookie");
// init range
if (http->option.range.bof && http->option.range.eof >= http->option.range.bof)
tb_static_string_cstrfcpy(&value, "bytes=%llu-%llu", http->option.range.bof, http->option.range.eof);
else if (http->option.range.bof && !http->option.range.eof)
tb_static_string_cstrfcpy(&value, "bytes=%llu-", http->option.range.bof);
else if (!http->option.range.bof && http->option.range.eof)
tb_static_string_cstrfcpy(&value, "bytes=0-%llu", http->option.range.eof);
else if (http->option.range.bof > http->option.range.eof)
{
http->status.state = TB_STATE_HTTP_RANGE_INVALID;
break;
}
// update range
if (tb_static_string_size(&value))
tb_hash_map_insert(http->head, "Range", tb_static_string_cstr(&value));
// remove range
else tb_hash_map_remove(http->head, "Range");
// init post
if (http->option.method == TB_HTTP_METHOD_POST)
{
// done
tb_bool_t post_ok = tb_false;
do
{
// init pstream
tb_char_t const* url = tb_url_cstr(&http->option.post_url);
if (http->option.post_data && http->option.post_size)
pstream = tb_stream_init_from_data(http->option.post_data, http->option.post_size);
else if (url) pstream = tb_stream_init_from_url(url);
tb_assert_and_check_break(pstream);
// open pstream
if (!tb_stream_open(pstream)) break;
// the post size
post_size = tb_stream_size(pstream);
tb_assert_and_check_break(post_size >= 0);
// append post size
tb_static_string_cstrfcpy(&value, "%lld", post_size);
tb_hash_map_insert(http->head, "Content-Length", tb_static_string_cstr(&value));
// ok
post_ok = tb_true;
} while (0);
// init post failed?
if (!post_ok)
{
http->status.state = TB_STATE_HTTP_POST_FAILED;
break;
}
}
// remove post
else tb_hash_map_remove(http->head, "Content-Length");
// replace the custom head
tb_char_t const* head_data = (tb_char_t const*)tb_buffer_data(&http->option.head_data);
tb_char_t const* head_tail = head_data + tb_buffer_size(&http->option.head_data);
while (head_data < head_tail)
{
// the name and data
tb_char_t const* name = head_data;
tb_char_t const* data = head_data + tb_strlen(name) + 1;
tb_check_break(data < head_tail);
// replace it
tb_hash_map_insert(http->head, name, data);
// next
head_data = data + tb_strlen(data) + 1;
}
// exit the head value
tb_static_string_exit(&value);
// check head
tb_assert_and_check_break(tb_hash_map_size(http->head));
// append method
tb_string_cstrcat(&http->request, method);
// append ' '
tb_string_chrcat(&http->request, ' ');
// encode path
tb_url_encode2(path, tb_strlen(path), http->data, sizeof(http->data) - 1);
path = http->data;
// append path
tb_string_cstrcat(&http->request, path);
// append args if exists
if (args)
{
// append '?'
tb_string_chrcat(&http->request, '?');
// encode args
tb_url_encode2(args, tb_strlen(args), http->data, sizeof(http->data) - 1);
args = http->data;
// append args
tb_string_cstrcat(&http->request, args);
}
// append ' '
tb_string_chrcat(&http->request, ' ');
// append version, HTTP/1.1
tb_string_cstrfcat(&http->request, "HTTP/1.%1u\r\n", http->status.balived? http->status.version : http->option.version);
// append key: value
tb_for_all (tb_hash_map_item_ref_t, item, http->head)
{
if (item && item->name && item->data)
tb_string_cstrfcat(&http->request, "%s: %s\r\n", (tb_char_t const*)item->name, (tb_char_t const*)item->data);
}
// append end
tb_string_cstrcat(&http->request, "\r\n");
// the request data and size
tb_char_t const* request_data = tb_string_cstr(&http->request);
tb_size_t request_size = tb_string_size(&http->request);
tb_assert_and_check_break(request_data && request_size);
// trace
tb_trace_d("request[%lu]:\n%s", request_size, request_data);
// writ request
if (!tb_stream_bwrit(http->stream, (tb_byte_t const*)request_data, request_size)) break;
// writ post
if (http->option.method == TB_HTTP_METHOD_POST)
{
// post stream
if (tb_transfer(pstream, http->stream, http->option.post_lrate, tb_http_request_post, http) != post_size)
{
http->status.state = TB_STATE_HTTP_POST_FAILED;
break;
}
}
// sync request
if (!tb_stream_sync(http->stream, tb_false)) break;
// ok
ok = tb_true;
}
while (0);
// failed?
if (!ok && !http->status.state) http->status.state = TB_STATE_HTTP_REQUEST_FAILED;
// exit pstream
if (pstream) tb_stream_exit(pstream);
pstream = tb_null;
// ok?
return ok;
}
/*
* HTTP/1.1 206 Partial Content
* Date: Fri, 23 Apr 2010 05:25:45 GMT
* Server: Apache/2.2.9 (Ubuntu) PHP/5.2.6-2ubuntu4.5 with Suhosin-Patch
* Last-Modified: Mon, 08 Mar 2010 09:58:09 GMT
* ETag: "6cc014-8f47f-481471a322e40"
* Accept-Ranges: bytes
* Content-Length: 586879
* Content-Range: bytes 0-586878/586879
* Connection: close
* Content-Type: application/x-shockwave-flash
*/
static tb_bool_t tb_http_response_done(tb_http_t* http, tb_char_t const* line, tb_size_t indx)
{
// check
tb_assert_and_check_return_val(http && http->sstream && line, tb_false);
// the first line?
tb_char_t const* p = line;
if (!indx)
{
// check http response
if (tb_strnicmp(p, "HTTP/1.", 7))
{
// failed
tb_assert(0);
return tb_false;
}
// seek to the http version
p += 7;
tb_assert_and_check_return_val(*p, tb_false);
// parse version
tb_assert_and_check_return_val((*p - '0') < 2, tb_false);
http->status.version = *p - '0';
// seek to the http code
p++; while (tb_isspace(*p)) p++;
// parse code
tb_assert_and_check_return_val(*p && tb_isdigit(*p), tb_false);
http->status.code = tb_stou32(p);
// save state
if (http->status.code == 200 || http->status.code == 206)
http->status.state = TB_STATE_OK;
else if (http->status.code == 204)
http->status.state = TB_STATE_HTTP_RESPONSE_204;
else if (http->status.code >= 300 && http->status.code <= 307)
http->status.state = TB_STATE_HTTP_RESPONSE_300 + (http->status.code - 300);
else if (http->status.code >= 400 && http->status.code <= 416)
http->status.state = TB_STATE_HTTP_RESPONSE_400 + (http->status.code - 400);
else if (http->status.code >= 500 && http->status.code <= 507)
http->status.state = TB_STATE_HTTP_RESPONSE_500 + (http->status.code - 500);
else http->status.state = TB_STATE_HTTP_RESPONSE_UNK;
// check state code: 4xx & 5xx
if (http->status.code >= 400 && http->status.code < 600) return tb_false;
}
// key: value?
else
{
// seek to value
while (*p && *p != ':') p++;
tb_assert_and_check_return_val(*p, tb_false);
p++; while (*p && tb_isspace(*p)) p++;
// no value
tb_check_return_val(*p, tb_true);
// parse content size
if (!tb_strnicmp(line, "Content-Length", 14))
{
http->status.content_size = tb_stou64(p);
if (http->status.document_size < 0)
http->status.document_size = http->status.content_size;
}
// parse content range: "bytes $from-$to/$document_size"
else if (!tb_strnicmp(line, "Content-Range", 13))
{
tb_hize_t from = 0;
tb_hize_t to = 0;
tb_hize_t document_size = 0;
if (!tb_strncmp(p, "bytes ", 6))
{
p += 6;
from = tb_stou64(p);
while (*p && *p != '-') p++;
if (*p && *p++ == '-') to = tb_stou64(p);
while (*p && *p != '/') p++;
if (*p && *p++ == '/') document_size = tb_stou64(p);
}
// no stream, be able to seek
http->status.bseeked = 1;
http->status.document_size = document_size;
if (http->status.content_size < 0)
{
if (from && to > from) http->status.content_size = to - from;
else if (!from && to) http->status.content_size = to;
else if (from && !to && document_size > from) http->status.content_size = document_size - from;
else http->status.content_size = document_size;
}
}
// parse accept-ranges: "bytes "
else if (!tb_strnicmp(line, "Accept-Ranges", 13))
{
// no stream, be able to seek
http->status.bseeked = 1;
}
// parse content type
else if (!tb_strnicmp(line, "Content-Type", 12))
{
tb_string_cstrcpy(&http->status.content_type, p);
tb_assert_and_check_return_val(tb_string_size(&http->status.content_type), tb_false);
}
// parse transfer encoding
else if (!tb_strnicmp(line, "Transfer-Encoding", 17))
{
if (!tb_stricmp(p, "chunked")) http->status.bchunked = 1;
}
// parse content encoding
else if (!tb_strnicmp(line, "Content-Encoding", 16))
{
if (!tb_stricmp(p, "gzip")) http->status.bgzip = 1;
else if (!tb_stricmp(p, "deflate")) http->status.bdeflate = 1;
}
// parse location
else if (!tb_strnicmp(line, "Location", 8))
{
// redirect? check code: 301 - 307
tb_assert_and_check_return_val(http->status.code > 300 && http->status.code < 308, tb_false);
// save location
tb_string_cstrcpy(&http->status.location, p);
}
// parse connection
else if (!tb_strnicmp(line, "Connection", 10))
{
// keep alive?
http->status.balived = !tb_stricmp(p, "close")? 0 : 1;
// ctrl stream for sock
if (!tb_stream_ctrl(http->sstream, TB_STREAM_CTRL_SOCK_KEEP_ALIVE, http->status.balived? tb_true : tb_false)) return tb_false;
}
// parse cookies
else if (http->option.cookies && !tb_strnicmp(line, "Set-Cookie", 10))
{
// the host
tb_char_t const* host = tb_null;
tb_http_ctrl((tb_http_ref_t)http, TB_HTTP_OPTION_GET_HOST, &host);
// the path
tb_char_t const* path = tb_null;
tb_http_ctrl((tb_http_ref_t)http, TB_HTTP_OPTION_GET_PATH, &path);
// is ssl?
tb_bool_t bssl = tb_false;
tb_http_ctrl((tb_http_ref_t)http, TB_HTTP_OPTION_GET_SSL, &bssl);
// set cookies
tb_cookies_set(http->option.cookies, host, path, bssl, p);
}
}
// ok
return tb_true;
}
static tb_bool_t tb_http_response(tb_http_t* http)
{
// check
tb_assert_and_check_return_val(http && http->stream, tb_false);
// done
tb_bool_t ok = tb_false;
do
{
// read line
tb_long_t real = 0;
tb_size_t indx = 0;
while ((real = tb_stream_bread_line(http->stream, http->data, sizeof(http->data) - 1)) >= 0)
{
// trace
tb_trace_d("response: %s", http->data);
// do callback
if (http->option.head_func && !http->option.head_func(http->data, http->option.head_priv)) break;
// end?
if (!real)
{
// switch to cstream if chunked
if (http->status.bchunked)
{
// init cstream
if (http->cstream)
{
if (!tb_stream_ctrl(http->cstream, TB_STREAM_CTRL_FLTR_SET_STREAM, http->stream)) break;
}
else http->cstream = tb_stream_init_filter_from_chunked(http->stream, tb_true);
tb_assert_and_check_break(http->cstream);
// open cstream, need not async
if (!tb_stream_open(http->cstream)) break;
// using cstream
http->stream = http->cstream;
// disable seek
http->status.bseeked = 0;
}
// switch to zstream if gzip or deflate
if (http->option.bunzip && (http->status.bgzip || http->status.bdeflate))
{
#if defined(TB_CONFIG_PACKAGE_HAVE_ZLIB) && defined(TB_CONFIG_MODULE_HAVE_ZIP)
// init zstream
if (http->zstream)
{
if (!tb_stream_ctrl(http->zstream, TB_STREAM_CTRL_FLTR_SET_STREAM, http->stream)) break;
}
else http->zstream = tb_stream_init_filter_from_zip(http->stream, http->status.bgzip? TB_ZIP_ALGO_GZIP : TB_ZIP_ALGO_ZLIB, TB_ZIP_ACTION_INFLATE);
tb_assert_and_check_break(http->zstream);
// the filter
tb_filter_ref_t filter = tb_null;
if (!tb_stream_ctrl(http->zstream, TB_STREAM_CTRL_FLTR_GET_FILTER, &filter)) break;
tb_assert_and_check_break(filter);
// ctrl filter
if (!tb_filter_ctrl(filter, TB_FILTER_CTRL_ZIP_SET_ALGO, http->status.bgzip? TB_ZIP_ALGO_GZIP : TB_ZIP_ALGO_ZLIB, TB_ZIP_ACTION_INFLATE)) break;
// limit the filter input size
if (http->status.content_size > 0) tb_filter_limit(filter, http->status.content_size);
// open zstream, need not async
if (!tb_stream_open(http->zstream)) break;
// using zstream
http->stream = http->zstream;
// disable seek
http->status.bseeked = 0;
#else
// trace
tb_trace_w("gzip is not supported now! please enable it from config if you need it.");
// not supported
http->status.state = TB_STATE_HTTP_GZIP_NOT_SUPPORTED;
break;
#endif
}
// trace
tb_trace_d("response: ok");
// dump status
#if defined(__tb_debug__) && TB_TRACE_MODULE_DEBUG
tb_http_status_dump(&http->status);
#endif
// ok
ok = tb_true;
break;
}
// done it
if (!tb_http_response_done(http, http->data, indx++)) break;
}
} while (0);
// ok?
return ok;
}
static tb_bool_t tb_http_redirect(tb_http_t* http)
{
// check
tb_assert_and_check_return_val(http && http->stream, tb_false);
// done
tb_size_t i = 0;
tb_bool_t ok = tb_true;
for (i = 0; i < http->option.redirect && tb_string_size(&http->status.location); i++)
{
// read the redirect content
if (http->status.content_size > 0)
{
tb_byte_t data[TB_STREAM_BLOCK_MAXN];
tb_hize_t read = 0;
tb_hize_t size = http->status.content_size;
while (read < size)
{
// the need
tb_size_t need = (tb_size_t)tb_min(size - read, (tb_hize_t)TB_STREAM_BLOCK_MAXN);
// read it
if (!tb_stream_bread(http->stream, data, need)) break;
// save size
read += need;
}
// check
tb_assert_pass_and_check_break(read == size);
}
// close stream
if (http->stream && !tb_stream_clos(http->stream)) break;
// switch to sstream
http->stream = http->sstream;
// get location url
tb_char_t const* location = tb_string_cstr(&http->status.location);
tb_assert_and_check_break(location);
// trace
tb_trace_d("redirect: %s", location);
// only path?
tb_size_t protocol = tb_url_protocol_probe(location);
if (protocol == TB_URL_PROTOCOL_FILE) tb_url_path_set(&http->option.url, location);
// full http url?
else if (protocol == TB_URL_PROTOCOL_HTTP)
{
// set url
if (!tb_url_cstr_set(&http->option.url, location)) break;
}
else
{
// trace
tb_trace_e("unsupported protocol for location %s", location);
break;
}
// connect it
if (!(ok = tb_http_connect(http))) break;
// request it
if (!(ok = tb_http_request(http))) break;
// response it
if (!(ok = tb_http_response(http))) break;
}
// ok?
return ok && !tb_string_size(&http->status.location);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_http_ref_t tb_http_init()
{
// done
tb_bool_t ok = tb_false;
tb_http_t* http = tb_null;
do
{
// make http
http = tb_malloc0_type(tb_http_t);
tb_assert_and_check_break(http);
// init stream
http->stream = http->sstream = tb_stream_init_sock();
tb_assert_and_check_break(http->stream);
// init head
http->head = tb_hash_map_init(8, tb_element_str(tb_false), tb_element_str(tb_false));
tb_assert_and_check_break(http->head);
// init request data
if (!tb_string_init(&http->request)) break;
// init cookies data
if (!tb_string_init(&http->cookies)) break;
// init option
if (!tb_http_option_init(&http->option)) break;
// init status
if (!tb_http_status_init(&http->status)) break;
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
if (http) tb_http_exit((tb_http_ref_t)http);
http = tb_null;
}
// ok?
return (tb_http_ref_t)http;
}
tb_void_t tb_http_kill(tb_http_ref_t self)
{
// check
tb_http_t* http = (tb_http_t*)self;
tb_assert_and_check_return(http);
// kill stream
if (http->stream) tb_stream_kill(http->stream);
}
tb_void_t tb_http_exit(tb_http_ref_t self)
{
// check
tb_http_t* http = (tb_http_t*)self;
tb_assert_and_check_return(http);
// close it
tb_http_close(self);
// exit zstream
if (http->zstream) tb_stream_exit(http->zstream);
http->zstream = tb_null;
// exit cstream
if (http->cstream) tb_stream_exit(http->cstream);
http->cstream = tb_null;
// exit sstream
if (http->sstream) tb_stream_exit(http->sstream);
http->sstream = tb_null;
// exit stream
http->stream = tb_null;
// exit status
tb_http_status_exit(&http->status);
// exit option
tb_http_option_exit(&http->option);
// exit cookies data
tb_string_exit(&http->cookies);
// exit request data
tb_string_exit(&http->request);
// exit head
if (http->head) tb_hash_map_exit(http->head);
http->head = tb_null;
// free it
tb_free(http);
}
tb_long_t tb_http_wait(tb_http_ref_t self, tb_size_t events, tb_long_t timeout)
{
// check
tb_http_t* http = (tb_http_t*)self;
tb_assert_and_check_return_val(http && http->stream, -1);
// opened?
tb_assert_and_check_return_val(http->bopened, -1);
// wait it
tb_long_t wait = tb_stream_wait(http->stream, events, timeout);
// failed? save state
if (wait < 0 && !http->status.state) http->status.state = tb_stream_state(http->stream);
// ok?
return wait;
}
tb_bool_t tb_http_open(tb_http_ref_t self)
{
// check
tb_http_t* http = (tb_http_t*)self;
tb_assert_and_check_return_val(http, tb_false);
// opened?
tb_assert_and_check_return_val(!http->bopened, tb_false);
// done
tb_bool_t ok = tb_false;
do
{
// connect it
if (!tb_http_connect(http)) break;
// request it
if (!tb_http_request(http)) break;
// response it
if (!tb_http_response(http)) break;
// redirect it
if (!tb_http_redirect(http)) break;
// ok
ok = tb_true;
} while (0);
// failed? close it
if (!ok)
{
// close stream
if (http->stream) tb_stream_clos(http->stream);
// switch to sstream
http->stream = http->sstream;
}
// is opened?
http->bopened = ok;
// ok?
return ok;
}
tb_bool_t tb_http_close(tb_http_ref_t self)
{
// check
tb_http_t* http = (tb_http_t*)self;
tb_assert_and_check_return_val(http, tb_false);
// opened?
tb_check_return_val(http->bopened, tb_true);
// close stream
if (http->stream && !tb_stream_clos(http->stream)) return tb_false;
// switch to sstream
http->stream = http->sstream;
// clear opened
http->bopened = tb_false;
// ok
return tb_true;
}
tb_bool_t tb_http_seek(tb_http_ref_t self, tb_hize_t offset)
{
// check
tb_http_t* http = (tb_http_t*)self;
tb_assert_and_check_return_val(http, tb_false);
// opened?
tb_assert_and_check_return_val(http->bopened, tb_false);
// seeked?
tb_check_return_val(http->status.bseeked, tb_false);
// done
tb_bool_t ok = tb_false;
do
{
// close stream
if (http->stream && !tb_stream_clos(http->stream)) break;
// switch to sstream
http->stream = http->sstream;
// trace
tb_trace_d("seek: %llu", offset);
// set range
http->option.range.bof = offset;
http->option.range.eof = http->status.document_size > 0? http->status.document_size - 1 : 0;
// connect it
if (!tb_http_connect(http)) break;
// request it
if (!tb_http_request(http)) break;
// response it
if (!tb_http_response(http)) break;
// ok
ok = tb_true;
} while (0);
// ok?
return ok;
}
tb_long_t tb_http_read(tb_http_ref_t self, tb_byte_t* data, tb_size_t size)
{
// check
tb_http_t* http = (tb_http_t*)self;
tb_assert_and_check_return_val(http && http->stream, -1);
// opened?
tb_assert_and_check_return_val(http->bopened, -1);
// read
return tb_stream_read(http->stream, data, size);
}
tb_bool_t tb_http_bread(tb_http_ref_t self, tb_byte_t* data, tb_size_t size)
{
// check
tb_http_t* http = (tb_http_t*)self;
tb_assert_and_check_return_val(http && http->stream, tb_false);
// opened?
tb_assert_and_check_return_val(http->bopened, tb_false);
// read
tb_size_t read = 0;
while (read < size)
{
// read data
tb_long_t real = tb_stream_read(http->stream, data + read, size - read);
// update size
if (real > 0) read += real;
// no data?
else if (!real)
{
// wait
tb_long_t e = tb_http_wait(self, TB_SOCKET_EVENT_RECV, http->option.timeout);
tb_assert_and_check_break(e >= 0);
// timeout?
tb_check_break(e);
// has read?
tb_assert_and_check_break(e & TB_SOCKET_EVENT_RECV);
}
else break;
}
// ok?
return read == size? tb_true : tb_false;
}
tb_bool_t tb_http_ctrl(tb_http_ref_t self, tb_size_t option, ...)
{
// check
tb_http_t* http = (tb_http_t*)self;
tb_assert_and_check_return_val(http && option, tb_false);
// check
if (TB_HTTP_OPTION_CODE_IS_SET(option) && http->bopened)
{
// abort
tb_assert(0);
return tb_false;
}
// init args
tb_va_list_t args;
tb_va_start(args, option);
// done
tb_bool_t ok = tb_http_option_ctrl(&http->option, option, args);
// exit args
tb_va_end(args);
// ok?
return ok;
}
tb_http_status_t const* tb_http_status(tb_http_ref_t self)
{
// check
tb_http_t* http = (tb_http_t*)self;
tb_assert_and_check_return_val(http, tb_null);
// the status
return &http->status;
}
tbox-1.7.6/src/tbox/network/http.h 0000664 0000000 0000000 00000031743 14671175054 0017107 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file http.h
* @ingroup network
*
*/
#ifndef TB_NETWORK_HTTP_H
#define TB_NETWORK_HTTP_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "cookies.h"
#include "url.h"
#include "../string/string.h"
#include "../container/container.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/// the http option code: get
#define TB_HTTP_OPTION_CODE_GET(x) ((x) + 1)
/// the http option code: set
#define TB_HTTP_OPTION_CODE_SET(x) (0xff00 | ((x) + 1))
/// the http option code is setter?
#define TB_HTTP_OPTION_CODE_IS_SET(x) ((x) & 0xff00)
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the http method enum
typedef enum __tb_http_method_e
{
TB_HTTP_METHOD_GET = 0
, TB_HTTP_METHOD_POST = 1
, TB_HTTP_METHOD_HEAD = 2
, TB_HTTP_METHOD_PUT = 3
, TB_HTTP_METHOD_OPTIONS = 4
, TB_HTTP_METHOD_DELETE = 5
, TB_HTTP_METHOD_TRACE = 6
, TB_HTTP_METHOD_CONNECT = 7
}tb_http_method_e;
/// the http code enum
typedef enum __tb_http_code_e
{
TB_HTTP_CODE_CONTINUE = 100
, TB_HTTP_CODE_SWITCHING_PROTOCOLS = 101
, TB_HTTP_CODE_PROCESSING = 102
, TB_HTTP_CODE_OK = 200
, TB_HTTP_CODE_CREATED = 201
, TB_HTTP_CODE_ACCEPTED = 202
, TB_HTTP_CODE_NON_AUTHORITATIVE_INFORMATION = 203
, TB_HTTP_CODE_NO_CONTENT = 204
, TB_HTTP_CODE_RESET_CONTENT = 205
, TB_HTTP_CODE_PARTIAL_CONTENT = 206
, TB_HTTP_CODE_MULTI_STATUS = 207
, TB_HTTP_CODE_MULTIPLE_CHOICES = 300
, TB_HTTP_CODE_MOVED_PERMANENTLY = 301
, TB_HTTP_CODE_MOVED_TEMPORARILY = 302
, TB_HTTP_CODE_SEE_OTHER = 303
, TB_HTTP_CODE_NOT_MODIFIED = 304
, TB_HTTP_CODE_USE_PROXY = 305
, TB_HTTP_CODE_SWITCH_PROXY = 306
, TB_HTTP_CODE_TEMPORARY_REDIRECT = 307
, TB_HTTP_CODE_BAD_REQUEST = 400
, TB_HTTP_CODE_UNAUTHORIZED = 401
, TB_HTTP_CODE_FORBIDDEN = 403
, TB_HTTP_CODE_NOT_FOUND = 404
, TB_HTTP_CODE_METHOD_NOT_ALLOWED = 405
, TB_HTTP_CODE_NOT_ACCEPTABLE = 406
, TB_HTTP_CODE_REQUEST_TIMEOUT = 408
, TB_HTTP_CODE_CONFLICT = 409
, TB_HTTP_CODE_GONE = 410
, TB_HTTP_CODE_LENGTH_REQUIRED = 411
, TB_HTTP_CODE_PRECONDITION_FAILED = 412
, TB_HTTP_CODE_REQUEST_ENTITY_TOO_LONG = 413
, TB_HTTP_CODE_REQUEST_URI_TOO_LONG = 414
, TB_HTTP_CODE_UNSUPPORTED_MEDIA_TYPE = 415
, TB_HTTP_CODE_RANGE_NOT_SATISFIABLE = 416
, TB_HTTP_CODE_EXPECTATION_FAILED = 417
, TB_HTTP_CODE_UNPROCESSABLE_ENTITY = 422
, TB_HTTP_CODE_LOCKED = 423
, TB_HTTP_CODE_FAILED_DEPENDENCY = 424
, TB_HTTP_CODE_UNORDERED_COLLECTION = 425
, TB_HTTP_CODE_UPGRADE_REQUIRED = 426
, TB_HTTP_CODE_RETRY_WITH = 449
, TB_HTTP_CODE_INTERNAL_SERVER_ERROR = 500
, TB_HTTP_CODE_NOT_IMPLEMENTED = 501
, TB_HTTP_CODE_BAD_GATEWAY = 502
, TB_HTTP_CODE_SERVICE_UNAVAILABLE = 503
, TB_HTTP_CODE_GATEWAY_TIMEOUT = 504
, TB_HTTP_CODE_INSUFFICIENT_STORAGE = 507
, TB_HTTP_CODE_LOOP_DETECTED = 508
, TB_HTTP_CODE_NOT_EXTENDED = 510
}tb_http_code_e;
/// the http option enum
typedef enum __tb_http_option_e
{
TB_HTTP_OPTION_NONE = 0
, TB_HTTP_OPTION_GET_SSL = TB_HTTP_OPTION_CODE_GET(1)
, TB_HTTP_OPTION_GET_URL = TB_HTTP_OPTION_CODE_GET(2)
, TB_HTTP_OPTION_GET_HOST = TB_HTTP_OPTION_CODE_GET(3)
, TB_HTTP_OPTION_GET_PORT = TB_HTTP_OPTION_CODE_GET(4)
, TB_HTTP_OPTION_GET_PATH = TB_HTTP_OPTION_CODE_GET(5)
, TB_HTTP_OPTION_GET_HEAD = TB_HTTP_OPTION_CODE_GET(6)
, TB_HTTP_OPTION_GET_RANGE = TB_HTTP_OPTION_CODE_GET(7)
, TB_HTTP_OPTION_GET_METHOD = TB_HTTP_OPTION_CODE_GET(8)
, TB_HTTP_OPTION_GET_VERSION = TB_HTTP_OPTION_CODE_GET(9)
, TB_HTTP_OPTION_GET_TIMEOUT = TB_HTTP_OPTION_CODE_GET(10)
, TB_HTTP_OPTION_GET_COOKIES = TB_HTTP_OPTION_CODE_GET(11)
, TB_HTTP_OPTION_GET_REDIRECT = TB_HTTP_OPTION_CODE_GET(12)
, TB_HTTP_OPTION_GET_HEAD_FUNC = TB_HTTP_OPTION_CODE_GET(13)
, TB_HTTP_OPTION_GET_HEAD_PRIV = TB_HTTP_OPTION_CODE_GET(14)
, TB_HTTP_OPTION_GET_AUTO_UNZIP = TB_HTTP_OPTION_CODE_GET(15)
, TB_HTTP_OPTION_GET_POST_URL = TB_HTTP_OPTION_CODE_GET(16)
, TB_HTTP_OPTION_GET_POST_DATA = TB_HTTP_OPTION_CODE_GET(17)
, TB_HTTP_OPTION_GET_POST_FUNC = TB_HTTP_OPTION_CODE_GET(18)
, TB_HTTP_OPTION_GET_POST_PRIV = TB_HTTP_OPTION_CODE_GET(19)
, TB_HTTP_OPTION_GET_POST_LRATE = TB_HTTP_OPTION_CODE_GET(20)
, TB_HTTP_OPTION_SET_SSL = TB_HTTP_OPTION_CODE_SET(1)
, TB_HTTP_OPTION_SET_URL = TB_HTTP_OPTION_CODE_SET(2)
, TB_HTTP_OPTION_SET_HOST = TB_HTTP_OPTION_CODE_SET(3)
, TB_HTTP_OPTION_SET_PORT = TB_HTTP_OPTION_CODE_SET(4)
, TB_HTTP_OPTION_SET_PATH = TB_HTTP_OPTION_CODE_SET(5)
, TB_HTTP_OPTION_SET_HEAD = TB_HTTP_OPTION_CODE_SET(6)
, TB_HTTP_OPTION_SET_RANGE = TB_HTTP_OPTION_CODE_SET(7)
, TB_HTTP_OPTION_SET_METHOD = TB_HTTP_OPTION_CODE_SET(8)
, TB_HTTP_OPTION_SET_VERSION = TB_HTTP_OPTION_CODE_SET(9)
, TB_HTTP_OPTION_SET_TIMEOUT = TB_HTTP_OPTION_CODE_SET(10)
, TB_HTTP_OPTION_SET_COOKIES = TB_HTTP_OPTION_CODE_SET(11)
, TB_HTTP_OPTION_SET_REDIRECT = TB_HTTP_OPTION_CODE_SET(12)
, TB_HTTP_OPTION_SET_HEAD_FUNC = TB_HTTP_OPTION_CODE_SET(13)
, TB_HTTP_OPTION_SET_HEAD_PRIV = TB_HTTP_OPTION_CODE_SET(14)
, TB_HTTP_OPTION_SET_AUTO_UNZIP = TB_HTTP_OPTION_CODE_SET(15)
, TB_HTTP_OPTION_SET_POST_URL = TB_HTTP_OPTION_CODE_SET(16)
, TB_HTTP_OPTION_SET_POST_DATA = TB_HTTP_OPTION_CODE_SET(17)
, TB_HTTP_OPTION_SET_POST_FUNC = TB_HTTP_OPTION_CODE_SET(18)
, TB_HTTP_OPTION_SET_POST_PRIV = TB_HTTP_OPTION_CODE_SET(19)
, TB_HTTP_OPTION_SET_POST_LRATE = TB_HTTP_OPTION_CODE_SET(20)
}tb_http_option_e;
/// the http range type
typedef struct __tb_http_range_t
{
/// the begin offset
tb_hize_t bof;
/// the end offset
tb_hize_t eof;
}tb_http_range_t;
/// the http ref type
typedef __tb_typeref__(http);
/*! the http head func type
*
* @param line the http head line
* @param priv the func private data
*
* @return tb_true: ok and continue it if need, tb_false: break it
*/
typedef tb_bool_t (*tb_http_head_func_t)(tb_char_t const* line, tb_cpointer_t priv);
/*! the http post func type
*
* @param offset the istream offset
* @param size the istream size, no size: -1
* @param save the saved size
* @param rate the current rate, bytes/s
* @param priv the func private data
*
* @return tb_true: ok and continue it if need, tb_false: break it
*/
typedef tb_bool_t (*tb_http_post_func_t)(tb_size_t state, tb_hize_t offset, tb_hong_t size, tb_hize_t save, tb_size_t rate, tb_cpointer_t priv);
/// the http option type
typedef struct __tb_http_option_t
{
/// the method
tb_uint16_t method : 4;
/// auto unzip for gzip encoding?
tb_uint16_t bunzip : 1;
/// the http version, 0: HTTP/1.0, 1: HTTP/1.1
tb_uint16_t version : 1;
/// the redirect maxn
tb_uint16_t redirect : 10;
/// the url
tb_url_t url;
/// timeout: ms
tb_long_t timeout;
/// range
tb_http_range_t range;
/// the cookies
tb_cookies_ref_t cookies;
/// the priv data
tb_pointer_t head_priv;
/// the head func
tb_http_head_func_t head_func;
/// the head data
tb_buffer_t head_data;
/// the post url
tb_url_t post_url;
/// the post data
tb_byte_t const* post_data;
/// the post size
tb_size_t post_size;
/// the post func
tb_http_post_func_t post_func;
/// the post data
tb_cpointer_t post_priv;
/// the post limit rate
tb_size_t post_lrate;
}tb_http_option_t;
/// the http status type
typedef struct __tb_http_status_t
{
/// the http code
tb_uint16_t code : 10;
/// the http version
tb_uint16_t version : 1;
/// keep alive?
tb_uint16_t balived : 1;
/// be able to seek?
tb_uint16_t bseeked : 1;
/// is chunked?
tb_uint16_t bchunked : 1;
/// is gzip?
tb_uint16_t bgzip : 1;
/// is deflate?
tb_uint16_t bdeflate : 1;
/// the state
tb_size_t state;
/// the document size
tb_hong_t document_size;
/// the current content size, maybe in range
tb_hong_t content_size;
/// the content type
tb_string_t content_type;
/// the location
tb_string_t location;
}tb_http_status_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init http
*
* return the http
*/
tb_http_ref_t tb_http_init(tb_noarg_t);
/*! exit http
*
* @param http the http
*/
tb_void_t tb_http_exit(tb_http_ref_t http);
/*! kill http
*
* @param http the http
*/
tb_void_t tb_http_kill(tb_http_ref_t http);
/*! wait the http
*
* blocking wait the single event object, so need not aiop
* return the event type if ok, otherwise return 0 for timeout
*
* @param http the http
* @param events the events
* @param timeout the timeout value, return immediately if 0, infinity if -1
*
* @return the event type, return 0 if timeout, return -1 if error
*/
tb_long_t tb_http_wait(tb_http_ref_t http, tb_size_t events, tb_long_t timeout);
/*! open the http
*
* @param http the http
*
* @return tb_true or tb_false
*/
tb_bool_t tb_http_open(tb_http_ref_t http);
/*! close http
*
* @param http the http
*
* @return tb_true or tb_false
*/
tb_bool_t tb_http_close(tb_http_ref_t http);
/*! seek http
*
* @param http the http
* @param offset the offset
*
* @return tb_true or tb_false
*/
tb_bool_t tb_http_seek(tb_http_ref_t http, tb_hize_t offset);
/*! read data, non-blocking
*
* @param http the http
* @param data the data
* @param size the size
*
* @return ok: real size, continue: 0, fail: -1
*/
tb_long_t tb_http_read(tb_http_ref_t http, tb_byte_t* data, tb_size_t size);
/*! read data, blocking
*
* @param http the http
* @param data the data
* @param size the size
*
* @return tb_true or tb_false
*/
tb_bool_t tb_http_bread(tb_http_ref_t http, tb_byte_t* data, tb_size_t size);
/*! ctrl the http option
*
* @param http the http
* @param option the ctrl option
*
* @return tb_true or tb_false
*/
tb_bool_t tb_http_ctrl(tb_http_ref_t http, tb_size_t option, ...);
/*! the http status
*
* @param http the http
*
* @return the http status
*/
tb_http_status_t const* tb_http_status(tb_http_ref_t http);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/network/hwaddr.c 0000664 0000000 0000000 00000007721 14671175054 0017373 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file hwaddr.c
* @ingroup network
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "hwaddr"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "hwaddr.h"
#include "../libc/libc.h"
#include "../math/math.h"
#include "../utils/utils.h"
#include "../string/string.h"
#include "../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_void_t tb_hwaddr_clear(tb_hwaddr_ref_t hwaddr)
{
// check
tb_assert_and_check_return(hwaddr);
// clear it
tb_memset(hwaddr->u8, 0, sizeof(hwaddr->u8));
}
tb_void_t tb_hwaddr_copy(tb_hwaddr_ref_t hwaddr, tb_hwaddr_ref_t copied)
{
// check
tb_assert_and_check_return(hwaddr && copied);
// copy it
hwaddr->u8[0] = copied->u8[0];
hwaddr->u8[1] = copied->u8[1];
hwaddr->u8[2] = copied->u8[2];
hwaddr->u8[3] = copied->u8[3];
hwaddr->u8[4] = copied->u8[4];
hwaddr->u8[5] = copied->u8[5];
}
tb_bool_t tb_hwaddr_is_equal(tb_hwaddr_ref_t hwaddr, tb_hwaddr_ref_t other)
{
// check
tb_assert_and_check_return_val(hwaddr && other, tb_false);
// is equal?
return !tb_memcmp(hwaddr->u8, other->u8, sizeof(hwaddr->u8));
}
tb_char_t const* tb_hwaddr_cstr(tb_hwaddr_ref_t hwaddr, tb_char_t* data, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(hwaddr && data && maxn >= TB_HWADDR_CSTR_MAXN, tb_null);
// make it
tb_long_t size = tb_snprintf(data, maxn - 1, "%02x:%02x:%02x:%02x:%02x:%02x", hwaddr->u8[0], hwaddr->u8[1], hwaddr->u8[2], hwaddr->u8[3], hwaddr->u8[4], hwaddr->u8[5]);
if (size >= 0) data[size] = '\0';
// ok
return data;
}
tb_bool_t tb_hwaddr_cstr_set(tb_hwaddr_ref_t hwaddr, tb_char_t const* cstr)
{
// check
tb_assert_and_check_return_val(cstr, tb_false);
// done
tb_uint32_t v = 0;
tb_char_t c = '\0';
tb_size_t i = 0;
tb_char_t const* p = cstr;
tb_bool_t ok = tb_true;
tb_hwaddr_t temp;
do
{
// the character
c = *p++;
// digit?
if (tb_isdigit16(c) && v <= 0xff)
{
// update value
if (tb_isdigit10(c))
v = (v << 4) + (c - '0');
else if (c > ('a' - 1) && c < ('f' + 1))
v = (v << 4) + (c - 'a') + 10;
else if (c > ('A' - 1) && c < ('F' + 1))
v = (v << 4) + (c - 'A') + 10;
else
{
// abort
tb_assert(0);
// failed
ok = tb_false;
break;
}
}
// ':' or "-" or '\0'?
else if (i < 6 && (c == ':' || c == '-' || !c) && v <= 0xff)
{
// save value
temp.u8[i++] = v;
// clear value
v = 0;
}
// failed?
else
{
ok = tb_false;
break;
}
} while (c);
// failed
if (i != 6) ok = tb_false;
// save it if ok
if (ok && hwaddr) *hwaddr = temp;
// trace
// tb_assertf(ok, "invalid hwaddr: %s", cstr);
// ok?
return ok;
}
tbox-1.7.6/src/tbox/network/hwaddr.h 0000664 0000000 0000000 00000005345 14671175054 0017400 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file hwaddr.h
* @ingroup network
*
*/
#ifndef TB_NETWORK_HWADDR_H
#define TB_NETWORK_HWADDR_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/// the hwaddr string data maxn
#define TB_HWADDR_CSTR_MAXN (18)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/*! the hardware address type
*
* mac: xx:xx:xx:xx:xx:xx
*/
typedef struct __tb_hwaddr_t
{
/// u8
tb_byte_t u8[6];
}tb_hwaddr_t, *tb_hwaddr_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! clear the hwaddr
*
* @param hwaddr the hwaddr
*/
tb_void_t tb_hwaddr_clear(tb_hwaddr_ref_t hwaddr);
/*! copy address, faster than *hwaddr = *other
*
* @param hwaddr the address
* @param copied the copied address
*/
tb_void_t tb_hwaddr_copy(tb_hwaddr_ref_t hwaddr, tb_hwaddr_ref_t copied);
/*! is equal?
*
* @param hwaddr the hwaddr
* @param other the other hwaddr
*
* @return tb_true or tb_false
*/
tb_bool_t tb_hwaddr_is_equal(tb_hwaddr_ref_t hwaddr, tb_hwaddr_ref_t other);
/*! get the hwaddr string
*
* @param hwaddr the hwaddr
* @param data the hwaddr data
* @param maxn the data maxn
*
* @return the hwaddr address
*/
tb_char_t const* tb_hwaddr_cstr(tb_hwaddr_ref_t hwaddr, tb_char_t* data, tb_size_t maxn);
/*! set the hwaddr from string
*
* @param hwaddr the hwaddr
* @param cstr the hwaddr string
*
* @return tb_true or tb_false
*/
tb_bool_t tb_hwaddr_cstr_set(tb_hwaddr_ref_t hwaddr, tb_char_t const* cstr);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/network/impl/ 0000775 0000000 0000000 00000000000 14671175054 0016710 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/network/impl/http/ 0000775 0000000 0000000 00000000000 14671175054 0017667 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/network/impl/http/date.c 0000664 0000000 0000000 00000013010 14671175054 0020743 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file date.c
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "http_date"
#define TB_TRACE_MODULE_DEBUG (1)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "date.h"
#include "../../../libc/libc.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_time_t tb_http_date_from_cstr(tb_char_t const* cstr, tb_size_t size)
{
// check
tb_assert_and_check_return_val(cstr && size, 0);
// done
tb_tm_t tm = {0};
tb_time_t date = 0;
tb_char_t const* p = cstr;
tb_char_t const* e = cstr + size;
do
{
// skip space
while (p < e && tb_isspace(*p)) p++;
// ignore
#if 0
// parse week
if ((p + 6 < e && !tb_strnicmp(p, "Monday", 6)) || (p + 3 < e && !tb_strnicmp(p, "Mon", 3)))
tm.week = 1;
else if ((p + 7 < e && !tb_strnicmp(p, "Tuesday", 7)) || (p + 3 < e && !tb_strnicmp(p, "Tue", 3)))
tm.week = 2;
else if ((p + 9 < e && !tb_strnicmp(p, "Wednesday", 9)) || (p + 3 < e && !tb_strnicmp(p, "Wed", 3)))
tm.week = 3;
else if ((p + 8 < e && !tb_strnicmp(p, "Thursday", 8)) || (p + 3 < e && !tb_strnicmp(p, "Thu", 3)))
tm.week = 4;
else if ((p + 6 < e && !tb_strnicmp(p, "Friday", 6)) || (p + 3 < e && !tb_strnicmp(p, "Fri", 3)))
tm.week = 5;
else if ((p + 8 < e && !tb_strnicmp(p, "Saturday", 8)) || (p + 3 < e && !tb_strnicmp(p, "Sat", 3)))
tm.week = 6;
else if ((p + 6 < e && !tb_strnicmp(p, "Sunday", 6)) || (p + 3 < e && !tb_strnicmp(p, "Sun", 3)))
tm.week = 7;
#endif
// skip week
while (p < e && *p != ',' && !tb_isspace(*p)) p++;
if (p < e && (*p == ',' || tb_isspace(*p))) p++;
// skip space
while (p < e && tb_isspace(*p)) p++;
// is day?
tb_bool_t year_suffix = tb_true;
if (p < e && tb_isdigit(*p))
{
/* prefix year
*
* .e.g
* year_suffix == false: Sun, 06-Nov-1994 08:49:37
* year_suffix == true: Sun Nov 6 08:49:37 1994
*/
year_suffix = tb_false;
// parse day
tm.mday = tb_s10tou32(p);
// skip day
while (p < e && *p != '-' && !tb_isspace(*p)) p++;
if (p < e && (*p == '-' || tb_isspace(*p))) p++;
}
// parse month
if (p + 3 < e && !tb_strnicmp(p, "Jan", 3))
tm.month = 1;
else if (p + 3 < e && !tb_strnicmp(p, "Feb", 3))
tm.month = 2;
else if (p + 3 < e && !tb_strnicmp(p, "Mar", 3))
tm.month = 3;
else if (p + 3 < e && !tb_strnicmp(p, "Apr", 3))
tm.month = 4;
else if (p + 3 < e && !tb_strnicmp(p, "May", 3))
tm.month = 5;
else if (p + 3 < e && !tb_strnicmp(p, "Jun", 3))
tm.month = 6;
else if (p + 3 < e && !tb_strnicmp(p, "Jul", 3))
tm.month = 7;
else if (p + 3 < e && !tb_strnicmp(p, "Aug", 3))
tm.month = 8;
else if (p + 3 < e && !tb_strnicmp(p, "Sep", 3))
tm.month = 9;
else if (p + 3 < e && !tb_strnicmp(p, "Oct", 3))
tm.month = 10;
else if (p + 3 < e && !tb_strnicmp(p, "Nov", 3))
tm.month = 11;
else if (p + 3 < e && !tb_strnicmp(p, "Dec", 3))
tm.month = 12;
// skip month
while (p < e && *p != '-' && !tb_isspace(*p)) p++;
if (p < e && (*p == '-' || tb_isspace(*p))) p++;
// year suffix?
if (year_suffix)
{
// parse day
tm.mday = tb_s10tou32(p);
}
else
{
// parse year
tm.year = tb_s10tou32(p);
if (tm.year < 100) tm.year += 2000;
}
// skip year or day
while (p < e && !tb_isspace(*p)) p++;
while (p < e && tb_isspace(*p)) p++;
// parse hour
tm.hour = tb_s10tou32(p);
// skip hour
while (p < e && *p != ':') p++;
if (p < e && *p == ':') p++;
// parse minute
tm.minute = tb_s10tou32(p);
// skip minute
while (p < e && *p != ':') p++;
if (p < e && *p == ':') p++;
// parse second
tm.second = tb_s10tou32(p);
// year suffix?
if (year_suffix)
{
// skip time
while (p < e && !tb_isspace(*p)) p++;
while (p < e && tb_isspace(*p)) p++;
// parse year
tm.year = tb_s10tou32(p);
if (tm.year < 100) tm.year += 1900;
}
// make date
date = tb_gmmktime(&tm);
} while (0);
// ok?
return date;
}
tbox-1.7.6/src/tbox/network/impl/http/date.h 0000664 0000000 0000000 00000003512 14671175054 0020756 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file date.h
*/
#ifndef TB_NETWORK_IMPL_HTTP_DATE_H
#define TB_NETWORK_IMPL_HTTP_DATE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* get the http date from the given cstring
*
*
* supports format:
* Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
* Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
* Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
*
* for cookies(RFC 822, RFC 850, RFC 1036, and RFC 1123):
* Sun, 06-Nov-1994 08:49:37 GMT
*
*
*
* @param cstr the cstring
* @param size the cstring length
*
* @return the date
*/
tb_time_t tb_http_date_from_cstr(tb_char_t const* cstr, tb_size_t size);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/network/impl/http/method.c 0000664 0000000 0000000 00000003064 14671175054 0021316 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file method.c
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "http_method"
#define TB_TRACE_MODULE_DEBUG (1)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "method.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
static tb_char_t const* g_http_methods[] =
{
"GET"
, "POST"
, "HEAD"
, "PUT"
, "OPTIONS"
, "DELETE"
, "TRACE"
, "CONNECT"
};
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_char_t const* tb_http_method_cstr(tb_size_t method)
{
// check
tb_assert_and_check_return_val(method < tb_arrayn(g_http_methods), tb_null);
// ok
return g_http_methods[method];
}
tbox-1.7.6/src/tbox/network/impl/http/method.h 0000664 0000000 0000000 00000002661 14671175054 0021325 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file method.h
*
*/
#ifndef TB_NETWORK_IMPL_HTTP_METHOD_H
#define TB_NETWORK_IMPL_HTTP_METHOD_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* get the http method string
*
* @param method the method
*
* @return the method string
*/
tb_char_t const* tb_http_method_cstr(tb_size_t method);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/network/impl/http/option.c 0000664 0000000 0000000 00000046757 14671175054 0021366 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file option.c
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "http_option"
#define TB_TRACE_MODULE_DEBUG (1)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "option.h"
#include "method.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_http_option_init(tb_http_option_t* option)
{
// check
tb_assert_and_check_return_val(option, tb_false);
// init option using the default value
option->method = TB_HTTP_METHOD_GET;
option->redirect = TB_HTTP_DEFAULT_REDIRECT;
option->timeout = TB_HTTP_DEFAULT_TIMEOUT;
option->version = 1; // HTTP/1.1
option->bunzip = 0;
option->cookies = tb_null;
// init url
if (!tb_url_init(&option->url)) return tb_false;
// init post url
if (!tb_url_init(&option->post_url)) return tb_false;
// init head data
if (!tb_buffer_init(&option->head_data)) return tb_false;
// ok
return tb_true;
}
tb_void_t tb_http_option_exit(tb_http_option_t* option)
{
// check
tb_assert_and_check_return(option);
// exit url
tb_url_exit(&option->url);
// exit post url
tb_url_exit(&option->post_url);
// exit head data
tb_buffer_exit(&option->head_data);
// clear cookies
option->cookies = tb_null;
}
tb_bool_t tb_http_option_ctrl(tb_http_option_t* option, tb_size_t code, tb_va_list_t args)
{
// check
tb_assert_and_check_return_val(option, tb_false);
// done
switch (code)
{
case TB_HTTP_OPTION_SET_URL:
{
// url
tb_char_t const* url = (tb_char_t const*)tb_va_arg(args, tb_char_t const*);
tb_assert_and_check_return_val(url, tb_false);
// set url
if (tb_url_cstr_set(&option->url, url)) return tb_true;
}
break;
case TB_HTTP_OPTION_GET_URL:
{
// purl
tb_char_t const** purl = (tb_char_t const**)tb_va_arg(args, tb_char_t const**);
tb_assert_and_check_return_val(purl, tb_false);
// get url
tb_char_t const* url = tb_url_cstr(&option->url);
tb_assert_and_check_return_val(url, tb_false);
// ok
*purl = url;
return tb_true;
}
break;
case TB_HTTP_OPTION_SET_HOST:
{
// host
tb_char_t const* host = (tb_char_t const*)tb_va_arg(args, tb_char_t const*);
tb_assert_and_check_return_val(host, tb_false);
// set host
tb_url_host_set(&option->url, host);
return tb_true;
}
break;
case TB_HTTP_OPTION_GET_HOST:
{
// phost
tb_char_t const** phost = (tb_char_t const**)tb_va_arg(args, tb_char_t const**);
tb_assert_and_check_return_val(phost, tb_false);
// get host
tb_char_t const* host = tb_url_host(&option->url);
tb_assert_and_check_return_val(host, tb_false);
// ok
*phost = host;
return tb_true;
}
break;
case TB_HTTP_OPTION_SET_PORT:
{
// port
tb_size_t port = (tb_size_t)tb_va_arg(args, tb_size_t);
tb_assert_and_check_return_val(port, tb_false);
// set port
tb_url_port_set(&option->url, (tb_uint16_t)port);
return tb_true;
}
break;
case TB_HTTP_OPTION_GET_PORT:
{
// pport
tb_size_t* pport = (tb_size_t*)tb_va_arg(args, tb_size_t*);
tb_assert_and_check_return_val(pport, tb_false);
// get port
*pport = tb_url_port(&option->url);
return tb_true;
}
break;
case TB_HTTP_OPTION_SET_PATH:
{
// path
tb_char_t const* path = (tb_char_t const*)tb_va_arg(args, tb_char_t const*);
tb_assert_and_check_return_val(path, tb_false);
// set path
tb_url_path_set(&option->url, path);
return tb_true;
}
break;
case TB_HTTP_OPTION_GET_PATH:
{
// ppath
tb_char_t const** ppath = (tb_char_t const**)tb_va_arg(args, tb_char_t const**);
tb_assert_and_check_return_val(ppath, tb_false);
// get path
tb_char_t const* path = tb_url_path(&option->url);
tb_assert_and_check_return_val(path, tb_false);
// ok
*ppath = path;
return tb_true;
}
break;
case TB_HTTP_OPTION_SET_METHOD:
{
// method
tb_size_t method = (tb_size_t)tb_va_arg(args, tb_size_t);
// set method
option->method = method;
return tb_true;
}
break;
case TB_HTTP_OPTION_GET_METHOD:
{
// pmethod
tb_size_t* pmethod = (tb_size_t*)tb_va_arg(args, tb_size_t*);
tb_assert_and_check_return_val(pmethod, tb_false);
// get method
*pmethod = option->method;
return tb_true;
}
break;
case TB_HTTP_OPTION_SET_HEAD:
{
// key
tb_char_t const* key = (tb_char_t const*)tb_va_arg(args, tb_char_t const*);
tb_assert_and_check_return_val(key, tb_false);
// val
tb_char_t const* val = (tb_char_t const*)tb_va_arg(args, tb_char_t const*);
tb_assert_and_check_return_val(val, tb_false);
// remove the previous key and value
tb_bool_t head_same = tb_false;
tb_char_t const* head_head = (tb_char_t const*)tb_buffer_data(&option->head_data);
tb_char_t const* head_data = head_head;
tb_char_t const* head_tail = head_data + tb_buffer_size(&option->head_data);
while (head_data < head_tail)
{
// the name and data
tb_char_t const* name = head_data;
tb_char_t const* data = head_data + tb_strlen(name) + 1;
tb_char_t const* next = data + tb_strlen(data) + 1;
tb_check_break(data < head_tail);
// is this?
if (!tb_stricmp(name, key))
{
// value is different? remove it
if (tb_stricmp(val, data)) tb_buffer_memmovp(&option->head_data, name - head_head, next - head_head);
else head_same = tb_true;
break;
}
// next
head_data = next;
}
// set head
if (!head_same)
{
tb_buffer_memncat(&option->head_data, (tb_byte_t const*)key, tb_strlen(key) + 1);
tb_buffer_memncat(&option->head_data, (tb_byte_t const*)val, tb_strlen(val) + 1);
}
// ok
return tb_true;
}
break;
case TB_HTTP_OPTION_GET_HEAD:
{
// key
tb_char_t const* key = (tb_char_t const*)tb_va_arg(args, tb_char_t const*);
tb_assert_and_check_return_val(key, tb_false);
// pval
tb_char_t const** pval = (tb_char_t const**)tb_va_arg(args, tb_char_t const**);
tb_assert_and_check_return_val(pval, tb_false);
// find head
tb_char_t const* head_data = (tb_char_t const*)tb_buffer_data(&option->head_data);
tb_char_t const* head_tail = head_data + tb_buffer_size(&option->head_data);
while (head_data < head_tail)
{
// the name and data
tb_char_t const* name = head_data;
tb_char_t const* data = head_data + tb_strlen(name) + 1;
tb_check_break(data < head_tail);
// is this?
if (!tb_stricmp(name, key))
{
// ok
*pval = data;
return tb_true;
}
// next
head_data = data + tb_strlen(data) + 1;
}
// failed
return tb_false;
}
break;
case TB_HTTP_OPTION_SET_HEAD_FUNC:
{
// head_func
tb_http_head_func_t head_func = (tb_http_head_func_t)tb_va_arg(args, tb_http_head_func_t);
// set head_func
option->head_func = head_func;
return tb_true;
}
break;
case TB_HTTP_OPTION_GET_HEAD_FUNC:
{
// phead_func
tb_http_head_func_t* phead_func = (tb_http_head_func_t*)tb_va_arg(args, tb_http_head_func_t*);
tb_assert_and_check_return_val(phead_func, tb_false);
// get head_func
*phead_func = option->head_func;
return tb_true;
}
break;
case TB_HTTP_OPTION_SET_HEAD_PRIV:
{
// head_priv
tb_pointer_t head_priv = (tb_pointer_t)tb_va_arg(args, tb_pointer_t);
// set head_priv
option->head_priv = head_priv;
return tb_true;
}
break;
case TB_HTTP_OPTION_GET_HEAD_PRIV:
{
// phead_priv
tb_pointer_t* phead_priv = (tb_pointer_t*)tb_va_arg(args, tb_pointer_t*);
tb_assert_and_check_return_val(phead_priv, tb_false);
// get head_priv
*phead_priv = option->head_priv;
return tb_true;
}
break;
case TB_HTTP_OPTION_SET_RANGE:
{
// set range
option->range.bof = (tb_hize_t)tb_va_arg(args, tb_hize_t);
option->range.eof = (tb_hize_t)tb_va_arg(args, tb_hize_t);
return tb_true;
}
break;
case TB_HTTP_OPTION_GET_RANGE:
{
// pbof
tb_hize_t* pbof = (tb_hize_t*)tb_va_arg(args, tb_hize_t*);
tb_assert_and_check_return_val(pbof, tb_false);
// peof
tb_hize_t* peof = (tb_hize_t*)tb_va_arg(args, tb_hize_t*);
tb_assert_and_check_return_val(peof, tb_false);
// ok
*pbof = option->range.bof;
*peof = option->range.eof;
return tb_true;
}
break;
case TB_HTTP_OPTION_SET_SSL:
{
// bssl
tb_bool_t bssl = (tb_bool_t)tb_va_arg(args, tb_bool_t);
// set ssl
tb_url_ssl_set(&option->url, bssl);
return tb_true;
}
break;
case TB_HTTP_OPTION_GET_SSL:
{
// pssl
tb_bool_t* pssl = (tb_bool_t*)tb_va_arg(args, tb_bool_t*);
tb_assert_and_check_return_val(pssl, tb_false);
// get ssl
*pssl = tb_url_ssl(&option->url);
return tb_true;
}
break;
case TB_HTTP_OPTION_SET_TIMEOUT:
{
// the timeout
tb_long_t timeout = (tb_long_t)tb_va_arg(args, tb_long_t);
// set timeout
option->timeout = timeout? timeout : TB_HTTP_DEFAULT_TIMEOUT;
return tb_true;
}
break;
case TB_HTTP_OPTION_GET_TIMEOUT:
{
// ptimeout
tb_long_t* ptimeout = (tb_long_t*)tb_va_arg(args, tb_long_t*);
tb_assert_and_check_return_val(ptimeout, tb_false);
// get timeout
*ptimeout = option->timeout;
return tb_true;
}
break;
case TB_HTTP_OPTION_SET_COOKIES:
{
// set cookies
option->cookies = (tb_cookies_ref_t)tb_va_arg(args, tb_cookies_ref_t);
return tb_true;
}
break;
case TB_HTTP_OPTION_GET_COOKIES:
{
// ptimeout
tb_cookies_ref_t* pcookies = (tb_cookies_ref_t*)tb_va_arg(args, tb_cookies_ref_t*);
tb_assert_and_check_return_val(pcookies, tb_false);
// get cookies
*pcookies = option->cookies;
return tb_true;
}
break;
case TB_HTTP_OPTION_SET_POST_URL:
{
// url
tb_char_t const* url = (tb_char_t const*)tb_va_arg(args, tb_char_t const*);
tb_assert_and_check_return_val(url, tb_false);
// clear post data and size
option->post_data = tb_null;
option->post_size = 0;
// set url
if (tb_url_cstr_set(&option->post_url, url)) return tb_true;
}
break;
case TB_HTTP_OPTION_GET_POST_URL:
{
// purl
tb_char_t const** purl = (tb_char_t const**)tb_va_arg(args, tb_char_t const**);
tb_assert_and_check_return_val(purl, tb_false);
// get url
tb_char_t const* url = tb_url_cstr(&option->post_url);
tb_assert_and_check_return_val(url, tb_false);
// ok
*purl = url;
return tb_true;
}
break;
case TB_HTTP_OPTION_SET_POST_DATA:
{
// post data
tb_byte_t const* data = (tb_byte_t const*)tb_va_arg(args, tb_byte_t const*);
// post size
tb_size_t size = (tb_size_t)tb_va_arg(args, tb_size_t);
// clear post url
tb_url_clear(&option->post_url);
// set post data
option->post_data = data;
option->post_size = size;
return tb_true;
}
break;
case TB_HTTP_OPTION_GET_POST_DATA:
{
// pdata and psize
tb_byte_t const** pdata = (tb_byte_t const**)tb_va_arg(args, tb_byte_t const**);
tb_size_t* psize = (tb_size_t*)tb_va_arg(args, tb_size_t*);
tb_assert_and_check_return_val(pdata && psize, tb_false);
// get post data and size
*pdata = option->post_data;
*psize = option->post_size;
return tb_true;
}
break;
case TB_HTTP_OPTION_SET_POST_FUNC:
{
// func
tb_http_post_func_t func = (tb_http_post_func_t)tb_va_arg(args, tb_http_post_func_t);
// set post func
option->post_func = func;
return tb_true;
}
break;
case TB_HTTP_OPTION_GET_POST_FUNC:
{
// pfunc
tb_http_post_func_t* pfunc = (tb_http_post_func_t*)tb_va_arg(args, tb_http_post_func_t*);
tb_assert_and_check_return_val(pfunc, tb_false);
// get post func
*pfunc = option->post_func;
return tb_true;
}
break;
case TB_HTTP_OPTION_SET_POST_PRIV:
{
// post priv
tb_cpointer_t priv = (tb_pointer_t)tb_va_arg(args, tb_pointer_t);
// set post priv
option->post_priv = priv;
return tb_true;
}
break;
case TB_HTTP_OPTION_GET_POST_PRIV:
{
// ppost priv
tb_cpointer_t* ppriv = (tb_cpointer_t*)tb_va_arg(args, tb_cpointer_t*);
tb_assert_and_check_return_val(ppriv, tb_false);
// get post priv
*ppriv = option->post_priv;
return tb_true;
}
break;
case TB_HTTP_OPTION_SET_POST_LRATE:
{
// post lrate
tb_size_t lrate = (tb_size_t)tb_va_arg(args, tb_size_t);
// set post lrate
option->post_lrate = lrate;
return tb_true;
}
break;
case TB_HTTP_OPTION_GET_POST_LRATE:
{
// ppost lrate
tb_size_t* plrate = (tb_size_t*)tb_va_arg(args, tb_size_t*);
tb_assert_and_check_return_val(plrate, tb_false);
// get post lrate
*plrate = option->post_lrate;
return tb_true;
}
break;
case TB_HTTP_OPTION_SET_AUTO_UNZIP:
{
// bunzip
tb_bool_t bunzip = (tb_bool_t)tb_va_arg(args, tb_bool_t);
// set bunzip
option->bunzip = bunzip? 1 : 0;
return tb_true;
}
break;
case TB_HTTP_OPTION_GET_AUTO_UNZIP:
{
// pbunzip
tb_bool_t* pbunzip = (tb_bool_t*)tb_va_arg(args, tb_bool_t*);
tb_assert_and_check_return_val(pbunzip, tb_false);
// get bunzip
*pbunzip = option->bunzip? tb_true : tb_false;
return tb_true;
}
break;
case TB_HTTP_OPTION_SET_REDIRECT:
{
// redirect
tb_size_t redirect = (tb_size_t)tb_va_arg(args, tb_size_t);
// set redirect
option->redirect = redirect;
return tb_true;
}
break;
case TB_HTTP_OPTION_GET_REDIRECT:
{
// predirect
tb_size_t* predirect = (tb_size_t*)tb_va_arg(args, tb_size_t*);
tb_assert_and_check_return_val(predirect, tb_false);
// get redirect
*predirect = option->redirect;
return tb_true;
}
break;
case TB_HTTP_OPTION_SET_VERSION:
{
// version
tb_size_t version = (tb_size_t)tb_va_arg(args, tb_size_t);
// set version
option->version = version;
return tb_true;
}
break;
case TB_HTTP_OPTION_GET_VERSION:
{
// pversion
tb_size_t* pversion = (tb_size_t*)tb_va_arg(args, tb_size_t*);
tb_assert_and_check_return_val(pversion, tb_false);
// get version
*pversion = option->version;
return tb_true;
}
break;
default:
break;
}
// failed
return tb_false;
}
#ifdef __tb_debug__
tb_void_t tb_http_option_dump(tb_http_option_t* option)
{
// check
tb_assert_and_check_return(option);
// dump option
tb_trace_i("======================================================================");
tb_trace_i("option: ");
tb_trace_i("option: url: %s", tb_url_cstr(&option->url));
tb_trace_i("option: version: HTTP/1.%1u", option->version);
tb_trace_i("option: method: %s", tb_http_method_cstr(option->method));
tb_trace_i("option: redirect: %d", option->redirect);
tb_trace_i("option: range: %llu-%llu", option->range.bof, option->range.eof);
tb_trace_i("option: bunzip: %s", option->bunzip? "true" : "false");
// dump head
tb_char_t const* head_data = (tb_char_t const*)tb_buffer_data(&option->head_data);
tb_char_t const* head_tail = head_data + tb_buffer_size(&option->head_data);
while (head_data < head_tail)
{
// the name and data
tb_char_t const* name = head_data;
tb_char_t const* data = head_data + tb_strlen(name) + 1;
tb_check_break(data < head_tail);
// trace
tb_trace_i("option: head: %s: %s", name, data);
// next
head_data = data + tb_strlen(data) + 1;
}
// dump end
tb_trace_i("");
}
#endif
tbox-1.7.6/src/tbox/network/impl/http/option.h 0000664 0000000 0000000 00000003721 14671175054 0021353 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file option.h
* @ingroup network
*
*/
#ifndef TB_NETWORK_IMPL_HTTP_OPTION_H
#define TB_NETWORK_IMPL_HTTP_OPTION_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* init option
*
* @param option the option
*
* @return tb_true or tb_false
*/
tb_bool_t tb_http_option_init(tb_http_option_t* option);
/* exit option
*
* @param option the option
*/
tb_void_t tb_http_option_exit(tb_http_option_t* option);
/* ctrl option
*
* @param option the option
* @param ctrl the ctrl code
* @param args the ctrl args
*/
tb_bool_t tb_http_option_ctrl(tb_http_option_t* option, tb_size_t code, tb_va_list_t args);
#ifdef __tb_debug__
/* dump option
*
* @param option the option
*/
tb_void_t tb_http_option_dump(tb_http_option_t* option);
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/network/impl/http/prefix.h 0000664 0000000 0000000 00000003021 14671175054 0021331 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_NETWORK_IMPL_HTTP_PREFIX_H
#define TB_NETWORK_IMPL_HTTP_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#include "../../url.h"
#include "../../http.h"
#include "../../cookies.h"
#include "../../../libc/libc.h"
#include "../../../string/string.h"
#include "../../../container/container.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/// the http default timeout, 10s
#define TB_HTTP_DEFAULT_TIMEOUT (10000)
/// the http default redirect maxn
#define TB_HTTP_DEFAULT_REDIRECT (10)
/// the http default port
#define TB_HTTP_DEFAULT_PORT (80)
/// the http default port for ssl
#define TB_HTTP_DEFAULT_PORT_SSL (443)
#endif
tbox-1.7.6/src/tbox/network/impl/http/status.c 0000664 0000000 0000000 00000006725 14671175054 0021370 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file status.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "http_status"
#define TB_TRACE_MODULE_DEBUG (1)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "status.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_http_status_init(tb_http_status_t* status)
{
// check
tb_assert_and_check_return_val(status, tb_false);
// init status using the default value
status->version = 1;
// init content type
if (!tb_string_init(&status->content_type)) return tb_false;
// init location
if (!tb_string_init(&status->location)) return tb_false;
// ok
return tb_true;
}
tb_void_t tb_http_status_exit(tb_http_status_t* status)
{
// check
tb_assert_and_check_return(status);
// exit the content type
tb_string_exit(&status->content_type);
// exit location
tb_string_exit(&status->location);
}
tb_void_t tb_http_status_cler(tb_http_status_t* status, tb_bool_t host_changed)
{
// check
tb_assert_and_check_return(status);
// clear status
status->code = 0;
status->bgzip = 0;
status->bdeflate = 0;
status->bchunked = 0;
status->content_size = -1;
status->document_size = -1;
status->state = TB_STATE_OK;
// clear content type
tb_string_clear(&status->content_type);
// clear location
tb_string_clear(&status->location);
// host is changed? clear the alived state
if (host_changed)
{
status->version = 1;
status->balived = 0;
status->bseeked = 0;
}
}
#ifdef __tb_debug__
tb_void_t tb_http_status_dump(tb_http_status_t* status)
{
// check
tb_assert_and_check_return(status);
// dump status
tb_trace_i("======================================================================");
tb_trace_i("status: ");
tb_trace_i("status: code: %d", status->code);
tb_trace_i("status: version: HTTP/1.%1u", status->version);
tb_trace_i("status: content:type: %s", tb_string_cstr(&status->content_type));
tb_trace_i("status: content:size: %lld", status->content_size);
tb_trace_i("status: document:size: %lld", status->document_size);
tb_trace_i("status: location: %s", tb_string_cstr(&status->location));
tb_trace_i("status: bgzip: %s", status->bgzip? "true" : "false");
tb_trace_i("status: bdeflate: %s", status->bdeflate? "true" : "false");
tb_trace_i("status: balived: %s", status->balived? "true" : "false");
tb_trace_i("status: bseeked: %s", status->bseeked? "true" : "false");
tb_trace_i("status: bchunked: %s", status->bchunked? "true" : "false");
// dump end
tb_trace_i("");
}
#endif
tbox-1.7.6/src/tbox/network/impl/http/status.h 0000664 0000000 0000000 00000003614 14671175054 0021367 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file status.h
*/
#ifndef TB_NETWORK_IMPL_HTTP_STATUS_H
#define TB_NETWORK_IMPL_HTTP_STATUS_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* init status
*
* @param status the status
*
* @return tb_true or tb_false
*/
tb_bool_t tb_http_status_init(tb_http_status_t* status);
/* exit status
*
* @param status the status
*/
tb_void_t tb_http_status_exit(tb_http_status_t* status);
/* clear status
*
* @param status the status
* @param host_changed the host is changed
*/
tb_void_t tb_http_status_cler(tb_http_status_t* status, tb_bool_t host_changed);
#ifdef __tb_debug__
/* dump status
*
* @param status the status
*/
tb_void_t tb_http_status_dump(tb_http_status_t* status);
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/network/impl/impl.h 0000664 0000000 0000000 00000001623 14671175054 0020024 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file network.h
* @ingroup network
*
*/
#ifndef TB_NETWORK_IMPL_H
#define TB_NETWORK_IMPL_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "network.h"
#endif
tbox-1.7.6/src/tbox/network/impl/network.c 0000664 0000000 0000000 00000010003 14671175054 0020537 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file network.c
* @ingroup network
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "network.h"
#include "../network.h"
#include "../../libc/libc.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
#ifndef TB_CONFIG_MICRO_ENABLE
static tb_long_t tb_network_printf_format_ipv4(tb_cpointer_t object, tb_char_t* cstr, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(object && cstr && maxn, -1);
// the ipv4
tb_ipv4_ref_t ipv4 = (tb_ipv4_ref_t)object;
// make it
cstr = (tb_char_t*)tb_ipv4_cstr(ipv4, cstr, maxn);
// ok?
return cstr? tb_strlen(cstr) : -1;
}
static tb_long_t tb_network_printf_format_ipv6(tb_cpointer_t object, tb_char_t* cstr, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(object && cstr && maxn, -1);
// the ipv6
tb_ipv6_ref_t ipv6 = (tb_ipv6_ref_t)object;
// make it
cstr = (tb_char_t*)tb_ipv6_cstr(ipv6, cstr, maxn);
// ok?
return cstr? tb_strlen(cstr) : -1;
}
static tb_long_t tb_network_printf_format_unixaddr(tb_cpointer_t object, tb_char_t* cstr, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(object && cstr && maxn, -1);
// the unixaddr
tb_unixaddr_ref_t unixaddr = (tb_unixaddr_ref_t)object;
// make it
cstr = (tb_char_t*)tb_unixaddr_cstr(unixaddr, cstr, maxn);
// ok?
return cstr? tb_strlen(cstr) : -1;
}
static tb_long_t tb_network_printf_format_ipaddr(tb_cpointer_t object, tb_char_t* cstr, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(object && cstr && maxn, -1);
// the ipaddr
tb_ipaddr_ref_t ipaddr = (tb_ipaddr_ref_t)object;
// make it
cstr = (tb_char_t*)tb_ipaddr_cstr(ipaddr, cstr, maxn);
// ok?
return cstr? tb_strlen(cstr) : -1;
}
static tb_long_t tb_network_printf_format_hwaddr(tb_cpointer_t object, tb_char_t* cstr, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(object && cstr && maxn, -1);
// the hwaddr
tb_hwaddr_ref_t hwaddr = (tb_hwaddr_ref_t)object;
// make it
cstr = (tb_char_t*)tb_hwaddr_cstr(hwaddr, cstr, maxn);
// ok?
return cstr? tb_strlen(cstr) : -1;
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_network_init_env()
{
#ifndef TB_CONFIG_MICRO_ENABLE
// init dns server
if (!tb_dns_server_init()) return tb_false;
// init dns cache
if (!tb_dns_cache_init()) return tb_false;
// register printf("%{ipv4}", &ipv4);
tb_printf_object_register("ipv4", tb_network_printf_format_ipv4);
// register printf("%{ipv6}", &ipv6);
tb_printf_object_register("ipv6", tb_network_printf_format_ipv6);
// register printf("%{unixaddr}", &unixaddr);
tb_printf_object_register("unixaddr", tb_network_printf_format_unixaddr);
// register printf("%{ipaddr}", &ipaddr);
tb_printf_object_register("ipaddr", tb_network_printf_format_ipaddr);
// register printf("%{hwaddr}", &hwaddr);
tb_printf_object_register("hwaddr", tb_network_printf_format_hwaddr);
#endif
// ok
return tb_true;
}
tb_void_t tb_network_exit_env()
{
#ifndef TB_CONFIG_MICRO_ENABLE
// exit dns cache
tb_dns_cache_exit();
// exit dns server
tb_dns_server_exit();
#endif
}
tbox-1.7.6/src/tbox/network/impl/network.h 0000664 0000000 0000000 00000002725 14671175054 0020560 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file network.h
* @ingroup network
*
*/
#ifndef TB_NETWORK_IMPL_NETWORK_H
#define TB_NETWORK_IMPL_NETWORK_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init network environment
*
* @return tb_true or tb_false
*/
tb_bool_t tb_network_init_env(tb_noarg_t);
/// exit network environment
tb_void_t tb_network_exit_env(tb_noarg_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/network/impl/prefix.h 0000664 0000000 0000000 00000001611 14671175054 0020355 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_NETWORK_IMPL_PREFIX_H
#define TB_NETWORK_IMPL_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/network/impl/ssl/ 0000775 0000000 0000000 00000000000 14671175054 0017511 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/network/impl/ssl/mbedtls.c 0000664 0000000 0000000 00000044040 14671175054 0021311 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file mbedtls.c
* @ingroup network
*
*/
#define TB_TRACE_MODULE_NAME "mbedtls"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include
#include
#include
#include
#include
#include
#include "../../../libc/libc.h"
#include "../../../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the ssl type
typedef struct __tb_ssl_t
{
// the ssl ctr drbg context
mbedtls_ssl_context ssl;
// the ssl entropy context
mbedtls_entropy_context entropy;
// the ssl ctr drbg context
mbedtls_ctr_drbg_context ctr_drbg;
// the ssl x509 crt
mbedtls_x509_crt x509_crt;
// the ssl config
mbedtls_ssl_config conf;
// is opened?
tb_bool_t bopened;
// the state
tb_size_t state;
// the last wait
tb_long_t lwait;
// the timeout
tb_long_t timeout;
// the read func
tb_ssl_func_read_t read;
// the writ func
tb_ssl_func_writ_t writ;
// the wait func
tb_ssl_func_wait_t wait;
// the priv data
tb_cpointer_t priv;
}tb_ssl_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static __tb_inline__ tb_void_t tb_ssl_error(tb_char_t const* info, tb_long_t error)
{
#ifdef MEBDTLS_ERROR_C
tb_char_t error_info[256] = {0};
mbedtls_strerror(error, error_info, sizeof(error_info));
tb_trace_e("%s: error: %ld, %s", info, error, error_info);
#else
tb_trace_e("%s: error: %ld", info, error);
#endif
}
#if TB_TRACE_MODULE_DEBUG && defined(__tb_debug__) && defined(MBEDTLS_DEBUG_C)
static tb_void_t tb_ssl_trace_info(tb_pointer_t ctx, tb_int_t level, tb_char_t const* file, tb_int_t line, tb_char_t const* info)
{
if (level < 1)
{
// strip file directory
tb_char_t const* filesep = tb_strchr(file, '/');
if (filesep) file = filesep + 1;
// trace
tb_printf("%s: %04d: %s", file, line, info);
}
}
#endif
static tb_long_t tb_ssl_sock_read(tb_cpointer_t priv, tb_byte_t* data, tb_size_t size)
{
// check
tb_assert_and_check_return_val(priv, -1);
// recv it
return tb_socket_recv((tb_socket_ref_t)priv, data, size);
}
static tb_long_t tb_ssl_sock_writ(tb_cpointer_t priv, tb_byte_t const* data, tb_size_t size)
{
// check
tb_assert_and_check_return_val(priv, -1);
// send it
return tb_socket_send((tb_socket_ref_t)priv, data, size);
}
static tb_long_t tb_ssl_sock_wait(tb_cpointer_t priv, tb_size_t events, tb_long_t timeout)
{
// check
tb_assert_and_check_return_val(priv, -1);
// wait it
return tb_socket_wait((tb_socket_ref_t)priv, events, timeout);
}
static tb_int_t tb_ssl_func_read(tb_pointer_t priv, tb_byte_t* data, size_t size)
{
// check
tb_ssl_t* ssl = (tb_ssl_t*)priv;
tb_assert_and_check_return_val(ssl && ssl->read, -1);
// recv it
tb_long_t real = ssl->read(ssl->priv, data, (tb_size_t)size);
// trace
tb_trace_d("read: %ld", real);
// ok? clear wait
if (real > 0) ssl->lwait = 0;
// peer closed?
else if (!real && ssl->lwait > 0 && (ssl->lwait & TB_SOCKET_EVENT_RECV)) real = MBEDTLS_ERR_NET_CONN_RESET;
// no data? continue to read it
else if (!real) real = MBEDTLS_ERR_SSL_WANT_READ;
// failed?
else real = MBEDTLS_ERR_NET_RECV_FAILED;
// ok?
return (tb_int_t)real;
}
static tb_int_t tb_ssl_func_writ(tb_pointer_t priv, tb_byte_t const* data, size_t size)
{
// check
tb_ssl_t* ssl = (tb_ssl_t*)priv;
tb_assert_and_check_return_val(ssl && ssl->writ, -1);
// send it
tb_long_t real = ssl->writ(ssl->priv, data, (tb_size_t)size);
// trace
tb_trace_d("writ: %ld", real);
// ok? clear wait
if (real > 0) ssl->lwait = 0;
// peer closed?
else if (!real && ssl->lwait > 0 && (ssl->lwait & TB_SOCKET_EVENT_SEND)) real = MBEDTLS_ERR_NET_CONN_RESET;
// no data? continue to writ
else if (!real) real = MBEDTLS_ERR_SSL_WANT_WRITE;
// failed?
else real = MBEDTLS_ERR_NET_SEND_FAILED;
// ok?
return (tb_int_t)real;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_ssl_ref_t tb_ssl_init(tb_bool_t bserver)
{
// done
tb_bool_t ok = tb_false;
tb_ssl_t* ssl = tb_null;
tb_char_t const* pers = "tbox";
tb_size_t perslen = tb_strlen(pers);
tb_int_t error = -1;
do
{
// make ssl
ssl = tb_malloc0_type(tb_ssl_t);
tb_assert_and_check_break(ssl);
// init timeout, 30s
ssl->timeout = 30000;
// init ssl x509_crt
mbedtls_x509_crt_init(&ssl->x509_crt);
// init ssl ctr_drbg context
mbedtls_ctr_drbg_init(&ssl->ctr_drbg);
// init ssl context
mbedtls_ssl_init(&ssl->ssl);
// init ssl entropy context
mbedtls_entropy_init(&ssl->entropy);
if ((error = mbedtls_ctr_drbg_seed(&ssl->ctr_drbg, mbedtls_entropy_func, &ssl->entropy, (tb_byte_t const*)pers, perslen)))
{
tb_ssl_error("mbedtls_ctr_drbg_seed() failed", error);
break;
}
#ifdef MBEDTLS_CERTS_C
// init ssl ca certificate
if ((error = mbedtls_x509_crt_parse(&ssl->x509_crt, (tb_byte_t const*)mbedtls_test_cas_pem, mbedtls_test_cas_pem_len)))
{
tb_ssl_error("parse x509_crt failed", error);
break;
}
#endif
// init ssl config
mbedtls_ssl_config_init(&ssl->conf);
// init ssl endpoint
if ((error = mbedtls_ssl_config_defaults(&ssl->conf, bserver? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)))
{
tb_ssl_error("mbedtls_ssl_config_defaults() failed", error);
break;
}
// SSLv3 is deprecated, set minimum to TLS 1.0
mbedtls_ssl_conf_min_version(&ssl->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1);
// init ssl authmode: optional
mbedtls_ssl_conf_authmode(&ssl->conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
// init ssl ca chain
mbedtls_ssl_conf_ca_chain(&ssl->conf, &ssl->x509_crt, tb_null);
// init ssl random generator
mbedtls_ssl_conf_rng(&ssl->conf, mbedtls_ctr_drbg_random, &ssl->ctr_drbg);
// enable ssl debug?
#if TB_TRACE_MODULE_DEBUG && defined(__tb_debug__) && defined(MBEDTLS_DEBUG_C)
mbedtls_debug_set_threshold(4);
mbedtls_ssl_conf_dbg(&ssl->conf, tb_ssl_trace_info, tb_null);
#endif
// setup ssl config
if ((error = mbedtls_ssl_setup(&ssl->ssl, &ssl->conf)))
{
tb_ssl_error("mbedtls_ssl_setup() failed", error);
break;
}
// init state
ssl->state = TB_STATE_OK;
// ok
ok = tb_true;
} while (0);
// failed? exit it
if (!ok)
{
if (ssl) tb_ssl_exit((tb_ssl_ref_t)ssl);
ssl = tb_null;
}
// ok?
return (tb_ssl_ref_t)ssl;
}
tb_void_t tb_ssl_exit(tb_ssl_ref_t self)
{
// check
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return(ssl);
// close it first
tb_ssl_close(self);
// exit ssl x509 crt
mbedtls_x509_crt_free(&ssl->x509_crt);
// exit ssl
mbedtls_ssl_free(&ssl->ssl);
// exit ssl entropy
mbedtls_entropy_free(&ssl->entropy);
// exit ssl ctr drbg
mbedtls_ctr_drbg_free(&ssl->ctr_drbg);
// exit ssl config
mbedtls_ssl_config_free(&ssl->conf);
// exit it
tb_free(ssl);
}
tb_void_t tb_ssl_set_bio_sock(tb_ssl_ref_t self, tb_socket_ref_t sock)
{
// the ssl
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return(ssl);
// set bio: sock
tb_ssl_set_bio_func(self, tb_ssl_sock_read, tb_ssl_sock_writ, tb_ssl_sock_wait, sock);
}
tb_void_t tb_ssl_set_bio_func(tb_ssl_ref_t self, tb_ssl_func_read_t read, tb_ssl_func_writ_t writ, tb_ssl_func_wait_t wait, tb_cpointer_t priv)
{
// check
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return(ssl && read && writ);
// save func
ssl->read = read;
ssl->writ = writ;
ssl->wait = wait;
ssl->priv = priv;
// set bio: func
mbedtls_ssl_set_bio(&ssl->ssl, ssl, tb_ssl_func_writ, tb_ssl_func_read, tb_null);
}
tb_void_t tb_ssl_set_timeout(tb_ssl_ref_t self, tb_long_t timeout)
{
// check
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return(ssl);
// save timeout
ssl->timeout = timeout;
}
tb_bool_t tb_ssl_open(tb_ssl_ref_t self)
{
// check
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return_val(ssl && ssl->wait, tb_false);
// open it
tb_long_t ok = -1;
while (!(ok = tb_ssl_open_try(self)))
{
// wait it
ok = tb_ssl_wait(self, TB_SOCKET_EVENT_RECV | TB_SOCKET_EVENT_SEND, ssl->timeout);
tb_check_break(ok > 0);
}
// ok?
return ok > 0? tb_true : tb_false;
}
tb_long_t tb_ssl_open_try(tb_ssl_ref_t self)
{
// check
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return_val(ssl, -1);
// done
tb_long_t ok = -1;
do
{
// init state
ssl->state = TB_STATE_OK;
// have been opened already?
if (ssl->bopened)
{
ok = 1;
break;
}
// done handshake
tb_long_t error = mbedtls_ssl_handshake(&ssl->ssl);
// trace
tb_trace_d("open: handshake: %ld", error);
// ok?
if (!error) ok = 1;
// peer closed
else if (error == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY || error == MBEDTLS_ERR_NET_CONN_RESET)
{
tb_trace_d("open: handshake: closed: %ld", error);
ssl->state = TB_STATE_CLOSED;
}
// continue to wait it?
else if (error == MBEDTLS_ERR_SSL_WANT_READ || error == MBEDTLS_ERR_SSL_WANT_WRITE)
{
// trace
tb_trace_d("open: handshake: wait: %s: ..", error == MBEDTLS_ERR_SSL_WANT_READ? "read" : "writ");
// continue it
ok = 0;
// save state
ssl->state = (error == MBEDTLS_ERR_SSL_WANT_READ)? TB_STATE_SOCK_SSL_WANT_READ : TB_STATE_SOCK_SSL_WANT_WRIT;
}
// failed?
else
{
// trace
tb_ssl_error("open: handshake: failed", error);
// save state
ssl->state = TB_STATE_SOCK_SSL_FAILED;
}
} while (0);
// ok?
if (ok > 0 && !ssl->bopened)
{
// done ssl verify
#if TB_TRACE_MODULE_DEBUG && defined(__tb_debug__)
tb_long_t error = 0;
if ((error = mbedtls_ssl_get_verify_result(&ssl->ssl)))
{
if ((error & MBEDTLS_X509_BADCERT_EXPIRED)) tb_trace_d("server certificate has expired");
if ((error & MBEDTLS_X509_BADCERT_REVOKED)) tb_trace_d("server certificate has been revoked");
if ((error & MBEDTLS_X509_BADCERT_CN_MISMATCH)) tb_trace_d("cn mismatch");
if ((error & MBEDTLS_X509_BADCERT_NOT_TRUSTED)) tb_trace_d("self-signed or not signed by a trusted ca");
tb_ssl_error("verify: failed", error);
}
#endif
// opened
ssl->bopened = tb_true;
}
// failed?
else if (ok < 0)
{
// save state
if (ssl->state == TB_STATE_OK)
ssl->state = TB_STATE_SOCK_SSL_FAILED;
}
// trace
tb_trace_d("open: handshake: %s", ok > 0? "ok" : (!ok? ".." : "no"));
// ok?
return ok;
}
tb_bool_t tb_ssl_close(tb_ssl_ref_t self)
{
// check
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return_val(ssl, tb_false);
// close it
tb_long_t ok = -1;
while (!(ok = tb_ssl_close_try(self)))
{
// wait it
ok = tb_ssl_wait(self, TB_SOCKET_EVENT_RECV | TB_SOCKET_EVENT_SEND, ssl->timeout);
tb_check_break(ok > 0);
}
// ok?
return ok > 0? tb_true : tb_false;
}
tb_long_t tb_ssl_close_try(tb_ssl_ref_t self)
{
// the ssl
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return_val(ssl, -1);
// done
tb_long_t ok = -1;
do
{
// init state
ssl->state = TB_STATE_OK;
// have been closed already?
if (!ssl->bopened)
{
ok = 1;
break;
}
// done close notify
tb_long_t error = mbedtls_ssl_close_notify(&ssl->ssl);
// trace
tb_trace_d("close: close_notify: %ld", error);
// ok?
if (!error) ok = 1;
// continue to wait it?
else if (error == MBEDTLS_ERR_SSL_WANT_READ || error == MBEDTLS_ERR_SSL_WANT_WRITE)
{
// trace
tb_trace_d("close: close_notify: wait: %s: ..", error == MBEDTLS_ERR_SSL_WANT_READ? "read" : "writ");
// continue it
ok = 0;
// save state
ssl->state = (error == MBEDTLS_ERR_SSL_WANT_READ)? TB_STATE_SOCK_SSL_WANT_READ : TB_STATE_SOCK_SSL_WANT_WRIT;
}
// failed?
else
{
// trace
tb_ssl_error("close: close_notify: failed", error);
// save state
ssl->state = TB_STATE_SOCK_SSL_FAILED;
}
} while (0);
// ok or failed?
if (ok > 0)
{
// closed
ssl->bopened = tb_false;
// clear ssl
mbedtls_ssl_session_reset(&ssl->ssl);
}
// trace
tb_trace_d("close: close_notify: %s", ok > 0? "ok" : (!ok? ".." : "no"));
// ok?
return ok;
}
tb_long_t tb_ssl_read(tb_ssl_ref_t self, tb_byte_t* data, tb_size_t size)
{
// check
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return_val(ssl && ssl->bopened && data, -1);
// read it
tb_long_t real = mbedtls_ssl_read(&ssl->ssl, data, size);
// want read? continue it
if (real == MBEDTLS_ERR_SSL_WANT_READ || !real)
{
// trace
tb_trace_d("read: want read");
// save state
ssl->state = TB_STATE_SOCK_SSL_WANT_READ;
return 0;
}
// want writ? continue it
else if (real == MBEDTLS_ERR_SSL_WANT_WRITE)
{
// trace
tb_trace_d("read: want writ");
// save state
ssl->state = TB_STATE_SOCK_SSL_WANT_WRIT;
return 0;
}
// peer closed?
else if (real == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY || real == MBEDTLS_ERR_NET_CONN_RESET)
{
// trace
tb_trace_d("read: peer closed");
// save state
ssl->state = TB_STATE_CLOSED;
return -1;
}
// failed?
else if (real < 0)
{
// trace
tb_ssl_error("read: failed:", real);
// save state
ssl->state = TB_STATE_SOCK_SSL_FAILED;
return -1;
}
// trace
tb_trace_d("read: %ld", real);
// ok
return real;
}
tb_long_t tb_ssl_writ(tb_ssl_ref_t self, tb_byte_t const* data, tb_size_t size)
{
// check
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return_val(ssl && ssl->bopened && data, -1);
// writ it
tb_long_t real = mbedtls_ssl_write(&ssl->ssl, data, size);
// want read? continue it
if (real == MBEDTLS_ERR_SSL_WANT_READ)
{
// trace
tb_trace_d("writ: want read");
// save state
ssl->state = TB_STATE_SOCK_SSL_WANT_READ;
return 0;
}
// want writ? continue it
else if (real == MBEDTLS_ERR_SSL_WANT_WRITE || !real)
{
// trace
tb_trace_d("writ: want writ");
// save state
ssl->state = TB_STATE_SOCK_SSL_WANT_WRIT;
return 0;
}
// peer closed?
else if (real == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY || real == MBEDTLS_ERR_NET_CONN_RESET)
{
// trace
tb_trace_d("writ: peer closed");
// save state
ssl->state = TB_STATE_CLOSED;
return -1;
}
// failed?
else if (real < 0)
{
// trace
tb_ssl_error("writ: failed", real);
// save state
ssl->state = TB_STATE_SOCK_SSL_FAILED;
return -1;
}
// trace
tb_trace_d("writ: %ld", real);
// ok
return real;
}
tb_long_t tb_ssl_wait(tb_ssl_ref_t self, tb_size_t events, tb_long_t timeout)
{
// check
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return_val(ssl && ssl->wait, -1);
// the ssl state
switch (ssl->state)
{
// wait read
case TB_STATE_SOCK_SSL_WANT_READ:
events = TB_SOCKET_EVENT_RECV;
break;
// wait writ
case TB_STATE_SOCK_SSL_WANT_WRIT:
events = TB_SOCKET_EVENT_SEND;
break;
// ok, wait it
case TB_STATE_OK:
break;
// failed or closed?
default:
return -1;
}
// trace
tb_trace_d("wait: %lu: ..", events);
// wait it
ssl->lwait = ssl->wait(ssl->priv, events, timeout);
// timeout or failed? save state
if (ssl->lwait < 0) ssl->state = TB_STATE_SOCK_SSL_WAIT_FAILED;
else if (!ssl->lwait) ssl->state = TB_STATE_SOCK_SSL_TIMEOUT;
// trace
tb_trace_d("wait: %ld", ssl->lwait);
// ok?
return ssl->lwait;
}
tb_size_t tb_ssl_state(tb_ssl_ref_t self)
{
// check
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return_val(ssl, TB_STATE_UNKNOWN_ERROR);
// the state
return ssl->state;
}
tbox-1.7.6/src/tbox/network/impl/ssl/openssl.c 0000664 0000000 0000000 00000046514 14671175054 0021352 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file openssl.c
* @ingroup network
*
*/
#define TB_TRACE_MODULE_NAME "openssl"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include
#include
#include
#include
#include "../../../utils/utils.h"
#include "../../../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the ssl type
typedef struct __tb_ssl_t
{
// the ssl session
SSL* ssl;
// the ssl context
SSL_CTX* ctx;
// the ssl bio
BIO* bio;
// is opened?
tb_bool_t bopened;
// the state
tb_size_t state;
// the last wait
tb_long_t lwait;
// the timeout
tb_long_t timeout;
// the read func
tb_ssl_func_read_t read;
// the writ func
tb_ssl_func_writ_t writ;
// the wait func
tb_ssl_func_wait_t wait;
// the priv data
tb_cpointer_t priv;
}tb_ssl_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* declaration
*/
static int tb_ssl_bio_method_init(BIO* bio);
static int tb_ssl_bio_method_exit(BIO* bio);
static int tb_ssl_bio_method_read(BIO* bio, char* data, int size);
static int tb_ssl_bio_method_writ(BIO* bio, char const* data, int size);
static long tb_ssl_bio_method_ctrl(BIO* bio, int cmd, long num, void* ptr);
static int tb_ssl_bio_method_puts(BIO* bio, char const* data);
static int tb_ssl_bio_method_gets(BIO* bio, char* data, int size);
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
static BIO_METHOD* g_ssl_bio_method = tb_null;
/* //////////////////////////////////////////////////////////////////////////////////////
* library implementation
*/
static tb_handle_t tb_ssl_library_init(tb_cpointer_t* ppriv)
{
// init it
SSL_library_init();
// init bio method
g_ssl_bio_method = BIO_meth_new(BIO_TYPE_SOURCE_SINK | 100, "ssl_bio");
tb_assert_and_check_return_val(g_ssl_bio_method, tb_null);
// init methods
BIO_meth_set_write(g_ssl_bio_method, tb_ssl_bio_method_writ);
BIO_meth_set_read(g_ssl_bio_method, tb_ssl_bio_method_read);
BIO_meth_set_puts(g_ssl_bio_method, tb_ssl_bio_method_puts);
BIO_meth_set_gets(g_ssl_bio_method, tb_ssl_bio_method_gets);
BIO_meth_set_ctrl(g_ssl_bio_method, tb_ssl_bio_method_ctrl);
BIO_meth_set_create(g_ssl_bio_method, tb_ssl_bio_method_init);
BIO_meth_set_destroy(g_ssl_bio_method, tb_ssl_bio_method_exit);
// ok
return ppriv;
}
static tb_void_t tb_ssl_library_exit(tb_handle_t ssl, tb_cpointer_t priv)
{
if (g_ssl_bio_method) BIO_meth_free(g_ssl_bio_method);
g_ssl_bio_method = tb_null;
}
static tb_handle_t tb_ssl_library_load()
{
return tb_singleton_instance(TB_SINGLETON_TYPE_LIBRARY_OPENSSL, tb_ssl_library_init, tb_ssl_library_exit, tb_null, tb_null);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_int_t tb_ssl_verify(tb_int_t ok, X509_STORE_CTX* ctx)
{
return 1;
}
#ifdef __tb_debug__
static tb_char_t const* tb_ssl_error(tb_long_t error)
{
// done
switch (error)
{
case SSL_ERROR_NONE:
return "SSL_ERROR_NONE";
case SSL_ERROR_SSL:
return "SSL_ERROR_SSL";
case SSL_ERROR_WANT_READ:
return "SSL_ERROR_WANT_READ";
case SSL_ERROR_WANT_WRITE:
return "SSL_ERROR_WANT_WRITE";
case SSL_ERROR_WANT_X509_LOOKUP:
return "SSL_ERROR_WANT_X509_LOOKUP";
case SSL_ERROR_SYSCALL:
return "SSL_ERROR_SYSCALL";
case SSL_ERROR_ZERO_RETURN:
return "SSL_ERROR_ZERO_RETURN";
case SSL_ERROR_WANT_CONNECT:
return "SSL_ERROR_WANT_CONNECT";
case SSL_ERROR_WANT_ACCEPT:
return "SSL_ERROR_WANT_ACCEPT";
default:
return "UNKOWN_ERROR_VALUE";
}
return "";
}
#endif
static tb_long_t tb_ssl_sock_read(tb_cpointer_t priv, tb_byte_t* data, tb_size_t size)
{
tb_assert_and_check_return_val(priv, -1);
return tb_socket_recv((tb_socket_ref_t)priv, data, size);
}
static tb_long_t tb_ssl_sock_writ(tb_cpointer_t priv, tb_byte_t const* data, tb_size_t size)
{
tb_assert_and_check_return_val(priv, -1);
return tb_socket_send((tb_socket_ref_t)priv, data, size);
}
static tb_long_t tb_ssl_sock_wait(tb_cpointer_t priv, tb_size_t events, tb_long_t timeout)
{
tb_assert_and_check_return_val(priv, -1);
return tb_socket_wait((tb_socket_ref_t)priv, events, timeout);
}
static int tb_ssl_bio_method_init(BIO* bio)
{
tb_assert_and_check_return_val(bio, 0);
// trace
tb_trace_d("bio: init");
// init
BIO_set_init(bio, 1);
BIO_set_data(bio, tb_null);
BIO_set_shutdown(bio, 1);
return 1;
}
static int tb_ssl_bio_method_exit(BIO* bio)
{
// check
tb_assert_and_check_return_val(bio, 0);
// trace
tb_trace_d("bio: exit");
// exit
BIO_set_init(bio, 0);
BIO_set_data(bio, tb_null);
BIO_set_shutdown(bio, 0);
return 1;
}
static int tb_ssl_bio_method_read(BIO* bio, char* data, int size)
{
// check
tb_assert_and_check_return_val(bio && data && size >= 0, -1);
// the ssl
tb_ssl_t* ssl = (tb_ssl_t*)BIO_get_data(bio);
tb_assert_and_check_return_val(ssl && ssl->read, -1);
// read data
tb_long_t real = ssl->read(ssl->priv, (tb_byte_t*)data, size);
// trace
tb_trace_d("bio: read: real: %ld, size: %d", real, size);
// ok? clear wait
if (real > 0) ssl->lwait = 0;
// peer closed?
else if (!real && ssl->lwait > 0 && (ssl->lwait & TB_SOCKET_EVENT_RECV))
{
BIO_clear_retry_flags(bio);
real = -1;
}
// no data? continue to read it
else if (!real)
{
BIO_clear_retry_flags(bio);
BIO_set_retry_read(bio);
real = -1;
}
// failed?
else
{
BIO_clear_retry_flags(bio);
real = -1;
}
return (int)real;
}
static int tb_ssl_bio_method_writ(BIO* bio, char const* data, int size)
{
// check
tb_assert_and_check_return_val(bio && data && size >= 0, -1);
// the ssl
tb_ssl_t* ssl = (tb_ssl_t*)BIO_get_data(bio);
tb_assert_and_check_return_val(ssl && ssl->writ, -1);
// write data
tb_long_t real = ssl->writ(ssl->priv, (tb_byte_t const*)data, size);
// trace
tb_trace_d("bio: writ: real: %ld, size: %d", real, size);
// ok? clear wait
if (real > 0) ssl->lwait = 0;
// peer closed?
else if (!real && ssl->lwait > 0 && (ssl->lwait & TB_SOCKET_EVENT_SEND))
{
BIO_clear_retry_flags(bio);
real = -1;
}
// no data? continue to writ
else if (!real)
{
BIO_clear_retry_flags(bio);
BIO_set_retry_write(bio);
real = -1;
}
// failed?
else
{
BIO_clear_retry_flags(bio);
real = -1;
}
return (int)real;
}
static long tb_ssl_bio_method_ctrl(BIO* bio, int cmd, long num, void* ptr)
{
// check
tb_assert_and_check_return_val(bio, -1);
// the ssl
tb_ssl_t* ssl = (tb_ssl_t*)BIO_get_data(bio);
tb_assert_and_check_return_val(ssl, -1);
tb_long_t ok = 0;
switch (cmd)
{
case BIO_CTRL_FLUSH:
{
tb_trace_d("bio: ctrl: flush");
ok = 1;
}
break;
default:
{
tb_trace_d("bio: ctrl: unknown: %d", cmd);
}
break;
}
return (long)ok;
}
static int tb_ssl_bio_method_puts(BIO* bio, char const* data)
{
tb_assert_and_check_return_val(bio && data, -1);
tb_trace_d("bio: puts: %s", data);
return tb_ssl_bio_method_writ(bio, data, (tb_int_t)tb_strlen(data));
}
static int tb_ssl_bio_method_gets(BIO* bio, char* data, int size)
{
tb_assert_and_check_return_val(bio && data, -1);
tb_trace_d("bio: gets: %d", size);
return tb_ssl_bio_method_read(bio, data, size);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_ssl_ref_t tb_ssl_init(tb_bool_t bserver)
{
tb_bool_t ok = tb_false;
tb_ssl_t* ssl = tb_null;
do
{
// load openssl library
if (!tb_ssl_library_load()) break;
// check
tb_assert_and_check_break(g_ssl_bio_method);
// make ssl
ssl = tb_malloc0_type(tb_ssl_t);
tb_assert_and_check_break(ssl);
// init timeout, 30s
ssl->timeout = 30000;
// init ctx
ssl->ctx = SSL_CTX_new(SSLv23_method());
tb_assert_and_check_break(ssl->ctx);
// make ssl
ssl->ssl = SSL_new(ssl->ctx);
tb_assert_and_check_break(ssl->ssl);
// init endpoint
if (bserver) SSL_set_accept_state(ssl->ssl);
else SSL_set_connect_state(ssl->ssl);
// init verify
SSL_set_verify(ssl->ssl, 0, tb_ssl_verify);
// init bio
ssl->bio = BIO_new(g_ssl_bio_method);
tb_assert_and_check_break(ssl->bio);
// set bio to ssl
BIO_set_data(ssl->bio, ssl);
SSL_set_bio(ssl->ssl, ssl->bio, ssl->bio);
// init state
ssl->state = TB_STATE_OK;
ok = tb_true;
} while (0);
// failed? exit it
if (!ok)
{
if (ssl) tb_ssl_exit((tb_ssl_ref_t)ssl);
ssl = tb_null;
}
return (tb_ssl_ref_t)ssl;
}
tb_void_t tb_ssl_exit(tb_ssl_ref_t self)
{
// the ssl
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return(ssl);
// close it first
tb_ssl_close(self);
// exit ssl
if (ssl->ssl) SSL_free(ssl->ssl);
ssl->ssl = tb_null;
// exit ctx
if (ssl->ctx) SSL_CTX_free(ssl->ctx);
ssl->ctx = tb_null;
// exit it
tb_free(ssl);
}
tb_void_t tb_ssl_set_bio_sock(tb_ssl_ref_t self, tb_socket_ref_t sock)
{
// the ssl
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return(ssl);
// set bio: sock
tb_ssl_set_bio_func(self, tb_ssl_sock_read, tb_ssl_sock_writ, tb_ssl_sock_wait, sock);
}
tb_void_t tb_ssl_set_bio_func(tb_ssl_ref_t self, tb_ssl_func_read_t read, tb_ssl_func_writ_t writ, tb_ssl_func_wait_t wait, tb_cpointer_t priv)
{
// the ssl
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return(ssl && read && writ);
// save func
ssl->read = read;
ssl->writ = writ;
ssl->wait = wait;
ssl->priv = priv;
}
tb_void_t tb_ssl_set_timeout(tb_ssl_ref_t self, tb_long_t timeout)
{
// the ssl
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return(ssl);
// save timeout
ssl->timeout = timeout;
}
tb_bool_t tb_ssl_open(tb_ssl_ref_t self)
{
// the ssl
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return_val(ssl && ssl->wait, tb_false);
// open it
tb_long_t ok = -1;
while (!(ok = tb_ssl_open_try(self)))
{
// wait it
ok = tb_ssl_wait(self, TB_SOCKET_EVENT_RECV | TB_SOCKET_EVENT_SEND, ssl->timeout);
tb_check_break(ok > 0);
}
return ok > 0? tb_true : tb_false;
}
tb_long_t tb_ssl_open_try(tb_ssl_ref_t self)
{
// the ssl
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return_val(ssl && ssl->ssl, -1);
tb_long_t ok = -1;
do
{
// init state
ssl->state = TB_STATE_OK;
// have been opened already?
if (ssl->bopened)
{
ok = 1;
break;
}
// do handshake
tb_long_t r = SSL_do_handshake(ssl->ssl);
// trace
tb_trace_d("open: handshake: %ld", r);
// ok?
if (r == 1) ok = 1;
// continue ?
else if (!r) ok = 0;
else
{
// the error
tb_long_t error = SSL_get_error(ssl->ssl, (tb_int_t)r);
// wait?
if (error == SSL_ERROR_WANT_WRITE || error == SSL_ERROR_WANT_READ)
{
tb_trace_d("open: handshake: wait: %s: ..", error == SSL_ERROR_WANT_READ? "read" : "writ");
ok = 0;
ssl->state = (error == SSL_ERROR_WANT_READ)? TB_STATE_SOCK_SSL_WANT_READ : TB_STATE_SOCK_SSL_WANT_WRIT;
}
// failed?
else
{
tb_trace_d("open: handshake: failed: %s", tb_ssl_error(error));
ssl->state = TB_STATE_SOCK_SSL_FAILED;
}
}
} while (0);
// ok?
if (ok > 0)
{
// opened
ssl->bopened = tb_true;
}
// failed?
else if (ok < 0)
{
// save state
if (ssl->state == TB_STATE_OK)
ssl->state = TB_STATE_SOCK_SSL_FAILED;
}
// trace
tb_trace_d("open: handshake: %s", ok > 0? "ok" : (!ok? ".." : "no"));
return ok;
}
tb_bool_t tb_ssl_close(tb_ssl_ref_t self)
{
// the ssl
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return_val(ssl, tb_false);
// open it
tb_long_t ok = -1;
while (!(ok = tb_ssl_close_try(self)))
{
// wait it
ok = tb_ssl_wait(self, TB_SOCKET_EVENT_RECV | TB_SOCKET_EVENT_SEND, ssl->timeout);
tb_check_break(ok > 0);
}
return ok > 0? tb_true : tb_false;
}
tb_long_t tb_ssl_close_try(tb_ssl_ref_t self)
{
// the ssl
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return_val(ssl, -1);
tb_long_t ok = -1;
do
{
// init state
ssl->state = TB_STATE_OK;
// have been closed already?
if (!ssl->bopened || !ssl->ssl)
{
ok = 1;
break;
}
// do shutdown
tb_long_t r = SSL_shutdown(ssl->ssl);
// trace
tb_trace_d("close: shutdown: %ld", r);
// ok?
if (r == 1) ok = 1;
// continue?
else if (!r) ok = 0;
else
{
// the error
tb_long_t error = SSL_get_error(ssl->ssl, (tb_int_t)r);
// wait?
if (error == SSL_ERROR_WANT_WRITE || error == SSL_ERROR_WANT_READ)
{
// trace
tb_trace_d("close: shutdown: wait: %s: ..", error == SSL_ERROR_WANT_READ? "read" : "writ");
// continue it
ok = 0;
// save state
ssl->state = (error == SSL_ERROR_WANT_READ)? TB_STATE_SOCK_SSL_WANT_READ : TB_STATE_SOCK_SSL_WANT_WRIT;
}
// failed?
else
{
// trace
tb_trace_d("close: shutdown: failed: %s", tb_ssl_error(error));
// save state
ssl->state = TB_STATE_SOCK_SSL_FAILED;
}
}
} while (0);
// ok or failed?
if (!ok)
{
// closed
ssl->bopened = tb_false;
// clear ssl
if (ssl->ssl) SSL_clear(ssl->ssl);
}
// trace
tb_trace_d("close: shutdown: %s", ok > 0? "ok" : (!ok? ".." : "no"));
return ok;
}
tb_long_t tb_ssl_read(tb_ssl_ref_t self, tb_byte_t* data, tb_size_t size)
{
// the ssl
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return_val(ssl && ssl->ssl && ssl->bopened && data, -1);
// read it
tb_long_t real = SSL_read(ssl->ssl, data, (tb_int_t)size);
// trace
tb_trace_d("read: %ld", real);
if (real < 0)
{
// the error
tb_long_t error = SSL_get_error(ssl->ssl, (tb_int_t)real);
// want read? continue it
if (error == SSL_ERROR_WANT_READ)
{
// trace
tb_trace_d("read: want read");
// save state
ssl->state = TB_STATE_SOCK_SSL_WANT_READ;
return 0;
}
// want writ? continue it
else if (error == SSL_ERROR_WANT_WRITE)
{
// trace
tb_trace_d("read: want writ");
// save state
ssl->state = TB_STATE_SOCK_SSL_WANT_WRIT;
return 0;
}
// failed?
else
{
// trace
tb_trace_d("read: failed: %ld, %s", real, tb_ssl_error(error));
// save state
ssl->state = TB_STATE_SOCK_SSL_FAILED;
return -1;
}
}
// closed?
else if (!real)
{
// trace
tb_trace_d("read: closed");
// save state
ssl->state = TB_STATE_CLOSED;
return -1;
}
return real;
}
tb_long_t tb_ssl_writ(tb_ssl_ref_t self, tb_byte_t const* data, tb_size_t size)
{
// the ssl
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return_val(ssl && ssl->ssl && ssl->bopened && data, -1);
// writ it
tb_long_t real = SSL_write(ssl->ssl, data, (tb_int_t)size);
// trace
tb_trace_d("writ: %ld", real);
// done
if (real < 0)
{
// the error
tb_long_t error = SSL_get_error(ssl->ssl, (tb_int_t)real);
// want read? continue it
if (error == SSL_ERROR_WANT_READ)
{
// trace
tb_trace_d("writ: want read");
// save state
ssl->state = TB_STATE_SOCK_SSL_WANT_READ;
return 0;
}
// want writ? continue it
else if (error == SSL_ERROR_WANT_WRITE)
{
// trace
tb_trace_d("writ: want writ");
// save state
ssl->state = TB_STATE_SOCK_SSL_WANT_WRIT;
return 0;
}
// failed?
else
{
// trace
tb_trace_d("writ: failed: %ld, %s", real, tb_ssl_error(error));
// save state
ssl->state = TB_STATE_SOCK_SSL_FAILED;
return -1;
}
}
// closed?
else if (!real)
{
// trace
tb_trace_d("read: closed");
// save state
ssl->state = TB_STATE_CLOSED;
return -1;
}
return real;
}
tb_long_t tb_ssl_wait(tb_ssl_ref_t self, tb_size_t events, tb_long_t timeout)
{
// the ssl
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return_val(ssl && ssl->wait, -1);
// the ssl state
switch (ssl->state)
{
// wait read
case TB_STATE_SOCK_SSL_WANT_READ:
events = TB_SOCKET_EVENT_RECV;
break;
// wait writ
case TB_STATE_SOCK_SSL_WANT_WRIT:
events = TB_SOCKET_EVENT_SEND;
break;
// ok, wait it
case TB_STATE_OK:
break;
// failed or closed?
default:
return -1;
}
// trace
tb_trace_d("wait: %lu: ..", events);
// wait it
ssl->lwait = ssl->wait(ssl->priv, events, timeout);
// timeout or failed? save state
if (ssl->lwait < 0) ssl->state = TB_STATE_SOCK_SSL_WAIT_FAILED;
else if (!ssl->lwait) ssl->state = TB_STATE_SOCK_SSL_TIMEOUT;
// trace
tb_trace_d("wait: %ld", ssl->lwait);
return ssl->lwait;
}
tb_size_t tb_ssl_state(tb_ssl_ref_t self)
{
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return_val(ssl, TB_STATE_UNKNOWN_ERROR);
return ssl->state;
}
tbox-1.7.6/src/tbox/network/impl/ssl/polarssl.c 0000664 0000000 0000000 00000041230 14671175054 0021514 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file polarssl.c
* @ingroup network
*
*/
#define TB_TRACE_MODULE_NAME "polarssl"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include
#include
#include
#include
#include
#include "../../../libc/libc.h"
#include "../../../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the ssl type
typedef struct __tb_ssl_t
{
// the ssl context
ssl_context ssl;
// the ssl entropy context
entropy_context entropy;
// the ssl ctr drbg context
ctr_drbg_context ctr_drbg;
// the ssl x509 crt
x509_crt x509_crt;
// is opened?
tb_bool_t bopened;
// the state
tb_size_t state;
// the last wait
tb_long_t lwait;
// the timeout
tb_long_t timeout;
// the read func
tb_ssl_func_read_t read;
// the writ func
tb_ssl_func_writ_t writ;
// the wait func
tb_ssl_func_wait_t wait;
// the priv data
tb_cpointer_t priv;
}tb_ssl_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static __tb_inline__ tb_void_t tb_ssl_error(tb_char_t const* info, tb_long_t error)
{
#ifdef POLARSSL_ERROR_C
tb_char_t error_info[256] = {0};
polarssl_strerror(error, error_info, sizeof(error_info));
tb_trace_e("%s: error: %ld, %s", info, error, error_info);
#else
tb_trace_e("%s: error: %ld", info, error);
#endif
}
#if TB_TRACE_MODULE_DEBUG && defined(__tb_debug__)
static tb_void_t tb_ssl_trace_info(tb_pointer_t priv, tb_int_t level, tb_char_t const* info)
{
// trace
if (level < 1) tb_printf("%s", info);
}
#endif
static tb_long_t tb_ssl_sock_read(tb_cpointer_t priv, tb_byte_t* data, tb_size_t size)
{
// check
tb_assert_and_check_return_val(priv, -1);
// recv it
return tb_socket_recv((tb_socket_ref_t)priv, data, size);
}
static tb_long_t tb_ssl_sock_writ(tb_cpointer_t priv, tb_byte_t const* data, tb_size_t size)
{
// check
tb_assert_and_check_return_val(priv, -1);
// send it
return tb_socket_send((tb_socket_ref_t)priv, data, size);
}
static tb_long_t tb_ssl_sock_wait(tb_cpointer_t priv, tb_size_t events, tb_long_t timeout)
{
// check
tb_assert_and_check_return_val(priv, -1);
// wait it
return tb_socket_wait((tb_socket_ref_t)priv, events, timeout);
}
static tb_int_t tb_ssl_func_read(tb_pointer_t priv, tb_byte_t* data, size_t size)
{
// check
tb_ssl_t* ssl = (tb_ssl_t*)priv;
tb_assert_and_check_return_val(ssl && ssl->read, -1);
// recv it
tb_long_t real = ssl->read(ssl->priv, data, (tb_size_t)size);
// trace
tb_trace_d("read: %ld", real);
// ok? clear wait
if (real > 0) ssl->lwait = 0;
// peer closed?
else if (!real && ssl->lwait > 0 && (ssl->lwait & TB_SOCKET_EVENT_RECV)) real = POLARSSL_ERR_NET_CONN_RESET;
// no data? continue to read it
else if (!real) real = POLARSSL_ERR_NET_WANT_READ;
// failed?
else real = POLARSSL_ERR_NET_RECV_FAILED;
// ok?
return (tb_int_t)real;
}
static tb_int_t tb_ssl_func_writ(tb_pointer_t priv, tb_byte_t const* data, size_t size)
{
// check
tb_ssl_t* ssl = (tb_ssl_t*)priv;
tb_assert_and_check_return_val(ssl && ssl->writ, -1);
// send it
tb_long_t real = ssl->writ(ssl->priv, data, (tb_size_t)size);
// trace
tb_trace_d("writ: %ld", real);
// ok? clear wait
if (real > 0) ssl->lwait = 0;
// peer closed?
else if (!real && ssl->lwait > 0 && (ssl->lwait & TB_SOCKET_EVENT_SEND)) real = POLARSSL_ERR_NET_CONN_RESET;
// no data? continue to writ
else if (!real) real = POLARSSL_ERR_NET_WANT_WRITE;
// failed?
else real = POLARSSL_ERR_NET_SEND_FAILED;
// ok?
return (tb_int_t)real;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_ssl_ref_t tb_ssl_init(tb_bool_t bserver)
{
// done
tb_bool_t ok = tb_false;
tb_ssl_t* ssl = tb_null;
do
{
// make ssl
ssl = tb_malloc0_type(tb_ssl_t);
tb_assert_and_check_break(ssl);
// init timeout, 30s
ssl->timeout = 30000;
// init ssl x509_crt
x509_crt_init(&ssl->x509_crt);
// init ssl entropy context
entropy_init(&ssl->entropy);
// init ssl ctr_drbg context
tb_long_t error = 0;
if ((error = ctr_drbg_init(&ssl->ctr_drbg, entropy_func, &ssl->entropy, tb_null, 0)))
{
tb_ssl_error("init ctr_drbg failed", error);
break;
}
#ifdef POLARSSL_CERTS_C
// init ssl ca certificate
if ((error = x509_crt_parse(&ssl->x509_crt, (tb_byte_t const*)test_ca_list, tb_strlen(test_ca_list))))
{
tb_ssl_error("parse x509_crt failed", error);
break;
}
#endif
// init ssl context
if ((error = ssl_init(&ssl->ssl)))
{
tb_ssl_error("init ssl failed", error);
break;
}
// init ssl endpoint
ssl_set_endpoint(&ssl->ssl, bserver? SSL_IS_SERVER : SSL_IS_CLIENT);
// init ssl authmode: optional
ssl_set_authmode(&ssl->ssl, SSL_VERIFY_OPTIONAL);
// init ssl ca chain
ssl_set_ca_chain(&ssl->ssl, &ssl->x509_crt, tb_null, tb_null);
// init ssl random generator
ssl_set_rng(&ssl->ssl, ctr_drbg_random, &ssl->ctr_drbg);
// enable ssl debug?
#if TB_TRACE_MODULE_DEBUG && defined(__tb_debug__)
ssl_set_dbg(&ssl->ssl, tb_ssl_trace_info, tb_null);
#endif
// init state
ssl->state = TB_STATE_OK;
// ok
ok = tb_true;
} while (0);
// failed? exit it
if (!ok)
{
if (ssl) tb_ssl_exit((tb_ssl_ref_t)ssl);
ssl = tb_null;
}
// ok?
return (tb_ssl_ref_t)ssl;
}
tb_void_t tb_ssl_exit(tb_ssl_ref_t self)
{
// check
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return(ssl);
// close it first
tb_ssl_close(self);
// exit ssl x509_crt
x509_crt_free(&ssl->x509_crt);
// exit ssl
ssl_free(&ssl->ssl);
// exit ssl entropy
entropy_free(&ssl->entropy);
// exit it
tb_free(ssl);
}
tb_void_t tb_ssl_set_bio_sock(tb_ssl_ref_t self, tb_socket_ref_t sock)
{
// the ssl
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return(ssl);
// set bio: sock
tb_ssl_set_bio_func(self, tb_ssl_sock_read, tb_ssl_sock_writ, tb_ssl_sock_wait, sock);
}
tb_void_t tb_ssl_set_bio_func(tb_ssl_ref_t self, tb_ssl_func_read_t read, tb_ssl_func_writ_t writ, tb_ssl_func_wait_t wait, tb_cpointer_t priv)
{
// check
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return(ssl && read && writ);
// save func
ssl->read = read;
ssl->writ = writ;
ssl->wait = wait;
ssl->priv = priv;
// set bio: func
ssl_set_bio(&ssl->ssl, tb_ssl_func_read, ssl, tb_ssl_func_writ, ssl);
}
tb_void_t tb_ssl_set_timeout(tb_ssl_ref_t self, tb_long_t timeout)
{
// check
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return(ssl);
// save timeout
ssl->timeout = timeout;
}
tb_bool_t tb_ssl_open(tb_ssl_ref_t self)
{
// check
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return_val(ssl && ssl->wait, tb_false);
// open it
tb_long_t ok = -1;
while (!(ok = tb_ssl_open_try(self)))
{
// wait it
ok = tb_ssl_wait(self, TB_SOCKET_EVENT_RECV | TB_SOCKET_EVENT_SEND, ssl->timeout);
tb_check_break(ok > 0);
}
// ok?
return ok > 0? tb_true : tb_false;
}
tb_long_t tb_ssl_open_try(tb_ssl_ref_t self)
{
// check
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return_val(ssl, -1);
// done
tb_long_t ok = -1;
do
{
// init state
ssl->state = TB_STATE_OK;
// have been opened already?
if (ssl->bopened)
{
ok = 1;
break;
}
// done handshake
tb_long_t error = ssl_handshake(&ssl->ssl);
// trace
tb_trace_d("open: handshake: %ld", error);
// ok?
if (!error) ok = 1;
// peer closed
else if (error == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY || error == POLARSSL_ERR_NET_CONN_RESET)
{
tb_trace_d("open: handshake: closed: %ld", error);
ssl->state = TB_STATE_CLOSED;
}
// continue to wait it?
else if (error == POLARSSL_ERR_NET_WANT_READ || error == POLARSSL_ERR_NET_WANT_WRITE)
{
// trace
tb_trace_d("open: handshake: wait: %s: ..", error == POLARSSL_ERR_NET_WANT_READ? "read" : "writ");
// continue it
ok = 0;
// save state
ssl->state = (error == POLARSSL_ERR_NET_WANT_READ)? TB_STATE_SOCK_SSL_WANT_READ : TB_STATE_SOCK_SSL_WANT_WRIT;
}
// failed?
else
{
// trace
tb_ssl_error("open: handshake: failed", error);
// save state
ssl->state = TB_STATE_SOCK_SSL_FAILED;
}
} while (0);
// ok?
if (ok > 0 && !ssl->bopened)
{
// done ssl verify
#if TB_TRACE_MODULE_DEBUG && defined(__tb_debug__)
tb_long_t error = 0;
if ((error = ssl_get_verify_result(&ssl->ssl)))
{
if ((error & BADCERT_EXPIRED)) tb_trace_d("server certificate has expired");
if ((error & BADCERT_REVOKED)) tb_trace_d("server certificate has been revoked");
if ((error & BADCERT_CN_MISMATCH)) tb_trace_d("cn mismatch");
if ((error & BADCERT_NOT_TRUSTED)) tb_trace_d("self-signed or not signed by a trusted ca");
tb_ssl_error("verify: failed", error);
}
#endif
// opened
ssl->bopened = tb_true;
}
// failed?
else if (ok < 0)
{
// save state
if (ssl->state == TB_STATE_OK)
ssl->state = TB_STATE_SOCK_SSL_FAILED;
}
// trace
tb_trace_d("open: handshake: %s", ok > 0? "ok" : (!ok? ".." : "no"));
// ok?
return ok;
}
tb_bool_t tb_ssl_close(tb_ssl_ref_t self)
{
// check
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return_val(ssl, tb_false);
// close it
tb_long_t ok = -1;
while (!(ok = tb_ssl_close_try(self)))
{
// wait it
ok = tb_ssl_wait(self, TB_SOCKET_EVENT_RECV | TB_SOCKET_EVENT_SEND, ssl->timeout);
tb_check_break(ok > 0);
}
// ok?
return ok > 0? tb_true : tb_false;
}
tb_long_t tb_ssl_close_try(tb_ssl_ref_t self)
{
// the ssl
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return_val(ssl, -1);
// done
tb_long_t ok = -1;
do
{
// init state
ssl->state = TB_STATE_OK;
// have been closed already?
if (!ssl->bopened)
{
ok = 1;
break;
}
// done close notify
tb_long_t error = ssl_close_notify(&ssl->ssl);
// trace
tb_trace_d("close: close_notify: %ld", error);
// ok?
if (!error) ok = 1;
// continue to wait it?
else if (error == POLARSSL_ERR_NET_WANT_READ || error == POLARSSL_ERR_NET_WANT_WRITE)
{
// trace
tb_trace_d("close: close_notify: wait: %s: ..", error == POLARSSL_ERR_NET_WANT_READ? "read" : "writ");
// continue it
ok = 0;
// save state
ssl->state = (error == POLARSSL_ERR_NET_WANT_READ)? TB_STATE_SOCK_SSL_WANT_READ : TB_STATE_SOCK_SSL_WANT_WRIT;
}
// failed?
else
{
// trace
tb_ssl_error("close: close_notify: failed", error);
// save state
ssl->state = TB_STATE_SOCK_SSL_FAILED;
}
// clear ssl
if (ok > 0) ssl_session_reset(&ssl->ssl);
} while (0);
// ok?
if (ok > 0)
{
// closed
ssl->bopened = tb_false;
}
// failed?
else if (ok < 0)
{
// save state
if (ssl->state == TB_STATE_OK)
ssl->state = TB_STATE_SOCK_SSL_FAILED;
}
// trace
tb_trace_d("close: close_notify: %s", ok > 0? "ok" : (!ok? ".." : "no"));
// ok?
return ok;
}
tb_long_t tb_ssl_read(tb_ssl_ref_t self, tb_byte_t* data, tb_size_t size)
{
// check
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return_val(ssl && ssl->bopened && data, -1);
// read it
tb_long_t real = ssl_read(&ssl->ssl, data, size);
// want read? continue it
if (real == POLARSSL_ERR_NET_WANT_READ || !real)
{
// trace
tb_trace_d("read: want read");
// save state
ssl->state = TB_STATE_SOCK_SSL_WANT_READ;
return 0;
}
// want writ? continue it
else if (real == POLARSSL_ERR_NET_WANT_WRITE)
{
// trace
tb_trace_d("read: want writ");
// save state
ssl->state = TB_STATE_SOCK_SSL_WANT_WRIT;
return 0;
}
// peer closed?
else if (real == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY || real == POLARSSL_ERR_NET_CONN_RESET)
{
// trace
tb_trace_d("read: peer closed");
// save state
ssl->state = TB_STATE_CLOSED;
return -1;
}
// failed?
else if (real < 0)
{
// trace
tb_ssl_error("read: failed:", real);
// save state
ssl->state = TB_STATE_SOCK_SSL_FAILED;
return -1;
}
// trace
tb_trace_d("read: %ld", real);
// ok
return real;
}
tb_long_t tb_ssl_writ(tb_ssl_ref_t self, tb_byte_t const* data, tb_size_t size)
{
// check
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return_val(ssl && ssl->bopened && data, -1);
// writ it
tb_long_t real = ssl_write(&ssl->ssl, data, size);
// want read? continue it
if (real == POLARSSL_ERR_NET_WANT_READ)
{
// trace
tb_trace_d("writ: want read");
// save state
ssl->state = TB_STATE_SOCK_SSL_WANT_READ;
return 0;
}
// want writ? continue it
else if (real == POLARSSL_ERR_NET_WANT_WRITE || !real)
{
// trace
tb_trace_d("writ: want writ");
// save state
ssl->state = TB_STATE_SOCK_SSL_WANT_WRIT;
return 0;
}
// peer closed?
else if (real == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY || real == POLARSSL_ERR_NET_CONN_RESET)
{
// trace
tb_trace_d("writ: peer closed");
// save state
ssl->state = TB_STATE_CLOSED;
return -1;
}
// failed?
else if (real < 0)
{
// trace
tb_ssl_error("writ: failed", real);
// save state
ssl->state = TB_STATE_SOCK_SSL_FAILED;
return -1;
}
// trace
tb_trace_d("writ: %ld", real);
// ok
return real;
}
tb_long_t tb_ssl_wait(tb_ssl_ref_t self, tb_size_t events, tb_long_t timeout)
{
// check
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return_val(ssl && ssl->wait, -1);
// the ssl state
switch (ssl->state)
{
// wait read
case TB_STATE_SOCK_SSL_WANT_READ:
events = TB_SOCKET_EVENT_RECV;
break;
// wait writ
case TB_STATE_SOCK_SSL_WANT_WRIT:
events = TB_SOCKET_EVENT_SEND;
break;
// ok, wait it
case TB_STATE_OK:
break;
// failed or closed?
default:
return -1;
}
// trace
tb_trace_d("wait: %lu: ..", events);
// wait it
ssl->lwait = ssl->wait(ssl->priv, events, timeout);
// timeout or failed? save state
if (ssl->lwait < 0) ssl->state = TB_STATE_SOCK_SSL_WAIT_FAILED;
else if (!ssl->lwait) ssl->state = TB_STATE_SOCK_SSL_TIMEOUT;
// trace
tb_trace_d("wait: %ld", ssl->lwait);
// ok?
return ssl->lwait;
}
tb_size_t tb_ssl_state(tb_ssl_ref_t self)
{
// check
tb_ssl_t* ssl = (tb_ssl_t*)self;
tb_assert_and_check_return_val(ssl, TB_STATE_UNKNOWN_ERROR);
// the state
return ssl->state;
}
tbox-1.7.6/src/tbox/network/impl/ssl/prefix.h 0000664 0000000 0000000 00000001650 14671175054 0021161 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_NETWORK_IMPL_SSL_PREFIX_H
#define TB_NETWORK_IMPL_SSL_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#include "../../ssl.h"
#endif
tbox-1.7.6/src/tbox/network/ipaddr.c 0000664 0000000 0000000 00000042362 14671175054 0017365 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file ipaddr.c
* @ingroup network
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "ipaddr.h"
#include "../libc/libc.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static __tb_inline__ tb_bool_t tb_ipaddr_ipv6_to_ipv4(tb_ipv6_ref_t ipv6, tb_ipv4_ref_t ipv4)
{
// check
tb_assert(ipv6 && ipv4);
// is ipv4?
if (!ipv6->addr.u32[0] && !ipv6->addr.u32[1] && ipv6->addr.u32[2] == 0xffff0000)
{
// make ipv4
ipv4->u32 = ipv6->addr.u32[3];
// ok
return tb_true;
}
// failed
return tb_false;
}
static __tb_inline__ tb_bool_t tb_ipaddr_ipv4_to_ipv6(tb_ipv4_ref_t ipv4, tb_ipv6_ref_t ipv6)
{
// check
tb_assert(ipv6 && ipv4);
// make ipv6
ipv6->addr.u32[0] = 0;
ipv6->addr.u32[1] = 0;
ipv6->addr.u32[2] = 0xffff0000;
ipv6->addr.u32[3] = ipv4->u32;
ipv6->scope_id = 0;
// ok
return tb_true;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_void_t tb_ipaddr_clear(tb_ipaddr_ref_t ipaddr)
{
// check
tb_assert_and_check_return(ipaddr);
// clear it
ipaddr->family = TB_IPADDR_FAMILY_NONE;
ipaddr->have_ip = 0;
ipaddr->port = 0;
}
tb_void_t tb_ipaddr_copy(tb_ipaddr_ref_t ipaddr, tb_ipaddr_ref_t copied)
{
// check
tb_assert_and_check_return(ipaddr && copied);
// no ip? only copy port and family
if (!copied->have_ip)
{
ipaddr->port = copied->port;
ipaddr->family = copied->family;
}
// attempt to copy ipv4 fastly
else if (copied->family == TB_IPADDR_FAMILY_IPV4)
{
ipaddr->port = copied->port;
ipaddr->have_ip = 1;
ipaddr->family = TB_IPADDR_FAMILY_IPV4;
ipaddr->u.ipv4 = copied->u.ipv4;
}
// copy it
else *ipaddr = *copied;
}
tb_bool_t tb_ipaddr_is_empty(tb_ipaddr_ref_t ipaddr)
{
// check
tb_assert_and_check_return_val(ipaddr, tb_true);
// no ip?
return tb_ipaddr_ip_is_empty(ipaddr);
}
tb_bool_t tb_ipaddr_is_equal(tb_ipaddr_ref_t ipaddr, tb_ipaddr_ref_t other)
{
// check
tb_assert_and_check_return_val(ipaddr && other, tb_false);
// port is equal?
if (ipaddr->port != other->port) return tb_false;
// ip is equal?
return tb_ipaddr_ip_is_equal(ipaddr, other);
}
tb_char_t const* tb_ipaddr_cstr(tb_ipaddr_ref_t ipaddr, tb_char_t* data, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(ipaddr && data && maxn >= TB_IPADDR_CSTR_MAXN, tb_null);
// is empty?
if (tb_ipaddr_is_empty(ipaddr))
{
// make it
tb_long_t size = tb_snprintf(data, maxn - 1, "0.0.0.0:0");
if (size >= 0) data[size] = '\0';
}
// ip is empty?
else if (tb_ipaddr_ip_is_empty(ipaddr))
{
// make it
tb_long_t size = tb_snprintf(data, maxn - 1, "0.0.0.0:%u", ipaddr->port);
if (size >= 0) data[size] = '\0';
}
else if (ipaddr->family == TB_IPADDR_FAMILY_UNIX)
{
// check (again)
tb_assert_and_check_return_val(maxn >= TB_UNIXADDR_CSTR_MAXN, tb_null);
// make it
tb_unixaddr_cstr(&ipaddr->u.unixaddr, data, maxn);
}
else
{
// make it
tb_char_t buff[TB_IPADDR_CSTR_MAXN];
tb_bool_t ipv6 = ipaddr->family == TB_IPADDR_FAMILY_IPV6;
tb_long_t size = tb_snprintf(data, maxn - 1, "%s%s%s:%u", ipv6? "[" : "", tb_ipaddr_ip_cstr(ipaddr, buff, sizeof(buff)), ipv6? "]" : "", ipaddr->port);
if (size >= 0) data[size] = '\0';
}
// ok
return data;
}
tb_bool_t tb_ipaddr_set(tb_ipaddr_ref_t ipaddr, tb_char_t const* cstr, tb_uint16_t port, tb_uint8_t family)
{
// check
tb_assert_and_check_return_val(ipaddr, tb_false);
// save port
tb_ipaddr_port_set(ipaddr, family != TB_IPADDR_FAMILY_UNIX? port : 0);
// save ip address and family
return tb_ipaddr_ip_cstr_set(ipaddr, cstr, family);
}
tb_void_t tb_ipaddr_ip_clear(tb_ipaddr_ref_t ipaddr)
{
// check
tb_assert_and_check_return(ipaddr);
// clear ip
ipaddr->have_ip = 0;
}
tb_bool_t tb_ipaddr_ip_is_empty(tb_ipaddr_ref_t ipaddr)
{
// check
tb_assert_and_check_return_val(ipaddr, tb_true);
// is empty?
return !ipaddr->have_ip;
}
tb_bool_t tb_ipaddr_ip_is_any(tb_ipaddr_ref_t ipaddr)
{
// check
tb_assert_and_check_return_val(ipaddr, tb_true);
// is empty? ok
tb_check_return_val(ipaddr->have_ip, tb_true);
// done
tb_bool_t is_any = tb_true;
switch (ipaddr->family)
{
case TB_IPADDR_FAMILY_IPV4:
is_any = tb_ipv4_is_any(&ipaddr->u.ipv4);
break;
case TB_IPADDR_FAMILY_IPV6:
is_any = tb_ipv6_is_any(&ipaddr->u.ipv6);
break;
case TB_IPADDR_FAMILY_UNIX:
is_any = tb_false;
break;
default:
break;
}
// is any?
return is_any;
}
tb_bool_t tb_ipaddr_ip_is_loopback(tb_ipaddr_ref_t ipaddr)
{
// check
tb_assert_and_check_return_val(ipaddr, tb_true);
// done
tb_bool_t is_loopback = tb_false;
switch (ipaddr->family)
{
case TB_IPADDR_FAMILY_IPV4:
is_loopback = tb_ipv4_is_loopback(&ipaddr->u.ipv4);
break;
case TB_IPADDR_FAMILY_IPV6:
is_loopback = tb_ipv6_is_loopback(&ipaddr->u.ipv6);
break;
case TB_IPADDR_FAMILY_UNIX:
is_loopback = tb_false;
break;
default:
break;
}
// is loopback?
return is_loopback;
}
tb_bool_t tb_ipaddr_ip_is_equal(tb_ipaddr_ref_t ipaddr, tb_ipaddr_ref_t other)
{
// check
tb_assert_and_check_return_val(ipaddr && other, tb_false);
// both empty?
if (!ipaddr->have_ip && !other->have_ip) return tb_true;
// only one is empty?
else if (ipaddr->have_ip != other->have_ip) return tb_false;
// both ipv4?
else if (ipaddr->family == TB_IPADDR_FAMILY_IPV4 && other->family == TB_IPADDR_FAMILY_IPV4)
{
// is equal?
return tb_ipv4_is_equal(&ipaddr->u.ipv4, &other->u.ipv4);
}
// both ipv6?
else if (ipaddr->family == TB_IPADDR_FAMILY_IPV6 && other->family == TB_IPADDR_FAMILY_IPV6)
{
// is equal?
return tb_ipv6_is_equal(&ipaddr->u.ipv6, &other->u.ipv6);
}
// both unixaddr?
else if (ipaddr->family == TB_IPADDR_FAMILY_UNIX && other->family == TB_IPADDR_FAMILY_UNIX)
{
// is equal?
return tb_unixaddr_is_equal(&ipaddr->u.unixaddr, &other->u.unixaddr);
}
// only one is unixaddr?
else if (ipaddr->family == TB_IPADDR_FAMILY_UNIX || other->family == TB_IPADDR_FAMILY_UNIX) return tb_false;
// ipaddr is ipv6?
else if (ipaddr->family == TB_IPADDR_FAMILY_IPV6)
{
// is equal?
tb_ipv4_t ipv4;
return tb_ipaddr_ipv6_to_ipv4(&ipaddr->u.ipv6, &ipv4) && tb_ipv4_is_equal(&ipv4, &other->u.ipv4);
}
// other is ipv6?
else if (other->family == TB_IPADDR_FAMILY_IPV6)
{
// is equal?
tb_ipv4_t ipv4;
return tb_ipaddr_ipv6_to_ipv4(&other->u.ipv6, &ipv4) && tb_ipv4_is_equal(&ipaddr->u.ipv4, &ipv4);
}
// failed
tb_assert(0);
return tb_false;
}
tb_char_t const* tb_ipaddr_ip_cstr(tb_ipaddr_ref_t ipaddr, tb_char_t* data, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(ipaddr && data && maxn, tb_null);
// done
tb_char_t const* cstr = tb_null;
switch (ipaddr->family)
{
case TB_IPADDR_FAMILY_IPV4:
{
// make ipv4 cstr
if (ipaddr->have_ip) cstr = tb_ipv4_cstr(&ipaddr->u.ipv4, data, maxn);
else
{
// check
tb_assert(maxn >= TB_IPV4_CSTR_MAXN);
// make empty cstr
tb_long_t size = tb_snprintf(data, maxn - 1, "0.0.0.0");
if (size >= 0) data[size] = '\0';
// ok
cstr = data;
}
}
break;
case TB_IPADDR_FAMILY_IPV6:
{
// make ipv6 cstr
if (ipaddr->have_ip) cstr = tb_ipv6_cstr(&ipaddr->u.ipv6, data, maxn);
else
{
// check
tb_assert(maxn >= TB_IPV6_CSTR_MAXN);
// make empty cstr
tb_long_t size = tb_snprintf(data, maxn - 1, "::");
if (size >= 0) data[size] = '\0';
// ok
cstr = data;
}
}
break;
case TB_IPADDR_FAMILY_UNIX:
{
// make unixaddr cstr
if (ipaddr->have_ip) cstr = tb_unixaddr_cstr(&ipaddr->u.unixaddr, data, maxn);
else
{
// check
tb_assert(maxn >= TB_UNIXADDR_CSTR_MAXN);
// make empty cstr
tb_memset(data, 0, maxn);
// ok
cstr = data;
}
}
break;
default:
tb_assert(0);
break;
}
// ok?
return cstr;
}
tb_bool_t tb_ipaddr_ip_cstr_set(tb_ipaddr_ref_t ipaddr, tb_char_t const* cstr, tb_uint8_t family)
{
// no ip? clear it fastly
if (!cstr)
{
// check
tb_assert(ipaddr);
// clear it
ipaddr->family = family;
ipaddr->have_ip = 0;
return tb_true;
}
// done
tb_bool_t ok = tb_false;
tb_ipaddr_t temp;
switch (family)
{
case TB_IPADDR_FAMILY_IPV4:
{
// make ipv4
ok = tb_ipv4_cstr_set(&temp.u.ipv4, cstr);
// make family
if (ok) temp.family = family;
}
break;
case TB_IPADDR_FAMILY_IPV6:
{
// make ipv6
ok = tb_ipv6_cstr_set(&temp.u.ipv6, cstr);
// make family
if (ok) temp.family = family;
}
break;
case TB_IPADDR_FAMILY_UNIX:
{
// make unixaddr
ok = tb_unixaddr_cstr_set(&temp.u.unixaddr, cstr, tb_false);
// make family
if (ok) temp.family = family;
}
break;
default:
{
// attempt to make ipv4
if ((ok = tb_ipv4_cstr_set(&temp.u.ipv4, cstr))) temp.family = TB_IPADDR_FAMILY_IPV4;
// make ipv6
else if ((ok = tb_ipv6_cstr_set(&temp.u.ipv6, cstr))) temp.family = TB_IPADDR_FAMILY_IPV6;
}
break;
}
// ok? save it
if (ok && ipaddr)
{
// save port
temp.port = ipaddr->port;
// have ip?
temp.have_ip = 1;
// save ipaddr
tb_ipaddr_copy(ipaddr, &temp);
}
// ok?
return ok;
}
tb_void_t tb_ipaddr_ip_set(tb_ipaddr_ref_t ipaddr, tb_ipaddr_ref_t other)
{
// check
tb_assert_and_check_return(ipaddr);
// no ip? clear it
if (!other)
{
ipaddr->have_ip = 0;
return ;
}
// done
switch (other->family)
{
case TB_IPADDR_FAMILY_IPV4:
{
// save ipv4
tb_ipaddr_ipv4_set(ipaddr, &other->u.ipv4);
// save state
ipaddr->have_ip = 1;
}
break;
case TB_IPADDR_FAMILY_IPV6:
{
// save ipv6
tb_ipaddr_ipv6_set(ipaddr, &other->u.ipv6);
// save state
ipaddr->have_ip = 1;
}
break;
case TB_IPADDR_FAMILY_UNIX:
{
// save unixaddr
tb_ipaddr_unix_set(ipaddr, &other->u.unixaddr);
// save state
ipaddr->have_ip = 1;
}
default:
tb_assert(0);
break;
}
}
tb_ipv4_ref_t tb_ipaddr_ipv4(tb_ipaddr_ref_t ipaddr)
{
// check
tb_assert_and_check_return_val(ipaddr, tb_null);
// no ip?
tb_check_return_val(ipaddr->have_ip, tb_null);
// done
tb_ipv4_ref_t ipv4 = tb_null;
switch (ipaddr->family)
{
case TB_IPADDR_FAMILY_IPV4:
ipv4 = &ipaddr->u.ipv4;
break;
case TB_IPADDR_FAMILY_IPV6:
{
tb_ipv4_t temp;
if (tb_ipaddr_ipv6_to_ipv4(&ipaddr->u.ipv6, &temp))
{
ipaddr->family = TB_IPADDR_FAMILY_IPV4;
ipaddr->u.ipv4 = temp;
ipv4 = &ipaddr->u.ipv4;
}
}
break;
case TB_IPADDR_FAMILY_UNIX:
break;
default:
tb_assert(0);
break;
}
// ok?
return ipv4;
}
tb_void_t tb_ipaddr_ipv4_set(tb_ipaddr_ref_t ipaddr, tb_ipv4_ref_t ipv4)
{
// check
tb_assert_and_check_return(ipaddr);
// no ipv4? clear it
if (!ipv4)
{
ipaddr->have_ip = 0;
return ;
}
// save it
ipaddr->family = TB_IPADDR_FAMILY_IPV4;
ipaddr->have_ip = 1;
ipaddr->u.ipv4 = *ipv4;
}
tb_ipv6_ref_t tb_ipaddr_ipv6(tb_ipaddr_ref_t ipaddr)
{
// check
tb_assert_and_check_return_val(ipaddr, tb_null);
// no ip?
tb_check_return_val(ipaddr->have_ip, tb_null);
// done
tb_ipv6_ref_t ipv6 = tb_null;
switch (ipaddr->family)
{
case TB_IPADDR_FAMILY_IPV4:
{
tb_ipv6_t temp;
if (tb_ipaddr_ipv4_to_ipv6(&ipaddr->u.ipv4, &temp))
{
ipaddr->family = TB_IPADDR_FAMILY_IPV6;
ipaddr->u.ipv6 = temp;
ipv6 = &ipaddr->u.ipv6;
}
}
break;
case TB_IPADDR_FAMILY_IPV6:
ipv6 = &ipaddr->u.ipv6;
break;
case TB_IPADDR_FAMILY_UNIX:
break;
default:
tb_assert(0);
break;
}
// ok?
return ipv6;
}
tb_void_t tb_ipaddr_ipv6_set(tb_ipaddr_ref_t ipaddr, tb_ipv6_ref_t ipv6)
{
// check
tb_assert_and_check_return(ipaddr && ipv6);
// no ipv6? clear it
if (!ipv6)
{
ipaddr->have_ip = 0;
return ;
}
// save it
ipaddr->family = TB_IPADDR_FAMILY_IPV6;
ipaddr->u.ipv6 = *ipv6;
ipaddr->have_ip = 1;
}
tb_unixaddr_ref_t tb_ipaddr_unix(tb_ipaddr_ref_t ipaddr)
{
// check
tb_assert_and_check_return_val(ipaddr, tb_null);
// no ip?
tb_check_return_val(ipaddr->have_ip, tb_null);
// done
if (ipaddr->family == TB_IPADDR_FAMILY_UNIX) return &ipaddr->u.unixaddr;
return tb_null;
}
tb_void_t tb_ipaddr_unix_set(tb_ipaddr_ref_t ipaddr, tb_unixaddr_ref_t unixaddr)
{
// check
tb_assert_and_check_return(ipaddr && unixaddr);
// no ipv6? clear it
if (!unixaddr)
{
ipaddr->have_ip = 0;
return ;
}
// save it
ipaddr->family = TB_IPADDR_FAMILY_UNIX;
ipaddr->u.unixaddr = *unixaddr;
ipaddr->have_ip = 1;
}
tb_bool_t tb_ipaddr_unix_set_cstr(tb_ipaddr_ref_t ipaddr, tb_char_t const* cstr, tb_bool_t is_abstract)
{
// check
tb_assert_and_check_return_val(ipaddr, tb_false);
// make unixaddr
tb_ipaddr_t temp;
if (!tb_unixaddr_cstr_set(&temp.u.unixaddr, cstr, is_abstract))
return tb_false;
// make family
temp.family = TB_IPADDR_FAMILY_UNIX;
// have ip?
temp.have_ip = 1;
// Set port to 0 = not used
temp.port = 0;
// save ipaddr
tb_ipaddr_copy(ipaddr, &temp);
return tb_true;
}
tb_size_t tb_ipaddr_family(tb_ipaddr_ref_t ipaddr)
{
// check
tb_assert_and_check_return_val(ipaddr, TB_IPADDR_FAMILY_NONE);
// the family
return ipaddr->family;
}
tb_void_t tb_ipaddr_family_set(tb_ipaddr_ref_t ipaddr, tb_size_t family)
{
// check
tb_assert_and_check_return(ipaddr);
// ipv4 => ipv6?
if (ipaddr->family == TB_IPADDR_FAMILY_IPV4 && family == TB_IPADDR_FAMILY_IPV6)
{
tb_ipv6_t temp;
if (tb_ipaddr_ipv4_to_ipv6(&ipaddr->u.ipv4, &temp))
{
ipaddr->family = TB_IPADDR_FAMILY_IPV6;
ipaddr->u.ipv6 = temp;
}
else
{
// check
tb_assert(0);
}
}
// ipv6 => ipv4?
else if (ipaddr->family == TB_IPADDR_FAMILY_IPV4 && family == TB_IPADDR_FAMILY_IPV6)
{
tb_ipv4_t temp;
if (tb_ipaddr_ipv6_to_ipv4(&ipaddr->u.ipv6, &temp))
{
ipaddr->family = TB_IPADDR_FAMILY_IPV4;
ipaddr->u.ipv4 = temp;
}
else
{
// check
tb_assert(0);
}
}
// unixaddr cannot be converted
else if ((ipaddr->family == TB_IPADDR_FAMILY_UNIX) != (family == TB_IPADDR_FAMILY_UNIX) && family != TB_IPADDR_FAMILY_NONE)
{
// check
tb_assert(0);
}
else ipaddr->family = family;
// no family? clear ip
if (!ipaddr->family) ipaddr->have_ip = 0;
}
tb_uint16_t tb_ipaddr_port(tb_ipaddr_ref_t ipaddr)
{
// check
tb_assert_and_check_return_val(ipaddr, 0);
// get port
return ipaddr->port;
}
tb_void_t tb_ipaddr_port_set(tb_ipaddr_ref_t ipaddr, tb_uint16_t port)
{
// check
tb_assert_and_check_return(ipaddr);
// set port
ipaddr->port = port;
}
tbox-1.7.6/src/tbox/network/ipaddr.h 0000664 0000000 0000000 00000017034 14671175054 0017370 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file ipaddr.h
* @ingroup network
*
*/
#ifndef TB_NETWORK_IPADDR_H
#define TB_NETWORK_IPADDR_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "ipv4.h"
#include "ipv6.h"
#include "unixaddr.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/// the address string data maxn
#define TB_IPADDR_CSTR_MAXN (TB_IPV6_CSTR_MAXN + 20)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the ip address family enum
typedef enum __tb_ipaddr_family_e
{
TB_IPADDR_FAMILY_NONE = 0
, TB_IPADDR_FAMILY_IPV4 = 1
, TB_IPADDR_FAMILY_IPV6 = 2
, TB_IPADDR_FAMILY_UNIX = 3
}tb_ipaddr_family_e;
/// the ip address type
typedef struct __tb_ipaddr_t
{
/// the family
tb_uint8_t family : 7;
/// have ip?
tb_uint8_t have_ip : 1;
/// the port
tb_uint16_t port;
/// the address
union
{
/// the ipv4
tb_ipv4_t ipv4;
/// the ipv6
tb_ipv6_t ipv6;
/// the unixaddr
tb_unixaddr_t unixaddr;
}u;
}tb_ipaddr_t, *tb_ipaddr_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! clear the address
*
* @param ipaddr the address
*/
tb_void_t tb_ipaddr_clear(tb_ipaddr_ref_t ipaddr);
/*! copy address, faster than *ipaddr = *other
*
* @param ipaddr the address
* @param copied the copied address
*/
tb_void_t tb_ipaddr_copy(tb_ipaddr_ref_t ipaddr, tb_ipaddr_ref_t copied);
/*! is empty?
*
* @param ipaddr the address
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ipaddr_is_empty(tb_ipaddr_ref_t ipaddr);
/*! is equal?
*
* @param ipaddr the address
* @param other the other address
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ipaddr_is_equal(tb_ipaddr_ref_t ipaddr, tb_ipaddr_ref_t other);
/*! get the address string
*
* @param ipaddr the address
* @param data the address string data
* @param maxn the address string data maxn
*
* @return the address string
*/
tb_char_t const* tb_ipaddr_cstr(tb_ipaddr_ref_t ipaddr, tb_char_t* data, tb_size_t maxn);
/*! set the ip address from string
*
* @param ipaddr the address, only analyze format if be null
* @param cstr the address string, init any address if be null
* @param port the port, optional
* @param family the address family, will analyze family automaticly if be none, optional
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ipaddr_set(tb_ipaddr_ref_t ipaddr, tb_char_t const* cstr, tb_uint16_t port, tb_uint8_t family);
/*! clear ip
*
* @param ipaddr the address
*/
tb_void_t tb_ipaddr_ip_clear(tb_ipaddr_ref_t ipaddr);
/*! the ip is empty?
*
* @param ipaddr the address
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ipaddr_ip_is_empty(tb_ipaddr_ref_t ipaddr);
/*! the ip is any?
*
* @param ipaddr the address
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ipaddr_ip_is_any(tb_ipaddr_ref_t ipaddr);
/*! the ip is loopback?
*
* @param ipaddr the address
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ipaddr_ip_is_loopback(tb_ipaddr_ref_t ipaddr);
/*! the ip is equal?
*
* @param ipaddr the address
* @param other the other address
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ipaddr_ip_is_equal(tb_ipaddr_ref_t ipaddr, tb_ipaddr_ref_t other);
/*! get the ip address string
*
* @param ipaddr the address
* @param data the address string data
* @param maxn the address string data maxn
*
* @return the address string
*/
tb_char_t const* tb_ipaddr_ip_cstr(tb_ipaddr_ref_t ipaddr, tb_char_t* data, tb_size_t maxn);
/*! set the ip address from string
*
* @param ipaddr the address, only analyze format if be null
* @param cstr the address string
* @param family the address family, will analyze family automaticly if be none
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ipaddr_ip_cstr_set(tb_ipaddr_ref_t ipaddr, tb_char_t const* cstr, tb_uint8_t family);
/*! only set ip address
*
* @param ipaddr the address
* @param other the other address with ip data, clear it if be null
*/
tb_void_t tb_ipaddr_ip_set(tb_ipaddr_ref_t ipaddr, tb_ipaddr_ref_t other);
/*! get the ipv4 address
*
* @param ipaddr the address
*
* @return the ipv4
*/
tb_ipv4_ref_t tb_ipaddr_ipv4(tb_ipaddr_ref_t ipaddr);
/*! set the address from ipv4
*
* @param ipaddr the address
* @param ipv4 the ipv4, clear it if be null
*/
tb_void_t tb_ipaddr_ipv4_set(tb_ipaddr_ref_t ipaddr, tb_ipv4_ref_t ipv4);
/*! get the ipv6 address
*
* @param ipaddr the address
*
* @return the ipv6
*/
tb_ipv6_ref_t tb_ipaddr_ipv6(tb_ipaddr_ref_t ipaddr);
/*! set the address from ipv6
*
* @param ipaddr the address
* @param ipv6 the ipv6, clear it if be null
*/
tb_void_t tb_ipaddr_ipv6_set(tb_ipaddr_ref_t ipaddr, tb_ipv6_ref_t ipv6);
/*! get the unix socket path
*
* @param ipaddr the address
*
* @return the unixaddr
*/
tb_unixaddr_ref_t tb_ipaddr_unix(tb_ipaddr_ref_t ipaddr);
/*! set the path from unix
*
* @param ipaddr the address
* @param unixaddr the unixaddr, clear it if be null
*/
tb_void_t tb_ipaddr_unix_set(tb_ipaddr_ref_t ipaddr, tb_unixaddr_ref_t unixaddr);
/*! set the unix socket address from string
*
* @param ipaddr the address
* @param cstr the address string
* @param is_abstract true if the address is abstract address
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ipaddr_unix_set_cstr(tb_ipaddr_ref_t ipaddr, tb_char_t const* cstr, tb_bool_t is_abstract);
/*! get the address family
*
* @param ipaddr the address
*
* @return the family
*/
tb_size_t tb_ipaddr_family(tb_ipaddr_ref_t ipaddr);
/*! set the address family
*
* @param ipaddr the address
* @param family the family
*/
tb_void_t tb_ipaddr_family_set(tb_ipaddr_ref_t ipaddr, tb_size_t family);
/*! get the address port
*
* @param ipaddr the address
*
* @return the port
*/
tb_uint16_t tb_ipaddr_port(tb_ipaddr_ref_t ipaddr);
/*! set the address family
*
* @param ipaddr the address
* @param port the port
*/
tb_void_t tb_ipaddr_port_set(tb_ipaddr_ref_t ipaddr, tb_uint16_t port);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/network/ipv4.c 0000664 0000000 0000000 00000006372 14671175054 0017005 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file ipv4.c
* @ingroup network
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "ipv4"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "ipv4.h"
#include "../libc/libc.h"
#include "../math/math.h"
#include "../utils/utils.h"
#include "../string/string.h"
#include "../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_void_t tb_ipv4_clear(tb_ipv4_ref_t ipv4)
{
// check
tb_assert_and_check_return(ipv4);
// clear it
ipv4->u32 = 0;
}
tb_bool_t tb_ipv4_is_any(tb_ipv4_ref_t ipv4)
{
// check
tb_assert_and_check_return_val(ipv4, tb_true);
// is empty?
return !ipv4->u32;
}
tb_bool_t tb_ipv4_is_loopback(tb_ipv4_ref_t ipv4)
{
// check
tb_assert_and_check_return_val(ipv4, tb_false);
// is loopback?
return (ipv4->u32 == 0x0100007f);
}
tb_bool_t tb_ipv4_is_equal(tb_ipv4_ref_t ipv4, tb_ipv4_ref_t other)
{
// check
tb_assert_and_check_return_val(ipv4 && other, tb_false);
// is equal?
return ipv4->u32 == other->u32;
}
tb_char_t const* tb_ipv4_cstr(tb_ipv4_ref_t ipv4, tb_char_t* data, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(ipv4 && data && maxn >= TB_IPV4_CSTR_MAXN, tb_null);
// make it
tb_long_t size = tb_snprintf(data, maxn - 1, "%u.%u.%u.%u", ipv4->u8[0], ipv4->u8[1], ipv4->u8[2], ipv4->u8[3]);
if (size >= 0) data[size] = '\0';
// ok
return data;
}
tb_bool_t tb_ipv4_cstr_set(tb_ipv4_ref_t ipv4, tb_char_t const* cstr)
{
// check
tb_assert_and_check_return_val(cstr, tb_false);
// done
tb_uint32_t r = 0;
tb_uint32_t v = 0;
tb_char_t c = '\0';
tb_size_t i = 0;
tb_char_t const* p = cstr;
do
{
// the character
c = *p++;
// digit?
if (tb_isdigit10(c) && v <= 0xff)
{
v *= 10;
v += (tb_uint32_t)(c - '0') & 0xff;
}
// '.' or '\0'?
else if ((c == '.' || !c) && v <= 0xff)
{
r |= ((tb_uint32_t)v) << ((i++) << 3);
v = 0;
}
// failed?
else
{
// trace
tb_trace_d("invalid ipv4 addr: %s", cstr);
// clear it
i = 0;
break;
}
} while (c);
// save it if ok
if (ipv4) ipv4->u32 = r;
// ok?
return i == 4;
}
tbox-1.7.6/src/tbox/network/ipv4.h 0000664 0000000 0000000 00000005537 14671175054 0017014 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file ipv4.h
* @ingroup network
*
*/
#ifndef TB_NETWORK_IPV4_H
#define TB_NETWORK_IPV4_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/// the ipv4 string data maxn
#define TB_IPV4_CSTR_MAXN (16)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/*! the ipv4 type
*
* xxx.xxx.xxx.xxx
*/
typedef union __tb_ipv4_t
{
/// u32, little-endian
tb_uint32_t u32;
/// u16
tb_uint16_t u16[2];
/// u8
tb_uint8_t u8[4];
}tb_ipv4_t, *tb_ipv4_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! clear the ipv4
*
* @param ipv4 the ipv4
*/
tb_void_t tb_ipv4_clear(tb_ipv4_ref_t ipv4);
/*! is any address?
*
* @param ipv4 the ipv4
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ipv4_is_any(tb_ipv4_ref_t ipv4);
/*! is loopback address?
*
* @param ipv4 the ipv4
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ipv4_is_loopback(tb_ipv4_ref_t ipv4);
/*! is equal?
*
* @param ipv4 the ipv4
* @param other the other ipv4
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ipv4_is_equal(tb_ipv4_ref_t ipv4, tb_ipv4_ref_t other);
/*! get the ipv4 string
*
* @param ipv4 the ipv4
* @param data the ipv4 data
* @param maxn the data maxn
*
* @return the ipv4 address
*/
tb_char_t const* tb_ipv4_cstr(tb_ipv4_ref_t ipv4, tb_char_t* data, tb_size_t maxn);
/*! set the ipv4 from string
*
* @param ipv4 the ipv4
* @param cstr the ipv4 string
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ipv4_cstr_set(tb_ipv4_ref_t ipv4, tb_char_t const* cstr);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/network/ipv6.c 0000664 0000000 0000000 00000022333 14671175054 0017002 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file ipv6.c
* @ingroup network
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "ipv6"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "ipv6.h"
#include "ipv4.h"
#include "ipaddr.h"
#include "../libc/libc.h"
#include "../math/math.h"
#include "../utils/utils.h"
#include "../string/string.h"
#include "../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_void_t tb_ipv6_clear(tb_ipv6_ref_t ipv6)
{
// check
tb_assert_and_check_return(ipv6);
// clear it
tb_memset(ipv6, 0, sizeof(tb_ipv6_t));
}
tb_bool_t tb_ipv6_is_any(tb_ipv6_ref_t ipv6)
{
// check
tb_assert_and_check_return_val(ipv6, tb_true);
// is any?
return !(ipv6->addr.u32[0] || ipv6->addr.u32[1] || ipv6->addr.u32[2] || ipv6->addr.u32[3]);
}
tb_bool_t tb_ipv6_is_loopback(tb_ipv6_ref_t ipv6)
{
// check
tb_assert_and_check_return_val(ipv6, tb_true);
// is loopback?
return !(ipv6->addr.u32[0] || ipv6->addr.u32[1] || ipv6->addr.u32[2]) && (ipv6->addr.u32[3] == 0x01000000);
}
tb_bool_t tb_ipv6_is_linklocal(tb_ipv6_ref_t ipv6)
{
// check
tb_assert_and_check_return_val(ipv6, tb_true);
// is linklocal?
return (ipv6->addr.u8[0] == 0xfe) && ((ipv6->addr.u8[1] & 0xc0) == 0x80);
}
tb_bool_t tb_ipv6_is_mc_linklocal(tb_ipv6_ref_t ipv6)
{
// check
tb_assert_and_check_return_val(ipv6, tb_true);
// is mc linklocal?
return tb_ipv6_is_multicast(ipv6) && ((ipv6->addr.u8[1] & 0x0f) == 0x02);
}
tb_bool_t tb_ipv6_is_sitelocal(tb_ipv6_ref_t ipv6)
{
// check
tb_assert_and_check_return_val(ipv6, tb_true);
// is sitelocal?
return (ipv6->addr.u8[0] == 0xfe) && ((ipv6->addr.u8[1] & 0xc0) == 0xc0);
}
tb_bool_t tb_ipv6_is_multicast(tb_ipv6_ref_t ipv6)
{
// check
tb_assert_and_check_return_val(ipv6, tb_true);
// is multicast?
return (ipv6->addr.u8[0] == 0xff);
}
tb_bool_t tb_ipv6_is_equal(tb_ipv6_ref_t ipv6, tb_ipv6_ref_t other)
{
// check
tb_assert_and_check_return_val(ipv6 && other, tb_false);
// have scope id?
tb_bool_t have_scope_id = tb_ipv6_is_linklocal(ipv6) || tb_ipv6_is_mc_linklocal(ipv6);
// is equal?
return (!have_scope_id || (ipv6->scope_id == other->scope_id))
&& (ipv6->addr.u32[0] == other->addr.u32[0])
&& (ipv6->addr.u32[1] == other->addr.u32[1])
&& (ipv6->addr.u32[2] == other->addr.u32[2])
&& (ipv6->addr.u32[3] == other->addr.u32[3]);
}
tb_char_t const* tb_ipv6_cstr(tb_ipv6_ref_t ipv6, tb_char_t* data, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(ipv6 && data && maxn >= TB_IPV6_CSTR_MAXN, tb_null);
// make scope_id
tb_char_t scope_id[20] = {0};
tb_bool_t have_scope_id = tb_ipv6_is_linklocal(ipv6) || tb_ipv6_is_mc_linklocal(ipv6);
if (have_scope_id) tb_snprintf(scope_id, sizeof(scope_id) - 1, "%%%u", ipv6->scope_id);
// make ipv6
tb_long_t size = tb_snprintf( data
, maxn - 1
, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x%s"
, tb_bits_swap_u16(ipv6->addr.u16[0])
, tb_bits_swap_u16(ipv6->addr.u16[1])
, tb_bits_swap_u16(ipv6->addr.u16[2])
, tb_bits_swap_u16(ipv6->addr.u16[3])
, tb_bits_swap_u16(ipv6->addr.u16[4])
, tb_bits_swap_u16(ipv6->addr.u16[5])
, tb_bits_swap_u16(ipv6->addr.u16[6])
, tb_bits_swap_u16(ipv6->addr.u16[7])
, have_scope_id? scope_id : "");
if (size >= 0) data[size] = '\0';
// ok
return data;
}
tb_bool_t tb_ipv6_cstr_set(tb_ipv6_ref_t ipv6, tb_char_t const* cstr)
{
// check
tb_assert_and_check_return_val(cstr, tb_false);
// ipv4: ::ffff:xxx.xxx.xxx.xxx?
if (!tb_strnicmp(cstr, "::ffff:", 7))
{
// attempt to make ipv6 from ipv4
tb_ipv4_t ipv4;
if (tb_ipv4_cstr_set(&ipv4, cstr + 7))
{
// make ipv6
ipv6->addr.u32[0] = 0;
ipv6->addr.u32[1] = 0;
ipv6->addr.u32[2] = 0xffff0000;
ipv6->addr.u32[3] = ipv4.u32;
// ok
return tb_true;
}
}
// ipv4: ::xxx.xxx.xxx.xxx?
else if (!tb_strnicmp(cstr, "::", 2))
{
// attempt to make ipv6 from ipv4
tb_ipv4_t ipv4;
if (tb_ipv4_cstr_set(&ipv4, cstr + 2))
{
// make ipv6
ipv6->addr.u32[0] = 0;
ipv6->addr.u32[1] = 0;
ipv6->addr.u32[2] = 0;
ipv6->addr.u32[3] = ipv4.u32;
// ok
return tb_true;
}
}
// done
tb_uint32_t v = 0;
tb_size_t i = 0;
tb_char_t c = '\0';
tb_char_t const* p = cstr;
tb_bool_t ok = tb_true;
tb_bool_t stub = tb_false;
tb_char_t prev = '\0';
tb_ipv6_t temp = {0};
do
{
// save previous character
prev = c;
// the character
c = *p++;
// digit?
if (tb_isdigit16(c) && v <= 0xffff)
{
// update value
if (tb_isdigit10(c))
v = (v << 4) + (c - '0');
else if (c > ('a' - 1) && c < ('f' + 1))
v = (v << 4) + (c - 'a') + 10;
else if (c > ('A' - 1) && c < ('F' + 1))
v = (v << 4) + (c - 'A') + 10;
else
{
// abort
tb_assert(0);
// failed
ok = tb_false;
break;
}
}
// "::"?
else if (c == ':' && *p == ':' && p[1] != ':' && !stub)
{
// save value
temp.addr.u16[i++] = tb_bits_swap_u16(v);
// clear value
v = 0;
// clear previous value
prev = '\0';
// find the left count of ':'
tb_long_t n = 0;
tb_char_t const* q = p;
while (*q)
{
if (*q == ':') n++;
q++;
}
tb_check_break_state(n <= 6, ok, tb_false);
// compute the stub count
n = 8 - n - i;
tb_check_break_state(n > 0, ok, tb_false);
// save the stub value
while (n-- > 0) temp.addr.u16[i++] = 0;
// only one "::"
stub = tb_true;
// skip ':'
p++;
}
// ':' or '\0' or '%'?
else if (i < 8 && ((c == ':' && *p != ':') || !c) && v <= 0xffff && prev)
{
// save value
temp.addr.u16[i++] = tb_bits_swap_u16(v);
// clear value
v = 0;
// clear previous value
prev = '\0';
}
// "%xxx"?
else if (i == 7 && c == '%' && *p)
{
// save value
temp.addr.u16[i++] = tb_bits_swap_u16(v);
// is scope id?
if (tb_isdigit(*p))
{
// save the scope id
temp.scope_id = tb_atoi(p);
// trace
tb_trace_d("scope_id: %u", temp.scope_id);
}
#ifndef TB_CONFIG_MICRO_ENABLE
// is interface name?
else
{
// trace
tb_trace_d("name: %s", p);
// get the scope id from the interface name
tb_ipaddr_t ipaddr;
if (tb_ifaddrs_ipaddr(tb_ifaddrs(), p, tb_false, TB_IPADDR_FAMILY_IPV6, &ipaddr))
{
// trace
tb_trace_d("scope_id: %u", ipaddr.u.ipv6.scope_id);
// save the scope id
temp.scope_id = ipaddr.u.ipv6.scope_id;
}
// clear the scope id
else temp.scope_id = 0;
}
#else
// clear the scope id
else temp.scope_id = 0;
#endif
// end
break;
}
// failed?
else
{
ok = tb_false;
break;
}
} while (c);
// failed
if (i != 8) ok = tb_false;
// save it if ok
if (ok && ipv6) *ipv6 = temp;
// trace
// tb_assertf(ok, "invalid addr: %s", cstr);
// ok?
return ok;
}
tbox-1.7.6/src/tbox/network/ipv6.h 0000664 0000000 0000000 00000007451 14671175054 0017013 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file ipv6.h
* @ingroup network
*
*/
#ifndef TB_NETWORK_IPV6_H
#define TB_NETWORK_IPV6_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/// the ipv6 string data maxn
#define TB_IPV6_CSTR_MAXN (40 + 20)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/*! the ipv6 type
*
*
* xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
* xxxx::xxxx:xxxx
* ::ffff:xxx.xxx.xxx.xxx
* ::fe80:1%1
*
*/
typedef struct __tb_ipv6_t
{
/// the scope id
tb_uint32_t scope_id;
/// the address
union
{
/// u32, little-endian
tb_uint32_t u32[4];
/// u16, little-endian
tb_uint16_t u16[8];
/// u8
tb_uint8_t u8[16];
} addr;
}tb_ipv6_t, *tb_ipv6_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! clear the ipv6
*
* @param ipv6 the ipv6
*/
tb_void_t tb_ipv6_clear(tb_ipv6_ref_t ipv6);
/*! is any address?
*
* @param ipv6 the ipv6
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ipv6_is_any(tb_ipv6_ref_t ipv6);
/*! is loopback address?
*
* @param ipv6 the ipv6
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ipv6_is_loopback(tb_ipv6_ref_t ipv6);
/*! is linklocal address?
*
* @param ipv6 the ipv6
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ipv6_is_linklocal(tb_ipv6_ref_t ipv6);
/*! is mc linklocal address?
*
* @param ipv6 the ipv6
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ipv6_is_mc_linklocal(tb_ipv6_ref_t ipv6);
/*! is sitelocal address?
*
* @param ipv6 the ipv6
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ipv6_is_sitelocal(tb_ipv6_ref_t ipv6);
/*! is multicast address?
*
* @param ipv6 the ipv6
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ipv6_is_multicast(tb_ipv6_ref_t ipv6);
/*! is equal?
*
* @param ipv6 the ipv6
* @param other the other ipv6
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ipv6_is_equal(tb_ipv6_ref_t ipv6, tb_ipv6_ref_t other);
/*! get the ipv6 string
*
* @param ipv6 the ipv6
* @param data the ipv6 string data
* @param maxn the ipv6 string data maxn
*
* @return the ipv6 string
*/
tb_char_t const* tb_ipv6_cstr(tb_ipv6_ref_t ipv6, tb_char_t* data, tb_size_t maxn);
/*! set the ipv6 from string
*
* @param ipv6 the ipv6
* @param cstr the ipv6 string
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ipv6_cstr_set(tb_ipv6_ref_t ipv6, tb_char_t const* cstr);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/network/network.h 0000664 0000000 0000000 00000002107 14671175054 0017611 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file network.h
* @defgroup network
*
*/
#ifndef TB_NETWORK_H
#define TB_NETWORK_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "ssl.h"
#include "url.h"
#include "ipv4.h"
#include "ipv6.h"
#include "unixaddr.h"
#include "ipaddr.h"
#include "hwaddr.h"
#include "http.h"
#include "cookies.h"
#include "dns/dns.h"
#endif
tbox-1.7.6/src/tbox/network/prefix.h 0000664 0000000 0000000 00000001577 14671175054 0017427 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_NETWORK_PREFIX_H
#define TB_NETWORK_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/network/ssl.h 0000664 0000000 0000000 00000013453 14671175054 0016727 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file ssl.h
* @ingroup network
*
*/
#ifndef TB_NETWORK_SSL_H
#define TB_NETWORK_SSL_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// enable ssl?
#if defined(TB_CONFIG_PACKAGE_HAVE_OPENSSL) \
|| defined(TB_CONFIG_PACKAGE_HAVE_MBEDTLS) \
|| defined(TB_CONFIG_PACKAGE_HAVE_POLARSSL)
# define TB_SSL_ENABLE
#else
# undef TB_SSL_ENABLE
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/*! the ssl read func type
*
* @param priv the priv data for context
* @param data the data
* @param size the size
*
* @return the real size, no data: 0, failed: -1
*/
typedef tb_long_t (*tb_ssl_func_read_t)(tb_cpointer_t priv, tb_byte_t* data, tb_size_t size);
/*! the ssl writ func type
*
* @param priv the priv data for context
* @param data the data
* @param size the size
*
* @return the real size, no data: 0, failed: -1
*/
typedef tb_long_t (*tb_ssl_func_writ_t)(tb_cpointer_t priv, tb_byte_t const* data, tb_size_t size);
/*! the ssl wait func type
*
* @param priv the priv data for context
* @param code the events code
* @param timeout the timeout
*
* @return the real code, no event: 0, failed or closed: -1
*/
typedef tb_long_t (*tb_ssl_func_wait_t)(tb_cpointer_t priv, tb_size_t code, tb_long_t timeout);
/// the ssl ref type
typedef __tb_typeref__(ssl);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init ssl
*
* @param bserver is server endpoint?
*
* @return the ssl
*/
tb_ssl_ref_t tb_ssl_init(tb_bool_t bserver);
/*! exit ssl
*
* @param ssl the ssl
*/
tb_void_t tb_ssl_exit(tb_ssl_ref_t ssl);
/*! set ssl bio sock
*
* @param ssl the ssl
* @param sock the sock handle, non-blocking
*/
tb_void_t tb_ssl_set_bio_sock(tb_ssl_ref_t ssl, tb_socket_ref_t sock);
/*! set ssl bio read and writ func
*
* @param ssl the ssl
* @param read the read func
* @param writ the writ func
* #param wait the wait func only for tb_ssl_open and tb_ssl_wait
* @param priv the priv data
*/
tb_void_t tb_ssl_set_bio_func(tb_ssl_ref_t ssl, tb_ssl_func_read_t read, tb_ssl_func_writ_t writ, tb_ssl_func_wait_t wait, tb_cpointer_t priv);
/*! set ssl timeout for opening
*
* @param ssl the ssl
* @param timeout the timeout
*/
tb_void_t tb_ssl_set_timeout(tb_ssl_ref_t ssl, tb_long_t timeout);
/*! open ssl using blocking mode
*
* @note need wait func
*
* @param ssl the ssl
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ssl_open(tb_ssl_ref_t ssl);
/*! try opening ssl using non-blocking mode
*
* @code
*
// open it
tb_long_t ok = -1;
while (!(ok = tb_ssl_open_try(handle)))
{
// wait it
ok = tb_ssl_wait(handle, TB_SOCKET_EVENT_RECV | TB_SOCKET_EVENT_SEND, timeout);
tb_check_break(ok > 0);
}
* @endcode
*
* @param ssl the ssl
*
* @return ok: 1, continue: 0, failed: -1
*/
tb_long_t tb_ssl_open_try(tb_ssl_ref_t ssl);
/*! clos ssl
*
* @param ssl the ssl
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ssl_close(tb_ssl_ref_t ssl);
/*! try closing ssl using non-blocking mode
*
* @code
*
// open it
tb_long_t ok = -1;
while (!(ok = tb_ssl_close_try(handle)))
{
// wait it
ok = tb_ssl_wait(handle, TB_SOCKET_EVENT_RECV | TB_SOCKET_EVENT_SEND, timeout);
tb_check_break(ok > 0);
}
* @endcode
*
* @param ssl the ssl
*
* @return ok: 1, continue: 0, failed: -1
*/
tb_long_t tb_ssl_close_try(tb_ssl_ref_t ssl);
/*! read ssl data
*
* @param ssl the ssl
* @param data the data
* @param size the size
*
* @return the real size, no data: 0 and see state for waiting, failed: -1
*/
tb_long_t tb_ssl_read(tb_ssl_ref_t ssl, tb_byte_t* data, tb_size_t size);
/*! writ ssl data
*
* @param ssl the ssl
* @param data the data
* @param size the size
*
* @return the real size, no data: 0 and see state for waiting, failed: -1
*/
tb_long_t tb_ssl_writ(tb_ssl_ref_t ssl, tb_byte_t const* data, tb_size_t size);
/*! wait ssl data
*
* @param ssl the ssl
* @param events the events
* @param timeout the timeout
*
* @return the real events, no event: 0, failed or closed: -1
*/
tb_long_t tb_ssl_wait(tb_ssl_ref_t ssl, tb_size_t events, tb_long_t timeout);
/*! the ssl state see the stream ssl state
*
* @param ssl the ssl
*
* @return the ssl state
*/
tb_size_t tb_ssl_state(tb_ssl_ref_t ssl);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/network/unixaddr.c 0000664 0000000 0000000 00000005126 14671175054 0017735 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author CodeHz
* @file unixaddr.c
* @ingroup network
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "unixaddr"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "unixaddr.h"
#include "../libc/libc.h"
#include "../math/math.h"
#include "../utils/utils.h"
#include "../string/string.h"
#include "../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_void_t tb_unixaddr_clear(tb_unixaddr_ref_t unixaddr)
{
// check
tb_assert_and_check_return(unixaddr);
// clear it
tb_memset(unixaddr->path, 0, sizeof(unixaddr->path));
}
tb_bool_t tb_unixaddr_is_abstract(tb_unixaddr_ref_t unixaddr)
{
// check
tb_assert_and_check_return_val(unixaddr, tb_false);
// is abstract?
return unixaddr->is_abstract;
}
tb_bool_t tb_unixaddr_is_equal(tb_unixaddr_ref_t unixaddr, tb_unixaddr_ref_t other)
{
// check
tb_assert_and_check_return_val(unixaddr && other, tb_false);
// is equal?
return tb_strcmp(unixaddr->path, other->path) == 0;
}
tb_char_t const* tb_unixaddr_cstr(tb_unixaddr_ref_t unixaddr, tb_char_t* data, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(unixaddr && data && maxn >= TB_UNIXADDR_CSTR_MAXN, tb_null);
// make it
tb_long_t size = tb_snprintf(data, maxn - 1, "%s", unixaddr->path);
if (size >= 0) data[size] = '\0';
// ok
return data;
}
tb_bool_t tb_unixaddr_cstr_set(tb_unixaddr_ref_t unixaddr, tb_char_t const* cstr, tb_bool_t is_abstract)
{
// check
tb_assert_and_check_return_val(cstr, tb_false);
// set is_abstract
unixaddr->is_abstract = is_abstract;
// copy and report
return tb_strlcpy(unixaddr->path, cstr, TB_UNIXADDR_CSTR_MAXN) < TB_UNIXADDR_CSTR_MAXN;
} tbox-1.7.6/src/tbox/network/unixaddr.h 0000664 0000000 0000000 00000005504 14671175054 0017742 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author CodeHz
* @file unixaddr.h
* @ingroup network
*
*/
#ifndef TB_NETWORK_UNIX_H
#define TB_NETWORK_UNIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/// the unixaddr string data maxn
#define TB_UNIXADDR_CSTR_MAXN (108)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/*! the unix type
*
* /path/to.sock
*/
typedef struct __tb_unixaddr_t
{
/// is abstract
tb_bool_t is_abstract;
/// path
tb_char_t path[TB_UNIXADDR_CSTR_MAXN];
}tb_unixaddr_t, *tb_unixaddr_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! clear the unixaddr
*
* @param unixaddr the unixaddr
*/
tb_void_t tb_unixaddr_clear(tb_unixaddr_ref_t unixaddr);
/*! is abstract?
*
* @param unixaddr the unixaddr
*
* @return tb_true or tb_false
*/
tb_bool_t tb_unixaddr_is_abstract(tb_unixaddr_ref_t unixaddr);
/*! is equal?
*
* @param unixaddr the unixaddr
* @param other the other unixaddr
*
* @return tb_true or tb_false
*/
tb_bool_t tb_unixaddr_is_equal(tb_unixaddr_ref_t unixaddr, tb_unixaddr_ref_t other);
/*! get the unixaddr string
*
* @param unixaddr the unixaddr
* @param data the unixaddr data
* @param maxn the data maxn
*
* @return the unixaddr path
*/
tb_char_t const* tb_unixaddr_cstr(tb_unixaddr_ref_t unixaddr, tb_char_t* data, tb_size_t maxn);
/*! set the unixaddr from string
*
* @param unixaddr the unixaddr
* @param cstr the unixaddr path
*
* @return tb_true or tb_false
*/
tb_bool_t tb_unixaddr_cstr_set(tb_unixaddr_ref_t unixaddr, tb_char_t const* cstr, tb_bool_t is_abstract);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/network/url.c 0000664 0000000 0000000 00000046742 14671175054 0016732 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file url.c
* @ingroup network
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "url"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "url.h"
#include "http.h"
#include "impl/http/prefix.h"
#include "../libc/libc.h"
#include "../math/math.h"
#include "../utils/utils.h"
#include "../platform/platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_char_t const* tb_url_parse_args(tb_string_ref_t args, tb_char_t const* p)
{
// check
tb_assert_and_check_return_val(args && p, tb_null);
// clear args
tb_string_clear(args);
// skip '?' or ' '
while (*p && (*p == '?' || tb_isspace(*p))) p++;
// done
while (*p) tb_string_chrcat(args, *p++);
// end
return p;
}
static tb_char_t const* tb_url_parse_path(tb_string_ref_t path, tb_char_t const* p, tb_size_t protocol)
{
// check
tb_assert_and_check_return_val(path && p, tb_null);
// clear path
tb_string_clear(path);
// skip ' '
while (*p && tb_isspace(*p)) p++;
// append root: '/'
if (*p != '/' && *p != '\\') tb_string_chrcat(path, '/');
// done
tb_char_t ch;
while ((ch = *p) && ((ch != '?' && ch != '#') || protocol == TB_URL_PROTOCOL_FILE))
{
// replace '\\' => '/'
if (ch == '\\') tb_string_chrcat(path, '/');
// append character
else tb_string_chrcat(path, ch);
// next
p++;
}
// end
return p;
}
static tb_char_t const* tb_url_parse_host(tb_string_ref_t host, tb_char_t const* p)
{
// check
tb_assert_and_check_return_val(host && p, tb_null);
// clear path
tb_string_clear(host);
// ipv6? [xxxx:xxxx:...]:port
if (*p == '[')
{
// skip '['
p++;
// parse host
tb_char_t ch;
while ((ch = *p) && ch != ']')
{
// append character
tb_string_chrcat(host, ch);
// next
p++;
}
// append ']'
if (ch == ']') p++;
}
else
{
// parse host
tb_char_t ch;
while ((ch = *p) && !tb_isspace(ch) && ch != ':' && ch != '/' && ch != '\\' && ch != '?' && ch != '&')
{
// append character
tb_string_chrcat(host, ch);
// next
p++;
}
}
// end
return p;
}
static tb_char_t const* tb_url_parse_port(tb_uint16_t* port, tb_char_t const* p)
{
// check
tb_assert_and_check_return_val(port && p, tb_null);
// done
tb_char_t data[12] = {0};
tb_char_t* pb = data;
tb_char_t* pe = data + sizeof(data);
while (pb < pe && *p && tb_isdigit(*p)) *pb++ = *p++;
*port = (tb_uint16_t)tb_s10tou32(data);
// end
return p;
}
static tb_char_t const* tb_url_parse_data(tb_string_ref_t data, tb_char_t const* p)
{
// check
tb_assert_and_check_return_val(data && p, tb_null);
// clear path
tb_string_clear(data);
// skip '/' and '\\' and ' '
while (*p && (*p == '/' || *p == '\\' || tb_isspace(*p))) p++;
// done
tb_char_t ch;
while ((ch = *p) && !tb_isspace(ch))
{
// append data
tb_string_chrcat(data, ch);
// next
p++;
}
// end
return p;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_url_init(tb_url_ref_t url)
{
// check
tb_assert_and_check_return_val(url, tb_false);
// done
tb_bool_t ok = tb_false;
do
{
// init url
url->protocol = TB_URL_PROTOCOL_NONE;
url->is_ssl = 0;
url->is_win = 0;
url->pwin = 0;
tb_ipaddr_clear(&url->addr);
if (!tb_string_init(&url->host)) break;
if (!tb_string_init(&url->path)) break;
if (!tb_string_init(&url->args)) break;
if (!tb_string_init(&url->cache)) break;
// ok
ok = tb_true;
} while (0);
// failed? exit it
if (!ok) tb_url_exit(url);
// ok
return ok;
}
tb_bool_t tb_url_init_from_cstr(tb_url_ref_t url, tb_char_t const* cstr)
{
return tb_url_init(url) && tb_url_cstr_set(url, cstr);
}
tb_void_t tb_url_exit(tb_url_ref_t url)
{
if (url)
{
tb_string_exit(&url->host);
tb_string_exit(&url->path);
tb_string_exit(&url->args);
tb_string_exit(&url->cache);
}
}
tb_void_t tb_url_clear(tb_url_ref_t url)
{
// check
tb_assert_and_check_return(url);
// clear
url->protocol = TB_URL_PROTOCOL_NONE;
url->is_ssl = 0;
url->is_win = 0;
url->pwin = 0;
tb_ipaddr_clear(&url->addr);
tb_string_clear(&url->host);
tb_string_clear(&url->path);
tb_string_clear(&url->args);
tb_string_clear(&url->cache);
}
tb_char_t const* tb_url_cstr(tb_url_ref_t url)
{
// check
tb_assert_and_check_return_val(url, tb_null);
// exists? return it directly
if (tb_string_size(&url->cache)) return tb_string_cstr(&url->cache);
// make
switch (url->protocol)
{
case TB_URL_PROTOCOL_FILE:
{
// check
tb_check_return_val(tb_string_size(&url->path), tb_null);
// add protocol for win
if (url->is_win)
{
tb_assert(url->pwin);
tb_string_cstrfcpy(&url->cache, "%c:/", url->pwin);
}
// add path
tb_string_cstrncat(&url->cache, tb_string_cstr(&url->path), tb_string_size(&url->path));
}
break;
case TB_URL_PROTOCOL_SOCK:
case TB_URL_PROTOCOL_HTTP:
case TB_URL_PROTOCOL_RTSP:
{
// the port
tb_uint16_t port = tb_ipaddr_port(&url->addr);
// check
tb_check_return_val(port && tb_string_size(&url->host), tb_null);
// add protocol
if (url->protocol == TB_URL_PROTOCOL_HTTP) tb_string_cstrcpy(&url->cache, "http");
else if (url->protocol == TB_URL_PROTOCOL_SOCK) tb_string_cstrcpy(&url->cache, "sock");
else if (url->protocol == TB_URL_PROTOCOL_RTSP) tb_string_cstrcpy(&url->cache, "rtsp");
else tb_assert_and_check_break(0);
// add ssl
if (url->is_ssl) tb_string_chrcat(&url->cache, 's');
// add ://
tb_string_cstrncat(&url->cache, "://", 3);
// add host for ipv6
if (tb_ipaddr_family(&url->addr) == TB_IPADDR_FAMILY_IPV6)
{
tb_string_chrcat(&url->cache, '[');
tb_string_cstrncat(&url->cache, tb_string_cstr(&url->host), tb_string_size(&url->host));
tb_string_chrcat(&url->cache, ']');
}
// add host for ipv4
else tb_string_cstrncat(&url->cache, tb_string_cstr(&url->host), tb_string_size(&url->host));
// add port
if ( (url->protocol != TB_URL_PROTOCOL_HTTP)
|| (url->is_ssl && port != TB_HTTP_DEFAULT_PORT_SSL)
|| (!url->is_ssl && port != TB_HTTP_DEFAULT_PORT))
{
tb_string_cstrfcat(&url->cache, ":%u", port);
}
// add path
if (tb_string_size(&url->path))
tb_string_cstrncat(&url->cache, tb_string_cstr(&url->path), tb_string_size(&url->path));
// add args
if (tb_string_size(&url->args))
{
tb_string_chrcat(&url->cache, '?');
tb_string_strcat(&url->cache, &url->args);
}
}
break;
case TB_URL_PROTOCOL_SQL:
{
// add protocol
tb_string_cstrcpy(&url->cache, "sql://");
// add host and port
if (tb_string_size(&url->host))
{
// the port
tb_uint16_t port = tb_ipaddr_port(&url->addr);
// add host
tb_string_cstrncat(&url->cache, tb_string_cstr(&url->host), tb_string_size(&url->host));
// add port
if (port) tb_string_cstrfcat(&url->cache, ":%u", port);
}
// add path
if (tb_string_size(&url->path))
tb_string_cstrncat(&url->cache, tb_string_cstr(&url->path), tb_string_size(&url->path));
// add args
if (tb_string_size(&url->args))
{
tb_string_chrcat(&url->cache, '?');
tb_string_strcat(&url->cache, &url->args);
}
}
break;
case TB_URL_PROTOCOL_DATA:
break;
default:
break;
}
// ok?
return tb_string_size(&url->cache)? tb_string_cstr(&url->cache) : tb_null;
}
tb_bool_t tb_url_cstr_set(tb_url_ref_t url, tb_char_t const* cstr)
{
// check
tb_assert_and_check_return_val(url && cstr, tb_false);
// done
tb_bool_t ok = tb_false;
do
{
// init
tb_url_clear(url);
// parse proto
tb_char_t const* p = cstr;
tb_char_t full[TB_PATH_MAXN];
if (!tb_strnicmp(p, "http://", 7))
{
url->protocol = TB_URL_PROTOCOL_HTTP;
url->is_ssl = 0;
p += 7;
}
else if (!tb_strnicmp(p, "sock://", 7))
{
url->protocol = TB_URL_PROTOCOL_SOCK;
url->is_ssl = 0;
p += 7;
}
else if (!tb_strnicmp(p, "file://", 7))
{
url->protocol = TB_URL_PROTOCOL_FILE;
url->is_ssl = 0;
p += 7;
}
else if (!tb_strnicmp(p, "rtsp://", 7))
{
url->protocol = TB_URL_PROTOCOL_RTSP;
url->is_ssl = 0;
p += 7;
}
else if (!tb_strnicmp(p, "data://", 7))
{
url->protocol = TB_URL_PROTOCOL_DATA;
url->is_ssl = 0;
p += 7;
}
else if (!tb_strnicmp(p, "https://", 8))
{
url->protocol = TB_URL_PROTOCOL_HTTP;
url->is_ssl = 1;
p += 8;
}
else if (!tb_strnicmp(p, "socks://", 8))
{
url->protocol = TB_URL_PROTOCOL_SOCK;
url->is_ssl = 1;
p += 8;
}
else if (!tb_strnicmp(p, "sql://", 6))
{
url->protocol = TB_URL_PROTOCOL_SQL;
url->is_ssl = 0;
p += 6;
}
// ./file or /home/file or c:/file or c:\\file ...
else if ((p = tb_path_absolute(cstr, full, TB_PATH_MAXN)))
{
// for unix style path
if ((*p == '/') || (!tb_strnicmp(p, "file://", 7)))
{
url->protocol = TB_URL_PROTOCOL_FILE;
url->is_ssl = 0;
if (*p != '/') p += 7;
}
// for windows style path
else if (tb_isalpha(p[0]) && p[1] == ':' && (p[2] == '/' || p[2] == '\\'))
{
url->protocol = TB_URL_PROTOCOL_FILE;
url->is_ssl = 0;
url->is_win = 1;
url->pwin = *p;
// skip the drive prefix
p += 3;
}
else break;
}
else
{
// trace
tb_trace_w("[url]: unknown prefix for url: %s", p);
break;
}
// end?
tb_assert_and_check_break(*p);
// parse host and port for http or sock or rtsp
if ( url->protocol == TB_URL_PROTOCOL_HTTP
|| url->protocol == TB_URL_PROTOCOL_SOCK
|| url->protocol == TB_URL_PROTOCOL_RTSP
|| url->protocol == TB_URL_PROTOCOL_SQL)
{
// parse host
p = tb_url_parse_host(&url->host, p);
tb_assert_and_check_break(p);
// attempt to parse address
if (tb_string_size(&url->host)) tb_ipaddr_ip_cstr_set(&url->addr, tb_string_cstr(&url->host), TB_IPADDR_FAMILY_NONE);
// parse port
tb_uint16_t port = 0;
if (*p == ':')
{
// parse it
p = tb_url_parse_port(&port, p + 1);
tb_assert_and_check_break(p);
// no port? using the default port
if (!port) port = url->is_ssl? TB_HTTP_DEFAULT_PORT_SSL : TB_HTTP_DEFAULT_PORT;
}
else if (url->protocol == TB_URL_PROTOCOL_HTTP) port = url->is_ssl? TB_HTTP_DEFAULT_PORT_SSL : TB_HTTP_DEFAULT_PORT;
else if (url->protocol != TB_URL_PROTOCOL_SQL) break;
// save port
tb_ipaddr_port_set(&url->addr, port);
}
// parse path and args
if (url->protocol != TB_URL_PROTOCOL_DATA)
{
// parse path
p = tb_url_parse_path(&url->path, p, url->protocol);
tb_assert_and_check_break(p);
// find args
while (*p && *p != '?') p++;
// parse args
if (*p == '?') tb_url_parse_args(&url->args, p);
}
// parse data
else p = tb_url_parse_data(&url->cache, p);
// ok
ok = tb_true;
} while (0);
// failed? clear the url
if (!ok) tb_url_clear(url);
// ok?
return ok;
}
tb_void_t tb_url_copy(tb_url_ref_t url, tb_url_ref_t copy)
{
// check
tb_assert_and_check_return(url && copy);
// copy it
url->protocol = copy->protocol;
url->addr = copy->addr;
url->is_ssl = copy->is_ssl;
url->is_win = copy->is_win;
url->pwin = copy->pwin;
tb_string_strcpy(&url->host, ©->host);
tb_string_strcpy(&url->path, ©->path);
tb_string_strcpy(&url->args, ©->args);
tb_string_strcpy(&url->cache, ©->cache);
}
tb_bool_t tb_url_ssl(tb_url_ref_t url)
{
// check
tb_assert_and_check_return_val(url, tb_false);
// get ssl
return url->is_ssl? tb_true : tb_false;
}
tb_void_t tb_url_ssl_set(tb_url_ref_t url, tb_bool_t is_ssl)
{
// check
tb_assert_and_check_return(url);
// set ssl
url->is_ssl = is_ssl? 1 : 0;
}
tb_size_t tb_url_protocol(tb_url_ref_t url)
{
// check
tb_assert_and_check_return_val(url, TB_URL_PROTOCOL_NONE);
// get protocol
return url->protocol;
}
tb_void_t tb_url_protocol_set(tb_url_ref_t url, tb_size_t protocol)
{
// check
tb_assert_and_check_return(url);
// set protocol
url->protocol = protocol;
}
tb_char_t const* tb_url_protocol_cstr(tb_url_ref_t url)
{
// check
tb_assert_and_check_return_val(url, tb_null);
// the protocols
static tb_char_t const* s_protocols[] =
{
tb_null
, "file"
, "sock"
, "http"
, "data"
, "rtsp"
, "sql"
};
tb_assert_and_check_return_val(url->protocol < tb_arrayn(s_protocols), tb_null);
// ok
return s_protocols[url->protocol];
}
tb_size_t tb_url_protocol_probe(tb_char_t const* url)
{
// check
tb_assert_and_check_return_val(url, TB_URL_PROTOCOL_NONE);
// init
tb_char_t full[TB_PATH_MAXN];
tb_char_t const* p = url;
tb_size_t protocol = TB_URL_PROTOCOL_NONE;
if (!tb_strnicmp(p, "http://", 7)) protocol = TB_URL_PROTOCOL_HTTP;
else if (!tb_strnicmp(p, "sock://", 7)) protocol = TB_URL_PROTOCOL_SOCK;
else if (!tb_strnicmp(p, "file://", 7)) protocol = TB_URL_PROTOCOL_FILE;
else if (!tb_strnicmp(p, "data://", 7)) protocol = TB_URL_PROTOCOL_DATA;
else if (!tb_strnicmp(p, "https://", 8)) protocol = TB_URL_PROTOCOL_HTTP;
else if (!tb_strnicmp(p, "socks://", 8)) protocol = TB_URL_PROTOCOL_SOCK;
else if (!tb_strnicmp(p, "rtsp://", 7)) protocol = TB_URL_PROTOCOL_RTSP;
else if (!tb_strnicmp(p, "sql://", 6)) protocol = TB_URL_PROTOCOL_SQL;
// ./file or /home/file or c:/file or c:\\file ...
else if ((p = tb_path_absolute(url, full, TB_PATH_MAXN)))
{
// for unix style path
if ((*p == '/') || (!tb_strnicmp(p, "file://", 7)))
protocol = TB_URL_PROTOCOL_FILE;
// for windows style path
else if (tb_isalpha(p[0]) && p[1] == ':' && (p[2] == '/' || p[2] == '\\'))
protocol = TB_URL_PROTOCOL_FILE;
}
if (protocol == TB_URL_PROTOCOL_NONE)
{
tb_trace_e("unknown protocol for url: %s", url);
}
return protocol;
}
tb_uint16_t tb_url_port(tb_url_ref_t url)
{
// check
tb_assert_and_check_return_val(url, 0);
// get port
return tb_ipaddr_port(&url->addr);
}
tb_void_t tb_url_port_set(tb_url_ref_t url, tb_uint16_t port)
{
// check
tb_assert_and_check_return(url);
// set port
tb_ipaddr_port_set(&url->addr, port);
// clear url
tb_string_clear(&url->cache);
}
tb_char_t const* tb_url_host(tb_url_ref_t url)
{
// check
tb_assert_and_check_return_val(url, tb_null);
// get host
return tb_string_size(&url->host)? tb_string_cstr(&url->host) : tb_null;
}
tb_void_t tb_url_host_set(tb_url_ref_t url, tb_char_t const* host)
{
// check
tb_assert_and_check_return(url);
// clear cache
tb_string_clear(&url->cache);
// clear address
tb_ipaddr_clear(&url->addr);
// parse host
tb_url_parse_host(&url->host, host);
// attempt to parse address
tb_ipaddr_ip_cstr_set(&url->addr, tb_string_cstr(&url->host), TB_IPADDR_FAMILY_NONE);
}
tb_ipaddr_ref_t tb_url_addr(tb_url_ref_t url)
{
// check
tb_assert_and_check_return_val(url, tb_null);
// get address
return &(url->addr);
}
tb_void_t tb_url_addr_set(tb_url_ref_t url, tb_ipaddr_ref_t addr)
{
// check
tb_assert_and_check_return(url && addr);
// changed?
if (!tb_ipaddr_is_equal(&url->addr, addr))
{
// set addr
url->addr = *addr;
// set it if the host not exists
if (!tb_string_size(&url->host))
{
// address => host
tb_char_t data[TB_IPADDR_CSTR_MAXN];
tb_char_t const* host = tb_ipaddr_ip_cstr(addr, data, sizeof(data));
if (host) tb_string_cstrcpy(&url->host, host);
// clear url
tb_string_clear(&url->cache);
}
}
}
tb_char_t const* tb_url_path(tb_url_ref_t url)
{
// check
tb_assert_and_check_return_val(url, tb_null);
// get path
return tb_string_size(&url->path)? tb_string_cstr(&url->path) : tb_null;
}
tb_void_t tb_url_path_set(tb_url_ref_t url, tb_char_t const* path)
{
// check
tb_assert_and_check_return(url);
// clear cache
tb_string_clear(&url->cache);
// parse path
tb_url_parse_path(&url->path, path, url->protocol);
}
tb_char_t const* tb_url_args(tb_url_ref_t url)
{
// check
tb_assert_and_check_return_val(url, tb_null);
// get args
return tb_string_size(&url->args)? tb_string_cstr(&url->args) : tb_null;
}
tb_void_t tb_url_args_set(tb_url_ref_t url, tb_char_t const* args)
{
// check
tb_assert_and_check_return(url);
// clear cache
tb_string_clear(&url->cache);
// parse args
tb_url_parse_args(&url->args, args);
}
tbox-1.7.6/src/tbox/network/url.h 0000664 0000000 0000000 00000014033 14671175054 0016723 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file url.h
* @ingroup network
*
*/
#ifndef TB_NETWORK_URL_H
#define TB_NETWORK_URL_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "ipaddr.h"
#include "../string/string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the url protocol type
typedef enum __tb_url_protocol_t
{
TB_URL_PROTOCOL_NONE = 0
, TB_URL_PROTOCOL_FILE = 1 //!< file://...
, TB_URL_PROTOCOL_SOCK = 2 //!< sock://... or socks://...
, TB_URL_PROTOCOL_HTTP = 3 //!< http://... or https://...
, TB_URL_PROTOCOL_DATA = 4 //!< data://...
, TB_URL_PROTOCOL_RTSP = 5 //!< rtsp://...
, TB_URL_PROTOCOL_SQL = 6 //!< sql://...
}tb_url_protocol_t;
/// the url type
typedef struct __tb_url_t
{
// the protocol
tb_uint16_t protocol: 6;
// is ssl?
tb_uint16_t is_ssl: 1;
// is win?
tb_uint16_t is_win: 1;
// the windows prefix
tb_uint16_t pwin: 8;
// the addr
tb_ipaddr_t addr;
// the host
tb_string_t host;
// the path
tb_string_t path;
// the args
tb_string_t args;
// the url cache
tb_string_t cache;
}tb_url_t, *tb_url_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init url
*
* @param url the url
*
* @return tb_true or tb_false
*/
tb_bool_t tb_url_init(tb_url_ref_t url);
/*! init url from c-string
*
* @param url the url
* @param cstr the url c-string
*
* @return tb_true or tb_false
*/
tb_bool_t tb_url_init_from_cstr(tb_url_ref_t url, tb_char_t const* cstr);
/*! exit url
*
* @param url the url
*/
tb_void_t tb_url_exit(tb_url_ref_t url);
/*! clear url
*
* @param url the url
*/
tb_void_t tb_url_clear(tb_url_ref_t url);
/*! get the url c-string
*
* @param url the url
*
* @return the c-string
*/
tb_char_t const* tb_url_cstr(tb_url_ref_t url);
/*! set the url c-string
*
* @param url the url
* @param cstr the url c-string
*
* @return tb_true or tb_false
*/
tb_bool_t tb_url_cstr_set(tb_url_ref_t url, tb_char_t const* cstr);
/*! copy the url
*
* @param url the url
* @param copy the copied url
*/
tb_void_t tb_url_copy(tb_url_ref_t url, tb_url_ref_t copy);
/*! is ssl?
*
* @param url the url
*
* @return tb_true or tb_false
*/
tb_bool_t tb_url_ssl(tb_url_ref_t url);
/*! set ssl
*
* @param url the url
* @param is_ssl is ssl?
*/
tb_void_t tb_url_ssl_set(tb_url_ref_t url, tb_bool_t is_ssl);
/*! get the protocol from the url
*
* @param url the url
*
* @return the url protocol
*/
tb_size_t tb_url_protocol(tb_url_ref_t url);
/*! set the protocol to the url
*
* @param url the url
* @param protocol the url protocol
*/
tb_void_t tb_url_protocol_set(tb_url_ref_t url, tb_size_t protocol);
/*! the protocol c-string
*
* @param url the url
*
* @return the url protocol c-string
*/
tb_char_t const* tb_url_protocol_cstr(tb_url_ref_t url);
/*! probe the protocol from the url
*
* @param url the url
*
* @return the url protocol
*/
tb_size_t tb_url_protocol_probe(tb_char_t const* url);
/*! get the port from the url
*
* @param url the url
*
* @return the url port
*/
tb_uint16_t tb_url_port(tb_url_ref_t url);
/*! set the port to the url
*
* @param url the url
* @param port the url port
*/
tb_void_t tb_url_port_set(tb_url_ref_t url, tb_uint16_t port);
/*! get the address from the url
*
* @param url the url
*
* @return the url address
*/
tb_ipaddr_ref_t tb_url_addr(tb_url_ref_t url);
/*! set the address to the url
*
* @param url the url
* @param addr the url address
*/
tb_void_t tb_url_addr_set(tb_url_ref_t url, tb_ipaddr_ref_t addr);
/*! get the host from the url
*
* @param url the url
*
* @return the url host
*/
tb_char_t const* tb_url_host(tb_url_ref_t url);
/*! set the host to the url
*
* @param url the url
* @param host the url host
*/
tb_void_t tb_url_host_set(tb_url_ref_t url, tb_char_t const* host);
/*! get the path from the url
*
* @param url the url
*
* @return the url path
*/
tb_char_t const* tb_url_path(tb_url_ref_t url);
/*! set the path to the url
*
* @param url the url
* @param path the url path
*/
tb_void_t tb_url_path_set(tb_url_ref_t url, tb_char_t const* path);
/*! get the arguments from the url
*
* @param url the url
*
* @return the url arguments
*/
tb_char_t const* tb_url_args(tb_url_ref_t url);
/*! set the arguments to the url
*
* @param url the url
* @param args the url arguments
*/
tb_void_t tb_url_args_set(tb_url_ref_t url, tb_char_t const* args);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/object/ 0000775 0000000 0000000 00000000000 14671175054 0015524 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/object/array.c 0000664 0000000 0000000 00000015277 14671175054 0017022 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file array.c
* @ingroup object
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "oc_array"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "object.h"
#include "../algorithm/algorithm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the array type
typedef struct __tb_oc_array_t
{
// the object base
tb_object_t base;
// the vector
tb_vector_ref_t vector;
// is increase refn?
tb_bool_t incr;
}tb_oc_array_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static __tb_inline__ tb_oc_array_t* tb_oc_array_cast(tb_object_ref_t object)
{
// check
tb_assert_and_check_return_val(object && object->type == TB_OBJECT_TYPE_ARRAY, tb_null);
// cast
return (tb_oc_array_t*)object;
}
static tb_object_ref_t tb_oc_array_copy(tb_object_ref_t object)
{
// check
tb_oc_array_t* array = tb_oc_array_cast(object);
tb_assert_and_check_return_val(array && array->vector, tb_null);
// init copy
tb_oc_array_t* copy = (tb_oc_array_t*)tb_oc_array_init(tb_vector_grow(array->vector), array->incr);
tb_assert_and_check_return_val(copy && copy->vector, tb_null);
// refn++
tb_for_all (tb_object_ref_t, item, array->vector)
{
if (item) tb_object_retain(item);
}
// copy
tb_vector_copy(copy->vector, array->vector);
// ok
return (tb_object_ref_t)copy;
}
static tb_void_t tb_oc_array_exit(tb_object_ref_t object)
{
// check
tb_oc_array_t* array = tb_oc_array_cast(object);
tb_assert_and_check_return(array);
// exit vector
if (array->vector) tb_vector_exit(array->vector);
array->vector = tb_null;
// exit it
tb_free(array);
}
static tb_void_t tb_oc_array_clear(tb_object_ref_t object)
{
tb_oc_array_t* array = tb_oc_array_cast(object);
tb_assert_and_check_return(array && array->vector);
// clear vector
tb_vector_clear(array->vector);
}
static tb_oc_array_t* tb_oc_array_init_base()
{
// done
tb_bool_t ok = tb_false;
tb_oc_array_t* array = tb_null;
do
{
// make array
array = tb_malloc0_type(tb_oc_array_t);
tb_assert_and_check_break(array);
// init array
if (!tb_object_init((tb_object_ref_t)array, TB_OBJECT_FLAG_NONE, TB_OBJECT_TYPE_ARRAY)) break;
// init base
array->base.copy = tb_oc_array_copy;
array->base.exit = tb_oc_array_exit;
array->base.clear = tb_oc_array_clear;
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (array) tb_object_exit((tb_object_ref_t)array);
array = tb_null;
}
// ok?
return array;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_object_ref_t tb_oc_array_init(tb_size_t grow, tb_bool_t incr)
{
// done
tb_bool_t ok = tb_false;
tb_oc_array_t* array = tb_null;
do
{
// make array
array = tb_oc_array_init_base();
tb_assert_and_check_break(array);
// init element
tb_element_t element = tb_element_obj();
// init vector
array->vector = tb_vector_init(grow, element);
tb_assert_and_check_break(array->vector);
// init incr
array->incr = incr;
// ok
ok = tb_true;
} while (0);
// failed
if (!ok)
{
// exit it
if (array) tb_oc_array_exit((tb_object_ref_t)array);
array = tb_null;
}
// ok?
return (tb_object_ref_t)array;
}
tb_size_t tb_oc_array_size(tb_object_ref_t object)
{
// check
tb_oc_array_t* array = tb_oc_array_cast(object);
tb_assert_and_check_return_val(array && array->vector, 0);
// size
return tb_vector_size(array->vector);
}
tb_object_ref_t tb_oc_array_item(tb_object_ref_t object, tb_size_t index)
{
// check
tb_oc_array_t* array = tb_oc_array_cast(object);
tb_assert_and_check_return_val(array && array->vector, tb_null);
// item
return (tb_object_ref_t)tb_iterator_item(array->vector, index);
}
tb_iterator_ref_t tb_oc_array_itor(tb_object_ref_t object)
{
// check
tb_oc_array_t* array = tb_oc_array_cast(object);
tb_assert_and_check_return_val(array, tb_null);
// iterator
return (tb_iterator_ref_t)array->vector;
}
tb_void_t tb_oc_array_remove(tb_object_ref_t object, tb_size_t index)
{
// check
tb_oc_array_t* array = tb_oc_array_cast(object);
tb_assert_and_check_return(array && array->vector);
// remove
tb_vector_remove(array->vector, index);
}
tb_void_t tb_oc_array_append(tb_object_ref_t object, tb_object_ref_t item)
{
// check
tb_oc_array_t* array = tb_oc_array_cast(object);
tb_assert_and_check_return(array && array->vector && item);
// insert
tb_vector_insert_tail(array->vector, item);
// refn--
if (!array->incr) tb_object_exit(item);
}
tb_void_t tb_oc_array_insert(tb_object_ref_t object, tb_size_t index, tb_object_ref_t item)
{
// check
tb_oc_array_t* array = tb_oc_array_cast(object);
tb_assert_and_check_return(array && array->vector && item);
// insert
tb_vector_insert_prev(array->vector, index, item);
// refn--
if (!array->incr) tb_object_exit(item);
}
tb_void_t tb_oc_array_replace(tb_object_ref_t object, tb_size_t index, tb_object_ref_t item)
{
// check
tb_oc_array_t* array = tb_oc_array_cast(object);
tb_assert_and_check_return(array && array->vector && item);
// replace
tb_vector_replace(array->vector, index, item);
// refn--
if (!array->incr) tb_object_exit(item);
}
tb_void_t tb_oc_array_incr(tb_object_ref_t object, tb_bool_t incr)
{
// check
tb_oc_array_t* array = tb_oc_array_cast(object);
tb_assert_and_check_return(array);
array->incr = incr;
}
tbox-1.7.6/src/tbox/object/array.h 0000664 0000000 0000000 00000006256 14671175054 0017024 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file array.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_ARRAY_H
#define TB_OBJECT_ARRAY_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init array
*
* @param grow the array grow
* @param incr is increase refn?
*
* @return the array object
*/
tb_object_ref_t tb_oc_array_init(tb_size_t grow, tb_bool_t incr);
/*! the array size
*
* @param array the array object
*
* @return the array size
*/
tb_size_t tb_oc_array_size(tb_object_ref_t array);
/*! the array item at index
*
* @param array the array object
* @param index the array index
*
* @return the array item
*/
tb_object_ref_t tb_oc_array_item(tb_object_ref_t array, tb_size_t index);
/*! set the array incr
*
* @param array the array object
* @param incr is increase refn?
*/
tb_void_t tb_oc_array_incr(tb_object_ref_t array, tb_bool_t incr);
/*! the array iterator
*
* @param array the array object
*
* @return the array iterator
*
* @code
* tb_for_all (tb_object_ref_t, item, tb_oc_array_itor(array))
* {
* if (item)
* {
* // ...
* }
* }
* @endcode
*/
tb_iterator_ref_t tb_oc_array_itor(tb_object_ref_t array);
/*! remove the item from index
*
* @param array the array object
* @param index the array index
*/
tb_void_t tb_oc_array_remove(tb_object_ref_t array, tb_size_t index);
/*! append item to array
*
* @param array the array object
* @param item the array item
*/
tb_void_t tb_oc_array_append(tb_object_ref_t array, tb_object_ref_t item);
/*! insert item to array
*
* @param array the array object
* @param index the array index
* @param item the array item
*/
tb_void_t tb_oc_array_insert(tb_object_ref_t array, tb_size_t index, tb_object_ref_t item);
/*! replace item to array
*
* @param array the array object
* @param index the array index
* @param item the array item
*/
tb_void_t tb_oc_array_replace(tb_object_ref_t array, tb_size_t index, tb_object_ref_t item);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/object/boolean.c 0000664 0000000 0000000 00000006112 14671175054 0017307 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file boolean.c
* @ingroup object
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "oc_boolean"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "object.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the boolean type
typedef struct __tb_oc_boolean_t
{
// the object base
tb_object_t base;
// the boolean value
tb_bool_t value;
}tb_oc_boolean_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static __tb_inline__ tb_oc_boolean_t* tb_oc_boolean_cast(tb_object_ref_t object)
{
// check
tb_assert_and_check_return_val(object && object->type == TB_OBJECT_TYPE_BOOLEAN, tb_null);
// cast
return (tb_oc_boolean_t*)object;
}
static tb_object_ref_t tb_oc_boolean_copy(tb_object_ref_t object)
{
// check
tb_oc_boolean_t* boolean = (tb_oc_boolean_t*)object;
tb_assert_and_check_return_val(boolean, tb_null);
// copy
return object;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
// true
static tb_oc_boolean_t const g_boolean_true =
{
{
TB_OBJECT_FLAG_READONLY | TB_OBJECT_FLAG_SINGLETON
, TB_OBJECT_TYPE_BOOLEAN
, 1
, tb_null
, tb_oc_boolean_copy
, tb_null
, tb_null
}
, tb_true
};
// false
static tb_oc_boolean_t const g_boolean_false =
{
{
TB_OBJECT_FLAG_READONLY | TB_OBJECT_FLAG_SINGLETON
, TB_OBJECT_TYPE_BOOLEAN
, 1
, tb_null
, tb_oc_boolean_copy
, tb_null
, tb_null
}
, tb_false
};
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_object_ref_t tb_oc_boolean_init(tb_bool_t value)
{
return value? tb_oc_boolean_true() : tb_oc_boolean_false();
}
tb_object_ref_t tb_oc_boolean_true()
{
return (tb_object_ref_t)&g_boolean_true;
}
tb_object_ref_t tb_oc_boolean_false()
{
return (tb_object_ref_t)&g_boolean_false;
}
tb_bool_t tb_oc_boolean_bool(tb_object_ref_t object)
{
tb_oc_boolean_t* boolean = tb_oc_boolean_cast(object);
tb_assert_and_check_return_val(boolean, tb_false);
return boolean->value;
}
tbox-1.7.6/src/tbox/object/boolean.h 0000664 0000000 0000000 00000003514 14671175054 0017317 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file boolean.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_BOOLEAN_H
#define TB_OBJECT_BOOLEAN_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init boolean
*
* @param value the value
*
* @return the boolean object
*/
tb_object_ref_t tb_oc_boolean_init(tb_bool_t value);
/*! the boolean value: true
*
* @return the boolean object
*/
tb_object_ref_t tb_oc_boolean_true(tb_noarg_t);
/*! the boolean value: false
*
* @return the boolean object
*/
tb_object_ref_t tb_oc_boolean_false(tb_noarg_t);
/*! the boolean value
*
* @param boolean the boolean object
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_boolean_bool(tb_object_ref_t boolean);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/object/data.c 0000664 0000000 0000000 00000015001 14671175054 0016576 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file data.c
* @ingroup object
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "oc_data"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "object.h"
#include "../utils/utils.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the data type
typedef struct __tb_oc_data_t
{
// the object base
tb_object_t base;
// the data buffer
tb_buffer_t buffer;
}tb_oc_data_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static __tb_inline__ tb_oc_data_t* tb_oc_data_cast(tb_object_ref_t object)
{
// check
tb_assert_and_check_return_val(object && object->type == TB_OBJECT_TYPE_DATA, tb_null);
// cast
return (tb_oc_data_t*)object;
}
static tb_object_ref_t tb_oc_data_copy(tb_object_ref_t object)
{
return tb_oc_data_init_from_data(tb_oc_data_getp(object), tb_oc_data_size(object));
}
static tb_void_t tb_oc_data_exit(tb_object_ref_t object)
{
tb_oc_data_t* data = tb_oc_data_cast(object);
if (data)
{
tb_buffer_exit(&data->buffer);
tb_free(data);
}
}
static tb_void_t tb_oc_data_clear(tb_object_ref_t object)
{
tb_oc_data_t* data = tb_oc_data_cast(object);
if (data) tb_buffer_clear(&data->buffer);
}
static tb_oc_data_t* tb_oc_data_init_base()
{
// done
tb_bool_t ok = tb_false;
tb_oc_data_t* data = tb_null;
do
{
// make data
data = tb_malloc0_type(tb_oc_data_t);
tb_assert_and_check_break(data);
// init data
if (!tb_object_init((tb_object_ref_t)data, TB_OBJECT_FLAG_NONE, TB_OBJECT_TYPE_DATA)) break;
// init base
data->base.copy = tb_oc_data_copy;
data->base.exit = tb_oc_data_exit;
data->base.clear = tb_oc_data_clear;
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (data) tb_object_exit((tb_object_ref_t)data);
data = tb_null;
}
// ok?
return data;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_object_ref_t tb_oc_data_init_from_url(tb_char_t const* url)
{
// check
tb_assert_and_check_return_val(url, tb_null);
// init stream
tb_stream_ref_t stream = tb_stream_init_from_url(url);
tb_assert_and_check_return_val(stream, tb_null);
// make stream
tb_object_ref_t object = tb_null;
if (tb_stream_open(stream))
{
// read all data
tb_size_t size = 0;
tb_byte_t* data = (tb_byte_t*)tb_stream_bread_all(stream, tb_false, &size);
if (data)
{
// make object
object = tb_oc_data_init_from_data(data, size);
// exit data
tb_free(data);
}
// exit stream
tb_stream_exit(stream);
}
// ok?
return object;
}
tb_object_ref_t tb_oc_data_init_from_data(tb_pointer_t addr, tb_size_t size)
{
// make
tb_oc_data_t* data = tb_oc_data_init_base();
tb_assert_and_check_return_val(data, tb_null);
// init buffer
if (!tb_buffer_init(&data->buffer))
{
tb_oc_data_exit((tb_object_ref_t)data);
return tb_null;
}
// copy data
if (addr && size) tb_buffer_memncpy(&data->buffer, (tb_byte_t const*)addr, size);
// ok
return (tb_object_ref_t)data;
}
tb_object_ref_t tb_oc_data_init_from_buffer(tb_buffer_ref_t pbuf)
{
// make
tb_oc_data_t* data = tb_oc_data_init_base();
tb_assert_and_check_return_val(data, tb_null);
// init buffer
if (!tb_buffer_init(&data->buffer))
{
tb_oc_data_exit((tb_object_ref_t)data);
return tb_null;
}
// copy data
if (pbuf) tb_buffer_memcpy(&data->buffer, pbuf);
// ok
return (tb_object_ref_t)data;
}
tb_pointer_t tb_oc_data_getp(tb_object_ref_t object)
{
// check
tb_oc_data_t* data = tb_oc_data_cast(object);
tb_assert_and_check_return_val(data, tb_null);
// data
return tb_buffer_data(&data->buffer);
}
tb_bool_t tb_oc_data_setp(tb_object_ref_t object, tb_pointer_t addr, tb_size_t size)
{
// check
tb_oc_data_t* data = tb_oc_data_cast(object);
tb_assert_and_check_return_val(data && addr, tb_false);
// data
tb_buffer_memncpy(&data->buffer, (tb_byte_t const*)addr, size);
// ok
return tb_true;
}
tb_size_t tb_oc_data_size(tb_object_ref_t object)
{
// check
tb_oc_data_t* data = tb_oc_data_cast(object);
tb_assert_and_check_return_val(data, 0);
// data
return tb_buffer_size(&data->buffer);
}
tb_buffer_ref_t tb_oc_data_buffer(tb_object_ref_t object)
{
// check
tb_oc_data_t* data = tb_oc_data_cast(object);
tb_assert_and_check_return_val(data, tb_null);
// buffer
return &data->buffer;
}
tb_bool_t tb_oc_data_writ_to_url(tb_object_ref_t object, tb_char_t const* url)
{
// check
tb_oc_data_t* data = tb_oc_data_cast(object);
tb_assert_and_check_return_val(data && tb_oc_data_getp((tb_object_ref_t)data) && url, tb_false);
// make stream
tb_stream_ref_t stream = tb_stream_init_from_url(url);
tb_assert_and_check_return_val(stream, tb_false);
// ctrl
if (tb_stream_type(stream) == TB_STREAM_TYPE_FILE)
tb_stream_ctrl(stream, TB_STREAM_CTRL_FILE_SET_MODE, TB_FILE_MODE_WO | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC);
// open stream
tb_bool_t ok = tb_false;
if (tb_stream_open(stream))
{
// writ stream
if (tb_stream_bwrit(stream, (tb_byte_t const*)tb_oc_data_getp((tb_object_ref_t)data), tb_oc_data_size((tb_object_ref_t)data))) ok = tb_true;
}
// exit stream
tb_stream_exit(stream);
// ok?
return ok;
}
tbox-1.7.6/src/tbox/object/data.h 0000664 0000000 0000000 00000005324 14671175054 0016612 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file data.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_DATA_H
#define TB_OBJECT_DATA_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init data from url
*
* @param url the url
*
* @return the data object
*/
tb_object_ref_t tb_oc_data_init_from_url(tb_char_t const* url);
/*! init data from data
*
* @param data the data
* @param size the size
*
* @return the data object
*/
tb_object_ref_t tb_oc_data_init_from_data(tb_pointer_t data, tb_size_t size);
/*! init data from buffer
*
* @param buffer the buffer
*
* @return the data object
*/
tb_object_ref_t tb_oc_data_init_from_buffer(tb_buffer_ref_t buffer);
/*! get the data
*
* @param data the data object
*
* @return the data address
*/
tb_pointer_t tb_oc_data_getp(tb_object_ref_t data);
/*! set the data
*
* @param data the data object
* @param addr the data address
* @param size the data size
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_data_setp(tb_object_ref_t data, tb_pointer_t addr, tb_size_t size);
/*! the data size
*
* @param data the data object
*
* @return the data size
*/
tb_size_t tb_oc_data_size(tb_object_ref_t data);
/*! the data buffer
*
* @param data the data object
*
* @return the data buffer
*/
tb_buffer_ref_t tb_oc_data_buffer(tb_object_ref_t data);
/*! writ data to url
*
* @param data the data object
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_data_writ_to_url(tb_object_ref_t data, tb_char_t const* url);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/object/date.c 0000664 0000000 0000000 00000010100 14671175054 0016575 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file date.c
* @ingroup object
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "oc_date"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "object.h"
#include "../utils/utils.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the date type
typedef struct __tb_oc_date_t
{
// the object base
tb_object_t base;
// the date time
tb_time_t time;
}tb_oc_date_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static __tb_inline__ tb_oc_date_t* tb_oc_date_cast(tb_object_ref_t object)
{
// check
tb_assert_and_check_return_val(object && object->type == TB_OBJECT_TYPE_DATE, tb_null);
// cast
return (tb_oc_date_t*)object;
}
static tb_object_ref_t tb_oc_date_copy(tb_object_ref_t object)
{
return tb_oc_date_init_from_time(tb_oc_date_time(object));
}
static tb_void_t tb_oc_date_exit(tb_object_ref_t object)
{
if (object) tb_free(object);
}
static tb_void_t tb_oc_date_clear(tb_object_ref_t object)
{
tb_oc_date_t* date = tb_oc_date_cast(object);
if (date) date->time = 0;
}
static tb_oc_date_t* tb_oc_date_init_base()
{
// done
tb_bool_t ok = tb_false;
tb_oc_date_t* date = tb_null;
do
{
// make date
date = tb_malloc0_type(tb_oc_date_t);
tb_assert_and_check_break(date);
// init date
if (!tb_object_init((tb_object_ref_t)date, TB_OBJECT_FLAG_NONE, TB_OBJECT_TYPE_DATE)) break;
// init base
date->base.copy = tb_oc_date_copy;
date->base.exit = tb_oc_date_exit;
date->base.clear = tb_oc_date_clear;
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (date) tb_object_exit((tb_object_ref_t)date);
date = tb_null;
}
// ok?
return date;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_object_ref_t tb_oc_date_init_from_now()
{
// make
tb_oc_date_t* date = tb_oc_date_init_base();
tb_assert_and_check_return_val(date, tb_null);
// init time
date->time = tb_time();
// ok
return (tb_object_ref_t)date;
}
tb_object_ref_t tb_oc_date_init_from_time(tb_time_t time)
{
// make
tb_oc_date_t* date = tb_oc_date_init_base();
tb_assert_and_check_return_val(date, tb_null);
// init time
if (time > 0) date->time = time;
// ok
return (tb_object_ref_t)date;
}
tb_time_t tb_oc_date_time(tb_object_ref_t object)
{
// check
tb_oc_date_t* date = tb_oc_date_cast(object);
tb_assert_and_check_return_val(date, -1);
// time
return date->time;
}
tb_bool_t tb_oc_date_time_set(tb_object_ref_t object, tb_time_t time)
{
// check
tb_oc_date_t* date = tb_oc_date_cast(object);
tb_assert_and_check_return_val(date, tb_false);
// set time
date->time = time;
// ok
return tb_true;
}
tb_bool_t tb_oc_date_time_set_now(tb_object_ref_t object)
{
// check
tb_oc_date_t* date = tb_oc_date_cast(object);
tb_assert_and_check_return_val(date, tb_false);
// set time
date->time = tb_time();
// ok
return tb_true;
}
tbox-1.7.6/src/tbox/object/date.h 0000664 0000000 0000000 00000004120 14671175054 0016607 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file date.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_DATE_H
#define TB_OBJECT_DATE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init date from now
*
* @return the date object
*/
tb_object_ref_t tb_oc_date_init_from_now(tb_noarg_t);
/*! init date from time
*
* @param time the date time
*
* @return the date object
*/
tb_object_ref_t tb_oc_date_init_from_time(tb_time_t time);
/*! the date time
*
* @param date the date object
*
* @return the date time
*/
tb_time_t tb_oc_date_time(tb_object_ref_t date);
/*! set the date time
*
* @param date the date object
* @param time the date time
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_date_time_set(tb_object_ref_t date, tb_time_t time);
/*! set the date time for now
*
* @param date the date object
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_date_time_set_now(tb_object_ref_t date);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/object/dictionary.c 0000664 0000000 0000000 00000016200 14671175054 0020034 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file dictionary.c
* @ingroup object
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "oc_dictionary"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "object.h"
#include "../string/string.h"
#include "../algorithm/algorithm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef __tb_small__
# define TB_OC_DICTIONARY_SIZE_DEFAULT TB_OC_DICTIONARY_SIZE_MICRO
#else
# define TB_OC_DICTIONARY_SIZE_DEFAULT TB_OC_DICTIONARY_SIZE_SMALL
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the dictionary type
typedef struct __tb_oc_dictionary_t
{
// the object base
tb_object_t base;
// the capacity size
tb_size_t size;
// the object hash
tb_hash_map_ref_t hash;
// increase refn?
tb_bool_t incr;
}tb_oc_dictionary_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static __tb_inline__ tb_oc_dictionary_t* tb_oc_dictionary_cast(tb_object_ref_t object)
{
// check
tb_assert_and_check_return_val(object && object->type == TB_OBJECT_TYPE_DICTIONARY, tb_null);
// cast
return (tb_oc_dictionary_t*)object;
}
static tb_object_ref_t tb_oc_dictionary_copy(tb_object_ref_t object)
{
// check
tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object);
tb_assert_and_check_return_val(dictionary, tb_null);
// init copy
tb_oc_dictionary_t* copy = (tb_oc_dictionary_t*)tb_oc_dictionary_init(dictionary->size, dictionary->incr);
tb_assert_and_check_return_val(copy, tb_null);
// walk copy
tb_for_all (tb_oc_dictionary_item_t*, item, tb_oc_dictionary_itor((tb_object_ref_t)dictionary))
{
if (item && item->key)
{
// refn++
if (item->val) tb_object_retain(item->val);
// copy
tb_oc_dictionary_insert((tb_object_ref_t)copy, item->key, item->val);
}
}
// ok
return (tb_object_ref_t)copy;
}
static tb_void_t tb_oc_dictionary_exit(tb_object_ref_t object)
{
// check
tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object);
tb_assert_and_check_return(dictionary);
// exit hash
if (dictionary->hash) tb_hash_map_exit(dictionary->hash);
dictionary->hash = tb_null;
// exit it
tb_free(dictionary);
}
static tb_void_t tb_oc_dictionary_clear(tb_object_ref_t object)
{
tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object);
tb_assert_and_check_return(dictionary);
// clear
if (dictionary->hash) tb_hash_map_clear(dictionary->hash);
}
static tb_oc_dictionary_t* tb_oc_dictionary_init_base()
{
// done
tb_bool_t ok = tb_false;
tb_oc_dictionary_t* dictionary = tb_null;
do
{
// make dictionary
dictionary = tb_malloc0_type(tb_oc_dictionary_t);
tb_assert_and_check_break(dictionary);
// init dictionary
if (!tb_object_init((tb_object_ref_t)dictionary, TB_OBJECT_FLAG_NONE, TB_OBJECT_TYPE_DICTIONARY)) break;
// init base
dictionary->base.copy = tb_oc_dictionary_copy;
dictionary->base.exit = tb_oc_dictionary_exit;
dictionary->base.clear = tb_oc_dictionary_clear;
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (dictionary) tb_object_exit((tb_object_ref_t)dictionary);
dictionary = tb_null;
}
// ok?
return dictionary;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_object_ref_t tb_oc_dictionary_init(tb_size_t size, tb_bool_t incr)
{
// done
tb_bool_t ok = tb_false;
tb_oc_dictionary_t* dictionary = tb_null;
do
{
// make dictionary
dictionary = tb_oc_dictionary_init_base();
tb_assert_and_check_break(dictionary);
// using the default size
if (!size) size = TB_OC_DICTIONARY_SIZE_DEFAULT;
// init
dictionary->size = size;
dictionary->incr = incr;
// init hash
dictionary->hash = tb_hash_map_init(size, tb_element_str(tb_true), tb_element_obj());
tb_assert_and_check_break(dictionary->hash);
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (dictionary) tb_oc_dictionary_exit((tb_object_ref_t)dictionary);
dictionary = tb_null;
}
// ok?
return (tb_object_ref_t)dictionary;
}
tb_size_t tb_oc_dictionary_size(tb_object_ref_t object)
{
// check
tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object);
tb_assert_and_check_return_val(dictionary && dictionary->hash, 0);
// size
return tb_hash_map_size(dictionary->hash);
}
tb_iterator_ref_t tb_oc_dictionary_itor(tb_object_ref_t object)
{
tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object);
tb_assert_and_check_return_val(dictionary, tb_null);
// iterator
return (tb_iterator_ref_t)dictionary->hash;
}
tb_object_ref_t tb_oc_dictionary_value(tb_object_ref_t object, tb_char_t const* key)
{
// check
tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object);
tb_assert_and_check_return_val(dictionary && dictionary->hash && key, tb_null);
// value
return (tb_object_ref_t)tb_hash_map_get(dictionary->hash, key);
}
tb_void_t tb_oc_dictionary_remove(tb_object_ref_t object, tb_char_t const* key)
{
// check
tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object);
tb_assert_and_check_return(dictionary && dictionary->hash && key);
// del
return tb_hash_map_remove(dictionary->hash, key);
}
tb_void_t tb_oc_dictionary_insert(tb_object_ref_t object, tb_char_t const* key, tb_object_ref_t val)
{
// check
tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object);
tb_assert_and_check_return(dictionary && dictionary->hash && key && val);
// add
tb_hash_map_insert(dictionary->hash, key, val);
// refn--
if (!dictionary->incr) tb_object_exit(val);
}
tb_void_t tb_oc_dictionary_incr(tb_object_ref_t object, tb_bool_t incr)
{
// check
tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object);
tb_assert_and_check_return(dictionary);
dictionary->incr = incr;
}
tbox-1.7.6/src/tbox/object/dictionary.h 0000664 0000000 0000000 00000010565 14671175054 0020051 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file dictionary.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_DICTIONARY_H
#define TB_OBJECT_DICTIONARY_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define TB_OC_DICTIONARY_SIZE_MICRO (64)
#define TB_OC_DICTIONARY_SIZE_SMALL (256)
#define TB_OC_DICTIONARY_SIZE_LARGE (65536)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the dictionary item type
typedef struct __tb_oc_dictionary_item_t
{
/// the key
tb_char_t const* key;
/// the value
tb_object_ref_t val;
}tb_oc_dictionary_item_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init dictionary
*
* @code
// init dictionary
// {"key1": "hello", "key2" :"world", "key3": 12345, "key4": true}
tb_object_ref_t dict = tb_oc_dictionary_init(0, tb_false);
if (dict)
{
// key1 => hello
tb_oc_dictionary_insert(dict, "key1", tb_oc_string_init_from_cstr("hello"));
// key2 => world
tb_oc_dictionary_insert(dict, "key2", tb_oc_string_init_from_cstr("world"));
// key3 => 12345
tb_oc_dictionary_insert(dict, "key3", tb_oc_number_init_from_sint32(12345));
// key4 => true
tb_oc_dictionary_insert(dict, "key4", tb_oc_boolean_true());
// exit dictionary
tb_object_exit(dict);
}
* @endcode
*
* @param size the dictionary size, using the default size if be zero
* @param incr is increase refn?
*
* @return the dictionary object
*/
tb_object_ref_t tb_oc_dictionary_init(tb_size_t size, tb_bool_t incr);
/*! the dictionary size
*
* @param dictionary the dictionary object
*
* @return the dictionary size
*/
tb_size_t tb_oc_dictionary_size(tb_object_ref_t dictionary);
/*! set the dictionary incr
*
* @param dictionary the dictionary object
* @param incr is increase refn?
*/
tb_void_t tb_oc_dictionary_incr(tb_object_ref_t dictionary, tb_bool_t incr);
/*! the dictionary iterator
*
* @param dictionary the dictionary object
*
* @return the dictionary iterator
*
* @code
tb_for_all (tb_oc_dictionary_item_t*, item, tb_oc_dictionary_itor(dictionary))
{
if (item)
{
tb_char_t const* key = item->key;
tb_object_ref_t val = item->val;
// ...
}
}
* @endcode
*/
tb_iterator_ref_t tb_oc_dictionary_itor(tb_object_ref_t dictionary);
/*! get the dictionary value
*
* @param dictionary the dictionary object
* @param key the key
*
* @return the dictionary value
*/
tb_object_ref_t tb_oc_dictionary_value(tb_object_ref_t dictionary, tb_char_t const* key);
/*! insert dictionary item
*
* @param dictionary the dictionary object
* @param key the key
* @param val the value
*/
tb_void_t tb_oc_dictionary_insert(tb_object_ref_t dictionary, tb_char_t const* key, tb_object_ref_t val);
/*! remove dictionary item
*
* @param dictionary the dictionary object
* @param key the key
*/
tb_void_t tb_oc_dictionary_remove(tb_object_ref_t dictionary, tb_char_t const* key);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/object/impl/ 0000775 0000000 0000000 00000000000 14671175054 0016465 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/object/impl/impl.h 0000664 0000000 0000000 00000001701 14671175054 0017576 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file impl.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_IMPL_H
#define TB_OBJECT_IMPL_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "object.h"
#include "reader/reader.h"
#include "writer/writer.h"
#endif
tbox-1.7.6/src/tbox/object/impl/object.c 0000664 0000000 0000000 00000005567 14671175054 0020114 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file object.c
* @ingroup object
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "object"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "object.h"
#include "reader/reader.h"
#include "writer/writer.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_object_init_env()
{
// register reader
if (!tb_oc_reader_set(TB_OBJECT_FORMAT_BIN, tb_oc_bin_reader())) return tb_false;
if (!tb_oc_reader_set(TB_OBJECT_FORMAT_JSON, tb_oc_json_reader())) return tb_false;
if (!tb_oc_reader_set(TB_OBJECT_FORMAT_BPLIST, tb_oc_bplist_reader())) return tb_false;
// register writer
if (!tb_oc_writer_set(TB_OBJECT_FORMAT_BIN, tb_oc_bin_writer())) return tb_false;
if (!tb_oc_writer_set(TB_OBJECT_FORMAT_JSON, tb_oc_json_writer())) return tb_false;
if (!tb_oc_writer_set(TB_OBJECT_FORMAT_BPLIST, tb_oc_bplist_writer())) return tb_false;
// register reader and writer for xml
#ifdef TB_CONFIG_MODULE_HAVE_XML
if (!tb_oc_reader_set(TB_OBJECT_FORMAT_XML, tb_oc_xml_reader())) return tb_false;
if (!tb_oc_writer_set(TB_OBJECT_FORMAT_XML, tb_oc_xml_writer())) return tb_false;
if (!tb_oc_reader_set(TB_OBJECT_FORMAT_XPLIST, tb_oc_xplist_reader())) return tb_false;
if (!tb_oc_writer_set(TB_OBJECT_FORMAT_XPLIST, tb_oc_xplist_writer())) return tb_false;
#endif
// ok
return tb_true;
}
tb_void_t tb_object_exit_env()
{
// remove reader
tb_oc_reader_remove(TB_OBJECT_FORMAT_BIN);
tb_oc_reader_remove(TB_OBJECT_FORMAT_JSON);
tb_oc_reader_remove(TB_OBJECT_FORMAT_BPLIST);
// remove writer
tb_oc_writer_remove(TB_OBJECT_FORMAT_BIN);
tb_oc_writer_remove(TB_OBJECT_FORMAT_JSON);
tb_oc_writer_remove(TB_OBJECT_FORMAT_BPLIST);
// remove reader and writer for xml
#ifdef TB_CONFIG_MODULE_HAVE_XML
tb_oc_reader_remove(TB_OBJECT_FORMAT_XML);
tb_oc_writer_remove(TB_OBJECT_FORMAT_XML);
tb_oc_reader_remove(TB_OBJECT_FORMAT_XPLIST);
tb_oc_writer_remove(TB_OBJECT_FORMAT_XPLIST);
#endif
}
tbox-1.7.6/src/tbox/object/impl/object.h 0000664 0000000 0000000 00000002726 14671175054 0020113 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file object.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_IMPL_OBJECT_H
#define TB_OBJECT_IMPL_OBJECT_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* init object environment
*
* @return tb_true or tb_false
*/
tb_bool_t tb_object_init_env(tb_noarg_t);
// exit object environment
tb_void_t tb_object_exit_env(tb_noarg_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/object/impl/prefix.h 0000664 0000000 0000000 00000004115 14671175054 0020134 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_IMPL_PREFIX_H
#define TB_OBJECT_IMPL_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#include "../object.h"
#include "../../stream/stream.h"
#include "../../charset/charset.h"
#include "../../container/container.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// need bytes
#define tb_object_need_bytes(x) \
(((tb_uint64_t)(x)) < (1ull << 8) ? 1 : \
(((tb_uint64_t)(x)) < (1ull << 16) ? 2 : \
(((tb_uint64_t)(x)) < (1ull << 32) ? 4 : 8)))
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the object reader type
typedef struct __tb_oc_reader_t
{
/// the hooker
tb_hash_map_ref_t hooker;
/// probe format
tb_size_t (*probe)(tb_stream_ref_t stream);
/// read it
tb_object_ref_t (*read)(tb_stream_ref_t stream);
}tb_oc_reader_t;
// the object writer type
typedef struct __tb_oc_writer_t
{
/// the hooker
tb_hash_map_ref_t hooker;
/// writ it
tb_long_t (*writ)(tb_stream_ref_t stream, tb_object_ref_t object, tb_bool_t deflate);
}tb_oc_writer_t;
#endif
tbox-1.7.6/src/tbox/object/impl/reader/ 0000775 0000000 0000000 00000000000 14671175054 0017727 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/object/impl/reader/bin.c 0000664 0000000 0000000 00000040016 14671175054 0020644 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file bin.c
* @ingroup object
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "oc_reader_bin"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "bin.h"
#include "reader.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the array grow
#ifdef __tb_small__
# define TB_OC_BIN_READER_ARRAY_GROW (64)
#else
# define TB_OC_BIN_READER_ARRAY_GROW (256)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_object_ref_t tb_oc_bin_reader_func_null(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size)
{
// check
tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null);
// ok
return tb_oc_null_init();
}
static tb_object_ref_t tb_oc_bin_reader_func_date(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size)
{
// check
tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null);
// ok
return tb_oc_date_init_from_time((tb_time_t)size);
}
static tb_object_ref_t tb_oc_bin_reader_func_data(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size)
{
// check
tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null);
// empty?
if (!size) return tb_oc_data_init_from_data(tb_null, 0);
// make data
tb_char_t* data = tb_malloc0_cstr((tb_size_t)size);
tb_assert_and_check_return_val(data, tb_null);
// read data
if (!tb_stream_bread(reader->stream, (tb_byte_t*)data, (tb_size_t)size))
{
tb_free(data);
return tb_null;
}
// decode data
{
tb_byte_t* pb = (tb_byte_t*)data;
tb_byte_t* pe = (tb_byte_t*)data + size;
tb_byte_t xb = (tb_byte_t)(((size >> 8) & 0xff) | (size & 0xff));
for (; pb < pe; pb++, xb++) *pb ^= xb;
}
// make the data object
tb_object_ref_t object = tb_oc_data_init_from_data(data, (tb_size_t)size);
// exit data
tb_free(data);
// ok?
return object;
}
static tb_object_ref_t tb_oc_bin_reader_func_array(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size)
{
// check
tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null);
// empty?
if (!size) return tb_oc_array_init(TB_OC_BIN_READER_ARRAY_GROW, tb_false);
// init array
tb_object_ref_t array = tb_oc_array_init(TB_OC_BIN_READER_ARRAY_GROW, tb_false);
tb_assert_and_check_return_val(array, tb_null);
// walk
tb_size_t i = 0;
tb_size_t n = (tb_size_t)size;
for (i = 0; i < n; i++)
{
// the type & size
tb_size_t type = 0;
tb_uint64_t size = 0;
tb_oc_reader_bin_type_size(reader->stream, &type, &size);
// trace
tb_trace_d("item: type: %lu, size: %llu", type, size);
// is index?
tb_object_ref_t item = tb_null;
if (!type)
{
// the object index
tb_size_t index = (tb_size_t)size;
// check
tb_assert_and_check_break(index < tb_vector_size(reader->list));
// the item
item = (tb_object_ref_t)tb_iterator_item(reader->list, index);
// refn++
if (item) tb_object_retain(item);
}
else
{
// the reader func
tb_oc_bin_reader_func_t func = tb_oc_bin_reader_func(type);
tb_assert_and_check_break(func);
// read it
item = func(reader, type, size);
// save it
tb_vector_insert_tail(reader->list, item);
}
// check
tb_assert_and_check_break(item);
// append item
tb_oc_array_append(array, item);
}
// failed?
if (i != n)
{
if (array) tb_object_exit(array);
array = tb_null;
}
// ok?
return array;
}
static tb_object_ref_t tb_oc_bin_reader_func_string(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size)
{
// check
tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null);
// empty?
if (!size) return tb_oc_string_init_from_cstr(tb_null);
// make data
tb_char_t* data = tb_malloc0_cstr((tb_size_t)size + 1);
tb_assert_and_check_return_val(data, tb_null);
// read data
if (!tb_stream_bread(reader->stream, (tb_byte_t*)data, (tb_size_t)size))
{
tb_free(data);
return tb_null;
}
// decode string
{
tb_byte_t* pb = (tb_byte_t*)data;
tb_byte_t* pe = (tb_byte_t*)data + size;
tb_byte_t xb = (tb_byte_t)(((size >> 8) & 0xff) | (size & 0xff));
for (; pb < pe; pb++, xb++) *pb ^= xb;
}
// make string
tb_object_ref_t string = tb_oc_string_init_from_cstr(data);
// exit data
tb_free(data);
// ok?
return string;
}
static tb_object_ref_t tb_oc_bin_reader_func_number(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size)
{
// check
tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null);
// the number type
tb_size_t number_type = (tb_size_t)size;
// read number
tb_value_t value;
tb_object_ref_t number = tb_null;
switch (number_type)
{
case TB_OC_NUMBER_TYPE_UINT64:
{
// read and init number
if (tb_stream_bread_u64_be(reader->stream, &value.u64))
number = tb_oc_number_init_from_uint64(value.u64);
}
break;
case TB_OC_NUMBER_TYPE_SINT64:
{
// read and init number
if (tb_stream_bread_s64_be(reader->stream, &value.s64))
number = tb_oc_number_init_from_sint64(value.s64);
}
break;
case TB_OC_NUMBER_TYPE_UINT32:
{
// read and init number
if (tb_stream_bread_u32_be(reader->stream, &value.u32))
number = tb_oc_number_init_from_uint32(value.u32);
}
break;
case TB_OC_NUMBER_TYPE_SINT32:
{
// read and init number
if (tb_stream_bread_s32_be(reader->stream, &value.s32))
number = tb_oc_number_init_from_sint32(value.s32);
}
break;
case TB_OC_NUMBER_TYPE_UINT16:
{
// read and init number
if (tb_stream_bread_u16_be(reader->stream, &value.u16))
number = tb_oc_number_init_from_uint16(value.u16);
}
break;
case TB_OC_NUMBER_TYPE_SINT16:
{
// read and init number
if (tb_stream_bread_s16_be(reader->stream, &value.s16))
number = tb_oc_number_init_from_sint16(value.s16);
}
break;
case TB_OC_NUMBER_TYPE_UINT8:
{
// read and init number
if (tb_stream_bread_u8(reader->stream, &value.u8))
number = tb_oc_number_init_from_uint8(value.u8);
}
break;
case TB_OC_NUMBER_TYPE_SINT8:
{
// read and init number
if (tb_stream_bread_s8(reader->stream, &value.s8))
number = tb_oc_number_init_from_sint8(value.s8);
}
break;
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
case TB_OC_NUMBER_TYPE_FLOAT:
{
// read and init number
if (tb_stream_bread_float_be(reader->stream, &value.f))
number = tb_oc_number_init_from_float(value.f);
}
break;
case TB_OC_NUMBER_TYPE_DOUBLE:
{
// read and init number
if (tb_stream_bread_double_bbe(reader->stream, &value.d))
number = tb_oc_number_init_from_double(value.d);
}
break;
#endif
default:
tb_assert_and_check_return_val(0, tb_null);
break;
}
// ok?
return number;
}
static tb_object_ref_t tb_oc_bin_reader_func_boolean(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size)
{
// check
tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null);
// ok?
return tb_oc_boolean_init(size? tb_true : tb_false);
}
static tb_object_ref_t tb_oc_bin_reader_func_dictionary(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size)
{
// check
tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null);
// empty?
if (!size) return tb_oc_dictionary_init(TB_OC_DICTIONARY_SIZE_MICRO, tb_false);
// init dictionary
tb_object_ref_t dictionary = tb_oc_dictionary_init(0, tb_false);
tb_assert_and_check_return_val(dictionary, tb_null);
// walk
tb_size_t i = 0;
tb_size_t n = (tb_size_t)size;
for (i = 0; i < n; i++)
{
// read key
tb_object_ref_t key = tb_null;
do
{
// the type & size
tb_size_t type = 0;
tb_uint64_t size = 0;
tb_oc_reader_bin_type_size(reader->stream, &type, &size);
// trace
tb_trace_d("key: type: %lu, size: %llu", type, size);
// is index?
if (!type)
{
// the object index
tb_size_t index = (tb_size_t)size;
// check
tb_assert_and_check_break(index < tb_vector_size(reader->list));
// the item
key = (tb_object_ref_t)tb_iterator_item(reader->list, index);
}
else
{
// check
tb_assert_and_check_break(type == TB_OBJECT_TYPE_STRING);
// the reader func
tb_oc_bin_reader_func_t func = tb_oc_bin_reader_func(type);
tb_assert_and_check_break(func);
// read it
key = func(reader, type, size);
tb_assert_and_check_break(key);
// save it
tb_vector_insert_tail(reader->list, key);
// refn--
tb_object_exit(key);
}
} while (0);
// check
tb_assert_and_check_break(key && tb_object_type(key) == TB_OBJECT_TYPE_STRING);
tb_assert_and_check_break(tb_oc_string_size(key) && tb_oc_string_cstr(key));
// read val
tb_object_ref_t val = tb_null;
do
{
// the type & size
tb_size_t type = 0;
tb_uint64_t size = 0;
tb_oc_reader_bin_type_size(reader->stream, &type, &size);
// trace
tb_trace_d("val: type: %lu, size: %llu", type, size);
// is index?
if (!type)
{
// the object index
tb_size_t index = (tb_size_t)size;
// check
tb_assert_and_check_break(index < tb_vector_size(reader->list));
// the item
val = (tb_object_ref_t)tb_iterator_item(reader->list, index);
// refn++
if (val) tb_object_retain(val);
}
else
{
// the reader func
tb_oc_bin_reader_func_t func = tb_oc_bin_reader_func(type);
tb_assert_and_check_break(func);
// read it
val = func(reader, type, size);
// save it
if (val) tb_vector_insert_tail(reader->list, val);
}
} while (0);
// check
tb_assert_and_check_break(val);
// set key => val
tb_oc_dictionary_insert(dictionary, tb_oc_string_cstr(key), val);
}
// failed?
if (i != n)
{
if (dictionary) tb_object_exit(dictionary);
dictionary = tb_null;
}
// ok?
return dictionary;
}
static tb_object_ref_t tb_oc_bin_reader_done(tb_stream_ref_t stream)
{
// read bin header
tb_byte_t data[32] = {0};
if (!tb_stream_bread(stream, data, 5)) return tb_null;
// check
if (tb_strnicmp((tb_char_t const*)data, "tbo00", 5)) return tb_null;
// init
tb_object_ref_t object = tb_null;
tb_oc_bin_reader_t reader = {0};
// init reader
reader.stream = stream;
reader.list = tb_vector_init(256, tb_element_obj());
tb_assert_and_check_return_val(reader.list, tb_null);
// the type & size
tb_size_t type = 0;
tb_uint64_t size = 0;
tb_oc_reader_bin_type_size(stream, &type, &size);
// trace
tb_trace_d("root: type: %lu, size: %llu", type, size);
// the func
tb_oc_bin_reader_func_t func = tb_oc_bin_reader_func(type);
// check
tb_assert(func);
// read it
if (func) object = func(&reader, type, size);
// exit the list
if (reader.list) tb_vector_exit(reader.list);
// ok?
return object;
}
static tb_size_t tb_oc_bin_reader_probe(tb_stream_ref_t stream)
{
// check
tb_assert_and_check_return_val(stream, 0);
// need it
tb_byte_t* p = tb_null;
if (!tb_stream_need(stream, &p, 3)) return 0;
tb_assert_and_check_return_val(p, 0);
// ok?
return !tb_strnicmp((tb_char_t const*)p, "tbo", 3)? 80 : 0;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_oc_reader_t* tb_oc_bin_reader()
{
// the reader
static tb_oc_reader_t s_reader = {0};
// init reader
s_reader.read = tb_oc_bin_reader_done;
s_reader.probe = tb_oc_bin_reader_probe;
// init hooker
s_reader.hooker = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_uint32(), tb_element_ptr(tb_null, tb_null));
tb_assert_and_check_return_val(s_reader.hooker, tb_null);
// hook reader
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OBJECT_TYPE_NULL, tb_oc_bin_reader_func_null);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DATE, tb_oc_bin_reader_func_date);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DATA, tb_oc_bin_reader_func_data);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OBJECT_TYPE_ARRAY, tb_oc_bin_reader_func_array);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OBJECT_TYPE_STRING, tb_oc_bin_reader_func_string);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OBJECT_TYPE_NUMBER, tb_oc_bin_reader_func_number);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OBJECT_TYPE_BOOLEAN, tb_oc_bin_reader_func_boolean);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DICTIONARY, tb_oc_bin_reader_func_dictionary);
// ok
return &s_reader;
}
tb_bool_t tb_oc_bin_reader_hook(tb_size_t type, tb_oc_bin_reader_func_t func)
{
// check
tb_assert_and_check_return_val(type && func, tb_false);
// the reader
tb_oc_reader_t* reader = tb_oc_reader_get(TB_OBJECT_FORMAT_BIN);
tb_assert_and_check_return_val(reader && reader->hooker, tb_false);
// hook it
tb_hash_map_insert(reader->hooker, (tb_pointer_t)type, func);
// ok
return tb_true;
}
tb_oc_bin_reader_func_t tb_oc_bin_reader_func(tb_size_t type)
{
// check
tb_assert_and_check_return_val(type, tb_null);
// the reader
tb_oc_reader_t* reader = tb_oc_reader_get(TB_OBJECT_FORMAT_BIN);
tb_assert_and_check_return_val(reader && reader->hooker, tb_null);
// the func
return (tb_oc_bin_reader_func_t)tb_hash_map_get(reader->hooker, (tb_pointer_t)type);
}
tbox-1.7.6/src/tbox/object/impl/reader/bin.h 0000664 0000000 0000000 00000004527 14671175054 0020660 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file bin.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_IMPL_READER_BIN_H
#define TB_OBJECT_IMPL_READER_BIN_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the bin reader type
typedef struct __tb_oc_bin_reader_t
{
/// the stream
tb_stream_ref_t stream;
/// the object list
tb_vector_ref_t list;
}tb_oc_bin_reader_t;
/// the bin reader func type
typedef tb_object_ref_t (*tb_oc_bin_reader_func_t)(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the bin reader
*
* @return the bin object reader
*/
tb_oc_reader_t* tb_oc_bin_reader(tb_noarg_t);
/*! hook the bin reader
*
* @param type the object type
* @param func the reader func
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_bin_reader_hook(tb_size_t type, tb_oc_bin_reader_func_t func);
/*! the bin reader func
*
* @param type the object type
*
* @return the object reader func
*/
tb_oc_bin_reader_func_t tb_oc_bin_reader_func(tb_size_t type);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/object/impl/reader/bplist.c 0000664 0000000 0000000 00000063774 14671175054 0021411 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file bplist.c
* @ingroup object
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "oc_reader_bplist"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "bplist.h"
#include "reader.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the array grow
#ifdef __tb_small__
# define TB_OC_BPLIST_READER_ARRAY_GROW (64)
#else
# define TB_OC_BPLIST_READER_ARRAY_GROW (256)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the bplist type enum
typedef enum __tb_oc_bplist_type_e
{
TB_OC_BPLIST_TYPE_NONE = 0x00
, TB_OC_BPLIST_TYPE_FALSE = 0x08
, TB_OC_BPLIST_TYPE_TRUE = 0x09
, TB_OC_BPLIST_TYPE_UINT = 0x10
, TB_OC_BPLIST_TYPE_REAL = 0x20
, TB_OC_BPLIST_TYPE_DATE = 0x30
, TB_OC_BPLIST_TYPE_DATA = 0x40
, TB_OC_BPLIST_TYPE_STRING = 0x50
, TB_OC_BPLIST_TYPE_UNICODE = 0x60
, TB_OC_BPLIST_TYPE_UID = 0x80
, TB_OC_BPLIST_TYPE_ARRAY = 0xA0
, TB_OC_BPLIST_TYPE_SET = 0xC0
, TB_OC_BPLIST_TYPE_DICT = 0xD0
, TB_OC_BPLIST_TYPE_MASK = 0xF0
}tb_oc_bplist_type_e;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static __tb_inline__ tb_time_t tb_oc_bplist_reader_time_apple2host(tb_time_t time)
{
tb_tm_t tm = {0};
if (tb_localtime(time, &tm))
{
if (tm.year < 2000) tm.year += 31;
time = tb_mktime(&tm);
}
return time;
}
static __tb_inline__ tb_size_t tb_oc_bplist_bits_get(tb_byte_t const* p, tb_size_t n)
{
tb_size_t v = 0;
switch (n)
{
case 1: v = tb_bits_get_u8((p)); break;
case 2: v = tb_bits_get_u16_be((p)); break;
case 4: v = tb_bits_get_u32_be((p)); break;
case 8: v = tb_bits_get_u64_be((p)); break;
default: break;
}
return v;
}
static tb_object_ref_t tb_oc_bplist_reader_func_object(tb_oc_bplist_reader_t* reader, tb_size_t item_size)
{
// check
tb_assert_and_check_return_val(reader && reader->stream, tb_null);
// read the object type
tb_uint8_t type = 0;
tb_bool_t ok = tb_stream_bread_u8(reader->stream, &type);
tb_assert_and_check_return_val(ok, tb_null);
// read the object type and size
tb_uint8_t size = type & 0x0f; type &= 0xf0;
tb_trace_d("type: %x, size: %x", type, size);
// the func
tb_oc_bplist_reader_func_t func = tb_oc_bplist_reader_func(type);
tb_assert_and_check_return_val(func, tb_null);
// read
return func(reader, type, size, item_size);
}
static tb_long_t tb_oc_bplist_reader_func_size(tb_oc_bplist_reader_t* reader, tb_size_t item_size)
{
// check
tb_assert_and_check_return_val(reader && reader->stream, -1);
// read size
tb_object_ref_t object = tb_oc_bplist_reader_func_object(reader, item_size);
tb_assert_and_check_return_val(object, -1);
tb_long_t size = -1;
if (tb_object_type(object) == TB_OBJECT_TYPE_NUMBER)
size = tb_oc_number_uint32(object);
// exit
tb_object_exit(object);
// size
return size;
}
static tb_object_ref_t tb_oc_bplist_reader_func_data(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size)
{
// check
tb_assert_and_check_return_val(reader && reader->stream, tb_null);
// init
tb_byte_t* data = tb_null;
tb_object_ref_t object = tb_null;
// size is too large?
if (size == 0x0f)
{
// read size
tb_long_t val = tb_oc_bplist_reader_func_size(reader, item_size);
tb_assert_and_check_return_val(val >= 0, tb_null);
size = (tb_size_t)val;
}
// no empty?
if (size)
{
// make data
data = tb_malloc_bytes(size);
tb_assert_and_check_return_val(data, tb_null);
// read data
if (tb_stream_bread(reader->stream, data, size))
object = tb_oc_data_init_from_data(data, size);
}
else object = tb_oc_data_init_from_data(tb_null, 0);
// exit
if (data) tb_free(data);
// ok?
return object;
}
static tb_object_ref_t tb_oc_bplist_reader_func_array(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size)
{
// check
tb_assert_and_check_return_val(reader && reader->stream, tb_null);
// init
tb_object_ref_t object = tb_null;
// size is too large?
if (size == 0x0f)
{
// read size
tb_long_t val = tb_oc_bplist_reader_func_size(reader, item_size);
tb_assert_and_check_return_val(val >= 0, tb_null);
size = (tb_size_t)val;
}
// init array
object = tb_oc_array_init(size? size : 16, tb_false);
tb_assert_and_check_return_val(object, tb_null);
// init items data
if (size)
{
tb_byte_t* data = tb_malloc_bytes(sizeof(tb_uint32_t) + (size * item_size));
if (data)
{
if (tb_stream_bread(reader->stream, data + sizeof(tb_uint32_t), size * item_size))
{
tb_bits_set_u32_ne(data, (tb_uint32_t)size);
// FIXME: not using the user private data
tb_object_setp(object, data);
}
else tb_free(data);
}
}
// ok?
return object;
}
static tb_object_ref_t tb_oc_bplist_reader_func_string(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size)
{
// check
tb_assert_and_check_return_val(reader && reader->stream, tb_null);
// init
tb_char_t* utf8 = tb_null;
tb_char_t* utf16 = tb_null;
tb_object_ref_t object = tb_null;
// read
switch (type)
{
case TB_OC_BPLIST_TYPE_STRING:
{
// size is too large?
if (size == 0x0f)
{
// read size
tb_long_t val = tb_oc_bplist_reader_func_size(reader, item_size);
tb_assert_and_check_return_val(val >= 0, tb_null);
size = (tb_size_t)val;
}
// read string
if (size)
{
// init utf8
utf8 = tb_malloc_cstr(size + 1);
tb_assert_and_check_break(utf8);
// read utf8
if (!tb_stream_bread(reader->stream, (tb_byte_t*)utf8, size)) break;
utf8[size] = '\0';
}
// init object
object = tb_oc_string_init_from_cstr(utf8);
}
break;
case TB_OC_BPLIST_TYPE_UNICODE:
{
#ifdef TB_CONFIG_MODULE_HAVE_CHARSET
// size is too large?
if (size == 0x0f)
{
// read size
tb_long_t val = tb_oc_bplist_reader_func_size(reader, item_size);
tb_assert_and_check_return_val(val >= 0, tb_null);
size = (tb_size_t)val;
}
// read string
if (size)
{
// init utf8 & utf16 data
utf8 = tb_malloc_cstr((size + 1) << 2);
utf16 = tb_malloc_cstr(size << 1);
tb_assert_and_check_break(utf8 && utf16);
// read utf16
if (!tb_stream_bread(reader->stream, (tb_byte_t*)utf16, size << 1)) break;
// utf16 to utf8
tb_long_t osize = tb_charset_conv_data(TB_CHARSET_TYPE_UTF16, TB_CHARSET_TYPE_UTF8, (tb_byte_t*)utf16, size << 1, (tb_byte_t*)utf8, (size + 1) << 2);
tb_assert_and_check_break(osize > 0 && osize < (tb_long_t)((size + 1) << 2));
utf8[osize] = '\0';
// init object
object = tb_oc_string_init_from_cstr(utf8);
}
#else
// trace
tb_trace1_e("unicode type is not supported, please enable charset module config if you want to use it!");
#endif
}
break;
default:
break;
}
// exit
if (utf8) tb_free(utf8);
if (utf16) tb_free(utf16);
// ok?
return object;
}
static tb_object_ref_t tb_oc_bplist_reader_func_number(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size)
{
// check
tb_assert_and_check_return_val(reader && reader->stream, tb_null);
// adjust size
size = (tb_size_t)1 << size;
// done
tb_value_t value;
tb_object_ref_t object = tb_null;
switch (size)
{
case 1:
{
// read and init object
if (tb_stream_bread_u8(reader->stream, &value.u8))
object = tb_oc_number_init_from_uint8(value.u8);
}
break;
case 2:
{
// read and init object
if (tb_stream_bread_u16_be(reader->stream, &value.u16))
object = tb_oc_number_init_from_uint16(value.u16);
}
break;
case 4:
{
switch (type)
{
case TB_OC_BPLIST_TYPE_UID:
case TB_OC_BPLIST_TYPE_UINT:
{
// read and init object
if (tb_stream_bread_u32_be(reader->stream, &value.u32))
object = tb_oc_number_init_from_uint32(value.u32);
}
break;
case TB_OC_BPLIST_TYPE_REAL:
{
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
// read and init object
if (tb_stream_bread_float_be(reader->stream, &value.f))
object = tb_oc_number_init_from_float(value.f);
#else
tb_trace_e("real type is not supported! please enable float config.");
#endif
}
break;
default:
tb_assert(0);
break;
}
}
break;
case 8:
{
switch (type)
{
case TB_OC_BPLIST_TYPE_UID:
case TB_OC_BPLIST_TYPE_UINT:
{
// read and init object
if (tb_stream_bread_u64_be(reader->stream, &value.u64))
object = tb_oc_number_init_from_uint64(value.u64);
}
break;
case TB_OC_BPLIST_TYPE_REAL:
{
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
// read and init object
if (tb_stream_bread_double_bbe(reader->stream, &value.d))
object = tb_oc_number_init_from_double(value.d);
#else
tb_trace_e("real type is not supported! please enable float config.");
#endif
}
break;
default:
tb_assert(0);
break;
}
}
break;
default:
tb_assert(0);
break;
}
// ok?
return object;
}
static tb_object_ref_t tb_oc_bplist_reader_func_uid(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size)
{
// check
tb_assert_and_check_return_val(reader && reader->stream, tb_null);
// done
tb_bool_t ok = tb_false;
tb_object_ref_t uid = tb_null;
tb_object_ref_t value = tb_null;
do
{
// read uid value
value = tb_oc_bplist_reader_func_number(reader, TB_OC_BPLIST_TYPE_UINT, size, item_size);
tb_assert_and_check_break(value);
// init uid object
uid = tb_oc_dictionary_init(8, tb_false);
tb_assert_and_check_break(uid);
// save this uid value
tb_oc_dictionary_insert(uid, "CF$UID", value);
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit value
if (value) tb_object_exit(value);
value = tb_null;
}
// ok?
return uid;
}
static tb_object_ref_t tb_oc_bplist_reader_func_date(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size)
{
// check
tb_assert_and_check_return_val(reader && reader->stream, tb_null);
// the date data
tb_object_ref_t data = tb_oc_bplist_reader_func_number(reader, TB_OC_BPLIST_TYPE_REAL, size, item_size);
tb_assert_and_check_return_val(data, tb_null);
// init date
tb_object_ref_t date = tb_oc_date_init_from_time(tb_oc_bplist_reader_time_apple2host((tb_time_t)tb_oc_number_uint64(data)));
// exit data
tb_object_exit(data);
// ok?
return date;
}
static tb_object_ref_t tb_oc_bplist_reader_func_boolean(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size)
{
// init
tb_object_ref_t object = tb_null;
// read
switch (size)
{
case TB_OC_BPLIST_TYPE_TRUE:
object = tb_oc_boolean_init(tb_true);
break;
case TB_OC_BPLIST_TYPE_FALSE:
object = tb_oc_boolean_init(tb_false);
break;
default:
tb_assert(0);
break;
}
return object;
}
static tb_object_ref_t tb_oc_bplist_reader_func_dictionary(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size)
{
// check
tb_assert_and_check_return_val(reader && reader->stream, tb_null);
// init
tb_object_ref_t object = tb_null;
// size is too large?
if (size == 0x0f)
{
// read size
tb_long_t val = tb_oc_bplist_reader_func_size(reader, item_size);
tb_assert_and_check_return_val(val >= 0, tb_null);
size = (tb_size_t)val;
}
// init dictionary
object = tb_oc_dictionary_init(TB_OC_DICTIONARY_SIZE_MICRO, tb_false);
tb_assert_and_check_return_val(object, tb_null);
// init items data
if (size)
{
item_size <<= 1;
tb_byte_t* data = tb_malloc_bytes(sizeof(tb_uint32_t) + (size * item_size));
if (data)
{
if (tb_stream_bread(reader->stream, data + sizeof(tb_uint32_t), size * item_size))
{
tb_bits_set_u32_ne(data, (tb_uint32_t)size);
tb_object_setp(object, data);
}
else tb_free(data);
}
}
// ok?
return object;
}
static tb_object_ref_t tb_oc_bplist_reader_done(tb_stream_ref_t stream)
{
// check
tb_assert_and_check_return_val(stream, tb_null);
// init root
tb_object_ref_t root = tb_null;
// init reader
tb_oc_bplist_reader_t reader = {0};
reader.stream = stream;
// init size
tb_hize_t size = tb_stream_size(stream);
tb_assert_and_check_return_val(size, tb_null);
// init data
tb_byte_t data[32] = {0};
// read magic & version
if (!tb_stream_bread(stream, data, 8)) return tb_null;
// check magic & version
if (tb_strncmp((tb_char_t const*)data, "bplist00", 8)) return tb_null;
// seek to tail
if (!tb_stream_seek(stream, size - 26)) return tb_null;
// read offset size
tb_uint8_t offset_size = 0;
if (!tb_stream_bread_u8(stream, &offset_size)) return tb_null;
// read item size for array and dictionary
tb_uint8_t item_size = 0;
if (!tb_stream_bread_u8(stream, &item_size)) return tb_null;
// read object count
tb_uint64_t object_count = 0;
if (!tb_stream_bread_u64_be(stream, &object_count)) return tb_null;
// read root object
tb_uint64_t root_object = 0;
if (!tb_stream_bread_u64_be(stream, &root_object)) return tb_null;
// read offset table index
tb_uint64_t offset_table_index = 0;
if (!tb_stream_bread_u64_be(stream, &offset_table_index)) return tb_null;
// trace
tb_trace_d("offset_size: %u", offset_size);
tb_trace_d("item_size: %u", item_size);
tb_trace_d("object_count: %llu", object_count);
tb_trace_d("root_object: %llu", root_object);
tb_trace_d("offset_table_index: %llu", offset_table_index);
// check
tb_assert_and_check_return_val(item_size && offset_size && object_count, tb_null);
// init object hash
tb_object_ref_t* object_hash = (tb_object_ref_t*)tb_malloc0(sizeof(tb_object_ref_t) * (tb_size_t)object_count);
tb_assert_and_check_return_val(object_hash, tb_null);
// done
tb_bool_t failed = tb_false;
do
{
// walk
tb_size_t i = 0;
for (i = 0; i < object_count; i++)
{
// seek to the offset entry
if (!tb_stream_seek(stream, offset_table_index + i * offset_size))
{
failed = tb_true;
break;
}
// read the object offset
tb_value_t value;
tb_hize_t offset = 0;
switch (offset_size)
{
case 1:
if (tb_stream_bread_u8(stream, &value.u8)) offset = value.u8;
break;
case 2:
if (tb_stream_bread_u16_be(stream, &value.u16)) offset = value.u16;
break;
case 4:
if (tb_stream_bread_u32_be(stream, &value.u32)) offset = value.u32;
break;
case 8:
if (tb_stream_bread_u64_be(stream, &value.u64)) offset = value.u64;
break;
default:
return tb_null;
break;
}
tb_check_break(!failed);
// seek to the object offset
if (!tb_stream_seek(stream, offset))
{
failed = tb_true;
break;
}
// read object
object_hash[i] = tb_oc_bplist_reader_func_object(&reader, item_size);
}
// failed?
tb_check_break(!failed);
// build array and dictionary items
for (i = 0; i < object_count; i++)
{
tb_object_ref_t object = object_hash[i];
if (object)
{
switch (tb_object_type(object))
{
case TB_OBJECT_TYPE_ARRAY:
{
// the priv data
tb_byte_t* priv = (tb_byte_t*)tb_object_getp(object);
if (priv)
{
// count
tb_size_t count = (tb_size_t)tb_bits_get_u32_ne(priv);
if (count)
{
// goto item data
tb_byte_t const* p = priv + sizeof(tb_uint32_t);
// walk items
tb_size_t j = 0;
for (j = 0; j < count; j++)
{
// the item index
tb_size_t item = tb_oc_bplist_bits_get(p + j * item_size, item_size);
tb_assert(item < object_count && object_hash[item]);
// append item
if (item < object_count && object_hash[item])
{
tb_object_retain(object_hash[item]);
tb_oc_array_append(object, object_hash[item]);
}
}
}
// exit priv
tb_free(priv);
tb_object_setp(object, tb_null);
}
}
break;
case TB_OBJECT_TYPE_DICTIONARY:
{
// the priv data
tb_byte_t* priv = (tb_byte_t*)tb_object_getp(object);
if (priv)
{
// count
tb_size_t count = (tb_size_t)tb_bits_get_u32_ne(priv);
if (count)
{
// goto item data
tb_byte_t const* p = priv + sizeof(tb_uint32_t);
// walk items
tb_size_t j = 0;
for (j = 0; j < count; j++)
{
// the key and val
tb_size_t key = tb_oc_bplist_bits_get(p + j * item_size, item_size);
tb_size_t val = tb_oc_bplist_bits_get(p + (count + j) * item_size, item_size);
tb_assert(key < object_count && object_hash[key]);
tb_assert(val < object_count && object_hash[val]);
// append the key & val
if (key < object_count && val < object_count && object_hash[key] && object_hash[val])
{
// key must be string now.
tb_assert(tb_object_type(object_hash[key]) == TB_OBJECT_TYPE_STRING);
if (tb_object_type(object_hash[key]) == TB_OBJECT_TYPE_STRING)
{
// set key => val
tb_char_t const* skey = tb_oc_string_cstr(object_hash[key]);
if (skey)
{
tb_object_retain(object_hash[val]);
tb_oc_dictionary_insert(object, skey, object_hash[val]);
}
tb_assert(skey);
}
}
}
}
// exit priv
tb_free(priv);
tb_object_setp(object, tb_null);
}
}
break;
default:
break;
}
}
}
} while (0);
// exit object hash
if (object_hash)
{
// root
if (root_object < object_count) root = object_hash[root_object];
// refn--
tb_size_t i;
for (i = 0; i < object_count; i++)
{
if (object_hash[i] && i != root_object)
tb_object_exit(object_hash[i]);
}
// exit object hash
tb_free(object_hash);
object_hash = tb_null;
}
// ok?
return root;
}
static tb_size_t tb_oc_bplist_reader_probe(tb_stream_ref_t stream)
{
// check
tb_assert_and_check_return_val(stream, 0);
// need it
tb_byte_t* p = tb_null;
if (!tb_stream_need(stream, &p, 6)) return 0;
tb_assert_and_check_return_val(p, 0);
// ok?
return !tb_strnicmp((tb_char_t const*)p, "bplist", 6)? 80 : 0;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_oc_reader_t* tb_oc_bplist_reader()
{
// the reader
static tb_oc_reader_t s_reader = {0};
// init reader
s_reader.read = tb_oc_bplist_reader_done;
s_reader.probe = tb_oc_bplist_reader_probe;
// init hooker
s_reader.hooker = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_uint32(), tb_element_ptr(tb_null, tb_null));
tb_assert_and_check_return_val(s_reader.hooker, tb_null);
// hook reader
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_DATE, tb_oc_bplist_reader_func_date);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_DATA, tb_oc_bplist_reader_func_data);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_UID, tb_oc_bplist_reader_func_uid);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_ARRAY, tb_oc_bplist_reader_func_array);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_STRING, tb_oc_bplist_reader_func_string);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_UNICODE, tb_oc_bplist_reader_func_string);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_UINT, tb_oc_bplist_reader_func_number);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_REAL, tb_oc_bplist_reader_func_number);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_NONE, tb_oc_bplist_reader_func_boolean);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_SET, tb_oc_bplist_reader_func_dictionary);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_DICT, tb_oc_bplist_reader_func_dictionary);
// ok
return &s_reader;
}
tb_bool_t tb_oc_bplist_reader_hook(tb_size_t type, tb_oc_bplist_reader_func_t func)
{
// check
tb_assert_and_check_return_val(func, tb_false);
// the reader
tb_oc_reader_t* reader = tb_oc_reader_get(TB_OBJECT_FORMAT_BPLIST);
tb_assert_and_check_return_val(reader && reader->hooker, tb_false);
// hook it
tb_hash_map_insert(reader->hooker, (tb_pointer_t)type, func);
// ok
return tb_true;
}
tb_oc_bplist_reader_func_t tb_oc_bplist_reader_func(tb_size_t type)
{
// the reader
tb_oc_reader_t* reader = tb_oc_reader_get(TB_OBJECT_FORMAT_BPLIST);
tb_assert_and_check_return_val(reader && reader->hooker, tb_null);
// the func
return (tb_oc_bplist_reader_func_t)tb_hash_map_get(reader->hooker, (tb_pointer_t)type);
}
tbox-1.7.6/src/tbox/object/impl/reader/bplist.h 0000664 0000000 0000000 00000004536 14671175054 0021405 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file bplist.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_IMPL_READER_BPLIST_H
#define TB_OBJECT_IMPL_READER_BPLIST_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the bplist reader type
typedef struct __tb_oc_bplist_reader_t
{
/// the stream
tb_stream_ref_t stream;
}tb_oc_bplist_reader_t;
/// the bplist reader func type
typedef tb_object_ref_t (*tb_oc_bplist_reader_func_t)(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the bplist reader
*
* @return the bplist object reader
*/
tb_oc_reader_t* tb_oc_bplist_reader(tb_noarg_t);
/*! hook the bplist reader
*
* @param type the object type
* @param func the reader func
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_bplist_reader_hook(tb_size_t type, tb_oc_bplist_reader_func_t func);
/*! the bplist reader func
*
* @param type the object type
*
* @return the object reader func
*/
tb_oc_bplist_reader_func_t tb_oc_bplist_reader_func(tb_size_t type);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/object/impl/reader/json.c 0000664 0000000 0000000 00000045117 14671175054 0021054 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file json.c
* @ingroup object
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "oc_reader_json"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "json.h"
#include "reader.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the array grow
#ifdef __tb_small__
# define TB_OC_JSON_READER_ARRAY_GROW (64)
#else
# define TB_OC_JSON_READER_ARRAY_GROW (256)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_object_ref_t tb_oc_json_reader_func_null(tb_oc_json_reader_t* reader, tb_char_t type)
{
// check
tb_assert_and_check_return_val(reader && reader->stream, tb_null);
// init data
tb_static_string_t data;
tb_char_t buff[256];
if (!tb_static_string_init(&data, buff, 256)) return tb_null;
// done
tb_object_ref_t null = tb_null;
do
{
// append character
tb_static_string_chrcat(&data, type);
// walk
tb_bool_t failed = tb_false;
while (!failed && tb_stream_left(reader->stream))
{
// need one character
tb_byte_t* p = tb_null;
if (!tb_stream_need(reader->stream, &p, 1) && p)
{
failed = tb_true;
break;
}
// the character
tb_char_t ch = *p;
// append character
if (tb_isalpha(ch)) tb_static_string_chrcat(&data, ch);
else break;
// skip it
tb_stream_skip(reader->stream, 1);
}
// failed?
tb_check_break(!failed);
// check
tb_assert_and_check_break(tb_static_string_size(&data));
// trace
tb_trace_d("null: %s", tb_static_string_cstr(&data));
// null?
if (!tb_stricmp(tb_static_string_cstr(&data), "null")) null = tb_oc_null_init();
} while (0);
// exit data
tb_static_string_exit(&data);
// ok?
return null;
}
static tb_object_ref_t tb_oc_json_reader_func_array(tb_oc_json_reader_t* reader, tb_char_t type)
{
// check
tb_assert_and_check_return_val(reader && reader->stream && type == '[', tb_null);
// init array
tb_object_ref_t array = tb_oc_array_init(TB_OC_JSON_READER_ARRAY_GROW, tb_false);
tb_assert_and_check_return_val(array, tb_null);
// done
tb_char_t ch;
tb_bool_t ok = tb_true;
while (ok && tb_stream_left(reader->stream))
{
// read one character
if (!tb_stream_bread_s8(reader->stream, (tb_sint8_t*)&ch)) break;
// end?
if (ch == ']') break;
// no space? skip ','
else if (!tb_isspace(ch) && ch != ',')
{
// the func
tb_oc_json_reader_func_t func = tb_oc_json_reader_func(ch);
tb_assert_and_check_break_state(func, ok, tb_false);
// read item
tb_object_ref_t item = func(reader, ch);
tb_assert_and_check_break_state(item, ok, tb_false);
// append item
tb_oc_array_append(array, item);
}
}
// failed?
if (!ok)
{
// exit it
if (array) tb_object_exit(array);
array = tb_null;
}
// ok?
return array;
}
static tb_object_ref_t tb_oc_json_reader_func_string(tb_oc_json_reader_t* reader, tb_char_t type)
{
// check
tb_assert_and_check_return_val(reader && reader->stream && (type == '\"' || type == '\''), tb_null);
// init data
tb_string_t data;
if (!tb_string_init(&data)) return tb_null;
// walk
tb_char_t ch;
while (tb_stream_left(reader->stream))
{
// read one character
if (!tb_stream_bread_s8(reader->stream, (tb_sint8_t*)&ch)) break;
// end?
if (ch == '\"' || ch == '\'') break;
// the escaped character?
else if (ch == '\\')
{
// read one character
if (!tb_stream_bread_s8(reader->stream, (tb_sint8_t*)&ch)) break;
// unicode?
if (ch == 'u')
{
#ifdef TB_CONFIG_MODULE_HAVE_CHARSET
// the unicode string
tb_char_t unicode_str[5];
if (!tb_stream_bread(reader->stream, (tb_byte_t*)unicode_str, 4)) break;
unicode_str[4] = '\0';
// the unicode value
tb_uint16_t unicode_val = tb_s16toi32(unicode_str);
// the utf8 stream
tb_char_t utf8_data[16] = {0};
tb_static_stream_t utf8_stream;
tb_static_stream_init(&utf8_stream, (tb_byte_t*)utf8_data, sizeof(utf8_data));
// the unicode stream
tb_static_stream_t unicode_stream = {0};
tb_static_stream_init(&unicode_stream, (tb_byte_t*)&unicode_val, 2);
// unicode to utf8
tb_long_t utf8_size = tb_charset_conv_bst(TB_CHARSET_TYPE_UCS2 | TB_CHARSET_TYPE_NE, TB_CHARSET_TYPE_UTF8, &unicode_stream, &utf8_stream);
if (utf8_size > 0) tb_string_cstrncat(&data, utf8_data, utf8_size);
#else
// trace
tb_trace1_e("unicode type is not supported, please enable charset module config if you want to use it!");
// only append it
tb_string_chrcat(&data, ch);
#endif
}
else if (ch == 'n') {
tb_string_chrcat(&data, '\n');
}
else if (ch == 't') {
tb_string_chrcat(&data, '\t');
}
// append escaped character
else tb_string_chrcat(&data, ch);
}
// append character
else tb_string_chrcat(&data, ch);
}
// init string
tb_object_ref_t string = tb_oc_string_init_from_cstr(tb_string_cstr(&data));
// trace
tb_trace_d("string: %s", tb_string_cstr(&data));
// exit data
tb_string_exit(&data);
// ok?
return string;
}
static tb_object_ref_t tb_oc_json_reader_func_number(tb_oc_json_reader_t* reader, tb_char_t type)
{
// check
tb_assert_and_check_return_val(reader && reader->stream, tb_null);
// init data
tb_static_string_t data;
tb_char_t buff[256];
if (!tb_static_string_init(&data, buff, 256)) return tb_null;
// done
tb_object_ref_t number = tb_null;
do
{
// append character
tb_static_string_chrcat(&data, type);
// walk
tb_bool_t bs = (type == '-')? tb_true : tb_false;
tb_bool_t bf = (type == '.')? tb_true : tb_false;
tb_bool_t failed = tb_false;
while (!failed && tb_stream_left(reader->stream))
{
// need one character
tb_byte_t* p = tb_null;
if (!tb_stream_need(reader->stream, &p, 1) && p)
{
failed = tb_true;
break;
}
// the character
tb_char_t ch = *p;
// is float?
if (!bf && ch == '.') bf = tb_true;
else if (bf && ch == '.')
{
failed = tb_true;
break;
}
// append character
if (tb_isdigit10(ch) || ch == '.' || ch == 'e' || ch == 'E' || ch == '-' || ch == '+')
tb_static_string_chrcat(&data, ch);
else break;
// skip it
tb_stream_skip(reader->stream, 1);
}
// failed?
tb_check_break(!failed);
// check
tb_assert_and_check_break(tb_static_string_size(&data));
// trace
tb_trace_d("number: %s", tb_static_string_cstr(&data));
// init number
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
if (bf) number = tb_oc_number_init_from_float(tb_stof(tb_static_string_cstr(&data)));
#else
if (bf) tb_trace_noimpl();
#endif
else if (bs)
{
tb_sint64_t value = tb_stoi64(tb_static_string_cstr(&data));
tb_size_t bytes = tb_object_need_bytes(-value);
switch (bytes)
{
case 1: number = tb_oc_number_init_from_sint8((tb_sint8_t)value); break;
case 2: number = tb_oc_number_init_from_sint16((tb_sint16_t)value); break;
case 4: number = tb_oc_number_init_from_sint32((tb_sint32_t)value); break;
case 8: number = tb_oc_number_init_from_sint64((tb_sint64_t)value); break;
default: break;
}
}
else
{
tb_uint64_t value = tb_stou64(tb_static_string_cstr(&data));
tb_size_t bytes = tb_object_need_bytes(value);
switch (bytes)
{
case 1: number = tb_oc_number_init_from_uint8((tb_uint8_t)value); break;
case 2: number = tb_oc_number_init_from_uint16((tb_uint16_t)value); break;
case 4: number = tb_oc_number_init_from_uint32((tb_uint32_t)value); break;
case 8: number = tb_oc_number_init_from_uint64((tb_uint64_t)value); break;
default: break;
}
}
} while (0);
// exit data
tb_static_string_exit(&data);
// ok?
return number;
}
static tb_object_ref_t tb_oc_json_reader_func_boolean(tb_oc_json_reader_t* reader, tb_char_t type)
{
// check
tb_assert_and_check_return_val(reader && reader->stream, tb_null);
// init data
tb_static_string_t data;
tb_char_t buff[256];
if (!tb_static_string_init(&data, buff, 256)) return tb_null;
// done
tb_object_ref_t boolean = tb_null;
do
{
// append character
tb_static_string_chrcat(&data, type);
// walk
tb_bool_t failed = tb_false;
while (!failed && tb_stream_left(reader->stream))
{
// need one character
tb_byte_t* p = tb_null;
if (!tb_stream_need(reader->stream, &p, 1) && p)
{
failed = tb_true;
break;
}
// the character
tb_char_t ch = *p;
// append character
if (tb_isalpha(ch)) tb_static_string_chrcat(&data, ch);
else break;
// skip it
tb_stream_skip(reader->stream, 1);
}
// failed?
tb_check_break(!failed);
// check
tb_assert_and_check_break(tb_static_string_size(&data));
// trace
tb_trace_d("boolean: %s", tb_static_string_cstr(&data));
// true?
if (!tb_stricmp(tb_static_string_cstr(&data), "true")) boolean = tb_oc_boolean_init(tb_true);
// false?
else if (!tb_stricmp(tb_static_string_cstr(&data), "false")) boolean = tb_oc_boolean_init(tb_false);
} while (0);
// exit data
tb_static_string_exit(&data);
// ok?
return boolean;
}
static tb_object_ref_t tb_oc_json_reader_func_dictionary(tb_oc_json_reader_t* reader, tb_char_t type)
{
// check
tb_assert_and_check_return_val(reader && reader->stream && type == '{', tb_null);
// init key name
tb_static_string_t kname;
tb_char_t kdata[8192];
if (!tb_static_string_init(&kname, kdata, 8192)) return tb_null;
// init dictionary
tb_object_ref_t dictionary = tb_oc_dictionary_init(0, tb_false);
tb_assert_and_check_return_val(dictionary, tb_null);
// walk
tb_char_t ch;
tb_bool_t ok = tb_true;
tb_bool_t bkey = tb_false;
tb_size_t bstr = 0;
while (ok && tb_stream_left(reader->stream))
{
// read one character
if (!tb_stream_bread_s8(reader->stream, (tb_sint8_t*)&ch)) break;
// end?
if (ch == '}') break;
// no space? skip ','
else if (!tb_isspace(ch) && ch != ',')
{
// no key?
if (!bkey)
{
// is str?
if (ch == '\"' || ch == '\'') bstr = !bstr;
// is key end?
else if (!bstr && ch == ':') bkey = tb_true;
// append key
else if (bstr) tb_static_string_chrcat(&kname, ch);
}
// key ok? read val
else
{
// trace
tb_trace_d("key: %s", tb_static_string_cstr(&kname));
// the func
tb_oc_json_reader_func_t func = tb_oc_json_reader_func(ch);
tb_assert_and_check_break_state(func, ok, tb_false);
// read val
tb_object_ref_t val = func(reader, ch);
tb_assert_and_check_break_state(val, ok, tb_false);
// set key => val
tb_oc_dictionary_insert(dictionary, tb_static_string_cstr(&kname), val);
// reset key
bstr = 0;
bkey = tb_false;
tb_static_string_clear(&kname);
}
}
}
// failed?
if (!ok)
{
// exit it
if (dictionary) tb_object_exit(dictionary);
dictionary = tb_null;
}
// exit key name
tb_static_string_exit(&kname);
// ok?
return dictionary;
}
static tb_object_ref_t tb_oc_json_reader_done(tb_stream_ref_t stream)
{
// check
tb_assert_and_check_return_val(stream, tb_null);
// init reader
tb_oc_json_reader_t reader = {0};
reader.stream = stream;
// skip spaces
tb_char_t type = '\0';
while (tb_stream_left(stream))
{
if (!tb_stream_bread_s8(stream, (tb_sint8_t*)&type)) break;
if (!tb_isspace(type)) break;
}
// empty?
tb_check_return_val(tb_stream_left(stream), tb_null);
// the func
tb_oc_json_reader_func_t func = tb_oc_json_reader_func(type);
tb_assert_and_check_return_val(func, tb_null);
// read it
return func(&reader, type);
}
static tb_size_t tb_oc_json_reader_probe(tb_stream_ref_t stream)
{
// check
tb_assert_and_check_return_val(stream, 0);
// need it
tb_byte_t* p = tb_null;
if (!tb_stream_need(stream, &p, 5)) return 0;
tb_assert_and_check_return_val(p, 0);
// probe it
tb_size_t s = 10;
tb_byte_t* e = p + 5;
for (; p < e && *p; p++)
{
if (*p == '{' || *p == '[')
{
s = 50;
break;
}
else if (!tb_isgraph(*p))
{
s = 0;
break;
}
}
// ok?
return s;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_oc_reader_t* tb_oc_json_reader()
{
// the reader
static tb_oc_reader_t s_reader = {0};
// init reader
s_reader.read = tb_oc_json_reader_done;
s_reader.probe = tb_oc_json_reader_probe;
// init hooker
s_reader.hooker = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_uint8(), tb_element_ptr(tb_null, tb_null));
tb_assert_and_check_return_val(s_reader.hooker, tb_null);
// hook reader
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'n', tb_oc_json_reader_func_null);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'N', tb_oc_json_reader_func_null);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'[', tb_oc_json_reader_func_array);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'\'', tb_oc_json_reader_func_string);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'\"', tb_oc_json_reader_func_string);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'0', tb_oc_json_reader_func_number);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'1', tb_oc_json_reader_func_number);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'2', tb_oc_json_reader_func_number);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'3', tb_oc_json_reader_func_number);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'4', tb_oc_json_reader_func_number);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'5', tb_oc_json_reader_func_number);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'6', tb_oc_json_reader_func_number);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'7', tb_oc_json_reader_func_number);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'8', tb_oc_json_reader_func_number);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'9', tb_oc_json_reader_func_number);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'.', tb_oc_json_reader_func_number);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'-', tb_oc_json_reader_func_number);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'+', tb_oc_json_reader_func_number);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'e', tb_oc_json_reader_func_number);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'E', tb_oc_json_reader_func_number);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'t', tb_oc_json_reader_func_boolean);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'T', tb_oc_json_reader_func_boolean);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'f', tb_oc_json_reader_func_boolean);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'F', tb_oc_json_reader_func_boolean);
tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'{', tb_oc_json_reader_func_dictionary);
// ok
return &s_reader;
}
tb_bool_t tb_oc_json_reader_hook(tb_char_t type, tb_oc_json_reader_func_t func)
{
// check
tb_assert_and_check_return_val(type && func, tb_false);
// the reader
tb_oc_reader_t* reader = tb_oc_reader_get(TB_OBJECT_FORMAT_JSON);
tb_assert_and_check_return_val(reader && reader->hooker, tb_false);
// hook it
tb_hash_map_insert(reader->hooker, (tb_pointer_t)(tb_size_t)type, func);
// ok
return tb_true;
}
tb_oc_json_reader_func_t tb_oc_json_reader_func(tb_char_t type)
{
// check
tb_assert_and_check_return_val(type, tb_null);
// the reader
tb_oc_reader_t* reader = tb_oc_reader_get(TB_OBJECT_FORMAT_JSON);
tb_assert_and_check_return_val(reader && reader->hooker, tb_null);
// the func
return (tb_oc_json_reader_func_t)tb_hash_map_get(reader->hooker, (tb_pointer_t)(tb_size_t)type);
}
tbox-1.7.6/src/tbox/object/impl/reader/json.h 0000664 0000000 0000000 00000004446 14671175054 0021061 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file json.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_IMPL_READER_JSON_H
#define TB_OBJECT_IMPL_READER_JSON_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the json reader type
typedef struct __tb_oc_json_reader_t
{
/// the stream
tb_stream_ref_t stream;
}tb_oc_json_reader_t;
/// the json reader func type
typedef tb_object_ref_t (*tb_oc_json_reader_func_t)(tb_oc_json_reader_t* reader, tb_char_t type);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the json object reader
*
* @return the json object reader
*/
tb_oc_reader_t* tb_oc_json_reader(tb_noarg_t);
/*! hook the json reader
*
* @param type the object type name
* @param func the reader func
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_json_reader_hook(tb_char_t type, tb_oc_json_reader_func_t func);
/*! the json reader func
*
* @param type the object type name
*
* @return the object reader func
*/
tb_oc_json_reader_func_t tb_oc_json_reader_func(tb_char_t type);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/object/impl/reader/prefix.h 0000664 0000000 0000000 00000004353 14671175054 0021402 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_READER_PREFIX_H
#define TB_OBJECT_READER_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* inlines
*/
static __tb_inline__ tb_void_t tb_oc_reader_bin_type_size(tb_stream_ref_t stream, tb_size_t* ptype, tb_uint64_t* psize)
{
// check
tb_assert_and_check_return(stream);
// clear it first
if (ptype) *ptype = 0;
if (psize) *psize = 0;
// the flag
tb_uint8_t flag = 0;
tb_bool_t ok = tb_stream_bread_u8(stream, &flag);
tb_assert_and_check_return(ok);
// read type and size
tb_size_t type = flag >> 4;
tb_uint64_t size = flag & 0x0f;
if (type == 0xf)
{
tb_uint8_t value = 0;
if (tb_stream_bread_u8(stream, &value)) type = value;
}
// done
tb_value_t value;
switch (size)
{
case 0xc:
if (tb_stream_bread_u8(stream, &value.u8)) size = value.u8;
break;
case 0xd:
if (tb_stream_bread_u16_be(stream, &value.u16)) size = value.u16;
break;
case 0xe:
if (tb_stream_bread_u32_be(stream, &value.u32)) size = value.u32;
break;
case 0xf:
if (tb_stream_bread_u64_be(stream, &value.u64)) size = value.u64;
break;
default:
break;
}
// trace
// tb_trace_d("type: %lu, size: %llu", type, size);
// save
if (ptype) *ptype = type;
if (psize) *psize = size;
}
#endif
tbox-1.7.6/src/tbox/object/impl/reader/reader.c 0000664 0000000 0000000 00000005433 14671175054 0021342 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file reader.c
* @ingroup object
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "reader.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
// the object reader
static tb_oc_reader_t* g_reader[TB_OBJECT_FORMAT_MAXN] = {tb_null};
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_oc_reader_set(tb_size_t format, tb_oc_reader_t* reader)
{
// check
format &= 0x00ff;
tb_assert_and_check_return_val(reader && (format < tb_arrayn(g_reader)), tb_false);
// exit the older reader if exists
tb_oc_reader_remove(format);
// set
g_reader[format] = reader;
// ok
return tb_true;
}
tb_void_t tb_oc_reader_remove(tb_size_t format)
{
// check
format &= 0x00ff;
tb_assert_and_check_return((format < tb_arrayn(g_reader)));
// exit it
if (g_reader[format])
{
// exit hooker
if (g_reader[format]->hooker) tb_hash_map_exit(g_reader[format]->hooker);
g_reader[format]->hooker = tb_null;
// clear it
g_reader[format] = tb_null;
}
}
tb_oc_reader_t* tb_oc_reader_get(tb_size_t format)
{
// check
format &= 0x00ff;
tb_assert_and_check_return_val((format < tb_arrayn(g_reader)), tb_null);
// ok
return g_reader[format];
}
tb_object_ref_t tb_oc_reader_done(tb_stream_ref_t stream)
{
// check
tb_assert_and_check_return_val(stream, tb_null);
// probe it
tb_size_t i = 0;
tb_size_t n = tb_arrayn(g_reader);
tb_size_t m = 0;
tb_size_t f = 0;
for (i = 0; i < n && m < 100; i++)
{
// the reader
tb_oc_reader_t* reader = g_reader[i];
if (reader && reader->probe)
{
// the probe score
tb_size_t score = reader->probe(stream);
if (score > m)
{
m = score;
f = i;
}
}
}
// ok? read it
return (m && g_reader[f] && g_reader[f]->read)? g_reader[f]->read(stream) : tb_null;
}
tbox-1.7.6/src/tbox/object/impl/reader/reader.h 0000664 0000000 0000000 00000004030 14671175054 0021337 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file reader.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_IMPL_READER_H
#define TB_OBJECT_IMPL_READER_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "xml.h"
#include "bin.h"
#include "json.h"
#include "xplist.h"
#include "bplist.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! set object reader
*
* @param format the reader format
* @param reader the reader
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_reader_set(tb_size_t format, tb_oc_reader_t* reader);
/*! get object reader
*
* @param format the reader format
*
* @return the object reader
*/
tb_oc_reader_t* tb_oc_reader_get(tb_size_t format);
/*! remove object reader
*
* @param format the reader format
*/
tb_void_t tb_oc_reader_remove(tb_size_t format);
/*! done reader
*
* @param stream the stream
*
* @return the object
*/
tb_object_ref_t tb_oc_reader_done(tb_stream_ref_t stream);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/object/impl/reader/xml.c 0000664 0000000 0000000 00000050372 14671175054 0020702 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file xml.c
* @ingroup object
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "oc_reader_xml"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "xml.h"
#include "reader.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the array grow
#ifdef __tb_small__
# define TB_OC_XML_READER_ARRAY_GROW (64)
#else
# define TB_OC_XML_READER_ARRAY_GROW (256)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_object_ref_t tb_oc_xml_reader_func_null(tb_oc_xml_reader_t* reader, tb_size_t event)
{
// check
tb_assert_and_check_return_val(reader && reader->reader && event, tb_null);
// ok
return (tb_object_ref_t)tb_oc_null_init();
}
static tb_object_ref_t tb_oc_xml_reader_func_date(tb_oc_xml_reader_t* reader, tb_size_t event)
{
// check
tb_assert_and_check_return_val(reader && reader->reader && event, tb_null);
// empty?
if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY)
return tb_oc_date_init_from_time(0);
// walk
tb_object_ref_t date = tb_null;
tb_bool_t leave = tb_false;
while (!leave && (event = tb_xml_reader_next(reader->reader)))
{
switch (event)
{
case TB_XML_READER_EVENT_ELEMENT_END:
{
// name
tb_char_t const* name = tb_xml_reader_element(reader->reader);
tb_assert_and_check_break_state(name, leave, tb_true);
// is end?
if (!tb_stricmp(name, "date"))
{
// empty?
if (!date) date = tb_oc_date_init_from_time(0);
// leave it
leave = tb_true;
}
}
break;
case TB_XML_READER_EVENT_TEXT:
{
// text
tb_char_t const* text = tb_xml_reader_text(reader->reader);
tb_assert_and_check_break_state(text, leave, tb_true);
tb_trace_d("date: %s", text);
// done date: %04ld-%02ld-%02ld %02ld:%02ld:%02ld
tb_tm_t tm = {0};
tb_char_t const* p = text;
tb_char_t const* e = text + tb_strlen(text);
// init year
while (p < e && *p && !tb_isdigit(*p)) p++;
tb_assert_and_check_break_state(p < e, leave, tb_true);
tm.year = tb_atoi(p);
// init month
while (p < e && *p && tb_isdigit(*p)) p++;
while (p < e && *p && !tb_isdigit(*p)) p++;
tb_assert_and_check_break_state(p < e, leave, tb_true);
tm.month = tb_atoi(p);
// init day
while (p < e && *p && tb_isdigit(*p)) p++;
while (p < e && *p && !tb_isdigit(*p)) p++;
tb_assert_and_check_break_state(p < e, leave, tb_true);
tm.mday = tb_atoi(p);
// init hour
while (p < e && *p && tb_isdigit(*p)) p++;
while (p < e && *p && !tb_isdigit(*p)) p++;
tb_assert_and_check_break_state(p < e, leave, tb_true);
tm.hour = tb_atoi(p);
// init minute
while (p < e && *p && tb_isdigit(*p)) p++;
while (p < e && *p && !tb_isdigit(*p)) p++;
tb_assert_and_check_break_state(p < e, leave, tb_true);
tm.minute = tb_atoi(p);
// init second
while (p < e && *p && tb_isdigit(*p)) p++;
while (p < e && *p && !tb_isdigit(*p)) p++;
tb_assert_and_check_break_state(p < e, leave, tb_true);
tm.second = tb_atoi(p);
// time
tb_time_t time = tb_mktime(&tm);
tb_assert_and_check_break_state(time >= 0, leave, tb_true);
// date
date = tb_oc_date_init_from_time(time);
}
break;
default:
break;
}
}
// ok?
return date;
}
static tb_object_ref_t tb_oc_xml_reader_func_data(tb_oc_xml_reader_t* reader, tb_size_t event)
{
// check
tb_assert_and_check_return_val(reader && reader->reader && event, tb_null);
// empty?
if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY)
return tb_oc_data_init_from_data(tb_null, 0);
// walk
tb_object_ref_t data = tb_null;
tb_char_t* base64 = tb_null;
tb_bool_t leave = tb_false;
while (!leave && (event = tb_xml_reader_next(reader->reader)))
{
switch (event)
{
case TB_XML_READER_EVENT_ELEMENT_END:
{
// name
tb_char_t const* name = tb_xml_reader_element(reader->reader);
tb_assert_and_check_break_state(name, leave, tb_true);
// is end?
if (!tb_stricmp(name, "data"))
{
// empty?
if (!data) data = tb_oc_data_init_from_data(tb_null, 0);
// leave it
leave = tb_true;
}
}
break;
case TB_XML_READER_EVENT_TEXT:
{
// text
tb_char_t const* text = tb_xml_reader_text(reader->reader);
tb_assert_and_check_break_state(text, leave, tb_true);
tb_trace_d("data: %s", text);
// base64
base64 = tb_strdup(text);
tb_char_t* p = base64;
tb_char_t* q = p;
for (; *p; p++) if (!tb_isspace(*p)) *q++ = *p;
*q = '\0';
// decode base64 data
tb_char_t const* ib = base64;
tb_size_t in = tb_strlen(base64);
if (in)
{
tb_size_t on = in;
tb_byte_t* ob = tb_malloc0_bytes(on);
tb_assert_and_check_break_state(ob && on, leave, tb_true);
on = tb_base64_decode(ib, in, ob, on);
tb_trace_d("base64: %u => %u", in, on);
// init data
data = tb_oc_data_init_from_data(ob, on); tb_free(ob);
}
else data = tb_oc_data_init_from_data(tb_null, 0);
tb_assert_and_check_break_state(data, leave, tb_true);
}
break;
default:
break;
}
}
// exit base64
if (base64) tb_free(base64);
base64 = tb_null;
// ok?
return data;
}
static tb_object_ref_t tb_oc_xml_reader_func_array(tb_oc_xml_reader_t* reader, tb_size_t event)
{
// check
tb_assert_and_check_return_val(reader && reader->reader && event, tb_null);
// empty?
if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY)
return tb_oc_array_init(TB_OC_XML_READER_ARRAY_GROW, tb_false);
// init array
tb_object_ref_t array = tb_oc_array_init(TB_OC_XML_READER_ARRAY_GROW, tb_false);
tb_assert_and_check_return_val(array, tb_null);
// done
tb_long_t ok = 0;
while (!ok && (event = tb_xml_reader_next(reader->reader)))
{
switch (event)
{
case TB_XML_READER_EVENT_ELEMENT_BEG:
case TB_XML_READER_EVENT_ELEMENT_EMPTY:
{
// name
tb_char_t const* name = tb_xml_reader_element(reader->reader);
tb_assert_and_check_break_state(name, ok, -1);
tb_trace_d("item: %s", name);
// func
tb_oc_xml_reader_func_t func = tb_oc_xml_reader_func(name);
tb_assert_and_check_break_state(func, ok, -1);
// read
tb_object_ref_t object = func(reader, event);
// append object
if (object) tb_oc_array_append(array, object);
}
break;
case TB_XML_READER_EVENT_ELEMENT_END:
{
// name
tb_char_t const* name = tb_xml_reader_element(reader->reader);
tb_assert_and_check_break_state(name, ok, -1);
// is end?
if (!tb_stricmp(name, "array")) ok = 1;
}
break;
default:
break;
}
}
// failed?
if (ok < 0)
{
// exit it
if (array) tb_object_exit(array);
array = tb_null;
}
// ok?
return array;
}
static tb_object_ref_t tb_oc_xml_reader_func_string(tb_oc_xml_reader_t* reader, tb_size_t event)
{
// check
tb_assert_and_check_return_val(reader && reader->reader && event, tb_null);
// empty?
if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY)
return tb_oc_string_init_from_cstr(tb_null);
// done
tb_bool_t leave = tb_false;
tb_object_ref_t string = tb_null;
while (!leave && (event = tb_xml_reader_next(reader->reader)))
{
switch (event)
{
case TB_XML_READER_EVENT_ELEMENT_END:
{
// name
tb_char_t const* name = tb_xml_reader_element(reader->reader);
tb_assert_and_check_break_state(name, leave, tb_true);
// is end?
if (!tb_stricmp(name, "string"))
{
// empty?
if (!string) string = tb_oc_string_init_from_cstr(tb_null);
// leave it
leave = tb_true;
}
}
break;
case TB_XML_READER_EVENT_TEXT:
{
// text
tb_char_t const* text = tb_xml_reader_text(reader->reader);
tb_assert_and_check_break_state(text, leave, tb_true);
tb_trace_d("string: %s", text);
// string
string = tb_oc_string_init_from_cstr(text);
tb_assert_and_check_break_state(string, leave, tb_true);
}
break;
default:
break;
}
}
// ok?
return string;
}
static tb_object_ref_t tb_oc_xml_reader_func_number(tb_oc_xml_reader_t* reader, tb_size_t event)
{
// check
tb_assert_and_check_return_val(reader && reader->reader && event, tb_null);
// empty?
if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY)
return tb_oc_number_init_from_uint32(0);
// done
tb_bool_t leave = tb_false;
tb_object_ref_t number = tb_null;
while (!leave && (event = tb_xml_reader_next(reader->reader)))
{
switch (event)
{
case TB_XML_READER_EVENT_ELEMENT_END:
{
// name
tb_char_t const* name = tb_xml_reader_element(reader->reader);
tb_assert_and_check_break_state(name, leave, tb_true);
// is end?
if (!tb_stricmp(name, "number")) leave = tb_true;
}
break;
case TB_XML_READER_EVENT_TEXT:
{
// text
tb_char_t const* text = tb_xml_reader_text(reader->reader);
tb_assert_and_check_break_state(text, leave, tb_true);
tb_trace_d("number: %s", text);
// has sign? is float?
tb_size_t s = 0;
tb_size_t f = 0;
tb_char_t const* p = text;
for (; *p; p++)
{
if (!s && *p == '-') s = 1;
if (!f && *p == '.') f = 1;
if (s && f) break;
}
// number
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
if (f) number = tb_oc_number_init_from_double(tb_atof(text));
#else
if (f) tb_trace_noimpl();
#endif
else number = s? tb_oc_number_init_from_sint64(tb_stoi64(text)) : tb_oc_number_init_from_uint64(tb_stou64(text));
tb_assert_and_check_break_state(number, leave, tb_true);
}
break;
default:
break;
}
}
// ok?
return number;
}
static tb_object_ref_t tb_oc_xml_reader_func_boolean(tb_oc_xml_reader_t* reader, tb_size_t event)
{
// check
tb_assert_and_check_return_val(reader && reader->reader && event, tb_null);
// name
tb_char_t const* name = tb_xml_reader_element(reader->reader);
tb_assert_and_check_return_val(name, tb_null);
tb_trace_d("boolean: %s", name);
// the boolean value
tb_bool_t val = tb_false;
if (!tb_stricmp(name, "true")) val = tb_true;
else if (!tb_stricmp(name, "false")) val = tb_false;
else return tb_null;
// ok?
return (tb_object_ref_t)tb_oc_boolean_init(val);
}
static tb_object_ref_t tb_oc_xml_reader_func_dictionary(tb_oc_xml_reader_t* reader, tb_size_t event)
{
// check
tb_assert_and_check_return_val(reader && reader->reader && event, tb_null);
// empty?
if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY)
return tb_oc_dictionary_init(TB_OC_DICTIONARY_SIZE_MICRO, tb_false);
// init key name
tb_static_string_t kname;
tb_char_t kdata[8192];
if (!tb_static_string_init(&kname, kdata, 8192)) return tb_null;
// init dictionary
tb_object_ref_t dictionary = tb_oc_dictionary_init(0, tb_false);
tb_assert_and_check_return_val(dictionary, tb_null);
// walk
tb_long_t ok = 0;
tb_bool_t key = tb_false;
while (!ok && (event = tb_xml_reader_next(reader->reader)))
{
switch (event)
{
case TB_XML_READER_EVENT_ELEMENT_BEG:
case TB_XML_READER_EVENT_ELEMENT_EMPTY:
{
// name
tb_char_t const* name = tb_xml_reader_element(reader->reader);
tb_assert_and_check_break_state(name, ok, -1);
tb_trace_d("%s", name);
// is key
if (!tb_stricmp(name, "key")) key = tb_true;
else if (!key)
{
// func
tb_oc_xml_reader_func_t func = tb_oc_xml_reader_func(name);
tb_assert_and_check_break_state(func, ok, -1);
// read
tb_object_ref_t object = func(reader, event);
tb_trace_d("%s => %p", tb_static_string_cstr(&kname), object);
tb_assert_and_check_break_state(object, ok, -1);
// set key & value
if (tb_static_string_size(&kname) && dictionary)
tb_oc_dictionary_insert(dictionary, tb_static_string_cstr(&kname), object);
// clear key name
tb_static_string_clear(&kname);
}
}
break;
case TB_XML_READER_EVENT_ELEMENT_END:
{
// name
tb_char_t const* name = tb_xml_reader_element(reader->reader);
tb_assert_and_check_break_state(name, ok, -1);
// is end?
if (!tb_stricmp(name, "dict")) ok = 1;
else if (!tb_stricmp(name, "key")) key = tb_false;
}
break;
case TB_XML_READER_EVENT_TEXT:
{
if (key)
{
// text
tb_char_t const* text = tb_xml_reader_text(reader->reader);
tb_assert_and_check_break_state(text, ok, -1);
// writ key name
tb_static_string_cstrcpy(&kname, text);
}
}
break;
default:
break;
}
}
// failed?
if (ok < 0)
{
// exit it
if (dictionary) tb_object_exit(dictionary);
dictionary = tb_null;
}
// exit key name
tb_static_string_exit(&kname);
// ok?
return dictionary;
}
static tb_object_ref_t tb_oc_xml_reader_done(tb_stream_ref_t stream)
{
// init reader
tb_oc_xml_reader_t reader = {0};
reader.reader = tb_xml_reader_init();
tb_assert_and_check_return_val(reader.reader, tb_null);
// open reader
tb_object_ref_t object = tb_null;
if (tb_xml_reader_open(reader.reader, stream, tb_false))
{
// done
tb_bool_t leave = tb_false;
tb_size_t event = TB_XML_READER_EVENT_NONE;
while (!leave && !object && (event = tb_xml_reader_next(reader.reader)))
{
switch (event)
{
case TB_XML_READER_EVENT_ELEMENT_EMPTY:
case TB_XML_READER_EVENT_ELEMENT_BEG:
{
// name
tb_char_t const* name = tb_xml_reader_element(reader.reader);
tb_assert_and_check_break_state(name, leave, tb_true);
// func
tb_oc_xml_reader_func_t func = tb_oc_xml_reader_func(name);
tb_assert_and_check_break_state(func, leave, tb_true);
// read
object = func(&reader, event);
}
break;
default:
break;
}
}
}
// exit reader
tb_xml_reader_exit(reader.reader);
// ok?
return object;
}
static tb_size_t tb_oc_xml_reader_probe(tb_stream_ref_t stream)
{
// check
tb_assert_and_check_return_val(stream, 0);
// need it
tb_byte_t* p = tb_null;
if (!tb_stream_need(stream, &p, 5)) return 0;
tb_assert_and_check_return_val(p, 0);
// ok?
return !tb_strnicmp((tb_char_t const*)p, "hooker, tb_false);
// hook it
tb_hash_map_insert(reader->hooker, type, func);
// ok
return tb_true;
}
tb_oc_xml_reader_func_t tb_oc_xml_reader_func(tb_char_t const* type)
{
// check
tb_assert_and_check_return_val(type, tb_null);
// the reader
tb_oc_reader_t* reader = tb_oc_reader_get(TB_OBJECT_FORMAT_XML);
tb_assert_and_check_return_val(reader && reader->hooker, tb_null);
// the func
return (tb_oc_xml_reader_func_t)tb_hash_map_get(reader->hooker, type);
}
tbox-1.7.6/src/tbox/object/impl/reader/xml.h 0000664 0000000 0000000 00000004452 14671175054 0020705 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file xml.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_IMPL_READER_XML_H
#define TB_OBJECT_IMPL_READER_XML_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the xml reader type
typedef struct __tb_oc_xml_reader_t
{
/// the xml reader
tb_xml_reader_ref_t reader;
}tb_oc_xml_reader_t;
/// the xml reader func type
typedef tb_object_ref_t (*tb_oc_xml_reader_func_t)(tb_oc_xml_reader_t* reader, tb_size_t event);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the xml object reader
*
* @return the xml object reader
*/
tb_oc_reader_t* tb_oc_xml_reader(tb_noarg_t);
/*! hook the xml reader
*
* @param type the object type name
* @param func the reader func
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_xml_reader_hook(tb_char_t const* type, tb_oc_xml_reader_func_t func);
/*! the xml reader func
*
* @param type the object type name
*
* @return the object reader func
*/
tb_oc_xml_reader_func_t tb_oc_xml_reader_func(tb_char_t const* type);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/object/impl/reader/xplist.c 0000664 0000000 0000000 00000051103 14671175054 0021416 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file xplist.c
* @ingroup object
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "oc_reader_xplist"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "xplist.h"
#include "reader.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the array grow
#ifdef __tb_small__
# define TB_OC_XPLIST_READER_ARRAY_GROW (64)
#else
# define TB_OC_XPLIST_READER_ARRAY_GROW (256)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_object_ref_t tb_oc_xplist_reader_func_date(tb_oc_xplist_reader_t* reader, tb_size_t event)
{
// check
tb_assert_and_check_return_val(reader && reader->reader && event, tb_null);
// empty?
if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY)
return tb_oc_date_init_from_time(0);
// done
tb_bool_t leave = tb_false;
tb_object_ref_t date = tb_null;
while (!leave && (event = tb_xml_reader_next(reader->reader)))
{
switch (event)
{
case TB_XML_READER_EVENT_ELEMENT_END:
{
// name
tb_char_t const* name = tb_xml_reader_element(reader->reader);
tb_assert_and_check_break_state(name, leave, tb_true);
// is end?
if (!tb_stricmp(name, "date"))
{
// empty?
if (!date) date = tb_oc_date_init_from_time(0);
// leave it
leave = tb_true;
}
}
break;
case TB_XML_READER_EVENT_TEXT:
{
// text
tb_char_t const* text = tb_xml_reader_text(reader->reader);
tb_assert_and_check_break_state(text, leave, tb_true);
tb_trace_d("date: %s", text);
// done date: %04ld-%02ld-%02ld %02ld:%02ld:%02ld
tb_tm_t tm = {0};
tb_char_t const* p = text;
tb_char_t const* e = text + tb_strlen(text);
// init year
while (p < e && *p && !tb_isdigit(*p)) p++;
tb_assert_and_check_break_state(p < e, leave, tb_true);
tm.year = tb_atoi(p);
// init month
while (p < e && *p && tb_isdigit(*p)) p++;
while (p < e && *p && !tb_isdigit(*p)) p++;
tb_assert_and_check_break_state(p < e, leave, tb_true);
tm.month = tb_atoi(p);
// init day
while (p < e && *p && tb_isdigit(*p)) p++;
while (p < e && *p && !tb_isdigit(*p)) p++;
tb_assert_and_check_break_state(p < e, leave, tb_true);
tm.mday = tb_atoi(p);
// init hour
while (p < e && *p && tb_isdigit(*p)) p++;
while (p < e && *p && !tb_isdigit(*p)) p++;
tb_assert_and_check_break_state(p < e, leave, tb_true);
tm.hour = tb_atoi(p);
// init minute
while (p < e && *p && tb_isdigit(*p)) p++;
while (p < e && *p && !tb_isdigit(*p)) p++;
tb_assert_and_check_break_state(p < e, leave, tb_true);
tm.minute = tb_atoi(p);
// init second
while (p < e && *p && tb_isdigit(*p)) p++;
while (p < e && *p && !tb_isdigit(*p)) p++;
tb_assert_and_check_break_state(p < e, leave, tb_true);
tm.second = tb_atoi(p);
// time
tb_time_t time = tb_mktime(&tm);
tb_assert_and_check_break_state(time >= 0, leave, tb_true);
// date
date = tb_oc_date_init_from_time(time);
}
break;
default:
break;
}
}
// ok?
return date;
}
static tb_object_ref_t tb_oc_xplist_reader_func_data(tb_oc_xplist_reader_t* reader, tb_size_t event)
{
// check
tb_assert_and_check_return_val(reader && reader->reader && event, tb_null);
// empty?
if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY)
return tb_oc_data_init_from_data(tb_null, 0);
// done
tb_bool_t leave = tb_false;
tb_char_t* base64 = tb_null;
tb_object_ref_t data = tb_null;
while (!leave && (event = tb_xml_reader_next(reader->reader)))
{
switch (event)
{
case TB_XML_READER_EVENT_ELEMENT_END:
{
// name
tb_char_t const* name = tb_xml_reader_element(reader->reader);
tb_assert_and_check_break_state(name, leave, tb_true);
// is end?
if (!tb_stricmp(name, "data"))
{
// empty?
if (!data) data = tb_oc_data_init_from_data(tb_null, 0);
// leave it
leave = tb_true;
}
}
break;
case TB_XML_READER_EVENT_TEXT:
{
// text
tb_char_t const* text = tb_xml_reader_text(reader->reader);
tb_assert_and_check_break_state(text, leave, tb_true);
tb_trace_d("data: %s", text);
// base64
base64 = tb_strdup(text);
tb_char_t* p = base64;
tb_char_t* q = p;
for (; *p; p++) if (!tb_isspace(*p)) *q++ = *p;
*q = '\0';
// decode base64 data
tb_char_t const* ib = base64;
tb_size_t in = tb_strlen(base64);
if (in)
{
tb_size_t on = in;
tb_byte_t* ob = tb_malloc0_bytes(on);
tb_assert_and_check_break_state(ob && on, leave, tb_true);
on = tb_base64_decode(ib, in, ob, on);
tb_trace_d("base64: %u => %u", in, on);
// init data
data = tb_oc_data_init_from_data(ob, on); tb_free(ob);
}
else data = tb_oc_data_init_from_data(tb_null, 0);
tb_assert_and_check_break_state(data, leave, tb_true);
}
break;
default:
break;
}
}
// free
if (base64) tb_free(base64);
// ok?
return data;
}
static tb_object_ref_t tb_oc_xplist_reader_func_array(tb_oc_xplist_reader_t* reader, tb_size_t event)
{
// check
tb_assert_and_check_return_val(reader && reader->reader && event, tb_null);
// empty?
if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY)
return tb_oc_array_init(TB_OC_XPLIST_READER_ARRAY_GROW, tb_false);
// init array
tb_object_ref_t array = tb_oc_array_init(TB_OC_XPLIST_READER_ARRAY_GROW, tb_false);
tb_assert_and_check_return_val(array, tb_null);
// done
tb_long_t ok = 0;
while (!ok && (event = tb_xml_reader_next(reader->reader)))
{
switch (event)
{
case TB_XML_READER_EVENT_ELEMENT_BEG:
case TB_XML_READER_EVENT_ELEMENT_EMPTY:
{
// name
tb_char_t const* name = tb_xml_reader_element(reader->reader);
tb_assert_and_check_break_state(name, ok, -1);
tb_trace_d("item: %s", name);
// func
tb_oc_xplist_reader_func_t func = tb_oc_xplist_reader_func(name);
tb_assert_and_check_break_state(func, ok, -1);
// read
tb_object_ref_t object = func(reader, event);
// append object
if (object) tb_oc_array_append(array, object);
}
break;
case TB_XML_READER_EVENT_ELEMENT_END:
{
// name
tb_char_t const* name = tb_xml_reader_element(reader->reader);
tb_assert_and_check_break_state(name, ok, -1);
// is end?
if (!tb_stricmp(name, "array")) ok = 1;
}
break;
default:
break;
}
}
// failed?
if (ok < 0)
{
// exit it
if (array) tb_object_exit(array);
array = tb_null;
}
// ok?
return array;
}
static tb_object_ref_t tb_oc_xplist_reader_func_string(tb_oc_xplist_reader_t* reader, tb_size_t event)
{
// check
tb_assert_and_check_return_val(reader && reader->reader && event, tb_null);
// empty?
if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY)
return tb_oc_string_init_from_cstr(tb_null);
// done
tb_bool_t leave = tb_false;
tb_object_ref_t string = tb_null;
while (!leave && (event = tb_xml_reader_next(reader->reader)))
{
switch (event)
{
case TB_XML_READER_EVENT_ELEMENT_END:
{
// name
tb_char_t const* name = tb_xml_reader_element(reader->reader);
tb_assert_and_check_break_state(name, leave, tb_true);
// is end?
if (!tb_stricmp(name, "string"))
{
// empty?
if (!string) string = tb_oc_string_init_from_cstr(tb_null);
// leave it
leave = tb_true;
}
}
break;
case TB_XML_READER_EVENT_TEXT:
{
// text
tb_char_t const* text = tb_xml_reader_text(reader->reader);
tb_assert_and_check_break_state(text, leave, tb_true);
tb_trace_d("string: %s", text);
// string
string = tb_oc_string_init_from_cstr(text);
tb_assert_and_check_break_state(string, leave, tb_true);
}
break;
default:
break;
}
}
// ok?
return string;
}
static tb_object_ref_t tb_oc_xplist_reader_func_number(tb_oc_xplist_reader_t* reader, tb_size_t event)
{
// check
tb_assert_and_check_return_val(reader && reader->reader && event, tb_null);
// empty?
if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY)
return tb_oc_number_init_from_uint32(0);
// done
tb_bool_t leave = tb_false;
tb_object_ref_t number = tb_null;
while (!leave && (event = tb_xml_reader_next(reader->reader)))
{
switch (event)
{
case TB_XML_READER_EVENT_ELEMENT_END:
{
// name
tb_char_t const* name = tb_xml_reader_element(reader->reader);
tb_assert_and_check_break_state(name, leave, tb_true);
// is end?
if (!tb_stricmp(name, "integer") || !tb_stricmp(name, "real")) leave = tb_true;
}
break;
case TB_XML_READER_EVENT_TEXT:
{
// text
tb_char_t const* text = tb_xml_reader_text(reader->reader);
tb_assert_and_check_break_state(text, leave, tb_true);
tb_trace_d("number: %s", text);
// has sign? is float?
tb_size_t s = 0;
tb_size_t f = 0;
tb_char_t const* p = text;
for (; *p; p++)
{
if (!s && *p == '-') s = 1;
if (!f && *p == '.') f = 1;
if (s && f) break;
}
// number
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
if (f) number = tb_oc_number_init_from_double(tb_atof(text));
#else
if (f) tb_trace_noimpl();
#endif
else number = s? tb_oc_number_init_from_sint64(tb_stoi64(text)) : tb_oc_number_init_from_uint64(tb_stou64(text));
tb_assert_and_check_break_state(number, leave, tb_true);
}
break;
default:
break;
}
}
// ok?
return number;
}
static tb_object_ref_t tb_oc_xplist_reader_func_boolean(tb_oc_xplist_reader_t* reader, tb_size_t event)
{
// check
tb_assert_and_check_return_val(reader && reader->reader && event, tb_null);
// name
tb_char_t const* name = tb_xml_reader_element(reader->reader);
tb_assert_and_check_return_val(name, tb_null);
tb_trace_d("boolean: %s", name);
// the boolean value
tb_bool_t val = tb_false;
if (!tb_stricmp(name, "true")) val = tb_true;
else if (!tb_stricmp(name, "false")) val = tb_false;
else return tb_null;
// ok?
return (tb_object_ref_t)tb_oc_boolean_init(val);
}
static tb_object_ref_t tb_oc_xplist_reader_func_dictionary(tb_oc_xplist_reader_t* reader, tb_size_t event)
{
// check
tb_assert_and_check_return_val(reader && reader->reader && event, tb_null);
// empty?
if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY)
return tb_oc_dictionary_init(TB_OC_DICTIONARY_SIZE_MICRO, tb_false);
// init key name
tb_static_string_t kname;
tb_char_t kdata[8192];
if (!tb_static_string_init(&kname, kdata, 8192)) return tb_null;
// init dictionary
tb_object_ref_t dictionary = tb_oc_dictionary_init(0, tb_false);
tb_assert_and_check_return_val(dictionary, tb_null);
// done
tb_long_t ok = 0;
tb_bool_t key = tb_false;
while (!ok && (event = tb_xml_reader_next(reader->reader)))
{
switch (event)
{
case TB_XML_READER_EVENT_ELEMENT_BEG:
case TB_XML_READER_EVENT_ELEMENT_EMPTY:
{
// name
tb_char_t const* name = tb_xml_reader_element(reader->reader);
tb_assert_and_check_break_state(name, ok, -1);
tb_trace_d("%s", name);
// is key
if (!tb_stricmp(name, "key")) key = tb_true;
else if (!key)
{
// func
tb_oc_xplist_reader_func_t func = tb_oc_xplist_reader_func(name);
tb_assert_and_check_break_state(func, ok, -1);
// read
tb_object_ref_t object = func(reader, event);
tb_trace_d("%s => %p", tb_static_string_cstr(&kname), object);
tb_assert_and_check_break_state(object, ok, -1);
// set key & value
if (tb_static_string_size(&kname) && dictionary)
tb_oc_dictionary_insert(dictionary, tb_static_string_cstr(&kname), object);
// clear key name
tb_static_string_clear(&kname);
}
}
break;
case TB_XML_READER_EVENT_ELEMENT_END:
{
// name
tb_char_t const* name = tb_xml_reader_element(reader->reader);
tb_assert_and_check_break_state(name, ok, -1);
// is end?
if (!tb_stricmp(name, "dict")) ok = 1;
else if (!tb_stricmp(name, "key")) key = tb_false;
}
break;
case TB_XML_READER_EVENT_TEXT:
{
if (key)
{
// text
tb_char_t const* text = tb_xml_reader_text(reader->reader);
tb_assert_and_check_break_state(text, ok, -1);
// writ key name
tb_static_string_cstrcpy(&kname, text);
}
}
break;
default:
break;
}
}
// failed
if (ok < 0)
{
// exit it
if (dictionary) tb_object_exit(dictionary);
dictionary = tb_null;
}
// exit key name
tb_static_string_exit(&kname);
// ok?
return dictionary;
}
static tb_object_ref_t tb_oc_xplist_reader_done(tb_stream_ref_t stream)
{
// init reader
tb_oc_xplist_reader_t reader = {0};
reader.reader = tb_xml_reader_init();
tb_assert_and_check_return_val(reader.reader, tb_null);
// open reader
tb_object_ref_t object = tb_null;
if (tb_xml_reader_open(reader.reader, stream, tb_false))
{
// done
tb_bool_t leave = tb_false;
tb_size_t event = TB_XML_READER_EVENT_NONE;
while (!leave && !object && (event = tb_xml_reader_next(reader.reader)))
{
switch (event)
{
case TB_XML_READER_EVENT_ELEMENT_EMPTY:
case TB_XML_READER_EVENT_ELEMENT_BEG:
{
// name
tb_char_t const* name = tb_xml_reader_element(reader.reader);
tb_assert_and_check_break_state(name, leave, tb_true);
// ?
if (tb_stricmp(name, "plist"))
{
// func
tb_oc_xplist_reader_func_t func = tb_oc_xplist_reader_func(name);
tb_assert_and_check_break_state(func, leave, tb_true);
// read
object = func(&reader, event);
}
}
break;
default:
break;
}
}
}
// exit reader
tb_xml_reader_exit(reader.reader);
// ok?
return object;
}
static tb_size_t tb_oc_xplist_reader_probe(tb_stream_ref_t stream)
{
// check
tb_assert_and_check_return_val(stream, 0);
// need it
tb_byte_t* p = tb_null;
if (!tb_stream_need(stream, &p, 5)) return 0;
tb_assert_and_check_return_val(p, 0);
// is xml data?
if (!tb_strnicmp((tb_char_t const*)p, "hooker, tb_false);
// hook it
tb_hash_map_insert(reader->hooker, type, func);
// ok
return tb_true;
}
tb_oc_xplist_reader_func_t tb_oc_xplist_reader_func(tb_char_t const* type)
{
// check
tb_assert_and_check_return_val(type, tb_null);
// the reader
tb_oc_reader_t* reader = tb_oc_reader_get(TB_OBJECT_FORMAT_XPLIST);
tb_assert_and_check_return_val(reader && reader->hooker, tb_null);
// the func
return (tb_oc_xplist_reader_func_t)tb_hash_map_get(reader->hooker, type);
}
tbox-1.7.6/src/tbox/object/impl/reader/xplist.h 0000664 0000000 0000000 00000004532 14671175054 0021427 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file xplist.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_IMPL_READER_XPLIST_H
#define TB_OBJECT_IMPL_READER_XPLIST_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the xplist reader type
typedef struct __tb_oc_xplist_reader_t
{
// the xplist reader
tb_xml_reader_ref_t reader;
}tb_oc_xplist_reader_t;
// the xplist reader func type
typedef tb_object_ref_t (*tb_oc_xplist_reader_func_t)(tb_oc_xplist_reader_t* reader, tb_size_t event);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* the xplist object reader
*
* @return the xplist object reader
*/
tb_oc_reader_t* tb_oc_xplist_reader(tb_noarg_t);
/* hook the xplist reader
*
* @param type the object type name
* @param func the reader func
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_xplist_reader_hook(tb_char_t const* type, tb_oc_xplist_reader_func_t func);
/* the xplist reader func
*
* @param type the object type name
*
* @return the object reader func
*/
tb_oc_xplist_reader_func_t tb_oc_xplist_reader_func(tb_char_t const* type);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/object/impl/writer/ 0000775 0000000 0000000 00000000000 14671175054 0020001 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/object/impl/writer/bin.c 0000664 0000000 0000000 00000035217 14671175054 0020725 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file bin.c
* @ingroup object
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "oc_writer_bin"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "bin.h"
#include "writer.h"
#include "../../../algorithm/algorithm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_bool_t tb_oc_bin_writer_func_null(tb_oc_bin_writer_t* writer, tb_object_ref_t object)
{
// check
tb_assert_and_check_return_val(object && writer && writer->stream, tb_false);
// write type & null
return tb_oc_writer_bin_type_size(writer->stream, object->type, 0);
}
static tb_bool_t tb_oc_bin_writer_func_date(tb_oc_bin_writer_t* writer, tb_object_ref_t object)
{
// check
tb_assert_and_check_return_val(object && writer && writer->stream, tb_false);
// write type & time
return tb_oc_writer_bin_type_size(writer->stream, object->type, (tb_uint64_t)tb_oc_date_time(object));
}
static tb_bool_t tb_oc_bin_writer_func_data(tb_oc_bin_writer_t* writer, tb_object_ref_t object)
{
// check
tb_assert_and_check_return_val(object && writer && writer->stream, tb_false);
// the data & size
tb_byte_t const* data = (tb_byte_t const*)tb_oc_data_getp(object);
tb_size_t size = tb_oc_data_size(object);
// write type & size
if (!tb_oc_writer_bin_type_size(writer->stream, object->type, size)) return tb_false;
// empty?
tb_check_return_val(size, tb_true);
// check
tb_assert_and_check_return_val(data, tb_false);
// make the encoder data
if (!writer->data)
{
writer->maxn = tb_max(size, 8192);
writer->data = tb_malloc0_bytes(writer->maxn);
}
else if (writer->maxn < size)
{
writer->maxn = size;
writer->data = (tb_byte_t*)tb_ralloc(writer->data, writer->maxn);
}
tb_assert_and_check_return_val(writer->data && size <= writer->maxn, tb_false);
// copy data to encoder
tb_memcpy(writer->data, data, size);
// encode data
tb_byte_t const* pb = data;
tb_byte_t const* pe = data + size;
tb_byte_t* qb = writer->data;
tb_byte_t* qe = writer->data + writer->maxn;
tb_byte_t xb = (tb_byte_t)(((size >> 8) & 0xff) | (size & 0xff));
for (; pb < pe && qb < qe; pb++, qb++, xb++) *qb = *pb ^ xb;
// write it
return tb_stream_bwrit(writer->stream, writer->data, size);
}
static tb_bool_t tb_oc_bin_writer_func_array(tb_oc_bin_writer_t* writer, tb_object_ref_t object)
{
// check
tb_assert_and_check_return_val(object && writer && writer->stream && writer->ohash, tb_false);
// write type & size
if (!tb_oc_writer_bin_type_size(writer->stream, object->type, tb_oc_array_size(object))) return tb_false;
// walk
tb_for_all (tb_object_ref_t, item, tb_oc_array_itor(object))
{
if (item)
{
// exists?
tb_size_t index = (tb_size_t)tb_hash_map_get(writer->ohash, item);
if (index)
{
// write index
if (!tb_oc_writer_bin_type_size(writer->stream, 0, (tb_uint64_t)(index - 1))) return tb_false;
}
else
{
// the func
tb_oc_bin_writer_func_t func = tb_oc_bin_writer_func(item->type);
tb_assert_and_check_continue(func);
// write it
if (!func(writer, item)) return tb_false;
// save index
tb_hash_map_insert(writer->ohash, item, (tb_cpointer_t)(++writer->index));
}
}
}
// ok
return tb_true;
}
static tb_bool_t tb_oc_bin_writer_func_string(tb_oc_bin_writer_t* writer, tb_object_ref_t object)
{
// check
tb_assert_and_check_return_val(object && writer && writer->stream, tb_false);
// the data & size
tb_char_t const* data = tb_oc_string_cstr(object);
tb_size_t size = tb_oc_string_size(object);
// write type & size
if (!tb_oc_writer_bin_type_size(writer->stream, object->type, size)) return tb_false;
// empty?
tb_check_return_val(size, tb_true);
// check
tb_assert_and_check_return_val(data, tb_false);
// make the encoder data
if (!writer->data)
{
writer->maxn = tb_max(size, 8192);
writer->data = tb_malloc0_bytes(writer->maxn);
}
else if (writer->maxn < size)
{
writer->maxn = size;
writer->data = (tb_byte_t*)tb_ralloc(writer->data, writer->maxn);
}
tb_assert_and_check_return_val(writer->data && size <= writer->maxn, tb_false);
// copy data to encoder
tb_memcpy(writer->data, data, size);
// encode data
tb_byte_t const* pb = (tb_byte_t const*)data;
tb_byte_t const* pe = (tb_byte_t const*)data + size;
tb_byte_t* qb = writer->data;
tb_byte_t* qe = writer->data + writer->maxn;
tb_byte_t xb = (tb_byte_t)(((size >> 8) & 0xff) | (size & 0xff));
for (; pb < pe && qb < qe && *pb; pb++, qb++, xb++) *qb = *pb ^ xb;
// write it
return tb_stream_bwrit(writer->stream, writer->data, size);
}
static tb_bool_t tb_oc_bin_writer_func_number(tb_oc_bin_writer_t* writer, tb_object_ref_t object)
{
// check
tb_assert_and_check_return_val(object && writer && writer->stream, tb_false);
// write type
if (!tb_oc_writer_bin_type_size(writer->stream, object->type, (tb_uint64_t)tb_oc_number_type(object))) return tb_false;
// write number
switch (tb_oc_number_type(object))
{
case TB_OC_NUMBER_TYPE_UINT64:
if (!tb_stream_bwrit_u64_be(writer->stream, tb_oc_number_uint64(object))) return tb_false;
break;
case TB_OC_NUMBER_TYPE_SINT64:
if (!tb_stream_bwrit_s64_be(writer->stream, tb_oc_number_sint64(object))) return tb_false;
break;
case TB_OC_NUMBER_TYPE_UINT32:
if (!tb_stream_bwrit_u32_be(writer->stream, tb_oc_number_uint32(object))) return tb_false;
break;
case TB_OC_NUMBER_TYPE_SINT32:
if (!tb_stream_bwrit_s32_be(writer->stream, tb_oc_number_sint32(object))) return tb_false;
break;
case TB_OC_NUMBER_TYPE_UINT16:
if (!tb_stream_bwrit_u16_be(writer->stream, tb_oc_number_uint16(object))) return tb_false;
break;
case TB_OC_NUMBER_TYPE_SINT16:
if (!tb_stream_bwrit_s16_be(writer->stream, tb_oc_number_sint16(object))) return tb_false;
break;
case TB_OC_NUMBER_TYPE_UINT8:
if (!tb_stream_bwrit_u8(writer->stream, tb_oc_number_uint8(object))) return tb_false;
break;
case TB_OC_NUMBER_TYPE_SINT8:
if (!tb_stream_bwrit_s8(writer->stream, tb_oc_number_sint8(object))) return tb_false;
break;
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
case TB_OC_NUMBER_TYPE_FLOAT:
{
tb_byte_t data[4];
tb_bits_set_float_be(data, tb_oc_number_float(object));
if (!tb_stream_bwrit(writer->stream, data, 4)) return tb_false;
}
break;
case TB_OC_NUMBER_TYPE_DOUBLE:
{
tb_byte_t data[8];
tb_bits_set_double_bbe(data, tb_oc_number_double(object));
if (!tb_stream_bwrit(writer->stream, data, 8)) return tb_false;
}
break;
#endif
default:
tb_assert_and_check_return_val(0, tb_false);
break;
}
// ok
return tb_true;
}
static tb_bool_t tb_oc_bin_writer_func_boolean(tb_oc_bin_writer_t* writer, tb_object_ref_t object)
{
// check
tb_assert_and_check_return_val(object && writer && writer->stream, tb_false);
// write type & bool
return tb_oc_writer_bin_type_size(writer->stream, object->type, tb_oc_boolean_bool(object));
}
static tb_bool_t tb_oc_bin_writer_func_dictionary(tb_oc_bin_writer_t* writer, tb_object_ref_t object)
{
// check
tb_assert_and_check_return_val(object && writer && writer->stream && writer->ohash, tb_false);
// write type & size
if (!tb_oc_writer_bin_type_size(writer->stream, object->type, tb_oc_dictionary_size(object))) return tb_false;
// walk
tb_for_all (tb_oc_dictionary_item_t*, item, tb_oc_dictionary_itor(object))
{
if (item)
{
tb_char_t const* key = item->key;
tb_object_ref_t val = item->val;
if (key && val)
{
// write key
{
// exists?
tb_size_t index = (tb_size_t)tb_hash_map_get(writer->shash, key);
if (index)
{
// write index
if (!tb_oc_writer_bin_type_size(writer->stream, 0, (tb_uint64_t)(index - 1))) return tb_false;
}
else
{
// the func
tb_oc_bin_writer_func_t func = tb_oc_bin_writer_func(TB_OBJECT_TYPE_STRING);
tb_assert_and_check_return_val(func, tb_false);
// make the key object
tb_object_ref_t okey = tb_oc_string_init_from_cstr(key);
tb_assert_and_check_return_val(okey, tb_false);
// write it
if (!func(writer, okey)) return tb_false;
// exit it
tb_object_exit(okey);
// save index
tb_hash_map_insert(writer->shash, key, (tb_cpointer_t)(++writer->index));
}
}
// write value
{
// exists?
tb_size_t index = (tb_size_t)tb_hash_map_get(writer->ohash, val);
if (index)
{
// write index
if (!tb_oc_writer_bin_type_size(writer->stream, 0, (tb_uint64_t)(index - 1))) return tb_false;
}
else
{
// the func
tb_oc_bin_writer_func_t func = tb_oc_bin_writer_func(val->type);
tb_assert_and_check_return_val(func, tb_false);
// write it
if (!func(writer, val)) return tb_false;
// save index
tb_hash_map_insert(writer->ohash, val, (tb_cpointer_t)(++writer->index));
}
}
}
}
}
// ok
return tb_true;
}
static tb_long_t tb_oc_bin_writer_done(tb_stream_ref_t stream, tb_object_ref_t object, tb_bool_t deflate)
{
// check
tb_assert_and_check_return_val(object && stream, -1);
// the func
tb_oc_bin_writer_func_t func = tb_oc_bin_writer_func(object->type);
tb_assert_and_check_return_val(func, -1);
// the begin offset
tb_hize_t bof = tb_stream_offset(stream);
// write bin header
if (!tb_stream_bwrit(stream, (tb_byte_t const*)"tbo00", 5)) return -1;
// done
tb_oc_bin_writer_t writer = {0};
do
{
// init writer
writer.stream = stream;
writer.ohash = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_ptr(tb_null, tb_null), tb_element_uint32());
writer.shash = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_str(tb_true), tb_element_uint32());
tb_assert_and_check_break(writer.shash && writer.ohash);
// write
if (!func(&writer, object)) break;
// sync
if (!tb_stream_sync(stream, tb_true)) break;
} while (0);
// exit the hash
if (writer.ohash) tb_hash_map_exit(writer.ohash);
if (writer.shash) tb_hash_map_exit(writer.shash);
// exit the data
if (writer.data) tb_free(writer.data);
// the end offset
tb_hize_t eof = tb_stream_offset(stream);
// ok?
return eof >= bof? (tb_long_t)(eof - bof) : -1;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_oc_writer_t* tb_oc_bin_writer()
{
// the writer
static tb_oc_writer_t s_writer = {0};
// init writer
s_writer.writ = tb_oc_bin_writer_done;
// init hooker
s_writer.hooker = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_uint32(), tb_element_ptr(tb_null, tb_null));
tb_assert_and_check_return_val(s_writer.hooker, tb_null);
// hook writer
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_NULL, tb_oc_bin_writer_func_null);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DATE, tb_oc_bin_writer_func_date);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DATA, tb_oc_bin_writer_func_data);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_ARRAY, tb_oc_bin_writer_func_array);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_STRING, tb_oc_bin_writer_func_string);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_NUMBER, tb_oc_bin_writer_func_number);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_BOOLEAN, tb_oc_bin_writer_func_boolean);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DICTIONARY, tb_oc_bin_writer_func_dictionary);
// ok
return &s_writer;
}
tb_bool_t tb_oc_bin_writer_hook(tb_size_t type, tb_oc_bin_writer_func_t func)
{
// check
tb_assert_and_check_return_val(func, tb_false);
// the writer
tb_oc_writer_t* writer = tb_oc_writer_get(TB_OBJECT_FORMAT_BIN);
tb_assert_and_check_return_val(writer && writer->hooker, tb_false);
// hook it
tb_hash_map_insert(writer->hooker, (tb_pointer_t)type, func);
// ok
return tb_true;
}
tb_oc_bin_writer_func_t tb_oc_bin_writer_func(tb_size_t type)
{
// the writer
tb_oc_writer_t* writer = tb_oc_writer_get(TB_OBJECT_FORMAT_BIN);
tb_assert_and_check_return_val(writer && writer->hooker, tb_null);
// the func
return (tb_oc_bin_writer_func_t)tb_hash_map_get(writer->hooker, (tb_pointer_t)type);
}
tbox-1.7.6/src/tbox/object/impl/writer/bin.h 0000664 0000000 0000000 00000005135 14671175054 0020726 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file bin.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_IMPL_WRITER_BIN_H
#define TB_OBJECT_IMPL_WRITER_BIN_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the object bin writer type
typedef struct __tb_oc_bin_writer_t
{
/// the stream
tb_stream_ref_t stream;
/// the object hash
tb_hash_map_ref_t ohash;
/// the string hash
tb_hash_map_ref_t shash;
/// the object index
tb_size_t index;
/// the encoder data
tb_byte_t* data;
/// the encoder maxn
tb_size_t maxn;
}tb_oc_bin_writer_t;
/// the bin writer func type
typedef tb_bool_t (*tb_oc_bin_writer_func_t)(tb_oc_bin_writer_t* writer, tb_object_ref_t object);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the bin object writer
*
* @return the bin object writer
*/
tb_oc_writer_t* tb_oc_bin_writer(tb_noarg_t);
/*! hook the bin writer
*
* @param type the object type
* @param func the writer func
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_bin_writer_hook(tb_size_t type, tb_oc_bin_writer_func_t func);
/*! the bin writer func
*
* @param type the object type
*
* @return the object writer func
*/
tb_oc_bin_writer_func_t tb_oc_bin_writer_func(tb_size_t type);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/object/impl/writer/bplist.c 0000664 0000000 0000000 00000065615 14671175054 0021457 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file bplist.c
* @ingroup object
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "oc_writer_bplist"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "bplist.h"
#include "writer.h"
#include "../../../algorithm/algorithm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// set bits
#define tb_oc_bplist_writer_bits_set(p, v, n) \
do { \
switch ((n)) \
{ \
case 1: tb_bits_set_u8((p), (tb_uint8_t)(v)); break; \
case 2: tb_bits_set_u16_be((p), (tb_uint16_t)(v)); break; \
case 4: tb_bits_set_u32_be((p), (tb_uint32_t)(v)); break; \
case 8: tb_bits_set_u64_be((p), (tb_uint64_t)(v)); break; \
default: break; \
} \
} while (0)
// number
#define tb_oc_bplist_writer_init_number(x) \
(((tb_uint64_t)(x)) < (1ull << 8) ? tb_oc_number_init_from_uint8((tb_uint8_t)(x)) : \
(((tb_uint64_t)(x)) < (1ull << 16) ? tb_oc_number_init_from_uint16((tb_uint16_t)(x)) : \
(((tb_uint64_t)(x)) < (1ull << 32) ? tb_oc_number_init_from_uint32((tb_uint32_t)(x)) : tb_oc_number_init_from_uint64((x)))))
// object list grow
#ifdef __tb_small__
# define TB_OBJECT_BPLIST_LIST_GROW (64)
#else
# define TB_OBJECT_BPLIST_LIST_GROW (256)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the bplist type enum
typedef enum __tb_oc_bplist_type_e
{
TB_OBJECT_BPLIST_TYPE_NONE = 0x00
, TB_OBJECT_BPLIST_TYPE_FALSE = 0x08
, TB_OBJECT_BPLIST_TYPE_TRUE = 0x09
, TB_OBJECT_BPLIST_TYPE_UINT = 0x10
, TB_OBJECT_BPLIST_TYPE_REAL = 0x20
, TB_OBJECT_BPLIST_TYPE_DATE = 0x30
, TB_OBJECT_BPLIST_TYPE_DATA = 0x40
, TB_OBJECT_BPLIST_TYPE_STRING = 0x50
, TB_OBJECT_BPLIST_TYPE_UNICODE = 0x60
, TB_OBJECT_BPLIST_TYPE_UID = 0x70
, TB_OBJECT_BPLIST_TYPE_ARRAY = 0xA0
, TB_OBJECT_BPLIST_TYPE_SET = 0xC0
, TB_OBJECT_BPLIST_TYPE_DICT = 0xD0
, TB_OBJECT_BPLIST_TYPE_MASK = 0xF0
}tb_oc_bplist_type_e;
/* //////////////////////////////////////////////////////////////////////////////////////
* declaration
*/
static tb_bool_t tb_oc_bplist_writer_func_number(tb_oc_bplist_writer_t* writer, tb_object_ref_t object, tb_size_t item_size);
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
static __tb_inline__ tb_time_t tb_oc_bplist_writer_time_host2apple(tb_time_t time)
{
tb_tm_t tm = {0};
if (tb_localtime(time, &tm))
{
if (tm.year >= 31) tm.year -= 31;
time = tb_mktime(&tm);
}
return time;
}
#endif
static tb_bool_t tb_oc_bplist_writer_func_rdata(tb_oc_bplist_writer_t* writer, tb_uint8_t bype, tb_byte_t const* data, tb_size_t size, tb_size_t item_size)
{
// check
tb_assert_and_check_return_val(writer && writer->stream && !data == !size, tb_false);
// write flag
tb_uint8_t flag = bype | (tb_uint8_t)(size < 15 ? size : 0xf);
if (!tb_stream_bwrit_u8(writer->stream, flag)) return tb_false;
// write size
if (size >= 15)
{
// init object
tb_object_ref_t object = tb_oc_bplist_writer_init_number(size);
tb_assert_and_check_return_val(object, tb_false);
// write it
if (!tb_oc_bplist_writer_func_number(writer, object, item_size))
{
tb_object_exit(object);
return tb_false;
}
// exit object
tb_object_exit(object);
}
// unicode? adjust size
if (bype == TB_OBJECT_BPLIST_TYPE_UNICODE) size <<= 1;
// write data
if (data) if (!tb_stream_bwrit(writer->stream, data, size)) return tb_false;
// ok
return tb_true;
}
static tb_bool_t tb_oc_bplist_writer_func_date(tb_oc_bplist_writer_t* writer, tb_object_ref_t object, tb_size_t item_size)
{
// check
tb_assert_and_check_return_val(writer && writer->stream && object, tb_false);
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
// write date time
if (!tb_stream_bwrit_u8(writer->stream, TB_OBJECT_BPLIST_TYPE_DATE | 3)) return tb_false;
if (!tb_stream_bwrit_double_bbe(writer->stream, (tb_double_t)tb_oc_bplist_writer_time_host2apple(tb_oc_date_time(object)))) return tb_false;
#else
tb_assert_and_check_return_val(0, tb_false);
#endif
// ok
return tb_true;
}
static tb_bool_t tb_oc_bplist_writer_func_data(tb_oc_bplist_writer_t* writer, tb_object_ref_t object, tb_size_t item_size)
{
// check
tb_assert_and_check_return_val(writer && writer->stream && object, tb_false);
// write
return tb_oc_bplist_writer_func_rdata(writer, TB_OBJECT_BPLIST_TYPE_DATA, (tb_byte_t const*)tb_oc_data_getp(object), tb_oc_data_size(object), item_size);
}
static tb_bool_t tb_oc_bplist_writer_func_array(tb_oc_bplist_writer_t* writer, tb_object_ref_t object, tb_size_t item_size)
{
// check
tb_assert_and_check_return_val(writer && writer->stream && object, tb_false);
// index tables
tb_byte_t* index_tables = (tb_byte_t*)tb_object_getp(object);
// size
tb_size_t size = tb_oc_array_size(object);
tb_assert_and_check_return_val(!size == !index_tables, tb_false);
// write flag
tb_uint8_t flag = TB_OBJECT_BPLIST_TYPE_ARRAY | (size < 15 ? (tb_uint8_t)size : 0xf);
if (!tb_stream_bwrit_u8(writer->stream, flag)) return tb_false;
// write size
if (size >= 15)
{
// init osize
tb_object_ref_t osize = tb_oc_bplist_writer_init_number(size);
tb_assert_and_check_return_val(osize, tb_false);
// write it
if (!tb_oc_bplist_writer_func_number(writer, osize, item_size))
{
tb_object_exit(osize);
return tb_false;
}
// exit osize
tb_object_exit(osize);
}
// write index tables
if (index_tables)
{
if (!tb_stream_bwrit(writer->stream, index_tables, size * item_size)) return tb_false;
}
// ok
return tb_true;
}
static tb_bool_t tb_oc_bplist_writer_func_string(tb_oc_bplist_writer_t* writer, tb_object_ref_t object, tb_size_t item_size)
{
// check
tb_assert_and_check_return_val(writer && writer->stream && object, tb_false);
#if 0
// write utf8
return tb_oc_bplist_writer_func_rdata(writer, TB_OBJECT_BPLIST_TYPE_STRING, tb_oc_string_cstr(object), tb_oc_string_size(object), item_size);
#else
// write utf16
tb_char_t const* utf8 = tb_oc_string_cstr(object);
tb_size_t size = tb_oc_string_size(object);
if (utf8 && size)
{
#ifdef TB_CONFIG_MODULE_HAVE_CHARSET
// done
tb_bool_t ok = tb_false;
tb_char_t* utf16 = tb_null;
tb_size_t osize = 0;
do
{
// init utf16 data
utf16 = tb_malloc_cstr((size + 1) << 2);
tb_assert_and_check_break(utf16);
// utf8 to utf16
osize = tb_charset_conv_data(TB_CHARSET_TYPE_UTF8, TB_CHARSET_TYPE_UTF16, (tb_byte_t const*)utf8, size, (tb_byte_t*)utf16, (size + 1) << 2);
tb_assert_and_check_break(osize > 0 && osize < (size + 1) << 2);
tb_assert_and_check_break(!(osize & 1));
// ok
ok = tb_true;
} while (0);
// ok?
if (ok)
{
// only ascii? write utf8
if (osize == (size << 1)) ok = tb_oc_bplist_writer_func_rdata(writer, TB_OBJECT_BPLIST_TYPE_STRING, (tb_byte_t*)utf8, size, item_size);
// write utf16
else ok = tb_oc_bplist_writer_func_rdata(writer, TB_OBJECT_BPLIST_TYPE_UNICODE, (tb_byte_t*)utf16, osize >> 1, item_size);
}
// exit utf16
if (utf16) tb_free(utf16);
utf16 = tb_null;
#else
// write utf8 only
tb_bool_t ok = tb_oc_bplist_writer_func_rdata(writer, TB_OBJECT_BPLIST_TYPE_STRING, (tb_byte_t*)utf8, size, item_size);
#endif
// ok?
return ok;
}
// write empty
else return tb_oc_bplist_writer_func_rdata(writer, TB_OBJECT_BPLIST_TYPE_STRING, tb_null, 0, item_size);
#endif
}
static tb_bool_t tb_oc_bplist_writer_func_number(tb_oc_bplist_writer_t* writer, tb_object_ref_t object, tb_size_t item_size)
{
// check
tb_assert_and_check_return_val(writer && writer->stream && object, tb_false);
// done
switch (tb_oc_number_type(object))
{
case TB_OC_NUMBER_TYPE_UINT64:
if (!tb_stream_bwrit_u8(writer->stream, TB_OBJECT_BPLIST_TYPE_UINT | 3)) return tb_false;
if (!tb_stream_bwrit_u64_be(writer->stream, tb_oc_number_uint64(object))) return tb_false;
break;
case TB_OC_NUMBER_TYPE_SINT64:
if (!tb_stream_bwrit_u8(writer->stream, TB_OBJECT_BPLIST_TYPE_UINT | 3)) return tb_false;
if (!tb_stream_bwrit_s64_be(writer->stream, tb_oc_number_sint64(object))) return tb_false;
break;
case TB_OC_NUMBER_TYPE_UINT32:
if (!tb_stream_bwrit_u8(writer->stream, TB_OBJECT_BPLIST_TYPE_UINT | 2)) return tb_false;
if (!tb_stream_bwrit_u32_be(writer->stream, tb_oc_number_uint32(object))) return tb_false;
break;
case TB_OC_NUMBER_TYPE_SINT32:
if (!tb_stream_bwrit_u8(writer->stream, TB_OBJECT_BPLIST_TYPE_UINT | 2)) return tb_false;
if (!tb_stream_bwrit_s32_be(writer->stream, tb_oc_number_sint32(object))) return tb_false;
break;
case TB_OC_NUMBER_TYPE_UINT16:
if (!tb_stream_bwrit_u8(writer->stream, TB_OBJECT_BPLIST_TYPE_UINT | 1)) return tb_false;
if (!tb_stream_bwrit_u16_be(writer->stream, tb_oc_number_uint16(object))) return tb_false;
break;
case TB_OC_NUMBER_TYPE_SINT16:
if (!tb_stream_bwrit_u8(writer->stream, TB_OBJECT_BPLIST_TYPE_UINT | 1)) return tb_false;
if (!tb_stream_bwrit_s16_be(writer->stream, tb_oc_number_sint16(object))) return tb_false;
break;
case TB_OC_NUMBER_TYPE_UINT8:
if (!tb_stream_bwrit_u8(writer->stream, TB_OBJECT_BPLIST_TYPE_UINT)) return tb_false;
if (!tb_stream_bwrit_u8(writer->stream, tb_oc_number_uint8(object))) return tb_false;
break;
case TB_OC_NUMBER_TYPE_SINT8:
if (!tb_stream_bwrit_u8(writer->stream, TB_OBJECT_BPLIST_TYPE_UINT)) return tb_false;
if (!tb_stream_bwrit_s8(writer->stream, tb_oc_number_sint8(object))) return tb_false;
break;
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
case TB_OC_NUMBER_TYPE_FLOAT:
{
if (!tb_stream_bwrit_u8(writer->stream, TB_OBJECT_BPLIST_TYPE_REAL | 2)) return tb_false;
if (!tb_stream_bwrit_float_be(writer->stream, tb_oc_number_float(object))) return tb_false;
}
break;
case TB_OC_NUMBER_TYPE_DOUBLE:
{
if (!tb_stream_bwrit_u8(writer->stream, TB_OBJECT_BPLIST_TYPE_REAL | 3)) return tb_false;
if (!tb_stream_bwrit_double_bbe(writer->stream, tb_oc_number_double(object))) return tb_false;
}
break;
#endif
default:
tb_assert_and_check_return_val(0, tb_false);
break;
}
// ok
return tb_true;
}
static tb_bool_t tb_oc_bplist_writer_func_boolean(tb_oc_bplist_writer_t* writer, tb_object_ref_t object, tb_size_t item_size)
{
// check
tb_assert_and_check_return_val(writer && writer->stream && object, tb_false);
// write it
return tb_stream_bwrit_u8(writer->stream, TB_OBJECT_BPLIST_TYPE_NONE | (tb_oc_boolean_bool(object)? TB_OBJECT_BPLIST_TYPE_TRUE : TB_OBJECT_BPLIST_TYPE_FALSE));
}
static tb_bool_t tb_oc_bplist_writer_func_dictionary(tb_oc_bplist_writer_t* writer, tb_object_ref_t object, tb_size_t item_size)
{
// check
tb_assert_and_check_return_val(writer && writer->stream && object, tb_false);
// index tables
tb_byte_t* index_tables = (tb_byte_t*)tb_object_getp(object);
// size
tb_size_t size = tb_oc_dictionary_size(object);
tb_assert_and_check_return_val(!size == !index_tables, tb_false);
// write flag
tb_uint8_t flag = TB_OBJECT_BPLIST_TYPE_DICT | (size < 15 ? (tb_uint8_t)size : 0xf);
if (!tb_stream_bwrit_u8(writer->stream, flag)) return tb_false;
// write size
if (size >= 15)
{
// init osize
tb_object_ref_t osize = tb_oc_bplist_writer_init_number(size);
tb_assert_and_check_return_val(osize, tb_false);
// write it
if (!tb_oc_bplist_writer_func_number(writer, osize, item_size))
{
tb_object_exit(osize);
return tb_false;
}
// exit osize
tb_object_exit(osize);
}
// write index tables
if (index_tables)
{
if (!tb_stream_bwrit(writer->stream, index_tables, (size << 1) * item_size)) return tb_false;
}
// ok
return tb_true;
}
static tb_uint64_t tb_oc_bplist_writer_builder_maxn(tb_object_ref_t object)
{
// check
tb_assert_and_check_return_val(object, 0);
// walk
tb_uint64_t size = 0;
switch (tb_object_type(object))
{
case TB_OBJECT_TYPE_ARRAY:
{
// walk
tb_for_all (tb_object_ref_t, item, tb_oc_array_itor(object))
{
if (item) size += tb_oc_bplist_writer_builder_maxn(item);
}
}
break;
case TB_OBJECT_TYPE_DICTIONARY:
{
// walk
tb_for_all (tb_oc_dictionary_item_t*, item, tb_oc_dictionary_itor(object))
{
// item
if (item && item->key && item->val)
size += 1 + tb_oc_bplist_writer_builder_maxn(item->val);
}
}
break;
default:
break;
}
return size + 1;
}
static tb_size_t tb_oc_bplist_writer_builder_addo(tb_object_ref_t object, tb_object_ref_t list, tb_hash_map_ref_t hash)
{
// check
tb_assert_and_check_return_val(object && list && hash, 0);
// the object index
tb_size_t index = (tb_size_t)tb_hash_map_get(hash, object);
// new object?
if (!index)
{
// append object
tb_oc_array_append(list, object);
// index
index = tb_oc_array_size(list);
// set index
tb_hash_map_insert(hash, object, (tb_pointer_t)index);
tb_object_retain(object);
// check
tb_assert(!tb_object_getp(object));
}
// ok?
return index;
}
static tb_void_t tb_oc_bplist_writer_builder_init(tb_object_ref_t object, tb_object_ref_t list, tb_hash_map_ref_t hash, tb_size_t item_size)
{
// check
tb_assert_and_check_return(object && list && hash);
// build items
switch (tb_object_type(object))
{
case TB_OBJECT_TYPE_ARRAY:
{
// make index tables
tb_byte_t* index_tables = tb_null;
tb_size_t size = tb_oc_array_size(object);
if (size)
{
index_tables = (tb_byte_t*)tb_object_getp(object);
if (!index_tables)
{
// make it
index_tables = tb_malloc0_bytes(size * item_size);
// FIXME: not using the user private data
tb_object_setp(object, index_tables);
}
}
// walk
tb_size_t i = 0;
tb_for_all (tb_object_ref_t, item, tb_oc_array_itor(object))
{
// build item
if (item)
{
// add item to builder
tb_size_t index = tb_oc_bplist_writer_builder_addo(item, list, hash);
// add index to tables
if (index && index_tables) tb_oc_bplist_writer_bits_set(index_tables + i++ * item_size, index - 1, item_size);
// tb_trace_d("item: %p[%lu]", index_tables, index - 1);
// init next
tb_oc_bplist_writer_builder_init(item, list, hash, item_size);
}
}
}
break;
case TB_OBJECT_TYPE_DICTIONARY:
{
// make index tables
tb_byte_t* index_tables = tb_null;
tb_size_t size = tb_oc_dictionary_size(object);
if (size)
{
index_tables = (tb_byte_t*)tb_object_getp(object);
if (!index_tables)
{
// make it
index_tables = tb_malloc0_bytes((size << 1) * item_size);
// FIXME: not using the user private data
tb_object_setp(object, index_tables);
}
}
// walk keys
{
tb_size_t i = 0;
tb_for_all (tb_oc_dictionary_item_t*, item, tb_oc_dictionary_itor(object))
{
// item
if (item && item->key && item->val)
{
// make key object
tb_object_ref_t key = tb_oc_string_init_from_cstr(item->key);
if (key)
{
// add key to builder
tb_size_t index = tb_oc_bplist_writer_builder_addo(key, list, hash);
// add index to tables
if (index && index_tables) tb_oc_bplist_writer_bits_set(index_tables + i++ * item_size, index - 1, item_size);
// tb_trace_d("keys: %p[%lu]", index_tables, index - 1);
// build key
tb_oc_bplist_writer_builder_init(key, list, hash, item_size);
tb_object_exit(key);
}
}
}
}
// walk vals
{
tb_size_t i = 0;
tb_for_all (tb_oc_dictionary_item_t*, item, tb_oc_dictionary_itor(object))
{
// item
if (item && item->key && item->val)
{
// add val to builder
tb_size_t index = tb_oc_bplist_writer_builder_addo(item->val, list, hash);
// add index to tables
if (index && index_tables) tb_oc_bplist_writer_bits_set(index_tables + (size + i++) * item_size, index - 1, item_size);
// tb_trace_d("vals: %p[%lu]", index_tables, index - 1);
// build val
tb_oc_bplist_writer_builder_init(item->val, list, hash, item_size);
}
}
}
}
break;
default:
break;
}
}
static tb_void_t tb_oc_bplist_writer_builder_exit(tb_object_ref_t list, tb_hash_map_ref_t hash)
{
// exit hash
if (hash)
{
// walk
tb_for_all (tb_hash_map_item_ref_t, item, hash)
{
// exit item
if (item && item->name)
{
tb_byte_t* priv = (tb_byte_t*)tb_object_getp((tb_object_ref_t)item->name);
if (priv)
{
tb_free(priv);
tb_object_setp((tb_object_ref_t)item->name, tb_null);
}
tb_object_exit((tb_object_ref_t)item->name);
}
}
// exit it
tb_hash_map_exit(hash);
}
// exit list
if (list) tb_object_exit(list);
}
static tb_long_t tb_oc_bplist_writer_done(tb_stream_ref_t stream, tb_object_ref_t object, tb_bool_t deflate)
{
// check
tb_assert_and_check_return_val(object && stream, -1);
// done
tb_bool_t ok = tb_false;
tb_size_t i = 0;
tb_byte_t pad[6] = {0};
tb_object_ref_t list = tb_null;
tb_hash_map_ref_t hash = tb_null;
tb_size_t object_count = 0;
tb_uint64_t object_maxn = 0;
tb_uint64_t root_object = 0;
tb_uint64_t offset_table_index = 0;
tb_size_t offset_size = 0;
tb_size_t item_size = 0;
tb_uint64_t* offsets = tb_null;
tb_hize_t bof = 0;
tb_hize_t eof = 0;
do
{
// init writer
tb_oc_bplist_writer_t writer = {0};
writer.stream = stream;
// init list
list = tb_oc_array_init(TB_OBJECT_BPLIST_LIST_GROW, tb_true);
tb_assert_and_check_break(list);
// init hash
hash = tb_hash_map_init(0, tb_element_ptr(tb_null, tb_null), tb_element_uint32());
tb_assert_and_check_break(hash);
// object maxn
object_maxn = tb_oc_bplist_writer_builder_maxn(object);
item_size = tb_object_need_bytes(object_maxn);
tb_trace_d("object_maxn: %llu", object_maxn);
tb_trace_d("item_size: %lu", item_size);
// add root object to builder
tb_oc_bplist_writer_builder_addo(object, list, hash);
// init object builder
tb_oc_bplist_writer_builder_init(object, list, hash, item_size);
// init object count
object_count = tb_oc_array_size(list);
tb_trace_d("object_count: %lu", object_count);
// init offsets
offsets = (tb_uint64_t*)tb_malloc0(object_count * sizeof(tb_uint64_t));
tb_assert_and_check_break(offsets);
// the begin offset
bof = tb_stream_offset(stream);
// write magic & version
if (!tb_stream_bwrit(stream, (tb_byte_t const*)"bplist00", 8)) break;
// write objects
if (object_count)
{
i = 0;
tb_bool_t failed = tb_false;
tb_for_all_if (tb_object_ref_t, item, tb_oc_array_itor(list), item && !failed)
{
// check
tb_assert_and_check_break_state(i < object_count, failed, tb_true);
// save offset
offsets[i++] = tb_stream_offset(stream);
// the func
tb_oc_bplist_writer_func_t func = tb_oc_bplist_writer_func(tb_object_type(item));
tb_assert_and_check_continue(func);
// write object
if (!func(&writer, item, item_size))
{
failed = tb_true;
break;
}
}
// failed?
tb_check_break(!failed);
}
// offset table index
offset_table_index = tb_stream_offset(stream);
offset_size = tb_object_need_bytes(offset_table_index);
tb_trace_d("offset_table_index: %llu", offset_table_index);
tb_trace_d("offset_size: %lu", offset_size);
// write offset table
tb_bool_t failed = tb_false;
for (i = 0; !failed && i < object_count; i++)
{
switch (offset_size)
{
case 1:
if (!tb_stream_bwrit_u8(stream, (tb_uint8_t)offsets[i])) failed = tb_true;
break;
case 2:
if (!tb_stream_bwrit_u16_be(stream, (tb_uint16_t)offsets[i])) failed = tb_true;
break;
case 4:
if (!tb_stream_bwrit_u32_be(stream, (tb_uint32_t)offsets[i])) failed = tb_true;
break;
case 8:
if (!tb_stream_bwrit_u64_be(stream, (tb_uint64_t)offsets[i])) failed = tb_true;
break;
default:
tb_assert_and_check_break_state(0, failed, tb_true);
break;
}
}
// failed?
tb_check_break(!failed);
// write pad, like apple?
if (!tb_stream_bwrit(stream, pad, 6)) break;
// write tail
if (!tb_stream_bwrit_u8(stream, (tb_uint8_t)offset_size)) break;
if (!tb_stream_bwrit_u8(stream, (tb_uint8_t)item_size)) break;
if (!tb_stream_bwrit_u64_be(stream, object_count)) break;
if (!tb_stream_bwrit_u64_be(stream, root_object)) break;
if (!tb_stream_bwrit_u64_be(stream, offset_table_index)) break;
// sync stream
if (!tb_stream_sync(stream, tb_true)) break;
// the end offset
eof = tb_stream_offset(stream);
// ok
ok = tb_true;
} while (0);
// exit offsets
if (offsets) tb_free(offsets);
offsets = tb_null;
// exit object builder
tb_oc_bplist_writer_builder_exit(list, hash);
list = tb_null;
hash = tb_null;
// ok?
return (ok && (eof >= bof))? (tb_long_t)(eof - bof) : -1;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_oc_writer_t* tb_oc_bplist_writer()
{
// the writer
static tb_oc_writer_t s_writer = {0};
// init writer
s_writer.writ = tb_oc_bplist_writer_done;
// init hooker
s_writer.hooker = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_uint32(), tb_element_ptr(tb_null, tb_null));
tb_assert_and_check_return_val(s_writer.hooker, tb_null);
// hook writer
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DATE, tb_oc_bplist_writer_func_date);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DATA, tb_oc_bplist_writer_func_data);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_ARRAY, tb_oc_bplist_writer_func_array);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_STRING, tb_oc_bplist_writer_func_string);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_NUMBER, tb_oc_bplist_writer_func_number);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_BOOLEAN, tb_oc_bplist_writer_func_boolean);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DICTIONARY, tb_oc_bplist_writer_func_dictionary);
// ok
return &s_writer;
}
tb_bool_t tb_oc_bplist_writer_hook(tb_size_t type, tb_oc_bplist_writer_func_t func)
{
// check
tb_assert_and_check_return_val(func, tb_false);
// the writer
tb_oc_writer_t* writer = tb_oc_writer_get(TB_OBJECT_FORMAT_BPLIST);
tb_assert_and_check_return_val(writer && writer->hooker, tb_false);
// hook it
tb_hash_map_insert(writer->hooker, (tb_pointer_t)type, func);
// ok
return tb_true;
}
tb_oc_bplist_writer_func_t tb_oc_bplist_writer_func(tb_size_t type)
{
// the writer
tb_oc_writer_t* writer = tb_oc_writer_get(TB_OBJECT_FORMAT_BPLIST);
tb_assert_and_check_return_val(writer && writer->hooker, tb_null);
// the func
return (tb_oc_bplist_writer_func_t)tb_hash_map_get(writer->hooker, (tb_pointer_t)type);
}
tbox-1.7.6/src/tbox/object/impl/writer/bplist.h 0000664 0000000 0000000 00000004541 14671175054 0021453 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file bplist.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_IMPL_WRITER_BPLIST_H
#define TB_OBJECT_IMPL_WRITER_BPLIST_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the object bplist writer type
typedef struct __tb_oc_bplist_writer_t
{
/// the stream
tb_stream_ref_t stream;
}tb_oc_bplist_writer_t;
/// the bplist writer func type
typedef tb_bool_t (*tb_oc_bplist_writer_func_t)(tb_oc_bplist_writer_t* writer, tb_object_ref_t object, tb_size_t item_size);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the bplist object writer
*
* @return the bplist object writer
*/
tb_oc_writer_t* tb_oc_bplist_writer(tb_noarg_t);
/*! hook the bplist writer
*
* @param type the object type
* @param func the writer func
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_bplist_writer_hook(tb_size_t type, tb_oc_bplist_writer_func_t func);
/*! the bplist writer func
*
* @param type the object type
*
* @return the object writer func
*/
tb_oc_bplist_writer_func_t tb_oc_bplist_writer_func(tb_size_t type);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/object/impl/writer/json.c 0000664 0000000 0000000 00000033333 14671175054 0021123 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file json.c
* @ingroup object
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "oc_writer_json"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "json.h"
#include "writer.h"
#include "../../../algorithm/algorithm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_char_t const* tb_oc_json_escape_cstr(tb_char_t* data, tb_size_t maxn, tb_object_ref_t object)
{
tb_char_t const* sp = tb_oc_string_cstr(object);
tb_char_t const* se = sp + tb_oc_string_size(object);
tb_char_t* dp = data;
tb_char_t const* de = data + maxn;
tb_char_t ch;
while (sp < se && dp < de)
{
ch = *sp++;
if (dp + 1 < de)
{
if (ch == '\n')
{
*dp++ = '\\';
*dp++ = 'n';
}
else if (ch == '\t')
{
*dp++ = '\\';
*dp++ = 't';
}
else if (ch == '"')
{
*dp++ = '\\';
*dp++ = '"';
}
else if (ch == '\\')
{
*dp++ = '\\';
*dp++ = '\\';
}
else
{
*dp++ = ch;
continue;
}
}
else *dp++ = ch;
}
if (dp < de) *dp = '\0';
return data;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_bool_t tb_oc_json_writer_func_null(tb_oc_json_writer_t* writer, tb_object_ref_t object, tb_size_t level)
{
// check
tb_assert_and_check_return_val(writer && writer->stream, tb_false);
// write
if (tb_stream_printf(writer->stream, "null") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
return tb_true;
}
static tb_bool_t tb_oc_json_writer_func_array(tb_oc_json_writer_t* writer, tb_object_ref_t object, tb_size_t level)
{
// check
tb_assert_and_check_return_val(writer && writer->stream, tb_false);
// write array
if (tb_oc_array_size(object))
{
// write begin
if (tb_stream_printf(writer->stream, "[") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
// walk
tb_for_all (tb_object_ref_t, item, tb_oc_array_itor(object))
{
// item
if (item)
{
// func
tb_oc_json_writer_func_t func = tb_oc_json_writer_func(item->type);
tb_assert_and_check_continue(func);
// write tab
if (item_itor != item_head)
{
if (!tb_oc_writer_spaces(writer->stream, writer->deflate, level, 2)) return tb_false;
if (tb_stream_printf(writer->stream, ",") < 0) return tb_false;
if (!tb_oc_writer_spaces(writer->stream, writer->deflate, 1, 1)) return tb_false;
}
else if (!tb_oc_writer_spaces(writer->stream, writer->deflate, level + 1, 2)) return tb_false;
// write
if (!func(writer, item, level + 1)) return tb_false;
}
}
// write end
if (!tb_oc_writer_spaces(writer->stream, writer->deflate, level, 2)) return tb_false;
if (tb_stream_printf(writer->stream, "]") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
}
else
{
if (tb_stream_printf(writer->stream, "[]") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
}
return tb_true;
}
static tb_bool_t tb_oc_json_writer_func_string(tb_oc_json_writer_t* writer, tb_object_ref_t object, tb_size_t level)
{
// check
tb_assert_and_check_return_val(writer && writer->stream, tb_false);
tb_size_t size = tb_oc_string_size(object);
if (size)
{
tb_size_t maxn = (size * 3 / 2) + 16;
if (maxn > 8192)
{
tb_char_t* data = (tb_char_t*)tb_malloc(maxn);
tb_char_t const* cstr = data? tb_oc_json_escape_cstr(data, maxn, object) : tb_null;
if (cstr && tb_stream_printf(writer->stream, "\"%s\"", cstr) < 0) return tb_false;
tb_free(data);
}
else
{
tb_char_t data[8192];
tb_char_t const* cstr = tb_oc_json_escape_cstr(data, maxn, object);
if (cstr && tb_stream_printf(writer->stream, "\"%s\"", cstr) < 0) return tb_false;
}
}
else if (tb_stream_printf(writer->stream, "\"\"") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
return tb_true;
}
static tb_bool_t tb_oc_json_writer_func_number(tb_oc_json_writer_t* writer, tb_object_ref_t object, tb_size_t level)
{
// check
tb_assert_and_check_return_val(writer && writer->stream, tb_false);
// write
switch (tb_oc_number_type(object))
{
case TB_OC_NUMBER_TYPE_UINT64:
if (tb_stream_printf(writer->stream, "%llu", tb_oc_number_uint64(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
case TB_OC_NUMBER_TYPE_SINT64:
if (tb_stream_printf(writer->stream, "%lld", tb_oc_number_sint64(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
case TB_OC_NUMBER_TYPE_UINT32:
if (tb_stream_printf(writer->stream, "%u", tb_oc_number_uint32(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
case TB_OC_NUMBER_TYPE_SINT32:
if (tb_stream_printf(writer->stream, "%d", tb_oc_number_sint32(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
case TB_OC_NUMBER_TYPE_UINT16:
if (tb_stream_printf(writer->stream, "%u", tb_oc_number_uint16(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
case TB_OC_NUMBER_TYPE_SINT16:
if (tb_stream_printf(writer->stream, "%d", tb_oc_number_sint16(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
case TB_OC_NUMBER_TYPE_UINT8:
if (tb_stream_printf(writer->stream, "%u", tb_oc_number_uint8(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
case TB_OC_NUMBER_TYPE_SINT8:
if (tb_stream_printf(writer->stream, "%d", tb_oc_number_sint8(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
case TB_OC_NUMBER_TYPE_FLOAT:
if (tb_stream_printf(writer->stream, "%f", tb_oc_number_float(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
case TB_OC_NUMBER_TYPE_DOUBLE:
if (tb_stream_printf(writer->stream, "%lf", tb_oc_number_double(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
#endif
default:
break;
}
return tb_true;
}
static tb_bool_t tb_oc_json_writer_func_boolean(tb_oc_json_writer_t* writer, tb_object_ref_t object, tb_size_t level)
{
// check
tb_assert_and_check_return_val(writer && writer->stream, tb_false);
// write
if (tb_stream_printf(writer->stream, "%s", tb_oc_boolean_bool(object)? "true" : "false") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
return tb_true;
}
static tb_bool_t tb_oc_json_writer_func_dictionary(tb_oc_json_writer_t* writer, tb_object_ref_t object, tb_size_t level)
{
// check
tb_assert_and_check_return_val(writer && writer->stream, tb_false);
// write
if (tb_oc_dictionary_size(object))
{
// write beg
if (tb_stream_printf(writer->stream, "{") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
// walk
tb_for_all (tb_oc_dictionary_item_t*, item, tb_oc_dictionary_itor(object))
{
// item
if (item && item->key && item->val)
{
// func
tb_oc_json_writer_func_t func = tb_oc_json_writer_func(item->val->type);
tb_assert_and_check_continue(func);
// write tab
if (item_itor != item_head)
{
if (!tb_oc_writer_spaces(writer->stream, writer->deflate, level, 2)) return tb_false;
if (tb_stream_printf(writer->stream, ",") < 0) return tb_false;
if (!tb_oc_writer_spaces(writer->stream, writer->deflate, 1, 1)) return tb_false;
}
else if (!tb_oc_writer_spaces(writer->stream, writer->deflate, level + 1, 2)) return tb_false;
// write key
if (tb_stream_printf(writer->stream, "\"%s\":", item->key) < 0) return tb_false;
// write spaces
if (!writer->deflate) if (tb_stream_printf(writer->stream, " ") < 0) return tb_false;
if (item->val->type == TB_OBJECT_TYPE_DICTIONARY || item->val->type == TB_OBJECT_TYPE_ARRAY)
{
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
if (!tb_oc_writer_spaces(writer->stream, writer->deflate, level + 1, 2)) return tb_false;
}
// write value
if (!func(writer, item->val, level + 1)) return tb_false;
}
}
// write end
if (!tb_oc_writer_spaces(writer->stream, writer->deflate, level, 2)) return tb_false;
if (tb_stream_printf(writer->stream, "}") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
}
else
{
if (tb_stream_printf(writer->stream, "{}") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
}
return tb_true;
}
static tb_long_t tb_oc_json_writer_done(tb_stream_ref_t stream, tb_object_ref_t object, tb_bool_t deflate)
{
// check
tb_assert_and_check_return_val(object && stream, -1);
// init writer
tb_oc_json_writer_t writer = {0};
writer.stream = stream;
writer.deflate = deflate;
// func
tb_oc_json_writer_func_t func = tb_oc_json_writer_func(object->type);
tb_assert_and_check_return_val(func, tb_false);
// the begin offset
tb_hize_t bof = tb_stream_offset(stream);
// write
if (!func(&writer, object, 0)) return -1;
// sync
if (!tb_stream_sync(stream, tb_true)) return -1;
// the end offset
tb_hize_t eof = tb_stream_offset(stream);
return eof >= bof? (tb_long_t)(eof - bof) : -1;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_oc_writer_t* tb_oc_json_writer()
{
// the writer
static tb_oc_writer_t s_writer = {0};
// init writer
s_writer.writ = tb_oc_json_writer_done;
// init hooker
s_writer.hooker = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_uint32(), tb_element_ptr(tb_null, tb_null));
tb_assert_and_check_return_val(s_writer.hooker, tb_null);
// hook writer
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_NULL, tb_oc_json_writer_func_null);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_ARRAY, tb_oc_json_writer_func_array);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_STRING, tb_oc_json_writer_func_string);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_NUMBER, tb_oc_json_writer_func_number);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_BOOLEAN, tb_oc_json_writer_func_boolean);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DICTIONARY, tb_oc_json_writer_func_dictionary);
return &s_writer;
}
tb_bool_t tb_oc_json_writer_hook(tb_size_t type, tb_oc_json_writer_func_t func)
{
tb_assert_and_check_return_val(func, tb_false);
tb_oc_writer_t* writer = tb_oc_writer_get(TB_OBJECT_FORMAT_JSON);
tb_assert_and_check_return_val(writer && writer->hooker, tb_false);
tb_hash_map_insert(writer->hooker, (tb_pointer_t)type, func);
return tb_true;
}
tb_oc_json_writer_func_t tb_oc_json_writer_func(tb_size_t type)
{
tb_oc_writer_t* writer = tb_oc_writer_get(TB_OBJECT_FORMAT_JSON);
tb_assert_and_check_return_val(writer && writer->hooker, tb_null);
return (tb_oc_json_writer_func_t)tb_hash_map_get(writer->hooker, (tb_pointer_t)type);
}
tbox-1.7.6/src/tbox/object/impl/writer/json.h 0000664 0000000 0000000 00000004574 14671175054 0021135 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file json.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_IMPL_WRITER_JSON_H
#define TB_OBJECT_IMPL_WRITER_JSON_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the object json writer type
typedef struct __tb_oc_json_writer_t
{
/// the stream
tb_stream_ref_t stream;
/// is deflate?
tb_bool_t deflate;
}tb_oc_json_writer_t;
/// the json writer func type
typedef tb_bool_t (*tb_oc_json_writer_func_t)(tb_oc_json_writer_t* writer, tb_object_ref_t object, tb_size_t level);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the json object writer
*
* @return the json object writer
*/
tb_oc_writer_t* tb_oc_json_writer(tb_noarg_t);
/*! hook the json writer
*
* @param type the object type
* @param func the writer func
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_json_writer_hook(tb_size_t type, tb_oc_json_writer_func_t func);
/*! the json writer func
*
* @param type the object type
*
* @return the object writer func
*/
tb_oc_json_writer_func_t tb_oc_json_writer_func(tb_size_t type);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/object/impl/writer/prefix.h 0000664 0000000 0000000 00000006543 14671175054 0021457 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_WRITER_PREFIX_H
#define TB_OBJECT_WRITER_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* inlines
*/
static __tb_inline__ tb_bool_t tb_oc_writer_spaces(tb_stream_ref_t stream, tb_bool_t deflate, tb_size_t tab, tb_size_t width)
{
// write tab
if (!deflate)
{
tb_size_t spaces = tab * width;
while (spaces--) if (tb_stream_printf(stream, " ") < 0) return tb_false;
}
return tb_true;
}
static __tb_inline__ tb_bool_t tb_oc_writer_tab(tb_stream_ref_t stream, tb_bool_t deflate, tb_size_t tab)
{
return tb_oc_writer_spaces(stream, deflate, tab, 4);
}
static __tb_inline__ tb_bool_t tb_oc_writer_newline(tb_stream_ref_t stream, tb_bool_t deflate)
{
// write newline
if (!deflate && tb_stream_printf(stream, __tb_newline__) < 0) return tb_false;
return tb_true;
}
static __tb_inline__ tb_bool_t tb_oc_writer_bin_type_size(tb_stream_ref_t stream, tb_size_t type, tb_uint64_t size)
{
// check
tb_assert_and_check_return_val(stream && type <= 0xff, tb_false);
// byte for size < 64bits
tb_size_t sizeb = tb_object_need_bytes(size);
tb_assert_and_check_return_val(sizeb <= 8, tb_false);
// flag for size
tb_size_t sizef = 0;
switch (sizeb)
{
case 1: sizef = 0xc; break;
case 2: sizef = 0xd; break;
case 4: sizef = 0xe; break;
case 8: sizef = 0xf; break;
default: break;
}
tb_assert_and_check_return_val(sizef, tb_false);
// write flag
tb_uint8_t flag = ((type < 0xf? (tb_uint8_t)type : 0xf) << 4) | (size < 0xc? (tb_uint8_t)size : (tb_uint8_t)sizef);
if (!tb_stream_bwrit_u8(stream, flag)) return tb_false;
// trace
// tb_trace("write: type: %lu, size: %llu", type, size);
// write type
if (type >= 0xf) if (!tb_stream_bwrit_u8(stream, (tb_uint8_t)type)) return tb_false;
// write size
if (size >= 0xc)
{
switch (sizeb)
{
case 1:
if (!tb_stream_bwrit_u8(stream, (tb_uint8_t)size)) return tb_false;
break;
case 2:
if (!tb_stream_bwrit_u16_be(stream, (tb_uint16_t)size)) return tb_false;
break;
case 4:
if (!tb_stream_bwrit_u32_be(stream, (tb_uint32_t)size)) return tb_false;
break;
case 8:
if (!tb_stream_bwrit_u64_be(stream, (tb_uint64_t)size)) return tb_false;
break;
default:
tb_assert_and_check_return_val(0, tb_false);
break;
}
}
return tb_true;
}
#endif
tbox-1.7.6/src/tbox/object/impl/writer/writer.c 0000664 0000000 0000000 00000004757 14671175054 0021476 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file writer.c
* @ingroup object
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "writer.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
// the object writer
static tb_oc_writer_t* g_writer[TB_OBJECT_FORMAT_MAXN] = {tb_null};
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_oc_writer_set(tb_size_t format, tb_oc_writer_t* writer)
{
// check
format &= 0x00ff;
tb_assert_and_check_return_val(writer && (format < tb_arrayn(g_writer)), tb_false);
// exit the older writer if exists
tb_oc_writer_remove(format);
// set
g_writer[format] = writer;
// ok
return tb_true;
}
tb_void_t tb_oc_writer_remove(tb_size_t format)
{
// check
format &= 0x00ff;
tb_assert_and_check_return((format < tb_arrayn(g_writer)));
// exit it
if (g_writer[format])
{
// exit hooker
if (g_writer[format]->hooker) tb_hash_map_exit(g_writer[format]->hooker);
g_writer[format]->hooker = tb_null;
// clear it
g_writer[format] = tb_null;
}
}
tb_oc_writer_t* tb_oc_writer_get(tb_size_t format)
{
// check
format &= 0x00ff;
tb_assert_and_check_return_val((format < tb_arrayn(g_writer)), tb_null);
// ok
return g_writer[format];
}
tb_long_t tb_oc_writer_done(tb_object_ref_t object, tb_stream_ref_t stream, tb_size_t format)
{
// check
tb_assert_and_check_return_val(object && stream, -1);
// the writer
tb_oc_writer_t* writer = tb_oc_writer_get(format);
tb_assert_and_check_return_val(writer && writer->writ, -1);
// writ it
return writer->writ(stream, object, (format & TB_OBJECT_FORMAT_DEFLATE)? tb_true : tb_false);
}
tbox-1.7.6/src/tbox/object/impl/writer/writer.h 0000664 0000000 0000000 00000004154 14671175054 0021472 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file writer.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_IMPL_WRITER_H
#define TB_OBJECT_IMPL_WRITER_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "xml.h"
#include "bin.h"
#include "json.h"
#include "xplist.h"
#include "bplist.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! set object writer
*
* @param format the writer format
* @param writer the writer
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_writer_set(tb_size_t format, tb_oc_writer_t* writer);
/*! get object writer
*
* @param format the writer format
*
* @return the object writer
*/
tb_oc_writer_t* tb_oc_writer_get(tb_size_t format);
/*! remove object writer
*
* @param format the writer format
*/
tb_void_t tb_oc_writer_remove(tb_size_t format);
/*! done writer
*
* @param object the object
* @param stream the stream
* @param format the object format
*
* @return the writed size, failed: -1
*/
tb_long_t tb_oc_writer_done(tb_object_ref_t object, tb_stream_ref_t stream, tb_size_t format);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/object/impl/writer/xml.c 0000664 0000000 0000000 00000041144 14671175054 0020751 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file xml.c
* @ingroup object
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "oc_writer_xml"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "xml.h"
#include "writer.h"
#include "../../../algorithm/algorithm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_bool_t tb_oc_xml_writer_func_null(tb_oc_xml_writer_t* writer, tb_object_ref_t object, tb_size_t level)
{
// check
tb_assert_and_check_return_val(writer && writer->stream, tb_false);
// write
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
// ok
return tb_true;
}
static tb_bool_t tb_oc_xml_writer_func_date(tb_oc_xml_writer_t* writer, tb_object_ref_t object, tb_size_t level)
{
// check
tb_assert_and_check_return_val(writer && writer->stream, tb_false);
// no empty?
tb_time_t time = tb_oc_date_time(object);
if (time > 0)
{
// write begin
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
// write date
tb_tm_t date = {0};
if (tb_localtime(time, &date))
{
if (tb_stream_printf(writer->stream, "%04ld-%02ld-%02ld %02ld:%02ld:%02ld"
, date.year
, date.month
, date.mday
, date.hour
, date.minute
, date.second) < 0) return tb_false;
}
// write end
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
}
else
{
// write
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
}
// ok
return tb_true;
}
static tb_bool_t tb_oc_xml_writer_func_data(tb_oc_xml_writer_t* writer, tb_object_ref_t object, tb_size_t level)
{
// check
tb_assert_and_check_return_val(writer && writer->stream, tb_false);
// no empty?
if (tb_oc_data_size(object))
{
// write begin
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
// decode base64 data
tb_byte_t const* ib = (tb_byte_t const*)tb_oc_data_getp(object);
tb_size_t in = tb_oc_data_size(object);
tb_size_t on = in << 1;
tb_char_t* ob = tb_malloc0_cstr(on);
tb_assert_and_check_return_val(ob && on, tb_false);
on = tb_base64_encode(ib, in, ob, on);
tb_trace_d("base64: %u => %u", in, on);
// write data
tb_char_t const* p = ob;
tb_char_t const* e = ob + on;
tb_size_t n = 0;
for (; p < e && *p; p++, n++)
{
if (!(n & 63))
{
if (n) if (!tb_oc_writer_newline(writer->stream, writer->deflate)) break;
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) break;
}
if (tb_stream_printf(writer->stream, "%c", *p) < 0) break;
}
// free the data
tb_free(ob);
// check
tb_check_return_val(p == e, tb_false);
// write newline
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
// write end
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
}
else
{
// write
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
}
// ok
return tb_true;
}
static tb_bool_t tb_oc_xml_writer_func_array(tb_oc_xml_writer_t* writer, tb_object_ref_t object, tb_size_t level)
{
// check
tb_assert_and_check_return_val(writer && writer->stream, tb_false);
// write
if (tb_oc_array_size(object))
{
// write begin
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
// walk
tb_for_all (tb_object_ref_t, item, tb_oc_array_itor(object))
{
// item
if (item)
{
// func
tb_oc_xml_writer_func_t func = tb_oc_xml_writer_func(item->type);
tb_assert_and_check_continue(func);
// write
if (!func(writer, item, level + 1)) return tb_false;
}
}
// write end
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
}
else
{
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
}
// ok
return tb_true;
}
static tb_bool_t tb_oc_xml_writer_func_string(tb_oc_xml_writer_t* writer, tb_object_ref_t object, tb_size_t level)
{
// check
tb_assert_and_check_return_val(writer && writer->stream, tb_false);
// write
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_oc_string_size(object))
{
if (tb_stream_printf(writer->stream, "%s", tb_oc_string_cstr(object)) < 0) return tb_false;
}
else if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
// ok
return tb_true;
}
static tb_bool_t tb_oc_xml_writer_func_number(tb_oc_xml_writer_t* writer, tb_object_ref_t object, tb_size_t level)
{
// check
tb_assert_and_check_return_val(writer && writer->stream, tb_false);
// write
switch (tb_oc_number_type(object))
{
case TB_OC_NUMBER_TYPE_UINT64:
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "%llu", tb_oc_number_uint64(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
case TB_OC_NUMBER_TYPE_SINT64:
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "%lld", tb_oc_number_sint64(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
case TB_OC_NUMBER_TYPE_UINT32:
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "%u", tb_oc_number_uint32(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
case TB_OC_NUMBER_TYPE_SINT32:
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "%d", tb_oc_number_sint32(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
case TB_OC_NUMBER_TYPE_UINT16:
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "%u", tb_oc_number_uint16(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
case TB_OC_NUMBER_TYPE_SINT16:
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "%d", tb_oc_number_sint16(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
case TB_OC_NUMBER_TYPE_UINT8:
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "%u", tb_oc_number_uint8(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
case TB_OC_NUMBER_TYPE_SINT8:
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "%d", tb_oc_number_sint8(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
case TB_OC_NUMBER_TYPE_FLOAT:
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "%f", tb_oc_number_float(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
case TB_OC_NUMBER_TYPE_DOUBLE:
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "%lf", tb_oc_number_double(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
#endif
default:
break;
}
// ok
return tb_true;
}
static tb_bool_t tb_oc_xml_writer_func_boolean(tb_oc_xml_writer_t* writer, tb_object_ref_t object, tb_size_t level)
{
// check
tb_assert_and_check_return_val(writer && writer->stream, tb_false);
// write
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "<%s/>", tb_oc_boolean_bool(object)? "true" : "false") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
// ok
return tb_true;
}
static tb_bool_t tb_oc_xml_writer_func_dictionary(tb_oc_xml_writer_t* writer, tb_object_ref_t object, tb_size_t level)
{
// check
tb_assert_and_check_return_val(writer && writer->stream, tb_false);
// write
if (tb_oc_dictionary_size(object))
{
// write begin
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
// walk
tb_for_all (tb_oc_dictionary_item_t*, item, tb_oc_dictionary_itor(object))
{
// item
if (item && item->key && item->val)
{
// func
tb_oc_xml_writer_func_t func = tb_oc_xml_writer_func(item->val->type);
tb_assert_and_check_continue(func);
// write key
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level + 1)) return tb_false;
if (tb_stream_printf(writer->stream, "%s", item->key) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
// write value
if (!func(writer, item->val, level + 1)) return tb_false;
}
}
// write end
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
}
else
{
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
}
// ok
return tb_true;
}
static tb_long_t tb_oc_xml_writer_done(tb_stream_ref_t stream, tb_object_ref_t object, tb_bool_t deflate)
{
// check
tb_assert_and_check_return_val(object && stream, -1);
// init writer
tb_oc_xml_writer_t writer = {0};
writer.stream = stream;
writer.deflate = deflate;
// func
tb_oc_xml_writer_func_t func = tb_oc_xml_writer_func(object->type);
tb_assert_and_check_return_val(func, -1);
// the begin offset
tb_hize_t bof = tb_stream_offset(stream);
// write xml header
if (tb_stream_printf(stream, "") < 0) return -1;
if (!tb_oc_writer_newline(stream, deflate)) return -1;
// write
if (!func(&writer, object, 0)) return -1;
// sync
if (!tb_stream_sync(stream, tb_true)) return -1;
// the end offset
tb_hize_t eof = tb_stream_offset(stream);
// ok?
return eof >= bof? (tb_long_t)(eof - bof) : -1;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_oc_writer_t* tb_oc_xml_writer()
{
// the writer
static tb_oc_writer_t s_writer = {0};
// init writer
s_writer.writ = tb_oc_xml_writer_done;
// init hooker
s_writer.hooker = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_uint32(), tb_element_ptr(tb_null, tb_null));
tb_assert_and_check_return_val(s_writer.hooker, tb_null);
// hook writer
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_NULL, tb_oc_xml_writer_func_null);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DATE, tb_oc_xml_writer_func_date);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DATA, tb_oc_xml_writer_func_data);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_ARRAY, tb_oc_xml_writer_func_array);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_STRING, tb_oc_xml_writer_func_string);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_NUMBER, tb_oc_xml_writer_func_number);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_BOOLEAN, tb_oc_xml_writer_func_boolean);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DICTIONARY, tb_oc_xml_writer_func_dictionary);
// ok
return &s_writer;
}
tb_bool_t tb_oc_xml_writer_hook(tb_size_t type, tb_oc_xml_writer_func_t func)
{
// check
tb_assert_and_check_return_val(func, tb_false);
// the writer
tb_oc_writer_t* writer = tb_oc_writer_get(TB_OBJECT_FORMAT_XML);
tb_assert_and_check_return_val(writer && writer->hooker, tb_false);
// hook it
tb_hash_map_insert(writer->hooker, (tb_pointer_t)type, func);
// ok
return tb_true;
}
tb_oc_xml_writer_func_t tb_oc_xml_writer_func(tb_size_t type)
{
// the writer
tb_oc_writer_t* writer = tb_oc_writer_get(TB_OBJECT_FORMAT_XML);
tb_assert_and_check_return_val(writer && writer->hooker, tb_null);
// the func
return (tb_oc_xml_writer_func_t)tb_hash_map_get(writer->hooker, (tb_pointer_t)type);
}
tbox-1.7.6/src/tbox/object/impl/writer/xml.h 0000664 0000000 0000000 00000004553 14671175054 0020761 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file xml.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_IMPL_WRITER_XML_H
#define TB_OBJECT_IMPL_WRITER_XML_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the object xml writer type
typedef struct __tb_oc_xml_writer_t
{
/// the stream
tb_stream_ref_t stream;
/// is deflate?
tb_bool_t deflate;
}tb_oc_xml_writer_t;
/// the xml writer func type
typedef tb_bool_t (*tb_oc_xml_writer_func_t)(tb_oc_xml_writer_t* writer, tb_object_ref_t object, tb_size_t level);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the xml object writer
*
* @return the xml object writer
*/
tb_oc_writer_t* tb_oc_xml_writer(tb_noarg_t);
/*! hook the xml writer
*
* @param type the object type
* @param func the writer func
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_xml_writer_hook(tb_size_t type, tb_oc_xml_writer_func_t func);
/*! the xml writer func
*
* @param type the object type
*
* @return the object writer func
*/
tb_oc_xml_writer_func_t tb_oc_xml_writer_func(tb_size_t type);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/object/impl/writer/xplist.c 0000664 0000000 0000000 00000041461 14671175054 0021476 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file xplist.c
* @ingroup object
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "oc_writer_xplist"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "xplist.h"
#include "writer.h"
#include "../../../algorithm/algorithm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_bool_t tb_oc_xplist_writer_func_date(tb_oc_xplist_writer_t* writer, tb_object_ref_t object, tb_size_t level)
{
// check
tb_assert_and_check_return_val(writer && writer->stream, tb_false);
// no empty?
tb_time_t time = tb_oc_date_time(object);
if (time > 0)
{
// write begin
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
// write date
tb_tm_t date = {0};
if (tb_localtime(time, &date))
{
if (tb_stream_printf(writer->stream, "%04ld-%02ld-%02ldT%02ld:%02ld:%02ldZ"
, date.year
, date.month
, date.mday
, date.hour
, date.minute
, date.second) < 0) return tb_false;
}
// write end
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
}
else
{
// write
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
}
// ok
return tb_true;
}
static tb_bool_t tb_oc_xplist_writer_func_data(tb_oc_xplist_writer_t* writer, tb_object_ref_t object, tb_size_t level)
{
// check
tb_assert_and_check_return_val(writer && writer->stream, tb_false);
// no empty?
if (tb_oc_data_size(object))
{
// write begin
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
// decode base64 data
tb_byte_t const* ib = (tb_byte_t const*)tb_oc_data_getp(object);
tb_size_t in = tb_oc_data_size(object);
tb_size_t on = in << 1;
tb_char_t* ob = tb_malloc0_cstr(on);
tb_assert_and_check_return_val(ob && on, tb_false);
on = tb_base64_encode(ib, in, ob, on);
tb_trace_d("base64: %u => %u", in, on);
// write data
tb_char_t const* p = ob;
tb_char_t const* e = ob + on;
tb_size_t n = 0;
for (; p < e && *p; p++, n++)
{
if (!(n % 68))
{
if (n) if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
}
if (tb_stream_printf(writer->stream, "%c", *p) < 0) return tb_false;
}
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
// free it
tb_free(ob);
// write end
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
}
else
{
// write
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
}
// ok
return tb_true;
}
static tb_bool_t tb_oc_xplist_writer_func_array(tb_oc_xplist_writer_t* writer, tb_object_ref_t object, tb_size_t level)
{
// check
tb_assert_and_check_return_val(writer && writer->stream, tb_false);
// write
if (tb_oc_array_size(object))
{
// write begin
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
// walk
tb_for_all (tb_object_ref_t, item, tb_oc_array_itor(object))
{
// item
if (item)
{
// func
tb_oc_xplist_writer_func_t func = tb_oc_xplist_writer_func(item->type);
tb_assert_and_check_continue(func);
// write
if (!func(writer, item, level + 1)) return tb_false;
}
}
// write end
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
}
else
{
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
}
// ok
return tb_true;
}
static tb_bool_t tb_oc_xplist_writer_func_string(tb_oc_xplist_writer_t* writer, tb_object_ref_t object, tb_size_t level)
{
// check
tb_assert_and_check_return_val(writer && writer->stream, tb_false);
// write
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_oc_string_size(object))
{
if (tb_stream_printf(writer->stream, "%s", tb_oc_string_cstr(object)) < 0) return tb_false;
}
else if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
// ok
return tb_true;
}
static tb_bool_t tb_oc_xplist_writer_func_number(tb_oc_xplist_writer_t* writer, tb_object_ref_t object, tb_size_t level)
{
// check
tb_assert_and_check_return_val(writer && writer->stream, tb_false);
// write
switch (tb_oc_number_type(object))
{
case TB_OC_NUMBER_TYPE_UINT64:
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "%llu", tb_oc_number_uint64(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
case TB_OC_NUMBER_TYPE_SINT64:
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "%lld", tb_oc_number_sint64(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
case TB_OC_NUMBER_TYPE_UINT32:
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "%u", tb_oc_number_uint32(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
case TB_OC_NUMBER_TYPE_SINT32:
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "%d", tb_oc_number_sint32(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
case TB_OC_NUMBER_TYPE_UINT16:
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "%u", tb_oc_number_uint16(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
case TB_OC_NUMBER_TYPE_SINT16:
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "%d", tb_oc_number_sint16(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
case TB_OC_NUMBER_TYPE_UINT8:
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "%u", tb_oc_number_uint8(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
case TB_OC_NUMBER_TYPE_SINT8:
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "%d", tb_oc_number_sint8(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
case TB_OC_NUMBER_TYPE_FLOAT:
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "%f", tb_oc_number_float(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
case TB_OC_NUMBER_TYPE_DOUBLE:
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "%lf", tb_oc_number_double(object)) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
break;
#endif
default:
break;
}
// ok
return tb_true;
}
static tb_bool_t tb_oc_xplist_writer_func_boolean(tb_oc_xplist_writer_t* writer, tb_object_ref_t object, tb_size_t level)
{
// check
tb_assert_and_check_return_val(writer && writer->stream, tb_false);
// write
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "<%s/>", tb_oc_boolean_bool(object)? "true" : "false") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
// ok
return tb_true;
}
static tb_bool_t tb_oc_xplist_writer_func_dictionary(tb_oc_xplist_writer_t* writer, tb_object_ref_t object, tb_size_t level)
{
// check
tb_assert_and_check_return_val(writer && writer->stream, tb_false);
// write
if (tb_oc_dictionary_size(object))
{
// write begin
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
// walk
tb_for_all (tb_oc_dictionary_item_t*, item, tb_oc_dictionary_itor(object))
{
// item
if (item && item->key && item->val)
{
// func
tb_oc_xplist_writer_func_t func = tb_oc_xplist_writer_func(item->val->type);
tb_assert_and_check_continue(func);
// write key
tb_oc_writer_tab(writer->stream, writer->deflate, level + 1);
if (tb_stream_printf(writer->stream, "%s", item->key) < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
// write value
if (!func(writer, item->val, level + 1)) return tb_false;
}
}
// write end
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
}
else
{
if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
if (tb_stream_printf(writer->stream, "") < 0) return tb_false;
if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
}
// ok
return tb_true;
}
static tb_long_t tb_oc_xplist_writer_done(tb_stream_ref_t stream, tb_object_ref_t object, tb_bool_t deflate)
{
// check
tb_assert_and_check_return_val(object && stream, -1);
// init writer
tb_oc_xplist_writer_t writer = {0};
writer.stream = stream;
writer.deflate = deflate;
// func
tb_oc_xplist_writer_func_t func = tb_oc_xplist_writer_func(object->type);
tb_assert_and_check_return_val(func, -1);
// the begin offset
tb_hize_t bof = tb_stream_offset(stream);
// write xplist header
if (tb_stream_printf(stream, "") < 0) return -1;
if (!tb_oc_writer_newline(stream, deflate)) return -1;
if (tb_stream_printf(stream, "") < 0) return -1;
if (!tb_oc_writer_newline(stream, deflate)) return -1;
if (tb_stream_printf(stream, "") < 0) return -1;
if (!tb_oc_writer_newline(stream, deflate)) return -1;
// write
if (!func(&writer, object, 0)) return -1;
// write xplist end
if (tb_stream_printf(stream, "") < 0) return -1;
if (!tb_oc_writer_newline(stream, deflate)) return -1;
// sync
if (!tb_stream_sync(stream, tb_true)) return -1;
// the end offset
tb_hize_t eof = tb_stream_offset(stream);
// ok?
return eof >= bof? (tb_long_t)(eof - bof) : -1;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_oc_writer_t* tb_oc_xplist_writer()
{
// the writer
static tb_oc_writer_t s_writer = {0};
// init writer
s_writer.writ = tb_oc_xplist_writer_done;
// init hooker
s_writer.hooker = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_uint32(), tb_element_ptr(tb_null, tb_null));
tb_assert_and_check_return_val(s_writer.hooker, tb_null);
// hook writer
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DATE, tb_oc_xplist_writer_func_date);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DATA, tb_oc_xplist_writer_func_data);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_ARRAY, tb_oc_xplist_writer_func_array);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_STRING, tb_oc_xplist_writer_func_string);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_NUMBER, tb_oc_xplist_writer_func_number);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_BOOLEAN, tb_oc_xplist_writer_func_boolean);
tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DICTIONARY, tb_oc_xplist_writer_func_dictionary);
// ok
return &s_writer;
}
tb_bool_t tb_oc_xplist_writer_hook(tb_size_t type, tb_oc_xplist_writer_func_t func)
{
// check
tb_assert_and_check_return_val(func, tb_false);
// the writer
tb_oc_writer_t* writer = tb_oc_writer_get(TB_OBJECT_FORMAT_XPLIST);
tb_assert_and_check_return_val(writer && writer->hooker, tb_false);
// hook it
tb_hash_map_insert(writer->hooker, (tb_pointer_t)type, func);
// ok
return tb_true;
}
tb_oc_xplist_writer_func_t tb_oc_xplist_writer_func(tb_size_t type)
{
// the writer
tb_oc_writer_t* writer = tb_oc_writer_get(TB_OBJECT_FORMAT_XPLIST);
tb_assert_and_check_return_val(writer && writer->hooker, tb_null);
// the func
return (tb_oc_xplist_writer_func_t)tb_hash_map_get(writer->hooker, (tb_pointer_t)type);
}
tbox-1.7.6/src/tbox/object/impl/writer/xplist.h 0000664 0000000 0000000 00000004636 14671175054 0021506 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file xplist.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_IMPL_WRITER_XPLIST_H
#define TB_OBJECT_IMPL_WRITER_XPLIST_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the object xplist writer type
typedef struct __tb_oc_xplist_writer_t
{
/// the stream
tb_stream_ref_t stream;
/// is deflate?
tb_bool_t deflate;
}tb_oc_xplist_writer_t;
/// the xplist writer func type
typedef tb_bool_t (*tb_oc_xplist_writer_func_t)(tb_oc_xplist_writer_t* writer, tb_object_ref_t object, tb_size_t level);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the xplist object writer
*
* @return the xplist object writer
*/
tb_oc_writer_t* tb_oc_xplist_writer(tb_noarg_t);
/*! hook the xplist writer
*
* @param type the object type
* @param func the writer func
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_xplist_writer_hook(tb_size_t type, tb_oc_xplist_writer_func_t func);
/*! the xplist writer func
*
* @param type the object type
*
* @return the object writer func
*/
tb_oc_xplist_writer_func_t tb_oc_xplist_writer_func(tb_size_t type);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/object/null.c 0000664 0000000 0000000 00000003267 14671175054 0016652 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file null.c
* @ingroup object
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "oc_null"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "object.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_object_ref_t tb_oc_null_copy(tb_object_ref_t object)
{
return object;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
// null
static tb_object_t const g_null =
{
TB_OBJECT_FLAG_READONLY | TB_OBJECT_FLAG_SINGLETON
, TB_OBJECT_TYPE_NULL
, 1
, tb_null
, tb_oc_null_copy
, tb_null
, tb_null
};
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_object_ref_t tb_oc_null_init()
{
return (tb_object_ref_t)&g_null;
}
tbox-1.7.6/src/tbox/object/null.h 0000664 0000000 0000000 00000002542 14671175054 0016652 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file null.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_NULL_H
#define TB_OBJECT_NULL_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init null
*
* @return the null object
*/
tb_object_ref_t tb_oc_null_init(tb_noarg_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/object/number.c 0000664 0000000 0000000 00000041510 14671175054 0017161 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file number.c
* @ingroup object
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "oc_number"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "object.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the number type
typedef struct __tb_oc_number_t
{
// the object base
tb_object_t base;
// the number type
tb_size_t type;
// the number value
union
{
// the uint8
tb_uint8_t u8;
// the sint8
tb_sint8_t s8;
// the uint16
tb_uint16_t u16;
// the sint16
tb_sint16_t s16;
// the uint32
tb_uint32_t u32;
// the sint32
tb_sint32_t s32;
// the uint64
tb_uint64_t u64;
// the sint64
tb_sint64_t s64;
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
// the float
tb_float_t f;
// the double
tb_double_t d;
#endif
}v;
}tb_oc_number_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static __tb_inline__ tb_oc_number_t* tb_oc_number_cast(tb_object_ref_t object)
{
// check
tb_assert_and_check_return_val(object && object->type == TB_OBJECT_TYPE_NUMBER, tb_null);
// cast
return (tb_oc_number_t*)object;
}
static tb_object_ref_t tb_oc_number_copy(tb_object_ref_t object)
{
// check
tb_oc_number_t* number = (tb_oc_number_t*)object;
tb_assert_and_check_return_val(number, tb_null);
// copy
switch (number->type)
{
case TB_OC_NUMBER_TYPE_UINT64:
return tb_oc_number_init_from_uint64(number->v.u64);
case TB_OC_NUMBER_TYPE_SINT64:
return tb_oc_number_init_from_sint64(number->v.s64);
case TB_OC_NUMBER_TYPE_UINT32:
return tb_oc_number_init_from_uint32(number->v.u32);
case TB_OC_NUMBER_TYPE_SINT32:
return tb_oc_number_init_from_sint32(number->v.s32);
case TB_OC_NUMBER_TYPE_UINT16:
return tb_oc_number_init_from_uint16(number->v.u16);
case TB_OC_NUMBER_TYPE_SINT16:
return tb_oc_number_init_from_sint16(number->v.s16);
case TB_OC_NUMBER_TYPE_UINT8:
return tb_oc_number_init_from_uint8(number->v.u8);
case TB_OC_NUMBER_TYPE_SINT8:
return tb_oc_number_init_from_sint8(number->v.s8);
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
case TB_OC_NUMBER_TYPE_FLOAT:
return tb_oc_number_init_from_float(number->v.f);
case TB_OC_NUMBER_TYPE_DOUBLE:
return tb_oc_number_init_from_double(number->v.d);
#endif
default:
break;
}
return tb_null;
}
static tb_void_t tb_oc_number_exit(tb_object_ref_t object)
{
if (object) tb_free(object);
}
static tb_void_t tb_oc_number_clear(tb_object_ref_t object)
{
// check
tb_oc_number_t* number = (tb_oc_number_t*)object;
tb_assert_and_check_return(number);
// clear
switch (number->type)
{
case TB_OC_NUMBER_TYPE_UINT64:
number->v.u64 = 0;
break;
case TB_OC_NUMBER_TYPE_SINT64:
number->v.s64 = 0;
break;
case TB_OC_NUMBER_TYPE_UINT32:
number->v.u32 = 0;
break;
case TB_OC_NUMBER_TYPE_SINT32:
number->v.s32 = 0;
break;
case TB_OC_NUMBER_TYPE_UINT16:
number->v.u16 = 0;
break;
case TB_OC_NUMBER_TYPE_SINT16:
number->v.s16 = 0;
break;
case TB_OC_NUMBER_TYPE_UINT8:
number->v.u8 = 0;
break;
case TB_OC_NUMBER_TYPE_SINT8:
number->v.s8 = 0;
break;
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
case TB_OC_NUMBER_TYPE_FLOAT:
number->v.f = 0.;
break;
case TB_OC_NUMBER_TYPE_DOUBLE:
number->v.d = 0.;
break;
#endif
default:
break;
}
}
static tb_oc_number_t* tb_oc_number_init_base()
{
// done
tb_bool_t ok = tb_false;
tb_oc_number_t* number = tb_null;
do
{
// make number
number = tb_malloc0_type(tb_oc_number_t);
tb_assert_and_check_break(number);
// init number
if (!tb_object_init((tb_object_ref_t)number, TB_OBJECT_FLAG_NONE, TB_OBJECT_TYPE_NUMBER)) break;
// init base
number->base.copy = tb_oc_number_copy;
number->base.exit = tb_oc_number_exit;
number->base.clear = tb_oc_number_clear;
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (number) tb_object_exit((tb_object_ref_t)number);
number = tb_null;
}
// ok?
return number;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_object_ref_t tb_oc_number_init_from_uint8(tb_uint8_t value)
{
// make
tb_oc_number_t* number = tb_oc_number_init_base();
tb_assert_and_check_return_val(number, tb_null);
// init value
number->type = TB_OC_NUMBER_TYPE_UINT8;
number->v.u8 = value;
// ok
return (tb_object_ref_t)number;
}
tb_object_ref_t tb_oc_number_init_from_sint8(tb_sint8_t value)
{
// make
tb_oc_number_t* number = tb_oc_number_init_base();
tb_assert_and_check_return_val(number, tb_null);
// init value
number->type = TB_OC_NUMBER_TYPE_SINT8;
number->v.s8 = value;
// ok
return (tb_object_ref_t)number;
}
tb_object_ref_t tb_oc_number_init_from_uint16(tb_uint16_t value)
{
// make
tb_oc_number_t* number = tb_oc_number_init_base();
tb_assert_and_check_return_val(number, tb_null);
// init value
number->type = TB_OC_NUMBER_TYPE_UINT16;
number->v.u16 = value;
// ok
return (tb_object_ref_t)number;
}
tb_object_ref_t tb_oc_number_init_from_sint16(tb_sint16_t value)
{
// make
tb_oc_number_t* number = tb_oc_number_init_base();
tb_assert_and_check_return_val(number, tb_null);
// init value
number->type = TB_OC_NUMBER_TYPE_SINT16;
number->v.s16 = value;
// ok
return (tb_object_ref_t)number;
}
tb_object_ref_t tb_oc_number_init_from_uint32(tb_uint32_t value)
{
// make
tb_oc_number_t* number = tb_oc_number_init_base();
tb_assert_and_check_return_val(number, tb_null);
// init value
number->type = TB_OC_NUMBER_TYPE_UINT32;
number->v.u32 = value;
// ok
return (tb_object_ref_t)number;
}
tb_object_ref_t tb_oc_number_init_from_sint32(tb_sint32_t value)
{
// make
tb_oc_number_t* number = tb_oc_number_init_base();
tb_assert_and_check_return_val(number, tb_null);
// init value
number->type = TB_OC_NUMBER_TYPE_SINT32;
number->v.s32 = value;
// ok
return (tb_object_ref_t)number;
}
tb_object_ref_t tb_oc_number_init_from_uint64(tb_uint64_t value)
{
// make
tb_oc_number_t* number = tb_oc_number_init_base();
tb_assert_and_check_return_val(number, tb_null);
// init value
number->type = TB_OC_NUMBER_TYPE_UINT64;
number->v.u64 = value;
// ok
return (tb_object_ref_t)number;
}
tb_object_ref_t tb_oc_number_init_from_sint64(tb_sint64_t value)
{
// make
tb_oc_number_t* number = tb_oc_number_init_base();
tb_assert_and_check_return_val(number, tb_null);
// init value
number->type = TB_OC_NUMBER_TYPE_SINT64;
number->v.s64 = value;
// ok
return (tb_object_ref_t)number;
}
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
tb_object_ref_t tb_oc_number_init_from_float(tb_float_t value)
{
// make
tb_oc_number_t* number = tb_oc_number_init_base();
tb_assert_and_check_return_val(number, tb_null);
// init value
number->type = TB_OC_NUMBER_TYPE_FLOAT;
number->v.f = value;
// ok
return (tb_object_ref_t)number;
}
tb_object_ref_t tb_oc_number_init_from_double(tb_double_t value)
{
// make
tb_oc_number_t* number = tb_oc_number_init_base();
tb_assert_and_check_return_val(number, tb_null);
// init value
number->type = TB_OC_NUMBER_TYPE_DOUBLE;
number->v.d = value;
// ok
return (tb_object_ref_t)number;
}
#endif
tb_size_t tb_oc_number_type(tb_object_ref_t object)
{
// check
tb_oc_number_t* number = tb_oc_number_cast(object);
tb_assert_and_check_return_val(number, TB_OC_NUMBER_TYPE_NONE);
// type
return number->type;
}
tb_uint8_t tb_oc_number_uint8(tb_object_ref_t object)
{
return (tb_uint8_t)tb_oc_number_uint64(object);
}
tb_sint8_t tb_oc_number_sint8(tb_object_ref_t object)
{
return (tb_sint8_t)tb_oc_number_sint64(object);
}
tb_uint16_t tb_oc_number_uint16(tb_object_ref_t object)
{
return (tb_uint16_t)tb_oc_number_uint64(object);
}
tb_sint16_t tb_oc_number_sint16(tb_object_ref_t object)
{
return (tb_sint16_t)tb_oc_number_sint64(object);
}
tb_uint32_t tb_oc_number_uint32(tb_object_ref_t object)
{
return (tb_uint32_t)tb_oc_number_uint64(object);
}
tb_sint32_t tb_oc_number_sint32(tb_object_ref_t object)
{
return (tb_sint32_t)tb_oc_number_sint64(object);
}
tb_uint64_t tb_oc_number_uint64(tb_object_ref_t object)
{
// check
tb_oc_number_t* number = tb_oc_number_cast(object);
tb_assert_and_check_return_val(number, 0);
// uint64
switch (number->type)
{
case TB_OC_NUMBER_TYPE_UINT64:
return number->v.u64;
case TB_OC_NUMBER_TYPE_SINT64:
return number->v.s64;
case TB_OC_NUMBER_TYPE_UINT32:
return number->v.u32;
case TB_OC_NUMBER_TYPE_SINT32:
return number->v.s32;
case TB_OC_NUMBER_TYPE_UINT16:
return number->v.u16;
case TB_OC_NUMBER_TYPE_SINT16:
return number->v.s16;
case TB_OC_NUMBER_TYPE_UINT8:
return number->v.u8;
case TB_OC_NUMBER_TYPE_SINT8:
return number->v.s8;
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
case TB_OC_NUMBER_TYPE_FLOAT:
return (tb_uint64_t)number->v.f;
case TB_OC_NUMBER_TYPE_DOUBLE:
return (tb_uint64_t)number->v.d;
#endif
default:
break;
}
tb_assert(0);
return 0;
}
tb_sint64_t tb_oc_number_sint64(tb_object_ref_t object)
{
// check
tb_oc_number_t* number = tb_oc_number_cast(object);
tb_assert_and_check_return_val(number, 0);
// sint64
switch (number->type)
{
case TB_OC_NUMBER_TYPE_UINT64:
return number->v.u64;
case TB_OC_NUMBER_TYPE_SINT64:
return number->v.s64;
case TB_OC_NUMBER_TYPE_UINT32:
return number->v.u32;
case TB_OC_NUMBER_TYPE_SINT32:
return number->v.s32;
case TB_OC_NUMBER_TYPE_UINT16:
return number->v.u16;
case TB_OC_NUMBER_TYPE_SINT16:
return number->v.s16;
case TB_OC_NUMBER_TYPE_UINT8:
return number->v.u8;
case TB_OC_NUMBER_TYPE_SINT8:
return number->v.s8;
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
case TB_OC_NUMBER_TYPE_FLOAT:
return (tb_sint64_t)number->v.f;
case TB_OC_NUMBER_TYPE_DOUBLE:
return (tb_sint64_t)number->v.d;
#endif
default:
break;
}
tb_assert(0);
return 0;
}
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
tb_float_t tb_oc_number_float(tb_object_ref_t object)
{
// check
tb_oc_number_t* number = tb_oc_number_cast(object);
tb_assert_and_check_return_val(number, 0);
// float
switch (number->type)
{
case TB_OC_NUMBER_TYPE_FLOAT:
return number->v.f;
case TB_OC_NUMBER_TYPE_DOUBLE:
return (tb_float_t)number->v.d;
case TB_OC_NUMBER_TYPE_UINT8:
return (tb_float_t)number->v.u8;
case TB_OC_NUMBER_TYPE_SINT8:
return (tb_float_t)number->v.s8;
case TB_OC_NUMBER_TYPE_UINT16:
return (tb_float_t)number->v.u16;
case TB_OC_NUMBER_TYPE_SINT16:
return (tb_float_t)number->v.s16;
case TB_OC_NUMBER_TYPE_UINT32:
return (tb_float_t)number->v.u32;
case TB_OC_NUMBER_TYPE_SINT32:
return (tb_float_t)number->v.s32;
case TB_OC_NUMBER_TYPE_UINT64:
return (tb_float_t)number->v.u64;
case TB_OC_NUMBER_TYPE_SINT64:
return (tb_float_t)number->v.s64;
default:
break;
}
tb_assert(0);
return 0;
}
tb_double_t tb_oc_number_double(tb_object_ref_t object)
{
// check
tb_oc_number_t* number = tb_oc_number_cast(object);
tb_assert_and_check_return_val(number, 0);
// double
switch (number->type)
{
case TB_OC_NUMBER_TYPE_DOUBLE:
return number->v.d;
case TB_OC_NUMBER_TYPE_FLOAT:
return (tb_double_t)number->v.f;
case TB_OC_NUMBER_TYPE_UINT8:
return (tb_double_t)number->v.u8;
case TB_OC_NUMBER_TYPE_SINT8:
return (tb_double_t)number->v.s8;
case TB_OC_NUMBER_TYPE_UINT16:
return (tb_double_t)number->v.u16;
case TB_OC_NUMBER_TYPE_SINT16:
return (tb_double_t)number->v.s16;
case TB_OC_NUMBER_TYPE_UINT32:
return (tb_double_t)number->v.u32;
case TB_OC_NUMBER_TYPE_SINT32:
return (tb_double_t)number->v.s32;
case TB_OC_NUMBER_TYPE_UINT64:
return (tb_double_t)number->v.u64;
case TB_OC_NUMBER_TYPE_SINT64:
return (tb_double_t)number->v.s64;
default:
break;
}
tb_assert(0);
return 0;
}
#endif
tb_bool_t tb_oc_number_uint8_set(tb_object_ref_t object, tb_uint8_t value)
{
// check
tb_oc_number_t* number = tb_oc_number_cast(object);
tb_assert_and_check_return_val(number, tb_false);
// init value
number->type = TB_OC_NUMBER_TYPE_UINT8;
number->v.u8 = value;
// ok
return tb_true;
}
tb_bool_t tb_oc_number_sint8_set(tb_object_ref_t object, tb_sint8_t value)
{
// check
tb_oc_number_t* number = tb_oc_number_cast(object);
tb_assert_and_check_return_val(number, tb_false);
// init value
number->type = TB_OC_NUMBER_TYPE_SINT8;
number->v.s8 = value;
// ok
return tb_true;
}
tb_bool_t tb_oc_number_uint16_set(tb_object_ref_t object, tb_uint16_t value)
{
// check
tb_oc_number_t* number = tb_oc_number_cast(object);
tb_assert_and_check_return_val(number, tb_false);
// init value
number->type = TB_OC_NUMBER_TYPE_UINT16;
number->v.u16 = value;
// ok
return tb_true;
}
tb_bool_t tb_oc_number_sint16_set(tb_object_ref_t object, tb_sint16_t value)
{
// check
tb_oc_number_t* number = tb_oc_number_cast(object);
tb_assert_and_check_return_val(number, tb_false);
// init value
number->type = TB_OC_NUMBER_TYPE_SINT16;
number->v.s16 = value;
// ok
return tb_true;
}
tb_bool_t tb_oc_number_uint32_set(tb_object_ref_t object, tb_uint32_t value)
{
// check
tb_oc_number_t* number = tb_oc_number_cast(object);
tb_assert_and_check_return_val(number, tb_false);
// init value
number->type = TB_OC_NUMBER_TYPE_UINT32;
number->v.u32 = value;
// ok
return tb_true;
}
tb_bool_t tb_oc_number_sint32_set(tb_object_ref_t object, tb_sint32_t value)
{
// check
tb_oc_number_t* number = tb_oc_number_cast(object);
tb_assert_and_check_return_val(number, tb_false);
// init value
number->type = TB_OC_NUMBER_TYPE_SINT32;
number->v.s32 = value;
// ok
return tb_true;
}
tb_bool_t tb_oc_number_uint64_set(tb_object_ref_t object, tb_uint64_t value)
{
// check
tb_oc_number_t* number = tb_oc_number_cast(object);
tb_assert_and_check_return_val(number, tb_false);
// init value
number->type = TB_OC_NUMBER_TYPE_UINT64;
number->v.u64 = value;
// ok
return tb_true;
}
tb_bool_t tb_oc_number_sint64_set(tb_object_ref_t object, tb_sint64_t value)
{
// check
tb_oc_number_t* number = tb_oc_number_cast(object);
tb_assert_and_check_return_val(number, tb_false);
// init value
number->type = TB_OC_NUMBER_TYPE_SINT64;
number->v.s64 = value;
// ok
return tb_true;
}
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
tb_bool_t tb_oc_number_float_set(tb_object_ref_t object, tb_float_t value)
{
// check
tb_oc_number_t* number = tb_oc_number_cast(object);
tb_assert_and_check_return_val(number, tb_false);
// init value
number->type = TB_OC_NUMBER_TYPE_FLOAT;
number->v.f = value;
// ok
return tb_true;
}
tb_bool_t tb_oc_number_double_set(tb_object_ref_t object, tb_double_t value)
{
// check
tb_oc_number_t* number = tb_oc_number_cast(object);
tb_assert_and_check_return_val(number, tb_false);
// init value
number->type = TB_OC_NUMBER_TYPE_DOUBLE;
number->v.d = value;
// ok
return tb_true;
}
#endif
tbox-1.7.6/src/tbox/object/number.h 0000664 0000000 0000000 00000017736 14671175054 0017203 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file number.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_NUMBER_H
#define TB_OBJECT_NUMBER_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the number type enum
typedef enum __tb_oc_number_type_e
{
TB_OC_NUMBER_TYPE_NONE = 0
, TB_OC_NUMBER_TYPE_UINT8 = 1
, TB_OC_NUMBER_TYPE_SINT8 = 2
, TB_OC_NUMBER_TYPE_UINT16 = 3
, TB_OC_NUMBER_TYPE_SINT16 = 4
, TB_OC_NUMBER_TYPE_UINT32 = 5
, TB_OC_NUMBER_TYPE_SINT32 = 6
, TB_OC_NUMBER_TYPE_UINT64 = 7
, TB_OC_NUMBER_TYPE_SINT64 = 8
, TB_OC_NUMBER_TYPE_FLOAT = 9
, TB_OC_NUMBER_TYPE_DOUBLE = 10
}tb_oc_number_type_e;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init number from uint8
*
* @param value the value
*
* @return the number object
*/
tb_object_ref_t tb_oc_number_init_from_uint8(tb_uint8_t value);
/*! init number from sint8
*
* @param value the value
*
* @return the number object
*/
tb_object_ref_t tb_oc_number_init_from_sint8(tb_sint8_t value);
/*! init number from uint16
*
* @param value the value
*
* @return the number object
*/
tb_object_ref_t tb_oc_number_init_from_uint16(tb_uint16_t value);
/*! init number from sint16
*
* @param value the value
*
* @return the number object
*/
tb_object_ref_t tb_oc_number_init_from_sint16(tb_sint16_t value);
/*! init number from uint32
*
* @param value the value
*
* @return the number object
*/
tb_object_ref_t tb_oc_number_init_from_uint32(tb_uint32_t value);
/*! init number from sint32
*
* @param value the value
*
* @return the number object
*/
tb_object_ref_t tb_oc_number_init_from_sint32(tb_sint32_t value);
/*! init number from uint64
*
* @param value the value
*
* @return the number object
*/
tb_object_ref_t tb_oc_number_init_from_uint64(tb_uint64_t value);
/*! init number from sint64
*
* @param value the value
*
* @return the number object
*/
tb_object_ref_t tb_oc_number_init_from_sint64(tb_sint64_t value);
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
/*! init number from float
*
* @param value the value
*
* @return the number object
*/
tb_object_ref_t tb_oc_number_init_from_float(tb_float_t value);
/*! init number from double
*
* @param value the value
*
* @return the number object
*/
tb_object_ref_t tb_oc_number_init_from_double(tb_double_t value);
#endif
/*! the number type
*
* @param number the object pointer
*
* @return the number type
*/
tb_size_t tb_oc_number_type(tb_object_ref_t number);
/*! the uint8 value of the number
*
* @param number the object pointer
*
* @return the number value
*/
tb_uint8_t tb_oc_number_uint8(tb_object_ref_t number);
/*! the sint8 value of the number
*
* @param number the object pointer
*
* @return the number value
*/
tb_sint8_t tb_oc_number_sint8(tb_object_ref_t number);
/*! the uint16 value of the number
*
* @param number the object pointer
*
* @return the number value
*/
tb_uint16_t tb_oc_number_uint16(tb_object_ref_t number);
/*! the sint16 value of the number
*
* @param number the object pointer
*
* @return the number value
*/
tb_sint16_t tb_oc_number_sint16(tb_object_ref_t number);
/*! the uint32 value of the number
*
* @param number the object pointer
*
* @return the number value
*/
tb_uint32_t tb_oc_number_uint32(tb_object_ref_t number);
/*! the sint32 value of the number
*
* @param number the object pointer
*
* @return the number value
*/
tb_sint32_t tb_oc_number_sint32(tb_object_ref_t number);
/*! the uint64 value of the number
*
* @param number the object pointer
*
* @return the number value
*/
tb_uint64_t tb_oc_number_uint64(tb_object_ref_t number);
/*! the sint64 value of the number
*
* @param number the object pointer
*
* @return the number value
*/
tb_sint64_t tb_oc_number_sint64(tb_object_ref_t number);
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
/*! the float value of the number
*
* @param number the object pointer
*
* @return the number value
*/
tb_float_t tb_oc_number_float(tb_object_ref_t number);
/*! the double value of the number
*
* @param number the object pointer
*
* @return the number value
*/
tb_double_t tb_oc_number_double(tb_object_ref_t number);
#endif
/*! set the uint8 value
*
* @param number the object pointer
* @param value the number value
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_number_uint8_set(tb_object_ref_t number, tb_uint8_t value);
/*! set the sint8 value
*
* @param number the object pointer
* @param value the number value
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_number_sint8_set(tb_object_ref_t number, tb_sint8_t value);
/*! set the uint16 value
*
* @param number the object pointer
* @param value the number value
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_number_uint16_set(tb_object_ref_t number, tb_uint16_t value);
/*! set the sint16 value
*
* @param number the object pointer
* @param value the number value
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_number_sint16_set(tb_object_ref_t number, tb_sint16_t value);
/*! set the uint32 value
*
* @param number the object pointer
* @param value the number value
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_number_uint32_set(tb_object_ref_t number, tb_uint32_t value);
/*! set the sint32 value
*
* @param number the object pointer
* @param value the number value
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_number_sint32_set(tb_object_ref_t number, tb_sint32_t value);
/*! set the uint64 value
*
* @param number the object pointer
* @param value the number value
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_number_uint64_set(tb_object_ref_t number, tb_uint64_t value);
/*! set the sint64 value
*
* @param number the object pointer
* @param value the number value
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_number_sint64_set(tb_object_ref_t number, tb_sint64_t value);
#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
/*! set the float value
*
* @param number the object pointer
* @param value the number value
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_number_float_set(tb_object_ref_t number, tb_float_t value);
/*! set the double value
*
* @param number the object pointer
* @param value the number value
*
* @return tb_true or tb_false
*/
tb_bool_t tb_oc_number_double_set(tb_object_ref_t number, tb_double_t value);
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/object/object.c 0000664 0000000 0000000 00000024663 14671175054 0017151 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file object.c
* @ingroup object
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "object"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "object.h"
#include "impl/impl.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_object_init(tb_object_ref_t object, tb_size_t flag, tb_size_t type)
{
// check
tb_assert_and_check_return_val(object, tb_false);
// init
tb_memset(object, 0, sizeof(tb_object_t));
object->flag = (tb_uint8_t)flag;
object->type = (tb_uint16_t)type;
object->refn = 1;
// ok
return tb_true;
}
tb_void_t tb_object_exit(tb_object_ref_t object)
{
// check
tb_assert_and_check_return(object);
// readonly?
tb_check_return(!(object->flag & TB_OBJECT_FLAG_READONLY));
// check refn
tb_assert_and_check_return(object->refn);
// refn--
object->refn--;
// exit it?
if (!object->refn && object->exit) object->exit(object);
}
tb_void_t tb_object_clear(tb_object_ref_t object)
{
// check
tb_assert_and_check_return(object);
// readonly?
tb_check_return(!(object->flag & TB_OBJECT_FLAG_READONLY));
// clear
if (object->clear) object->clear(object);
}
tb_void_t tb_object_setp(tb_object_ref_t object, tb_cpointer_t priv)
{
// check
tb_assert_and_check_return(object);
// set it
object->priv = priv;
}
tb_cpointer_t tb_object_getp(tb_object_ref_t object)
{
// check
tb_assert_and_check_return_val(object, tb_null);
// get it
return object->priv;
}
tb_object_ref_t tb_object_copy(tb_object_ref_t object)
{
// check
tb_assert_and_check_return_val(object && object->copy, tb_null);
// copy
return object->copy(object);
}
tb_size_t tb_object_type(tb_object_ref_t object)
{
// check
tb_assert_and_check_return_val(object, TB_OBJECT_TYPE_NONE);
// the object type
return object->type;
}
tb_object_ref_t tb_object_data(tb_object_ref_t object, tb_size_t format)
{
// check
tb_assert_and_check_return_val(object, tb_null);
// done
tb_object_ref_t odata = tb_null;
tb_size_t maxn = TB_STREAM_BLOCK_MAXN;
tb_byte_t* data = tb_null;
do
{
// make data
data = data? (tb_byte_t*)tb_ralloc(data, maxn) : tb_malloc_bytes(maxn);
tb_assert_and_check_break(data);
// writ object to data
tb_long_t size = tb_object_writ_to_data(object, data, maxn, format);
// ok? make the data object
if (size >= 0) odata = tb_oc_data_init_from_data(data, size);
// failed? grow it
else maxn <<= 1;
} while (!odata);
// exit data
if (data) tb_free(data);
data = tb_null;
// ok?
return odata;
}
tb_object_ref_t tb_object_seek(tb_object_ref_t object, tb_char_t const* path, tb_bool_t bmacro)
{
// check
tb_assert_and_check_return_val(object, tb_null);
// null?
tb_check_return_val(path, object);
// done
tb_object_ref_t root = object;
tb_char_t const* p = path;
tb_char_t const* e = path + tb_strlen(path);
while (p < e && object)
{
// done seek
switch (*p)
{
case '.':
{
// check
tb_assert_and_check_return_val(tb_object_type(object) == TB_OBJECT_TYPE_DICTIONARY, tb_null);
// skip
p++;
// read the key name
tb_char_t key[4096] = {0};
tb_char_t* kb = key;
tb_char_t* ke = key + 4095;
for (; p < e && kb < ke && *p && (*p != '.' && *p != '[' && *p != ']'); p++, kb++)
{
if (*p == '\\') p++;
*kb = *p;
}
// trace
tb_trace_d("key: %s", key);
// the value
object = tb_oc_dictionary_value(object, key);
}
break;
case '[':
{
// check
tb_assert_and_check_return_val(tb_object_type(object) == TB_OBJECT_TYPE_ARRAY, tb_null);
// skip
p++;
// read the item index
tb_char_t index[32] = {0};
tb_char_t* ib = index;
tb_char_t* ie = index + 31;
for (; p < e && ib < ie && *p && tb_isdigit10(*p); p++, ib++) *ib = *p;
// trace
tb_trace_d("index: %s", index);
// check
tb_size_t i = tb_atoi(index);
tb_assert_and_check_return_val(i < tb_oc_array_size(object), tb_null);
// the value
object = tb_oc_array_item(object, i);
}
break;
case ']':
default:
p++;
break;
}
// is macro? done it if be enabled
if ( object
&& bmacro
&& tb_object_type(object) == TB_OBJECT_TYPE_STRING
&& tb_oc_string_size(object)
&& tb_oc_string_cstr(object)[0] == '$')
{
// the next path
path = tb_oc_string_cstr(object) + 1;
// continue to seek it
object = tb_object_seek(root, path, bmacro);
}
}
// ok?
return object;
}
tb_object_ref_t tb_object_dump(tb_object_ref_t object, tb_size_t format)
{
// check
tb_assert_and_check_return_val(object, tb_null);
// data
tb_object_ref_t odata = tb_object_data(object, format);
if (odata)
{
// the data and size
tb_byte_t const* data = (tb_byte_t const*)tb_oc_data_getp(odata);
tb_size_t size = tb_oc_data_size(odata);
if (data && size)
{
// done
tb_char_t const* p = (tb_char_t const*)data;
tb_char_t const* e = (tb_char_t const*)data + size;
tb_char_t b[4096 + 1];
if (p && p < e)
{
while (p < e && *p && tb_isspace(*p)) p++;
while (p < e && *p)
{
tb_char_t* q = b;
tb_char_t const* d = b + 4096;
for (; p < e && q < d && *p; p++, q++) *q = *p;
*q = '\0';
tb_printf("%s", b);
}
tb_printf("\n");
}
}
// exit data
tb_object_exit(odata);
}
// the object
return object;
}
tb_size_t tb_object_refn(tb_object_ref_t object)
{
// check
tb_assert_and_check_return_val(object, 0);
// get it
return object->refn;
}
tb_void_t tb_object_retain(tb_object_ref_t object)
{
// check
tb_assert_and_check_return(object);
// readonly?
tb_check_return(!(object->flag & TB_OBJECT_FLAG_READONLY));
// refn++
object->refn++;
}
tb_object_ref_t tb_object_read(tb_stream_ref_t stream)
{
// check
tb_assert_and_check_return_val(stream, tb_null);
// done reader
return tb_oc_reader_done(stream);
}
tb_object_ref_t tb_object_read_from_url(tb_char_t const* url)
{
// check
tb_assert_and_check_return_val(url, tb_null);
// init
tb_object_ref_t object = tb_null;
// make stream
tb_stream_ref_t stream = tb_stream_init_from_url(url);
tb_assert_and_check_return_val(stream, tb_null);
// read object
if (tb_stream_open(stream)) object = tb_object_read(stream);
// exit stream
tb_stream_exit(stream);
// ok?
return object;
}
tb_object_ref_t tb_object_read_from_data(tb_byte_t const* data, tb_size_t size)
{
// check
tb_assert_and_check_return_val(data && size, tb_null);
// init
tb_object_ref_t object = tb_null;
// make stream
tb_stream_ref_t stream = tb_stream_init_from_data(data, size);
tb_assert_and_check_return_val(stream, tb_null);
// read object
if (tb_stream_open(stream)) object = tb_object_read(stream);
// exit stream
tb_stream_exit(stream);
// ok?
return object;
}
tb_long_t tb_object_writ(tb_object_ref_t object, tb_stream_ref_t stream, tb_size_t format)
{
// check
tb_assert_and_check_return_val(object && stream, -1);
// for xml
#ifndef TB_CONFIG_MODULE_HAVE_XML
tb_assertf(format != TB_OBJECT_FORMAT_XML || format != TB_OBJECT_FORMAT_XPLIST, "please enable xml module first!");
#endif
// writ it
return tb_oc_writer_done(object, stream, format);
}
tb_long_t tb_object_writ_to_url(tb_object_ref_t object, tb_char_t const* url, tb_size_t format)
{
// check
tb_assert_and_check_return_val(object && url, -1);
// make stream
tb_long_t writ = -1;
tb_stream_ref_t stream = tb_stream_init_from_url(url);
if (stream)
{
// ctrl stream
if (tb_stream_type(stream) == TB_STREAM_TYPE_FILE)
tb_stream_ctrl(stream, TB_STREAM_CTRL_FILE_SET_MODE, TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC);
// open and writ stream
if (tb_stream_open(stream)) writ = tb_object_writ(object, stream, format);
// exit stream
tb_stream_exit(stream);
}
// ok?
return writ;
}
tb_long_t tb_object_writ_to_data(tb_object_ref_t object, tb_byte_t* data, tb_size_t size, tb_size_t format)
{
// check
tb_assert_and_check_return_val(object && data && size, -1);
// make stream
tb_long_t writ = -1;
tb_stream_ref_t stream = tb_stream_init_from_data(data, size);
if (stream)
{
// open and writ stream
if (tb_stream_open(stream)) writ = tb_object_writ(object, stream, format);
// exit stream
tb_stream_exit(stream);
}
// ok?
return writ;
}
tbox-1.7.6/src/tbox/object/object.h 0000664 0000000 0000000 00000014151 14671175054 0017145 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file object.h
* @defgroup object
*
*/
#ifndef TB_OBJECT_H
#define TB_OBJECT_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "null.h"
#include "data.h"
#include "date.h"
#include "array.h"
#include "string.h"
#include "number.h"
#include "boolean.h"
#include "dictionary.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init object
*
* @param object the object
* @param flag the object flag
* @param type the object type
*
* @return tb_true or tb_false
*/
tb_bool_t tb_object_init(tb_object_ref_t object, tb_size_t flag, tb_size_t type);
/*! decrease the object reference count, will exit it if --refn == 0
*
* @param object the object
*
* @note the reference count must be one
*/
tb_void_t tb_object_exit(tb_object_ref_t object);
/*! clear object
*
* @param object the object
*/
tb_void_t tb_object_clear(tb_object_ref_t object);
/*! set the object private data
*
* @param object the object
* @param priv the private data
*
*/
tb_void_t tb_object_setp(tb_object_ref_t object, tb_cpointer_t priv);
/*! get the object private data
*
* @param object the object
*
* @return the private data
*/
tb_cpointer_t tb_object_getp(tb_object_ref_t object);
/*! read object
*
* @param stream the stream
*
* @return the object
*/
tb_object_ref_t tb_object_read(tb_stream_ref_t stream);
/*! read object from url
*
* @param url the url
*
* @return the object
*/
tb_object_ref_t tb_object_read_from_url(tb_char_t const* url);
/*! read object from data
*
* @param data the data
* @param size the size
*
* @return the object
*/
tb_object_ref_t tb_object_read_from_data(tb_byte_t const* data, tb_size_t size);
/*! writ object
*
* @param object the object
* @param stream the stream
* @param format the object format
*
* @return the writed size, failed: -1
*/
tb_long_t tb_object_writ(tb_object_ref_t object, tb_stream_ref_t stream, tb_size_t format);
/*! writ object to url
*
* @param object the object
* @param url the url
* @param format the format
*
* @return the writed size, failed: -1
*/
tb_long_t tb_object_writ_to_url(tb_object_ref_t object, tb_char_t const* url, tb_size_t format);
/*! writ object to data
*
* @param object the object
* @param data the data
* @param size the size
* @param format the format
*
* @return the writed size, failed: -1
*/
tb_long_t tb_object_writ_to_data(tb_object_ref_t object, tb_byte_t* data, tb_size_t size, tb_size_t format);
/*! copy object
*
* @param object the object
*
* @return the object copy
*/
tb_object_ref_t tb_object_copy(tb_object_ref_t object);
/*! the object type
*
* @param object the object
*
* @return the object type
*/
tb_size_t tb_object_type(tb_object_ref_t object);
/*! the object data
*
* @param object the object
* @param format the format
*
* @return the data object
*/
tb_object_ref_t tb_object_data(tb_object_ref_t object, tb_size_t format);
/*! seek to the object for the gived path
*
*
*
file:
{
"string": "hello world!"
, "com.xxx.xxx": "hello world"
, "integer": 31415926
, "array":
[
"hello world!"
, 31415926
, 3.1415926
, false
, true
, { "string": "hello world!" }
]
, "macro": "$.array[2]"
, "macro2": "$.com\\\\.xxx\\\\.xxx"
, "macro3": "$.macro"
, "macro4": "$.array"
}
path:
1. ".string" : hello world!
2. ".array[1]" : 31415926
3. ".array[5].string" : hello world!
4. ".com\\.xxx\\.xxx" : hello world
5. ".macro" : 3.1415926
6. ".macro2" : hello world
7. ".macro3" : 3.1415926
8. ".macro4[0]" : "hello world!"
*
*
*
* @param object the object
* @param path the object path
* @param bmacro enable macro(like "$.path")?
*
*
* tb_object_ref_t object = tb_object_seek(root, ".array[5].string", tb_false);
* if (object)
* {
* tb_trace_d("%s", tb_oc_string_cstr(object));
* }
*
*
*
* @return the object
*/
tb_object_ref_t tb_object_seek(tb_object_ref_t object, tb_char_t const* path, tb_bool_t bmacro);
/*! dump the object
*
* @param object the object
* @param format the format, support: .xml, .xplist, .json
*
* @return the object
*/
tb_object_ref_t tb_object_dump(tb_object_ref_t object, tb_size_t format);
/*! the object reference count
*
* @param object the object
*
* @return the object reference count
*/
tb_size_t tb_object_refn(tb_object_ref_t object);
/*! retain object and increase the object reference count
*
* @param object the object
*/
tb_void_t tb_object_retain(tb_object_ref_t object);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/object/prefix.h 0000664 0000000 0000000 00000005616 14671175054 0017202 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_PREFIX_H
#define TB_OBJECT_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#include "../xml/xml.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the object type enum
typedef enum __tb_object_type_e
{
TB_OBJECT_TYPE_NONE = 0
, TB_OBJECT_TYPE_DATA = 1
, TB_OBJECT_TYPE_DATE = 2
, TB_OBJECT_TYPE_ARRAY = 3
, TB_OBJECT_TYPE_STRING = 4
, TB_OBJECT_TYPE_NUMBER = 5
, TB_OBJECT_TYPE_BOOLEAN = 6
, TB_OBJECT_TYPE_DICTIONARY = 7
, TB_OBJECT_TYPE_NULL = 8
, TB_OBJECT_TYPE_USER = 9 //!< the user defined type, ...
}tb_object_type_e;
/// the object flag enum
typedef enum __tb_object_flag_e
{
TB_OBJECT_FLAG_NONE = 0
, TB_OBJECT_FLAG_READONLY = 1
, TB_OBJECT_FLAG_SINGLETON = 2
}tb_object_flag_e;
/// the object format enum
typedef enum __tb_object_format_e
{
TB_OBJECT_FORMAT_NONE = 0x0000 //!< none
, TB_OBJECT_FORMAT_BIN = 0x0001 //!< the tbox binary format
, TB_OBJECT_FORMAT_BPLIST = 0x0002 //!< the bplist format for apple
, TB_OBJECT_FORMAT_XPLIST = 0x0003 //!< the xplist format for apple
, TB_OBJECT_FORMAT_XML = 0x0004 //!< the xml format
, TB_OBJECT_FORMAT_JSON = 0x0005 //!< the json format
, TB_OBJECT_FORMAT_MAXN = 0x000f //!< the format maxn
, TB_OBJECT_FORMAT_DEFLATE = 0x0100 //!< deflate?
}tb_object_format_e;
/// the object type
typedef struct __tb_object_t
{
/// the object flag
tb_uint8_t flag;
/// the object type
tb_uint16_t type;
/// the object reference count
tb_size_t refn;
/// the object private data
tb_cpointer_t priv;
/// the copy func
struct __tb_object_t* (*copy)(struct __tb_object_t* object);
/// the clear func
tb_void_t (*clear)(struct __tb_object_t* object);
/// the exit func
tb_void_t (*exit)(struct __tb_object_t* object);
}tb_object_t, *tb_object_ref_t;
#endif
tbox-1.7.6/src/tbox/object/string.c 0000664 0000000 0000000 00000012633 14671175054 0017203 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file string.c
* @ingroup object
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "oc_string"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "object.h"
#include "../string/string.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the scache string size
#define TB_OBJECT_STRING_CACHE_SIZE (64)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the string type
typedef struct __tb_oc_string_t
{
// the object base
tb_object_t base;
// the string
tb_string_t str;
}tb_oc_string_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static __tb_inline__ tb_oc_string_t* tb_oc_string_cast(tb_object_ref_t object)
{
// check
tb_assert_and_check_return_val(object && object->type == TB_OBJECT_TYPE_STRING, tb_null);
// cast
return (tb_oc_string_t*)object;
}
static tb_object_ref_t tb_oc_string_copy(tb_object_ref_t object)
{
return tb_oc_string_init_from_cstr(tb_oc_string_cstr(object));
}
static tb_void_t tb_oc_string_exit(tb_object_ref_t object)
{
tb_oc_string_t* string = tb_oc_string_cast(object);
if (string)
{
// exit the string
tb_string_exit(&string->str);
// exit the object
tb_free(object);
}
}
static tb_void_t tb_oc_string_clear(tb_object_ref_t object)
{
tb_oc_string_t* string = tb_oc_string_cast(object);
if (string)
{
// clear the string
tb_string_clear(&string->str);
}
}
static tb_oc_string_t* tb_oc_string_init_base()
{
// done
tb_bool_t ok = tb_false;
tb_oc_string_t* string = tb_null;
do
{
// make string
string = tb_malloc0_type(tb_oc_string_t);
tb_assert_and_check_break(string);
// init string
if (!tb_object_init((tb_object_ref_t)string, TB_OBJECT_FLAG_NONE, TB_OBJECT_TYPE_STRING)) break;
// init base
string->base.copy = tb_oc_string_copy;
string->base.exit = tb_oc_string_exit;
string->base.clear = tb_oc_string_clear;
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (string) tb_object_exit((tb_object_ref_t)string);
string = tb_null;
}
// ok?
return string;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_object_ref_t tb_oc_string_init_from_cstr(tb_char_t const* cstr)
{
// done
tb_bool_t ok = tb_false;
tb_oc_string_t* string = tb_null;
do
{
// make string
string = tb_oc_string_init_base();
tb_assert_and_check_break(string);
// init str
if (!tb_string_init(&string->str)) break;
// copy string
if (cstr) tb_string_cstrcpy(&string->str, cstr);
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
tb_oc_string_exit((tb_object_ref_t)string);
string = tb_null;
}
// ok?
return (tb_object_ref_t)string;
}
tb_object_ref_t tb_oc_string_init_from_str(tb_string_ref_t str)
{
// done
tb_bool_t ok = tb_false;
tb_oc_string_t* string = tb_null;
do
{
// make string
string = tb_oc_string_init_base();
tb_assert_and_check_break(string);
// init str
if (!tb_string_init(&string->str)) break;
// copy string
if (str) tb_string_strcpy(&string->str, str);
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
tb_oc_string_exit((tb_object_ref_t)string);
string = tb_null;
}
// ok?
return (tb_object_ref_t)string;
}
tb_char_t const* tb_oc_string_cstr(tb_object_ref_t object)
{
// check
tb_oc_string_t* string = tb_oc_string_cast(object);
tb_assert_and_check_return_val(string, tb_null);
// cstr
return tb_string_cstr(&string->str);
}
tb_size_t tb_oc_string_cstr_set(tb_object_ref_t object, tb_char_t const* cstr)
{
// check
tb_oc_string_t* string = tb_oc_string_cast(object);
tb_assert_and_check_return_val(string && cstr, 0);
// copy string
tb_string_cstrcpy(&string->str, cstr);
// ok?
return tb_string_size(&string->str);
}
tb_size_t tb_oc_string_size(tb_object_ref_t object)
{
// check
tb_oc_string_t* string = tb_oc_string_cast(object);
tb_assert_and_check_return_val(string, 0);
// size
return tb_string_size(&string->str);
}
tbox-1.7.6/src/tbox/object/string.h 0000664 0000000 0000000 00000004225 14671175054 0017206 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file string.h
* @ingroup object
*
*/
#ifndef TB_OBJECT_STRING_H
#define TB_OBJECT_STRING_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init string from c-string
*
* @param cstr the c-string
*
* @return the string object
*/
tb_object_ref_t tb_oc_string_init_from_cstr(tb_char_t const* cstr);
/*! init string from string
*
* @param str the string
*
* @return the string object
*/
tb_object_ref_t tb_oc_string_init_from_str(tb_string_ref_t str);
/*! the c-string
*
* @param string the string object
*
* @return the c-string
*/
tb_char_t const* tb_oc_string_cstr(tb_object_ref_t string);
/*! set the c-string
*
* @param string the string object
* @param cstr the c-string
*
* @return the string size
*/
tb_size_t tb_oc_string_cstr_set(tb_object_ref_t string, tb_char_t const* cstr);
/*! the string size
*
* @param string the string object
*
* @return the string size
*/
tb_size_t tb_oc_string_size(tb_object_ref_t string);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/ 0000775 0000000 0000000 00000000000 14671175054 0016102 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/platform/addrinfo.c 0000664 0000000 0000000 00000004504 14671175054 0020037 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file addrinfo.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "addrinfo"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "addrinfo.h"
#include "../network/network.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_OS_WINDOWS)
# define TB_ADDRINFO_ADDR_IMPL
# include "windows/addrinfo.c"
# undef TB_ADDRINFO_ADDR_IMPL
#elif defined(TB_CONFIG_POSIX_HAVE_GETADDRINFO) || \
defined(TB_CONFIG_POSIX_HAVE_GETHOSTBYNAME)
# define TB_ADDRINFO_ADDR_IMPL
# include "posix/addrinfo.c"
# undef TB_ADDRINFO_ADDR_IMPL
#else
tb_bool_t tb_addrinfo_addr(tb_char_t const* name, tb_ipaddr_ref_t addr)
{
#ifndef TB_CONFIG_MICRO_ENABLE
// attempt to get address using dns looker
if (tb_ipaddr_family(addr) != TB_IPADDR_FAMILY_IPV6 && tb_dns_looker_done(name, addr))
return tb_true;
#endif
// not implemented
tb_trace_noimpl();
return tb_false;
}
#endif
#if defined(TB_CONFIG_OS_WINDOWS)
# define TB_ADDRINFO_NAME_IMPL
# include "windows/addrinfo.c"
# undef TB_ADDRINFO_NAME_IMPL
#elif defined(TB_CONFIG_POSIX_HAVE_GETNAMEINFO) || \
defined(TB_CONFIG_POSIX_HAVE_GETHOSTBYADDR)
# define TB_ADDRINFO_NAME_IMPL
# include "posix/addrinfo.c"
# undef TB_ADDRINFO_NAME_IMPL
#else
tb_char_t const* tb_addrinfo_name(tb_ipaddr_ref_t addr, tb_char_t* name, tb_size_t maxn)
{
tb_trace_noimpl();
return tb_null;
}
#endif
tbox-1.7.6/src/tbox/platform/addrinfo.h 0000664 0000000 0000000 00000005030 14671175054 0020037 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file addrinfo.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_ADDRINFO_H
#define TB_PLATFORM_ADDRINFO_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../network/ipaddr.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! get the first dns address from the host name
*
* @code
// get the default address (ipv4)
tb_ipaddr_t addr = {0};
if (tb_addrinfo_addr("www.tboox.org", &addr))
tb_trace_i("%{ipaddr}", &addr);
// get the ipv6 address by the hint info
tb_ipaddr_t addr = {0};
tb_ipaddr_family_set(&addr, TB_IPADDR_FAMILY_IPV6);
if (tb_addrinfo_addr("www.tboox.org", &addr))
tb_trace_i("%{ipaddr}", &addr);
* @endcode
*
* @param name the host name (cannot be null)
* @param addr the ip address (we can fill some hint info first)
*
* @return tb_true or tb_false
*/
tb_bool_t tb_addrinfo_addr(tb_char_t const* name, tb_ipaddr_ref_t addr);
/*! get the host name from the given address
*
* @code
// get the host name by address
tb_ipaddr_t addr;
tb_char_t host[256];
tb_ipaddr_ip_cstr_set(&addr, "127.0.0.1");
tb_trace_i("%s", tb_addrinfo_name(&addr, host, sizeof(host)));
* @endcode
*
* @param addr the ip address (cannot be null)
* @param name the host name buffer
* @param maxn the host name buffer maxn
*
* @return the host name or tb_null
*/
tb_char_t const* tb_addrinfo_name(tb_ipaddr_ref_t addr, tb_char_t* name, tb_size_t maxn);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/android/ 0000775 0000000 0000000 00000000000 14671175054 0017522 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/platform/android/android.c 0000664 0000000 0000000 00000003103 14671175054 0021303 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file android.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "android.h"
#include "../atomic.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
static tb_atomic_t g_jvm = 0;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_android_init_env(JavaVM* jvm)
{
// check
if (!jvm)
{
// warning
tb_trace_w("the java machine be not inited, please pass it to the tb_init function!");
}
// init it
tb_atomic_set(&g_jvm, (tb_size_t)jvm);
// ok
return tb_true;
}
tb_void_t tb_android_exit_env()
{
// clear it
tb_atomic_set(&g_jvm, 0);
}
JavaVM* tb_android_jvm()
{
// get it
return (JavaVM*)tb_atomic_get(&g_jvm);
}
tbox-1.7.6/src/tbox/platform/android/android.h 0000664 0000000 0000000 00000002616 14671175054 0021320 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file android.h
* @ingroup platform
*/
#ifndef TB_PLATFORM_ANDROID_H
#define TB_PLATFORM_ANDROID_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init the android platform
*
* @param jvm the java machine pointer
*
* @return tb_true or tb_false
*/
tb_bool_t tb_android_init_env(JavaVM* jvm);
/// exit the android platform
tb_void_t tb_android_exit_env(tb_noarg_t);
/*! the java machine pointer
*
* @return the java machine pointer
*/
JavaVM* tb_android_jvm(tb_noarg_t);
#endif
tbox-1.7.6/src/tbox/platform/android/backtrace.c 0000664 0000000 0000000 00000027770 14671175054 0021622 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file backtrace.c
* @ingroup platform
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../atomic.h"
#include "../memory.h"
#include "../dynamic.h"
#include "../native_memory.h"
#if 0
# include
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/* a single frame of a backtrace.
*
* from corkscrew/backtrace.h
*/
typedef struct __tb_backtrace_frame_t
{
// absolute PC offset
tb_size_t absolute_pc;
// top of stack for this frame
tb_size_t stack_top;
// size of this stack frame
tb_size_t stack_size;
} tb_backtrace_frame_t, *tb_backtrace_frame_ref_t;
/* the symbols associated with a backtrace frame.
*
* from corkscrew/backtrace.h
*/
typedef struct __tb_backtrace_symbol_t
{
/* relative frame PC offset from the start of the library,
* or the absolute PC if the library is unknown
*/
tb_size_t relative_pc;
/* relative offset of the symbol from the start of the
* library or 0 if the library is unknown
*/
tb_size_t relative_symbol_addr;
// executable or library name, or NULL if unknown
tb_char_t* map_name;
// symbol name, or NULL if unknown
tb_char_t* symbol_name;
// demangled symbol name, or NULL if unknown
tb_char_t* demangled_name;
} tb_backtrace_symbol_t, *tb_backtrace_symbol_ref_t;
// the symbols type
typedef struct __tb_backtrace_symbols_t
{
// the symbols
tb_backtrace_symbol_t symbols[64];
// the info
tb_char_t info[256];
// the frame count
tb_size_t nframe;
} tb_backtrace_symbols_t, *tb_backtrace_symbols_ref_t;
// the unwind_backtrace function type
typedef tb_long_t (*tb_backtrace_unwind_backtrace_func_t)(tb_backtrace_frame_ref_t, tb_size_t, tb_size_t);
// the get_backtrace_symbols function type
typedef tb_void_t (*tb_backtrace_get_backtrace_symbols_func_t)(tb_backtrace_frame_ref_t, tb_size_t, tb_backtrace_symbol_ref_t);
// the free_backtrace_symbols function type
typedef tb_void_t (*tb_backtrace_free_backtrace_symbols_func_t)(tb_backtrace_symbol_ref_t, tb_size_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
// the unwind_backtrace function
static tb_backtrace_unwind_backtrace_func_t g_unwind_backtrace = tb_null;
// the get_backtrace_symbols function
static tb_backtrace_get_backtrace_symbols_func_t g_get_backtrace_symbols = tb_null;
// the free_backtrace_symbols function
static tb_backtrace_free_backtrace_symbols_func_t g_free_backtrace_symbols = tb_null;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
#if 0
static _Unwind_Reason_Code tb_backtrace_unwind(struct _Unwind_Context* context, tb_pointer_t args)
{
// check
tb_value_ref_t info = (tb_value_ref_t)args;
tb_check_return_val(context && info, _URC_END_OF_STACK);
// get info
tb_backtrace_frame_ref_t frames = (tb_backtrace_frame_ref_t)info[0].ptr;
tb_size_t nskip = info[1].ul;
tb_size_t nframe_maxn = info[2].ul;
tb_long_t count = info[3].l;
tb_check_return_val(frames && nframe_maxn && count < nframe_maxn, _URC_END_OF_STACK);
// get ip
#ifdef HAVE_GETIPINFO
tb_int_t ip_before_insn = 0;
tb_size_t ip = (tb_size_t)_Unwind_GetIPInfo (context, &ip_before_insn);
if (!ip_before_insn) ip--;
#else
tb_size_t ip = (tb_size_t)_Unwind_GetIP (context);
#endif
// trace
tb_trace_d("unwind: count: %ld, nframe_maxn: %lu, ip: %p", count, nframe_maxn, ip);
// skip and save frame
if (ip)
{
if (nskip > 0) nskip--;
else
{
frames[count].absolute_pc = ip;
frames[count].stack_top = 0;
frames[count].stack_size = 0;
count++;
}
}
// update info
info[1].ul = nskip;
info[3].l = count;
// ok
return _URC_OK;
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_backtrace_frames(tb_pointer_t* frames, tb_size_t nframe, tb_size_t nskip)
{
// check
tb_check_return_val(frames && nframe, 0);
// done
tb_long_t count = 0;
do
{
// load libcorkscrew.so?
static tb_atomic_flag_t g_loaded = TB_ATOMIC_FLAG_INIT;
if (!tb_atomic_flag_test_and_set(&g_loaded))
{
// init dynamic
tb_dynamic_ref_t dynamic = tb_dynamic_init("/system/lib/libcorkscrew.so");
tb_check_break(dynamic);
// get the unwind_backtrace function
g_unwind_backtrace = (tb_backtrace_unwind_backtrace_func_t)tb_dynamic_func(dynamic, "unwind_backtrace");
// get the get_backtrace_symbols function
g_get_backtrace_symbols = (tb_backtrace_get_backtrace_symbols_func_t)tb_dynamic_func(dynamic, "get_backtrace_symbols");
// get the free_backtrace_symbols function
g_free_backtrace_symbols = (tb_backtrace_free_backtrace_symbols_func_t)tb_dynamic_func(dynamic, "free_backtrace_symbols");
}
tb_check_break(g_unwind_backtrace && g_get_backtrace_symbols && g_free_backtrace_symbols);
// calculate max frames count which can be storaged
tb_size_t nframe_maxn = (sizeof(tb_pointer_t) * nframe) / sizeof(tb_backtrace_frame_t);
tb_check_break(nframe_maxn && nframe_maxn < 64);
#if 1
// unwind backtrace
count = g_unwind_backtrace((tb_backtrace_frame_ref_t)frames, nskip, nframe_maxn);
tb_check_break_state(count >= 0, count, 0);
#else
// need add cxflags: -funwind-tables
tb_value_t info[4];
info[0].ptr = (tb_pointer_t)frames;
info[1].ul = nskip;
info[2].ul = nframe_maxn;
info[3].l = 0;
_Unwind_Backtrace(tb_backtrace_unwind, info);
count = info[3].l;
#endif
} while (0);
// ok?
return count;
}
tb_handle_t tb_backtrace_symbols_init(tb_pointer_t* frames, tb_size_t nframe)
{
// check
tb_check_return_val(frames && nframe, tb_null);
tb_check_return_val(g_get_backtrace_symbols, tb_null);
// done
tb_backtrace_symbols_ref_t symbols = tb_null;
do
{
// the real frames count
tb_size_t nframe_real = tb_min(nframe, 64);
// make symbols
symbols = (tb_backtrace_symbols_ref_t)tb_native_memory_malloc0(sizeof(tb_backtrace_symbols_t));
tb_check_break(symbols);
// get backtrace symbols
g_get_backtrace_symbols((tb_backtrace_frame_ref_t)frames, nframe_real, symbols->symbols);
// save the frame count
symbols->nframe = nframe_real;
} while (0);
// ok?
return (tb_handle_t)symbols;
}
#if 1
tb_char_t const* tb_backtrace_symbols_name(tb_handle_t handle, tb_pointer_t* frames, tb_size_t nframe, tb_size_t iframe)
{
// check
tb_backtrace_symbols_ref_t symbols = (tb_backtrace_symbols_ref_t)handle;
tb_check_return_val(symbols && symbols->nframe && frames && iframe < symbols->nframe && symbols->nframe == nframe, tb_null);
// get symbol
tb_backtrace_symbol_ref_t symbol = &symbols->symbols[iframe];
// get map name
tb_char_t const* map_name = symbol->map_name? symbol->map_name : "";
// get symbol name
tb_char_t const* symbol_name = symbol->demangled_name? symbol->demangled_name : symbol->symbol_name;
// make symbol info
tb_long_t info_size = 0;
if (symbol_name)
{
// the pc offset relative symbol
tb_size_t relative_symbol_pc_offset = symbol->relative_pc - symbol->relative_symbol_addr;
if (relative_symbol_pc_offset)
{
// make it
info_size = tb_snprintf( symbols->info
, sizeof(symbols->info)
, "[%08lx]: %2lu %s %08lx %s + %lu"
, symbol->relative_pc
, iframe
, map_name
, symbol->relative_pc
, symbol_name
, relative_symbol_pc_offset);
}
else
{
// make it
info_size = tb_snprintf( symbols->info
, sizeof(symbols->info)
, "[%08lx]: %2lu %s %08lx %s"
, symbol->relative_pc
, iframe
, map_name
, symbol->relative_pc
, symbol_name);
}
}
else
{
// make it
info_size = tb_snprintf( symbols->info
, sizeof(symbols->info)
, "[%08lx]: %2lu %s %08lx"
, symbol->relative_pc
, iframe
, map_name
, symbol->relative_pc);
}
// end
if (info_size >= 0 && info_size < sizeof(symbols->info))
symbols->info[info_size] = '\0';
// ok?
return symbols->info;
}
#else
tb_char_t const* tb_backtrace_symbols_name(tb_handle_t handle, tb_pointer_t* frames, tb_size_t nframe, tb_size_t iframe)
{
// check
tb_backtrace_symbols_ref_t symbols = (tb_backtrace_symbols_ref_t)handle;
tb_check_return_val(symbols && frames && iframe < nframe, tb_null);
// get frame address
tb_size_t addr = ((tb_backtrace_frame_ref_t)frames)[iframe].absolute_pc;
// make symbol info
Dl_info info;
tb_long_t info_size = 0;
if (dladdr((tb_pointer_t)addr, &info) && info.dli_sname)
{
// make it
info_size = tb_snprintf( symbols->info
, sizeof(symbols->info)
, "[%08lx]: %2lu %s %08lx %s + %lu"
, addr
, iframe
, ""
, addr
, info.dli_sname
, 0);
}
else
{
// make it
info_size = tb_snprintf( symbols->info
, sizeof(symbols->info)
, "[%08lx]: %2lu %s %08lx"
, addr
, iframe
, ""
, addr);
}
// end
if (info_size >= 0 && info_size < sizeof(symbols->info))
symbols->info[info_size] = '\0';
// ok?
return symbols->info;
}
#endif
tb_void_t tb_backtrace_symbols_exit(tb_handle_t handle)
{
// check
tb_backtrace_symbols_ref_t symbols = (tb_backtrace_symbols_ref_t)handle;
tb_check_return(symbols && g_free_backtrace_symbols);
// free symbols
if (symbols->nframe) g_free_backtrace_symbols(symbols->symbols, symbols->nframe);
// exit it
tb_native_memory_free(symbols);
}
tbox-1.7.6/src/tbox/platform/android/directory.c 0000664 0000000 0000000 00000010573 14671175054 0021700 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file directory.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "android_directory"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "android.h"
#include "../directory.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_directory_temporary(tb_char_t* path, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(path && maxn > 4, 0);
// the jvm
JavaVM* jvm = tb_android_jvm();
tb_assert_and_check_return_val(jvm, 0);
// attempt to get jni environment first
JNIEnv* jenv = tb_null;
tb_bool_t jattached = tb_false;
if ((*jvm)->GetEnv(jvm, (tb_pointer_t*)&jenv, JNI_VERSION_1_4) != JNI_OK)
{
// bind jni environment
if ((*jvm)->AttachCurrentThread(jvm, &jenv, tb_null) != JNI_OK) return 0;
// attach ok
jattached = tb_true;
}
tb_assert_and_check_return_val(jenv, 0);
// enter
if ((*jenv)->PushLocalFrame(jenv, 10) < 0) return 0;
// done
tb_size_t size = 0;
jboolean error = tb_false;
do
{
// get the environment class
jclass environment = (*jenv)->FindClass(jenv, "android/os/Environment");
tb_assert_and_check_break(!(error = (*jenv)->ExceptionCheck(jenv)) && environment);
// get the getDownloadCacheDirectory func
jmethodID getDownloadCacheDirectory_func = (*jenv)->GetStaticMethodID(jenv, environment, "getDownloadCacheDirectory", "()Ljava/io/File;");
tb_assert_and_check_break(getDownloadCacheDirectory_func);
// get the download cache directory
jobject directory = (*jenv)->CallStaticObjectMethod(jenv, environment, getDownloadCacheDirectory_func);
tb_assert_and_check_break(!(error = (*jenv)->ExceptionCheck(jenv)) && directory);
// get file class
jclass file_class = (*jenv)->GetObjectClass(jenv, directory);
tb_assert_and_check_break(!(error = (*jenv)->ExceptionCheck(jenv)) && file_class);
// get the getPath func
jmethodID getPath_func = (*jenv)->GetMethodID(jenv, file_class, "getPath", "()Ljava/lang/String;");
tb_assert_and_check_break(getPath_func);
// get the directory path
jstring path_jstr = (jstring)(*jenv)->CallObjectMethod(jenv, directory, getPath_func);
tb_assert_and_check_break(!(error = (*jenv)->ExceptionCheck(jenv)) && path_jstr);
// get the path string length
size = (tb_size_t)(*jenv)->GetStringLength(jenv, path_jstr);
tb_assert_and_check_break(size);
// get the path string
tb_char_t const* path_cstr = (*jenv)->GetStringUTFChars(jenv, path_jstr, tb_null);
tb_assert_and_check_break(path_cstr);
// trace
tb_trace_d("temp: %s", path_cstr);
// copy it
tb_size_t need = tb_min(size + 1, maxn);
tb_strlcpy(path, path_cstr, need);
// exit the path string
(*jenv)->ReleaseStringUTFChars(jenv, path_jstr, path_cstr);
} while (0);
// exception? clear it
if (error) (*jenv)->ExceptionClear(jenv);
// leave
(*jenv)->PopLocalFrame(jenv, tb_null);
// detach it?
if (jattached)
{
// detach jni environment
if ((*jvm)->DetachCurrentThread(jvm) == JNI_OK)
jattached = tb_false;
}
// ok?
return size;
}
tb_size_t tb_directory_home(tb_char_t* path, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(path && maxn, 0);
// trace
tb_trace_noimpl();
return 0;
}
tbox-1.7.6/src/tbox/platform/android/dns.c 0000664 0000000 0000000 00000003147 14671175054 0020457 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file dns.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../impl/dns.h"
#include "../../network/network.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_bool_t tb_dns_init_env()
{
// done
tb_size_t count = 0;
for (count = 0; count < 6; count++)
{
// init the dns property name
tb_char_t prop_name[PROP_NAME_MAX] = {0};
tb_snprintf(prop_name, sizeof(prop_name) - 1, "net.dns%lu", count + 1);
// get dns address name
tb_char_t dns[64] = {0};
if (!__system_property_get(prop_name, dns)) break;
// trace
tb_trace_d("addr: %s", dns);
// add server
tb_dns_server_add(dns);
}
// ok
return tb_true;
}
tb_void_t tb_dns_exit_env()
{
}
tbox-1.7.6/src/tbox/platform/android/prefix.h 0000664 0000000 0000000 00000001764 14671175054 0021200 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
* @ingroup platform
*/
#ifndef TB_PLATFORM_ANDROID_PREFIX_H
#define TB_PLATFORM_ANDROID_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#include "../../libc/libc.h"
#include "../../utils/utils.h"
#include
#endif
tbox-1.7.6/src/tbox/platform/android/print.c 0000664 0000000 0000000 00000003464 14671175054 0021031 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file print.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../thread.h"
#include
#include
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_void_t tb_print(tb_char_t const* string)
{
// check
tb_check_return(string);
// print to the android device log
__android_log_print(ANDROID_LOG_ERROR, __tb_prefix__? __tb_prefix__ : "tbox", "[%08x]: %s", (tb_uint32_t)tb_thread_self(), string);
// print to the stdout
fputs(string, stdout);
}
tb_void_t tb_printl(tb_char_t const* string)
{
// check
tb_check_return(string);
// print to the android device log
__android_log_print(ANDROID_LOG_ERROR, __tb_prefix__? __tb_prefix__ : "tbox", "[%08x]: %s", (tb_uint32_t)tb_thread_self(), string);
// print string to the stdout
fputs(string, stdout);
// print newline to the stdout
fputs(__tb_newline__, stdout);
}
tb_void_t tb_print_sync()
{
// flush the stdout
fflush(stdout);
}
tbox-1.7.6/src/tbox/platform/arch/ 0000775 0000000 0000000 00000000000 14671175054 0017017 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/platform/arch/arm/ 0000775 0000000 0000000 00000000000 14671175054 0017576 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/platform/arch/arm/context.S 0000664 0000000 0000000 00000016754 14671175054 0021423 0 ustar 00root root 0000000 0000000 /*
Copyright Oliver Kowalke 2009.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
/*
* Boost Software License - Version 1.0 - August 17th, 2003
*
* Permission is hereby granted, free of charge, to any person or organization
* obtaining a copy of the software and accompanying documentation covered by
* this license (the "Software") to use, reproduce, display, distribute,
* execute, and transmit the Software, and to prepare derivative works of the
* Software, and to permit third-parties to whom the Software is furnished to
* do so, all subject to the following:
*
* The copyright notices in the Software and this entire statement, including
* the above license grant, this restriction and the following disclaimer,
* must be included in all copies of the Software, in whole or in part, and
* all derivative works of the Software, unless such copies or derivative
* works are solely in the form of machine-executable object code generated by
* a source language processor.
*
* 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_CONFIG_OS_IOS
# define TB_CONTEXT_SJLJ_BYTES 4
#else
# define TB_CONTEXT_SJLJ_BYTES 0
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
/* make context (refer to boost.context)
*
*
* --------------------------------------------------------------------------------------
* stackdata: | | context ||
* --------------------------------------------------------------------------------------
* (16-align)
*
* for macho (ios):
*
* save and restore the sjlj(setjmp/longjmp) exception handler on tls
*
* -------------------------------------------------------
* context: | sjlj | retval | r4 | r5 | r6 | r7 |
* -------------------------------------------------------
* 0 4 | 8 12 16 20
* |
* ------------------------------------------------
* \|/
* __end func retval(from)
* --------------------------------------------------------------------------------------
* | r8 | r9 | r10 | r11 | lr | pc | context | priv | padding |
* --------------------------------------------------------------------------------------
* 24 28 32 36 40 44 48 52 |
* | |
* | 16-align
* |
* sp when jump to function
*
* for elf (linux, ..):
*
* -----------------------------------------------
* context: | retval | r4 | r5 | r6 | r7 |
* -----------------------------------------------
* 0 | 4 8 12 16
* |
* ---------------------------------------------------------
* \|/
* __end func retval(from)
* --------------------------------------------------------------------------------------
* | r8 | r9 | r10 | r11 | lr | pc | context | priv | padding |
* --------------------------------------------------------------------------------------
* 20 24 28 32 36 40 44 48 |
* | |
* | 16-align
* |
* sp when jump to function
*
*
* @param stackdata the stack data (r0)
* @param stacksize the stack size (r1)
* @param func the entry function (r2)
*
* @return the context pointer (r0)
*/
function tb_context_make, export=1
// save the stack top to r0
add r0, r0, r1
// 16-align of the stack top address
bic r0, r0, #15
/* reserve space for context-data on context-stack
*
* 64 = align8(52 + TB_CONTEXT_SJLJ_BYTES)
*/
sub r0, r0, #64
// context.pc = func
str r2, [r0, #40 + TB_CONTEXT_SJLJ_BYTES]
/* init retval = a writeable space (context)
*
* it will write retval(context, priv) when jump to a new context function entry first
*/
add r1, r0, #44 + TB_CONTEXT_SJLJ_BYTES
str r1, [r0, #0 + TB_CONTEXT_SJLJ_BYTES]
// context.lr = address of label __end
adr r1, __end
str r1, [r0, #36 + TB_CONTEXT_SJLJ_BYTES]
// return pointer to context-data
bx lr
__end:
// exit(0)
mov r0, #0
#ifdef TB_ARCH_ELF
bl _exit@PLT
#else
bl __exit
#endif
endfunc
/* jump context (refer to boost.context)
*
* @param retval the from-context (r0)
* @param context the to-context (r1)
* @param priv the passed user private data (r2)
*
* @return the from-context (retval)
*/
function tb_context_jump, export=1
// save lr as pc
push {lr}
// save retval, r4 - r11, lr
push {r0, r4 - r11, lr}
#ifdef TB_CONFIG_OS_IOS
// load tls to save or restore sjlj handler
mrc p15, 0, r5, c13, c0, #3
bic r5, r5, #3
// load and save sjlj handler: tls[__PTK_LIBC_DYLD_Unwind_SjLj_Key]
ldr r4, [r5, #8]
push {r4}
#endif
// save the old context(sp) to r0
mov r0, sp
// switch to the new context(sp) and stack
mov sp, r1
#ifdef TB_CONFIG_OS_IOS
// restore sjlj handler
pop {r4}
str r4, [r5, #8]
#endif
// restore retval, r4 - r11, lr
pop {r3, r4 - r11, lr}
// return from-context: retval(context: r0, priv: r2) from jump
str r0, [r3, #0]
str r2, [r3, #4]
// pass old-context(context: r0, priv: r1 = r2) arguments to the context function
mov r1, r2
/* jump to the return or entry address(pc)
*
* func retval(from)
* ---------------------------------------
* context: | pc | context | priv | padding |
* ---------------------------------------
* 0 4 8
* |
* sp
*/
pop {pc}
endfunc
tbox-1.7.6/src/tbox/platform/arch/arm/frame.h 0000664 0000000 0000000 00000003402 14671175054 0021040 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file frame.h
*
*/
#ifndef TB_PLATFORM_ARCH_ARM_FRAME_H
#define TB_PLATFORM_ARCH_ARM_FRAME_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the current stack frame address
#if !defined(TB_CURRENT_STACK_FRAME) \
&& defined(TB_COMPILER_IS_GCC) \
&& TB_COMPILER_VERSION_BE(4, 1)
# define TB_CURRENT_STACK_FRAME (__builtin_frame_address(0) - 12)
#endif
// the advance stack frame address
#ifndef TB_ADVANCE_STACK_FRAME
# define TB_ADVANCE_STACK_FRAME(next) ((tb_frame_layout_t*)(next) - 1)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the frame layout type
typedef struct __tb_frame_layout_t
{
// the next
struct __tb_frame_layout_t* next;
// the sp
tb_pointer_t sp;
// the frame return address
tb_pointer_t return_address;
}tb_frame_layout_t;
#endif
tbox-1.7.6/src/tbox/platform/arch/arm/prefix.h 0000664 0000000 0000000 00000001624 14671175054 0021247 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_PLATFORM_ARCH_ARM_PREFIX_H
#define TB_PLATFORM_ARCH_ARM_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/platform/arch/arm64/ 0000775 0000000 0000000 00000000000 14671175054 0017750 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/platform/arch/arm64/context.S 0000664 0000000 0000000 00000013065 14671175054 0021565 0 ustar 00root root 0000000 0000000 /*
Copyright Oliver Kowalke 2009.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
/*
* Boost Software License - Version 1.0 - August 17th, 2003
*
* Permission is hereby granted, free of charge, to any person or organization
* obtaining a copy of the software and accompanying documentation covered by
* this license (the "Software") to use, reproduce, display, distribute,
* execute, and transmit the Software, and to prepare derivative works of the
* Software, and to permit third-parties to whom the Software is furnished to
* do so, all subject to the following:
*
* The copyright notices in the Software and this entire statement, including
* the above license grant, this restriction and the following disclaimer,
* must be included in all copies of the Software, in whole or in part, and
* all derivative works of the Software, unless such copies or derivative
* works are solely in the form of machine-executable object code generated by
* a source language processor.
*
* 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
/* make context (refer to boost.context)
*
*
* --------------------------------------------------------------------------------------
* stackdata: | | context ||
* --------------------------------------------------------------------------------------
* (16-align)
*
* ---------------------------------------------------------------------
* context: | x19 | x20 | x21 | x22 | x23 | x24 | x25 |
* ---------------------------------------------------------------------
* 0 8 16 24 32 40 48
*
*
* __end func
* ---------------------------------------------------------------------
* | x26 | x27 | x28 | fp | lr | pc | padding |
* ---------------------------------------------------------------------
* 56 64 72 80 88 96 |
* |
* 16-align
*
*
* @param stackdata the stack data (x0)
* @param stacksize the stack size (x1)
* @param func the entry function (x2)
*
* @return the context pointer (x0)
*/
function tb_context_make, export=1
// save the stack top to x0
add x0, x0, x1
// 16-align of the stack top address
and x0, x0, ~0xf
/* reserve space for context-data on context-stack
*
* 112 = align16(13 * 8)
*/
sub x0, x0, #112
// context.pc = func
str x2, [x0, #96]
// get the address of label __end
#ifdef TB_CONFIG_OS_IOS
/* numeric offset since llvm still does not support labels in adr
*
* 0x0c = 3 instructions * size (4) before label '__end'
*
* new version llvm have already fix this issues.
*/
adr x1, 0x0c
#else
adr x1, __end
#endif
// context.lr = the address of label __end
str x1, [x0, #88]
// return pointer to context-data (x0)
#ifdef TB_CONFIG_OS_IOS
ret lr
#else
ret x30
#endif
__end:
// exit(0)
mov x0, #0
#ifdef TB_ARCH_ELF
bl _exit
#else
bl __exit
#endif
endfunc
/* jump context (refer to boost.context)
*
* @param context the to-context (x0)
* @param priv the passed user private data (x1)
*
* @return the from-context (context: x0, priv: x1)
*/
function tb_context_jump, export=1
/* prepare stack space first
*
* 0x70 = align16(13 * 8)
*/
sub sp, sp, #0x70
// save x19 - x30
stp x19, x20, [sp, #0x00]
stp x21, x22, [sp, #0x10]
stp x23, x24, [sp, #0x20]
stp x25, x26, [sp, #0x30]
stp x27, x28, [sp, #0x40]
#ifdef TB_CONFIG_OS_IOS
stp fp, lr, [sp, #0x50]
#else
stp x29, x30, [sp, #0x50]
#endif
// save lr as pc
#ifdef TB_CONFIG_OS_IOS
str lr, [sp, #0x60]
#else
str x30, [sp, #0x60]
#endif
// save the old context(sp) to x4
mov x4, sp
// switch to the new context(sp) and stack
mov sp, x0
// restore x19 - x30
ldp x19, x20, [sp, #0x00]
ldp x21, x22, [sp, #0x10]
ldp x23, x24, [sp, #0x20]
ldp x25, x26, [sp, #0x30]
ldp x27, x28, [sp, #0x40]
#ifdef TB_CONFIG_OS_IOS
ldp fp, lr, [sp, #0x50]
#else
ldp x29, x30, [sp, #0x50]
#endif
/* pass old-context(context: x0, priv: x1) arguments to the context function
*
* and return from-context: retval(context: x0, priv: x1) from jump
*/
mov x0, x4
// load pc
ldr x4, [sp, #0x60]
// restore stack space
add sp, sp, #0x70
// jump to the return or entry address(pc)
ret x4
endfunc
tbox-1.7.6/src/tbox/platform/arch/arm64/prefix.h 0000664 0000000 0000000 00000001630 14671175054 0021416 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_PLATFORM_ARCH_ARM64_PREFIX_H
#define TB_PLATFORM_ARCH_ARM64_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/platform/arch/atomic.h 0000664 0000000 0000000 00000002307 14671175054 0020446 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file atomic.h
*
*/
#ifndef TB_PLATFORM_ARCH_ATOMIC_H
#define TB_PLATFORM_ARCH_ATOMIC_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#if !defined(tb_memory_barrier) && defined(TB_ASSEMBLER_IS_GAS) && (defined(TB_ARCH_x86) || defined(TB_ARCH_x64))
# define tb_memory_barrier() __tb_asm__ __tb_volatile__ ("" ::: "memory")
#endif
#endif
tbox-1.7.6/src/tbox/platform/arch/atomic32.h 0000664 0000000 0000000 00000001743 14671175054 0020616 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file atomic32.h
*
*/
#ifndef TB_PLATFORM_ARCH_ATOMIC32_H
#define TB_PLATFORM_ARCH_ATOMIC32_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#if defined(TB_ARCH_x86) || defined(TB_ARCH_x64)
# include "x86/atomic32.h"
#endif
#endif
tbox-1.7.6/src/tbox/platform/arch/atomic64.h 0000664 0000000 0000000 00000001714 14671175054 0020621 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file atomic64.h
*
*/
#ifndef TB_PLATFORM_ARCH_ATOMIC64_H
#define TB_PLATFORM_ARCH_ATOMIC64_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#if defined(TB_ARCH_x64)
# include "x64/atomic64.h"
#endif
#endif
tbox-1.7.6/src/tbox/platform/arch/context.S 0000664 0000000 0000000 00000002326 14671175054 0020632 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-2020, TBOOX Open Source Group.
*
* @author ruki
* @file context.S
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../../prefix/prefix.S"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_ARCH_x86)
# include "x86/context.S"
#elif defined(TB_ARCH_x64)
# include "x64/context.S"
#elif defined(TB_ARCH_ARM64)
# include "arm64/context.S"
#elif defined(TB_ARCH_ARM)
# include "arm/context.S"
#elif defined(TB_ARCH_MIPS)
# include "mips/context.S"
#endif
tbox-1.7.6/src/tbox/platform/arch/frame.h 0000664 0000000 0000000 00000003706 14671175054 0020270 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file frame.h
*
*/
#ifndef TB_PLATFORM_ARCH_FRAME_H
#define TB_PLATFORM_ARCH_FRAME_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#if defined(TB_ARCH_x86)
# include "x86/frame.h"
#elif defined(TB_ARCH_x64)
# include "x64/frame.h"
#elif defined(TB_ARCH_ARM)
# include "arm/frame.h"
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the first frame address
#if !defined(TB_FIRST_FRAME_POINTER) \
&& defined(TB_COMPILER_IS_GCC) \
&& TB_COMPILER_VERSION_BE(4, 1)
# define TB_FIRST_FRAME_POINTER __builtin_frame_address(0)
#endif
// the current stack frame address
#ifndef TB_CURRENT_STACK_FRAME
# define TB_CURRENT_STACK_FRAME ({ tb_char_t __csf; &__csf; })
#endif
/* the advance stack frame address
*
* by default assume the `next' pointer in struct layout points to the next struct layout.
*/
#ifndef TB_ADVANCE_STACK_FRAME
# define TB_ADVANCE_STACK_FRAME(next) ((tb_frame_layout_t*)(next))
#endif
/* the address is inner than the stack address
*
* by default we assume that the stack grows downward.
*/
#ifndef TB_STACK_INNER_THAN
# define TB_STACK_INNER_THAN <
#endif
#endif
tbox-1.7.6/src/tbox/platform/arch/mips/ 0000775 0000000 0000000 00000000000 14671175054 0017767 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/platform/arch/mips/context.S 0000664 0000000 0000000 00000014632 14671175054 0021605 0 ustar 00root root 0000000 0000000 /*
Copyright Oliver Kowalke 2009.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
/*
* Boost Software License - Version 1.0 - August 17th, 2003
*
* Permission is hereby granted, free of charge, to any person or organization
* obtaining a copy of the software and accompanying documentation covered by
* this license (the "Software") to use, reproduce, display, distribute,
* execute, and transmit the Software, and to prepare derivative works of the
* Software, and to permit third-parties to whom the Software is furnished to
* do so, all subject to the following:
*
* The copyright notices in the Software and this entire statement, including
* the above license grant, this restriction and the following disclaimer,
* must be included in all copies of the Software, in whole or in part, and
* all derivative works of the Software, unless such copies or derivative
* works are solely in the form of machine-executable object code generated by
* a source language processor.
*
* 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/* modified by ruki
*
* - modify stack layout
* - fix some bugs on mips32
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
/* make context (refer to boost.context)
*
*
* --------------------------------------------------------------------------------------
* stackdata: | | context ||
* --------------------------------------------------------------------------------------
* (16-align)
*
* ------------------------------------------------
* context: | s0 | s1 | s2 | s3 | s4 | s5 | s6 |
* ------------------------------------------------
* 0 4 8 12 16 20 24
*
* ------------------------------------
* | \|/
* | __end func retval(from) function arguments
* -----------------------------------------------------------------------------------------------------
* | s7 | fp | retval | ra | pc | gp | context | priv | padding | (a0-a3) | padding |
* -----------------------------------------------------------------------------------------------------
* 28 32 36 40 44 48 52 56 60 64
* |(16-align)
* |
* sp when jump to function
*
*
* @param stackdata the stack data (a0)
* @param stacksize the stack size (a1)
* @param func the entry function (a2)
*
* @return the context pointer (v0)
*/
function tb_context_make, export=1
#ifdef __PIC__
.set noreorder
.cpload $t9
.set reorder
#endif
// save the stack top to v0
addu $v0, $a0, $a1
// reserve space for arguments(a0-a3) of context-function
addiu $v0, $v0, -32
// 16-align of the stack top address
move $v1, $v0
li $v0, -16
and $v0, $v1, $v0
/* reserve space for context-data on context-stack
*
* 64 = align8(60)
*/
addiu $v0, $v0, -64
// context.pc = func
sw $a2, 44($v0)
// context.gp = global pointer
sw $gp, 48($v0)
/* init retval = a writeable space (context)
*
* it will write retval(context, priv) when jump to a new context function entry first
*/
addiu $t0, $v0, 52
sw $t0, 36($v0)
// context.ra = address of label __end
la $t9, __end
sw $t9, 40($v0)
// return pointer to context-data
jr $ra
__end:
// allocate stack frame space and save return address
addiu $sp, $sp, -32
sw $ra, 28($sp)
// exit(0)
move $a0, $zero
lw $t9, %call16(_exit)($gp)
jalr $t9
endfunc
/* jump context (refer to boost.context)
*
* @param retval the from-context (a0)
* @param context the to-context (a1)
* @param priv the passed user private data (a2)
*
* @return the from-context (v0: retval)
*/
function tb_context_jump, export=1
# reserve stack space first
addiu $sp, $sp, -64
// save registers and construct the current context
sw $s0, ($sp)
sw $s1, 4($sp)
sw $s2, 8($sp)
sw $s3, 12($sp)
sw $s4, 16($sp)
sw $s5, 20($sp)
sw $s6, 24($sp)
sw $s7, 28($sp)
sw $fp, 32($sp)
sw $a0, 36($sp) // save retval
sw $ra, 40($sp)
sw $ra, 44($sp) // save ra as pc
sw $gp, 48($sp) // save gp
// save the old context(sp) to a0
move $a0, $sp
// switch to the new context(sp) and stack
move $sp, $a1
// restore registers of the new context
lw $s0, ($sp)
lw $s1, 4($sp)
lw $s2, 8($sp)
lw $s3, 12($sp)
lw $s4, 16($sp)
lw $s5, 20($sp)
lw $s6, 24($sp)
lw $s7, 28($sp)
lw $fp, 32($sp)
lw $t0, 36($sp) // load retval
lw $ra, 40($sp)
lw $t9, 44($sp) // load t9 = pc
lw $gp, 48($sp) // load gp
// restore stack space
addiu $sp, $sp, 64
// return from-context(context: a0, priv: a1) from jump
sw $a0, ($t0)
sw $a2, 4($t0)
// pass old-context(context: a0, priv: a1) arguments to the context function
move $a1, $a2
/* jump to the return or entry address(pc)
*
* ----------------------
* context: | args | padding |
* ----------------------
* 0
* |
* sp
*/
jr $t9
endfunc
tbox-1.7.6/src/tbox/platform/arch/mips/prefix.h 0000664 0000000 0000000 00000001626 14671175054 0021442 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_PLATFORM_ARCH_MIPS_PREFIX_H
#define TB_PLATFORM_ARCH_MIPS_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/platform/arch/prefix.h 0000664 0000000 0000000 00000001614 14671175054 0020467 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_PLATFORM_ARCH_PREFIX_H
#define TB_PLATFORM_ARCH_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/platform/arch/x64/ 0000775 0000000 0000000 00000000000 14671175054 0017440 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/platform/arch/x64/atomic64.h 0000664 0000000 0000000 00000006315 14671175054 0021244 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file atomic64.h
*
*/
#ifndef TB_PLATFORM_ARCH_x64_ATOMIC64_H
#define TB_PLATFORM_ARCH_x64_ATOMIC64_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
#ifndef tb_atomic64_fetch_and_set_explicit
# define tb_atomic64_fetch_and_set_explicit(a, v, mo) tb_atomic64_fetch_and_set_explicit_x64(a, v, mo)
#endif
#ifndef tb_atomic64_compare_and_swap_explicit
# define tb_atomic64_compare_and_swap_explicit(a, p, v, succ, fail) \
tb_atomic64_compare_and_swap_explicit_x64(a, p, v, succ, fail)
#endif
#ifndef tb_atomic64_fetch_and_add_explicit
# define tb_atomic64_fetch_and_add_explicit(a, v, mo) tb_atomic64_fetch_and_add_explicit_x64(a, v, mo)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* inlines
*/
static __tb_inline__ tb_int64_t tb_atomic64_fetch_and_set_explicit_x64(tb_atomic64_t* a, tb_int64_t v, tb_int_t mo)
{
// check
tb_assert(a);
__tb_asm__ __tb_volatile__
(
"lock xchgq %0, %1\n" //!< xchgq v, [a]
: "+r" (v)
: "m" (*a)
: "memory"
);
return v;
}
static __tb_inline__ tb_bool_t tb_atomic64_compare_and_swap_explicit_x64(tb_atomic64_t* a, tb_int64_t* p, tb_int64_t v, tb_int_t succ, tb_int_t fail)
{
// check
tb_assert(a && p);
/*
* cmpxchgl v, [a]:
*
* if (eax == [a])
* {
* zf = 1;
* [a] = v;
* }
* else
* {
* zf = 0;
* eax = [a];
* }
*
*/
tb_int64_t o;
tb_int64_t e = *p;
__tb_asm__ __tb_volatile__
(
"lock cmpxchgq %3, %1 \n" //!< cmpxchgl v, [a]
: "=a" (o)
: "m" (*a), "a" (e), "r" (v)
: "cc", "memory" //!< "cc" means that flags were changed.
);
*p = o;
return o == e;
}
static __tb_inline__ tb_int64_t tb_atomic64_fetch_and_add_explicit_x64(tb_atomic64_t* a, tb_int64_t v, tb_int_t mo)
{
// check
tb_assert(a);
/*
* xaddl v, [a]:
*
* o = [a]
* [a] += v;
* v = o;
*
* cf, ef, of, sf, zf, pf... maybe changed
*/
__tb_asm__ __tb_volatile__
(
"lock xaddq %0, %1 \n" //!< xaddq v, [a]
: "+r" (v)
: "m" (*a)
: "cc", "memory"
);
return v;
}
#endif // TB_ASSEMBLER_IS_GAS
#endif
tbox-1.7.6/src/tbox/platform/arch/x64/context.S 0000664 0000000 0000000 00000020730 14671175054 0021252 0 ustar 00root root 0000000 0000000 /*
Copyright Oliver Kowalke 2009.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
/*
* Boost Software License - Version 1.0 - August 17th, 2003
*
* Permission is hereby granted, free of charge, to any person or organization
* obtaining a copy of the software and accompanying documentation covered by
* this license (the "Software") to use, reproduce, display, distribute,
* execute, and transmit the Software, and to prepare derivative works of the
* Software, and to permit third-parties to whom the Software is furnished to
* do so, all subject to the following:
*
* The copyright notices in the Software and this entire statement, including
* the above license grant, this restriction and the following disclaimer,
* must be included in all copies of the Software, in whole or in part, and
* all derivative works of the Software, unless such copies or derivative
* works are solely in the form of machine-executable object code generated by
* a source language processor.
*
* 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
/**
* translated from x64/context.asm by Alvin
*
* - support mingw/cygwin on windows
*/
#ifdef _WIN32
function(tb_context_make)
// save the stack top to rax
movq %rcx, %rax
addq %rdx, %rax
// reserve space for first argument(from) and retval(from) item of context-function
subq $32, %rax
// 16-align of the stack top address
andq $-16, %rax
// reserve space for context-data on context-stack
subq $112, %rax
// context.rbx = func
movq %r8, 80(%rax)
// save bottom address of context stack as 'limit'
movq %rcx, 16(%rax)
// save address of context stack limit as 'dealloction stack'
movq %rcx, 8(%rax)
// save top address of context stack as 'base'
addq %rdx, %rcx
movq %rcx, 24(%rax)
// init fiber-storage to zero
xorq %rcx, %rcx
movq %rcx, (%rax)
// init context.retval(saved) = a writeable space (unused)
// it will write context (unused) and priv (unused) when jump to a new context function entry first
leaq 128(%rax), %rcx
movq %rcx, 96(%rax)
// context.rip = the address of label __entry
leaq __entry(%rip), %rcx
movq %rcx, 104(%rax)
// context.end = the address of label __end
leaq __end(%rip), %rcx
movq %rcx, 88(%rax)
// return pointer to context-data
ret
__entry:
// patch return address (__end) on stack
push %rbp
// jump to the context function entry(rip)
jmp *%rbx
__end:
xorq %rcx, %rcx
call _exit
hlt
endfunc
function(tb_context_jump)
// save the hidden argument: retval (from-context)
pushq %rcx
// save registers and construct the current context
pushq %rbp
pushq %rbx
pushq %rsi
pushq %rdi
pushq %r15
pushq %r14
pushq %r13
pushq %r12
// load TIB
movq %gs:(0x30), %r10
// save current stack base
movq 0x08(%r10), %rax
pushq %rax
// save current stack limit
movq 0x10(%r10), %rax
pushq %rax
// save current deallocation stack
movq 0x1478(%r10), %rax
pushq %rax
// save fiber local storage
movq 0x18(%r10), %rax
pushq %rax
// save the old context(esp) to r9
movq %rsp, %r9
// switch to the new context(esp) and stack
movq %rdx, %rsp
// load TIB
movq %gs:(0x30), %r10
// restore fiber local storage
popq %rax
movq %rax, 0x18(%r10)
// restore deallocation stack
popq %rax
movq %rax, 0x1478(%r10)
// restore stack limit
popq %rax
mov %rax, 0x10(%r10)
// restore stack base
popq %rax
movq %rax, 0x08(%r10)
// restore registers of the new context
popq %r12
popq %r13
popq %r14
popq %r15
popq %rdi
popq %rsi
popq %rbx
popq %rbp
// restore retval (saved) to rax
popq %rax
// restore the return or function address(r10)
popq %r10
// return from-context(retval: [rcx](context: r9, priv: r8)) from jump
// it will write context (unused) and priv (unused) when jump to a new context function entry first
movq %r9, (%rax)
movq %r8, 8(%rax)
movq %rax, %rcx
// jump to the return or function address(rip)
jmp *%r10
endfunc
#else
/* make context (refer to boost.context)
*
* ------------------------------------------------------------------------------------------
* stackdata: | | context |||||||
* ------------------------------------------------------------------------------------|-----
* (16-align for macosx)
*
* func __end __entry
* ------------------------------------------------------------------------------------------
* context: | r12 | r13 | r14 | r15 | rbx | rbp | rip | args | padding ... |
* ------------------------------------------------------------------------------------------
* 0 8 16 24 32 40 48 56
* | 16-align for macosx
* |
* esp when jump to function
*
* @param stackdata the stack data (rdi)
* @param stacksize the stack size (rsi)
* @param func the entry function (rdx)
*
* @return the context pointer (rax)
*/
function(tb_context_make)
// save the stack top to rax
addq %rsi, %rdi
movq %rdi, %rax
// 16-align for the stack top address
movabs $-16, %r8
andq %r8, %rax
// reserve space for context-data on context-stack
leaq -56(%rax), %rax
// context.rbx = func
movq %rdx, 32(%rax)
// context.rip = the address of label __entry
leaq __entry(%rip), %rcx
movq %rcx, 48(%rax)
// context.end = the address of label __end
leaq __end(%rip), %rcx
movq %rcx, 40(%rax)
// return the context pointer
ret
__entry:
// pass old-context(context: rdi, priv: rsi) argument to the context function
movq %rax, %rdi
// patch __end
push %rbp
/* jump to the context function entry(rip)
*
* -------------------------------
* context: .. | end | args | padding ... |
* -------------------------------
* 0 8
* | 16-align for macosx
* rsp
*/
jmp *%rbx
__end:
// exit(0)
xorq %rdi, %rdi
#ifdef TB_ARCH_ELF
call _exit@PLT
#else
call __exit
#endif
hlt
endfunc
/* jump context (refer to boost.context)
*
* @param context the to-context (rdi)
* @param priv the passed user private data (rsi)
*
* @return the from-context (context: rax, priv: rdx)
*/
function(tb_context_jump)
// save registers and construct the current context
pushq %rbp
pushq %rbx
pushq %r15
pushq %r14
pushq %r13
pushq %r12
// save the old context(rsp) to rax
movq %rsp, %rax
// switch to the new context(rsp) and stack
movq %rdi, %rsp
// restore registers of the new context
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbx
popq %rbp
// restore the return or function address(rip)
popq %r8
// return from-context(context: rax, priv: rdx) from jump
movq %rsi, %rdx
/* jump to the return or function address(rip)
*
* ---------------------
* context: .. | args | padding ... |
* ---------------------
* 0 8
* | 16-align for macosx
* rsp
*/
jmp *%r8
endfunc
#endif
tbox-1.7.6/src/tbox/platform/arch/x64/context.asm 0000664 0000000 0000000 00000020715 14671175054 0021633 0 ustar 00root root 0000000 0000000 ; Copyright Oliver Kowalke 2009.
; Distributed under the Boost Software License, Version 1.0.
; (See accompanying file LICENSE_1_0.txt or copy at
; http://www.boost.org/LICENSE_1_0.txt)
;
; Boost Software License - Version 1.0 - August 17th, 2003
;
; Permission is hereby granted, free of charge, to any person or organization
; obtaining a copy of the software and accompanying documentation covered by
; this license (the "Software") to use, reproduce, display, distribute,
; execute, and transmit the Software, and to prepare derivative works of the
; Software, and to permit third-parties to whom the Software is furnished to
; do so, all subject to the following:
;
; The copyright notices in the Software and this entire statement, including
; the above license grant, this restriction and the following disclaimer,
; must be included in all copies of the Software, in whole or in part, and
; all derivative works of the Software, unless such copies or derivative
; works are solely in the form of machine-executable object code generated by
; a source language processor.
;
; 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
; SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
; FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
; ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
; DEALINGS IN THE SOFTWARE.
;;
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; declaration
;;
; exit(value)
extern _exit:proc
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; implementation
;;
.code
; make context (refer to boost.context)
;
;
; -----------------------------------------------------------------------------------------
; stackdata: | | context |||||||
; -----------------------------------------------------------------------------------|-----
; (16-align)
;
;
; ---------------------------------------
; context: | fiber | dealloc | limit | base |
; ---------------------------------------
; 0 8 16 24
;
; ---------------------------------------
; | r12 | r13 | r14 | r15 |
; ---------------------------------------
; 32 40 48 56 -------------------------------------------------------
; | |
; func __end | __entry arguments retval(from)
; ----------------------------------------------------------------------------------------------------------------------------------
; | rdi | rsi | rbx | rbp | retval(saved) | rip | from(ctx/priv) | context(unused) | priv(unused) | padding |
; ----------------------------------------------------------------------------------------------------------------------------------
; 64 72 80 88 96 104 112 128 136 144
; |
; | 16-align
; |
; rsp when jump to function
;
;
; @param stackdata the stack data (rcx)
; @param stacksize the stack size (rdx)
; @param func the entry function (r8)
;
; @return the context pointer (rax)
;;
tb_context_make proc frame
; .xdata for a function's structured exception handling unwind behavior
.endprolog
; save the stack top to rax
mov rax, rcx
add rax, rdx
; reserve space for first argument(from) and retval(from) item of context-function
; 4 * 8 = 32
sub rax, 32
; 16-align of the stack top address
and rax, -16
; reserve space for context-data on context-stack
sub rax, 112
; context.rbx = func
mov [rax + 80], r8
; save bottom address of context stack as 'limit'
mov [rax + 16], rcx
; save address of context stack limit as 'dealloction stack'
mov [rax + 8], rcx
; save top address of context stack as 'base'
add rcx, rdx
mov [rax + 24], rcx
; init fiber-storage to zero
xor rcx, rcx
mov [rax], rcx
; init context.retval(saved) = a writeable space (unused)
;
; it will write context (unused) and priv (unused) when jump to a new context function entry first
;;
lea rcx, [rax + 128]
mov [rax + 96], rcx
; context.rip = the address of label __entry
lea rcx, __entry
mov [rax + 104], rcx
; context.end = the address of label __end
lea rcx, __end
mov [rax + 88], rcx
; return pointer to context-data
ret
__entry:
; patch return address (__end) on stack
push rbp
; jump to the context function entry(rip)
;
;
;
; -----------------------------------------------------------------
; context: .. | end | unused | context(unused) | priv(unused) | padding |
; -----------------------------------------------------------------
; 0 8 arguments
; |
; rsp 16-align
; (now)
;;
jmp rbx
__end:
; exit(0)
xor rcx, rcx
call _exit
hlt
tb_context_make endp
; jump context (refer to boost.context)
;
; @param retval the from-context (rcx)
; @param context the to-context (rdx)
; @param priv the passed user private data (r8)
;
; @return the from-context (retval: rcx)
;;
tb_context_jump proc frame
; .xdata for a function's structured exception handling unwind behavior
.endprolog
; save the hidden argument: retval (from-context)
push rcx
; save registers and construct the current context
push rbp
push rbx
push rsi
push rdi
push r15
push r14
push r13
push r12
; load TIB
mov r10, gs:[030h]
; save current stack base
mov rax, [r10 + 08h]
push rax
; save current stack limit
mov rax, [r10 + 010h]
push rax
; save current deallocation stack
mov rax, [r10 + 01478h]
push rax
; save fiber local storage
mov rax, [r10 + 018h]
push rax
; save the old context(esp) to r9
mov r9, rsp
; switch to the new context(esp) and stack
mov rsp, rdx
; load TIB
mov r10, gs:[030h]
; restore fiber local storage
pop rax
mov [r10 + 018h], rax
; restore deallocation stack
pop rax
mov [r10 + 01478h], rax
; restore stack limit
pop rax
mov [r10 + 010h], rax
; restore stack base
pop rax
mov [r10 + 08h], rax
; restore registers of the new context
pop r12
pop r13
pop r14
pop r15
pop rdi
pop rsi
pop rbx
pop rbp
; restore retval (saved) to rax
pop rax
; restore the return or function address(r10)
pop r10
; return from-context(retval: [rcx](context: r9, priv: r8)) from jump
;
; it will write context (unused) and priv (unused) when jump to a new context function entry first
;;
mov [rax], r9
mov [rax + 8], r8
; pass old-context(rcx(context: r9, priv: r8)) arguments to the context function
;
; tb_context_from_t from;
; func(from)
;
; lea rcx, address of from
; rcx.context = r9
; rcx.priv = r8
; call func
;;
mov rcx, rax
; jump to the return or function address(rip)
;
;
;
; -----------------------------------------------------------------
; context: .. | end | unused | context(unused) | priv(unused) | padding |
; -----------------------------------------------------------------
; 0 8 arguments
; | |
; rsp 16-align
; (now)
;;
jmp r10
tb_context_jump endp
end
tbox-1.7.6/src/tbox/platform/arch/x64/frame.h 0000664 0000000 0000000 00000003041 14671175054 0020701 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file frame.h
*
*/
#ifndef TB_PLATFORM_ARCH_x64_FRAME_H
#define TB_PLATFORM_ARCH_x64_FRAME_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the current stack frame address
#if !defined(TB_CURRENT_STACK_FRAME) \
&& defined(TB_ASSEMBLER_IS_GAS)
# define TB_CURRENT_STACK_FRAME ({ __tb_register__ tb_char_t* frame __tb_asm__("rsp"); frame; })
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the frame layout type
typedef struct __tb_frame_layout_t
{
// the next
struct __tb_frame_layout_t* next;
// the frame return address
tb_pointer_t return_address;
}tb_frame_layout_t;
#endif
tbox-1.7.6/src/tbox/platform/arch/x64/prefix.h 0000664 0000000 0000000 00000001624 14671175054 0021111 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_PLATFORM_ARCH_x64_PREFIX_H
#define TB_PLATFORM_ARCH_x64_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/platform/arch/x86/ 0000775 0000000 0000000 00000000000 14671175054 0017444 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/platform/arch/x86/atomic32.h 0000664 0000000 0000000 00000006316 14671175054 0021244 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file atomic32.h
*
*/
#ifndef TB_PLATFORM_ARCH_x86_ATOMIC32_H
#define TB_PLATFORM_ARCH_x86_ATOMIC32_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef TB_ASSEMBLER_IS_GAS
#ifndef tb_atomic32_fetch_and_set_explicit
# define tb_atomic32_fetch_and_set_explicit(a, v, mo) tb_atomic32_fetch_and_set_explicit_x86(a, v, mo)
#endif
#ifndef tb_atomic32_compare_and_swap_explicit
# define tb_atomic32_compare_and_swap_explicit(a, p, v, succ, fail) \
tb_atomic32_compare_and_swap_explicit_x86(a, p, v, succ, fail)
#endif
#ifndef tb_atomic32_fetch_and_add_explicit
# define tb_atomic32_fetch_and_add_explicit(a, v, mo) tb_atomic32_fetch_and_add_explicit_x86(a, v, mo)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* inlines
*/
static __tb_inline__ tb_int32_t tb_atomic32_fetch_and_set_explicit_x86(tb_atomic32_t* a, tb_int32_t v, tb_int_t mo)
{
// check
tb_assert(a);
__tb_asm__ __tb_volatile__
(
"lock xchgl %0, %1\n" //!< xchgl v, [a]
: "+r" (v)
: "m" (*a)
: "memory"
);
return v;
}
static __tb_inline__ tb_bool_t tb_atomic32_compare_and_swap_explicit_x86(tb_atomic32_t* a, tb_int32_t* p, tb_int32_t v, tb_int_t succ, tb_int_t fail)
{
// check
tb_assert(a && p);
/*
* cmpxchgl v, [a]:
*
* if (eax == [a])
* {
* zf = 1;
* [a] = v;
* }
* else
* {
* zf = 0;
* eax = [a];
* }
*
*/
tb_int32_t o;
tb_int32_t e = *p;
__tb_asm__ __tb_volatile__
(
"lock cmpxchgl %3, %1 \n" //!< cmpxchgq v, [a]
: "=a" (o)
: "m" (*a), "a" (e), "r" (v)
: "cc", "memory" //!< "cc" means that flags were changed.
);
*p = o;
return o == e;
}
static __tb_inline__ tb_int32_t tb_atomic32_fetch_and_add_explicit_x86(tb_atomic32_t* a, tb_int32_t v, tb_int_t mo)
{
// check
tb_assert(a);
/*
* xaddl v, [a]:
*
* o = [a]
* [a] += v;
* v = o;
*
* cf, ef, of, sf, zf, pf... maybe changed
*/
__tb_asm__ __tb_volatile__
(
"lock xaddl %0, %1 \n" //!< xaddl v, [a]
: "+r" (v)
: "m" (*a)
: "cc", "memory"
);
return v;
}
#endif // TB_ASSEMBLER_IS_GAS
#endif
tbox-1.7.6/src/tbox/platform/arch/x86/context.S 0000664 0000000 0000000 00000036360 14671175054 0021264 0 ustar 00root root 0000000 0000000 /*
Copyright Oliver Kowalke 2009.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
/*
* Boost Software License - Version 1.0 - August 17th, 2003
*
* Permission is hereby granted, free of charge, to any person or organization
* obtaining a copy of the software and accompanying documentation covered by
* this license (the "Software") to use, reproduce, display, distribute,
* execute, and transmit the Software, and to prepare derivative works of the
* Software, and to permit third-parties to whom the Software is furnished to
* do so, all subject to the following:
*
* The copyright notices in the Software and this entire statement, including
* the above license grant, this restriction and the following disclaimer,
* must be included in all copies of the Software, in whole or in part, and
* all derivative works of the Software, unless such copies or derivative
* works are solely in the form of machine-executable object code generated by
* a source language processor.
*
* 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/* modified by ruki
*
* - modify stack layout
* - fix some bugs on macosx i386
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
/**
* translated from x86/context.asm by Alvin
*
* - support mingw/cygwin.. on windows
*/
#if defined(_WIN32)
function(tb_context_make)
// save the stack top to eax
movl 4(%esp), %eax
addl 8(%esp), %eax
movl %eax, %ecx
// reserve space for first argument(from) and seh item of context-function
leal -20(%eax), %eax
// 16-align of the stack top address
andl $-16, %eax
// reserve space for context-data on context-stack
leal -40(%eax), %eax
// save top address of context stack as 'base'
movl %ecx, 12(%eax)
// save bottom address of context-stack as 'limit'
movl 4(%esp), %ecx
movl %ecx, 8(%eax)
// save bottom address of context-stack as 'dealloction stack'
movl %ecx, 4(%eax)
// set fiber-storage as zero
xorl %ecx, %ecx
movl %ecx, (%eax)
// context.ebx = func
movl 12(%esp), %ecx
movl %ecx, 28(%eax)
// context.eip = __entry
movl $__entry, %ecx
movl %ecx, 36(%eax)
// context.ebp = the address of label __end
movl $__end, %ecx
movl %ecx, 32(%eax)
// load the current seh chain from TIB
//assume fs:nothing
movl %fs:(0x0), %ecx
//assume fs:error
__walkchain:
// if (sehitem.prev == 0xffffffff) (last?) goto __found
movl (%ecx), %edx
incl %edx
jz __found
// sehitem = sehitem.prev
decl %edx
xchgl %ecx, %edx
jmp __walkchain
__found:
// context.seh.handler = sehitem.handler
movl 4(%ecx), %ecx
movl %ecx, 60(%eax)
// context.seh.prev = 0xffffffff
movl $0xffffffff, %ecx
movl %ecx, 56(%eax)
// context.seh = the address of context.seh.prev
leal 56(%eax), %ecx
movl %ecx, 16(%eax)
// return pointer to context-data
ret
__entry:
// pass old-context(context: eax, priv: edx) arguments to the context function
movl %eax, (%esp)
movl %edx, 4(%esp)
// patch return address: __end
pushl %ebp
// jump to the context function entry(eip)
jmp *%ebx
__end:
// exit(0)
xorl %eax, %eax
movl %eax, (%esp)
call __exit
hlt
endfunc
function(tb_context_jump)
// save registers and construct the current context
pushl %ebp
pushl %ebx
pushl %esi
pushl %edi
// load TIB to edx
//assume fs:nothing
movl %fs:(0x18), %edx
//assume fs:error
// load and save current seh exception list
movl (%edx), %eax
pushl %eax
// load and save current stack base
movl 0x04(%edx), %eax
pushl %eax
// load and save current stack limit
movl 0x08(%edx), %eax
pushl %eax
// load and save current deallocation stack
movl 0xe0c(%edx), %eax
pushl %eax
// load and save fiber local storage
movl 0x10(%edx), %eax
pushl %eax
// save the old context(esp) to eax
movl %esp, %eax
// switch to the new context(esp) and stack
movl 40(%esp), %ecx
movl %ecx, %esp
// load TIB to edx
//assume fs:nothing
movl %fs:(0x18), %edx
//assume fs:error
// restore fiber local storage (context.fiber)
popl %ecx
movl %ecx, 0x10(%edx)
// restore current deallocation stack (context.dealloc)
popl %ecx
movl %ecx, 0xe0c(%edx)
// restore current stack limit (context.limit)
popl %ecx
movl %ecx, 0x08(%edx)
// restore current stack base (context.base)
popl %ecx
movl %ecx, 0x04(%edx)
// restore current seh exception list (context.seh)
popl %ecx
movl %ecx, (%edx)
// restore registers of the new context
popl %edi
popl %esi
popl %ebx
popl %ebp
// restore the return or function address(ecx)
popl %ecx
// return from-context(context: eax, priv: edx) from jump
// edx = [eax + 44] = [esp_jump + 44] = jump.argument(priv)
movl 44(%eax), %edx
// jump to the return or function address(eip)
jmp *%ecx
endfunc
#elif defined(TB_CONFIG_OS_MACOSX) || defined(TB_CONFIG_OS_IOS)
/* make context
*
*
* -----------------------------------------------------------------------------------------
* stackdata: | | context |||||||
* -----------------------------------------------------------------------------------|-----
* (16-align for macosx)
*
*
* func __end __entry from
* --------------------------------------------------------------------------------
* context: | edi | esi | ebx | ebp | eip | context | priv | padding |
* --------------------------------------------------------------------------------
* 0 4 8 12 16 20 24 arguments
* |
* | 16-align for macosx
* |
* esp when jump to function
*
* @param stackdata the stack data (esp + 4)
* @param stacksize the stack size (esp + 8)
* @param func the entry function (esp + 12)
*
* @return the context pointer (eax)
*/
function(tb_context_make)
// save the stack top to eax
movl 4(%esp), %eax
addl 8(%esp), %eax
// reserve space for first argument(from) of context-function
leal -8(%eax), %eax
// 16-align of the stack top address for macosx
andl $-16, %eax
// reserve space for context-data on context-stack
leal -20(%eax), %eax
/* context.ebx = func
*
* @note ebp will be affected only when enter into the context function first
*/
movl 12(%esp), %edx
movl %edx, 8(%eax)
// context.eip = the address of label __entry
call 1f
1: popl %ecx
addl $__entry - 1b, %ecx
movl %ecx, 16(%eax)
/* context.ebp = the address of label __end
*
* @note ebp will be affected only when enter into the context function first
*/
call 2f
2: popl %ecx
addl $__end - 2b, %ecx
movl %ecx, 12(%eax)
// return the context pointer
ret
__entry:
// pass old-arguments(context: eax, priv: edx) to the context function
movl %eax, (%esp)
movl %edx, 0x4(%esp)
// patch __end, retval = the address of label __end
pushl %ebp
/* jump to the context function entry
*
* patch __end
* |
* | old-context
* ----|------------------------------------
* context: .. | retval | context | priv | padding |
* -----------------------------------------
* 0 4 arguments
* | |
* esp 16-align
* (now)
*/
jmp *%ebx
__end:
// exit(0)
xorl %eax, %eax
movl %eax, (%esp)
#ifdef TB_ARCH_ELF
call _exit@PLT
#else
call __exit
#endif
hlt
endfunc
/* jump context
*
* @param context the to-context (esp + 4)
* @param priv the passed user private data (esp + 8)
*
* @return the from-context (context: eax, priv: edx)
*/
function(tb_context_jump)
// save registers and construct the current context
pushl %ebp
pushl %ebx
pushl %esi
pushl %edi
// save the old context(esp) to eax
movl %esp, %eax
// ecx = argument(context)
movl 20(%esp), %ecx
// edx = argument(priv)
movl 24(%esp), %edx
// switch to the new context(esp) and stack
movl %ecx, %esp
// restore registers of the new context
popl %edi
popl %esi
popl %ebx
popl %ebp
// restore the return or function address(ecx)
popl %ecx
// return from-context(context: eax, priv: edx) from jump
// ...
/* jump to the return or function address(eip)
*
*
* old-context
* --------------------------------
* context: .. | context | priv | padding |
* --------------------------------
* 0 4 arguments
* |
* esp 16-align for macosx
* (now)
*/
jmp *%ecx
endfunc
#else
/* make context (refer to boost.context)
*
*
* -----------------------------------------------------------------------------------------
* stackdata: | | context |||||||
* -----------------------------------------------------------------------------------|-----
* (16-align)
*
*
* func __end __entry from
* -----------------------------------------------------------------------------------------
* context: | edi | esi | ebx | ebp | eip | retval | context | priv | padding |
* -----------------------------------------------------------------------------------------
* 0 4 8 12 16 20 24 arguments
* | |
* | 16-align
* |
* esp when jump to function
*
* @param stackdata the stack data (esp + 4)
* @param stacksize the stack size (esp + 8)
* @param func the entry function (esp + 12)
*
* @return the context pointer (eax)
*/
function(tb_context_make)
// save the stack top to eax
movl 4(%esp), %eax
addl 8(%esp), %eax
// reserve space for first argument(from) of context-function
leal -8(%eax), %eax
// 16-align of the stack top address for macosx
andl $-16, %eax
// reserve space for context-data on context-stack
leal -24(%eax), %eax
/* context.ebx = func
*
* @note ebp will be affected only when enter into the context function first
*/
movl 12(%esp), %edx
movl %edx, 8(%eax)
/* init retval = a writeable space (context)
*
* it will write context.edi and context.esi (unused) when jump to a new context function entry first
*/
movl %eax, 20(%eax)
// context.eip = the address of label __entry
call 1f
1: popl %ecx
addl $__entry - 1b, %ecx
movl %ecx, 16(%eax)
/* context.ebp = the address of label __end
*
* @note ebp will be affected only when enter into the context function first
*/
call 2f
2: popl %ecx
addl $__end - 2b, %ecx
movl %ecx, 12(%eax)
// return the context pointer
ret
__entry:
/* pass arguments(context: eax, priv: edx) to the context function
*
* patch __end
* |
* | old-context
* ----|------------------------------------
* context: .. | retval | context | priv | padding |
* -----------------------------------------
* 0 4 arguments
* | |
* esp 16-align
* (now)
*/
movl %eax, (%esp)
movl %edx, 0x4(%esp)
// retval = the address of label __end
pushl %ebp
/* jump to the context function entry
*
* @note need not adjust stack pointer(+4) using 'ret $4' when enter into function first
*/
jmp *%ebx
__end:
// exit(0)
xorl %eax, %eax
movl %eax, (%esp)
#ifdef TB_ARCH_ELF
call _exit@PLT
#else
call __exit
#endif
hlt
endfunc
/* jump context (refer to boost.context)
*
* @code
*
* subl $4, %esp <---- padding (need ret $4)
* pushl priv
* pushl context
* pushl retval
* call tb_context_jump
* addl $12, %esp
*
* tb_context_jump():
* ret 4
*
* @endcode
*
* @param retval the from-context (esp + 4)
* @param context the to-context (esp + 8)
* @param priv the passed user private data (esp + 12)
*
* @return the from-context (retval (esp + 4))
*/
function(tb_context_jump)
// save registers and construct the current context
pushl %ebp
pushl %ebx
pushl %esi
pushl %edi
// save the old context(esp) to eax
movl %esp, %eax
// ecx = argument(context)
movl 24(%esp), %ecx
// edx = argument(priv)
movl 28(%esp), %edx
// switch to the new context(esp) and stack
movl %ecx, %esp
// restore registers of the new context
popl %edi
popl %esi
popl %ebx
popl %ebp
/* return from-context(retval: [to_esp + 4](context: eax, priv: edx)) from jump
*
* it will write context.edi and context.esi (unused) when jump to a new context function entry first
*/
movl 4(%esp), %ecx
movl %eax, (%ecx)
movl %edx, 4(%ecx)
/* jump to the return or entry address(eip)
*
* @note need adjust stack pointer(+4) when return from tb_context_jump()
*
* old-context
* ---------------------------------------------------
* context: .. | eip | retval | context | priv | padding |
* ---------------------------------------------------
* 0 4 8 arguments
* | |
* esp 16-align
* (now)
*/
ret $4
endfunc
#endif
tbox-1.7.6/src/tbox/platform/arch/x86/context.asm 0000664 0000000 0000000 00000027711 14671175054 0021642 0 ustar 00root root 0000000 0000000 ; Copyright Oliver Kowalke 2009.
; Distributed under the Boost Software License, Version 1.0.
; (See accompanying file LICENSE_1_0.txt or copy at
; http://www.boost.org/LICENSE_1_0.txt)
;
; Boost Software License - Version 1.0 - August 17th, 2003
;
; Permission is hereby granted, free of charge, to any person or organization
; obtaining a copy of the software and accompanying documentation covered by
; this license (the "Software") to use, reproduce, display, distribute,
; execute, and transmit the Software, and to prepare derivative works of the
; Software, and to permit third-parties to whom the Software is furnished to
; do so, all subject to the following:
;
; The copyright notices in the Software and this entire statement, including
; the above license grant, this restriction and the following disclaimer,
; must be included in all copies of the Software, in whole or in part, and
; all derivative works of the Software, unless such copies or derivative
; works are solely in the form of machine-executable object code generated by
; a source language processor.
;
; 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
; SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
; FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
; ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
; DEALINGS IN THE SOFTWARE.
;;
; modified by ruki
;
; - modify stack layout
; - remove trampoline to optimize switch performance
;;
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; prefix
;;
.386
.model flat, c
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; declaration
;;
; exit(value)
_exit proto, value:sdword
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Contents of the TIB (32-bit Windows)
;;
; FS:[0x00] * Current Structured Exception Handling (SEH) frame
; FS:[0x04] * Stack Base / Bottom of stack (high address)
; FS:[0x08] * Stack Limit / Ceiling of stack (low address)
; FS:[0x0C] SubSystemTib
; FS:[0x10] * Fiber data
; FS:[0x14] Arbitrary data slot
; FS:[0x18] * Linear address of TEB
; FS:[0x1C] Environment Pointer
; FS:[0x20] Process ID (in some windows distributions this field is used as 'DebugContext')
; FS:[0x24] Current thread ID
; FS:[0x28] Active RPC Handle
; FS:[0x2C] Linear address of the thread-local storage array
; FS:[0x30] Linear address of Process Environment Block (PEB)
; FS:[0x34] Last error number
; FS:[0x38] Count of owned critical sections
; FS:[0x3C] Address of CSR Client Thread
; FS:[0x40] Win32 Thread Information
; FS:[0x44] Win32 client information (NT), user32 private data (Wine), 0x60 = LastError (Win95), 0x74 = LastError (WinME)
; FS:[0xC0] Reserved for Wow64. Contains a pointer to FastSysCall in Wow64.
; FS:[0xC4] Current Locale
; FS:[0xC8] FP Software Status Register
; FS:[0xCC] Reserved for OS (NT), kernel32 private data (Wine)
; FS:[0x1A4] Exception code
; FS:[0x1A8] Activation context stack
; FS:[0x1BC] Spare bytes (NT), ntdll private data (Wine)
; FS:[0x1D4] Reserved for OS (NT), ntdll private data (Wine)
; FS:[0x1FC] GDI TEB Batch (OS), vm86 private data (Wine)
; FS:[0x6DC] GDI Region
; FS:[0x6E0] GDI Pen
; FS:[0x6E4] GDI Brush
; FS:[0x6E8] Real Process ID
; FS:[0x6EC] Real Thread ID
; FS:[0x6F0] GDI cached process handle
; FS:[0x6F4] GDI client process ID (PID)
; FS:[0x6F8] GDI client thread ID (TID)
; FS:[0x6FC] GDI thread locale information
; FS:[0x700] Reserved for user application
; FS:[0x714] Reserved for GL
; FS:[0xBF4] Last Status Value
; FS:[0xBF8] Static UNICODE_STRING buffer
; FS:[0xE0C] * Pointer to deallocation stack
; FS:[0xE10] TLS slots, 4 byte per slot
; FS:[0xF10] TLS links (LIST_ENTRY structure)
; FS:[0xF18] VDM
; FS:[0xF1C] Reserved for RPC
; FS:[0xF28] Thread error mode (RtlSetThreadErrorMode)
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Structured Exception Handling (SEH) frame
;;
; ---------- ----------
; FS:[0x00] -> | prev | -> | prev | -> ... -> 0xffffffff (end)
; |----------| |----------|
; | handler | | handler |
; ---------- ----------
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; implementation
;;
.code
; make context (refer to boost.context)
;
; -----------------------------------------------------------------------------------------
; stackdata: | | context |||||||
; -----------------------------------------------------------------------------------|-----
; (16-align)
;
;
; -------------------------------------------------
; context: | fiber | dealloc | limit | base | seh | ----------------------------
; ------------------------------------------------- |
; 0 4 8 12 16 | seh chain for context function
; |
; |
; func __end __entry arguments(from) \|/
; -----------------------------------------------------------------------------------------------------------------------------------------
; | edi | esi | ebx | ebp | eip | context | priv | unused | seh.prev (0xffffffff) | seh.handler | padding |
; -----------------------------------------------------------------------------------------------------------------------------------------
; 20 24 28 32 36 40 44 48 52 56 60
; |
; | 16-align
; |
; esp when jump to function
;
; @param stackdata the stack data (esp + 4)
; @param stacksize the stack size (esp + 8)
; @param func the entry function (esp + 12)
;
; @return the context pointer (eax)
;;
tb_context_make proc
; save the stack top to eax
mov eax, [esp + 4]
add eax, [esp + 8]
mov ecx, eax
; reserve space for first argument(from) and seh item of context-function
; 5 * 4 = 20
lea eax, [eax - 20]
; 16-align of the stack top address
and eax, -16
; reserve space for context-data on context-stack
lea eax, [eax - 40]
; save top address of context stack as 'base'
mov [eax + 12], ecx
; save bottom address of context-stack as 'limit'
mov ecx, [esp + 4]
mov [eax + 8], ecx
; save bottom address of context-stack as 'dealloction stack'
mov [eax + 4], ecx
; set fiber-storage as zero
xor ecx, ecx
mov [eax], ecx
; context.ebx = func
mov ecx, [esp + 12]
mov [eax + 28], ecx
; context.eip = __entry
mov ecx, __entry
mov [eax + 36], ecx
; context.ebp = the address of label __end
mov ecx, __end
mov [eax + 32], ecx
; install seh chain when enter into the context function
;
; traverse current seh chain to get the last exception handler installed by Windows
; note that on Windows Server 2008 and 2008 R2, SEHOP is activated by default
;
; the exception handler chain is tested for the presence of ntdll.dll!FinalExceptionHandler
; at its end by RaiseException all seh-handlers are disregarded if not present and the
; program is aborted
;
; load the current seh chain from TIB
assume fs:nothing
mov ecx, fs:[0h]
assume fs:error
__walkchain:
; if (sehitem.prev == 0xffffffff) (last?) goto __found
mov edx, [ecx]
inc edx
jz __found
; sehitem = sehitem.prev
dec edx
xchg edx, ecx
jmp __walkchain
__found:
; context.seh.handler = sehitem.handler
mov ecx, [ecx + 4]
mov [eax + 56], ecx
; context.seh.prev = 0xffffffff
mov ecx, 0ffffffffh
mov [eax + 52], ecx
; context.seh = the address of context.seh.prev
lea ecx, [eax + 52]
mov [eax + 16], ecx
; return pointer to context-data
ret
__entry:
; pass old-context(context: eax, priv: edx) arguments to the context function
mov [esp], eax
mov [esp + 4], edx
; patch return address: __end
push ebp
; jump to the context function entry(eip)
;
;
; old-context
; ------------------------------------------
; context: .. | end | context | priv | ... |
; ------------------------------------------
; 0 4 arguments
; | |
; esp 16-align
; (now)
;;
jmp ebx
__end:
; exit(0)
xor eax, eax
mov [esp], eax
call _exit
hlt
tb_context_make endp
; jump context (refer to boost.context)
;
; optimzation (jump context faster 30% than boost.context):
; - adjust context stack layout (patch end behind eip)
; - remove trampoline and jump to context function directly
;
; @param context the to-context (esp + 4)
; @param priv the passed user private data (esp + 8)
;
; @return the from-context (context: eax, priv: edx)
;;
tb_context_jump proc
; save registers and construct the current context
push ebp
push ebx
push esi
push edi
; load TIB to edx
assume fs:nothing
mov edx, fs:[018h]
assume fs:error
; load and save current seh exception list
mov eax, [edx]
push eax
; load and save current stack base
mov eax, [edx + 04h]
push eax
; load and save current stack limit
mov eax, [edx + 08h]
push eax
; load and save current deallocation stack
mov eax, [edx + 0e0ch]
push eax
; load and save fiber local storage
mov eax, [edx + 010h]
push eax
; save the old context(esp) to eax
mov eax, esp
; switch to the new context(esp) and stack
mov ecx, [esp + 40]
mov esp, ecx
; load TIB to edx
assume fs:nothing
mov edx, fs:[018h]
assume fs:error
; restore fiber local storage (context.fiber)
pop ecx
mov [edx + 010h], ecx
; restore current deallocation stack (context.dealloc)
pop ecx
mov [edx + 0e0ch], ecx
; restore current stack limit (context.limit)
pop ecx
mov [edx + 08h], ecx
; restore current stack base (context.base)
pop ecx
mov [edx + 04h], ecx
; restore current seh exception list (context.seh)
pop ecx
mov [edx], ecx
; restore registers of the new context
pop edi
pop esi
pop ebx
pop ebp
; restore the return or function address(ecx)
pop ecx
; return from-context(context: eax, priv: edx) from jump
;
; edx = [eax + 44] = [esp_jump + 44] = jump.argument(priv)
;
mov edx, [eax + 44]
; jump to the return or function address(eip)
;
;
; old-context
; --------------------------------
; context: .. | context | priv | ... |
; --------------------------------
; 0 arguments
; |
; esp
; (now)
;;
jmp ecx
tb_context_jump endp
end
tbox-1.7.6/src/tbox/platform/arch/x86/frame.h 0000664 0000000 0000000 00000003040 14671175054 0020704 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file frame.h
*
*/
#ifndef TB_PLATFORM_ARCH_x86_FRAME_H
#define TB_PLATFORM_ARCH_x86_FRAME_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the current stack frame address
#if !defined(TB_CURRENT_STACK_FRAME) \
&& defined(TB_COMPILER_IS_GCC) \
&& TB_COMPILER_VERSION_BE(4, 1)
# define TB_CURRENT_STACK_FRAME __builtin_frame_address(0)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the frame layout type
typedef struct __tb_frame_layout_t
{
// the next
struct __tb_frame_layout_t* next;
// the frame return address
tb_pointer_t return_address;
}tb_frame_layout_t;
#endif
tbox-1.7.6/src/tbox/platform/arch/x86/prefix.h 0000664 0000000 0000000 00000001624 14671175054 0021115 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_PLATFORM_ARCH_x86_PREFIX_H
#define TB_PLATFORM_ARCH_x86_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/platform/atomic.h 0000664 0000000 0000000 00000034314 14671175054 0017534 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file atomic.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_ATOMIC_H
#define TB_PLATFORM_ATOMIC_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#if __tb_has_feature__(c_atomic) && !defined(__STDC_NO_ATOMICS__)
# include "libc/atomic.h"
#elif defined(TB_COMPILER_IS_GCC) && defined(__ATOMIC_SEQ_CST)
# include "compiler/gcc/atomic.h"
#elif defined(TB_CONFIG_OS_WINDOWS)
# include "windows/atomic.h"
#endif
#include "arch/atomic.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/// the atomic flag initialize value
#ifndef TB_ATOMIC_FLAG_INIT
# define TB_ATOMIC_FLAG_INIT {0}
#endif
/// no barriers or synchronization.
#ifndef TB_ATOMIC_RELAXED
# define TB_ATOMIC_RELAXED (1)
#endif
/// data dependency only for both barrier and synchronization with another thread.
#ifndef TB_ATOMIC_CONSUME
# define TB_ATOMIC_CONSUME (2)
#endif
/// barrier to hoisting of code and synchronizes with release (or stronger) semantic stores from another thread.
#ifndef TB_ATOMIC_ACQUIRE
# define TB_ATOMIC_ACQUIRE (3)
#endif
/// barrier to sinking of code and synchronizes with acquire (or stronger) semantic loads from another thread.
#ifndef TB_ATOMIC_RELEASE
# define TB_ATOMIC_RELEASE (4)
#endif
/// full barrier in both directions and synchronizes with acquire loads and release stores in another thread.
#ifndef TB_ATOMIC_ACQ_REL
# define TB_ATOMIC_ACQ_REL (5)
#endif
/// full barrier in both directions and synchronizes with acquire loads and release stores in all threads.
#ifndef TB_ATOMIC_SEQ_CST
# define TB_ATOMIC_SEQ_CST (6)
#endif
/// memory barrier (full barrier)
#ifndef tb_memory_barrier
# define tb_memory_barrier()
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "atomic32.h"
#include "atomic64.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/*! initializes the default-constructed atomic object obj with the value desired.
*
* the function is not atomic: concurrent access from another thread, even through an atomic operation, is a data race.
*/
#if TB_CPU_BIT64
# define tb_atomic_init(a, v) tb_atomic64_init(a, (tb_int64_t)(v))
#else
# define tb_atomic_init(a, v) tb_atomic32_init(a, (tb_int32_t)(v))
#endif
/*! atomically compares the contents of memory pointed to by obj with the contents of memory pointed to by expected,
* and if those are bitwise equal, replaces the former with desired (performs read-modify-write operation).
*
* otherwise, loads the actual contents of memory pointed to by obj into *p (performs load operation).
*
* @param a pointer to the atomic object to test and modify
* @param p pointer to the value expected to be found in the atomic object
* @param v the value to store in the atomic object if it is as expected
*
* @return the result of the comparison: true if *a was equal to *p, false otherwise.
* - succ the memory synchronization ordering for the read-modify-write operation if the comparison succeeds. All values are permitted.
* - fail the memory synchronization ordering for the load operation if the comparison fails. Cannot be memory_order_release or memory_order_acq_rel and cannot specify stronger ordering than succ
*
* @code
* tb_atomic_init(&a, 1);
*
* tb_long_t expected = 1;
* if (tb_atomic_compare_and_swap(&a, &expected, 2)) {
* // *a = 2
* } else {
* // expected = *a
* }
* @endcode
*/
#if TB_CPU_BIT64
# define tb_atomic_compare_and_swap_explicit(a, p, v, succ, fail) \
tb_atomic64_compare_and_swap_explicit(a, (tb_int64_t*)(p), (tb_int64_t)(v), succ, fail)
# define tb_atomic_compare_and_swap(a, p, v) tb_atomic64_compare_and_swap(a, (tb_int64_t*)(p), (tb_int64_t)(v))
#else
# define tb_atomic_compare_and_swap_explicit(a, p, v, succ, fail) \
tb_atomic32_compare_and_swap_explicit(a, (tb_int32_t*)(p), (tb_int32_t)(v), succ, fail)
# define tb_atomic_compare_and_swap(a, p, v) tb_atomic32_compare_and_swap(a, (tb_int32_t*)(p), (tb_int32_t)(v))
#endif
/*! like tb_atomic_compare_and_swap(), but it's allowed to fail spuriously, that is, act as if *obj != *p even if they are equal.
*
* when a compare-and-swap is in a loop, the weak version will yield better performance on some platforms.
* when a weak compare-and-swap would require a loop and a strong one would not, the strong one is preferable.
*
* @param a pointer to the atomic object to test and modify
* @param p pointer to the value expected to be found in the atomic object
* @param v the value to store in the atomic object if it is as expected
*
* @return the result of the comparison: true if *a was equal to *p, false otherwise.
* - succ the memory synchronization ordering for the read-modify-write operation if the comparison succeeds. All values are permitted.
* - fail the memory synchronization ordering for the load operation if the comparison fails. Cannot be memory_order_release or memory_order_acq_rel and cannot specify stronger ordering than succ
*/
#if TB_CPU_BIT64
# define tb_atomic_compare_and_swap_weak_explicit(a, p, v, succ, fail) \
tb_atomic64_compare_and_swap_weak_explicit(a, (tb_int64_t*)(p), (tb_int64_t)(v), succ, fail)
# define tb_atomic_compare_and_swap_weak(a, p, v) tb_atomic64_compare_and_swap_weak(a, (tb_int64_t*)(p), (tb_int64_t)(v))
#else
# define tb_atomic_compare_and_swap_weak_explicit(a, p, v, succ, fail) \
tb_atomic32_compare_and_swap_weak_explicit(a, (tb_int32_t*)(p), (tb_int32_t)(v), succ, fail)
# define tb_atomic_compare_and_swap_weak(a, p, v) tb_atomic32_compare_and_swap_weak(a, (tb_int32_t*)(p), (tb_int32_t)(v))
#endif
/// fetch the atomic value and compare and set value
#if TB_CPU_BIT64
# define tb_atomic_fetch_and_cmpset_explicit(a, p, v, succ, fail) \
(tb_long_t)tb_atomic64_fetch_and_cmpset_explicit(a, (tb_int64_t)(p), (tb_int64_t)(v), succ, fail)
# define tb_atomic_fetch_and_cmpset(a, p, v) (tb_long_t)tb_atomic64_fetch_and_cmpset(a, (tb_int64_t)(p), (tb_int64_t)(v))
#else
# define tb_atomic_fetch_and_cmpset_explicit(a, p, v, succ, fail) \
(tb_long_t)tb_atomic32_fetch_and_cmpset_explicit(a, (tb_int32_t)(p), (tb_int32_t)(v), succ, fail)
# define tb_atomic_fetch_and_cmpset(a, p, v) (tb_long_t)tb_atomic32_fetch_and_cmpset(a, (tb_int32_t)(p), (tb_long_t)(v))
#endif
/// fetch the atomic value and set value
#if TB_CPU_BIT64
# define tb_atomic_fetch_and_set_explicit(a, v, mo) (tb_long_t)tb_atomic64_fetch_and_set_explicit(a, (tb_int64_t)(v), mo)
# define tb_atomic_fetch_and_set(a, v) (tb_long_t)tb_atomic64_fetch_and_set(a, (tb_int64_t)(v))
#else
# define tb_atomic_fetch_and_set_explicit(a, v, mo) (tb_long_t)tb_atomic32_fetch_and_set_explicit(a, (tb_int32_t)(v), mo)
# define tb_atomic_fetch_and_set(a, v) (tb_long_t)tb_atomic32_fetch_and_set(a, (tb_int32_t)(v))
#endif
/// fetch the atomic value and compute add value
#if TB_CPU_BIT64
# define tb_atomic_fetch_and_add_explicit(a, v, mo) (tb_long_t)tb_atomic64_fetch_and_add_explicit(a, (tb_int64_t)(v), mo)
# define tb_atomic_fetch_and_add(a, v) (tb_long_t)tb_atomic64_fetch_and_add(a, (tb_int64_t)(v))
#else
# define tb_atomic_fetch_and_add_explicit(a, v, mo) (tb_long_t)tb_atomic32_fetch_and_add_explicit(a, (tb_int32_t)(v), mo)
# define tb_atomic_fetch_and_add(a, v) (tb_long_t)tb_atomic32_fetch_and_add(a, (tb_int32_t)(v))
#endif
/// fetch the atomic value and compute sub value
#if TB_CPU_BIT64
# define tb_atomic_fetch_and_sub_explicit(a, v, mo) (tb_long_t)tb_atomic64_fetch_and_sub_explicit(a, (tb_int64_t)(v), mo)
# define tb_atomic_fetch_and_sub(a, v) (tb_long_t)tb_atomic64_fetch_and_sub(a, (tb_int64_t)(v))
#else
# define tb_atomic_fetch_and_sub_explicit(a, v, mo) (tb_long_t)tb_atomic32_fetch_and_sub_explicit(a, (tb_int32_t)(v), mo)
# define tb_atomic_fetch_and_sub(a, v) (tb_long_t)tb_atomic32_fetch_and_sub(a, (tb_int32_t)(v))
#endif
/// fetch the atomic value and compute or value
#if TB_CPU_BIT64
# define tb_atomic_fetch_and_or_explicit(a, v, mo) (tb_long_t)tb_atomic64_fetch_and_or_explicit(a, (tb_int64_t)(v), mo)
# define tb_atomic_fetch_and_or(a, v) (tb_long_t)tb_atomic64_fetch_and_or(a, (tb_int64_t)(v))
#else
# define tb_atomic_fetch_and_or_explicit(a, v, mo) (tb_long_t)tb_atomic32_fetch_and_or_explicit(a, (tb_int32_t)(v), mo)
# define tb_atomic_fetch_and_or(a, v) (tb_long_t)tb_atomic32_fetch_and_or(a, (tb_int32_t)(v))
#endif
/// fetch the atomic value and compute xor operation
#if TB_CPU_BIT64
# define tb_atomic_fetch_and_xor_explicit(a, v, mo) (tb_long_t)tb_atomic64_fetch_and_xor_explicit(a, (tb_int64_t)(v), mo)
# define tb_atomic_fetch_and_xor(a, v) (tb_long_t)tb_atomic64_fetch_and_xor(a, (tb_int64_t)(v))
#else
# define tb_atomic_fetch_and_xor_explicit(a, v, mo) (tb_long_t)tb_atomic32_fetch_and_xor_explicit(a, (tb_int32_t)(v), mo)
# define tb_atomic_fetch_and_xor(a, v) (tb_long_t)tb_atomic32_fetch_and_xor(a, (tb_int32_t)(v))
#endif
/// fetch the atomic value and compute and operation
#if TB_CPU_BIT64
# define tb_atomic_fetch_and_and_explicit(a, v, mo) (tb_long_t)tb_atomic64_fetch_and_and_explicit(a, (tb_int64_t)(v), mo)
# define tb_atomic_fetch_and_and(a, v) (tb_long_t)tb_atomic64_fetch_and_and(a, (tb_int64_t)(v))
#else
# define tb_atomic_fetch_and_and_explicit(a, v, mo) (tb_long_t)tb_atomic32_fetch_and_and_explicit(a, (tb_int32_t)(v), mo)
# define tb_atomic_fetch_and_and(a, v) (tb_long_t)tb_atomic32_fetch_and_and(a, (tb_int32_t)(v))
#endif
/// get the atomic value
#if TB_CPU_BIT64
# define tb_atomic_get_explicit(a, mo) (tb_long_t)tb_atomic64_get_explicit(a, mo)
# define tb_atomic_get(a) (tb_long_t)tb_atomic64_get(a)
#else
# define tb_atomic_get_explicit(a, mo) (tb_long_t)tb_atomic32_get_explicit(a, mo)
# define tb_atomic_get(a) (tb_long_t)tb_atomic32_get(a)
#endif
/// set the atomic value
#if TB_CPU_BIT64
# define tb_atomic_set_explicit(a, v, mo) tb_atomic64_set_explicit(a, (tb_int64_t)(v), mo)
# define tb_atomic_set(a, v) tb_atomic64_set(a, (tb_int64_t)(v))
#else
# define tb_atomic_set_explicit(a, v, mo) tb_atomic32_set_explicit(a, (tb_int32_t)(v), mo)
# define tb_atomic_set(a, v) tb_atomic32_set(a, (tb_int32_t)(v))
#endif
/// sets an atomic_flag to true and returns the old value
#ifndef tb_atomic_flag_test_and_set_explicit
# define tb_atomic_flag_test_and_set_explicit_generic_impl
# define tb_atomic_flag_test_and_set_explicit(a, mo) tb_atomic_flag_test_and_set_explicit_generic(a, mo)
#endif
#ifndef tb_atomic_flag_test_and_set
# define tb_atomic_flag_test_and_set(a) tb_atomic_flag_test_and_set_explicit(a, TB_ATOMIC_SEQ_CST)
#endif
/// returns the test result of an atomic_flag
#ifndef tb_atomic_flag_test_explicit
# define tb_atomic_flag_test_explicit_generic_impl
# define tb_atomic_flag_test_explicit(a, mo) tb_atomic_flag_test_explicit_generic(a, mo)
#endif
#ifndef tb_atomic_flag_test
# define tb_atomic_flag_test(a) tb_atomic_flag_test_explicit(a, TB_ATOMIC_SEQ_CST)
#endif
/// sets an atomic_flag to false
#ifndef tb_atomic_flag_clear_explicit
# define tb_atomic_flag_clear_explicit_generic_impl
# define tb_atomic_flag_clear_explicit(a, mo) tb_atomic_flag_clear_explicit_generic(a, mo)
#endif
#ifndef tb_atomic_flag_clear
# define tb_atomic_flag_clear(a) tb_atomic_flag_clear_explicit(a, TB_ATOMIC_SEQ_CST)
#endif
/// get value of an atomic_flag directly (non-atomic)
#ifndef tb_atomic_flag_test_noatomic
# define tb_atomic_flag_test_noatomic(a) ((a)->__val)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#ifdef TB_CONFIG_API_HAVE_DEPRECATED
# include "deprecated/atomic.h"
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* inline implementation
*/
#ifdef tb_atomic_flag_test_and_set_explicit_generic_impl
static __tb_inline__ tb_bool_t tb_atomic_flag_test_and_set_explicit_generic(tb_atomic_flag_t* a, tb_int_t mo)
{
tb_assert(a);
tb_assert_static(sizeof(tb_atomic_flag_t) == sizeof(tb_atomic32_t));
return (tb_bool_t)tb_atomic32_fetch_and_set_explicit((tb_atomic32_t*)a, 1, mo);
}
#endif
#ifdef tb_atomic_flag_test_explicit_generic_impl
static __tb_inline__ tb_bool_t tb_atomic_flag_test_explicit_generic(tb_atomic_flag_t* a, tb_int_t mo)
{
tb_assert(a);
tb_assert_static(sizeof(tb_atomic_flag_t) == sizeof(tb_atomic32_t));
return (tb_bool_t)tb_atomic32_get_explicit((tb_atomic32_t*)a, mo);
}
#endif
#ifdef tb_atomic_flag_clear_explicit_generic_impl
static __tb_inline__ tb_void_t tb_atomic_flag_clear_explicit_generic(tb_atomic_flag_t* a, tb_int_t mo)
{
tb_assert(a);
tb_assert_static(sizeof(tb_atomic_flag_t) == sizeof(tb_atomic32_t));
tb_atomic32_set_explicit((tb_atomic32_t*)a, 0, mo);
}
#endif
#endif
tbox-1.7.6/src/tbox/platform/atomic32.h 0000664 0000000 0000000 00000016202 14671175054 0017675 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file atomic32.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_IMPL_ATOMIC32_H
#define TB_PLATFORM_IMPL_ATOMIC32_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#if __tb_has_feature__(c_atomic) && !defined(__STDC_NO_ATOMICS__)
# include "libc/atomic32.h"
#elif defined(TB_CONFIG_OS_WINDOWS)
# include "windows/atomic32.h"
#elif defined(TB_COMPILER_IS_GCC) \
&& (defined(__ATOMIC_SEQ_CST) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4))
# include "compiler/gcc/atomic32.h"
#endif
#include "arch/atomic32.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifndef tb_atomic32_init
# define tb_atomic32_init(a, v) do { *(a) = (v); } while (0)
#endif
#ifndef tb_atomic32_compare_and_swap_explicit
# define tb_atomic32_compare_and_swap_explicit(a, p, v, succ, fail) \
tb_atomic32_compare_and_swap_explicit_generic(a, p, v, succ, fail)
#endif
#ifndef tb_atomic32_compare_and_swap
# define tb_atomic32_compare_and_swap(a, p, v) tb_atomic32_compare_and_swap_explicit(a, p, v, TB_ATOMIC_SEQ_CST, TB_ATOMIC_SEQ_CST)
#endif
#ifndef tb_atomic32_compare_and_swap_weak_explicit
# define tb_atomic32_compare_and_swap_weak_explicit(a, p, v, succ, fail) \
tb_atomic32_compare_and_swap_explicit(a, p, v, succ, fail)
#endif
#ifndef tb_atomic32_compare_and_swap_weak
# define tb_atomic32_compare_and_swap_weak(a, p, v) tb_atomic32_compare_and_swap_weak_explicit(a, p, v, TB_ATOMIC_SEQ_CST, TB_ATOMIC_SEQ_CST)
#endif
#ifndef tb_atomic32_fetch_and_cmpset_explicit
# define tb_atomic32_fetch_and_cmpset_explicit(a, p, v, succ, fail) \
tb_atomic32_fetch_and_cmpset_explicit_generic(a, p, v, succ, fail)
#endif
#ifndef tb_atomic32_fetch_and_cmpset
# define tb_atomic32_fetch_and_cmpset(a, p, v) tb_atomic32_fetch_and_cmpset_explicit(a, p, v, TB_ATOMIC_SEQ_CST, TB_ATOMIC_SEQ_CST)
#endif
#ifndef tb_atomic32_fetch_and_set_explicit
# define tb_atomic32_fetch_and_set_explicit(a, v, mo) tb_atomic32_fetch_and_set_explicit_generic(a, v, mo)
#endif
#ifndef tb_atomic32_fetch_and_set
# define tb_atomic32_fetch_and_set(a, v) tb_atomic32_fetch_and_set_explicit(a, v, TB_ATOMIC_SEQ_CST)
#endif
#ifndef tb_atomic32_fetch_and_add_explicit
# define tb_atomic32_fetch_and_add_explicit(a, v, mo) tb_atomic32_fetch_and_add_explicit_generic(a, v, mo)
#endif
#ifndef tb_atomic32_fetch_and_add
# define tb_atomic32_fetch_and_add(a, v) tb_atomic32_fetch_and_add_explicit(a, v, TB_ATOMIC_SEQ_CST)
#endif
#ifndef tb_atomic32_fetch_and_sub_explicit
# define tb_atomic32_fetch_and_sub_explicit(a, v, mo) tb_atomic32_fetch_and_add_explicit(a, -(v), mo)
#endif
#ifndef tb_atomic32_fetch_and_sub
# define tb_atomic32_fetch_and_sub(a, v) tb_atomic32_fetch_and_sub_explicit(a, v, TB_ATOMIC_SEQ_CST)
#endif
#ifndef tb_atomic32_fetch_and_or_explicit
# define tb_atomic32_fetch_and_or_explicit(a, v, mo) tb_atomic32_fetch_and_or_explicit_generic(a, v, mo)
#endif
#ifndef tb_atomic32_fetch_and_or
# define tb_atomic32_fetch_and_or(a, v) tb_atomic32_fetch_and_or_explicit(a, v, TB_ATOMIC_SEQ_CST)
#endif
#ifndef tb_atomic32_fetch_and_xor_explicit
# define tb_atomic32_fetch_and_xor_explicit(a, v, mo) tb_atomic32_fetch_and_xor_explicit_generic(a, v, mo)
#endif
#ifndef tb_atomic32_fetch_and_xor
# define tb_atomic32_fetch_and_xor(a, v) tb_atomic32_fetch_and_xor_explicit(a, v, TB_ATOMIC_SEQ_CST)
#endif
#ifndef tb_atomic32_fetch_and_and_explicit
# define tb_atomic32_fetch_and_and_explicit(a, v, mo) tb_atomic32_fetch_and_and_explicit_generic(a, v, mo)
#endif
#ifndef tb_atomic32_fetch_and_and
# define tb_atomic32_fetch_and_and(a, v) tb_atomic32_fetch_and_and_explicit(a, v, TB_ATOMIC_SEQ_CST)
#endif
#ifndef tb_atomic32_get_explicit
# define tb_atomic32_get_explicit(a, mo) tb_atomic32_fetch_and_cmpset_explicit(a, 0, 0, mo, mo)
#endif
#ifndef tb_atomic32_get
# define tb_atomic32_get(a) tb_atomic32_get_explicit(a, TB_ATOMIC_SEQ_CST)
#endif
#ifndef tb_atomic32_set_explicit
# define tb_atomic32_set_explicit(a, v, mo) tb_atomic32_fetch_and_set_explicit(a, v, mo)
#endif
#ifndef tb_atomic32_set
# define tb_atomic32_set(a, v) tb_atomic32_set_explicit(a, v, TB_ATOMIC_SEQ_CST)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* inlines
*/
static __tb_inline__ tb_bool_t tb_atomic32_compare_and_swap_explicit_generic(tb_atomic32_t* a, tb_int32_t* p, tb_int32_t v, tb_int_t succ, tb_int_t fail)
{
// FIXME
// no safe
tb_atomic32_t o = *a;
if (o == *p)
{
*a = v;
return tb_true;
}
else
{
*p = o;
return tb_false;
}
}
static __tb_inline__ tb_int32_t tb_atomic32_fetch_and_cmpset_explicit_generic(tb_atomic32_t* a, tb_int32_t p, tb_int32_t v, tb_int_t succ, tb_int_t fail)
{
tb_atomic32_compare_and_swap_explicit(a, &p, v, succ, fail);
return p;
}
static __tb_inline__ tb_int32_t tb_atomic32_fetch_and_set_explicit_generic(tb_atomic32_t* a, tb_int32_t v, tb_int_t mo)
{
tb_int32_t o;
do { o = *a; } while (!tb_atomic32_compare_and_swap_weak_explicit(a, &o, v, mo, mo));
return o;
}
static __tb_inline__ tb_int32_t tb_atomic32_fetch_and_add_explicit_generic(tb_atomic32_t* a, tb_int32_t v, tb_int_t mo)
{
tb_int32_t o; do { o = *a; } while (!tb_atomic32_compare_and_swap_weak_explicit(a, &o, o + v, mo, mo));
return o;
}
static __tb_inline__ tb_int32_t tb_atomic32_fetch_and_xor_explicit_generic(tb_atomic32_t* a, tb_int32_t v, tb_int_t mo)
{
tb_int32_t o; do { o = *a; } while (!tb_atomic32_compare_and_swap_weak_explicit(a, &o, o ^ v, mo, mo));
return o;
}
static __tb_inline__ tb_int32_t tb_atomic32_fetch_and_and_explicit_generic(tb_atomic32_t* a, tb_int32_t v, tb_int_t mo)
{
tb_int32_t o; do { o = *a; } while (!tb_atomic32_compare_and_swap_weak_explicit(a, &o, o & v, mo, mo));
return o;
}
static __tb_inline__ tb_int32_t tb_atomic32_fetch_and_or_explicit_generic(tb_atomic32_t* a, tb_int32_t v, tb_int_t mo)
{
tb_int32_t o; do { o = *a; } while (!tb_atomic32_compare_and_swap_weak_explicit(a, &o, o | v, mo, mo));
return o;
}
#endif
tbox-1.7.6/src/tbox/platform/atomic64.c 0000664 0000000 0000000 00000005341 14671175054 0017677 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file atomic64.c
* @ingroup platform
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "spinlock.h"
#include "atomic64.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the atomic64 lock mac count
#define TB_ATOMIC64_LOCK_MAXN (16)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the atomic64 lock type
typedef __tb_cacheline_aligned__ struct __tb_atomic64_lock_t
{
// the lock
tb_spinlock_t lock;
// the padding
tb_byte_t padding[TB_L1_CACHE_BYTES];
}__tb_cacheline_aligned__ tb_atomic64_lock_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
// the locks
static tb_atomic64_lock_t g_locks[TB_ATOMIC64_LOCK_MAXN] =
{
{TB_SPINLOCK_INIT, {0}}
};
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static __tb_inline_force__ tb_spinlock_ref_t tb_atomic64_lock(tb_atomic64_t* a)
{
// trace
tb_trace1_w("using generic atomic64, maybe slower!");
// the addr
tb_size_t addr = (tb_size_t)a;
// compile the hash value
addr >>= TB_L1_CACHE_SHIFT;
addr ^= (addr >> 8) ^ (addr >> 16);
// the lock
return &g_locks[addr & (TB_ATOMIC64_LOCK_MAXN - 1)].lock;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_atomic64_compare_and_swap_explicit_generic(tb_atomic64_t* a, tb_int64_t* p, tb_int64_t v, tb_int_t succ, tb_int_t fail)
{
// check
tb_assert(a && p);
// the lock
tb_spinlock_ref_t lock = tb_atomic64_lock(a);
// enter
tb_spinlock_enter(lock);
// set value
tb_bool_t ok = tb_false;
tb_atomic64_t o = *a;
if (o == *p)
{
*a = v;
ok = tb_true;
}
else *p = o;
// leave
tb_spinlock_leave(lock);
// ok?
return ok;
}
tbox-1.7.6/src/tbox/platform/atomic64.h 0000664 0000000 0000000 00000017471 14671175054 0017713 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file atomic64.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_IMPL_ATOMIC64_H
#define TB_PLATFORM_IMPL_ATOMIC64_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "atomic32.h"
#if __tb_has_feature__(c_atomic) && !defined(__STDC_NO_ATOMICS__)
# include "libc/atomic64.h"
#elif defined(TB_COMPILER_IS_GCC) \
&& (defined(__ATOMIC_SEQ_CST) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8))
# include "compiler/gcc/atomic64.h"
#elif defined(TB_CONFIG_OS_WINDOWS)
# include "windows/atomic64.h"
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifndef tb_atomic64_init
# define tb_atomic64_init(a, v) do { *(a) = (v); } while (0)
#endif
#ifndef tb_atomic64_compare_and_swap_explicit
# define tb_atomic64_compare_and_swap_explicit(a, p, v, succ, fail) \
tb_atomic64_compare_and_swap_explicit_generic(a, p, v, succ, fail)
#endif
#ifndef tb_atomic64_compare_and_swap
# define tb_atomic64_compare_and_swap(a, p, v) tb_atomic64_compare_and_swap_explicit(a, p, v, TB_ATOMIC_SEQ_CST, TB_ATOMIC_SEQ_CST)
#endif
#ifndef tb_atomic64_compare_and_swap_weak_explicit
# define tb_atomic64_compare_and_swap_weak_explicit(a, p, v, succ, fail) \
tb_atomic64_compare_and_swap_explicit(a, p, v, succ, fail)
#endif
#ifndef tb_atomic64_compare_and_swap_weak
# define tb_atomic64_compare_and_swap_weak(a, p, v) tb_atomic64_compare_and_swap_weak_explicit(a, p, v, TB_ATOMIC_SEQ_CST, TB_ATOMIC_SEQ_CST)
#endif
#ifndef tb_atomic64_fetch_and_cmpset_explicit
# define tb_atomic64_fetch_and_cmpset_explicit(a, p, v, succ, fail) \
tb_atomic64_fetch_and_cmpset_explicit_generic(a, p, v, succ, fail)
#endif
#ifndef tb_atomic64_fetch_and_cmpset
# define tb_atomic64_fetch_and_cmpset(a, p, v) tb_atomic64_fetch_and_cmpset_explicit(a, p, v, TB_ATOMIC_SEQ_CST, TB_ATOMIC_SEQ_CST)
#endif
#ifndef tb_atomic64_fetch_and_set_explicit
# define tb_atomic64_fetch_and_set_explicit(a, v, mo) tb_atomic64_fetch_and_set_explicit_generic(a, v, mo)
#endif
#ifndef tb_atomic64_fetch_and_set
# define tb_atomic64_fetch_and_set(a, v) tb_atomic64_fetch_and_set_explicit(a, v, TB_ATOMIC_SEQ_CST)
#endif
#ifndef tb_atomic64_fetch_and_add_explicit
# define tb_atomic64_fetch_and_add_explicit(a, v, mo) tb_atomic64_fetch_and_add_explicit_generic(a, v, mo)
#endif
#ifndef tb_atomic64_fetch_and_add
# define tb_atomic64_fetch_and_add(a, v) tb_atomic64_fetch_and_add_explicit(a, v, TB_ATOMIC_SEQ_CST)
#endif
#ifndef tb_atomic64_fetch_and_sub_explicit
# define tb_atomic64_fetch_and_sub_explicit(a, v, mo) tb_atomic64_fetch_and_add_explicit(a, -(v), mo)
#endif
#ifndef tb_atomic64_fetch_and_sub
# define tb_atomic64_fetch_and_sub(a, v) tb_atomic64_fetch_and_sub_explicit(a, v, TB_ATOMIC_SEQ_CST)
#endif
#ifndef tb_atomic64_fetch_and_or_explicit
# define tb_atomic64_fetch_and_or_explicit(a, v, mo) tb_atomic64_fetch_and_or_explicit_generic(a, v, mo)
#endif
#ifndef tb_atomic64_fetch_and_or
# define tb_atomic64_fetch_and_or(a, v) tb_atomic64_fetch_and_or_explicit(a, v, TB_ATOMIC_SEQ_CST)
#endif
#ifndef tb_atomic64_fetch_and_xor_explicit
# define tb_atomic64_fetch_and_xor_explicit(a, v, mo) tb_atomic64_fetch_and_xor_explicit_generic(a, v, mo)
#endif
#ifndef tb_atomic64_fetch_and_xor
# define tb_atomic64_fetch_and_xor(a, v) tb_atomic64_fetch_and_xor_explicit(a, v, TB_ATOMIC_SEQ_CST)
#endif
#ifndef tb_atomic64_fetch_and_and_explicit
# define tb_atomic64_fetch_and_and_explicit(a, v, mo) tb_atomic64_fetch_and_and_explicit_generic(a, v, mo)
#endif
#ifndef tb_atomic64_fetch_and_and
# define tb_atomic64_fetch_and_and(a, v) tb_atomic64_fetch_and_and_explicit(a, v, TB_ATOMIC_SEQ_CST)
#endif
#ifndef tb_atomic64_get_explicit
# define tb_atomic64_get_explicit(a, mo) tb_atomic64_fetch_and_cmpset_explicit(a, 0, 0, mo, mo)
#endif
#ifndef tb_atomic64_get
# define tb_atomic64_get(a) tb_atomic64_get_explicit(a, TB_ATOMIC_SEQ_CST)
#endif
#ifndef tb_atomic64_set_explicit
# define tb_atomic64_set_explicit(a, v, mo) tb_atomic64_fetch_and_set_explicit(a, v, mo)
#endif
#ifndef tb_atomic64_set
# define tb_atomic64_set(a, v) tb_atomic64_set_explicit(a, v, TB_ATOMIC_SEQ_CST)
#endif
#ifdef TB_CONFIG_API_HAVE_DEPRECATED
# include "deprecated/atomic64.h"
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* compare and set the 64bits value
*
* @param a pointer to the atomic object to test and modify
* @param p pointer to the value expected to be found in the atomic object
* @param v the value to store in the atomic object if it is as expected
* @param succ the memory order if be successful
* @param fail the memory order if be failed
*
* @return the result of the comparison: true if *a was equal to *p, false otherwise.
*/
tb_bool_t tb_atomic64_compare_and_swap_explicit_generic(tb_atomic64_t* a, tb_int64_t* p, tb_int64_t v, tb_int_t succ, tb_int_t fail);
/* //////////////////////////////////////////////////////////////////////////////////////
* inline interfaces
*/
static __tb_inline__ tb_int64_t tb_atomic64_fetch_and_cmpset_explicit_generic(tb_atomic64_t* a, tb_int64_t p, tb_int64_t v, tb_int_t succ, tb_int_t fail)
{
tb_atomic64_compare_and_swap_explicit(a, &p, v, succ, fail);
return p;
}
static __tb_inline__ tb_int64_t tb_atomic64_fetch_and_set_explicit_generic(tb_atomic64_t* a, tb_int64_t v, tb_int_t mo)
{
tb_int64_t o;
do { o = *a; } while (!tb_atomic64_compare_and_swap_weak_explicit(a, &o, v, mo, mo));
return o;
}
static __tb_inline__ tb_int64_t tb_atomic64_fetch_and_add_explicit_generic(tb_atomic64_t* a, tb_int64_t v, tb_int_t mo)
{
tb_int64_t o; do { o = *a; } while (!tb_atomic64_compare_and_swap_weak_explicit(a, &o, o + v, mo, mo));
return o;
}
static __tb_inline__ tb_int64_t tb_atomic64_fetch_and_xor_explicit_generic(tb_atomic64_t* a, tb_int64_t v, tb_int_t mo)
{
tb_int64_t o; do { o = *a; } while (!tb_atomic64_compare_and_swap_weak_explicit(a, &o, o ^ v, mo, mo));
return o;
}
static __tb_inline__ tb_int64_t tb_atomic64_fetch_and_and_explicit_generic(tb_atomic64_t* a, tb_int64_t v, tb_int_t mo)
{
tb_int64_t o; do { o = *a; } while (!tb_atomic64_compare_and_swap_weak_explicit(a, &o, o & v, mo, mo));
return o;
}
static __tb_inline__ tb_int64_t tb_atomic64_fetch_and_or_explicit_generic(tb_atomic64_t* a, tb_int64_t v, tb_int_t mo)
{
tb_int64_t o; do { o = *a; } while (!tb_atomic64_compare_and_swap_weak_explicit(a, &o, o | v, mo, mo));
return o;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/backtrace.c 0000664 0000000 0000000 00000005212 14671175054 0020165 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file backtrace.c
* @ingroup platform
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "backtrace"
#define TB_TRACE_MODULE_DEBUG (1)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "backtrace.h"
#if defined(TB_CONFIG_OS_WINDOWS)
# include "windows/backtrace.c"
#elif defined(TB_CONFIG_OS_ANDROID)
# include "android/backtrace.c"
#else
# include "libc/backtrace.c"
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_void_t tb_backtrace_dump(tb_char_t const* prefix, tb_pointer_t* frames, tb_size_t nframe)
{
// check
tb_check_return(nframe < 256);
// the frames
tb_pointer_t frames_data[256] = {0};
if (!frames)
{
nframe = tb_backtrace_frames(frames_data, nframe, 2);
frames = frames_data;
}
// dump frames
if (frames && nframe)
{
// init symbols
tb_handle_t symbols = tb_backtrace_symbols_init(frames, nframe);
if (symbols)
{
// walk
tb_size_t i = 0;
for (i = 0; i < nframe; i++)
{
#if TB_CPU_BIT64
tb_trace_i("%s[%016p]: %s", prefix? prefix : "", frames[i], tb_backtrace_symbols_name(symbols, frames, nframe, i));
#else
tb_trace_i("%s[%08p]: %s", prefix? prefix : "", frames[i], tb_backtrace_symbols_name(symbols, frames, nframe, i));
#endif
}
// exit symbols
tb_backtrace_symbols_exit(symbols);
}
else
{
// walk
tb_size_t i = 0;
for (i = 0; i < nframe; i++)
{
#if TB_CPU_BIT64
tb_trace_i("%s[%016p]", prefix? prefix : "", frames[i]);
#else
tb_trace_i("%s[%08p]", prefix? prefix : "", frames[i]);
#endif
}
}
}
}
tbox-1.7.6/src/tbox/platform/backtrace.h 0000664 0000000 0000000 00000005341 14671175054 0020175 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file backtrace.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_BACKTRACE_H
#define TB_PLATFORM_BACKTRACE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! get backtrace frames
*
* @param frames the backtrace frames
* @param nframe the backtrace frame maxn
* @param nskip the backtrace frame skip
*
* @return the real backtrace frame count
*/
tb_size_t tb_backtrace_frames(tb_pointer_t* frames, tb_size_t nframe, tb_size_t nskip);
/*! init backtrace frame symbols
*
* @param frames the backtrace frames
* @param nframe the backtrace frame count
*
* @return the backtrace frame symbols handle
*/
tb_handle_t tb_backtrace_symbols_init(tb_pointer_t* frames, tb_size_t nframe);
/*! get backtrace frame symbol name
*
* @param symbols the symbols handle
* @param frames the backtrace frames
* @param nframe the backtrace frame count
* @param iframe the backtrace frame index
*
* @return the symbol name
*/
tb_char_t const* tb_backtrace_symbols_name(tb_handle_t symbols, tb_pointer_t* frames, tb_size_t nframe, tb_size_t iframe);
/*! exit backtrace frame symbols
*
* @param symbols the symbols handle
*/
tb_void_t tb_backtrace_symbols_exit(tb_handle_t symbols);
/*! dump backtrace
*
* @param prefix the backtrace prefix
* @param frames the backtrace frames, dump the current frames if null
* @param nframe the backtrace frame count
*/
tb_void_t tb_backtrace_dump(tb_char_t const* prefix, tb_pointer_t* frames, tb_size_t nframe);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/bsd/ 0000775 0000000 0000000 00000000000 14671175054 0016652 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/platform/bsd/filelock.c 0000664 0000000 0000000 00000006627 14671175054 0020621 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file filelock.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../filelock.h"
#include "../file.h"
#if defined(TB_CONFIG_OS_LINUX) || defined(TB_CONFIG_OS_ANDROID) || defined(TB_CONFIG_OS_WEB)
# include
#else
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the file lock type
typedef struct __tb_filelock_t
{
// the file reference
tb_file_ref_t file;
// is owner?
tb_bool_t owner;
}tb_filelock_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_filelock_ref_t tb_filelock_init_impl(tb_file_ref_t file, tb_bool_t owner)
{
// check
tb_assert_and_check_return_val(file, tb_null);
tb_filelock_t* lock = tb_null;
do
{
// init lock
lock = tb_malloc0_type(tb_filelock_t);
tb_assert_and_check_break(lock);
lock->file = file;
lock->owner = owner;
} while (0);
return (tb_filelock_ref_t)lock;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_filelock_ref_t tb_filelock_init(tb_file_ref_t file)
{
return tb_filelock_init_impl(file, tb_false);
}
tb_filelock_ref_t tb_filelock_init_from_path(tb_char_t const* path, tb_size_t mode)
{
tb_assert_and_check_return_val(path, tb_null);
return tb_filelock_init_impl(tb_file_init(path, mode), tb_true);
}
tb_void_t tb_filelock_exit(tb_filelock_ref_t self)
{
// check
tb_filelock_t* lock = (tb_filelock_t*)self;
tb_assert_and_check_return(lock);
// exit file
if (lock->file && lock->owner) tb_file_exit(lock->file);
lock->file = tb_null;
// exit lock
tb_free(lock);
}
tb_bool_t tb_filelock_enter(tb_filelock_ref_t self, tb_size_t mode)
{
// check
tb_filelock_t* lock = (tb_filelock_t*)self;
tb_assert_and_check_return_val(lock && lock->file, tb_false);
// lock it
return flock(tb_file2fd(lock->file), (mode == TB_FILELOCK_MODE_EX)? LOCK_EX : LOCK_SH) == 0;
}
tb_bool_t tb_filelock_enter_try(tb_filelock_ref_t self, tb_size_t mode)
{
// check
tb_filelock_t* lock = (tb_filelock_t*)self;
tb_assert_and_check_return_val(lock && lock->file, tb_false);
// try to lock it
return flock(tb_file2fd(lock->file), ((mode == TB_FILELOCK_MODE_EX)? LOCK_EX : LOCK_SH) | LOCK_NB) == 0;
}
tb_bool_t tb_filelock_leave(tb_filelock_ref_t self)
{
// check
tb_filelock_t* lock = (tb_filelock_t*)self;
tb_assert_and_check_return_val(lock && lock->file, tb_false);
// unlock it
return flock(tb_file2fd(lock->file), LOCK_UN) == 0;
}
tbox-1.7.6/src/tbox/platform/bsd/fwatcher_kqueue.c 0000664 0000000 0000000 00000036641 14671175054 0022212 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file fwatcher_kqueue.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../fwatcher.h"
#include "../file.h"
#include "../socket.h"
#include "../directory.h"
#include "../../libc/libc.h"
#include "../../container/container.h"
#include "../../algorithm/algorithm.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#if defined(TB_CONFIG_MODULE_HAVE_COROUTINE) \
&& !defined(TB_CONFIG_MICRO_ENABLE)
# include "../../coroutine/coroutine.h"
# include "../../coroutine/impl/impl.h"
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifndef EV_ENABLE
# define EV_ENABLE (0)
#endif
#ifndef NOTE_EOF
# define NOTE_EOF (0)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the watch item type
typedef struct __tb_fwatcher_item_t
{
tb_int_t wd;
tb_char_t const* watchdir;
tb_bool_t recursion;
}tb_fwatcher_item_t;
// the fwatcher type
typedef struct __tb_fwatcher_t
{
tb_int_t kqfd;
struct kevent* watchevents;
tb_size_t watchevents_size;
tb_size_t watchevents_maxn;
struct kevent* events;
tb_size_t events_count;
tb_hash_map_ref_t watchitems;
tb_socket_ref_t pair[2];
tb_queue_ref_t waited_events;
}tb_fwatcher_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_void_t tb_fwatcher_item_free(tb_element_ref_t element, tb_pointer_t buff)
{
tb_fwatcher_item_t* watchitem = (tb_fwatcher_item_t*)buff;
if (watchitem && watchitem->wd >= 0)
{
close(watchitem->wd);
watchitem->wd = -1;
}
}
static tb_bool_t tb_fwatcher_add_watch(tb_fwatcher_t* fwatcher, tb_char_t const* watchdir, tb_bool_t recursion)
{
// check
tb_assert_and_check_return_val(fwatcher && fwatcher->kqfd >= 0 && fwatcher->watchitems && watchdir, tb_false);
// this path has been added?
tb_size_t itor = tb_hash_map_find(fwatcher->watchitems, watchdir);
if (itor != tb_iterator_tail(fwatcher->watchitems))
return tb_true;
// open watch fd
tb_int_t o_flags = 0;
# ifdef O_EVTONLY
o_flags |= O_EVTONLY;
# else
o_flags |= O_RDONLY;
# endif
tb_int_t wd = open(watchdir, o_flags);
tb_check_return_val(wd >= 0, tb_false);
// save watch item
tb_fwatcher_item_t watchitem;
watchitem.wd = wd;
watchitem.recursion = recursion;
watchitem.watchdir = tb_null;
return tb_hash_map_insert(fwatcher->watchitems, watchdir, &watchitem) != tb_iterator_tail(fwatcher->watchitems);
}
static tb_long_t tb_fwatcher_add_watch_filedirs(tb_char_t const* path, tb_file_info_t const* info, tb_cpointer_t priv)
{
// check
tb_fwatcher_t* fwatcher = (tb_fwatcher_t*)priv;
tb_assert_and_check_return_val(path && info && fwatcher, TB_DIRECTORY_WALK_CODE_END);
// add file watch
tb_fwatcher_add_watch(fwatcher, path, tb_true);
return TB_DIRECTORY_WALK_CODE_CONTINUE;
}
static tb_bool_t tb_fwatcher_rm_watch(tb_fwatcher_t* fwatcher, tb_char_t const* watchdir)
{
// check
tb_assert_and_check_return_val(fwatcher && fwatcher->kqfd >= 0 && fwatcher->watchitems && watchdir, tb_false);
// remove the watchitem
tb_hash_map_remove(fwatcher->watchitems, watchdir);
return tb_true;
}
static tb_long_t tb_fwatcher_rm_watch_filedirs(tb_char_t const* path, tb_file_info_t const* info, tb_cpointer_t priv)
{
// check
tb_value_t* values = (tb_value_t*)priv;
tb_assert_and_check_return_val(path && info && values, TB_DIRECTORY_WALK_CODE_END);
// get fwatcher
tb_fwatcher_t* fwatcher = values[0].ptr;
tb_assert_and_check_return_val(fwatcher, TB_DIRECTORY_WALK_CODE_END);
// rm file watch
tb_fwatcher_rm_watch(fwatcher, path);
return TB_DIRECTORY_WALK_CODE_CONTINUE;
}
static tb_bool_t tb_fwatcher_update_watchevents(tb_iterator_ref_t iterator, tb_pointer_t item, tb_cpointer_t priv)
{
// check
tb_fwatcher_t* fwatcher = (tb_fwatcher_t*)priv;
tb_hash_map_item_ref_t hashitem = (tb_hash_map_item_ref_t)item;
tb_assert_and_check_return_val(fwatcher && fwatcher->watchitems && hashitem, tb_false);
// get watch item and path
tb_char_t const* path = (tb_char_t const*)hashitem->name;
tb_fwatcher_item_t* watchitem = (tb_fwatcher_item_t*)hashitem->data;
tb_assert_and_check_return_val(watchitem->wd >= 0 && path, tb_false);
// grow watchevents
tb_size_t watchsize = tb_hash_map_size(fwatcher->watchitems);
if (!fwatcher->watchevents)
{
fwatcher->watchevents_maxn = watchsize;
fwatcher->watchevents = tb_nalloc_type(1 + fwatcher->watchevents_maxn, struct kevent);
}
else if (fwatcher->watchevents_size >= fwatcher->watchevents_maxn)
{
fwatcher->watchevents_maxn = watchsize + 64;
fwatcher->watchevents = tb_ralloc(fwatcher->watchevents, (1 + fwatcher->watchevents_maxn) * sizeof(struct kevent));
}
tb_assert_and_check_return_val(fwatcher->watchevents && fwatcher->watchevents_size < fwatcher->watchevents_maxn, tb_false);
// register pair1 to watchevents first
if (!fwatcher->watchevents_size)
{
EV_SET(&fwatcher->watchevents[0], tb_sock2fd(fwatcher->pair[1]),
EVFILT_READ, EV_ADD | EV_ENABLE | EV_CLEAR, NOTE_EOF, 0, tb_null);
}
// register watch events
tb_uint_t vnode_events = NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_LINK | NOTE_RENAME | NOTE_REVOKE;
tb_assert_and_check_return_val(vnode_events, tb_false);
watchitem->watchdir = path;
EV_SET(&fwatcher->watchevents[1 + fwatcher->watchevents_size], watchitem->wd,
EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, vnode_events, 0, (tb_pointer_t)watchitem);
fwatcher->watchevents_size++;
return tb_true;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_fwatcher_ref_t tb_fwatcher_init()
{
tb_bool_t ok = tb_false;
tb_fwatcher_t* fwatcher = tb_null;
do
{
// init fwatcher
fwatcher = tb_malloc0_type(tb_fwatcher_t);
tb_assert_and_check_break(fwatcher);
// init kqueue
fwatcher->kqfd = kqueue();
tb_assert_and_check_break(fwatcher->kqfd >= 0);
// init socket pair
if (!tb_socket_pair(TB_SOCKET_TYPE_TCP, fwatcher->pair)) break;
// init watch items
fwatcher->watchitems = tb_hash_map_init(0, tb_element_str(tb_true), tb_element_mem(sizeof(tb_fwatcher_item_t), tb_fwatcher_item_free, tb_null));
tb_assert_and_check_break(fwatcher->watchitems);
// init waited events
fwatcher->waited_events = tb_queue_init(0, tb_element_mem(sizeof(tb_fwatcher_event_t), tb_null, tb_null));
tb_assert_and_check_break(fwatcher->waited_events);
ok = tb_true;
} while (0);
if (!ok && fwatcher)
{
tb_fwatcher_exit((tb_fwatcher_ref_t)fwatcher);
fwatcher = tb_null;
}
return (tb_fwatcher_ref_t)fwatcher;
}
tb_void_t tb_fwatcher_exit(tb_fwatcher_ref_t self)
{
tb_fwatcher_t* fwatcher = (tb_fwatcher_t*)self;
if (fwatcher)
{
// exit pair sockets
if (fwatcher->pair[0]) tb_socket_exit(fwatcher->pair[0]);
if (fwatcher->pair[1]) tb_socket_exit(fwatcher->pair[1]);
fwatcher->pair[0] = tb_null;
fwatcher->pair[1] = tb_null;
// exit events
if (fwatcher->events) tb_free(fwatcher->events);
fwatcher->events = tb_null;
fwatcher->events_count = 0;
// exit watch events
if (fwatcher->watchevents) tb_free(fwatcher->watchevents);
fwatcher->watchevents = tb_null;
fwatcher->watchevents_size = 0;
fwatcher->watchevents_maxn = 0;
// exit watch items
if (fwatcher->watchitems)
{
tb_hash_map_exit(fwatcher->watchitems);
fwatcher->watchitems = tb_null;
}
// exit waited events
if (fwatcher->waited_events)
{
tb_queue_exit(fwatcher->waited_events);
fwatcher->waited_events = tb_null;
}
// exit kqueue fd
if (fwatcher->kqfd >= 0)
{
close(fwatcher->kqfd);
fwatcher->kqfd = -1;
}
// wait watcher
tb_free(fwatcher);
fwatcher = tb_null;
}
}
tb_bool_t tb_fwatcher_add(tb_fwatcher_ref_t self, tb_char_t const* watchdir, tb_bool_t recursion)
{
tb_fwatcher_t* fwatcher = (tb_fwatcher_t*)self;
tb_assert_and_check_return_val(fwatcher && watchdir, tb_false);
// file not found
tb_file_info_t info;
if (!tb_file_info(watchdir, &info) || info.type != TB_FILE_TYPE_DIRECTORY)
return tb_false;
// is directory? we need scan it and add all subfiles
if (info.type == TB_FILE_TYPE_DIRECTORY)
tb_directory_walk(watchdir, recursion? -1 : 0, tb_true, tb_fwatcher_add_watch_filedirs, fwatcher);
return tb_fwatcher_add_watch(fwatcher, watchdir, recursion);
}
tb_bool_t tb_fwatcher_remove(tb_fwatcher_ref_t self, tb_char_t const* watchdir)
{
tb_fwatcher_t* fwatcher = (tb_fwatcher_t*)self;
tb_assert_and_check_return_val(fwatcher && watchdir, tb_false);
// is directory? we need scan it and remove all subfiles
tb_file_info_t info;
if (tb_file_info(watchdir, &info) && info.type == TB_FILE_TYPE_DIRECTORY)
{
tb_value_t values[1];
values[0].ptr = (tb_pointer_t)fwatcher;
tb_directory_walk(watchdir, 0, tb_false, tb_fwatcher_rm_watch_filedirs, values);
}
return tb_fwatcher_rm_watch(fwatcher, watchdir);
}
tb_void_t tb_fwatcher_spak(tb_fwatcher_ref_t self)
{
tb_fwatcher_t* fwatcher = (tb_fwatcher_t*)self;
tb_assert_and_check_return(fwatcher);
if (fwatcher->pair[0]) tb_socket_send(fwatcher->pair[0], (tb_byte_t const*)"p", 1);
}
tb_long_t tb_fwatcher_wait(tb_fwatcher_ref_t self, tb_fwatcher_event_t* event, tb_long_t timeout)
{
tb_fwatcher_t* fwatcher = (tb_fwatcher_t*)self;
tb_assert_and_check_return_val(fwatcher && fwatcher->kqfd >= 0 && fwatcher->waited_events && event, -1);
#if defined(TB_CONFIG_MODULE_HAVE_COROUTINE) \
&& !defined(TB_CONFIG_MICRO_ENABLE)
// attempt to wait it in coroutine if timeout is non-zero
if (timeout && tb_coroutine_self())
{
tb_poller_object_t object;
object.type = TB_POLLER_OBJECT_FWATCHER;
object.ref.fwatcher = self;
return tb_coroutine_waitfs(&object, event, timeout);
}
#endif
// get it if has events
tb_bool_t has_events = tb_false;
if (!tb_queue_null(fwatcher->waited_events))
{
tb_fwatcher_event_t* e = (tb_fwatcher_event_t*)tb_queue_get(fwatcher->waited_events);
if (e)
{
*event = *e;
tb_queue_pop(fwatcher->waited_events);
has_events = tb_true;
}
}
tb_check_return_val(!has_events, 1);
// init time
struct timespec t = {0};
if (timeout > 0)
{
t.tv_sec = timeout / 1000;
t.tv_nsec = (timeout % 1000) * 1000000;
}
// init events
tb_size_t grow = 256;
if (!fwatcher->events)
{
fwatcher->events_count = grow;
fwatcher->events = tb_nalloc_type(fwatcher->events_count, struct kevent);
tb_assert_and_check_return_val(fwatcher->events, -1);
}
// update watch events
fwatcher->watchevents_size = 0;
tb_walk_all(fwatcher->watchitems, tb_fwatcher_update_watchevents, fwatcher);
tb_assert_and_check_return_val(fwatcher->watchevents && fwatcher->watchevents_size, -1);
// wait events
tb_long_t events_count = kevent(fwatcher->kqfd, fwatcher->watchevents, fwatcher->watchevents_size,
fwatcher->events, fwatcher->events_count, timeout >= 0? &t : tb_null);
// timeout or interrupted?
if (!events_count || (events_count == -1 && errno == EINTR))
return 0;
// error?
tb_assert_and_check_return_val(events_count >= 0 && events_count <= fwatcher->events_count, -1);
// grow it if events is full
if (events_count == fwatcher->events_count)
{
// grow size
fwatcher->events_count += grow;
// grow data
fwatcher->events = (struct kevent*)tb_ralloc(fwatcher->events, fwatcher->events_count * sizeof(struct kevent));
tb_assert_and_check_return_val(fwatcher->events, -1);
}
tb_assert(events_count <= fwatcher->events_count);
// handle events
tb_size_t i = 0;
tb_socket_ref_t pair = fwatcher->pair[1];
struct kevent* kevt = tb_null;
for (i = 0; i < events_count; i++)
{
// get event
kevt = fwatcher->events + i;
if (kevt->flags & EV_ERROR)
continue;
// spank socket events?
tb_socket_ref_t sock = tb_fd2sock(kevt->ident);
if (sock == pair && kevt->filter == EVFILT_READ)
{
tb_char_t spak = '\0';
if (1 != tb_socket_recv(pair, (tb_byte_t*)&spak, 1)) return -1;
continue ;
}
// get watchitem
tb_fwatcher_item_t const* watchitem = (tb_fwatcher_item_t const*)kevt->udata;
tb_assert_and_check_break(watchitem);
// get event code
tb_size_t event_code = 0;
if (kevt->fflags & NOTE_DELETE)
event_code = TB_FWATCHER_EVENT_DELETE;
else if ((kevt->fflags & NOTE_RENAME) || (kevt->fflags & NOTE_REVOKE) || (kevt->fflags & NOTE_WRITE))
event_code = TB_FWATCHER_EVENT_MODIFY;
// add event
if (event_code)
{
tb_fwatcher_event_t evt;
if (watchitem->watchdir) tb_strlcpy(evt.filepath, watchitem->watchdir, TB_PATH_MAXN);
else evt.filepath[0] = '\0';
evt.event = event_code;
tb_queue_put(fwatcher->waited_events, &evt);
}
// rescan the watch directory
if (watchitem->watchdir)
{
tb_file_info_t info;
if ((event_code == TB_FWATCHER_EVENT_MODIFY || event_code == TB_FWATCHER_EVENT_CREATE) &&
tb_file_info(watchitem->watchdir, &info) && info.type == TB_FILE_TYPE_DIRECTORY)
tb_fwatcher_add(self, watchitem->watchdir, watchitem->recursion);
else if (event_code == TB_FWATCHER_EVENT_DELETE)
tb_fwatcher_remove(self, watchitem->watchdir);
}
}
// get event
if (!tb_queue_null(fwatcher->waited_events))
{
tb_fwatcher_event_t* e = (tb_fwatcher_event_t*)tb_queue_get(fwatcher->waited_events);
if (e)
{
*event = *e;
tb_queue_pop(fwatcher->waited_events);
has_events = tb_true;
}
}
return has_events? 1 : 0;
}
tbox-1.7.6/src/tbox/platform/bsd/poller_kqueue.c 0000664 0000000 0000000 00000032200 14671175054 0021667 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file poller_kqueue.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include
#include
#include
#include
#include
#include
#ifdef TB_CONFIG_POSIX_HAVE_GETRLIMIT
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifndef EV_ENABLE
# define EV_ENABLE (0)
#endif
#ifndef NOTE_EOF
# define NOTE_EOF (0)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the kqueue poller type
typedef struct __tb_poller_kqueue_t
{
// the poller base
tb_poller_t base;
// the maxn
tb_size_t maxn;
// the pair sockets for spak, kill ..
tb_socket_ref_t pair[2];
// the kqueue fd
tb_long_t kqfd;
// the events
struct kevent* events;
// the events count
tb_size_t events_count;
// the poller data
tb_pollerdata_t pollerdata;
}tb_poller_kqueue_t, *tb_poller_kqueue_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_size_t tb_poller_kqueue_maxfds()
{
// attempt to get it from getdtablesize
tb_size_t maxfds = 0;
#ifdef TB_CONFIG_POSIX_HAVE_GETDTABLESIZE
if (!maxfds) maxfds = getdtablesize();
#endif
// attempt to get it from getrlimit
#ifdef TB_CONFIG_POSIX_HAVE_GETRLIMIT
struct rlimit rl;
if (!maxfds && !getrlimit(RLIMIT_NOFILE, &rl))
maxfds = rl.rlim_cur;
#endif
// attempt to get it from sysconf
if (!maxfds) maxfds = sysconf(_SC_OPEN_MAX);
// ok?
return maxfds;
}
static tb_bool_t tb_poller_kqueue_change(tb_poller_kqueue_ref_t poller, struct kevent* events, tb_size_t count)
{
// check
tb_assert_and_check_return_val(events && count, tb_false);
// change events
struct timespec t = {0};
if (kevent(poller->kqfd, events, count, tb_null, 0, &t) < 0)
{
// trace
tb_trace_e("change kevent failed, errno: %d", errno);
// failed
return tb_false;
}
// ok
return tb_true;
}
static tb_void_t tb_poller_kqueue_exit(tb_poller_t* self)
{
// check
tb_poller_kqueue_ref_t poller = (tb_poller_kqueue_ref_t)self;
tb_assert_and_check_return(poller);
// exit pair sockets
if (poller->pair[0]) tb_socket_exit(poller->pair[0]);
if (poller->pair[1]) tb_socket_exit(poller->pair[1]);
poller->pair[0] = tb_null;
poller->pair[1] = tb_null;
// exit events
if (poller->events) tb_free(poller->events);
poller->events = tb_null;
poller->events_count = 0;
// close kqfd
if (poller->kqfd > 0) close(poller->kqfd);
poller->kqfd = 0;
// exit socket data
tb_pollerdata_exit(&poller->pollerdata);
// free it
tb_free(poller);
}
static tb_void_t tb_poller_kqueue_kill(tb_poller_t* self)
{
// check
tb_poller_kqueue_ref_t poller = (tb_poller_kqueue_ref_t)self;
tb_assert_and_check_return(poller);
// kill it
if (poller->pair[0]) tb_socket_send(poller->pair[0], (tb_byte_t const*)"k", 1);
}
static tb_void_t tb_poller_kqueue_spak(tb_poller_t* self)
{
// check
tb_poller_kqueue_ref_t poller = (tb_poller_kqueue_ref_t)self;
tb_assert_and_check_return(poller);
// post it
if (poller->pair[0]) tb_socket_send(poller->pair[0], (tb_byte_t const*)"p", 1);
}
static tb_bool_t tb_poller_kqueue_insert(tb_poller_t* self, tb_poller_object_ref_t object, tb_size_t events, tb_cpointer_t priv)
{
// check
tb_poller_kqueue_ref_t poller = (tb_poller_kqueue_ref_t)self;
tb_assert_and_check_return_val(poller && poller->kqfd > 0 && object, tb_false);
// init the add event
tb_size_t adde = EV_ADD | EV_ENABLE;
if (events & TB_POLLER_EVENT_CLEAR) adde |= EV_CLEAR;
if (events & TB_POLLER_EVENT_ONESHOT) adde |= EV_ONESHOT;
// bind the object type to the private data
priv = tb_poller_priv_set_object_type(object, priv);
// insert socket and add events
struct kevent e[2];
tb_size_t n = 0;
tb_int_t fd = tb_ptr2fd(object->ref.ptr);
if (events & TB_POLLER_EVENT_RECV)
{
EV_SET(&e[n], fd, EVFILT_READ, adde, NOTE_EOF, 0, (tb_pointer_t)priv); n++;
}
if (events & TB_POLLER_EVENT_SEND)
{
EV_SET(&e[n], fd, EVFILT_WRITE, adde, NOTE_EOF, 0, (tb_pointer_t)priv); n++;
}
// change it
tb_bool_t ok = n? tb_poller_kqueue_change(poller, e, n) : tb_true;
// save events to object
if (ok) tb_pollerdata_set(&poller->pollerdata, object, (tb_cpointer_t)events);
// ok?
return ok;
}
static tb_bool_t tb_poller_kqueue_remove(tb_poller_t* self, tb_poller_object_ref_t object)
{
// check
tb_poller_kqueue_ref_t poller = (tb_poller_kqueue_ref_t)self;
tb_assert_and_check_return_val(poller && poller->kqfd > 0 && object, tb_false);
// get the previous events
tb_size_t events = (tb_size_t)tb_pollerdata_get(&poller->pollerdata, object);
// remove this socket and events
struct kevent e[2];
tb_size_t n = 0;
tb_int_t fd = tb_ptr2fd(object->ref.ptr);
if (events & TB_POLLER_EVENT_RECV)
{
EV_SET(&e[n], fd, EVFILT_READ, EV_DELETE, 0, 0, tb_null);
n++;
}
if (events & TB_POLLER_EVENT_SEND)
{
EV_SET(&e[n], fd, EVFILT_WRITE, EV_DELETE, 0, 0, tb_null);
n++;
}
// change it
tb_bool_t ok = n? tb_poller_kqueue_change(poller, e, n) : tb_true;
// remove events from object
if (ok) tb_pollerdata_reset(&poller->pollerdata, object);
// ok?
return ok;
}
static tb_bool_t tb_poller_kqueue_modify(tb_poller_t* self, tb_poller_object_ref_t object, tb_size_t events, tb_cpointer_t priv)
{
// check
tb_poller_kqueue_ref_t poller = (tb_poller_kqueue_ref_t)self;
tb_assert_and_check_return_val(poller && poller->kqfd > 0 && object, tb_false);
// get the previous events
tb_size_t events_old = (tb_size_t)tb_pollerdata_get(&poller->pollerdata, object);
// get changed events
tb_size_t adde = events & ~events_old;
tb_size_t dele = ~events & events_old;
// init the add event
tb_size_t add_event = EV_ADD | EV_ENABLE;
if (events & TB_POLLER_EVENT_CLEAR) add_event |= EV_CLEAR;
if (events & TB_POLLER_EVENT_ONESHOT) add_event |= EV_ONESHOT;
// bind the object type to the private data
priv = tb_poller_priv_set_object_type(object, priv);
// modify events
struct kevent e[2];
tb_size_t n = 0;
tb_int_t fd = tb_ptr2fd(object->ref.ptr);
if (adde & TB_SOCKET_EVENT_RECV)
{
EV_SET(&e[n], fd, EVFILT_READ, add_event, NOTE_EOF, 0, (tb_pointer_t)priv);
n++;
}
else if (dele & TB_SOCKET_EVENT_RECV)
{
EV_SET(&e[n], fd, EVFILT_READ, EV_DELETE, 0, 0, (tb_pointer_t)priv);
n++;
}
if (adde & TB_SOCKET_EVENT_SEND)
{
EV_SET(&e[n], fd, EVFILT_WRITE, add_event, NOTE_EOF, 0, (tb_pointer_t)priv);
n++;
}
else if (dele & TB_SOCKET_EVENT_SEND)
{
EV_SET(&e[n], fd, EVFILT_WRITE, EV_DELETE, 0, 0, (tb_pointer_t)priv);
n++;
}
// change it
tb_bool_t ok = n? tb_poller_kqueue_change(poller, e, n) : tb_true;
// save events to socket
if (ok) tb_pollerdata_set(&poller->pollerdata, object, (tb_cpointer_t)events);
// ok?
return ok;
}
static tb_long_t tb_poller_kqueue_wait(tb_poller_t* self, tb_poller_event_func_t func, tb_long_t timeout)
{
// check
tb_poller_kqueue_ref_t poller = (tb_poller_kqueue_ref_t)self;
tb_assert_and_check_return_val(poller && poller->kqfd > 0 && poller->maxn && func, -1);
// init time
struct timespec t = {0};
if (timeout > 0)
{
t.tv_sec = timeout / 1000;
t.tv_nsec = (timeout % 1000) * 1000000;
}
// init events
tb_size_t grow = tb_align8((poller->maxn >> 3) + 1);
if (!poller->events)
{
poller->events_count = grow;
poller->events = tb_nalloc_type(poller->events_count, struct kevent);
tb_assert_and_check_return_val(poller->events, -1);
}
// wait events
tb_long_t events_count = kevent(poller->kqfd, tb_null, 0, poller->events, poller->events_count, timeout >= 0? &t : tb_null);
// timeout or interrupted?
if (!events_count || (events_count == -1 && errno == EINTR))
return 0;
// error?
tb_assert_and_check_return_val(events_count >= 0 && events_count <= poller->events_count, -1);
// grow it if events is full
if (events_count == poller->events_count)
{
// grow size
poller->events_count += grow;
if (poller->events_count > poller->maxn) poller->events_count = poller->maxn;
// grow data
poller->events = (struct kevent*)tb_ralloc(poller->events, poller->events_count * sizeof(struct kevent));
tb_assert_and_check_return_val(poller->events, -1);
}
tb_assert(events_count <= poller->events_count);
// limit
events_count = tb_min(events_count, poller->maxn);
// handle events
tb_size_t i = 0;
tb_size_t wait = 0;
struct kevent* e = tb_null;
tb_socket_ref_t pair = poller->pair[1];
tb_poller_object_t object;
for (i = 0; i < events_count; i++)
{
// the kevents
e = poller->events + i;
// get the object pointer
object.ref.ptr = tb_fd2ptr(e->ident);
tb_assert(object.ref.ptr);
// spank socket events?
if (object.ref.sock == pair && e->filter == EVFILT_READ)
{
// read spak
tb_char_t spak = '\0';
if (1 != tb_socket_recv(pair, (tb_byte_t*)&spak, 1)) return -1;
// killed?
if (spak == 'k') return -1;
// continue it
continue ;
}
// skip spak
tb_check_continue(object.ref.sock != pair);
// init events
tb_size_t events = TB_POLLER_EVENT_NONE;
if (e->filter == EVFILT_READ) events |= TB_POLLER_EVENT_RECV;
if (e->filter == EVFILT_WRITE) events |= TB_POLLER_EVENT_SEND;
if ((e->flags & EV_ERROR) && !(events & (TB_POLLER_EVENT_RECV | TB_POLLER_EVENT_SEND)))
events |= TB_POLLER_EVENT_RECV | TB_POLLER_EVENT_SEND;
// connection closed for the edge trigger?
if (e->flags & EV_EOF)
events |= TB_POLLER_EVENT_EOF;
// call event function
object.type = tb_poller_priv_get_object_type(e->udata);
func((tb_poller_ref_t)self, &object, events, tb_poller_priv_get_original(e->udata));
// update the events count
wait++;
}
// ok
return wait;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_poller_t* tb_poller_kqueue_init()
{
tb_bool_t ok = tb_false;
tb_poller_kqueue_ref_t poller = tb_null;
do
{
// make poller
poller = tb_malloc0_type(tb_poller_kqueue_t);
tb_assert_and_check_break(poller);
// init base
poller->base.type = TB_POLLER_TYPE_KQUEUE;
poller->base.exit = tb_poller_kqueue_exit;
poller->base.kill = tb_poller_kqueue_kill;
poller->base.spak = tb_poller_kqueue_spak;
poller->base.wait = tb_poller_kqueue_wait;
poller->base.insert = tb_poller_kqueue_insert;
poller->base.remove = tb_poller_kqueue_remove;
poller->base.modify = tb_poller_kqueue_modify;
poller->base.supported_events = TB_POLLER_EVENT_EALL | TB_POLLER_EVENT_CLEAR | TB_POLLER_EVENT_ONESHOT;
// init socket data
tb_pollerdata_init(&poller->pollerdata);
// init kqueue
poller->kqfd = kqueue();
tb_assert_and_check_break(poller->kqfd > 0);
// init maxn
poller->maxn = tb_poller_kqueue_maxfds();
tb_assert_and_check_break(poller->maxn);
// init pair sockets
if (!tb_socket_pair(TB_SOCKET_TYPE_TCP, poller->pair)) break;
// insert pair socket first
tb_poller_object_t pair1;
pair1.type = TB_POLLER_OBJECT_SOCK;
pair1.ref.sock = poller->pair[1];
if (!tb_poller_kqueue_insert((tb_poller_t*)poller, &pair1, TB_POLLER_EVENT_RECV, tb_null)) break;
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (poller) tb_poller_kqueue_exit((tb_poller_t*)poller);
poller = tb_null;
}
// ok?
return (tb_poller_t*)poller;
}
tbox-1.7.6/src/tbox/platform/bsd/prefix.h 0000664 0000000 0000000 00000001735 14671175054 0020326 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
* @ingroup platform
*/
#ifndef TB_PLATFORM_BSD_PREFIX_H
#define TB_PLATFORM_BSD_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../platform.h"
#include "../../libc/libc.h"
#include "../../utils/utils.h"
#endif
tbox-1.7.6/src/tbox/platform/cache_time.c 0000664 0000000 0000000 00000003427 14671175054 0020335 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file cache_time.c
* @ingroup platform
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "cache_time.h"
#include "time.h"
#include "atomic.h"
#include "../libc/libc.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
// the cached time
static tb_atomic64_t g_time = 0;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_hong_t tb_cache_time_spak()
{
// get the time
tb_timeval_t tv = {0};
if (!tb_gettimeofday(&tv, tb_null)) return -1;
// the time value
tb_hong_t val = ((tb_hong_t)tv.tv_sec * 1000 + tv.tv_usec / 1000);
// save it
tb_atomic64_set(&g_time, val);
// ok
return val;
}
tb_hong_t tb_cache_time_mclock()
{
tb_hong_t t;
if (!(t = (tb_hong_t)tb_atomic64_get(&g_time)))
t = tb_cache_time_spak();
return t;
}
tb_hong_t tb_cache_time_sclock()
{
return tb_cache_time_mclock() / 1000;
}
tb_time_t tb_cache_time()
{
return (tb_time_t)tb_cache_time_sclock();
}
tbox-1.7.6/src/tbox/platform/cache_time.h 0000664 0000000 0000000 00000003616 14671175054 0020342 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file cache_time.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_CACHE_TIME_H
#define TB_PLATFORM_CACHE_TIME_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the cached time, like tb_time
*
* lower accuracy and faster
*
* @return the now time, s
*/
tb_time_t tb_cache_time(tb_noarg_t);
/*! spak cached time
*
* update the cached time for the external loop thread
*
* @return the now ms-clock
*/
tb_hong_t tb_cache_time_spak(tb_noarg_t);
/*! the cached ms-clock
*
* lower accuracy and faster
*
* @return the now ms-clock
*/
tb_hong_t tb_cache_time_mclock(tb_noarg_t);
/*! the cached s-clock
*
* lower accuracy and faster
*
* @return the now s-clock
*/
tb_hong_t tb_cache_time_clock(tb_noarg_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/compiler/ 0000775 0000000 0000000 00000000000 14671175054 0017714 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/platform/compiler/gcc/ 0000775 0000000 0000000 00000000000 14671175054 0020450 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/platform/compiler/gcc/atomic.h 0000664 0000000 0000000 00000005175 14671175054 0022105 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file atomic.h
*
*/
#ifndef TB_PLATFORM_COMPILER_GCC_ATOMIC_H
#define TB_PLATFORM_COMPILER_GCC_ATOMIC_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef __ATOMIC_SEQ_CST
# define TB_ATOMIC_RELAXED __ATOMIC_RELAXED
# define TB_ATOMIC_CONSUME __ATOMIC_CONSUME
# define TB_ATOMIC_ACQUIRE __ATOMIC_ACQUIRE
# define TB_ATOMIC_RELEASE __ATOMIC_RELEASE
# define TB_ATOMIC_ACQ_REL __ATOMIC_ACQ_REL
# define TB_ATOMIC_SEQ_CST __ATOMIC_SEQ_CST
# define tb_memory_barrier() __atomic_thread_fence(__ATOMIC_SEQ_CST)
# define tb_atomic_flag_test_and_set_explicit(a, mo) __atomic_test_and_set(a, mo)
# define tb_atomic_flag_test_and_set(a) __atomic_test_and_set(a, __ATOMIC_SEQ_CST)
# define tb_atomic_flag_test_explicit(a, mo) tb_atomic_flag_test_explicit_gcc(a, mo)
# define tb_atomic_flag_test(a) tb_atomic_flag_test_explicit(a, __ATOMIC_SEQ_CST)
# define tb_atomic_flag_clear_explicit(a, mo) __atomic_clear(a, mo)
# define tb_atomic_flag_clear(a) __atomic_clear(a, __ATOMIC_SEQ_CST)
#else
# define tb_memory_barrier() __sync_synchronize()
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* inline implementation
*/
#ifdef __ATOMIC_SEQ_CST
static __tb_inline__ tb_bool_t tb_atomic_flag_test_explicit_gcc(tb_atomic_flag_t* a, tb_int_t mo)
{
tb_assert(a);
tb_assert_static(sizeof(tb_atomic_flag_t) == sizeof(unsigned char));
unsigned char t;
__atomic_load((__tb_volatile__ unsigned char*)a, &t, mo);
return (tb_bool_t)t;
}
#endif
#endif
tbox-1.7.6/src/tbox/platform/compiler/gcc/atomic32.h 0000664 0000000 0000000 00000013236 14671175054 0022247 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file atomic32.h
*
*/
#ifndef TB_PLATFORM_COMPILER_GCC_ATOMIC32_H
#define TB_PLATFORM_COMPILER_GCC_ATOMIC32_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef __ATOMIC_SEQ_CST
# define tb_atomic32_init(a, v) tb_atomic32_set_explicit_gcc(a, v, __ATOMIC_RELAXED)
# define tb_atomic32_get(a) tb_atomic32_get_explicit_gcc(a, __ATOMIC_SEQ_CST)
# define tb_atomic32_get_explicit(a, mo) tb_atomic32_get_explicit_gcc(a, mo)
# define tb_atomic32_set(a, v) tb_atomic32_set_explicit_gcc(a, v, __ATOMIC_SEQ_CST)
# define tb_atomic32_set_explicit(a, v, mo) tb_atomic32_set_explicit_gcc(a, v, mo)
# define tb_atomic32_compare_and_swap(a, p, v) tb_atomic32_compare_and_swap_explicit_gcc(a, p, v, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
# define tb_atomic32_compare_and_swap_explicit(a, p, v, succ, fail) \
tb_atomic32_compare_and_swap_explicit_gcc(a, p, v, succ, fail)
# define tb_atomic32_compare_and_swap_weak(a, p, v) tb_atomic32_compare_and_swap_weak_explicit_gcc(a, p, v, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
# define tb_atomic32_compare_and_swap_weak_explicit(a, p, v, succ, fail) \
tb_atomic32_compare_and_swap_weak_explicit_gcc(a, p, v, succ, fail)
# define tb_atomic32_fetch_and_set(a, v) tb_atomic32_fetch_and_set_explicit_gcc(a, v, __ATOMIC_SEQ_CST)
# define tb_atomic32_fetch_and_set_explicit(a, v, mo) tb_atomic32_fetch_and_set_explicit_gcc(a, v, mo)
# define tb_atomic32_fetch_and_add(a, v) __atomic_fetch_add(a, v, __ATOMIC_SEQ_CST)
# define tb_atomic32_fetch_and_add_explicit(a, v, mo) __atomic_fetch_add(a, v, mo)
# define tb_atomic32_fetch_and_sub(a, v) __atomic_fetch_sub(a, v, __ATOMIC_SEQ_CST)
# define tb_atomic32_fetch_and_sub_explicit(a, v, mo) __atomic_fetch_sub(a, v, mo)
# define tb_atomic32_fetch_and_or(a, v) __atomic_fetch_or(a, v, __ATOMIC_SEQ_CST)
# define tb_atomic32_fetch_and_or_explicit(a, v, mo) __atomic_fetch_or(a, v, mo)
# define tb_atomic32_fetch_and_and(a, v) __atomic_fetch_and(a, v, __ATOMIC_SEQ_CST)
# define tb_atomic32_fetch_and_and_explicit(a, v, mo) __atomic_fetch_and(a, v, mo)
# define tb_atomic32_fetch_and_xor(a, v) __atomic_fetch_xor(a, v, __ATOMIC_SEQ_CST)
# define tb_atomic32_fetch_and_xor_explicit(a, v, mo) __atomic_fetch_xor(a, v, mo)
#else
# define tb_atomic32_compare_and_swap_explicit(a, p, v, succ, fail) \
tb_atomic32_compare_and_swap_gcc(a, p, v)
# define tb_atomic32_fetch_and_cmpset_explicit(a, p, v, succ, fail) \
__sync_val_compare_and_swap(a, p, v)
# define tb_atomic32_fetch_and_add_explicit(a, v, mo) __sync_fetch_and_add(a, v)
# define tb_atomic32_fetch_and_sub_explicit(a, v, mo) __sync_fetch_and_sub(a, v)
# define tb_atomic32_fetch_and_or_explicit(a, v, mo) __sync_fetch_and_or(a, v)
# define tb_atomic32_fetch_and_and_explicit(a, v, mo) __sync_fetch_and_and(a, v)
// FIXME: ios armv6: no defined refernece?
# if !(defined(TB_CONFIG_OS_IOS) && TB_ARCH_ARM_VERSION < 7)
# define tb_atomic32_fetch_and_xor_explicit(a, v, mo) __sync_fetch_and_xor(a, v)
# endif
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* inline implementation
*/
#ifdef __ATOMIC_SEQ_CST
static __tb_inline__ tb_int32_t tb_atomic32_get_explicit_gcc(tb_atomic32_t* a, tb_int_t mo)
{
tb_assert(a);
tb_int32_t t;
__atomic_load(a, &t, mo);
return t;
}
static __tb_inline__ tb_void_t tb_atomic32_set_explicit_gcc(tb_atomic32_t* a, tb_int32_t v, tb_int_t mo)
{
tb_assert(a);
__atomic_store(a, &v, mo);
}
static __tb_inline__ tb_bool_t tb_atomic32_compare_and_swap_explicit_gcc(tb_atomic32_t* a, tb_int32_t* p, tb_int32_t v, tb_int_t succ, tb_int_t fail)
{
tb_assert(a);
return __atomic_compare_exchange(a, p, &v, 0, succ, fail);
}
static __tb_inline__ tb_bool_t tb_atomic32_compare_and_swap_weak_explicit_gcc(tb_atomic32_t* a, tb_int32_t* p, tb_int32_t v, tb_int_t succ, tb_int_t fail)
{
tb_assert(a);
return __atomic_compare_exchange(a, p, &v, 1, succ, fail);
}
static __tb_inline__ tb_int32_t tb_atomic32_fetch_and_set_explicit_gcc(tb_atomic32_t* a, tb_int32_t v, tb_int_t mo)
{
tb_assert(a);
tb_int32_t o;
__atomic_exchange(a, &v, &o, mo);
return o;
}
#else
static __tb_inline__ tb_bool_t tb_atomic32_compare_and_swap_gcc(tb_atomic32_t* a, tb_int32_t* p, tb_int32_t v)
{
tb_assert(a && p);
tb_int32_t e = *p;
*p = __sync_val_compare_and_swap(a, e, v);
return *p == e;
}
#endif
#endif
tbox-1.7.6/src/tbox/platform/compiler/gcc/atomic64.h 0000664 0000000 0000000 00000013034 14671175054 0022250 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file atomic64.h
*
*/
#ifndef TB_PLATFORM_COMPILER_GCC_ATOMIC64_H
#define TB_PLATFORM_COMPILER_GCC_ATOMIC64_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef __ATOMIC_SEQ_CST
# define tb_atomic64_init(a, v) tb_atomic64_set_explicit_gcc(a, v, __ATOMIC_RELAXED)
# define tb_atomic64_get(a) tb_atomic64_get_explicit_gcc(a, __ATOMIC_SEQ_CST)
# define tb_atomic64_get_explicit(a, mo) tb_atomic64_get_explicit_gcc(a, mo)
# define tb_atomic64_set(a, v) tb_atomic64_set_explicit_gcc(a, v, __ATOMIC_SEQ_CST)
# define tb_atomic64_set_explicit(a, v, mo) tb_atomic64_set_explicit_gcc(a, v, mo)
# define tb_atomic64_compare_and_swap(a, p, v) tb_atomic64_compare_and_swap_explicit_gcc(a, p, v, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
# define tb_atomic64_compare_and_swap_explicit(a, p, v, succ, fail) \
tb_atomic64_compare_and_swap_explicit_gcc(a, p, v, succ, fail)
# define tb_atomic64_compare_and_swap_weak(a, p, v) tb_atomic64_compare_and_swap_weak_explicit_gcc(a, p, v, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
# define tb_atomic64_compare_and_swap_weak_explicit(a, p, v, succ, fail) \
tb_atomic64_compare_and_swap_weak_explicit_gcc(a, p, v, succ, fail)
# define tb_atomic64_fetch_and_set(a, v) tb_atomic64_fetch_and_set_explicit_gcc(a, v, __ATOMIC_SEQ_CST)
# define tb_atomic64_fetch_and_set_explicit(a, v, mo) tb_atomic64_fetch_and_set_explicit_gcc(a, v, mo)
# define tb_atomic64_fetch_and_add(a, v) __atomic_fetch_add(a, v, __ATOMIC_SEQ_CST)
# define tb_atomic64_fetch_and_add_explicit(a, v, mo) __atomic_fetch_add(a, v, mo)
# define tb_atomic64_fetch_and_sub(a, v) __atomic_fetch_sub(a, v, __ATOMIC_SEQ_CST)
# define tb_atomic64_fetch_and_sub_explicit(a, v, mo) __atomic_fetch_sub(a, v, mo)
# define tb_atomic64_fetch_and_or(a, v) __atomic_fetch_or(a, v, __ATOMIC_SEQ_CST)
# define tb_atomic64_fetch_and_or_explicit(a, v, mo) __atomic_fetch_or(a, v, mo)
# define tb_atomic64_fetch_and_and(a, v) __atomic_fetch_and(a, v, __ATOMIC_SEQ_CST)
# define tb_atomic64_fetch_and_and_explicit(a, v, mo) __atomic_fetch_and(a, v, mo)
# define tb_atomic64_fetch_and_xor(a, v) __atomic_fetch_xor(a, v, __ATOMIC_SEQ_CST)
# define tb_atomic64_fetch_and_xor_explicit(a, v, mo) __atomic_fetch_xor(a, v, mo)
#else
# define tb_atomic64_compare_and_swap(a, p, v) tb_atomic64_compare_and_swap_gcc(a, p, v)
# define tb_atomic64_fetch_and_cmpset(a, p, v) __sync_val_compare_and_swap_8(a, p, v)
# define tb_atomic64_fetch_and_add(a, v) __sync_fetch_and_add_8(a, v)
# define tb_atomic64_fetch_and_sub(a, v) __sync_fetch_and_sub_8(a, v)
# define tb_atomic64_fetch_and_or(a, v) __sync_fetch_and_or_8(a, v)
# define tb_atomic64_fetch_and_and(a, v) __sync_fetch_and_and_8(a, v)
// FIXME: ios armv6: no defined refernece?
# if !(defined(TB_CONFIG_OS_IOS) && TB_ARCH_ARM_VERSION < 7)
# define tb_atomic64_fetch_and_xor(a, v) __sync_fetch_and_xor_8(a, v)
# endif
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* inline implementation
*/
#ifdef __ATOMIC_SEQ_CST
static __tb_inline__ tb_int64_t tb_atomic64_get_explicit_gcc(tb_atomic64_t* a, tb_int_t mo)
{
tb_assert(a);
tb_int64_t t;
__atomic_load(a, &t, mo);
return t;
}
static __tb_inline__ tb_void_t tb_atomic64_set_explicit_gcc(tb_atomic64_t* a, tb_int64_t v, tb_int_t mo)
{
tb_assert(a);
__atomic_store(a, &v, mo);
}
static __tb_inline__ tb_bool_t tb_atomic64_compare_and_swap_explicit_gcc(tb_atomic64_t* a, tb_int64_t* p, tb_int64_t v, tb_int_t succ, tb_int_t fail)
{
tb_assert(a);
return __atomic_compare_exchange(a, p, &v, 0, succ, fail);
}
static __tb_inline__ tb_bool_t tb_atomic64_compare_and_swap_weak_explicit_gcc(tb_atomic64_t* a, tb_int64_t* p, tb_int64_t v, tb_int_t succ, tb_int_t fail)
{
tb_assert(a);
return __atomic_compare_exchange(a, p, &v, 1, succ, fail);
}
static __tb_inline__ tb_int64_t tb_atomic64_fetch_and_set_explicit_gcc(tb_atomic64_t* a, tb_int64_t v, tb_int_t mo)
{
tb_assert(a);
tb_int64_t o;
__atomic_exchange(a, &v, &o, mo);
return o;
}
#else
static __tb_inline__ tb_bool_t tb_atomic64_compare_and_swap_gcc(tb_atomic64_t* a, tb_int64_t* p, tb_int64_t v)
{
tb_assert(a && p);
tb_int64_t e = *p;
*p = __sync_val_compare_and_swap_8(a, e, v);
return *p == e;
}
#endif
#endif
tbox-1.7.6/src/tbox/platform/compiler/gcc/prefix.h 0000664 0000000 0000000 00000001634 14671175054 0022122 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_PLATFORM_COMPILER_GCC_PREFIX_H
#define TB_PLATFORM_COMPILER_GCC_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/platform/compiler/prefix.h 0000664 0000000 0000000 00000001624 14671175054 0021365 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_PLATFORM_COMPILER_PREFIX_H
#define TB_PLATFORM_COMPILER_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/platform/context.c 0000664 0000000 0000000 00000002641 14671175054 0017735 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file context.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "context.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if !defined(TB_ARCH_x86) && \
!defined(TB_ARCH_x64) && \
!defined(TB_ARCH_ARM) && \
!defined(TB_ARCH_MIPS)
tb_context_ref_t tb_context_make(tb_byte_t* stackdata, tb_size_t stacksize, tb_context_func_t func)
{
tb_trace_noimpl();
return tb_null;
}
tb_context_from_t tb_context_jump(tb_context_ref_t context, tb_cpointer_t priv)
{
// noimpl
tb_trace_noimpl();
// return emtry context
tb_context_from_t from = {0};
return from;
}
#endif
tbox-1.7.6/src/tbox/platform/context.h 0000664 0000000 0000000 00000004576 14671175054 0017753 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file context.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_CONTEXT_H
#define TB_PLATFORM_CONTEXT_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the context ref type
typedef __tb_typeref__(context);
// the context-from type
typedef struct __tb_context_from_t
{
// the from-context
tb_context_ref_t context;
// the passed user private data
tb_cpointer_t priv;
}tb_context_from_t;
/*! the context entry function type
*
* @param from the from-context
*/
typedef tb_void_t (*tb_context_func_t)(tb_context_from_t from);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! make context from the given the stack space and the callback function
*
* @param stackdata the stack data
* @param stacksize the stack size
* @param func the entry function
*
* @return the context pointer
*/
tb_context_ref_t tb_context_make(tb_byte_t* stackdata, tb_size_t stacksize, tb_context_func_t func);
/*! jump to the given context
*
* @param context the to-context
* @param priv the passed user private data
*
* @return the from-context
*/
tb_context_from_t tb_context_jump(tb_context_ref_t context, tb_cpointer_t priv);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/cpu.c 0000664 0000000 0000000 00000002216 14671175054 0017036 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file cpu.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "cpu.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_OS_WINDOWS)
# include "windows/cpu.c"
#elif defined(TB_CONFIG_POSIX_HAVE_SYSCONF)
# include "posix/cpu.c"
#else
tb_size_t tb_cpu_count()
{
return 1;
}
#endif
tbox-1.7.6/src/tbox/platform/cpu.h 0000664 0000000 0000000 00000006325 14671175054 0017050 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file cpu.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_CPU_H
#define TB_PLATFORM_CPU_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#if defined(TB_CONFIG_OS_WINDOWS) && defined(TB_COMPILER_IS_MSVC)
# include "windows/prefix.h"
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/*! notifies the CPU that this is a spinlock wait loop so memory and cache accesses may be optimized.
* pause may actually stop CPU for some time to save power. Older CPUs decode it as REP NOP, so you don't have to check if its supported. Older CPUs will simply do nothing (NOP) as fast as possible.
*/
#if defined(TB_CONFIG_OS_WINDOWS) && defined(TB_COMPILER_IS_MSVC)
# if defined(_M_AMD64) || defined(_M_IX86)
# pragma intrinsic(_mm_pause)
# define tb_cpu_pause() do { _mm_pause(); } while (0)
# elif defined(_M_IA64)
# pragma intrinsic(__yield)
# define tb_cpu_pause() do { __yield(); } while (0)
# else
# define tb_cpu_pause() do { YieldProcessor(); } while (0)
# endif
#elif defined(TB_ASSEMBLER_IS_GAS)
# if defined(TB_COMPILER_IS_GCC) && defined(TB_ARCH_x86)
// old "as" does not support "pause" opcode
# define tb_cpu_pause() do { __tb_asm__ __tb_volatile__ (".byte 0xf3, 0x90"); } while (0)
# elif (defined(TB_ARCH_x86) || defined(TB_ARCH_x64))
# if defined(TB_COMPILER_IS_SUNC)
// Sun Studio 12 exits with segmentation fault on '__asm ("pause")'
# define tb_cpu_pause() do { __tb_asm__ __tb_volatile__ ("rep;nop" ::: "memory"); } while (0)
# else
# define tb_cpu_pause() do { __tb_asm__ __tb_volatile__ ("pause"); } while (0)
# endif
# elif 0 // defined(TB_ARCH_ARM), TODO some cross-toolchains may be not supported
# ifdef __CC_ARM
# define tb_cpu_pause() __yield()
# else
# define tb_cpu_pause() do { __tb_asm__ __volatile__ ("yield"); } while (0)
# endif
# endif
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the cpu count
*
* @return the cpu count
*/
tb_size_t tb_cpu_count(tb_noarg_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/deprecated/ 0000775 0000000 0000000 00000000000 14671175054 0020202 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/platform/deprecated/atomic.h 0000664 0000000 0000000 00000004640 14671175054 0021633 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file atomic.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_DEPRECATED_ATOMIC_H
#define TB_PLATFORM_DEPRECATED_ATOMIC_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../atomic.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifndef tb_atomic_set0
# define tb_atomic_set0(a) tb_atomic_set(a, 0)
#endif
#ifndef tb_atomic_fetch_and_pset
# define tb_atomic_fetch_and_pset(a, p, v) tb_atomic_fetch_and_cmpset(a, p, v)
#endif
#ifndef tb_atomic_fetch_and_set0
# define tb_atomic_fetch_and_set0(a) tb_atomic_fetch_and_set(a, 0)
#endif
#ifndef tb_atomic_fetch_and_inc
# define tb_atomic_fetch_and_inc(a) tb_atomic_fetch_and_add(a, 1)
#endif
#ifndef tb_atomic_fetch_and_dec
# define tb_atomic_fetch_and_dec(a) tb_atomic_fetch_and_add(a, -1)
#endif
#ifndef tb_atomic_add_and_fetch
# define tb_atomic_add_and_fetch(a, v) (tb_atomic_fetch_and_add(a, v) + (v))
#endif
#ifndef tb_atomic_inc_and_fetch
# define tb_atomic_inc_and_fetch(a) tb_atomic_add_and_fetch(a, 1)
#endif
#ifndef tb_atomic_dec_and_fetch
# define tb_atomic_dec_and_fetch(a) tb_atomic_add_and_fetch(a, -1)
#endif
#ifndef tb_atomic_sub_and_fetch
# define tb_atomic_sub_and_fetch(a, v) tb_atomic_add_and_fetch(a, -(v))
#endif
#ifndef tb_atomic_or_and_fetch
# define tb_atomic_or_and_fetch(a, v) (tb_atomic_fetch_and_or(a, v) | (v))
#endif
#ifndef tb_atomic_xor_and_fetch
# define tb_atomic_xor_and_fetch(a, v) (tb_atomic_fetch_and_xor(a, v) ^ (v))
#endif
#ifndef tb_atomic_and_and_fetch
# define tb_atomic_and_and_fetch(a, v) (tb_atomic_fetch_and_and(a, v) & (v))
#endif
#endif
tbox-1.7.6/src/tbox/platform/deprecated/atomic64.h 0000664 0000000 0000000 00000005146 14671175054 0022007 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file atomic64.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_DEPRECATED_ATOMIC64_H
#define TB_PLATFORM_DEPRECATED_ATOMIC64_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../atomic64.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifndef tb_atomic64_set0
# define tb_atomic64_set0(a) tb_atomic64_set(a, 0)
#endif
#ifndef tb_atomic64_fetch_and_pset
# define tb_atomic64_fetch_and_pset(a, p, v) tb_atomic64_fetch_and_cmpset(a, p, v)
#endif
#ifndef tb_atomic64_pset
# define tb_atomic64_pset(a, p, v) tb_atomic64_fetch_and_pset(a, p, v)
#endif
#ifndef tb_atomic64_fetch_and_set0
# define tb_atomic64_fetch_and_set0(a) tb_atomic64_fetch_and_set(a, 0)
#endif
#ifndef tb_atomic64_fetch_and_inc
# define tb_atomic64_fetch_and_inc(a) tb_atomic64_fetch_and_add(a, 1)
#endif
#ifndef tb_atomic64_fetch_and_dec
# define tb_atomic64_fetch_and_dec(a) tb_atomic64_fetch_and_add(a, -1)
#endif
#ifndef tb_atomic64_add_and_fetch
# define tb_atomic64_add_and_fetch(a, v) (tb_atomic64_fetch_and_add(a, v) + (v))
#endif
#ifndef tb_atomic64_inc_and_fetch
# define tb_atomic64_inc_and_fetch(a) tb_atomic64_add_and_fetch(a, 1)
#endif
#ifndef tb_atomic64_dec_and_fetch
# define tb_atomic64_dec_and_fetch(a) tb_atomic64_add_and_fetch(a, -1)
#endif
#ifndef tb_atomic64_sub_and_fetch
# define tb_atomic64_sub_and_fetch(a, v) tb_atomic64_add_and_fetch(a, -(v))
#endif
#ifndef tb_atomic64_or_and_fetch
# define tb_atomic64_or_and_fetch(a, v) (tb_atomic64_fetch_and_or(a, v) | (v))
#endif
#ifndef tb_atomic64_xor_and_fetch
# define tb_atomic64_xor_and_fetch(a, v) (tb_atomic64_fetch_and_xor(a, v) ^ (v))
#endif
#ifndef tb_atomic64_and_and_fetch
# define tb_atomic64_and_and_fetch(a, v) (tb_atomic64_fetch_and_and(a, v) & (v))
#endif
#endif
tbox-1.7.6/src/tbox/platform/deprecated/deprecated.h 0000664 0000000 0000000 00000001640 14671175054 0022454 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file deprecated.h
* @ingroup platform
*/
#ifndef TB_PLATFORM_DEPRECATED_H
#define TB_PLATFORM_DEPRECATED_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#endif
tbox-1.7.6/src/tbox/platform/deprecated/prefix.h 0000664 0000000 0000000 00000001655 14671175054 0021657 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
* @ingroup platform
*/
#ifndef TB_PLATFORM_DEPRECATED_PREFIX_H
#define TB_PLATFORM_DEPRECATED_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/platform/directory.c 0000664 0000000 0000000 00000004052 14671175054 0020253 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file directory.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "directory.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_OS_WINDOWS) && !defined(TB_COMPILER_LIKE_UNIX)
# include "windows/directory.c"
#elif defined(TB_CONFIG_POSIX_HAVE_OPENDIR)
# include "posix/directory.c"
#else
tb_bool_t tb_directory_create(tb_char_t const* path)
{
tb_trace_noimpl();
return tb_false;
}
tb_bool_t tb_directory_remove(tb_char_t const* path)
{
tb_trace_noimpl();
return tb_false;
}
tb_size_t tb_directory_home(tb_char_t* path, tb_size_t maxn)
{
tb_trace_noimpl();
return 0;
}
tb_size_t tb_directory_current(tb_char_t* path, tb_size_t maxn)
{
tb_trace_noimpl();
return 0;
}
tb_bool_t tb_directory_current_set(tb_char_t const* path)
{
tb_trace_noimpl();
return tb_false;
}
tb_size_t tb_directory_temporary(tb_char_t* path, tb_size_t maxn)
{
tb_trace_noimpl();
return 0;
}
tb_void_t tb_directory_walk(tb_char_t const* path, tb_long_t recursion, tb_bool_t prefix, tb_directory_walk_func_t func, tb_cpointer_t priv)
{
tb_trace_noimpl();
}
tb_bool_t tb_directory_copy(tb_char_t const* path, tb_char_t const* dest, tb_size_t flags)
{
tb_trace_noimpl();
return tb_false;
}
#endif
tbox-1.7.6/src/tbox/platform/directory.h 0000664 0000000 0000000 00000010201 14671175054 0020251 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file directory.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_DIRECTORY_H
#define TB_PLATFORM_DIRECTORY_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "file.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the directory walk code
typedef enum __tb_directory_walk_code_e
{
TB_DIRECTORY_WALK_CODE_END = 0
, TB_DIRECTORY_WALK_CODE_CONTINUE = 1
, TB_DIRECTORY_WALK_CODE_SKIP_RECURSION = 2 //!< continue and skip sub-directory, only for prefix recursion mode
}tb_directory_walk_code_e;
/*! the directory walk func type
*
* @param path the file path
* @param info the file info
* @param priv the user private data
*
* @return continue: 1 skip-recursion: 2, break: 0
*/
typedef tb_long_t (*tb_directory_walk_func_t)(tb_char_t const* path, tb_file_info_t const* info, tb_cpointer_t priv);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! create the directory
*
* @param path the directory path
*
* @return tb_true or tb_false
*/
tb_bool_t tb_directory_create(tb_char_t const* path);
/*! remove the directory
*
* @param path the directory path
*
* @return tb_true or tb_false
*/
tb_bool_t tb_directory_remove(tb_char_t const* path);
/*! the home directory
*
* @param path the directory path data
* @param maxn the directory path maxn
*
* @return the directory path size
*/
tb_size_t tb_directory_home(tb_char_t* path, tb_size_t maxn);
/*! the current directory
*
* @param path the directory path data
* @param maxn the directory path maxn
*
* @return the directory path size
*/
tb_size_t tb_directory_current(tb_char_t* path, tb_size_t maxn);
/*! set the current directory
*
* @param path the directory path
*
* @return tb_true or tb_false
*/
tb_bool_t tb_directory_current_set(tb_char_t const* path);
/*! the temporary directory
*
* @param path the directory path data
* @param maxn the directory path maxn
*
* @return the directory path size
*/
tb_size_t tb_directory_temporary(tb_char_t* path, tb_size_t maxn);
/*! the directory walk
*
* @param path the directory path
* @param recursion the recursion level, 0, 1, 2, .. or -1 (infinite)
* @param prefix is prefix recursion? directory is the first item
* @param func the callback func
* @param priv the callback priv
*
*/
tb_void_t tb_directory_walk(tb_char_t const* path, tb_long_t recursion, tb_bool_t prefix, tb_directory_walk_func_t func, tb_cpointer_t priv);
/*! copy directory
*
* @param path the directory path
* @param dest the directory dest
* @param flags the copy flags, e.g. TB_FILE_COPY_LINK
*
* @return tb_true or tb_false
*/
tb_bool_t tb_directory_copy(tb_char_t const* path, tb_char_t const* dest, tb_size_t flags);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/dynamic.c 0000664 0000000 0000000 00000003010 14671175054 0017664 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file dynamic.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "dynamic.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#ifdef TB_CONFIG_OS_WINDOWS
# include "windows/dynamic.c"
#elif defined(TB_CONFIG_POSIX_HAVE_DLOPEN)
# include "posix/dynamic.c"
#else
tb_dynamic_ref_t tb_dynamic_init(tb_char_t const* name)
{
tb_trace_noimpl();
return tb_null;
}
tb_void_t tb_dynamic_exit(tb_dynamic_ref_t dynamic)
{
tb_trace_noimpl();
}
tb_pointer_t tb_dynamic_func(tb_dynamic_ref_t dynamic, tb_char_t const* name)
{
tb_trace_noimpl();
return tb_null;
}
tb_pointer_t tb_dynamic_pvar(tb_dynamic_ref_t dynamic, tb_char_t const* name)
{
tb_trace_noimpl();
return tb_null;
}
#endif
tbox-1.7.6/src/tbox/platform/dynamic.h 0000664 0000000 0000000 00000004314 14671175054 0017701 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file mutex.h
* @ingroup dynamic
*
*/
#ifndef TB_PLATFORM_DYNAMIC_H
#define TB_PLATFORM_DYNAMIC_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the dynamic ref type
typedef __tb_typeref__(dynamic);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init dynamic library
*
* @param name the library name
*
* @return the dynamic library
*/
tb_dynamic_ref_t tb_dynamic_init(tb_char_t const* name);
/*! exit dynamic library
*
* @param dynamic the dynamic library
*/
tb_void_t tb_dynamic_exit(tb_dynamic_ref_t dynamic);
/*! the dynamic library function
*
* @param dynamic the dynamic library
* @param name the function name
*
* @return the function address
*/
tb_pointer_t tb_dynamic_func(tb_dynamic_ref_t dynamic, tb_char_t const* name);
/*! the dynamic library variable
*
* @param dynamic the dynamic library
* @param name the variable name
*
* @return the variable address
*/
tb_pointer_t tb_dynamic_pvar(tb_dynamic_ref_t dynamic, tb_char_t const* name);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/environment.c 0000664 0000000 0000000 00000023070 14671175054 0020614 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file environment.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "environment.h"
#include "path.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the separator
#if defined(TB_CONFIG_OS_WINDOWS) && !defined(TB_COMPILER_LIKE_UNIX)
# define TM_ENVIRONMENT_SEP ';'
#else
# define TM_ENVIRONMENT_SEP ':'
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_OS_WINDOWS) && !defined(TB_COMPILER_LIKE_UNIX)
# include "windows/environment.c"
#else
# include "libc/environment.c"
#endif
tb_environment_ref_t tb_environment_init()
{
// init environment
return tb_vector_init(8, tb_element_str(tb_true));
}
tb_void_t tb_environment_exit(tb_environment_ref_t environment)
{
// exit environment
if (environment) tb_vector_exit(environment);
}
tb_size_t tb_environment_size(tb_environment_ref_t environment)
{
return tb_vector_size(environment);
}
tb_char_t const* tb_environment_at(tb_environment_ref_t environment, tb_size_t index)
{
// check
tb_assert_and_check_return_val(environment, tb_null);
// get the value
return (index < tb_vector_size(environment))? (tb_char_t const*)tb_iterator_item(environment, index) : tb_null;
}
tb_bool_t tb_environment_replace(tb_environment_ref_t environment, tb_char_t const* value)
{
// check
tb_assert_and_check_return_val(environment, tb_false);
// clear it first
tb_vector_clear(environment);
// insert value
if (value && *value != '\0') tb_vector_insert_tail(environment, value);
// ok
return tb_true;
}
tb_bool_t tb_environment_insert(tb_environment_ref_t environment, tb_char_t const* value, tb_bool_t to_head)
{
// check
tb_assert_and_check_return_val(environment && value, tb_false);
tb_check_return_val(*value != '\0', tb_true);
// insert value into the head
if (to_head) tb_vector_insert_head(environment, value);
// insert value into the tail
else tb_vector_insert_tail(environment, value);
// ok
return tb_true;
}
tb_size_t tb_environment_get(tb_char_t const* name, tb_char_t* values, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(name && values && maxn, 0);
// init values
tb_string_t valuestrs;
if (!tb_string_init(&valuestrs)) return 0;
// init environment
tb_environment_ref_t environment = tb_environment_init();
if (environment)
{
// load variable
if (tb_environment_load(environment, name))
{
// make values
tb_bool_t is_first = tb_true;
tb_for_all_if (tb_char_t const*, value, environment, value)
{
// append separator
if (!is_first) tb_string_chrcat(&valuestrs, TM_ENVIRONMENT_SEP);
else is_first = tb_false;
// append value
tb_string_cstrcat(&valuestrs, value);
}
}
// exit environment
tb_environment_exit(environment);
}
// save result
tb_size_t size = tb_string_size(&valuestrs);
tb_char_t const* cstr = tb_string_cstr(&valuestrs);
if (size && cstr)
{
// copy it
size = tb_strlcpy(values, cstr, maxn);
tb_assert(size < maxn);
}
// exit values
tb_string_exit(&valuestrs);
// ok?
return size;
}
tb_bool_t tb_environment_set(tb_char_t const* name, tb_char_t const* values)
{
// check
tb_assert_and_check_return_val(name && values, tb_false);
// find the first separator position
tb_bool_t ok = tb_false;
tb_char_t const* p = values? tb_strchr(values, TM_ENVIRONMENT_SEP) : tb_null;
if (p)
{
// init filter
tb_hash_set_ref_t filter = tb_hash_set_init(8, tb_element_str(tb_true));
// init environment
tb_char_t data[TB_PATH_MAXN];
tb_environment_ref_t environment = tb_environment_init();
if (environment)
{
// make environment
tb_char_t const* b = values;
tb_char_t const* e = b + tb_strlen(values);
do
{
// not empty?
if (b < p)
{
// the size
tb_size_t size = tb_min(p - b, sizeof(data) - 1);
// copy it
tb_strncpy(data, b, size);
data[size] = '\0';
// have been not inserted?
if (!filter || !tb_hash_set_get(filter, data))
{
// append the environment
tb_environment_insert(environment, data, tb_false);
// save it to the filter
tb_hash_set_insert(filter, data);
}
}
// end?
tb_check_break(p + 1 < e);
// find the next separator position
b = p + 1;
p = tb_strchr(b, TM_ENVIRONMENT_SEP);
if (!p) p = e;
} while (1);
// set environment variables
ok = tb_environment_save(environment, name);
// exit environment
tb_environment_exit(environment);
}
// exit filter
if (filter) tb_hash_set_exit(filter);
filter = tb_null;
}
// only one?
else
{
// set environment variables
tb_environment_ref_t environment = tb_environment_init();
if (environment)
{
// append the environment
tb_environment_insert(environment, values, tb_false);
// set environment variables
ok = tb_environment_save(environment, name);
// exit environment
tb_environment_exit(environment);
}
}
// ok?
return ok;
}
tb_bool_t tb_environment_add(tb_char_t const* name, tb_char_t const* values, tb_bool_t to_head)
{
// check
tb_assert_and_check_return_val(name && values, tb_false);
// find the first separator position
tb_bool_t ok = tb_false;
tb_char_t const* p = values? tb_strchr(values, TM_ENVIRONMENT_SEP) : tb_null;
if (p)
{
// init filter
tb_hash_set_ref_t filter = tb_hash_set_init(8, tb_element_str(tb_true));
// init environment
tb_char_t data[TB_PATH_MAXN];
tb_environment_ref_t environment = tb_environment_init();
if (environment)
{
// load the previous values
tb_environment_load(environment, name);
// make environment
tb_char_t const* b = values;
tb_char_t const* e = b + tb_strlen(values);
do
{
// not empty?
if (b < p)
{
// the size
tb_size_t size = tb_min(p - b, sizeof(data) - 1);
// copy it
tb_strncpy(data, b, size);
data[size] = '\0';
// have been not inserted?
if (!filter || !tb_hash_set_get(filter, data))
{
// append the environment
tb_environment_insert(environment, data, to_head);
// save it to the filter
tb_hash_set_insert(filter, data);
}
}
// end?
tb_check_break(p + 1 < e);
// find the next separator position
b = p + 1;
p = tb_strchr(b, TM_ENVIRONMENT_SEP);
if (!p) p = e;
} while (1);
// set environment variables
ok = tb_environment_save(environment, name);
// exit environment
tb_environment_exit(environment);
}
// exit filter
if (filter) tb_hash_set_exit(filter);
filter = tb_null;
}
// only one?
else
{
// set environment variables
tb_environment_ref_t environment = tb_environment_init();
if (environment)
{
// load the previous values
tb_environment_load(environment, name);
// append the environment
tb_environment_insert(environment, values, to_head);
// set environment variables
ok = tb_environment_save(environment, name);
// exit environment
tb_environment_exit(environment);
}
}
// ok?
return ok;
}
#ifdef __tb_debug__
tb_void_t tb_environment_dump(tb_environment_ref_t environment, tb_char_t const* name)
{
// trace
tb_trace_i("%s:", name);
// dump values
tb_for_all_if (tb_char_t const*, value, environment, value)
{
// trace
tb_trace_i(" %s", value);
}
}
#endif
tbox-1.7.6/src/tbox/platform/environment.h 0000664 0000000 0000000 00000016750 14671175054 0020630 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file environment.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_ENVIRONMENT_H
#define TB_PLATFORM_ENVIRONMENT_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../container/iterator.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the environment variable ref type
typedef tb_iterator_ref_t tb_environment_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init the environment variable
*
* @return the environment variable
*/
tb_environment_ref_t tb_environment_init(tb_noarg_t);
/*! exit the environment variable
*
* @param environment the environment variable
*/
tb_void_t tb_environment_exit(tb_environment_ref_t environment);
/*! the environment variable count
*
* @param environment the environment variable
*
* @return the environment variable count
*/
tb_size_t tb_environment_size(tb_environment_ref_t environment);
/*! load the environment variable from the given name
*
* @code
*
// init environment
tb_environment_ref_t environment = tb_environment_init();
if (environment)
{
// load variable
if (tb_environment_load(environment, "PATH"))
{
// trace
tb_trace_i("%s:", name);
// dump values
tb_for_all_if (tb_char_t const*, value, environment, value)
{
// trace
tb_trace_i(" %s", value);
}
}
// exit environment
tb_environment_exit(environment);
}
* @endcode
*
* @param environment the environment variable
* @param name the variable name
*
* @return the count of the variable value
*/
tb_size_t tb_environment_load(tb_environment_ref_t environment, tb_char_t const* name);
/*! save the environment variable and will overwrite it
*
* we will remove this environment variable if environment is null or empty
*
* @code
*
// init environment
tb_environment_ref_t environment = tb_environment_init();
if (environment)
{
// insert values
tb_environment_insert(environment, "/xxx/0", tb_false);
tb_environment_insert(environment, "/xxx/1", tb_false);
tb_environment_insert(environment, "/xxx/2", tb_false);
tb_environment_insert(environment, "/xxx/3", tb_false);
// save variable
tb_environment_save(environment, "PATH");
// exit environment
tb_environment_exit(environment);
}
* @endcode
*
* @param environment the environment variable
* @param name the variable name
*
* @return tb_true or tb_false
*/
tb_bool_t tb_environment_save(tb_environment_ref_t environment, tb_char_t const* name);
/*! get the environment variable from the given index
*
* @code
*
// init environment
tb_environment_ref_t environment = tb_environment_init();
if (environment)
{
// load variable
if (tb_environment_load(environment, "PATH"))
{
tb_char_t const* value = tb_environment_at(environment, 0);
if (value)
{
// ...
}
}
// exit environment
tb_environment_exit(environment);
}
* @endcode
*
*
* @param environment the environment variable
* @param index the variable index
*
* @return the variable value
*/
tb_char_t const* tb_environment_at(tb_environment_ref_t environment, tb_size_t index);
/*! replace the environment variable and will overwrite it
*
* we will clear environment and overwrite it
*
* @param environment the environment variable
* @param value the variable value, will clear it if be null
*
* @return tb_true or tb_false
*/
tb_bool_t tb_environment_replace(tb_environment_ref_t environment, tb_char_t const* value);
/*! set the environment variable
*
* @param environment the environment variable
* @param value the variable value
* @param to_head insert value into the head?
*
* @return tb_true or tb_false
*/
tb_bool_t tb_environment_insert(tb_environment_ref_t environment, tb_char_t const* value, tb_bool_t to_head);
#ifdef __tb_debug__
/*! dump the environment variable
*
* @param environment the environment variable
* @param name the variable name
*/
tb_void_t tb_environment_dump(tb_environment_ref_t environment, tb_char_t const* name);
#endif
/*! get the first environment variable value
*
* @code
tb_char_t value[TB_PATH_MAXN];
if (tb_environment_first("HOME", value, sizeof(value)))
{
// ...
}
* @endcode
*
* @param name the variable name
* @param value the variable value
* @param maxn the variable value maxn
*
* @return the variable value size
*/
tb_size_t tb_environment_first(tb_char_t const* name, tb_char_t* value, tb_size_t maxn);
/*! get the environment variable values
*
* @code
tb_char_t value[TB_PATH_MAXN];
if (tb_environment_get("HOME", value, sizeof(value)))
{
// ...
}
* @endcode
*
* @param name the variable name
* @param values the variable values, separator: windows(';') or other(';')
* @param maxn the variable values maxn
*
* @return the variable values size
*/
tb_size_t tb_environment_get(tb_char_t const* name, tb_char_t* values, tb_size_t maxn);
/*! set the environment variable values
*
* we will set all values and overwrite it
*
* @param name the variable name
* @param values the variable values, separator: windows(';') or other(';')
*
* @return tb_true or tb_false
*/
tb_bool_t tb_environment_set(tb_char_t const* name, tb_char_t const* values);
/*! add the environment variable values and not overwrite it
*
* @param name the variable name
* @param values the variable values, separator: windows(';') or other(';')
* @param to_head add value into the head?
*
* @return tb_true or tb_false
*/
tb_bool_t tb_environment_add(tb_char_t const* name, tb_char_t const* values, tb_bool_t to_head);
/*! remove the given environment variable
*
* @param name the variable name
*
* @return tb_true or tb_false
*/
tb_bool_t tb_environment_remove(tb_char_t const* name);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/event.c 0000664 0000000 0000000 00000003270 14671175054 0017371 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file event.c
* @ingroup platform
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "event.h"
#include "time.h"
#include "cache_time.h"
#include "atomic.h"
#include "semaphore.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_OS_WINDOWS)
# include "windows/event.c"
#else
tb_event_ref_t tb_event_init()
{
return (tb_event_ref_t)tb_semaphore_init(0);
}
tb_void_t tb_event_exit(tb_event_ref_t event)
{
if (event) tb_semaphore_exit((tb_semaphore_ref_t)event);
}
tb_bool_t tb_event_post(tb_event_ref_t event)
{
// check
tb_assert_and_check_return_val(event, tb_false);
// post
return tb_semaphore_post((tb_semaphore_ref_t)event, 1);
}
tb_long_t tb_event_wait(tb_event_ref_t event, tb_long_t timeout)
{
// check
tb_assert_and_check_return_val(event, -1);
// wait
return tb_semaphore_wait((tb_semaphore_ref_t)event, timeout);
}
#endif
tbox-1.7.6/src/tbox/platform/event.h 0000664 0000000 0000000 00000003516 14671175054 0017401 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file event.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_EVENT_H
#define TB_PLATFORM_EVENT_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init event
*
* @return the event
*/
tb_event_ref_t tb_event_init(tb_noarg_t);
/*! exit event
*
* @param event the event
*/
tb_void_t tb_event_exit(tb_event_ref_t event);
/*! post event
*
* @param event the event
*
* @return tb_true or tb_false
*/
tb_bool_t tb_event_post(tb_event_ref_t event);
/*! wait event
*
* @param event the event
* @param timeout the timeout
*
* @return ok: 1, timeout or interrupted: 0, fail: -1
*/
tb_long_t tb_event_wait(tb_event_ref_t event, tb_long_t timeout);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/exception.c 0000664 0000000 0000000 00000002711 14671175054 0020245 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file exception.c
* @ingroup platform
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "platform.h"
#include "impl/exception.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_EXCEPTION_ENABLE) && defined(TB_CONFIG_OS_WINDOWS)
# include "windows/exception.c"
#elif defined(TB_CONFIG_EXCEPTION_ENABLE) && \
defined(TB_CONFIG_LIBC_HAVE_SIGNAL) && \
(defined(TB_CONFIG_LIBC_HAVE_SETJMP) || defined(TB_CONFIG_LIBC_HAVE_SIGSETJMP))
# include "libc/exception.c"
#else
tb_bool_t tb_exception_init_env()
{
tb_trace_noimpl();
return tb_true;
}
tb_void_t tb_exception_exit_env()
{
tb_trace_noimpl();
}
#endif
tbox-1.7.6/src/tbox/platform/exception.h 0000664 0000000 0000000 00000004452 14671175054 0020256 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file exception.h
*
*/
#ifndef TB_PLATFORM_EXCEPTION_H
#define TB_PLATFORM_EXCEPTION_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#ifdef TB_CONFIG_EXCEPTION_ENABLE
# if defined(TB_CONFIG_OS_WINDOWS)
# include "windows/exception.h"
# elif defined(TB_CONFIG_LIBC_HAVE_SIGNAL) && \
(defined(TB_CONFIG_LIBC_HAVE_SETJMP) || defined(TB_CONFIG_LIBC_HAVE_SIGSETJMP))
# include "libc/exception.h"
# endif
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// try
#ifndef __tb_try
# define __tb_try do
#endif
// except
#ifndef __tb_except
# define __tb_except(x) while (0); if (0)
#endif
// leave
#ifndef __tb_leave
# define __tb_leave break
#endif
// end
#ifndef __tb_end
# define __tb_end
#endif
// check
#define tb_check_leave(x) { if (!(x)) __tb_leave ; }
// assert
#ifdef __tb_debug__
# define tb_assert_leave(x) { if (!(x)) {tb_trace_a("expr: %s", #x); __tb_leave ; } }
# define tb_assert_and_check_leave(x) tb_assert_leave(x)
#else
# define tb_assert_leave(x)
# define tb_assert_and_check_leave(x) tb_check_leave(x)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/file.c 0000664 0000000 0000000 00000011544 14671175054 0017172 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file file.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "platform_file"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "file.h"
#include "path.h"
#include "../libc/libc.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_OS_WINDOWS) && !defined(TB_COMPILER_LIKE_UNIX)
# include "windows/file.c"
#elif defined(TB_CONFIG_POSIX_HAVE_OPEN)
# include "posix/file.c"
#else
tb_file_ref_t tb_file_init(tb_char_t const* path, tb_size_t mode)
{
tb_trace_noimpl();
return tb_null;
}
tb_bool_t tb_file_exit(tb_file_ref_t file)
{
tb_trace_noimpl();
return tb_false;
}
tb_long_t tb_file_read(tb_file_ref_t file, tb_byte_t* data, tb_size_t size)
{
tb_trace_noimpl();
return -1;
}
tb_long_t tb_file_writ(tb_file_ref_t file, tb_byte_t const* data, tb_size_t size)
{
tb_trace_noimpl();
return -1;
}
tb_long_t tb_file_pread(tb_file_ref_t file, tb_byte_t* data, tb_size_t size, tb_hize_t offset)
{
tb_trace_noimpl();
return -1;
}
tb_long_t tb_file_pwrit(tb_file_ref_t file, tb_byte_t const* data, tb_size_t size, tb_hize_t offset)
{
tb_trace_noimpl();
return -1;
}
tb_long_t tb_file_readv(tb_file_ref_t file, tb_iovec_t const* list, tb_size_t size)
{
tb_trace_noimpl();
return -1;
}
tb_long_t tb_file_writv(tb_file_ref_t file, tb_iovec_t const* list, tb_size_t size)
{
tb_trace_noimpl();
return -1;
}
tb_hong_t tb_file_writf(tb_file_ref_t file, tb_file_ref_t ifile, tb_hize_t offset, tb_hize_t size)
{
tb_trace_noimpl();
return -1;
}
tb_long_t tb_file_preadv(tb_file_ref_t file, tb_iovec_t const* list, tb_size_t size, tb_hize_t offset)
{
tb_trace_noimpl();
return -1;
}
tb_long_t tb_file_pwritv(tb_file_ref_t file, tb_iovec_t const* list, tb_size_t size, tb_hize_t offset)
{
tb_trace_noimpl();
return -1;
}
tb_bool_t tb_file_sync(tb_file_ref_t file)
{
tb_trace_noimpl();
return tb_false;
}
tb_hong_t tb_file_seek(tb_file_ref_t file, tb_hong_t offset, tb_size_t mode)
{
tb_trace_noimpl();
return -1;
}
tb_hong_t tb_file_offset(tb_file_ref_t file)
{
tb_trace_noimpl();
return -1;
}
tb_hize_t tb_file_size(tb_file_ref_t file)
{
tb_trace_noimpl();
return 0;
}
tb_bool_t tb_file_info(tb_char_t const* path, tb_file_info_t* info)
{
tb_trace_noimpl();
return tb_false;
}
tb_bool_t tb_file_copy(tb_char_t const* path, tb_char_t const* dest, tb_size_t flags)
{
tb_trace_noimpl();
return tb_false;
}
tb_bool_t tb_file_create(tb_char_t const* path)
{
tb_trace_noimpl();
return tb_false;
}
tb_bool_t tb_file_remove(tb_char_t const* path)
{
tb_trace_noimpl();
return tb_false;
}
tb_bool_t tb_file_rename(tb_char_t const* path, tb_char_t const* dest)
{
tb_trace_noimpl();
return tb_false;
}
tb_bool_t tb_file_link(tb_char_t const* path, tb_char_t const* dest)
{
tb_trace_noimpl();
return tb_false;
}
tb_bool_t tb_file_access(tb_char_t const* path, tb_size_t mode)
{
tb_trace_noimpl();
return tb_false;
}
tb_bool_t tb_file_touch(tb_char_t const* path, tb_time_t atime, tb_time_t mtime)
{
tb_trace_noimpl();
return tb_false;
}
#endif
tb_long_t tb_file_fscase(tb_char_t const* path)
{
// check
tb_assert_and_check_return_val(path, -1);
// flip path case
tb_char_t path_flipcase[TB_PATH_MAXN];
tb_char_t const* p = path;
tb_size_t i = 0;
tb_char_t ch;
while (*p && i < (TB_PATH_MAXN - 1))
{
ch = *p++;
ch = tb_islower(ch)? tb_toupper(ch) : tb_tolower(ch);
path_flipcase[i++] = ch;
}
path_flipcase[i] = '\0';
tb_file_info_t info, info_flipcase;
if (tb_file_info(path, &info))
{
if (tb_file_info(path_flipcase, &info_flipcase)
&& info.size == info_flipcase.size
&& info.mtime == info_flipcase.mtime
&& info.type == info_flipcase.type
&& info.flags == info_flipcase.flags)
{
return 0;
}
return 1;
}
else return -1;
}
tbox-1.7.6/src/tbox/platform/file.h 0000664 0000000 0000000 00000023663 14671175054 0017204 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file file.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_FILE_H
#define TB_PLATFORM_FILE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
/// the aligned size for direct mode
#define TB_FILE_DIRECT_ASIZE (512)
/// the cached size for direct mode
#ifdef __tb_small__
# define TB_FILE_DIRECT_CSIZE (1 << 14)
#else
# define TB_FILE_DIRECT_CSIZE (1 << 17)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the file mode type
typedef enum __tb_file_mode_e
{
TB_FILE_MODE_RO = 1 //!< read only
, TB_FILE_MODE_WO = 2 //!< write only
, TB_FILE_MODE_RW = 4 //!< read and write
, TB_FILE_MODE_CREAT = 8 //!< create
, TB_FILE_MODE_APPEND = 16 //!< append
, TB_FILE_MODE_TRUNC = 32 //!< truncate
, TB_FILE_MODE_DIRECT = 64 //!< direct, no cache, @note data & size must be aligned by TB_FILE_DIRECT_ASIZE
, TB_FILE_MODE_EXEC = 128 //!< executable, only for tb_file_access, not supported when creating files, not supported on windows
}tb_file_mode_e;
/// the file seek flag
typedef enum __tb_file_seek_flag_e
{
TB_FILE_SEEK_BEG = 0
, TB_FILE_SEEK_CUR = 1
, TB_FILE_SEEK_END = 2
}tb_file_seek_flag_e;
/// the file copy flag
typedef enum __tb_file_copy_flag_e
{
TB_FILE_COPY_NONE = 0 //!< default: copy symlink as file
, TB_FILE_COPY_LINK = 1 //!< reserve symlink
, TB_FILE_COPY_WRITEABLE = 2 //!< writeable, we can copy readonly file and mark it as writeable
}tb_file_copy_flag_e;
/// the file type
typedef enum __tb_file_type_e
{
TB_FILE_TYPE_NONE = 0
, TB_FILE_TYPE_DIRECTORY = 1
, TB_FILE_TYPE_FILE = 2
, TB_FILE_TYPE_DOT = 3
, TB_FILE_TYPE_DOT2 = 4
}tb_file_type_e;
/// the file flag
typedef enum __tb_file_flag_e
{
TB_FILE_FLAG_NONE = 0
, TB_FILE_FLAG_LINK = 1 //!< is symlink?
}tb_file_flag_e;
/// the file info type
typedef struct __tb_file_info_t
{
/// the file type
tb_size_t type: 16;
/// the file flags
tb_size_t flags: 16;
/// the file size
tb_hize_t size;
/// the last access time
tb_time_t atime;
/// the last modify time
tb_time_t mtime;
}tb_file_info_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init the file
*
* @param path the file path
* @param mode the file mode
*
* @return the file
*/
tb_file_ref_t tb_file_init(tb_char_t const* path, tb_size_t mode);
/*! exit the file
*
* @param file the file
*
* @return tb_true or tb_false
*/
tb_bool_t tb_file_exit(tb_file_ref_t file);
/*! read the file data
*
* @param file the file
* @param data the data
* @param size the size
*
* @return the real size or -1
*/
tb_long_t tb_file_read(tb_file_ref_t file, tb_byte_t* data, tb_size_t size);
/*! writ the file data
*
* @param file the file
* @param data the data
* @param size the size
*
* @return the real size or -1
*/
tb_long_t tb_file_writ(tb_file_ref_t file, tb_byte_t const* data, tb_size_t size);
/*! pread the file data
*
* @param file the file
* @param data the data
* @param size the size
* @param offset the offset, the file offset will not be changed
*
* @return the real size or -1
*/
tb_long_t tb_file_pread(tb_file_ref_t file, tb_byte_t* data, tb_size_t size, tb_hize_t offset);
/*! pwrit the file data
*
* @param file the file
* @param data the data
* @param size the size
* @param offset the offset, the file offset will not be changed
*
* @return the real size or -1
*/
tb_long_t tb_file_pwrit(tb_file_ref_t file, tb_byte_t const* data, tb_size_t size, tb_hize_t offset);
/*! readv the file data
*
* @param file the file
* @param list the iovec list
* @param size the iovec size
*
* @return the real size or -1
*/
tb_long_t tb_file_readv(tb_file_ref_t file, tb_iovec_t const* list, tb_size_t size);
/*! writv the file data
*
* @param file the file
* @param list the iovec list
* @param size the iovec size
*
* @return the real size or -1
*/
tb_long_t tb_file_writv(tb_file_ref_t file, tb_iovec_t const* list, tb_size_t size);
/*! writf the file data
*
* @param file the file
* @param ifile the input file
* @param offset the input file offset, the file offset will not be changed
* @param size the writed size
*
* @return the real size or -1
*/
tb_hong_t tb_file_writf(tb_file_ref_t file, tb_file_ref_t ifile, tb_hize_t offset, tb_hize_t size);
/*! preadv the file data
*
* @param file the file
* @param list the iovec list
* @param size the iovec size
* @param offset the offset, the file offset will not be changed
*
* @return the real size or -1
*/
tb_long_t tb_file_preadv(tb_file_ref_t file, tb_iovec_t const* list, tb_size_t size, tb_hize_t offset);
/*! pwritv the file data
*
* @param file the file
* @param list the iovec list
* @param size the iovec size
* @param offset the offset, the file offset will not be changed
*
* @return the real size or -1
*/
tb_long_t tb_file_pwritv(tb_file_ref_t file, tb_iovec_t const* list, tb_size_t size, tb_hize_t offset);
/*! seek the file offset
*
* @param file the file
* @param offset the file offset
* @param mode the seek mode
*
* @return the real offset or -1
*/
tb_hong_t tb_file_seek(tb_file_ref_t file, tb_hong_t offset, tb_size_t mode);
/*! fsync the file
*
* @param file the file
*/
tb_bool_t tb_file_sync(tb_file_ref_t file);
/*! the file size
*
* @param file the file
*
* @return the file size
*/
tb_hize_t tb_file_size(tb_file_ref_t file);
/*! the file offset
*
* @param file the file
*
* @return the file offset or -1
*/
tb_hong_t tb_file_offset(tb_file_ref_t file);
/*! the file info for file or directory
*
* @param path the file path
* @param info the file info
*
* @return tb_true or tb_false
*/
tb_bool_t tb_file_info(tb_char_t const* path, tb_file_info_t* info);
/*! is this file path is case sensitive?
*
* @param path the file path, @note We must pass a path to the file that exists
*
* @return 1: case sensitive, 0: case insensitive, -1: failed
*/
tb_long_t tb_file_fscase(tb_char_t const* path);
/*! copy the file
*
* @param path the file path
* @param dest the dest path
* @param flags the copy flags, e.g. TB_FILE_COPY_LINK
*
* @return tb_true or tb_false
*/
tb_bool_t tb_file_copy(tb_char_t const* path, tb_char_t const* dest, tb_size_t flags);
/*! create the file
*
* @param path the file path
*
* @return tb_true or tb_false
*/
tb_bool_t tb_file_create(tb_char_t const* path);
/*! remove the file
*
* @param path the file path
*
* @return tb_true or tb_false
*/
tb_bool_t tb_file_remove(tb_char_t const* path);
/*! rename the file
*
* @param path the source file path
* @param dest the destination file path
*
* @return tb_true or tb_false
*/
tb_bool_t tb_file_rename(tb_char_t const* path, tb_char_t const* dest);
/*! link the file
*
* @param path the source file path
* @param dest the destination file path
*
* @return tb_true or tb_false
*/
tb_bool_t tb_file_link(tb_char_t const* path, tb_char_t const* dest);
/*! check whether the file or directory can be accessed
*
* @param path the path of the file or directory
* @param mode the required accessing mode
*
* @return tb_true or tb_false
*/
tb_bool_t tb_file_access(tb_char_t const* path, tb_size_t mode);
/*! update the file time, it will create a new if file not found
*
* @param path the file path
* @param atime the last access time, it will not modify this time if it's zero
* @param mtime the last modify time, it will not modify this time if it's zero
*
* @return tb_true or tb_false
*/
tb_bool_t tb_file_touch(tb_char_t const* path, tb_time_t atime, tb_time_t mtime);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/filelock.c 0000664 0000000 0000000 00000003557 14671175054 0020050 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file filelock.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "filelock.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_OS_WINDOWS) && !defined(TB_COMPILER_LIKE_UNIX)
# include "windows/filelock.c"
#elif defined(TB_CONFIG_BSD_HAVE_FLOCK) && !defined(TB_CONFIG_OS_HAIKU)
# include "bsd/filelock.c"
#elif defined(TB_CONFIG_POSIX_HAVE_FCNTL)
# include "posix/filelock.c"
#else
tb_filelock_ref_t tb_filelock_init(tb_file_ref_t file)
{
tb_trace_noimpl();
return tb_null;
}
tb_filelock_ref_t tb_filelock_init_from_path(tb_char_t const* path, tb_size_t mode)
{
tb_trace_noimpl();
return tb_null;
}
tb_void_t tb_filelock_exit(tb_filelock_ref_t lock)
{
tb_trace_noimpl();
}
tb_bool_t tb_filelock_enter(tb_filelock_ref_t lock, tb_size_t mode)
{
tb_trace_noimpl();
return tb_false;
}
tb_bool_t tb_filelock_enter_try(tb_filelock_ref_t lock, tb_size_t mode)
{
tb_trace_noimpl();
return tb_false;
}
tb_bool_t tb_filelock_leave(tb_filelock_ref_t lock)
{
tb_trace_noimpl();
return tb_false;
}
#endif
tbox-1.7.6/src/tbox/platform/filelock.h 0000664 0000000 0000000 00000005463 14671175054 0020053 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file filelock.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_FILELOCK_H
#define TB_PLATFORM_FILELOCK_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "file.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the file lock ref type
typedef __tb_typeref__(filelock);
/// the file lock mode type
typedef enum __tb_filelock_mode_e
{
TB_FILELOCK_MODE_NONE = 0 //!< none
, TB_FILELOCK_MODE_EX = 1 //!< exclusive lock mode
, TB_FILELOCK_MODE_SH = 2 //!< share lock mode
}tb_filelock_mode_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init the file lock
*
* @param file the file reference
*
* @return the file lock
*/
tb_filelock_ref_t tb_filelock_init(tb_file_ref_t file);
/*! init the file lock from the file path
*
* @param path the file path
* @param mode the file mode
*
* @return the file lock
*/
tb_filelock_ref_t tb_filelock_init_from_path(tb_char_t const* path, tb_size_t mode);
/*! exit the file lock
*
* @param lock the file lock
*/
tb_void_t tb_filelock_exit(tb_filelock_ref_t lock);
/*! enter the file lock (block)
*
* @param lock the file lock
* @param mode the lock mode
*
* @return tb_true or tb_false
*/
tb_bool_t tb_filelock_enter(tb_filelock_ref_t lock, tb_size_t mode);
/*! try to enter the file lock
*
* @param lock the file lock
* @param mode the lock mode
*
* @return tb_true or tb_false
*/
tb_bool_t tb_filelock_enter_try(tb_filelock_ref_t lock, tb_size_t mode);
/*! leave the file lock
*
* @param lock the file lock
*
* @return tb_true or tb_false
*/
tb_bool_t tb_filelock_leave(tb_filelock_ref_t lock);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/fwatcher.c 0000664 0000000 0000000 00000004144 14671175054 0020054 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file fwatcher.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "fwatcher"
#define TB_TRACE_MODULE_DEBUG (1)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "fwatcher.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_OS_WINDOWS)
# include "windows/fwatcher_iocp.c"
#elif defined(TB_CONFIG_LINUX_HAVE_INOTIFY_INIT)
# include "linux/fwatcher_inotify.c"
#elif defined(TB_CONFIG_OS_MACOSX)
# include "mach/fwatcher_fsevent.c"
#elif defined(TB_CONFIG_OS_BSD)
# include "bsd/fwatcher_kqueue.c"
#else
tb_fwatcher_ref_t tb_fwatcher_init()
{
tb_trace_noimpl();
return tb_null;
}
tb_void_t tb_fwatcher_exit(tb_fwatcher_ref_t self)
{
tb_trace_noimpl();
}
tb_bool_t tb_fwatcher_add(tb_fwatcher_ref_t self, tb_char_t const* watchdir, tb_bool_t recursion)
{
tb_trace_noimpl();
return tb_false;
}
tb_bool_t tb_fwatcher_remove(tb_fwatcher_ref_t self, tb_char_t const* watchdir)
{
tb_trace_noimpl();
return tb_false;
}
tb_void_t tb_fwatcher_spak(tb_fwatcher_ref_t self)
{
tb_trace_noimpl();
}
tb_long_t tb_fwatcher_wait(tb_fwatcher_ref_t self, tb_fwatcher_event_t* event, tb_long_t timeout)
{
tb_trace_noimpl();
return -1;
}
#endif
tbox-1.7.6/src/tbox/platform/fwatcher.h 0000664 0000000 0000000 00000006422 14671175054 0020062 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file fwatcher.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_FWATCHER_H
#define TB_PLATFORM_FWATCHER_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "path.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the fwatcher ref type
typedef __tb_typeref__(fwatcher);
/// the fwatcher event enum
typedef enum __tb_fwatcher_event_e
{
TB_FWATCHER_EVENT_NONE = 0
, TB_FWATCHER_EVENT_MODIFY = 1
, TB_FWATCHER_EVENT_CREATE = 2
, TB_FWATCHER_EVENT_DELETE = 4
}tb_fwatcher_event_e;
/// the fwatcher event type
typedef struct __tb_fwatcher_event_t
{
tb_size_t event;
tb_char_t filepath[TB_PATH_MAXN];
}tb_fwatcher_event_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init the fwatcher directory watcher
*
* @return the fwatcher
*/
tb_fwatcher_ref_t tb_fwatcher_init(tb_noarg_t);
/*! exit the fwatcher
*
* @param fwatcher the fwatcher
*/
tb_void_t tb_fwatcher_exit(tb_fwatcher_ref_t fwatcher);
/*! add the watched directory, we can just watch single-level directory
*
* @param fwatcher the fwatcher
* @param watchdir the watched directory
* @param recursion is recursion?
*
* @return tb_true or tb_false
*/
tb_bool_t tb_fwatcher_add(tb_fwatcher_ref_t fwatcher, tb_char_t const* watchdir, tb_bool_t recursion);
/*! remove the watched directory, we can just watch single-level directory
*
* @param fwatcher the fwatcher
* @param watchdir the watched directory
*
* @return tb_true or tb_false
*/
tb_bool_t tb_fwatcher_remove(tb_fwatcher_ref_t fwatcher, tb_char_t const* watchdir);
/*! spank the fwatcher, break the tb_fwatcher_wait() and return all events
*
* @param fwatcher the fwatcher
*/
tb_void_t tb_fwatcher_spak(tb_fwatcher_ref_t fwatcher);
/*! wait the fwatcher event
*
* @param fwatcher the fwatcher
* @param event the event
* @param timeout the timeout, infinity: -1
*
* @return > 0: has event, 0: timeout, -1: failed
*/
tb_long_t tb_fwatcher_wait(tb_fwatcher_ref_t fwatcher, tb_fwatcher_event_t* event, tb_long_t timeout);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/hostname.c 0000664 0000000 0000000 00000002307 14671175054 0020066 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file hostname.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "hostname.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#ifdef TB_CONFIG_OS_WINDOWS
# include "windows/hostname.c"
#elif defined(TB_CONFIG_POSIX_HAVE_GETHOSTNAME)
# include "posix/hostname.c"
#else
tb_bool_t tb_hostname(tb_char_t* name, tb_size_t size)
{
tb_trace_noimpl();
return tb_false;
}
#endif
tbox-1.7.6/src/tbox/platform/hostname.h 0000664 0000000 0000000 00000002715 14671175054 0020076 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file hostname.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_HOSTNAME_H
#define TB_PLATFORM_HOSTNAME_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the host name
*
* @param name the hostname data
* @param size the hostname size
*
* @return tb_true or tb_false
*/
tb_bool_t tb_hostname(tb_char_t* name, tb_size_t size);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/ifaddrs.c 0000664 0000000 0000000 00000017243 14671175054 0017671 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file ifaddrs.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "ifaddrs"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "ifaddrs.h"
#include "../utils/utils.h"
#include "../algorithm/algorithm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* instance implementation
*/
static tb_handle_t tb_ifaddrs_instance_init(tb_cpointer_t* ppriv)
{
// init it
return (tb_handle_t)tb_ifaddrs_init();
}
static tb_void_t tb_ifaddrs_instance_exit(tb_handle_t ifaddrs, tb_cpointer_t priv)
{
// exit it
tb_ifaddrs_exit((tb_ifaddrs_ref_t)ifaddrs);
}
static tb_bool_t tb_ifaddrs_interface_pred(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t name)
{
// check
tb_assert(item);
// is equal?
return !tb_stricmp(((tb_ifaddrs_interface_ref_t)item)->name, (tb_char_t const*)name);
}
static tb_ifaddrs_interface_ref_t tb_ifaddrs_interface_find(tb_iterator_ref_t iterator, tb_char_t const* name)
{
// check
tb_assert_and_check_return_val(iterator && name, tb_null);
// find it
tb_size_t itor = tb_find_all_if(iterator, tb_ifaddrs_interface_pred, name);
tb_check_return_val(itor != tb_iterator_tail(iterator), tb_null);
// ok
return (tb_ifaddrs_interface_ref_t)tb_iterator_item(iterator, itor);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#ifdef TB_CONFIG_OS_WINDOWS
# include "windows/ifaddrs.c"
#elif defined(TB_CONFIG_POSIX_HAVE_GETIFADDRS) && !defined(TB_CONFIG_OS_WEB)
# if defined(TB_CONFIG_LINUX_HAVE_IFADDRS) || defined(TB_CONFIG_OS_ANDROID)
# include "linux/ifaddrs.c"
# else
# include "posix/ifaddrs.c"
# endif
#elif defined(TB_CONFIG_LINUX_HAVE_IFADDRS) || defined(TB_CONFIG_OS_ANDROID)
# include "linux/ifaddrs2.c"
#else
tb_ifaddrs_ref_t tb_ifaddrs_init()
{
tb_trace_noimpl();
return tb_null;
}
tb_void_t tb_ifaddrs_exit(tb_ifaddrs_ref_t ifaddrs)
{
tb_trace_noimpl();
}
tb_iterator_ref_t tb_ifaddrs_itor(tb_ifaddrs_ref_t ifaddrs, tb_bool_t reload)
{
tb_trace_noimpl();
return tb_null;
}
#endif
tb_ifaddrs_ref_t tb_ifaddrs()
{
return (tb_ifaddrs_ref_t)tb_singleton_instance(TB_SINGLETON_TYPE_IFADDRS, tb_ifaddrs_instance_init, tb_ifaddrs_instance_exit, tb_null, tb_null);
}
tb_ifaddrs_interface_ref_t tb_ifaddrs_interface(tb_ifaddrs_ref_t ifaddrs, tb_char_t const* name, tb_bool_t reload)
{
// check
tb_assert_and_check_return_val(ifaddrs && name, tb_null);
// the iterator
tb_iterator_ref_t iterator = tb_ifaddrs_itor(ifaddrs, reload);
tb_assert_and_check_return_val(iterator, tb_null);
// reload it if the cached interfaces is empty
if (!reload && !tb_iterator_size(iterator)) iterator = tb_ifaddrs_itor(ifaddrs, tb_true);
// ok
return tb_ifaddrs_interface_find(iterator, name);
}
tb_bool_t tb_ifaddrs_hwaddr(tb_ifaddrs_ref_t ifaddrs, tb_char_t const* name, tb_bool_t reload, tb_hwaddr_ref_t hwaddr)
{
// check
tb_assert_and_check_return_val(ifaddrs && hwaddr, tb_false);
// clear it first
tb_hwaddr_clear(hwaddr);
// the iterator
tb_iterator_ref_t iterator = tb_ifaddrs_itor(ifaddrs, reload);
tb_assert_and_check_return_val(iterator, tb_false);
// reload it if the cached interfaces is empty
if (!reload && !tb_iterator_size(iterator)) iterator = tb_ifaddrs_itor(ifaddrs, tb_true);
// done
tb_bool_t ok = tb_false;
tb_for_all_if (tb_ifaddrs_interface_ref_t, iface, iterator, iface)
{
// get hwaddr from the given iface name?
if (name)
{
// is this?
if ( (iface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR)
&& (iface->name && !tb_strcmp(iface->name, name)))
{
// save hwaddr
tb_hwaddr_copy(hwaddr, &iface->hwaddr);
// ok
ok = tb_true;
break;
}
}
else
{
// is this?
if ( (iface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR)
&& (iface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR)
&& !(iface->flags & TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK))
{
// save hwaddr
tb_hwaddr_copy(hwaddr, &iface->hwaddr);
// ok
ok = tb_true;
break;
}
}
}
// ok?
return ok;
}
tb_bool_t tb_ifaddrs_ipaddr(tb_ifaddrs_ref_t ifaddrs, tb_char_t const* name, tb_bool_t reload, tb_size_t family, tb_ipaddr_ref_t ipaddr)
{
// check
tb_assert_and_check_return_val(ifaddrs && ipaddr, tb_false);
// clear it first
tb_ipaddr_clear(ipaddr);
// the iterator
tb_iterator_ref_t iterator = tb_ifaddrs_itor(ifaddrs, reload);
tb_assert_and_check_return_val(iterator, tb_false);
// reload it if the cached interfaces is empty
if (!reload && !tb_iterator_size(iterator)) iterator = tb_ifaddrs_itor(ifaddrs, tb_true);
tb_bool_t ok = tb_false;
tb_for_all_if (tb_ifaddrs_interface_ref_t, iface, iterator, iface)
{
// is this?
if ( (name || !(iface->flags & TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK))
&& (iface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR)
&& (!name || (iface->name && !tb_strcmp(iface->name, name))))
{
// ipv4?
if ( iface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR4
&& (!family || family == TB_IPADDR_FAMILY_IPV4))
{
// save ipaddr4
tb_ipaddr_ipv4_set(ipaddr, &iface->ipaddr4);
// ok
ok = tb_true;
break;
}
// ipv6?
else if ( iface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR6
&& (!family || family == TB_IPADDR_FAMILY_IPV6))
{
// save ipaddr6
tb_ipaddr_ipv6_set(ipaddr, &iface->ipaddr6);
// ok
ok = tb_true;
break;
}
}
}
return ok;
}
#ifdef __tb_debug__
tb_void_t tb_ifaddrs_dump(tb_ifaddrs_ref_t ifaddrs)
{
// trace
tb_trace_i("");
// done
tb_for_all_if (tb_ifaddrs_interface_ref_t, iface, tb_ifaddrs_itor(ifaddrs, tb_true), iface)
{
// trace
tb_trace_i("name: %s%s", iface->name, (iface->flags & TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK)? "[loopback]" : "");
if (iface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR4)
tb_trace_i(" ipaddr4: %{ipv4}", &iface->ipaddr4);
if (iface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR6)
tb_trace_i(" ipaddr6: %{ipv6}", &iface->ipaddr6);
if (iface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR)
tb_trace_i(" hwaddr: %{hwaddr}", &iface->hwaddr);
}
}
#endif
tbox-1.7.6/src/tbox/platform/ifaddrs.h 0000664 0000000 0000000 00000011563 14671175054 0017675 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file ifaddrs.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_IFADDRS_H
#define TB_PLATFORM_IFADDRS_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../network/ipaddr.h"
#include "../network/hwaddr.h"
#include "../container/iterator.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the ifaddrs interface flag enum
typedef enum __tb_ifaddrs_interface_flag_e
{
TB_IFADDRS_INTERFACE_FLAG_NONE = 0
, TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR4 = 1
, TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR6 = 2
, TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR = TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR4 | TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR6
, TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR = 4
, TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK = 8
}tb_ifaddrs_interface_flag_e;
/// the ifaddrs interface type
typedef struct __tb_ifaddrs_interface_t
{
/// the interface name
tb_char_t const* name;
/// the interface flags
tb_uint32_t flags;
// the hardware address
tb_hwaddr_t hwaddr;
// the ipv4 address
tb_ipv4_t ipaddr4;
// the ipv6 address
tb_ipv6_t ipaddr6;
}tb_ifaddrs_interface_t, *tb_ifaddrs_interface_ref_t;
/// the ifaddrs type
typedef __tb_typeref__(ifaddrs);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! the ifaddrs instance
*
* @return the ifaddrs
*/
tb_ifaddrs_ref_t tb_ifaddrs(tb_noarg_t);
/*! init ifaddrs
*
* @return the ifaddrs
*/
tb_ifaddrs_ref_t tb_ifaddrs_init(tb_noarg_t);
/*! exit ifaddrs
*
* @param ifaddrs the ifaddrs
*/
tb_void_t tb_ifaddrs_exit(tb_ifaddrs_ref_t ifaddrs);
/*! the ifaddrs interface iterator
*
* @code
* tb_for_all_if (tb_ifaddrs_interface_ref_t, interface, tb_ifaddrs_itor(ifaddrs, tb_false), interface)
* {
* // ...
* }
* @endcode
*
* @param ifaddrs the ifaddrs
* @param reload force to reload the ifaddrs list, will cache list if be false
*
* @return the interface iterator
*/
tb_iterator_ref_t tb_ifaddrs_itor(tb_ifaddrs_ref_t ifaddrs, tb_bool_t reload);
/*! get the interface from the given interface name
*
* @param ifaddrs the ifaddrs
* @param name the interface name
* @param reload force to reload the ifaddrs list, will cache list if be false
*
* @return tb_true or tb_false
*/
tb_ifaddrs_interface_ref_t tb_ifaddrs_interface(tb_ifaddrs_ref_t ifaddrs, tb_char_t const* name, tb_bool_t reload);
/*! the hardware address from the given interface name
*
* @param ifaddrs the ifaddrs
* @param name the interface name, get the first ether address if be null
* @param reload force to reload the ifaddrs list, will cache list if be false
* @param hwaddr the hardware address
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ifaddrs_hwaddr(tb_ifaddrs_ref_t ifaddrs, tb_char_t const* name, tb_bool_t reload, tb_hwaddr_ref_t hwaddr);
/*! the hardware address from the given interface name
*
* @param ifaddrs the ifaddrs
* @param name the interface name, get the first ether address if be null
* @param reload force to reload the ifaddrs list, will cache list if be false
* @param family the address family
* @param ipaddr the ip address
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ifaddrs_ipaddr(tb_ifaddrs_ref_t ifaddrs, tb_char_t const* name, tb_bool_t reload, tb_size_t family, tb_ipaddr_ref_t ipaddr);
#ifdef __tb_debug__
/*! dump the ifaddrs
*
* @param ifaddrs the ifaddrs
*/
tb_void_t tb_ifaddrs_dump(tb_ifaddrs_ref_t ifaddrs);
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/impl/ 0000775 0000000 0000000 00000000000 14671175054 0017043 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/platform/impl/charset.c 0000664 0000000 0000000 00000002644 14671175054 0020646 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file charset.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "platform_charset"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "charset.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_OS_WINDOWS) && defined(TB_CONFIG_MODULE_HAVE_CHARSET)
# include "../windows/charset.c"
#else
tb_long_t tb_charset_conv_impl(tb_size_t ftype, tb_size_t ttype, tb_static_stream_ref_t fst, tb_static_stream_ref_t tst)
{
return -1;
}
#endif
tbox-1.7.6/src/tbox/platform/impl/charset.h 0000664 0000000 0000000 00000003327 14671175054 0020652 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file charset.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_IMPL_CHARSET_H
#define TB_PLATFORM_IMPL_CHARSET_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../../stream/stream.h"
#include "../../charset/charset.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* convert charset encoding data using the platform api
*
* @param ftype the from charset
* @param ttype the to charset
* @param fst the from stream
* @param tst the to stream
*
* @return the converted bytes for output or -1
*/
tb_long_t tb_charset_conv_impl(tb_size_t ftype, tb_size_t ttype, tb_static_stream_ref_t fst, tb_static_stream_ref_t tst);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/impl/dns.c 0000664 0000000 0000000 00000002614 14671175054 0017776 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file dns.c
* @ingroup platform
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "dns"
#define TB_TRACE_MODULE_DEBUG (1)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "dns.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_OS_WINDOWS)
# include "../windows/dns.c"
#elif defined(TB_CONFIG_OS_MACOSX) || defined(TB_CONFIG_OS_IOS)
# include "../mach/dns.c"
#elif defined(TB_CONFIG_OS_ANDROID)
# include "../android/dns.c"
#else
# include "../unix/dns.c"
#endif
tbox-1.7.6/src/tbox/platform/impl/dns.h 0000664 0000000 0000000 00000002656 14671175054 0020011 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file dns.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_IMPL_DNS_H
#define TB_PLATFORM_IMPL_DNS_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* init dns environment
*
* @return tb_true or tb_false
*/
tb_bool_t tb_dns_init_env(tb_noarg_t);
// exit dns environment
tb_void_t tb_dns_exit_env(tb_noarg_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/impl/exception.h 0000664 0000000 0000000 00000002737 14671175054 0021223 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file exception.h
*
*/
#ifndef TB_PLATFORM_IMPL_EXCEPTION_H
#define TB_PLATFORM_IMPL_EXCEPTION_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* init the exception environment
*
* @return tb_true or tb_false
*/
tb_bool_t tb_exception_init_env(tb_noarg_t);
// exit the exception environment
tb_void_t tb_exception_exit_env(tb_noarg_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/impl/impl.h 0000664 0000000 0000000 00000001751 14671175054 0020161 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file impl.h
*
*/
#ifndef TB_PLATFORM_IMPL_H
#define TB_PLATFORM_IMPL_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "dns.h"
#include "socket.h"
#include "pollerdata.h"
#include "exception.h"
#include "thread_local.h"
#include "platform.h"
#endif
tbox-1.7.6/src/tbox/platform/impl/mutex.h 0000664 0000000 0000000 00000004555 14671175054 0020367 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file mutex.h
*
*/
#ifndef TB_PLATFORM_IMPL_MUTEX_H
#define TB_PLATFORM_IMPL_MUTEX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#ifdef TB_CONFIG_OS_WINDOWS
# include "../windows/prefix.h"
#elif defined(TB_CONFIG_POSIX_HAVE_PTHREAD_MUTEX_INIT)
# include
#else
# include "../spinlock.h"
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
#if defined(TB_CONFIG_OS_WINDOWS)
typedef HANDLE tb_mutex_t;
#elif defined(TB_CONFIG_POSIX_HAVE_PTHREAD_MUTEX_INIT)
typedef pthread_mutex_t tb_mutex_t;
#else
typedef tb_spinlock_t tb_mutex_t;
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* init mutex at the given mutex data
*
* @param the mutex data
*
* @return the mutex reference
*/
tb_mutex_ref_t tb_mutex_init_impl(tb_mutex_t* mutex);
/* exit mutex
*
* @param the mutex data
*/
tb_void_t tb_mutex_exit_impl(tb_mutex_t* mutex);
/* enter mutex without profiler
*
* @param mutex the mutex
*
* @return tb_true or tb_false
*/
tb_bool_t tb_mutex_enter_without_profiler(tb_mutex_ref_t mutex);
/* try to enter mutex without profiler
*
* @param mutex the mutex
*
* @return tb_true or tb_false
*/
tb_bool_t tb_mutex_entry_try_without_profiler(tb_mutex_ref_t mutex);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/impl/platform.c 0000664 0000000 0000000 00000006102 14671175054 0021032 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file platform.c
* @ingroup platform
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "platform.h"
#include "impl.h"
#include "../cpu.h"
#include "../exception.h"
#include "../cache_time.h"
#include "../../network/network.h"
#if defined(TB_CONFIG_OS_ANDROID)
# include "../android/android.h"
#elif defined(TB_CONFIG_OS_WINDOWS)
# include "../windows/windows.h"
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* declaration
*/
__tb_extern_c_enter__
tb_bool_t tb_process_group_init();
tb_void_t tb_process_group_exit();
__tb_extern_c_leave__
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_platform_init_env(tb_handle_t priv)
{
// init the current platform environment
#if defined(TB_CONFIG_OS_ANDROID)
if (!tb_android_init_env(priv)) return tb_false;
#elif defined(TB_CONFIG_OS_WINDOWS)
if (!tb_windows_init_env()) return tb_false;
#endif
// init socket environment
if (!tb_socket_init_env()) return tb_false;
// init dns environment
#ifndef TB_CONFIG_MICRO_ENABLE
if (!tb_dns_init_env()) return tb_false;
#endif
// init thread local environment
#ifndef TB_CONFIG_MICRO_ENABLE
if (!tb_thread_local_init_env()) return tb_false;
#endif
// init exception environment
#ifdef TB_CONFIG_EXCEPTION_ENABLE
if (!tb_exception_init_env()) return tb_false;
#endif
// init cpu count/cache
#ifndef TB_CONFIG_MICRO_ENABLE
(tb_void_t)tb_cpu_count();
#endif
// init the global process group
#ifndef TB_CONFIG_MICRO_ENABLE
if (!tb_process_group_init()) return tb_false;
#endif
// ok
return tb_true;
}
tb_void_t tb_platform_exit_env()
{
// exit all process in the process group
#ifndef TB_CONFIG_MICRO_ENABLE
tb_process_group_exit();
#endif
// exit exception environment
#ifdef TB_CONFIG_EXCEPTION_ENABLE
tb_exception_exit_env();
#endif
// exit thread local environment
#ifndef TB_CONFIG_MICRO_ENABLE
tb_thread_local_exit_env();
#endif
// exit dns environment
#ifndef TB_CONFIG_MICRO_ENABLE
tb_dns_exit_env();
#endif
// exit socket environment
tb_socket_exit_env();
// exit the current platform environment
#if defined(TB_CONFIG_OS_ANDROID)
tb_android_exit_env();
#elif defined(TB_CONFIG_OS_WINDOWS)
tb_windows_exit_env();
#endif
}
tbox-1.7.6/src/tbox/platform/impl/platform.h 0000664 0000000 0000000 00000003217 14671175054 0021043 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file platform.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_IMPL_PLATFORM_H
#define TB_PLATFORM_IMPL_PLATFORM_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init the platform environment
*
* @param priv the platform private data
* pass JavaVM* jvm for android
* pass tb_null for other platform
*
* @return tb_true or tb_false
*/
tb_bool_t tb_platform_init_env(tb_handle_t priv);
/// exit the platform environment
tb_void_t tb_platform_exit_env(tb_noarg_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/impl/poller.h 0000664 0000000 0000000 00000011507 14671175054 0020515 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file poller.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_IMPL_POLLER_H
#define TB_PLATFORM_IMPL_POLLER_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../poller.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// get the poller object type from the private pointer
#define tb_poller_priv_get_object_type(ptr) (((tb_size_t)(ptr) & ((tb_size_t)0x1 << (TB_CPU_BITSIZE - 1)))? TB_POLLER_OBJECT_PIPE : TB_POLLER_OBJECT_SOCK)
// get the original private pointer
#define tb_poller_priv_get_original(ptr) ((tb_cpointer_t)((tb_size_t)(ptr) & ~((tb_size_t)0x1 << (TB_CPU_BITSIZE - 1))))
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the process poller ref type
typedef __tb_typeref__(poller_process);
/// the fwatcher poller ref type
typedef __tb_typeref__(poller_fwatcher);
// the poller type
typedef struct __tb_poller_t
{
// the user private data
tb_cpointer_t priv;
// the poller type
tb_uint16_t type;
// the supported events
tb_uint16_t supported_events;
#ifndef TB_CONFIG_MICRO_ENABLE
// the process poller
tb_poller_process_ref_t process_poller;
// the fwatcher poller
tb_poller_fwatcher_ref_t fwatcher_poller;
#endif
/* exit poller
*
* @param poller the poller
*/
tb_void_t (*exit)(struct __tb_poller_t* poller);
/* kill all waited events, tb_poller_wait() will return -1
*
* @param poller the poller
*/
tb_void_t (*kill)(struct __tb_poller_t* poller);
/* spak the poller, break the tb_poller_wait() and return all events
*
* @param poller the poller
*/
tb_void_t (*spak)(struct __tb_poller_t* poller);
/* wait events for all objects
*
* @param poller the poller
* @param func the events function
* @param timeout the timeout, infinity: -1
*
* @return > 0: the events number, 0: timeout, -1: failed
*/
tb_long_t (*wait)(struct __tb_poller_t* poller, tb_poller_event_func_t func, tb_long_t timeout);
/* insert socket to poller
*
* @param poller the poller
* @param object the poller object
* @param events the poller events
* @param priv the private data
*
* @return tb_true or tb_false
*/
tb_bool_t (*insert)(struct __tb_poller_t* poller, tb_poller_object_ref_t object, tb_size_t events, tb_cpointer_t priv);
/* remove socket from poller
*
* @param poller the poller
* @param object the poller object
*
* @return tb_true or tb_false
*/
tb_bool_t (*remove)(struct __tb_poller_t* poller, tb_poller_object_ref_t object);
/* modify events for the given socket
*
* @param poller the poller
* @param object the poller object
* @param events the poller events
* @param priv the private data
*
* @return tb_true or tb_false
*/
tb_bool_t (*modify)(struct __tb_poller_t* poller, tb_poller_object_ref_t object, tb_size_t events, tb_cpointer_t priv);
/* attach the poller to the current thread (only for windows/iocp now)
*
* @param poller the poller
*/
tb_void_t (*attach)(struct __tb_poller_t* poller);
}tb_poller_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* inline implementation
*/
// set the object type to the private pointer
static __tb_inline__ tb_cpointer_t tb_poller_priv_set_object_type(tb_poller_object_ref_t object, tb_cpointer_t ptr)
{
// must be a valid pointer address
tb_assert(!((tb_size_t)ptr & ((tb_size_t)0x1 << (TB_CPU_BITSIZE - 1))));
return object->type == TB_POLLER_OBJECT_PIPE? (tb_cpointer_t)((tb_size_t)ptr | ((tb_size_t)0x1 << (TB_CPU_BITSIZE - 1))) : ptr;
}
#endif
tbox-1.7.6/src/tbox/platform/impl/poller_fwatcher.c 0000664 0000000 0000000 00000026417 14671175054 0022401 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file poller_fwatcher.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../fwatcher.h"
#include "../thread.h"
#include "../atomic.h"
#include "../spinlock.h"
#include "../semaphore.h"
#include "../../algorithm/algorithm.h"
#include "../../container/container.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the poller fwatcher type
typedef struct __tb_poller_fwatcher_t
{
// the main poller
tb_poller_t* main_poller;
// the fwatcher poller thread
tb_thread_ref_t thread;
// is stopped?
tb_atomic32_t is_stopped;
// the lock
tb_spinlock_t lock;
// the fwatcher
tb_fwatcher_ref_t fwatcher;
// the user data
tb_cpointer_t udata;
// the semaphore
tb_semaphore_ref_t semaphore;
// the waiting event
tb_fwatcher_event_t waiting_event;
// the waited events
tb_vector_ref_t waited_events;
tb_vector_ref_t waited_events_copied;
}tb_poller_fwatcher_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_int_t tb_poller_fwatcher_loop(tb_cpointer_t priv)
{
// check
tb_poller_fwatcher_t* poller = (tb_poller_fwatcher_t*)priv;
tb_assert_and_check_return_val(poller && poller->semaphore && poller->waited_events, -1);
// do loop
tb_fwatcher_ref_t fwatcher = tb_null;
while (!tb_atomic32_get(&poller->is_stopped))
{
// get fwatcher
tb_spinlock_enter(&poller->lock);
fwatcher = poller->fwatcher;
tb_spinlock_leave(&poller->lock);
if (fwatcher)
{
// wait events
tb_long_t wait = tb_fwatcher_wait(fwatcher, &poller->waiting_event, -1);
tb_assert_and_check_break(wait >= 0);
tb_check_continue(wait > 0);
// save waited event
tb_spinlock_enter(&poller->lock);
tb_vector_insert_tail(poller->waited_events, &poller->waiting_event);
tb_spinlock_leave(&poller->lock);
// notify the main poller to poll them
tb_poller_t* main_poller = poller->main_poller;
if (main_poller && main_poller->spak)
main_poller->spak(main_poller);
}
else
{
// wait semaphore
tb_long_t wait = tb_semaphore_wait(poller->semaphore, -1);
tb_assert_and_check_break(wait >= 0);
// interrupted? continue to wait
tb_check_continue(wait != 0);
}
}
// mark this thread is stopped
tb_atomic32_set(&poller->is_stopped, 1);
return 0;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_poller_fwatcher_kill(tb_poller_fwatcher_ref_t self)
{
// check
tb_poller_fwatcher_t* poller = (tb_poller_fwatcher_t*)self;
tb_assert_and_check_return(poller && poller->semaphore);
// trace
tb_trace_d("fwatcher: kill ..");
// stop thread and post it
if (!tb_atomic32_fetch_and_set(&poller->is_stopped, 1))
{
if (poller->fwatcher)
tb_fwatcher_spak(poller->fwatcher);
tb_semaphore_post(poller->semaphore, 1);
}
}
static tb_void_t tb_poller_fwatcher_exit(tb_poller_fwatcher_ref_t self)
{
// check
tb_poller_fwatcher_t* poller = (tb_poller_fwatcher_t*)self;
tb_assert_and_check_return(poller);
// kill the fwatcher poller first
tb_poller_fwatcher_kill(self);
// exit the fwatcher poller thread
if (poller->thread)
{
// wait it
tb_long_t wait = 0;
if ((wait = tb_thread_wait(poller->thread, 5000, tb_null)) <= 0)
{
// trace
tb_trace_e("wait fwatcher poller thread failed: %ld!", wait);
}
// exit it
tb_thread_exit(poller->thread);
poller->thread = tb_null;
}
// exit waited events
if (poller->waited_events) tb_vector_exit(poller->waited_events);
if (poller->waited_events_copied) tb_vector_exit(poller->waited_events_copied);
poller->waited_events = tb_null;
poller->waited_events_copied = tb_null;
// exit semaphore
if (poller->semaphore) tb_semaphore_exit(poller->semaphore);
poller->semaphore = tb_null;
// exit lock
tb_spinlock_exit(&poller->lock);
// reset fwatcher
poller->fwatcher = tb_null;
poller->udata = tb_null;
// exit poller
tb_free(poller);
}
static tb_poller_fwatcher_ref_t tb_poller_fwatcher_init(tb_poller_t* main_poller)
{
tb_bool_t ok = tb_false;
tb_poller_fwatcher_t* poller = tb_null;
do
{
// @note only support one fwatcher poller instance
static tb_size_t s_poller_fwatcher_num = 0;
if (s_poller_fwatcher_num++)
{
tb_trace_e("only support one fwatcher poller!");
break;
}
// make the fwatcher poller
poller = tb_malloc0_type(tb_poller_fwatcher_t);
tb_assert_and_check_break(poller);
// save the main poller
poller->main_poller = main_poller;
// init lock
tb_spinlock_init(&poller->lock);
// init semaphore
poller->semaphore = tb_semaphore_init(0);
tb_assert_and_check_break(poller->semaphore);
// init waited events
poller->waited_events = tb_vector_init(0, tb_element_mem(sizeof(tb_fwatcher_event_t), tb_null, tb_null));
poller->waited_events_copied = tb_vector_init(0, tb_element_mem(sizeof(tb_fwatcher_event_t), tb_null, tb_null));
tb_assert_and_check_break(poller->waited_events && poller->waited_events_copied);
// start the poller thread for fwatchers first
poller->thread = tb_thread_init(tb_null, tb_poller_fwatcher_loop, poller, 0);
tb_assert_and_check_break(poller->thread);
// ok
ok = tb_true;
} while (0);
// failed? exit the poller
if (!ok)
{
if (poller) tb_poller_fwatcher_exit((tb_poller_fwatcher_ref_t)poller);
poller = tb_null;
}
return (tb_poller_fwatcher_ref_t)poller;
}
static tb_void_t tb_poller_fwatcher_spak(tb_poller_fwatcher_ref_t self)
{
// check
tb_poller_fwatcher_t* poller = (tb_poller_fwatcher_t*)self;
tb_assert_and_check_return(poller && poller->semaphore);
if (poller->fwatcher) tb_fwatcher_spak(poller->fwatcher);
tb_semaphore_post(poller->semaphore, 1);
}
static tb_bool_t tb_poller_fwatcher_insert(tb_poller_fwatcher_ref_t self, tb_fwatcher_ref_t fwatcher, tb_cpointer_t priv)
{
// check
tb_poller_fwatcher_t* poller = (tb_poller_fwatcher_t*)self;
tb_assert_and_check_return_val(poller && poller->semaphore && fwatcher, tb_false);
// attach fwatcher
tb_bool_t ok = tb_false;
tb_bool_t notify = tb_false;
tb_spinlock_enter(&poller->lock);
tb_fwatcher_ref_t fwatcher_old = poller->fwatcher;
if (!poller->fwatcher)
{
poller->fwatcher = fwatcher;
poller->udata = priv;
ok = tb_true;
notify = tb_true;
}
else if (poller->fwatcher == fwatcher)
{
poller->udata = priv;
ok = tb_true;
}
tb_spinlock_leave(&poller->lock);
// notify thread to update fwatcher
if (notify)
{
if (fwatcher_old) tb_fwatcher_spak(fwatcher_old);
tb_semaphore_post(poller->semaphore, 1);
}
// we can insert only one fwatcher
return ok;
}
static tb_bool_t tb_poller_fwatcher_modify(tb_poller_fwatcher_ref_t self, tb_fwatcher_ref_t fwatcher, tb_cpointer_t priv)
{
// check
tb_poller_fwatcher_t* poller = (tb_poller_fwatcher_t*)self;
tb_assert_and_check_return_val(poller && poller->semaphore && fwatcher, tb_false);
// update fwatcher
tb_bool_t notify = tb_false;
tb_spinlock_enter(&poller->lock);
tb_fwatcher_ref_t fwatcher_old = poller->fwatcher;
if (poller->fwatcher != fwatcher)
{
poller->fwatcher = fwatcher;
notify = tb_true;
}
poller->udata = priv;
tb_spinlock_leave(&poller->lock);
// notify thread to update fwatcher
if (notify)
{
if (fwatcher_old) tb_fwatcher_spak(fwatcher_old);
tb_semaphore_post(poller->semaphore, 1);
}
return tb_true;
}
static tb_bool_t tb_poller_fwatcher_remove(tb_poller_fwatcher_ref_t self, tb_fwatcher_ref_t fwatcher)
{
// check
tb_poller_fwatcher_t* poller = (tb_poller_fwatcher_t*)self;
tb_assert_and_check_return_val(poller && poller->semaphore && fwatcher, tb_false);
// remove fwatcher
tb_bool_t ok = tb_false;
tb_bool_t notify = tb_false;
tb_spinlock_enter(&poller->lock);
tb_fwatcher_ref_t fwatcher_old = poller->fwatcher;
if (poller->fwatcher == fwatcher)
{
poller->fwatcher = tb_null;
poller->udata = tb_null;
ok = tb_true;
notify = tb_true;
}
tb_spinlock_leave(&poller->lock);
// notify thread to update fwatcher
if (notify)
{
if (fwatcher_old) tb_fwatcher_spak(fwatcher_old);
tb_semaphore_post(poller->semaphore, 1);
}
return ok;
}
static tb_bool_t tb_poller_fwatcher_wait_prepare(tb_poller_fwatcher_ref_t self)
{
// check
tb_poller_fwatcher_t* poller = (tb_poller_fwatcher_t*)self;
tb_assert_and_check_return_val(poller, tb_false);
// is stopped?
return !tb_atomic32_get(&poller->is_stopped) && poller->fwatcher;
}
static tb_long_t tb_poller_fwatcher_wait_poll(tb_poller_fwatcher_ref_t self, tb_poller_event_func_t func)
{
// check
tb_poller_fwatcher_t* poller = (tb_poller_fwatcher_t*)self;
tb_assert_and_check_return_val(poller && func, -1);
tb_assert_and_check_return_val(poller->waited_events && poller->waited_events_copied, -1);
// get all waited events
tb_vector_clear(poller->waited_events_copied);
tb_spinlock_enter(&poller->lock);
if (tb_vector_size(poller->waited_events))
{
tb_vector_copy(poller->waited_events_copied, poller->waited_events);
tb_vector_clear(poller->waited_events);
}
tb_spinlock_leave(&poller->lock);
// trace
tb_trace_d("fwatcher: poll %lu", tb_vector_size(poller->waited_events_copied));
// poll all waited events
tb_long_t wait = 0;
tb_poller_object_t object;
object.type = TB_POLLER_OBJECT_FWATCHER;
object.ref.fwatcher = poller->fwatcher;
tb_for_all_if (tb_fwatcher_event_t*, event, poller->waited_events_copied, event)
{
func((tb_poller_ref_t)poller->main_poller, &object, (tb_long_t)event, poller->udata);
wait++;
}
// trace
tb_trace_d("fwatcher: poll wait %ld", wait);
return wait;
}
tbox-1.7.6/src/tbox/platform/impl/pollerdata.c 0000664 0000000 0000000 00000010665 14671175054 0021346 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file pollerdata.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "pollerdata.h"
#include "../pipe.h"
#include "../thread_local.h"
#include "../../libc/libc.h"
#ifdef TB_CONFIG_OS_WINDOWS
# include "../windows/windows.h"
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#ifdef __tb_small__
# define TB_POLLERDATA_GROW (64)
#else
# define TB_POLLERDATA_GROW (256)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* declaration
*/
#ifdef TB_CONFIG_OS_WINDOWS
__tb_extern_c_enter__
HANDLE tb_pipe_file_handle(tb_pipe_file_ref_t file);
__tb_extern_c_leave__
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_long_t tb_pollerdata_object2fd(tb_poller_object_ref_t object)
{
// check
tb_assert(object && object->ref.ptr);
// get the fd
tb_long_t fd;
#ifdef TB_CONFIG_OS_WINDOWS
if (object->type == TB_POLLER_OBJECT_PIPE)
fd = (tb_long_t)tb_pipe_file_handle(object->ref.pipe);
else fd = tb_ptr2fd(object->ref.ptr);
#else
fd = tb_ptr2fd(object->ref.ptr);
#endif
tb_assert(fd > 0 && fd < TB_MAXS16);
return fd;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_void_t tb_pollerdata_init(tb_pollerdata_ref_t pollerdata)
{
// check
tb_assert(pollerdata);
// init it
pollerdata->data = tb_null;
pollerdata->maxn = 0;
}
tb_void_t tb_pollerdata_exit(tb_pollerdata_ref_t pollerdata)
{
// check
tb_assert(pollerdata);
// exit poller data
if (pollerdata->data) tb_free(pollerdata->data);
pollerdata->data = tb_null;
pollerdata->maxn = 0;
}
tb_void_t tb_pollerdata_clear(tb_pollerdata_ref_t pollerdata)
{
// check
tb_assert(pollerdata);
// clear data
if (pollerdata->data) tb_memset(pollerdata->data, 0, pollerdata->maxn * sizeof(tb_cpointer_t));
}
tb_cpointer_t tb_pollerdata_get(tb_pollerdata_ref_t pollerdata, tb_poller_object_ref_t object)
{
// check
tb_assert(pollerdata);
// get the poller private data
tb_long_t fd = tb_pollerdata_object2fd(object);
return (pollerdata->data && fd < pollerdata->maxn)? pollerdata->data[fd] : tb_null;
}
tb_void_t tb_pollerdata_set(tb_pollerdata_ref_t pollerdata, tb_poller_object_ref_t object, tb_cpointer_t priv)
{
// check
tb_assert(pollerdata && object);
// get fd
tb_long_t fd = tb_pollerdata_object2fd(object);
// no data? init it first
tb_size_t need = fd + 1;
if (!pollerdata->data)
{
// init data
need += TB_POLLERDATA_GROW;
pollerdata->data = tb_nalloc0_type(need, tb_cpointer_t);
tb_assert_and_check_return(pollerdata->data);
// init data size
pollerdata->maxn = need;
}
else if (need > pollerdata->maxn)
{
// grow data
need += TB_POLLERDATA_GROW;
pollerdata->data = (tb_cpointer_t*)tb_ralloc(pollerdata->data, need * sizeof(tb_cpointer_t));
tb_assert_and_check_return(pollerdata->data);
// init growed space
tb_memset(pollerdata->data + pollerdata->maxn, 0, (need - pollerdata->maxn) * sizeof(tb_cpointer_t));
// grow data size
pollerdata->maxn = need;
}
// save the poller private data
pollerdata->data[fd] = priv;
}
tb_void_t tb_pollerdata_reset(tb_pollerdata_ref_t pollerdata, tb_poller_object_ref_t object)
{
// check
tb_assert(pollerdata && object);
// get fd
tb_long_t fd = tb_pollerdata_object2fd(object);
// remove the poller private data
if (fd < pollerdata->maxn) pollerdata->data[fd] = tb_null;
}
tbox-1.7.6/src/tbox/platform/impl/pollerdata.h 0000664 0000000 0000000 00000006134 14671175054 0021347 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file pollerdata.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_IMPL_POLLERDATA_H
#define TB_PLATFORM_IMPL_POLLERDATA_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "poller.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// fd to pointer
#define tb_fd2ptr(fd) ((fd) >= 0? (tb_pointer_t)((tb_long_t)(fd) + 1) : tb_null)
// pointer to fd
#define tb_ptr2fd(ptr) (tb_int_t)((ptr)? (((tb_long_t)(ptr)) - 1) : -1)
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the poller data type
typedef struct __tb_pollerdata_t
{
// the poller data (fd => priv)
tb_cpointer_t* data;
// the poller data maximum count
tb_size_t maxn;
}tb_pollerdata_t, *tb_pollerdata_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* init poller data
*
* @param pollerdata the pollerdata
*/
tb_void_t tb_pollerdata_init(tb_pollerdata_ref_t pollerdata);
/* exit poller data
*
* @param pollerdata the pollerdata
*/
tb_void_t tb_pollerdata_exit(tb_pollerdata_ref_t pollerdata);
/* clear poller data
*
* @param pollerdata the pollerdata
*/
tb_void_t tb_pollerdata_clear(tb_pollerdata_ref_t pollerdata);
/* set poller data
*
* @param pollerdata the pollerdata
* @param object the poller object
* @param priv the poller private data
*/
tb_void_t tb_pollerdata_set(tb_pollerdata_ref_t pollerdata, tb_poller_object_ref_t object, tb_cpointer_t priv);
/* get poller data
*
* @param pollerdata the pollerdata
* @param object the poller object
*
* @return the poller private data
*/
tb_cpointer_t tb_pollerdata_get(tb_pollerdata_ref_t pollerdata, tb_poller_object_ref_t object);
/* reset poller data
*
* @param pollerdata the pollerdata
* @param object the poller object
*/
tb_void_t tb_pollerdata_reset(tb_pollerdata_ref_t pollerdata, tb_poller_object_ref_t object);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/impl/prefix.h 0000664 0000000 0000000 00000001614 14671175054 0020513 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_PLATFORM_IMPL_PREFIX_H
#define TB_PLATFORM_IMPL_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/platform/impl/socket.h 0000664 0000000 0000000 00000002603 14671175054 0020505 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file socket.h
*
*/
#ifndef TB_PLATFORM_IMPL_SOCKET_H
#define TB_PLATFORM_IMPL_SOCKET_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
// init socket environment
tb_bool_t tb_socket_init_env(tb_noarg_t);
// exit socket environment
tb_void_t tb_socket_exit_env(tb_noarg_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/impl/thread_local.h 0000664 0000000 0000000 00000003340 14671175054 0021635 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file thread_local.h
*
*/
#ifndef TB_PLATFORM_IMPL_THREAD_LOCAL_H
#define TB_PLATFORM_IMPL_THREAD_LOCAL_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../../algorithm/algorithm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/* init the thread local environment
*
* @return tb_true or tb_false
*/
tb_bool_t tb_thread_local_init_env(tb_noarg_t);
// exit the thread local environment
tb_void_t tb_thread_local_exit_env(tb_noarg_t);
/* walk all thread locals
*
* @param func the walk function
* @param priv the user private data
*/
tb_void_t tb_thread_local_walk(tb_walk_func_t func, tb_cpointer_t priv);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/libc/ 0000775 0000000 0000000 00000000000 14671175054 0017013 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/platform/libc/atomic.h 0000664 0000000 0000000 00000006053 14671175054 0020444 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file atomic.h
*
*/
#ifndef TB_PLATFORM_COMPILER_LIBC_ATOMIC_H
#define TB_PLATFORM_COMPILER_LIBC_ATOMIC_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define TB_ATOMIC_RELAXED memory_order_relaxed
#define TB_ATOMIC_CONSUME memory_order_consume
#define TB_ATOMIC_ACQUIRE memory_order_acquire
#define TB_ATOMIC_RELEASE memory_order_release
#define TB_ATOMIC_ACQ_REL memory_order_acq_rel
#define TB_ATOMIC_SEQ_CST memory_order_seq_cst
#define tb_memory_barrier() atomic_thread_fence(memory_order_seq_cst)
#define TB_ATOMIC_FLAG_INIT ATOMIC_FLAG_INIT
#define tb_atomic_flag_test_and_set_explicit(a, mo) atomic_flag_test_and_set_explicit(a, mo)
#define tb_atomic_flag_test_and_set(a) atomic_flag_test_and_set(a)
#ifdef atomic_flag_test_explicit
# define tb_atomic_flag_test_explicit(a, mo) atomic_flag_test_explicit(a, mo)
#else
# define tb_atomic_flag_test_explicit(a, mo) tb_atomic_flag_test_explicit_libc(a, mo)
#endif
#define tb_atomic_flag_test(a) tb_atomic_flag_test_explicit(a, memory_order_seq_cst)
#define tb_atomic_flag_test_noatomic(a) tb_atomic_flag_test_noatomic_libc(a)
#define tb_atomic_flag_clear_explicit(a, mo) atomic_flag_clear_explicit(a, mo)
#define tb_atomic_flag_clear(a) atomic_flag_clear(a)
/* //////////////////////////////////////////////////////////////////////////////////////
* inline implementation
*/
static __tb_inline__ tb_bool_t tb_atomic_flag_test_explicit_libc(tb_atomic_flag_t* a, tb_int_t mo)
{
tb_assert(a);
tb_assert_static(sizeof(tb_atomic_flag_t) == sizeof(unsigned char));
return (tb_bool_t)atomic_load_explicit((__tb_volatile__ _Atomic unsigned char*)a, mo);
}
static __tb_inline__ tb_bool_t tb_atomic_flag_test_noatomic_libc(tb_atomic_flag_t* a)
{
tb_assert(a);
tb_assert_static(sizeof(tb_atomic_flag_t) == sizeof(unsigned char));
return (tb_bool_t)*((__tb_volatile__ unsigned char*)a);
}
#endif
tbox-1.7.6/src/tbox/platform/libc/atomic32.h 0000664 0000000 0000000 00000005735 14671175054 0020617 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file atomic32.h
*
*/
#ifndef TB_PLATFORM_COMPILER_LIBC_ATOMIC32_H
#define TB_PLATFORM_COMPILER_LIBC_ATOMIC32_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define tb_atomic32_init(a, v) atomic_init(a, v)
#define tb_atomic32_get(a) atomic_load(a)
#define tb_atomic32_get_explicit(a, mo) atomic_load_explicit(a, mo)
#define tb_atomic32_set(a, v) atomic_store(a, v)
#define tb_atomic32_set_explicit(a, v, mo) atomic_store_explicit(a, v, mo)
#define tb_atomic32_compare_and_swap(a, p, v) atomic_compare_exchange_strong(a, p, v)
#define tb_atomic32_compare_and_swap_explicit(a, p, v, succ, fail) \
atomic_compare_exchange_strong_explicit(a, p, v, succ, fail)
#define tb_atomic32_compare_and_swap_weak(a, p, v) atomic_compare_exchange_weak(a, p, v)
#define tb_atomic32_compare_and_swap_weak_explicit(a, p, v, succ, fail) \
atomic_compare_exchange_weak_explicit(a, p, v, succ, fail)
#define tb_atomic32_fetch_and_set(a, v) atomic_exchange(a, v)
#define tb_atomic32_fetch_and_set_explicit(a, v, mo) atomic_exchange_explicit(a, v, mo)
#define tb_atomic32_fetch_and_add(a, v) atomic_fetch_add(a, v)
#define tb_atomic32_fetch_and_add_explicit(a, v, mo) atomic_fetch_add_explicit(a, v, mo)
#define tb_atomic32_fetch_and_sub(a, v) atomic_fetch_sub(a, v)
#define tb_atomic32_fetch_and_sub_explicit(a, v, mo) atomic_fetch_sub_explicit(a, v, mo)
#define tb_atomic32_fetch_and_or(a, v) atomic_fetch_or(a, v)
#define tb_atomic32_fetch_and_or_explicit(a, v, mo) atomic_fetch_or_explicit(a, v, mo)
#define tb_atomic32_fetch_and_and(a, v) atomic_fetch_and(a, v)
#define tb_atomic32_fetch_and_and_explicit(a, v, mo) atomic_fetch_and_explicit(a, v, mo)
#define tb_atomic32_fetch_and_xor(a, v) atomic_fetch_xor(a, v)
#define tb_atomic32_fetch_and_xor_explicit(a, v, mo) atomic_fetch_xor_explicit(a, v, mo)
#endif
tbox-1.7.6/src/tbox/platform/libc/atomic64.h 0000664 0000000 0000000 00000005662 14671175054 0020623 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file atomic64.h
*
*/
#ifndef TB_PLATFORM_COMPILER_LIBC_ATOMIC64_H
#define TB_PLATFORM_COMPILER_LIBC_ATOMIC64_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define tb_atomic64_init(a, v) atomic_init(a, v)
#define tb_atomic64_get(a) atomic_load(a)
#define tb_atomic64_get_explicit(a, mo) atomic_load_explicit(a, mo)
#define tb_atomic64_set(a, v) atomic_store(a, v)
#define tb_atomic64_set_explicit(a, v, mo) atomic_store_explicit(a, v, mo)
#define tb_atomic64_compare_and_swap(a, p, v) atomic_compare_exchange_strong(a, p, v)
#define tb_atomic64_compare_and_swap_explicit(a, p, v, succ, fail) \
atomic_compare_exchange_strong_explicit(a, p, v, succ, fail)
#define tb_atomic64_compare_and_swap_weak(a, p, v) atomic_compare_exchange_weak(a, p, v)
#define tb_atomic64_compare_and_swap_weak_explicit(a, p, v, succ, fail) \
atomic_compare_exchange_weak_explicit(a, p, v, succ, fail)
#define tb_atomic64_fetch_and_set(a, v) atomic_exchange(a, v)
#define tb_atomic64_fetch_and_set_explicit(a, v, mo) atomic_exchange_explicit(a, v, mo)
#define tb_atomic64_fetch_and_add(a, v) atomic_fetch_add(a, v)
#define tb_atomic64_fetch_and_add_explicit(a, v, mo) atomic_fetch_add_explicit(a, v, mo)
#define tb_atomic64_fetch_and_sub(a, v) atomic_fetch_sub(a, v)
#define tb_atomic64_fetch_and_sub_explicit(a, v, mo) atomic_fetch_sub_explicit(a, v, mo)
#define tb_atomic64_fetch_and_or(a, v) atomic_fetch_or(a, v)
#define tb_atomic64_fetch_and_or_explicit(a, v, mo) atomic_fetch_or_explicit(a, v, mo)
#define tb_atomic64_fetch_and_and(a, v) atomic_fetch_and(a, v)
#define tb_atomic64_fetch_and_and_explicit(a, v, mo) atomic_fetch_and_explicit(a, v, mo)
#define tb_atomic64_fetch_and_xor(a, v) atomic_fetch_xor(a, v)
#define tb_atomic64_fetch_and_xor_explicit(a, v, mo) atomic_fetch_xor_explicit(a, v, mo)
#endif
tbox-1.7.6/src/tbox/platform/libc/backtrace.c 0000664 0000000 0000000 00000014571 14671175054 0021106 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file backtrace.c
* @ingroup platform
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include
#include
#include
#include "../arch/frame.h"
#include "../../libc/libc.h"
#if defined(TB_CONFIG_LIBC_HAVE_BACKTRACE)
# include
#elif 0/*defined(TB_FIRST_FRAME_POINTER) \
&& defined(TB_CURRENT_STACK_FRAME) \
&& defined(TB_ADVANCE_STACK_FRAME) \
&& defined(TB_STACK_INNER_THAN)
# include */
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* backtrace implementation
*/
#if defined(TB_CONFIG_LIBC_HAVE_BACKTRACE)
tb_size_t tb_backtrace_frames(tb_pointer_t* frames, tb_size_t nframe, tb_size_t nskip)
{
// note: cannot use assert
tb_check_return_val(frames && nframe, 0);
// skip some frames?
if (nskip)
{
// init temp frames
tb_pointer_t temp[256] = {0};
tb_check_return_val(nframe + nskip < 256, 0);
// done backtrace
tb_size_t size = backtrace(temp, nframe + nskip);
tb_check_return_val(nskip < size, 0);
// update nframe
nframe = tb_min(nframe, size - nskip);
// save to frames
tb_memcpy_(frames, temp + nskip, nframe * sizeof(tb_pointer_t));
}
// backtrace
else nframe = backtrace(frames, nframe);
// ok?
return nframe;
}
// FIXME
#elif 0/*defined(TB_FIRST_FRAME_POINTER) \
&& defined(TB_CURRENT_STACK_FRAME) \
&& defined(TB_ADVANCE_STACK_FRAME) \
&& defined(TB_STACK_INNER_THAN) */
//extern tb_pointer_t __libc_stack_end;
tb_size_t tb_backtrace_frames(tb_pointer_t* frames, tb_size_t nframe, tb_size_t nskip)
{
// the libc stack end pointer
tb_pointer_t* __plibc_stack_end = dlsym(tb_null, "__libc_stack_end");
tb_pointer_t __libc_stack_end = __plibc_stack_end? *__plibc_stack_end : tb_null;
// trace
// tb_trace_d("__libc_stack_end: %p", __libc_stack_end);
// the top frame and stack address
tb_pointer_t top_frame = TB_FIRST_FRAME_POINTER;
tb_pointer_t top_stack = TB_CURRENT_STACK_FRAME;
// trace
// tb_trace_d("top_frame: %p", top_frame);
// tb_trace_d("top_stack: %p", top_stack);
// the current frame
tb_frame_layout_t* current = ((tb_frame_layout_t*)top_frame);
// the top frame not contain this func, nskip--
if (nskip) nskip--;
// walk frames
tb_size_t n = 0;
tb_size_t m = __libc_stack_end? 100 : 16;
while (n < nframe && m--)
{
// trace
// tb_trace_d("current: %p", current);
// out of range?
if ( (tb_pointer_t)current TB_STACK_INNER_THAN top_stack
|| (__libc_stack_end && !((tb_pointer_t)current TB_STACK_INNER_THAN __libc_stack_end)))
{
break;
}
#if 1
// save the return address
if (!nskip) frames[n++] = current->return_address;
// skip this frame
else nskip--;
#else
frames[n++] = current->return_address;
#endif
// the next frame address
current = TB_ADVANCE_STACK_FRAME(current->next);
}
// ok?
return n;
}
#else
tb_size_t tb_backtrace_frames(tb_pointer_t* frames, tb_size_t nframe, tb_size_t nskip)
{
tb_trace_noimpl();
return 0;
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* symbols implementation
*/
#if defined(TB_CONFIG_LIBC_HAVE_BACKTRACE)
tb_handle_t tb_backtrace_symbols_init(tb_pointer_t* frames, tb_size_t nframe)
{
tb_check_return_val(frames && nframe, tb_null);
return (tb_handle_t)backtrace_symbols(frames, nframe);
}
tb_char_t const* tb_backtrace_symbols_name(tb_handle_t symbols, tb_pointer_t* frames, tb_size_t nframe, tb_size_t iframe)
{
tb_check_return_val(symbols && frames && nframe && iframe < nframe, tb_null);
return ((tb_char_t const**)symbols)[iframe];
}
tb_void_t tb_backtrace_symbols_exit(tb_handle_t symbols)
{
if (symbols) free(symbols);
}
#elif 0
tb_handle_t tb_backtrace_symbols_init(tb_pointer_t* frames, tb_size_t nframe)
{
// check
tb_check_return_val(frames && nframe, tb_null);
// init symbols
return malloc(8192);
}
tb_char_t const* tb_backtrace_symbols_name(tb_handle_t symbols, tb_pointer_t* frames, tb_size_t nframe, tb_size_t iframe)
{
// check
tb_check_return_val(symbols && frames && nframe && iframe < nframe, tb_null);
// the frame address
tb_pointer_t frame = frames[iframe];
tb_check_return_val(frame, tb_null);
// the frame dlinfo
Dl_info dlinfo = {0};
if (!dladdr(frame, &dlinfo)) return tb_null;
// format
tb_long_t size = 0;
tb_size_t maxn = 8192;
if (dlinfo.dli_fname) size = tb_snprintf((tb_char_t*)symbols, maxn, "%s(", dlinfo.dli_fname);
if (dlinfo.dli_sname && size >= 0) size += tb_snprintf((tb_char_t*)symbols + size, maxn - size, "%s", dlinfo.dli_sname);
if (dlinfo.dli_sname && frame >= dlinfo.dli_saddr && size >= 0) size += tb_snprintf((tb_char_t*)symbols + size, maxn - size, "+%#lx", (tb_size_t)(frame - dlinfo.dli_saddr));
if (size >= 0) size += tb_snprintf((tb_char_t*)symbols + size, maxn - size, ") [%p]", frame);
if (size >= 0) ((tb_char_t*)symbols)[size] = '\0';
// ok
return symbols;
}
tb_void_t tb_backtrace_symbols_exit(tb_handle_t symbols)
{
// exit symbols
if (symbols) free(symbols);
}
#else
tb_handle_t tb_backtrace_symbols_init(tb_pointer_t* frames, tb_size_t nframe)
{
tb_trace_noimpl();
return tb_null;
}
tb_char_t const* tb_backtrace_symbols_name(tb_handle_t symbols, tb_pointer_t* frames, tb_size_t nframe, tb_size_t iframe)
{
tb_trace_noimpl();
return tb_null;
}
tb_void_t tb_backtrace_symbols_exit(tb_handle_t symbols)
{
tb_trace_noimpl();
}
#endif
tbox-1.7.6/src/tbox/platform/libc/environment.c 0000664 0000000 0000000 00000010054 14671175054 0021523 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file environment.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../../libc/libc.h"
#include "../../string/string.h"
#include "../../algorithm/algorithm.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_environment_load(tb_environment_ref_t environment, tb_char_t const* name)
{
// check
tb_assert_and_check_return_val(environment && name, 0);
// clear environment first
tb_vector_clear(environment);
// get values
tb_char_t const* values = getenv(name);
tb_check_return_val(values, 0);
// init value string
tb_string_t value;
if (!tb_string_init(&value)) return 0;
// done
tb_char_t const* p = values;
tb_char_t c = '\0';
while (1)
{
// the character
c = *p++;
// make value
if (c != ':' && c) tb_string_chrcat(&value, c);
else
{
// save value to environment
if (tb_string_size(&value))
tb_vector_insert_tail(environment, tb_string_cstr(&value));
// clear value
tb_string_clear(&value);
// end?
tb_check_break(c);
}
}
// exit value string
tb_string_exit(&value);
// ok?
return tb_vector_size(environment);
}
tb_bool_t tb_environment_save(tb_environment_ref_t environment, tb_char_t const* name)
{
// check
tb_assert_and_check_return_val(environment && name, tb_false);
// empty? remove this environment variable
if (!tb_vector_size(environment)) return !unsetenv(name);
// init values string
tb_string_t values;
if (!tb_string_init(&values)) return tb_false;
// make values string
tb_for_all_if (tb_char_t const*, value, environment, value)
{
// the single value cannot exist ':'
tb_assertf(!tb_strchr(value, ':'), "invalid value: %s", value);
// append value
tb_string_cstrcat(&values, value);
tb_string_chrcat(&values, ':');
}
// strip the last ':'
tb_string_strip(&values, tb_string_size(&values) - 1);
// save variable
tb_bool_t ok;
tb_char_t const* value_cstr = tb_string_cstr(&values);
if (value_cstr) ok = !setenv(name, value_cstr, 1);
else ok = !unsetenv(name);
// exit values string
tb_string_exit(&values);
// ok?
return ok;
}
tb_size_t tb_environment_first(tb_char_t const* name, tb_char_t* value, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(name && value && maxn, 0);
// get it
tb_char_t const* data = getenv(name);
tb_check_return_val(data, 0);
// the value size
tb_size_t size = tb_strlen(data);
tb_check_return_val(size, 0);
// the space is not enough
tb_assert_and_check_return_val(size < maxn, 0);
// copy it
tb_strlcpy(value, data, maxn);
value[size] = '\0';
// only get the first one if exists multiple values
tb_char_t* p = tb_strchr(value, ':');
if (p)
{
// strip it
*p = '\0';
// update size
size = p - value;
}
// ok
return size;
}
tb_bool_t tb_environment_remove(tb_char_t const* name)
{
// check
tb_assert_and_check_return_val(name, tb_false);
// remove it
return !unsetenv(name);
}
tbox-1.7.6/src/tbox/platform/libc/exception.c 0000664 0000000 0000000 00000006173 14671175054 0021164 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file exception.c
* @ingroup platform
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "exception.h"
#include "../thread_local.h"
#include
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
tb_thread_local_t g_exception_local = TB_THREAD_LOCAL_INIT;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_void_t tb_exception_stack_exit(tb_cpointer_t priv)
{
if (priv) tb_stack_exit((tb_stack_ref_t)priv);
}
static tb_void_t tb_exception_signal_func(tb_int_t sig)
{
tb_stack_ref_t stack = (tb_stack_ref_t)tb_thread_local_get(&g_exception_local);
if (stack && tb_stack_size(stack))
{
#if defined(TB_CONFIG_LIBC_HAVE_SIGSETJMP)
sigjmp_buf* jmpbuf = (sigjmp_buf*)tb_stack_top(stack);
if (jmpbuf) siglongjmp(*jmpbuf, 1);
#else
jmpbuf* jmpbuf = (jmpbuf*)tb_stack_top(stack);
if (jmpbuf) longjmp(*jmpbuf, 1);
#endif
}
else
{
// trace
tb_trace_e("exception: no handler for signal: %d", sig);
// ignore signal
signal(SIGILL, SIG_DFL);
signal(SIGFPE, SIG_DFL);
signal(SIGBUS, SIG_DFL);
signal(SIGSEGV, SIG_DFL);
signal(SIGABRT, SIG_DFL);
#ifdef TB_CONFIG_LIBC_HAVE_KILL
// kill it
kill(getpid(), sig);
#endif
}
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_exception_init_env()
{
// init the thread local, only once
if (!tb_thread_local_init(&g_exception_local, tb_exception_stack_exit)) return tb_false;
// register signal handler
// signal(SIGINT, tb_exception_signal_func);
signal(SIGILL, tb_exception_signal_func);
signal(SIGFPE, tb_exception_signal_func);
signal(SIGBUS, tb_exception_signal_func);
signal(SIGSEGV, tb_exception_signal_func);
signal(SIGABRT, tb_exception_signal_func);
// signal(SIGTRAP, tb_exception_signal_func);
// ok
return tb_true;
}
tb_void_t tb_exception_exit_env()
{
// unregister signal handler
// signal(SIGINT, SIG_DFL);
signal(SIGILL, SIG_DFL);
signal(SIGFPE, SIG_DFL);
signal(SIGBUS, SIG_DFL);
signal(SIGSEGV, SIG_DFL);
signal(SIGABRT, SIG_DFL);
// signal(SIGTRAP, SIG_DFL);
// exit the thread local
tb_thread_local_exit(&g_exception_local);
}
tbox-1.7.6/src/tbox/platform/libc/exception.h 0000664 0000000 0000000 00000011655 14671175054 0021172 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file exception.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_LIBC_EXCEPTION_H
#define TB_PLATFORM_LIBC_EXCEPTION_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../thread_local.h"
#include "../../container/container.h"
#if defined(TB_CONFIG_LIBC_HAVE_SETJMP) || defined(TB_CONFIG_LIBC_HAVE_SIGSETJMP)
# include
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
extern tb_thread_local_t g_exception_local;
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#if defined(TB_CONFIG_LIBC_HAVE_SIGSETJMP)
// try
# define __tb_try \
do \
{ \
/* init exception stack */ \
tb_stack_ref_t __stack = tb_null; \
if (!(__stack = (tb_stack_ref_t)tb_thread_local_get(&g_exception_local))) \
{ \
tb_stack_ref_t __stack_new = tb_stack_init(16, tb_element_mem(sizeof(sigjmp_buf), tb_null, tb_null)); \
if (__stack_new && tb_thread_local_set(&g_exception_local, __stack_new)) \
__stack = __stack_new; \
else if (__stack_new) \
tb_stack_exit(__stack_new); \
} \
\
/* push jmpbuf */ \
sigjmp_buf* __top = tb_null; \
if (__stack) \
{ \
sigjmp_buf __buf; \
tb_stack_put(__stack, &__buf); \
__top = (sigjmp_buf*)tb_stack_top(__stack); \
} \
\
/* init jmpbuf and save sigmask */ \
__tb_volatile__ tb_int_t __j = __top? sigsetjmp(*__top, 1) : 0; \
/* done try */ \
if (!__j) \
{
// except
# define __tb_except(x) \
} \
\
/* check */ \
tb_assert(x >= 0); \
/* pop the jmpbuf */ \
if (__stack) tb_stack_pop(__stack); \
/* do not this catch? */ \
if (__j && !(x)) \
{ \
/* goto the top exception stack */ \
if (__stack && tb_stack_size(__stack)) \
{ \
sigjmp_buf* jmpbuf = (sigjmp_buf*)tb_stack_top(__stack); \
if (jmpbuf) siglongjmp(*jmpbuf, 1); \
} \
else \
{ \
/* no exception handler */ \
tb_assert_and_check_break(0); \
} \
} \
/* exception been catched? */ \
if (__j)
#elif defined(TB_CONFIG_LIBC_HAVE_SETJMP)
// try
# define __tb_try \
do \
{ \
/* init exception stack */ \
tb_stack_ref_t __stack = tb_null; \
if (!(__stack = (tb_stack_ref_t)tb_thread_local_get(&g_exception_local))) \
{ \
tb_stack_ref_t __stack_new = tb_stack_init(16, tb_element_mem(sizeof(jmpbuf), tb_null, tb_null)); \
if (__stack_new && tb_thread_local_set(&g_exception_local, __stack_new)) \
__stack = __stack_new; \
else if (__stack_new) \
tb_stack_exit(__stack_new); \
} \
\
/* push jmpbuf */ \
jmpbuf* __top = tb_null; \
if (__stack) \
{ \
jmpbuf __buf; \
tb_stack_put(__stack, &__buf); \
__top = (jmpbuf*)tb_stack_top(__stack); \
} \
\
/* init jmpbuf */ \
__tb_volatile__ tb_int_t __j = __top? setjmp(*__top) : 0; \
/* done try */ \
if (!__j) \
{
// except
# define __tb_except(x) \
} \
\
/* check */ \
tb_assert(x >= 0); \
/* pop the jmpbuf */ \
if (__stack) tb_stack_pop(__stack); \
/* do not this catch? */ \
if (__j && !(x)) \
{ \
/* goto the top exception stack */ \
if (__stack && tb_stack_size(__stack)) \
{ \
jmpbuf* jmpbuf = (jmpbuf*)tb_stack_top(__stack); \
if (jmpbuf) longjmp(*jmpbuf, 1); \
} \
else \
{ \
/* no exception handler */ \
tb_assert_and_check_break(0); \
} \
} \
/* exception been catched? */ \
if (__j)
#endif
// end
#define __tb_end \
} while (0);
// leave
#define __tb_leave break
#endif
tbox-1.7.6/src/tbox/platform/libc/native_memory.c 0000664 0000000 0000000 00000004223 14671175054 0022036 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file native_memory.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../native_memory.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_native_memory_init()
{
return tb_true;
}
tb_void_t tb_native_memory_exit()
{
}
tb_pointer_t tb_native_memory_malloc(tb_size_t size)
{
// check
tb_check_return_val(size, tb_null);
// malloc it
return malloc(size);
}
tb_pointer_t tb_native_memory_malloc0(tb_size_t size)
{
// check
tb_check_return_val(size, tb_null);
// malloc0 it
return calloc(1, size);
}
tb_pointer_t tb_native_memory_nalloc(tb_size_t item, tb_size_t size)
{
// check
tb_check_return_val(item && size, tb_null);
// nalloc it
return malloc(item * size);
}
tb_pointer_t tb_native_memory_nalloc0(tb_size_t item, tb_size_t size)
{
// check
tb_check_return_val(item && size, tb_null);
// nalloc0 it
return calloc(item, size);
}
tb_pointer_t tb_native_memory_ralloc(tb_pointer_t data, tb_size_t size)
{
// no size? free it
if (!size)
{
free(data);
return tb_null;
}
// no data? malloc it
else if (!data) return malloc(size);
// realloc it
else return realloc(data, size);
}
tb_bool_t tb_native_memory_free(tb_pointer_t data)
{
// free it
if (data) free(data);
// ok
return tb_true;
}
tbox-1.7.6/src/tbox/platform/libc/prefix.h 0000664 0000000 0000000 00000001614 14671175054 0020463 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
#ifndef TB_PLATFORM_LIBC_PREFIX_H
#define TB_PLATFORM_LIBC_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/platform/libc/print.c 0000664 0000000 0000000 00000002644 14671175054 0020321 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file print.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_void_t tb_print(tb_char_t const* string)
{
// check
tb_check_return(string);
// print to the stdout
fputs(string, stdout);
}
tb_void_t tb_printl(tb_char_t const* string)
{
// check
tb_check_return(string);
// print string to the stdout
fputs(string, stdout);
// print newline to the stdout
fputs(__tb_newline__, stdout);
}
tb_void_t tb_print_sync()
{
// flush the stdout
fflush(stdout);
}
tbox-1.7.6/src/tbox/platform/libc/random.c 0000664 0000000 0000000 00000002127 14671175054 0020441 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file random.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_void_t tb_random_seed(tb_size_t seed)
{
srandom(seed);
}
tb_long_t tb_random_value()
{
return (tb_long_t)random();
}
tbox-1.7.6/src/tbox/platform/libc/stdfile.c 0000664 0000000 0000000 00000016324 14671175054 0020617 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file stdfile.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../stdfile.h"
#include
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the stdfile type
typedef struct __tb_stdfile_t
{
// the file type
tb_size_t type;
// the file pointer
FILE* fp;
}tb_stdfile_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_stdfile_ref_t tb_stdfile_init(tb_size_t type)
{
// check
tb_assert_and_check_return_val(type, tb_null);
// get std pointer
FILE* fp = tb_null;
switch (type)
{
case TB_STDFILE_TYPE_STDIN: fp = stdin; break;
case TB_STDFILE_TYPE_STDOUT: fp = stdout; break;
case TB_STDFILE_TYPE_STDERR: fp = stderr; break;
}
tb_assert_and_check_return_val(fp, tb_null);
// create standard device file
tb_bool_t ok = tb_false;
tb_stdfile_t* file = tb_null;
do
{
// make file
file = tb_malloc0_type(tb_stdfile_t);
tb_assert_and_check_break(file);
// init file
file->fp = fp;
file->type = type;
// ok
ok = tb_true;
} while (0);
// failed? exit file
if (!ok)
{
if (file) tb_stdfile_exit((tb_stdfile_ref_t)file);
file = tb_null;
}
return (tb_stdfile_ref_t)file;
}
tb_void_t tb_stdfile_exit(tb_stdfile_ref_t self)
{
// check
tb_stdfile_t* stdfile = (tb_stdfile_t*)self;
tb_assert_and_check_return(stdfile);
// free it
tb_free(stdfile);
}
tb_size_t tb_stdfile_type(tb_stdfile_ref_t self)
{
// check
tb_stdfile_t* stdfile = (tb_stdfile_t*)self;
tb_assert_and_check_return_val(stdfile, TB_STDFILE_TYPE_NONE);
return stdfile->type;
}
tb_bool_t tb_stdfile_flush(tb_stdfile_ref_t self)
{
// check
tb_stdfile_t* stdfile = (tb_stdfile_t*)self;
tb_assert_and_check_return_val(stdfile && stdfile->fp, tb_false);
tb_assert_and_check_return_val(stdfile->type != TB_STDFILE_TYPE_STDIN, tb_false);
return !fflush(stdfile->fp)? tb_true : tb_false;
}
tb_bool_t tb_stdfile_read(tb_stdfile_ref_t self, tb_byte_t* data, tb_size_t size)
{
// check
tb_stdfile_t* stdfile = (tb_stdfile_t*)self;
tb_assert_and_check_return_val(stdfile && stdfile->fp && data, tb_false);
tb_assert_and_check_return_val(stdfile->type == TB_STDFILE_TYPE_STDIN, tb_false);
// read data from stdin
return fread(data, size, 1, stdfile->fp) == 1;
}
tb_bool_t tb_stdfile_writ(tb_stdfile_ref_t self, tb_byte_t const* data, tb_size_t size)
{
// check
tb_stdfile_t* stdfile = (tb_stdfile_t*)self;
tb_assert_and_check_return_val(stdfile && stdfile->fp && data, tb_false);
tb_assert_and_check_return_val(stdfile->type != TB_STDFILE_TYPE_STDIN, tb_false);
// write data to stdout/stderr
return fwrite(data, size, 1, stdfile->fp) == 1;
}
#if defined(TB_CONFIG_LIBC_HAVE_FGETC) && defined(TB_CONFIG_LIBC_HAVE_UNGETC)
tb_bool_t tb_stdfile_peek(tb_stdfile_ref_t self, tb_char_t* pch)
{
// check
tb_stdfile_t* stdfile = (tb_stdfile_t*)self;
tb_assert_and_check_return_val(stdfile && stdfile->fp && pch, tb_false);
tb_assert_and_check_return_val(stdfile->type == TB_STDFILE_TYPE_STDIN, tb_false);
// read character from stdin
tb_int_t ch = fgetc(stdfile->fp);
tb_check_return_val(ch != EOF, tb_false);
// unread character from stdin
ungetc(ch, stdfile->fp);
// save result
*pch = (tb_char_t)ch;
return tb_true;
}
#else
tb_bool_t tb_stdfile_peek(tb_stdfile_ref_t self, tb_char_t* pch)
{
tb_trace_noimpl();
return tb_false;
}
#endif
#ifdef TB_CONFIG_LIBC_HAVE_FGETC
tb_bool_t tb_stdfile_getc(tb_stdfile_ref_t self, tb_char_t* pch)
{
// check
tb_stdfile_t* stdfile = (tb_stdfile_t*)self;
tb_assert_and_check_return_val(stdfile && stdfile->fp && pch, tb_false);
tb_assert_and_check_return_val(stdfile->type == TB_STDFILE_TYPE_STDIN, tb_false);
// read character from stdin
tb_int_t ch = fgetc(stdfile->fp);
tb_check_return_val(ch != EOF, tb_false);
// save result
*pch = (tb_char_t)ch;
return tb_true;
}
#else
tb_bool_t tb_stdfile_getc(tb_stdfile_ref_t self, tb_char_t* pch)
{
return tb_stdfile_read(self, (tb_byte_t*)pch, 1);
}
#endif
#ifdef TB_CONFIG_LIBC_HAVE_FPUTC
tb_bool_t tb_stdfile_putc(tb_stdfile_ref_t self, tb_char_t ch)
{
// check
tb_stdfile_t* stdfile = (tb_stdfile_t*)self;
tb_assert_and_check_return_val(stdfile && stdfile->fp, tb_false);
tb_assert_and_check_return_val(stdfile->type != TB_STDFILE_TYPE_STDIN, tb_false);
// write character to stdout/stderr
return fputc((tb_int_t)ch, stdfile->fp) == ch;
}
#else
tb_bool_t tb_stdfile_putc(tb_stdfile_ref_t self, tb_char_t ch)
{
return tb_stdfile_writ(self, (tb_byte_t const*)&ch, 1);
}
#endif
#ifdef TB_CONFIG_LIBC_HAVE_FGETS
tb_bool_t tb_stdfile_gets(tb_stdfile_ref_t self, tb_char_t* str, tb_size_t num)
{
// check
tb_stdfile_t* stdfile = (tb_stdfile_t*)self;
tb_assert_and_check_return_val(stdfile && stdfile->fp && str && num, tb_false);
tb_assert_and_check_return_val(stdfile->type == TB_STDFILE_TYPE_STDIN, tb_false);
// read string from stdin
return fgets(str, (tb_int_t)num, stdfile->fp) == str;
}
#else
tb_bool_t tb_stdfile_gets(tb_stdfile_ref_t self, tb_char_t* str, tb_size_t num)
{
// check
tb_assert_and_check_return_val(num && str, tb_false);
tb_size_t i;
tb_char_t ch;
for (i = 0; i < num - 1; i++)
{
if (tb_stdfile_getc(self, &ch))
{
if (ch == '\n')
{
str[i++] = '\n';
break;
}
else str[i] = ch;
}
else return tb_false;
}
if (i < num) str[i] = '\0';
return i < num;
}
#endif
#ifdef TB_CONFIG_LIBC_HAVE_FPUTS
tb_bool_t tb_stdfile_puts(tb_stdfile_ref_t self, tb_char_t const* str)
{
// check
tb_stdfile_t* stdfile = (tb_stdfile_t*)self;
tb_assert_and_check_return_val(stdfile && stdfile->fp && str, tb_false);
tb_assert_and_check_return_val(stdfile->type != TB_STDFILE_TYPE_STDIN, tb_false);
// write string to stdout/stderr
return fputs(str, stdfile->fp) >= 0;
}
#else
tb_bool_t tb_stdfile_puts(tb_stdfile_ref_t self, tb_char_t const* str)
{
// check
tb_assert_and_check_return_val(str, tb_false);
// write string to stdout/stderr
tb_size_t len = tb_strlen(str);
return len? tb_stdfile_writ(self, (tb_byte_t const*)str, tb_strlen(str)) : tb_true;
}
#endif
tbox-1.7.6/src/tbox/platform/libc/syserror.c 0000664 0000000 0000000 00000002420 14671175054 0021045 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file syserror.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_syserror_state()
{
// get last error
switch (errno)
{
case EPERM:
return TB_STATE_SYSERROR_NOT_PERM;
case ENOENT:
return TB_STATE_SYSERROR_NOT_FILEDIR;
case EACCES:
return TB_STATE_SYSERROR_NOT_ACCESS;
default:
return TB_STATE_SYSERROR_UNKNOWN_ERROR;
}
}
tbox-1.7.6/src/tbox/platform/linux/ 0000775 0000000 0000000 00000000000 14671175054 0017241 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/platform/linux/fwatcher_inotify.c 0000664 0000000 0000000 00000031111 14671175054 0022746 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file fwatcher_inotify.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../fwatcher.h"
#include "../socket.h"
#include "../poller.h"
#include "../file.h"
#include "../directory.h"
#include "../../libc/libc.h"
#include "../impl/pollerdata.h"
#include "../../container/container.h"
#include "../../algorithm/algorithm.h"
#include
#include
#include
#include
#include
#if defined(TB_CONFIG_MODULE_HAVE_COROUTINE) \
&& !defined(TB_CONFIG_MICRO_ENABLE)
# include "../../coroutine/coroutine.h"
# include "../../coroutine/impl/impl.h"
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
#define TB_FWATCHER_EVENT_SIZE (sizeof(struct inotify_event))
#ifdef TB_CONFIG_SMALL
# define TB_FWATCHER_BUFFER_SIZE (4096 * (TB_FWATCHER_EVENT_SIZE + 16))
#else
# define TB_FWATCHER_BUFFER_SIZE (8192 * (TB_FWATCHER_EVENT_SIZE + 16))
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the watch item type
typedef struct __tb_fwatcher_item_t
{
tb_int_t wd;
tb_char_t const* watchdir;
tb_bool_t recursion;
}tb_fwatcher_item_t;
// the fwatcher type
typedef struct __tb_fwatcher_t
{
tb_int_t fd;
tb_byte_t buffer[TB_FWATCHER_BUFFER_SIZE];
tb_poller_ref_t poller;
tb_hash_map_ref_t watchitems;
tb_queue_ref_t waited_events;
}tb_fwatcher_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_void_t tb_fwatcher_event(tb_poller_ref_t poller, tb_poller_object_ref_t object, tb_long_t events, tb_cpointer_t priv)
{
// we need only an empty callback
}
static tb_bool_t tb_fwatcher_item_eq(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value)
{
tb_hash_map_item_ref_t hashitem = (tb_hash_map_item_ref_t)item;
tb_fwatcher_item_t* watchitem = (tb_fwatcher_item_t*)hashitem->data;
if (watchitem && watchitem->watchdir && value && !tb_strcmp(watchitem->watchdir, value))
return tb_true;
return tb_false;
}
static tb_void_t tb_fwatcher_item_free(tb_element_ref_t element, tb_pointer_t buff)
{
tb_fwatcher_t* fwatcher = (tb_fwatcher_t*)element->priv;
tb_fwatcher_item_t* watchitem = (tb_fwatcher_item_t*)buff;
tb_assert_and_check_return(fwatcher && watchitem);
if (fwatcher->fd >= 0 && watchitem->wd >= 0)
{
inotify_rm_watch(fwatcher->fd, watchitem->wd);
watchitem->wd = -1;
}
if (watchitem->watchdir) tb_free(watchitem->watchdir);
watchitem->watchdir = tb_null;
}
static tb_bool_t tb_fwatcher_add_watch(tb_fwatcher_t* fwatcher, tb_char_t const* watchdir, tb_bool_t recursion)
{
// check
tb_assert_and_check_return_val(fwatcher && fwatcher->fd >= 0 && fwatcher->watchitems && watchdir, tb_false);
// this directory has been watched?
tb_size_t itor = tb_find_all_if(fwatcher->watchitems, tb_fwatcher_item_eq, watchdir);
if (itor != tb_iterator_tail(fwatcher->watchitems))
return tb_true;
// add watch
tb_int_t wd = inotify_add_watch(fwatcher->fd, watchdir, IN_MODIFY | IN_CREATE | IN_DELETE);
tb_assert_and_check_return_val(wd >= 0, tb_false);
// save wd -> watchitem
tb_fwatcher_item_t watchitem;
watchitem.wd = wd;
watchitem.watchdir = tb_strdup(watchdir);
watchitem.recursion = recursion;
tb_hash_map_insert(fwatcher->watchitems, tb_i2p(wd), &watchitem);
return tb_true;
}
static tb_long_t tb_fwatcher_add_watch_dirs(tb_char_t const* path, tb_file_info_t const* info, tb_cpointer_t priv)
{
// check
tb_fwatcher_t* fwatcher = (tb_fwatcher_t*)priv;
tb_assert_and_check_return_val(path && info && fwatcher, TB_DIRECTORY_WALK_CODE_END);
// add watch directory
if (info->type == TB_FILE_TYPE_DIRECTORY)
tb_fwatcher_add_watch(fwatcher, path, tb_true);
return TB_DIRECTORY_WALK_CODE_CONTINUE;
}
static tb_bool_t tb_fwatcher_rm_watch(tb_fwatcher_t* fwatcher, tb_char_t const* watchdir)
{
// check
tb_assert_and_check_return_val(fwatcher && fwatcher->fd >= 0 && fwatcher->watchitems && watchdir, tb_false);
// remove watchitem
tb_remove_first_if(fwatcher->watchitems, tb_fwatcher_item_eq, watchdir);
return tb_true;
}
static tb_long_t tb_fwatcher_rm_watch_dirs(tb_char_t const* path, tb_file_info_t const* info, tb_cpointer_t priv)
{
// check
tb_value_t* values = (tb_value_t*)priv;
tb_assert_and_check_return_val(path && info && values, TB_DIRECTORY_WALK_CODE_END);
// get fwatcher
tb_fwatcher_t* fwatcher = values[0].ptr;
tb_assert_and_check_return_val(fwatcher, TB_DIRECTORY_WALK_CODE_END);
// rm watch directory
if (info->type == TB_FILE_TYPE_DIRECTORY)
tb_fwatcher_rm_watch(fwatcher, path);
return TB_DIRECTORY_WALK_CODE_CONTINUE;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_fwatcher_ref_t tb_fwatcher_init()
{
tb_bool_t ok = tb_false;
tb_fwatcher_t* fwatcher = tb_null;
do
{
// init fwatcher
fwatcher = tb_malloc0_type(tb_fwatcher_t);
tb_assert_and_check_break(fwatcher);
// init inotify
fwatcher->fd = inotify_init();
tb_assert_and_check_break(fwatcher->fd >= 0);
// init poller
fwatcher->poller = tb_poller_init(tb_null);
tb_assert_and_check_break(fwatcher->poller);
tb_poller_insert_sock(fwatcher->poller, tb_fd2sock(fwatcher->fd), TB_POLLER_EVENT_RECV, tb_null);
// init watchitems
fwatcher->watchitems = tb_hash_map_init(0, tb_element_uint32(), tb_element_mem(sizeof(tb_fwatcher_item_t), tb_fwatcher_item_free, fwatcher));
tb_assert_and_check_break(fwatcher->watchitems);
// init waited events
fwatcher->waited_events = tb_queue_init(0, tb_element_mem(sizeof(tb_fwatcher_event_t), tb_null, tb_null));
tb_assert_and_check_break(fwatcher->waited_events);
ok = tb_true;
} while (0);
if (!ok && fwatcher)
{
tb_fwatcher_exit((tb_fwatcher_ref_t)fwatcher);
fwatcher = tb_null;
}
return (tb_fwatcher_ref_t)fwatcher;
}
tb_void_t tb_fwatcher_exit(tb_fwatcher_ref_t self)
{
tb_fwatcher_t* fwatcher = (tb_fwatcher_t*)self;
if (fwatcher)
{
// exit poller
if (fwatcher->poller)
tb_poller_exit(fwatcher->poller);
// exit watchitems
if (fwatcher->watchitems)
{
tb_hash_map_exit(fwatcher->watchitems);
fwatcher->watchitems = tb_null;
}
// exit fd
if (fwatcher->fd >= 0)
{
close(fwatcher->fd);
fwatcher->fd = -1;
}
// exit waited events
if (fwatcher->waited_events)
{
tb_queue_exit(fwatcher->waited_events);
fwatcher->waited_events = tb_null;
}
// exit watcher
tb_free(fwatcher);
fwatcher = tb_null;
}
}
tb_bool_t tb_fwatcher_add(tb_fwatcher_ref_t self, tb_char_t const* watchdir, tb_bool_t recursion)
{
// check
tb_fwatcher_t* fwatcher = (tb_fwatcher_t*)self;
tb_assert_and_check_return_val(fwatcher && fwatcher->fd >= 0 && fwatcher->watchitems && watchdir, tb_false);
// directory not found
tb_file_info_t info;
if (!tb_file_info(watchdir, &info) || info.type != TB_FILE_TYPE_DIRECTORY)
return tb_false;
// is directory? we need scan it and add all subdirs
if (info.type == TB_FILE_TYPE_DIRECTORY && recursion)
tb_directory_walk(watchdir, 0, tb_true, tb_fwatcher_add_watch_dirs, fwatcher);
return tb_fwatcher_add_watch(fwatcher, watchdir, recursion);
}
tb_bool_t tb_fwatcher_remove(tb_fwatcher_ref_t self, tb_char_t const* watchdir)
{
// check
tb_fwatcher_t* fwatcher = (tb_fwatcher_t*)self;
tb_assert_and_check_return_val(fwatcher && watchdir, tb_false);
// is directory? we need scan it and remove all subdirs
tb_file_info_t info;
if (tb_file_info(watchdir, &info) && info.type == TB_FILE_TYPE_DIRECTORY)
{
tb_value_t values[1];
values[0].ptr = (tb_pointer_t)fwatcher;
tb_directory_walk(watchdir, 0, tb_false, tb_fwatcher_rm_watch_dirs, values);
}
return tb_fwatcher_rm_watch(fwatcher, watchdir);
}
tb_void_t tb_fwatcher_spak(tb_fwatcher_ref_t self)
{
tb_fwatcher_t* fwatcher = (tb_fwatcher_t*)self;
if (fwatcher && fwatcher->poller)
tb_poller_spak(fwatcher->poller);
}
tb_long_t tb_fwatcher_wait(tb_fwatcher_ref_t self, tb_fwatcher_event_t* event, tb_long_t timeout)
{
tb_fwatcher_t* fwatcher = (tb_fwatcher_t*)self;
tb_assert_and_check_return_val(fwatcher && fwatcher->fd >= 0 && fwatcher->waited_events && event, -1);
#if defined(TB_CONFIG_MODULE_HAVE_COROUTINE) \
&& !defined(TB_CONFIG_MICRO_ENABLE)
// attempt to wait it in coroutine if timeout is non-zero
if (timeout && tb_coroutine_self())
{
tb_poller_object_t object;
object.type = TB_POLLER_OBJECT_FWATCHER;
object.ref.fwatcher = self;
return tb_coroutine_waitfs(&object, event, timeout);
}
#endif
// get it if has events
tb_bool_t has_events = tb_false;
if (!tb_queue_null(fwatcher->waited_events))
{
tb_fwatcher_event_t* e = (tb_fwatcher_event_t*)tb_queue_get(fwatcher->waited_events);
if (e)
{
*event = *e;
tb_queue_pop(fwatcher->waited_events);
has_events = tb_true;
}
}
tb_check_return_val(!has_events, 1);
// wait events
tb_long_t wait = tb_poller_wait(fwatcher->poller, tb_fwatcher_event, timeout);
tb_assert_and_check_return_val(wait >= 0, -1);
tb_check_return_val(wait > 0, 0);
tb_int_t real = read(fwatcher->fd, fwatcher->buffer, sizeof(fwatcher->buffer));
tb_check_return_val(real >= 0, -1);
tb_int_t i = 0;
while (i < real)
{
struct inotify_event* ievent = (struct inotify_event*)&fwatcher->buffer[i];
i += TB_FWATCHER_EVENT_SIZE + ievent->len;
// get event code
tb_size_t event_code = 0;
if (ievent->mask & IN_CREATE)
event_code = TB_FWATCHER_EVENT_CREATE;
else if (ievent->mask & IN_DELETE)
event_code = TB_FWATCHER_EVENT_DELETE;
else if (ievent->mask & IN_MODIFY)
event_code = TB_FWATCHER_EVENT_MODIFY;
// get watchitem
tb_fwatcher_item_t* watchitem = (tb_fwatcher_item_t*)tb_hash_map_get(fwatcher->watchitems, tb_i2p(ievent->wd));
tb_check_continue(watchitem);
tb_assert_and_check_break(watchitem->watchdir);
// add event
if (event_code)
{
tb_fwatcher_event_t evt;
if (ievent->len)
tb_snprintf(evt.filepath, TB_PATH_MAXN, "%s/%s", watchitem->watchdir, ievent->name);
else tb_strlcpy(evt.filepath, watchitem->watchdir, TB_PATH_MAXN);
evt.event = event_code;
tb_queue_put(fwatcher->waited_events, &evt);
// rescan the watch directory
tb_file_info_t info;
if (watchitem->recursion &&
tb_file_info(evt.filepath, &info) && info.type == TB_FILE_TYPE_DIRECTORY)
{
if (event_code == TB_FWATCHER_EVENT_MODIFY ||
event_code == TB_FWATCHER_EVENT_CREATE)
tb_fwatcher_add(self, evt.filepath, watchitem->recursion);
else if (event_code == TB_FWATCHER_EVENT_DELETE)
tb_fwatcher_remove(self, evt.filepath);
}
}
}
// get event
if (!tb_queue_null(fwatcher->waited_events))
{
tb_fwatcher_event_t* e = (tb_fwatcher_event_t*)tb_queue_get(fwatcher->waited_events);
if (e)
{
*event = *e;
tb_queue_pop(fwatcher->waited_events);
has_events = tb_true;
}
}
return has_events? 1 : 0;
}
tbox-1.7.6/src/tbox/platform/linux/ifaddrs.c 0000664 0000000 0000000 00000021223 14671175054 0021021 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file ifaddrs.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include "../posix/sockaddr.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_void_t tb_ifaddrs_interface_exit(tb_element_ref_t element, tb_pointer_t buff)
{
// check
tb_ifaddrs_interface_ref_t interface = (tb_ifaddrs_interface_ref_t)buff;
if (interface)
{
// exit the interface name
if (interface->name) tb_free(interface->name);
interface->name = tb_null;
}
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_ifaddrs_ref_t tb_ifaddrs_init()
{
// init it
return (tb_ifaddrs_ref_t)tb_list_init(8, tb_element_mem(sizeof(tb_ifaddrs_interface_t), tb_ifaddrs_interface_exit, tb_null));
}
tb_void_t tb_ifaddrs_exit(tb_ifaddrs_ref_t ifaddrs)
{
// exit it
if (ifaddrs) tb_list_exit((tb_list_ref_t)ifaddrs);
}
tb_iterator_ref_t tb_ifaddrs_itor(tb_ifaddrs_ref_t ifaddrs, tb_bool_t reload)
{
// check
tb_list_ref_t interfaces = (tb_list_ref_t)ifaddrs;
tb_assert_and_check_return_val(interfaces, tb_null);
// uses the cached interfaces?
tb_check_return_val(reload, (tb_iterator_ref_t)interfaces);
// clear interfaces first
tb_list_clear(interfaces);
// query the list of interfaces.
struct ifaddrs* list = tb_null;
if (!getifaddrs(&list) && list)
{
#if 0
// init sock
tb_long_t sock = socket(AF_INET, SOCK_DGRAM, 0);
#endif
// done
struct ifaddrs* item = tb_null;
for (item = list; item; item = item->ifa_next)
{
// check
tb_check_continue(item->ifa_addr && item->ifa_name);
/* attempt to get the interface from the cached interfaces
* and make a new interface if no the cached interface
*/
tb_ifaddrs_interface_t interface_new = {0};
tb_ifaddrs_interface_ref_t interface = tb_ifaddrs_interface_find((tb_iterator_ref_t)interfaces, item->ifa_name);
if (!interface) interface = &interface_new;
// check
tb_assert(interface == &interface_new || interface->name);
// done
switch (item->ifa_addr->sa_family)
{
case AF_INET:
{
// the address
struct sockaddr_storage const* addr = (struct sockaddr_storage const*)item->ifa_addr;
// save ipaddr4
tb_ipaddr_t ipaddr4;
if (!tb_sockaddr_save(&ipaddr4, addr)) break;
interface->ipaddr4 = ipaddr4.u.ipv4;
// save flags
interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR4;
if ((item->ifa_flags & IFF_LOOPBACK) || tb_ipaddr_ip_is_loopback(&ipaddr4))
interface->flags |= TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK;
#if 0
// no hwaddr? get it
if (!(interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR))
{
// attempt get the hwaddr
struct ifreq ifr;
tb_memset(&ifr, 0, sizeof(ifr));
tb_strcpy(ifr.ifr_name, item->ifa_name);
if (!ioctl(sock, SIOCGIFHWADDR, &ifr))
{
// have hwaddr
interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR;
// save hwaddr
tb_memcpy(interface->hwaddr.u8, ifr.ifr_hwaddr.sa_data, sizeof(interface->hwaddr.u8));
}
}
#endif
// new interface? save it
if (interface == &interface_new)
{
// save interface name
interface->name = tb_strdup(item->ifa_name);
tb_assert(interface->name);
// save interface
tb_list_insert_tail(interfaces, interface);
}
}
break;
case AF_INET6:
{
// the address
struct sockaddr_storage const* addr = (struct sockaddr_storage const*)item->ifa_addr;
// save ipaddr6
tb_ipaddr_t ipaddr6;
if (!tb_sockaddr_save(&ipaddr6, addr)) break;
interface->ipaddr6 = ipaddr6.u.ipv6;
// save flags
interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR6;
if ((item->ifa_flags & IFF_LOOPBACK) || tb_ipaddr_ip_is_loopback(&ipaddr6))
interface->flags |= TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK;
#if 0
// no hwaddr? get it
if (!(interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR))
{
// attempt get the hwaddr
struct ifreq ifr;
tb_memset(&ifr, 0, sizeof(ifr));
tb_strcpy(ifr.ifr_name, item->ifa_name);
if (!ioctl(sock, SIOCGIFHWADDR, &ifr))
{
// have hwaddr
interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR;
// save hwaddr
tb_memcpy(interface->hwaddr.u8, ifr.ifr_hwaddr.sa_data, sizeof(interface->hwaddr.u8));
}
}
#endif
// new interface? save it
if (interface == &interface_new)
{
// save interface name
interface->name = tb_strdup(item->ifa_name);
tb_assert(interface->name);
// save interface
tb_list_insert_tail(interfaces, interface);
}
}
break;
case AF_PACKET:
{
// the address
struct sockaddr_ll const* addr = (struct sockaddr_ll const*)item->ifa_addr;
// check
tb_check_break(addr->sll_halen == sizeof(interface->hwaddr.u8));
// no hwaddr? get it
if (!(interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR))
{
// have hwaddr
interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR;
// save hwaddr
tb_memcpy(interface->hwaddr.u8, addr->sll_addr, sizeof(interface->hwaddr.u8));
// new interface? save it
if (interface == &interface_new)
{
// save interface name
interface->name = tb_strdup(item->ifa_name);
tb_assert(interface->name);
// save interface
tb_list_insert_tail(interfaces, interface);
}
}
}
break;
default:
{
// trace
tb_trace_d("unknown family: %d", item->ifa_addr->sa_family);
}
break;
}
}
#if 0
// exit socket
if (sock) close(sock);
sock = 0;
#endif
// exit the interface list
freeifaddrs(list);
}
// ok?
return (tb_iterator_ref_t)interfaces;
}
tbox-1.7.6/src/tbox/platform/linux/ifaddrs2.c 0000664 0000000 0000000 00000045564 14671175054 0021121 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file ifaddrs.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "../posix/sockaddr.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_long_t tb_ifaddrs_netlink_socket_init()
{
// done
tb_long_t sock = -1;
tb_bool_t ok = tb_false;
do
{
// make socket
sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
tb_check_break(sock >= 0);
// bind socket
struct sockaddr_nl addr;
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) break;
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (sock >= 0) close(sock);
sock = -1;
}
// ok?
return sock;
}
static tb_long_t tb_ifaddrs_netlink_socket_send(tb_long_t sock, tb_long_t request)
{
// check
tb_assert_and_check_return_val(sock >= 0, -1);
// init packet
struct
{
struct nlmsghdr m_hdr;
struct rtgenmsg m_msg;
} packet;
tb_memset(&packet, 0, sizeof(packet));
packet.m_hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
packet.m_hdr.nlmsg_type = (tb_int_t)request;
packet.m_hdr.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
packet.m_hdr.nlmsg_pid = 0;
packet.m_hdr.nlmsg_seq = (tb_int_t)sock;
packet.m_msg.rtgen_family = AF_UNSPEC;
// send packet
struct sockaddr_nl addr;
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
return sendto(sock, &packet.m_hdr, packet.m_hdr.nlmsg_len, 0, (struct sockaddr *)&addr, sizeof(addr));
}
static tb_long_t tb_ifaddrs_netlink_socket_recv(tb_long_t sock, tb_pointer_t data, tb_size_t size)
{
// check
tb_assert_and_check_return_val(sock >= 0 && data && size, -1);
// done
struct msghdr packet;
struct iovec iov = { data, size };
struct sockaddr_nl addr;
while (1)
{
// init packet
packet.msg_name = (tb_pointer_t)&addr;
packet.msg_namelen = sizeof(addr);
packet.msg_iov = &iov;
packet.msg_iovlen = 1;
packet.msg_control = tb_null;
packet.msg_controllen = 0;
packet.msg_flags = 0;
// recv packet
tb_long_t ok = recvmsg(sock, &packet, 0);
// failed or continue
if (ok < 0)
{
if (errno == EINTR) continue;
return -2;
}
// buffer was too small
if (packet.msg_flags & MSG_TRUNC) return -1;
// ok
return ok;
}
}
static tb_size_t tb_ifaddrs_netlink_ipaddr_save(tb_ipaddr_ref_t ipaddr, tb_size_t family, tb_size_t scope_id, tb_cpointer_t saddr)
{
// check
tb_assert_and_check_return_val(ipaddr && saddr, 0);
// clear address
tb_ipaddr_clear(ipaddr);
// done
tb_size_t size = 0;
switch (family)
{
case AF_INET:
{
// the ipv4 ipaddr
struct in_addr* addr4 = (struct in_addr*)saddr;
// save family
tb_ipaddr_family_set(ipaddr, TB_IPADDR_FAMILY_IPV4);
// make ipv4
tb_ipv4_t ipv4;
ipv4.u32 = (tb_uint32_t)addr4->s_addr;
// save ipv4
tb_ipaddr_ipv4_set(ipaddr, &ipv4);
// save size
size = sizeof(struct in_addr);
}
break;
case AF_INET6:
{
// the ipv6 ipaddr
struct in6_addr* addr6 = (struct in6_addr*)saddr;
// check
tb_assert_static(sizeof(ipaddr->u.ipv6.addr.u8) == sizeof(addr6->s6_addr));
tb_assert_static(tb_arrayn(ipaddr->u.ipv6.addr.u8) == tb_arrayn(addr6->s6_addr));
// save family
tb_ipaddr_family_set(ipaddr, TB_IPADDR_FAMILY_IPV6);
// make ipv6
tb_ipv6_t ipv6;
tb_memcpy(ipv6.addr.u8, addr6->s6_addr, sizeof(ipv6.addr.u8));
// save scope id
ipv6.scope_id = 0;
if (IN6_IS_ADDR_LINKLOCAL(addr6) || IN6_IS_ADDR_MC_LINKLOCAL(addr6))
ipv6.scope_id = (tb_uint32_t)scope_id;
// save ipv6
tb_ipaddr_ipv6_set(ipaddr, &ipv6);
// save size
size = sizeof(struct in6_addr);
}
break;
default:
tb_assert(0);
break;
}
// ok?
return size;
}
static tb_void_t tb_ifaddrs_interface_exit(tb_element_ref_t element, tb_pointer_t buff)
{
// check
tb_ifaddrs_interface_ref_t interface = (tb_ifaddrs_interface_ref_t)buff;
if (interface)
{
// exit the interface name
if (interface->name) tb_free(interface->name);
interface->name = tb_null;
}
}
static tb_void_t tb_ifaddrs_interface_done_ipaddr(tb_list_ref_t interfaces, tb_hash_map_ref_t names, struct nlmsghdr* response)
{
// check
tb_assert_and_check_return(interfaces && names && response);
// the info
struct ifaddrmsg* info = (struct ifaddrmsg *)NLMSG_DATA(response);
// must be not link
tb_assert_and_check_return(info->ifa_family != AF_PACKET);
// attempt to find the interface name
tb_bool_t owner = tb_false;
tb_char_t* name = (tb_char_t*)tb_hash_map_get(names, tb_u2p(info->ifa_index));
if (!name)
{
// get the interface name
struct rtattr* rta = tb_null;
tb_size_t rta_size = NLMSG_PAYLOAD(response, sizeof(struct ifaddrmsg));
for(rta = IFA_RTA(info); RTA_OK(rta, rta_size); rta = RTA_NEXT(rta, rta_size))
{
// done
tb_pointer_t rta_data = RTA_DATA(rta);
tb_size_t rta_data_size = RTA_PAYLOAD(rta);
switch(rta->rta_type)
{
case IFA_LABEL:
{
// make name
name = (tb_char_t*)tb_ralloc(name, rta_data_size + 1);
tb_assert_and_check_break(name);
// copy name
tb_strlcpy(name, rta_data, rta_data_size + 1);
// save name
tb_hash_map_insert(names, tb_u2p(info->ifa_index), name);
owner = tb_true;
}
break;
default:
break;
}
}
}
// check
tb_check_return(name);
// done
struct rtattr* rta = tb_null;
tb_size_t rta_size = NLMSG_PAYLOAD(response, sizeof(struct ifaddrmsg));
for(rta = IFA_RTA(info); RTA_OK(rta, rta_size); rta = RTA_NEXT(rta, rta_size))
{
/* attempt to get the interface from the cached interfaces
* and make a new interface if no the cached interface
*/
tb_ifaddrs_interface_t interface_new = {0};
tb_ifaddrs_interface_ref_t interface = tb_ifaddrs_interface_find((tb_iterator_ref_t)interfaces, name);
if (!interface) interface = &interface_new;
// check
tb_assert(interface == &interface_new || interface->name);
// done
tb_pointer_t rta_data = RTA_DATA(rta);
switch(rta->rta_type)
{
case IFA_LOCAL:
case IFA_ADDRESS:
{
// make ipaddr
tb_ipaddr_t ipaddr;
if (!tb_ifaddrs_netlink_ipaddr_save(&ipaddr, info->ifa_family, info->ifa_index, rta_data)) break;
// save flags
if ((info->ifa_flags & IFF_LOOPBACK) || tb_ipaddr_ip_is_loopback(&ipaddr))
interface->flags |= TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK;
// save ipaddr
switch (tb_ipaddr_family(&ipaddr))
{
case TB_IPADDR_FAMILY_IPV4:
{
interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR4;
interface->ipaddr4 = ipaddr.u.ipv4;
}
break;
case TB_IPADDR_FAMILY_IPV6:
{
interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR6;
interface->ipaddr6 = ipaddr.u.ipv6;
}
break;
default:
break;
}
// trace
tb_trace_d("name: %s, ipaddr: %{ipaddr}", name, &ipaddr);
// new interface? save it
if (tb_ipaddr_family(&ipaddr) && interface == &interface_new)
{
// save interface name
interface->name = tb_strdup(name);
tb_assert(interface->name);
// save interface
tb_list_insert_tail(interfaces, interface);
}
}
break;
case IFA_LABEL:
case IFA_BROADCAST:
break;
default:
break;
}
}
// exit name
if (name && owner) tb_free(name);
name = tb_null;
}
static tb_void_t tb_ifaddrs_interface_done_hwaddr(tb_list_ref_t interfaces, tb_hash_map_ref_t names, struct nlmsghdr* response)
{
// check
tb_assert_and_check_return(interfaces && names && response);
// the info
struct ifaddrmsg* info = (struct ifaddrmsg *)NLMSG_DATA(response);
// attempt to find the interface name
tb_bool_t owner = tb_false;
tb_char_t* name = (tb_char_t*)tb_hash_map_get(names, tb_u2p(info->ifa_index));
if (!name)
{
// get the interface name
struct rtattr* rta = tb_null;
tb_size_t rta_size = NLMSG_PAYLOAD(response, sizeof(struct ifaddrmsg));
for(rta = IFLA_RTA(info); RTA_OK(rta, rta_size); rta = RTA_NEXT(rta, rta_size))
{
// done
tb_pointer_t rta_data = RTA_DATA(rta);
tb_size_t rta_data_size = RTA_PAYLOAD(rta);
switch(rta->rta_type)
{
case IFLA_IFNAME:
{
// make name
name = (tb_char_t*)tb_ralloc(name, rta_data_size + 1);
tb_assert_and_check_break(name);
// copy name
tb_strlcpy(name, rta_data, rta_data_size + 1);
// save name
tb_hash_map_insert(names, tb_u2p(info->ifa_index), name);
owner = tb_true;
}
break;
default:
break;
}
}
}
// check
tb_check_return(name);
// done
struct rtattr* rta = tb_null;
tb_size_t rta_size = NLMSG_PAYLOAD(response, sizeof(struct ifaddrmsg));
for(rta = IFLA_RTA(info); RTA_OK(rta, rta_size); rta = RTA_NEXT(rta, rta_size))
{
/* attempt to get the interface from the cached interfaces
* and make a new interface if no the cached interface
*/
tb_ifaddrs_interface_t interface_new = {0};
tb_ifaddrs_interface_ref_t interface = tb_ifaddrs_interface_find((tb_iterator_ref_t)interfaces, name);
if (!interface) interface = &interface_new;
// check
tb_assert(interface == &interface_new || interface->name);
// done
tb_pointer_t rta_data = RTA_DATA(rta);
tb_size_t rta_data_size = RTA_PAYLOAD(rta);
switch(rta->rta_type)
{
case IFLA_ADDRESS:
{
// no hwaddr?
if (!(interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR))
{
// check
tb_check_break(rta_data_size == sizeof(interface->hwaddr.u8));
// save flags
interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR;
if (info->ifa_flags & IFF_LOOPBACK) interface->flags |= TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK;
// save hwaddr
tb_memcpy(interface->hwaddr.u8, rta_data, sizeof(interface->hwaddr.u8));
// trace
tb_trace_d("name: %s, hwaddr: %{hwaddr}", name, &interface->hwaddr);
// new interface? save it
if (interface == &interface_new)
{
// save interface name
interface->name = tb_strdup(name);
tb_assert(interface->name);
// save interface
tb_list_insert_tail(interfaces, interface);
}
}
}
break;
case IFLA_IFNAME:
case IFLA_BROADCAST:
case IFLA_STATS:
break;
default:
break;
}
}
// exit name
if (name && owner) tb_free(name);
name = tb_null;
}
static tb_long_t tb_ifaddrs_interface_done(tb_list_ref_t interfaces, tb_hash_map_ref_t names, tb_long_t sock, tb_long_t request)
{
// check
tb_assert_and_check_return_val(interfaces && names && sock >= 0, -1);
// done
tb_size_t size = 4096;
tb_pointer_t data = tb_null;
tb_long_t ok = -1;
pid_t pid = getpid();
while (ok < 0)
{
// make data
data = tb_ralloc(data, size);
tb_assert_and_check_break(data);
// trace
tb_trace_d("netlink: recv: ..");
// recv response
tb_long_t recv = tb_ifaddrs_netlink_socket_recv(sock, data, size);
// trace
tb_trace_d("netlink: recv: %ld", recv);
// space not enough?
if (recv == -1)
{
// grow space and continue it
size <<= 1;
continue ;
}
// check
tb_assert_and_check_break(recv > 0);
// done
tb_bool_t failed = tb_false;
struct nlmsghdr* response = tb_null;
for (response = (struct nlmsghdr *)data; NLMSG_OK(response, (tb_uint_t)recv); response = (struct nlmsghdr *)NLMSG_NEXT(response, recv))
{
// trace
tb_trace_d("type: %d, pid: %ld ?= %ld, sock: %ld ?= %ld", response->nlmsg_type, (tb_long_t)response->nlmsg_pid, (tb_long_t)pid, (tb_long_t)response->nlmsg_seq, (tb_long_t)sock);
// failed?
tb_check_break_state(response->nlmsg_type != NLMSG_ERROR, failed, tb_true);
// invalid pid?
tb_assert_and_check_break_state((tb_long_t)response->nlmsg_pid > 0, failed, tb_true);
// isn't it?
if ((pid_t)response->nlmsg_pid != pid || (tb_long_t)response->nlmsg_seq != sock)
continue;
// done?
if (response->nlmsg_type == NLMSG_DONE)
{
// trace
tb_trace_d("done");
// ok
ok = 1;
break;
}
// get hwaddr?
if (request == RTM_GETLINK && response->nlmsg_type == RTM_NEWLINK)
{
// done hwaddr
tb_ifaddrs_interface_done_hwaddr(interfaces, names, response);
}
// get ipaddr?
else if (request == RTM_GETADDR && response->nlmsg_type == RTM_NEWADDR)
{
// done ipaddr
tb_ifaddrs_interface_done_ipaddr(interfaces, names, response);
}
}
// failed?
tb_check_break(!failed);
// continue if empty?
if (ok < 0) ok = 0;
break;
}
// exit data
if (data) tb_free(data);
data = tb_null;
// ok?
return ok;
}
static tb_bool_t tb_ifaddrs_interface_load(tb_list_ref_t interfaces, tb_long_t sock, tb_long_t request)
{
// trace
tb_trace_d("netlink: load: ..");
// send request
if (tb_ifaddrs_netlink_socket_send(sock, request) < 0) return tb_false;
// make names
tb_hash_map_ref_t names = tb_hash_map_init(8, tb_element_size(), tb_element_str(tb_true));
tb_assert_and_check_return_val(names, tb_false);
// done
tb_long_t ok = -1;
while (!(ok = tb_ifaddrs_interface_done(interfaces, names, sock, request))) {};
// trace
tb_trace_d("netlink: load: %s", ok > 0? "ok" : "no");
// exit names
if (names) tb_hash_map_exit(names);
names = tb_null;
// ok?
return ok > 0;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_ifaddrs_ref_t tb_ifaddrs_init()
{
// init it
return (tb_ifaddrs_ref_t)tb_list_init(8, tb_element_mem(sizeof(tb_ifaddrs_interface_t), tb_ifaddrs_interface_exit, tb_null));
}
tb_void_t tb_ifaddrs_exit(tb_ifaddrs_ref_t ifaddrs)
{
// exit it
if (ifaddrs) tb_list_exit((tb_list_ref_t)ifaddrs);
}
tb_iterator_ref_t tb_ifaddrs_itor(tb_ifaddrs_ref_t ifaddrs, tb_bool_t reload)
{
// check
tb_list_ref_t interfaces = (tb_list_ref_t)ifaddrs;
tb_assert_and_check_return_val(interfaces, tb_null);
// uses the cached interfaces?
tb_check_return_val(reload, (tb_iterator_ref_t)interfaces);
// clear interfaces first
tb_list_clear(interfaces);
// done
tb_long_t sock = -1;
do
{
// make sock
sock = tb_ifaddrs_netlink_socket_init();
tb_assert_and_check_break(sock >= 0);
// load ipaddr
if (!tb_ifaddrs_interface_load(interfaces, sock, RTM_GETADDR)) break;
// load hwaddr
if (!tb_ifaddrs_interface_load(interfaces, sock, RTM_GETLINK)) break;
} while (0);
// exit sock
if (sock >= 0) close(sock);
sock = -1;
// ok?
return (tb_iterator_ref_t)interfaces;
}
tbox-1.7.6/src/tbox/platform/linux/poller_epoll.c 0000664 0000000 0000000 00000030355 14671175054 0022103 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file poller_epoll.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include
#include
#include
#include
#ifdef TB_CONFIG_POSIX_HAVE_GETRLIMIT
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the epoll poller type
typedef struct __tb_poller_epoll_t
{
// the poller base
tb_poller_t base;
// the maxn
tb_size_t maxn;
// the pair sockets for spak, kill ..
tb_socket_ref_t pair[2];
// the epoll fd
tb_long_t epfd;
// the events
struct epoll_event* events;
// the events count
tb_size_t events_count;
// the socket data
tb_pollerdata_t pollerdata;
}tb_poller_epoll_t, *tb_poller_epoll_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_size_t tb_poller_epoll_maxfds()
{
// attempt to get it from getdtablesize
tb_size_t maxfds = 0;
#ifdef TB_CONFIG_POSIX_HAVE_GETDTABLESIZE
if (!maxfds) maxfds = getdtablesize();
#endif
// attempt to get it from getrlimit
#ifdef TB_CONFIG_POSIX_HAVE_GETRLIMIT
struct rlimit rl;
if (!maxfds && !getrlimit(RLIMIT_NOFILE, &rl))
maxfds = rl.rlim_cur;
#endif
// attempt to get it from sysconf
if (!maxfds) maxfds = sysconf(_SC_OPEN_MAX);
// ok?
return maxfds;
}
static tb_void_t tb_poller_epoll_exit(tb_poller_t* self)
{
// check
tb_poller_epoll_ref_t poller = (tb_poller_epoll_ref_t)self;
tb_assert_and_check_return(poller);
// exit pair sockets
if (poller->pair[0]) tb_socket_exit(poller->pair[0]);
if (poller->pair[1]) tb_socket_exit(poller->pair[1]);
poller->pair[0] = tb_null;
poller->pair[1] = tb_null;
// exit events
if (poller->events) tb_free(poller->events);
poller->events = tb_null;
poller->events_count = 0;
// close epfd
if (poller->epfd > 0) close(poller->epfd);
poller->epfd = 0;
// exit socket data
tb_pollerdata_exit(&poller->pollerdata);
// free it
tb_free(poller);
}
static tb_void_t tb_poller_epoll_kill(tb_poller_t* self)
{
// check
tb_poller_epoll_ref_t poller = (tb_poller_epoll_ref_t)self;
tb_assert_and_check_return(poller);
// kill it
if (poller->pair[0]) tb_socket_send(poller->pair[0], (tb_byte_t const*)"k", 1);
}
static tb_void_t tb_poller_epoll_spak(tb_poller_t* self)
{
// check
tb_poller_epoll_ref_t poller = (tb_poller_epoll_ref_t)self;
tb_assert_and_check_return(poller);
// post it
if (poller->pair[0]) tb_socket_send(poller->pair[0], (tb_byte_t const*)"p", 1);
}
static tb_bool_t tb_poller_epoll_insert(tb_poller_t* self, tb_poller_object_ref_t object, tb_size_t events, tb_cpointer_t priv)
{
// check
tb_poller_epoll_ref_t poller = (tb_poller_epoll_ref_t)self;
tb_assert_and_check_return_val(poller && poller->epfd > 0 && object, tb_false);
// init event
struct epoll_event e = {0};
if (events & TB_POLLER_EVENT_RECV) e.events |= EPOLLIN;
if (events & TB_POLLER_EVENT_SEND) e.events |= EPOLLOUT;
if (events & TB_POLLER_EVENT_CLEAR)
{
e.events |= EPOLLET;
#ifdef EPOLLRDHUP
e.events |= EPOLLRDHUP;
#endif
}
#ifdef EPOLLONESHOT
if (events & TB_POLLER_EVENT_ONESHOT) e.events |= EPOLLONESHOT;
#else
// oneshot is not supported now
tb_assertf(!(events & TB_POLLER_EVENT_ONESHOT), "cannot insert events with oneshot, not supported!");
#endif
// save fd
e.data.fd = (tb_int_t)tb_ptr2fd(object->ref.ptr);
// bind the object type to the private data
priv = tb_poller_priv_set_object_type(object, priv);
// bind user private data to object
if (!(events & TB_POLLER_EVENT_NOEXTRA) || object->type == TB_POLLER_OBJECT_PIPE)
tb_pollerdata_set(&poller->pollerdata, object, priv);
// add socket and events
if (epoll_ctl(poller->epfd, EPOLL_CTL_ADD, e.data.fd, &e) < 0)
{
// trace
tb_trace_e("insert object(%p) events: %lu failed, errno: %d", object->ref.ptr, events, errno);
return tb_false;
}
// ok
return tb_true;
}
static tb_bool_t tb_poller_epoll_remove(tb_poller_t* self, tb_poller_object_ref_t object)
{
// check
tb_poller_epoll_ref_t poller = (tb_poller_epoll_ref_t)self;
tb_assert_and_check_return_val(poller && poller->epfd > 0 && object, tb_false);
// remove object and events
struct epoll_event e = {0};
tb_long_t fd = tb_ptr2fd(object->ref.ptr);
if (epoll_ctl(poller->epfd, EPOLL_CTL_DEL, fd, &e) < 0)
{
// trace
tb_trace_e("remove object(%p) failed, errno: %d", object->ref.ptr, errno);
return tb_false;
}
// remove user private data from this object
tb_pollerdata_reset(&poller->pollerdata, object);
return tb_true;
}
static tb_bool_t tb_poller_epoll_modify(tb_poller_t* self, tb_poller_object_ref_t object, tb_size_t events, tb_cpointer_t priv)
{
// check
tb_poller_epoll_ref_t poller = (tb_poller_epoll_ref_t)self;
tb_assert_and_check_return_val(poller && poller->epfd > 0 && object, tb_false);
// init event
struct epoll_event e = {0};
if (events & TB_POLLER_EVENT_RECV) e.events |= EPOLLIN;
if (events & TB_POLLER_EVENT_SEND) e.events |= EPOLLOUT;
if (events & TB_POLLER_EVENT_CLEAR)
{
e.events |= EPOLLET;
#ifdef EPOLLRDHUP
e.events |= EPOLLRDHUP;
#endif
}
#ifdef EPOLLONESHOT
if (events & TB_POLLER_EVENT_ONESHOT) e.events |= EPOLLONESHOT;
#else
// oneshot is not supported now
tb_assertf(!(events & TB_POLLER_EVENT_ONESHOT), "cannot insert events with oneshot, not supported!");
#endif
// save fd
e.data.fd = (tb_int_t)tb_ptr2fd(object->ref.ptr);
// bind the object type to the private data
priv = tb_poller_priv_set_object_type(object, priv);
// bind user private data to object
if (!(events & TB_POLLER_EVENT_NOEXTRA) || object->type == TB_POLLER_OBJECT_PIPE)
tb_pollerdata_set(&poller->pollerdata, object, priv);
// modify events
if (epoll_ctl(poller->epfd, EPOLL_CTL_MOD, e.data.fd, &e) < 0)
{
// trace
tb_trace_e("modify object(%p) events: %lu failed, errno: %d", object->ref.ptr, events, errno);
return tb_false;
}
return tb_true;
}
static tb_long_t tb_poller_epoll_wait(tb_poller_t* self, tb_poller_event_func_t func, tb_long_t timeout)
{
// check
tb_poller_epoll_ref_t poller = (tb_poller_epoll_ref_t)self;
tb_assert_and_check_return_val(poller && poller->epfd > 0 && poller->maxn && func, -1);
// init events
tb_size_t grow = tb_align8((poller->maxn >> 3) + 1);
if (!poller->events)
{
poller->events_count = grow;
poller->events = tb_nalloc_type(poller->events_count, struct epoll_event);
tb_assert_and_check_return_val(poller->events, -1);
}
// wait events
tb_long_t events_count = epoll_wait(poller->epfd, poller->events, poller->events_count, timeout);
// timeout or interrupted?
if (!events_count || (events_count == -1 && errno == EINTR))
return 0;
// check error?
tb_assert_and_check_return_val(events_count >= 0 && events_count <= poller->events_count, -1);
// grow it if events is full
if (events_count == poller->events_count)
{
// grow size
poller->events_count += grow;
if (poller->events_count > poller->maxn) poller->events_count = poller->maxn;
// grow data
poller->events = (struct epoll_event*)tb_ralloc(poller->events, poller->events_count * sizeof(struct epoll_event));
tb_assert_and_check_return_val(poller->events, -1);
}
tb_assert(events_count <= poller->events_count);
// limit
events_count = tb_min(events_count, poller->maxn);
// handle events
tb_size_t i = 0;
tb_size_t wait = 0;
struct epoll_event* e = tb_null;
tb_socket_ref_t pair = poller->pair[1];
tb_poller_object_t object;
for (i = 0; i < events_count; i++)
{
// the epoll event
e = poller->events + i;
// the events for epoll
tb_size_t epoll_events = e->events;
// the socket
tb_long_t fd = e->data.fd;
object.ref.ptr = tb_fd2ptr(fd);
tb_assert(object.ref.ptr);
// spank socket events?
if (object.ref.sock == pair && (epoll_events & EPOLLIN))
{
// read spak
tb_char_t spak = '\0';
if (1 != tb_socket_recv(pair, (tb_byte_t*)&spak, 1)) return -1;
// killed?
if (spak == 'k') return -1;
// continue it
continue ;
}
tb_check_continue(object.ref.sock != pair);
// init events
tb_size_t events = TB_POLLER_EVENT_NONE;
if (epoll_events & EPOLLIN) events |= TB_POLLER_EVENT_RECV;
if (epoll_events & EPOLLOUT) events |= TB_POLLER_EVENT_SEND;
if (epoll_events & (EPOLLHUP | EPOLLERR) && !(events & (TB_POLLER_EVENT_RECV | TB_POLLER_EVENT_SEND)))
events |= TB_POLLER_EVENT_RECV | TB_POLLER_EVENT_SEND;
#ifdef EPOLLRDHUP
// connection closed for the edge trigger?
if (epoll_events & EPOLLRDHUP) events |= TB_POLLER_EVENT_EOF;
#endif
// call event function
tb_cpointer_t priv = tb_pollerdata_get(&poller->pollerdata, &object);
object.type = tb_poller_priv_get_object_type(priv);
func((tb_poller_ref_t)self, &object, events, tb_poller_priv_get_original(priv));
// update the events count
wait++;
}
// ok
return wait;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_poller_t* tb_poller_epoll_init()
{
// done
tb_bool_t ok = tb_false;
tb_poller_epoll_ref_t poller = tb_null;
do
{
// make poller
poller = tb_malloc0_type(tb_poller_epoll_t);
tb_assert_and_check_break(poller);
// init base
poller->base.type = TB_POLLER_TYPE_EPOLL;
poller->base.exit = tb_poller_epoll_exit;
poller->base.kill = tb_poller_epoll_kill;
poller->base.spak = tb_poller_epoll_spak;
poller->base.wait = tb_poller_epoll_wait;
poller->base.insert = tb_poller_epoll_insert;
poller->base.remove = tb_poller_epoll_remove;
poller->base.modify = tb_poller_epoll_modify;
#ifdef EPOLLONESHOT
poller->base.supported_events = TB_POLLER_EVENT_EALL | TB_POLLER_EVENT_CLEAR | TB_POLLER_EVENT_ONESHOT;
#else
poller->base.supported_events = TB_POLLER_EVENT_EALL | TB_POLLER_EVENT_CLEAR;
#endif
// init poller data
tb_pollerdata_init(&poller->pollerdata);
// init maxn
poller->maxn = tb_poller_epoll_maxfds();
tb_assert_and_check_break(poller->maxn);
// init epoll
poller->epfd = epoll_create(poller->maxn);
tb_assert_and_check_break(poller->epfd > 0);
// init pair sockets
if (!tb_socket_pair(TB_SOCKET_TYPE_TCP, poller->pair)) break;
// insert pair socket first
tb_poller_object_t object;
object.type = TB_POLLER_OBJECT_SOCK;
object.ref.sock = poller->pair[1];
if (!tb_poller_epoll_insert((tb_poller_t*)poller, &object, TB_POLLER_EVENT_RECV, tb_null)) break;
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (poller) tb_poller_epoll_exit((tb_poller_t*)poller);
poller = tb_null;
}
// ok?
return (tb_poller_t*)poller;
}
tbox-1.7.6/src/tbox/platform/linux/prefix.h 0000664 0000000 0000000 00000001737 14671175054 0020717 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
* @ingroup platform
*/
#ifndef TB_PLATFORM_LINUX_PREFIX_H
#define TB_PLATFORM_LINUX_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#include "../../libc/libc.h"
#include "../../utils/utils.h"
#endif
tbox-1.7.6/src/tbox/platform/ltimer.c 0000664 0000000 0000000 00000053317 14671175054 0017553 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file ltimer.c
* @ingroup platform
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "ltimer"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "platform.h"
#include "../memory/memory.h"
#include "../container/container.h"
#include "../algorithm/algorithm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the timer wheel maxn
#ifdef __tb_small__
# define TB_LTIMER_WHEEL_MAXN (4096)
#else
# define TB_LTIMER_WHEEL_MAXN (8192)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the timer task type
typedef struct __tb_ltimer_task_t
{
// the func
tb_ltimer_task_func_t func;
// the priv
tb_cpointer_t priv;
// the when
tb_hong_t when;
// the period
tb_uint32_t period : 28;
// is repeat?
tb_uint32_t repeat : 1;
// is killed?
tb_uint32_t killed : 1;
// the refn, <= 2
tb_uint32_t refn : 2;
// the wheel index
tb_uint32_t windx;
}tb_ltimer_task_t;
/*! the timer type
*
*
*
* tick: 1s
*
* 1s 1s ..
* wheel: |-----|-----|-----|-----|-----|-----|---- ... -----| <= circle queue
* timers
* btime ==================> now
* | | |
* | | |
* | | | => the same timeout timer_task list (vector)
* |
*
*
*/
typedef struct __tb_ltimer_t
{
// the grow
tb_uint16_t grow;
// is stoped?
tb_atomic_flag_t stop;
// is worked?
tb_atomic32_t work;
// the base time
tb_hong_t btime;
// cache time?
tb_bool_t ctime;
// the tick
tb_size_t tick;
// the lock
tb_spinlock_t lock;
// the pool
tb_fixed_pool_ref_t pool;
// the expired tasks
tb_vector_ref_t expired;
// the wheel
tb_vector_ref_t wheel[TB_LTIMER_WHEEL_MAXN];
// the wheel base
tb_size_t wbase;
}tb_ltimer_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static __tb_inline__ tb_hong_t tb_ltimer_now(tb_ltimer_t* timer)
{
// using the real time?
if (!timer->ctime)
{
// get the time
tb_timeval_t tv = {0};
if (tb_gettimeofday(&tv, tb_null)) return ((tb_hong_t)tv.tv_sec * 1000 + tv.tv_usec / 1000);
}
// using cached time
return tb_cache_time_mclock();
}
static tb_bool_t tb_ltimer_add_task(tb_ltimer_t* timer, tb_ltimer_task_t* timer_task)
{
// check
tb_assert_and_check_return_val(timer && timer->pool && timer->tick, tb_false);
tb_assert_and_check_return_val(timer_task && timer_task->func && timer_task->refn && timer_task->when, tb_false);
// trace
tb_trace_d("add: when: %lld, period: %u, refn: %u", timer_task->when, timer_task->period, timer_task->refn);
// done
tb_bool_t ok = tb_false;
do
{
// empty? move to the wheel head
if (!tb_fixed_pool_size(timer->pool))
{
timer->btime = tb_ltimer_now(timer);
timer->wbase = 0;
}
// trace
tb_trace_d("add: btime: %lld, wbase: %lu", timer->btime, timer->wbase);
// the timer difference
tb_hong_t tdiff = timer_task->when - timer->btime;
tb_assert_and_check_break(tdiff >= 0);
// trace
tb_trace_d("add: tdiff: %lld", tdiff);
// the wheel difference
tb_size_t wdiff = (tb_size_t)(tdiff / timer->tick);
tb_assert_and_check_break(wdiff < TB_LTIMER_WHEEL_MAXN);
// trace
tb_trace_d("add: wdiff: %lu", wdiff);
// the wheel index
tb_size_t windx = (timer->wbase + wdiff) & (TB_LTIMER_WHEEL_MAXN - 1);
// trace
tb_trace_d("add: windx: %lu", windx);
// the wheel list
tb_vector_ref_t wlist = timer->wheel[windx];
if (!wlist) wlist = timer->wheel[windx] = tb_vector_init(timer->grow, tb_element_ptr(tb_null, tb_null));
tb_assert_and_check_break(wlist);
// save the wheel index
timer_task->windx = (tb_uint32_t)windx;
// add task to the wheel list
tb_vector_insert_tail(wlist, timer_task);
// ok
ok = tb_true;
} while (0);
// ok?
return ok;
}
static tb_bool_t tb_ltimer_del_task(tb_ltimer_t* timer, tb_ltimer_task_t* timer_task)
{
// check
tb_assert_and_check_return_val(timer && timer->pool && timer->tick, tb_false);
tb_assert_and_check_return_val(timer_task && timer_task->func && timer_task->refn && timer_task->when, tb_false);
// trace
tb_trace_d("del: when: %lld, period: %u, refn: %u", timer_task->when, timer_task->period, timer_task->refn);
// done
tb_bool_t ok = tb_false;
do
{
// check
tb_assert_and_check_break(timer_task->windx != -1 && timer_task->windx < tb_arrayn(timer->wheel));
// the wheel list
tb_vector_ref_t wlist = timer->wheel[timer_task->windx];
tb_assert_and_check_break(wlist);
// find the task from the wheel list
tb_size_t itor = tb_find_all(wlist, timer_task);
tb_assert_and_check_break(itor != tb_iterator_tail(wlist));
// del the task from the wheel list
tb_vector_remove(wlist, itor);
// clear the wheel index
timer_task->windx = -1;
// ok
ok = tb_true;
} while (0);
// ok?
return ok;
}
static tb_bool_t tb_ltimer_expired_task_done(tb_iterator_ref_t iterator, tb_pointer_t item, tb_cpointer_t priv)
{
// the task
tb_ltimer_task_t const* timer_task = (tb_ltimer_task_t const*)item;
// done func
if (timer_task && timer_task->func)
{
// trace
tb_trace_d("done: expired: when: %lld, period: %u, refn: %u, killed: %u", timer_task->when, timer_task->period, timer_task->refn, timer_task->killed);
// done
timer_task->func(timer_task->killed? tb_true : tb_false, timer_task->priv);
}
// ok
return tb_true;
}
static tb_bool_t tb_ltimer_expired_task_exit(tb_iterator_ref_t iterator, tb_pointer_t item, tb_cpointer_t priv)
{
// check
tb_ltimer_t* timer = priv? (tb_ltimer_t*)(((tb_pointer_t*)priv)[0]) : tb_null;
tb_hong_t* now = priv? (tb_hong_t*)(((tb_pointer_t*)priv)[1]) : tb_null;
tb_assert_and_check_return_val(timer && now, tb_false);
// the task
tb_ltimer_task_t* timer_task = (tb_ltimer_task_t*)item;
if (timer_task)
{
// repeat?
if (timer_task->repeat)
{
// update when
timer_task->when = *now + timer_task->period;
// continue the task
if (!tb_ltimer_add_task(timer, timer_task))
{
// trace
tb_trace_e("continue to add timer_task failed");
}
}
else
{
// refn--
if (timer_task->refn > 1) timer_task->refn--;
// remove it from pool directly
else tb_fixed_pool_free(timer->pool, timer_task);
}
}
// ok
return tb_true;
}
static tb_void_t tb_ltimer_expired_list_exit(tb_element_ref_t element, tb_pointer_t buff)
{
// check
tb_vector_ref_t list = buff? *((tb_vector_ref_t*)buff) : tb_null;
tb_assert_and_check_return(list);
// exit list
tb_vector_exit(list);
// clear it
*((tb_pointer_t*)buff) = tb_null;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_ltimer_ref_t tb_ltimer_init(tb_size_t grow, tb_size_t tick, tb_bool_t ctime)
{
// check
tb_assert_and_check_return_val(tick >= TB_LTIMER_TICK_100MS, tb_null);
// done
tb_bool_t ok = tb_false;
tb_ltimer_t* timer = tb_null;
do
{
// make timer
timer = tb_malloc0_type(tb_ltimer_t);
tb_assert_and_check_break(timer);
// init timer
timer->grow = (tb_uint16_t)tb_max(grow, 16);
timer->ctime = ctime;
timer->tick = tick;
timer->btime = tb_ltimer_now(timer);
tb_atomic_flag_clear_explicit(&timer->stop, TB_ATOMIC_RELAXED);
tb_atomic32_init(&timer->work, 0);
// init lock
if (!tb_spinlock_init(&timer->lock)) break;
// init pool
timer->pool = tb_fixed_pool_init(tb_null, timer->grow, sizeof(tb_ltimer_task_t), tb_null, tb_null, tb_null);
tb_assert_and_check_break(timer->pool);
// init the expired tasks
timer->expired = tb_vector_init((TB_LTIMER_WHEEL_MAXN >> 3) + 8, tb_element_ptr(tb_ltimer_expired_list_exit, tb_null));
tb_assert_and_check_break(timer->expired);
// register lock profiler
#ifdef TB_LOCK_PROFILER_ENABLE
tb_lock_profiler_register(tb_lock_profiler(), (tb_pointer_t)&timer->lock, TB_TRACE_MODULE_NAME);
#endif
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (timer) tb_ltimer_exit((tb_ltimer_ref_t)timer);
timer = tb_null;
}
// ok?
return (tb_ltimer_ref_t)timer;
}
tb_void_t tb_ltimer_exit(tb_ltimer_ref_t self)
{
// check
tb_ltimer_t* timer = (tb_ltimer_t*)self;
tb_assert_and_check_return(self);
// kill it first
tb_ltimer_kill(self);
// wait loop exit
tb_size_t tryn = 10;
while (tb_atomic32_get_explicit(&timer->work, TB_ATOMIC_RELAXED) && tryn--) tb_msleep(500);
// warning
if (!tryn && tb_atomic32_get_explicit(&timer->work, TB_ATOMIC_RELAXED))
{
tb_trace_w("[ltimer]: the loop has been not exited now!");
}
// enter
tb_spinlock_enter(&timer->lock);
// exit wheel
{
tb_size_t i = 0;
for (i = 0; i < TB_LTIMER_WHEEL_MAXN; i++)
{
if (timer->wheel[i]) tb_vector_exit(timer->wheel[i]);
timer->wheel[i] = tb_null;
}
}
// exit pool
if (timer->pool) tb_fixed_pool_exit(timer->pool);
timer->pool = tb_null;
// leave
tb_spinlock_leave(&timer->lock);
// exit the expired tasks
if (timer->expired) tb_vector_exit(timer->expired);
timer->expired = tb_null;
// exit lock
tb_spinlock_exit(&timer->lock);
// exit it
tb_free(timer);
}
tb_void_t tb_ltimer_kill(tb_ltimer_ref_t self)
{
// check
tb_ltimer_t* timer = (tb_ltimer_t*)self;
tb_assert_and_check_return(self);
// stop it
tb_atomic_flag_test_and_set_explicit(&timer->stop, TB_ATOMIC_RELAXED);
}
tb_void_t tb_ltimer_clear(tb_ltimer_ref_t self)
{
tb_ltimer_t* timer = (tb_ltimer_t*)self;
if (timer)
{
// enter
tb_spinlock_enter(&timer->lock);
// move to the wheel head
timer->btime = tb_ltimer_now(timer);
timer->wbase = 0;
// clear wheel
{
tb_size_t i = 0;
for (i = 0; i < TB_LTIMER_WHEEL_MAXN; i++)
{
if (timer->wheel[i]) tb_vector_clear(timer->wheel[i]);
}
}
// clear pool
if (timer->pool) tb_fixed_pool_clear(timer->pool);
// leave
tb_spinlock_leave(&timer->lock);
}
}
tb_size_t tb_ltimer_limit(tb_ltimer_ref_t self)
{
// check
tb_ltimer_t* timer = (tb_ltimer_t*)self;
tb_assert_and_check_return_val(timer, 0);
// the self limit
return (TB_LTIMER_WHEEL_MAXN * timer->tick);
}
tb_size_t tb_ltimer_delay(tb_ltimer_ref_t self)
{
// check
tb_ltimer_t* timer = (tb_ltimer_t*)self;
tb_assert_and_check_return_val(timer, -1);
// ok?
return timer->tick;
}
tb_bool_t tb_ltimer_spak(tb_ltimer_ref_t self)
{
// check
tb_ltimer_t* timer = (tb_ltimer_t*)self;
tb_assert_and_check_return_val(timer && timer->pool && timer->tick && timer->expired, tb_false);
// stoped?
tb_check_return_val(!tb_atomic_flag_test_explicit(&timer->stop, TB_ATOMIC_RELAXED), tb_false);
// the now time
tb_hong_t now = tb_ltimer_now(timer);
// enter
tb_spinlock_enter(&timer->lock);
// done
tb_bool_t ok = tb_false;
do
{
// less than one tick? continue to wait
if (now - timer->btime < timer->tick)
{
ok = tb_true;
break;
}
// empty? move to the wheel head
if (!tb_fixed_pool_size(timer->pool))
{
timer->btime = now;
timer->wbase = 0;
ok = tb_true;
break;
}
// the diff
tb_size_t diff = (tb_size_t)((now - timer->btime) / timer->tick);
// trace
tb_trace_d("spak: btime: %lld, wbase: %lu, now: %lld, diff: %lu", timer->btime, timer->wbase, now, diff);
// walk the expired lists
tb_size_t i = 0;
tb_size_t n = tb_min(diff, TB_LTIMER_WHEEL_MAXN - 1);
for (i = 0; i <= n; i++)
{
// the wheel index
tb_size_t indx = (timer->wbase + i) & (TB_LTIMER_WHEEL_MAXN - 1);
// the wheel list
tb_vector_ref_t list = timer->wheel[indx];
tb_check_continue(list && tb_vector_size(list));
// detach the wheel list to the expired tasks
tb_vector_insert_tail(timer->expired, list);
timer->wheel[indx] = tb_null;
}
// update the base time
timer->btime = now;
// update the wheel base
timer->wbase = (timer->wbase + diff) & (TB_LTIMER_WHEEL_MAXN - 1);
// ok
ok = tb_true;
} while (0);
// leave
tb_spinlock_leave(&timer->lock);
// ok? and exists expired tasks?
if (ok && tb_vector_size(timer->expired))
{
// done all expired list
tb_for_all_if (tb_vector_ref_t, list, timer->expired, list)
{
// done the expired task
tb_walk_all(list, tb_ltimer_expired_task_done, tb_null);
// enter
tb_spinlock_enter(&timer->lock);
// exit the expired task
tb_pointer_t data[2]; data[0] = (tb_pointer_t)self; data[1] = &now;
tb_walk_all(list, tb_ltimer_expired_task_exit, data);
// leave
tb_spinlock_leave(&timer->lock);
}
}
// clear expired
tb_vector_clear(timer->expired);
// ok?
return ok;
}
tb_void_t tb_ltimer_loop(tb_ltimer_ref_t self)
{
// check
tb_ltimer_t* timer = (tb_ltimer_t*)self;
tb_assert_and_check_return(timer);
// work++
tb_atomic32_fetch_and_add_explicit(&timer->work, 1, TB_ATOMIC_RELAXED);
// loop
while (!tb_atomic_flag_test_explicit(&timer->stop, TB_ATOMIC_RELAXED))
{
// the delay
tb_size_t delay = tb_ltimer_delay(self);
tb_assert_and_check_break(delay != -1);
// wait some time
if (delay) tb_msleep(delay);
// spak ctime
if (timer->ctime) tb_cache_time_spak();
// spak it
if (!tb_ltimer_spak(self)) break;
}
// work--
tb_atomic32_fetch_and_sub_explicit(&timer->work, 1, TB_ATOMIC_RELAXED);
}
tb_ltimer_task_ref_t tb_ltimer_task_init(tb_ltimer_ref_t self, tb_size_t delay, tb_bool_t repeat, tb_ltimer_task_func_t func, tb_cpointer_t priv)
{
// check
tb_ltimer_t* timer = (tb_ltimer_t*)self;
tb_assert_and_check_return_val(timer && func, tb_null);
// add task
return tb_ltimer_task_init_at(self, tb_ltimer_now(timer) + delay, delay, repeat, func, priv);
}
tb_ltimer_task_ref_t tb_ltimer_task_init_at(tb_ltimer_ref_t self, tb_hize_t when, tb_size_t period, tb_bool_t repeat, tb_ltimer_task_func_t func, tb_cpointer_t priv)
{
// check
tb_ltimer_t* timer = (tb_ltimer_t*)self;
tb_assert_and_check_return_val(timer && timer->pool && func, tb_null);
// stoped?
tb_assert_and_check_return_val(!tb_atomic_flag_test_explicit(&timer->stop, TB_ATOMIC_RELAXED), tb_null);
// enter
tb_spinlock_enter(&timer->lock);
// make task
tb_ltimer_task_t* timer_task = (tb_ltimer_task_t*)tb_fixed_pool_malloc0(timer->pool);
if (timer_task)
{
// init task
timer_task->refn = 2;
timer_task->func = func;
timer_task->priv = priv;
timer_task->when = when;
timer_task->period = period;
timer_task->repeat = repeat? 1 : 0;
timer_task->killed = 0;
timer_task->windx = -1;
// add timer_task
if (!tb_ltimer_add_task(timer, timer_task))
{
tb_fixed_pool_free(timer->pool, timer_task);
timer_task = tb_null;
}
}
// leave
tb_spinlock_leave(&timer->lock);
// ok?
return (tb_ltimer_task_ref_t)timer_task;
}
tb_ltimer_task_ref_t tb_ltimer_task_init_after(tb_ltimer_ref_t self, tb_hize_t after, tb_size_t period, tb_bool_t repeat, tb_ltimer_task_func_t func, tb_cpointer_t priv)
{
// check
tb_ltimer_t* timer = (tb_ltimer_t*)self;
tb_assert_and_check_return_val(timer && func, tb_null);
// add task
return tb_ltimer_task_init_at(self, tb_ltimer_now(timer) + after, period, repeat, func, priv);
}
tb_void_t tb_ltimer_task_post(tb_ltimer_ref_t self, tb_size_t delay, tb_bool_t repeat, tb_ltimer_task_func_t func, tb_cpointer_t priv)
{
// check
tb_ltimer_t* timer = (tb_ltimer_t*)self;
tb_assert_and_check_return(timer && func);
// run task
tb_ltimer_task_post_at(self, tb_ltimer_now(timer) + delay, delay, repeat, func, priv);
}
tb_void_t tb_ltimer_task_post_at(tb_ltimer_ref_t self, tb_hize_t when, tb_size_t period, tb_bool_t repeat, tb_ltimer_task_func_t func, tb_cpointer_t priv)
{
// check
tb_ltimer_t* timer = (tb_ltimer_t*)self;
tb_assert_and_check_return(timer && timer->pool && func);
// stoped?
tb_assert_and_check_return(!tb_atomic_flag_test_explicit(&timer->stop, TB_ATOMIC_RELAXED));
// enter
tb_spinlock_enter(&timer->lock);
// make task
tb_ltimer_task_t* timer_task = (tb_ltimer_task_t*)tb_fixed_pool_malloc0(timer->pool);
if (timer_task)
{
// init task
timer_task->refn = 1;
timer_task->func = func;
timer_task->priv = priv;
timer_task->when = when;
timer_task->period = period;
timer_task->repeat = repeat? 1 : 0;
timer_task->killed = 0;
timer_task->windx = -1;
// add task
if (!tb_ltimer_add_task(timer, timer_task))
tb_fixed_pool_free(timer->pool, timer_task);
}
// leave
tb_spinlock_leave(&timer->lock);
}
tb_void_t tb_ltimer_task_post_after(tb_ltimer_ref_t self, tb_hize_t after, tb_size_t period, tb_bool_t repeat, tb_ltimer_task_func_t func, tb_cpointer_t priv)
{
// check
tb_ltimer_t* timer = (tb_ltimer_t*)self;
tb_assert_and_check_return(timer && func);
// run task
tb_ltimer_task_post_at(self, tb_ltimer_now(timer) + after, period, repeat, func, priv);
}
tb_void_t tb_ltimer_task_exit(tb_ltimer_ref_t self, tb_ltimer_task_ref_t task)
{
// check
tb_ltimer_t* timer = (tb_ltimer_t*)self;
tb_ltimer_task_t* timer_task = (tb_ltimer_task_t*)task;
tb_assert_and_check_return(timer && timer->pool && timer_task);
// trace
tb_trace_d("exit: when: %lld, period: %u, refn: %u", timer_task->when, timer_task->period, timer_task->refn);
// enter
tb_spinlock_enter(&timer->lock);
if (timer_task->refn > 1)
{
// refn--
timer_task->refn--;
// cancel task
timer_task->func = tb_null;
timer_task->priv = tb_null;
timer_task->repeat = 0;
}
// remove it from pool directly if the task have been expired
else tb_fixed_pool_free(timer->pool, timer_task);
// leave
tb_spinlock_leave(&timer->lock);
}
tb_void_t tb_ltimer_task_kill(tb_ltimer_ref_t self, tb_ltimer_task_ref_t task)
{
// check
tb_ltimer_t* timer = (tb_ltimer_t*)self;
tb_ltimer_task_t* timer_task = (tb_ltimer_task_t*)task;
tb_assert_and_check_return(timer && timer->pool && timer_task);
// trace
tb_trace_d("kill: when: %lld, period: %u, refn: %u", timer_task->when, timer_task->period, timer_task->refn);
// enter
tb_spinlock_enter(&timer->lock);
// done
do
{
// expired or removed?
tb_check_break(timer_task->refn == 2);
// del the task first
if (!tb_ltimer_del_task(timer, timer_task))
{
// trace
tb_trace_e("del timer_task failed");
break;
}
// killed
timer_task->killed = 1;
// no repeat
timer_task->repeat = 0;
// modify when => now
timer_task->when = tb_ltimer_now(timer);
// re-add task
if (!tb_ltimer_add_task(timer, timer_task))
{
// trace
tb_trace_e("re-add timer_task failed");
break;
}
} while (0);
// leave
tb_spinlock_leave(&timer->lock);
}
tbox-1.7.6/src/tbox/platform/ltimer.h 0000664 0000000 0000000 00000015711 14671175054 0017554 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file ltimer.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_LTIMER_H
#define TB_PLATFORM_LTIMER_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "timer.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the timer tick enum
typedef enum __tb_ltimer_tick_e
{
TB_LTIMER_TICK_100MS = 100
, TB_LTIMER_TICK_S = 1000
, TB_LTIMER_TICK_M = 60000
, TB_LTIMER_TICK_H = 3600000
}tb_ltimer_tick_e;
/// the ltimer task func type
typedef tb_timer_task_func_t tb_ltimer_task_func_t;
/// the ltimer ref type
typedef __tb_typeref__(ltimer);
/// the ltimer task ref type
typedef __tb_typeref__(ltimer_task);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init timer
*
* lower tick and limit range, but faster
*
* @param grow the timer grow
* @param tick the timer tick
* @param ctime using ctime?
*
* @return the timer
*/
tb_ltimer_ref_t tb_ltimer_init(tb_size_t grow, tb_size_t tick, tb_bool_t ctime);
/*! exit timer
*
* @param timer the timer
*/
tb_void_t tb_ltimer_exit(tb_ltimer_ref_t timer);
/*! kill timer for tb_ltimer_loop()
*
* @param timer the timer
*/
tb_void_t tb_ltimer_kill(tb_ltimer_ref_t timer);
/*! clear timer
*
* @param timer the timer
*/
tb_void_t tb_ltimer_clear(tb_ltimer_ref_t timer);
/*! the timer limit
*
* @param timer the timer
*
* @return the timer limit range: [now, now + limit)
*/
tb_size_t tb_ltimer_limit(tb_ltimer_ref_t timer);
/*! the timer delay for spak
*
* @param timer the timer
*
* @return the timer delay, (tb_size_t)-1: error or no task
*/
tb_size_t tb_ltimer_delay(tb_ltimer_ref_t timer);
/*! spak timer for the external loop at the single thread
*
* @code
tb_void_t tb_ltimer_loop()
{
while (1)
{
// wait
wait(tb_ltimer_delay(timer))
// spak timer
tb_ltimer_spak(timer);
}
}
* @endcode
*
* @param timer the timer
*
* @return tb_true or tb_false
*/
tb_bool_t tb_ltimer_spak(tb_ltimer_ref_t timer);
/*! loop timer for the external thread
*
* @code
tb_void_t tb_ltimer_thread(tb_cpointer_t priv)
{
tb_ltimer_loop(timer);
}
* @endcode
*
* @param timer the timer
*
*/
tb_void_t tb_ltimer_loop(tb_ltimer_ref_t timer);
/*! post timer task after delay and will be auto-remove it after be expired
*
* @param timer the timer
* @param delay the delay time, ms
* @param repeat is repeat?
* @param func the timer func
* @param priv the timer priv
*
*/
tb_void_t tb_ltimer_task_post(tb_ltimer_ref_t timer, tb_size_t delay, tb_bool_t repeat, tb_ltimer_task_func_t func, tb_cpointer_t priv);
/*! post timer task at the absolute time and will be auto-remove it after be expired
*
* @param timer the timer
* @param when the absolute time, ms
* @param period the period time, ms
* @param repeat is repeat?
* @param func the timer func
* @param priv the timer priv
*
*/
tb_void_t tb_ltimer_task_post_at(tb_ltimer_ref_t timer, tb_hize_t when, tb_size_t period, tb_bool_t repeat, tb_ltimer_task_func_t func, tb_cpointer_t priv);
/*! run timer task after the relative time and will be auto-remove it after be expired
*
* @param timer the timer
* @param after the after time, ms
* @param period the period time, ms
* @param repeat is repeat?
* @param func the timer func
* @param priv the timer priv
*
*/
tb_void_t tb_ltimer_task_post_after(tb_ltimer_ref_t timer, tb_hize_t after, tb_size_t period, tb_bool_t repeat, tb_ltimer_task_func_t func, tb_cpointer_t priv);
/*! init and post timer task after delay and need remove it manually
*
* @param timer the timer
* @param delay the delay time, ms
* @param repeat is repeat?
* @param func the timer func
* @param priv the timer priv
*
* @return the timer task
*/
tb_ltimer_task_ref_t tb_ltimer_task_init(tb_ltimer_ref_t timer, tb_size_t delay, tb_bool_t repeat, tb_ltimer_task_func_t func, tb_cpointer_t priv);
/*! init and post timer task at the absolute time and need remove it manually
*
* @param timer the timer
* @param when the absolute time, ms
* @param period the period time, ms
* @param repeat is repeat?
* @param func the timer func
* @param priv the timer priv
*
* @return the timer task
*/
tb_ltimer_task_ref_t tb_ltimer_task_init_at(tb_ltimer_ref_t timer, tb_hize_t when, tb_size_t period, tb_bool_t repeat, tb_ltimer_task_func_t func, tb_cpointer_t priv);
/*! init and post timer task after the relative time and need remove it manually
*
* @param timer the timer
* @param after the after time, ms
* @param period the period time, ms
* @param repeat is repeat?
* @param func the timer func
* @param priv the timer priv
*
* @return the timer task
*/
tb_ltimer_task_ref_t tb_ltimer_task_init_after(tb_ltimer_ref_t timer, tb_hize_t after, tb_size_t period, tb_bool_t repeat, tb_ltimer_task_func_t func, tb_cpointer_t priv);
/*! exit timer task, the task will be not called if have been not called
*
* @param timer the timer
* @param task the timer task
*/
tb_void_t tb_ltimer_task_exit(tb_ltimer_ref_t timer, tb_ltimer_task_ref_t task);
/*! kill timer task, the task will be called immediately if have been not called
*
* @param timer the timer
* @param task the timer task
*/
tb_void_t tb_ltimer_task_kill(tb_ltimer_ref_t timer, tb_ltimer_task_ref_t task);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/mach/ 0000775 0000000 0000000 00000000000 14671175054 0017012 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/platform/mach/dns.c 0000664 0000000 0000000 00000004625 14671175054 0017751 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file dns.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../file.h"
#include "../dynamic.h"
#include "../../libc/libc.h"
#include "../../stream/stream.h"
#include "../../network/network.h"
#include "../impl/dns.h"
#include
#include
#include
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the res_ninit func type
typedef tb_int_t (*tb_dns_res_ninit_func_t)(res_state);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
tb_bool_t tb_dns_init_env()
{
// done
tb_size_t count = 0;
tb_dynamic_ref_t library = tb_dynamic_init("libresolv.dylib");
if (library)
{
// the res_ninit func
tb_dns_res_ninit_func_t pres_ninit = (tb_dns_res_ninit_func_t)tb_dynamic_func(library, "res_9_ninit");
if (pres_ninit)
{
// init state
struct __res_state state;
if (!pres_ninit(&state))
{
// walk it
tb_size_t i = 0;
for (i = 0; i < state.nscount; i++, count++)
{
// the address
tb_char_t const* addr = inet_ntoa(state.nsaddr_list[i].sin_addr);
tb_assert_and_check_continue(addr);
// trace
tb_trace_d("addr: %s", addr);
// add address
tb_dns_server_add(addr);
}
}
}
}
// ok
return tb_true;
}
tb_void_t tb_dns_exit_env()
{
}
tbox-1.7.6/src/tbox/platform/mach/fwatcher_fsevent.c 0000664 0000000 0000000 00000032210 14671175054 0022511 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file fwatcher_fsevent.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../fwatcher.h"
#include "../file.h"
#include "../socket.h"
#include "../directory.h"
#include "../spinlock.h"
#include "../semaphore.h"
#include "../../libc/libc.h"
#include "../../container/container.h"
#include "../../algorithm/algorithm.h"
#if defined(TB_CONFIG_MODULE_HAVE_COROUTINE) \
&& !defined(TB_CONFIG_MICRO_ENABLE)
# include "../../coroutine/coroutine.h"
# include "../../coroutine/impl/impl.h"
#endif
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the watch item type
typedef struct __tb_fwatcher_item_t
{
FSEventStreamContext context;
FSEventStreamRef stream;
dispatch_queue_t fsevents_queue;
tb_char_t const* watchdir;
tb_bool_t recursion;
tb_fwatcher_ref_t fwatcher;
}tb_fwatcher_item_t;
// the fwatcher type
typedef struct __tb_fwatcher_t
{
tb_hash_map_ref_t watchitems;
tb_semaphore_ref_t semaphore;
tb_queue_ref_t events_queue;
tb_spinlock_t lock;
}tb_fwatcher_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_void_t tb_fwatcher_item_free(tb_element_ref_t element, tb_pointer_t buff)
{
tb_fwatcher_item_t* watchitem = (tb_fwatcher_item_t*)buff;
if (watchitem)
{
// exit stream
if (watchitem->stream)
{
FSEventStreamStop(watchitem->stream);
FSEventStreamInvalidate(watchitem->stream);
FSEventStreamRelease(watchitem->stream);
watchitem->stream = tb_null;
}
// exit dispatch queue
if (watchitem->fsevents_queue)
dispatch_release(watchitem->fsevents_queue);
watchitem->fsevents_queue = tb_null;
// reset watchdir
watchitem->watchdir = tb_null;
}
}
static tb_void_t tb_fwatcher_item_callback(ConstFSEventStreamRef stream, tb_pointer_t priv,
size_t events_count, tb_pointer_t event_paths, const FSEventStreamEventFlags event_flags[], FSEventStreamEventId const* event_id)
{
// check
tb_fwatcher_item_t* watchitem = (tb_fwatcher_item_t*)priv;
tb_assert_and_check_return(watchitem && watchitem->stream && watchitem->watchdir);
// get fwatcher
tb_fwatcher_t* fwatcher = (tb_fwatcher_t*)watchitem->fwatcher;
tb_assert_and_check_return(fwatcher && fwatcher->semaphore && fwatcher->events_queue);
// get events
size_t i;
tb_bool_t has_events = tb_false;
for (i = 0; i < events_count; ++i)
{
// get event
#if defined(HAVE_MACOS_GE_10_13)
CFDictionaryRef path_info_dict = (CFDictionaryRef)CFArrayGetValueAtIndex((CFArrayRef)event_paths, i);
CFStringRef path = (CFStringRef)CFDictionaryGetValue(path_info_dict, kFSEventStreamEventExtendedDataPathKey);
CFNumberRef cf_inode = (CFNumberRef)CFDictionaryGetValue(path_info_dict, kFSEventStreamEventExtendedFileIDKey);
unsigned long inode;
CFNumberGetValue(cf_inode, kCFNumberLongType, &inode);
tb_char_t const* filepath = CFStringGetCStringPtr(path, kCFStringEncodingUTF8);
#else
tb_char_t const* filepath = ((tb_char_t const**)event_paths)[i];
#endif
// get file path
FSEventStreamEventFlags flags = event_flags[i];
tb_fwatcher_event_t event;
if (filepath) tb_strlcpy(event.filepath, filepath, TB_PATH_MAXN);
else event.filepath[0] = '\0';
// we need filter file path if not recursion
tb_bool_t matched = tb_false;
if (watchitem->recursion)
matched = tb_true;
else
{
tb_char_t const* p = tb_strrchr(event.filepath, '/');
if (p && p - event.filepath == tb_strlen(watchitem->watchdir))
matched = tb_true;
}
tb_check_continue(matched);
// filter need events
if (flags & kFSEventStreamEventFlagItemCreated)
event.event = TB_FWATCHER_EVENT_CREATE;
else if (flags & kFSEventStreamEventFlagItemRemoved)
event.event = TB_FWATCHER_EVENT_DELETE;
else if (flags & kFSEventStreamEventFlagItemModified)
event.event = TB_FWATCHER_EVENT_MODIFY;
else if (flags & kFSEventStreamEventFlagItemRenamed)
{
// the parent directory is changed
event.event = TB_FWATCHER_EVENT_MODIFY;
tb_path_directory(filepath, event.filepath, TB_PATH_MAXN);
}
// add event to queue
if (event.event)
{
tb_spinlock_enter(&fwatcher->lock);
if (!tb_queue_full(fwatcher->events_queue))
tb_queue_put(fwatcher->events_queue, &event);
tb_spinlock_leave(&fwatcher->lock);
has_events = tb_true;
}
}
// notify events
if (has_events) tb_semaphore_post(fwatcher->semaphore, 1);
}
static tb_bool_t tb_fwatcher_item_init(tb_fwatcher_t* fwatcher, tb_char_t const* watchdir, tb_fwatcher_item_t* watchitem)
{
// check
tb_assert_and_check_return_val(fwatcher && watchdir && watchitem, tb_false);
// get path array
CFStringRef pathstr = CFStringCreateWithCString(tb_null, watchdir, kCFStringEncodingUTF8);
CFArrayRef path_array = CFArrayCreate(tb_null, (tb_cpointer_t*)&pathstr, 1, &kCFTypeArrayCallBacks);
// init context
FSEventStreamContext* context = &watchitem->context;
context->version = 0;
context->info = watchitem;
context->retain = tb_null;
context->release = tb_null;
context->copyDescription = tb_null;
// attach watchdir
watchitem->fwatcher = (tb_fwatcher_ref_t)fwatcher;
watchitem->watchdir = watchdir;
// create fsevent stream
FSEventStreamCreateFlags flags = kFSEventStreamCreateFlagFileEvents | kFSEventStreamCreateFlagNoDefer;
#if defined (HAVE_MACOS_GE_10_13)
flags |= kFSEventStreamCreateFlagUseExtendedData;
flags |= kFSEventStreamCreateFlagUseCFTypes;
#endif
watchitem->stream = FSEventStreamCreate(tb_null, tb_fwatcher_item_callback, context,
path_array, kFSEventStreamEventIdSinceNow, 0, flags);
// creating dispatch queue
watchitem->fsevents_queue = dispatch_queue_create("fswatch_event_queue", tb_null);
FSEventStreamSetDispatchQueue(watchitem->stream, watchitem->fsevents_queue);
// start stream
FSEventStreamStart(watchitem->stream);
// free path array
CFRelease(pathstr);
CFRelease(path_array);
return tb_true;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_fwatcher_ref_t tb_fwatcher_init()
{
tb_bool_t ok = tb_false;
tb_fwatcher_t* fwatcher = tb_null;
do
{
// init fwatcher
fwatcher = tb_malloc0_type(tb_fwatcher_t);
tb_assert_and_check_break(fwatcher);
// init watch items
fwatcher->watchitems = tb_hash_map_init(0, tb_element_str(tb_true), tb_element_mem(sizeof(tb_fwatcher_item_t), tb_fwatcher_item_free, tb_null));
tb_assert_and_check_break(fwatcher->watchitems);
// init events queue
fwatcher->events_queue = tb_queue_init(0, tb_element_mem(sizeof(tb_fwatcher_event_t), tb_null, tb_null));
tb_assert_and_check_break(fwatcher->events_queue);
// init semaphore
fwatcher->semaphore = tb_semaphore_init(0);
tb_assert_and_check_break(fwatcher->semaphore);
// init lock
tb_spinlock_init(&fwatcher->lock);
ok = tb_true;
} while (0);
if (!ok && fwatcher)
{
tb_fwatcher_exit((tb_fwatcher_ref_t)fwatcher);
fwatcher = tb_null;
}
return (tb_fwatcher_ref_t)fwatcher;
}
tb_void_t tb_fwatcher_exit(tb_fwatcher_ref_t self)
{
tb_fwatcher_t* fwatcher = (tb_fwatcher_t*)self;
if (fwatcher)
{
// exit watchitems
if (fwatcher->watchitems) tb_hash_map_exit(fwatcher->watchitems);
fwatcher->watchitems = tb_null;
// exit semaphore
if (fwatcher->semaphore) tb_semaphore_exit(fwatcher->semaphore);
fwatcher->semaphore = tb_null;
// exit events queue
if (fwatcher->events_queue) tb_queue_exit(fwatcher->events_queue);
fwatcher->events_queue = tb_null;
// exit lock
tb_spinlock_exit(&fwatcher->lock);
// wait watcher
tb_free(fwatcher);
fwatcher = tb_null;
}
}
tb_bool_t tb_fwatcher_add(tb_fwatcher_ref_t self, tb_char_t const* watchdir, tb_bool_t recursion)
{
tb_fwatcher_t* fwatcher = (tb_fwatcher_t*)self;
tb_assert_and_check_return_val(fwatcher && fwatcher->watchitems && watchdir, tb_false);
// file not found
tb_file_info_t info;
if (!tb_file_info(watchdir, &info) || info.type != TB_FILE_TYPE_DIRECTORY)
return tb_false;
// get real path, we need match file path from event callback
tb_char_t data[PATH_MAX];
tb_char_t const* watchdir_real = realpath(watchdir, data);
if (!watchdir_real) watchdir_real = watchdir;
// this path has been added?
tb_size_t itor = tb_hash_map_find(fwatcher->watchitems, watchdir_real);
if (itor != tb_iterator_tail(fwatcher->watchitems))
return tb_true;
// save watch item
tb_fwatcher_item_t watchitem;
tb_memset(&watchitem, 0, sizeof(tb_fwatcher_item_t));
watchitem.recursion = recursion;
return tb_hash_map_insert(fwatcher->watchitems, watchdir_real, &watchitem) != tb_iterator_tail(fwatcher->watchitems);
}
tb_bool_t tb_fwatcher_remove(tb_fwatcher_ref_t self, tb_char_t const* watchdir)
{
tb_fwatcher_t* fwatcher = (tb_fwatcher_t*)self;
tb_assert_and_check_return_val(fwatcher && fwatcher->watchitems && watchdir, tb_false);
// get real path, we need match file path from event callback
tb_char_t data[PATH_MAX];
tb_char_t const* watchdir_real = realpath(watchdir, data);
if (!watchdir_real) watchdir_real = watchdir;
// remove the watchitem
tb_hash_map_remove(fwatcher->watchitems, watchdir_real);
return tb_true;
}
tb_void_t tb_fwatcher_spak(tb_fwatcher_ref_t self)
{
tb_fwatcher_t* fwatcher = (tb_fwatcher_t*)self;
tb_assert_and_check_return(fwatcher && fwatcher->semaphore);
tb_semaphore_post(fwatcher->semaphore, 1);
}
tb_long_t tb_fwatcher_wait(tb_fwatcher_ref_t self, tb_fwatcher_event_t* event, tb_long_t timeout)
{
tb_fwatcher_t* fwatcher = (tb_fwatcher_t*)self;
tb_assert_and_check_return_val(fwatcher && fwatcher->semaphore && fwatcher->events_queue && event, -1);
#if defined(TB_CONFIG_MODULE_HAVE_COROUTINE) \
&& !defined(TB_CONFIG_MICRO_ENABLE)
// attempt to wait it in coroutine if timeout is non-zero
if (timeout && tb_coroutine_self())
{
tb_poller_object_t object;
object.type = TB_POLLER_OBJECT_FWATCHER;
object.ref.fwatcher = self;
return tb_coroutine_waitfs(&object, event, timeout);
}
#endif
// get it if has events
tb_bool_t has_events = tb_false;
tb_spinlock_enter(&fwatcher->lock);
if (!tb_queue_null(fwatcher->events_queue))
{
tb_fwatcher_event_t* e = (tb_fwatcher_event_t*)tb_queue_get(fwatcher->events_queue);
if (e)
{
*event = *e;
tb_queue_pop(fwatcher->events_queue);
has_events = tb_true;
}
}
tb_spinlock_leave(&fwatcher->lock);
tb_check_return_val(!has_events, 1);
// init watch items
tb_for_all(tb_hash_map_item_ref_t, item, fwatcher->watchitems)
{
// get watch item and path
tb_char_t const* watchdir = (tb_char_t const*)item->name;
tb_fwatcher_item_t* watchitem = (tb_fwatcher_item_t*)item->data;
tb_assert_and_check_return_val(watchitem && watchdir, -1);
// init watch item first
if (!watchitem->stream && !tb_fwatcher_item_init(fwatcher, watchdir, watchitem))
{
tb_trace_d("watch %s failed", watchdir);
return -1;
}
}
// wait events
tb_long_t wait = tb_semaphore_wait(fwatcher->semaphore, timeout);
tb_assert_and_check_return_val(wait >= 0, -1);
tb_check_return_val(wait > 0, 0);
// get event
tb_spinlock_enter(&fwatcher->lock);
if (!tb_queue_null(fwatcher->events_queue))
{
tb_fwatcher_event_t* e = (tb_fwatcher_event_t*)tb_queue_get(fwatcher->events_queue);
if (e)
{
*event = *e;
tb_queue_pop(fwatcher->events_queue);
has_events = tb_true;
}
}
tb_spinlock_leave(&fwatcher->lock);
return has_events? 1 : 0;
}
tbox-1.7.6/src/tbox/platform/mach/ios/ 0000775 0000000 0000000 00000000000 14671175054 0017604 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/platform/mach/ios/directory.m 0000664 0000000 0000000 00000004455 14671175054 0021776 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-2020, TBOOX Open Source Group.
*
* @author ruki
* @file directory.m
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../../directory.h"
#include "../../environment.h"
#import
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_directory_home(tb_char_t* path, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(path && maxn, 0);
// the documents
NSString* documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
tb_char_t const* cstr = [documents UTF8String];
tb_size_t size = [documents length];
if (documents)
{
// copy it
size = tb_min(size, maxn - 1);
tb_strncpy(path, cstr, size);
path[size] = '\0';
}
else
{
// get the home directory
size = tb_environment_first("HOME", path, maxn);
}
// ok?
return size;
}
tb_size_t tb_directory_temporary(tb_char_t* path, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(path && maxn > 4, 0);
// the temp
NSString* temp = NSTemporaryDirectory();
tb_char_t const* cstr = [temp UTF8String];
tb_size_t size = [temp length];
if (temp)
{
// copy it
size = tb_min(size, maxn - 1);
tb_strncpy(path, cstr, size);
path[size] = '\0';
}
else
{
// copy the default temporary directory
size = tb_strlcpy(path, "/tmp", maxn);
}
// ok?
return size;
}
tbox-1.7.6/src/tbox/platform/mach/ios/prefix.h 0000664 0000000 0000000 00000001651 14671175054 0021255 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
* @ingroup platform
*/
#ifndef TB_PLATFORM_MACH_IOS_PREFIX_H
#define TB_PLATFORM_MACH_IOS_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#endif
tbox-1.7.6/src/tbox/platform/mach/ios/print.c 0000664 0000000 0000000 00000003274 14671175054 0021112 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file print.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../../thread.h"
#include
#include
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_void_t tb_print(tb_char_t const* string)
{
// check
tb_check_return(string);
// print to the ios device log
os_log(OS_LOG_DEFAULT, "[%08x]: %s", (tb_uint32_t)tb_thread_self(), string);
// print to the stdout
fputs(string, stdout);
}
tb_void_t tb_printl(tb_char_t const* string)
{
// check
tb_check_return(string);
// print to the ios device log
os_log(OS_LOG_DEFAULT, "[%08x]: %s", (tb_uint32_t)tb_thread_self(), string);
// print string to the stdout
fputs(string, stdout);
// print newline to the stdout
fputs(__tb_newline__, stdout);
}
tb_void_t tb_print_sync()
{
// flush the stdout
fflush(stdout);
}
tbox-1.7.6/src/tbox/platform/mach/prefix.h 0000664 0000000 0000000 00000001735 14671175054 0020466 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
* @ingroup platform
*/
#ifndef TB_PLATFORM_MACH_PREFIX_H
#define TB_PLATFORM_MACH_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#include "../../libc/libc.h"
#include "../../utils/utils.h"
#endif
tbox-1.7.6/src/tbox/platform/mach/sched_affinity.c 0000664 0000000 0000000 00000012632 14671175054 0022141 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file sched_affinity.c
* @ingroup platform
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../sched.h"
#include
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_sched_setaffinity(tb_size_t pid, tb_cpuset_ref_t cpuset)
{
// check
tb_assert_and_check_return_val(cpuset, tb_false);
// get the first cpu core index
tb_int_t core = TB_CPUSET_FFS(cpuset);
// trace
tb_trace_d("setaffinity: core(%d) to pid(%zu)", core, pid);
// get port
mach_port_name_t port;
if (pid)
{
if (task_for_pid(mach_task_self(), (tb_int_t)pid, &port) != KERN_SUCCESS)
{
tb_trace_e("cannot get port for the gived pid(%zu)!", pid);
return tb_false;
}
}
else port = mach_task_self();
// get all threads
thread_act_t* threads = tb_null;
mach_msg_type_number_t thread_count = 0;
if (task_threads(port, &threads, &thread_count) != KERN_SUCCESS)
{
tb_trace_e("cannot get task threads for the gived pid(%lu)!", pid);
return tb_false;
}
tb_assert_and_check_return_val(threads && thread_count > 0, tb_false);
// suspend threads first
tb_size_t i;
thread_t thread_self = mach_thread_self();
mach_port_deallocate(mach_task_self(), thread_self);
for (i = 0; i < thread_count; i++)
{
if (threads[i] != MACH_PORT_NULL && threads[i] != thread_self)
thread_suspend(threads[i]);
}
// set affinity for all threads
tb_size_t ok = tb_true;
thread_affinity_policy_data_t policy;
for (i = 0; i < thread_count; i++)
{
if (threads[i] != MACH_PORT_NULL)
{
// TODO only set the first thread successfully now.
policy.affinity_tag = core;
if (thread_policy_set(threads[i], THREAD_AFFINITY_POLICY, (thread_policy_t)&policy, THREAD_AFFINITY_POLICY_COUNT) != KERN_SUCCESS)
ok = tb_false;
}
}
// resume threads
for (i = 0; i < thread_count; i++)
{
if (threads[i] != MACH_PORT_NULL && threads[i] != thread_self)
thread_suspend(threads[i]);
}
// free threads
for (i = 0; i < thread_count; i++)
{
if (threads[i] != MACH_PORT_NULL)
mach_port_deallocate(port, threads[i]);
}
mach_vm_deallocate(port, (mach_vm_address_t)threads, thread_count * sizeof(*threads));
return ok;
}
tb_bool_t tb_sched_getaffinity(tb_size_t pid, tb_cpuset_ref_t cpuset)
{
// check
tb_assert_and_check_return_val(cpuset, tb_false);
// get port
mach_port_name_t port;
if (pid)
{
if (task_for_pid(mach_task_self(), (tb_int_t)pid, &port) != KERN_SUCCESS)
{
tb_trace_e("cannot get port for the gived pid(%lu)!", pid);
return tb_false;
}
}
else port = mach_task_self();
// get all threads
thread_act_t* threads = tb_null;
mach_msg_type_number_t thread_count = 0;
if (task_threads(port, &threads, &thread_count) != KERN_SUCCESS)
{
tb_trace_e("cannot get task threads for the gived pid(%lu)!", pid);
return tb_false;
}
tb_assert_and_check_return_val(threads && thread_count > 0, tb_false);
// suspend threads first
tb_size_t i;
thread_t thread_self = mach_thread_self();
mach_port_deallocate(mach_task_self(), thread_self);
for (i = 0; i < thread_count; i++)
{
if (threads[i] != MACH_PORT_NULL && threads[i] != thread_self)
thread_suspend(threads[i]);
}
// set affinity for all threads
tb_size_t ok = tb_true;
TB_CPUSET_ZERO(cpuset);
for (i = 0; i < thread_count; i++)
{
if (threads[i] != MACH_PORT_NULL)
{
boolean_t get_default = tb_false;
mach_msg_type_number_t count = THREAD_AFFINITY_POLICY_COUNT;
thread_affinity_policy_data_t policy;
policy.affinity_tag = 0;
if (thread_policy_get(threads[i], THREAD_AFFINITY_POLICY, (thread_policy_t)&policy, &count, &get_default) == KERN_SUCCESS)
{
TB_CPUSET_SET(policy.affinity_tag, cpuset);
}
else ok = tb_false;
}
}
// resume threads
for (i = 0; i < thread_count; i++)
{
if (threads[i] != MACH_PORT_NULL && threads[i] != thread_self)
thread_suspend(threads[i]);
}
// free threads
for (i = 0; i < thread_count; i++)
{
if (threads[i] != MACH_PORT_NULL)
mach_port_deallocate(port, threads[i]);
}
mach_vm_deallocate(port, (mach_vm_address_t)threads, thread_count * sizeof(*threads));
return ok;
}
tbox-1.7.6/src/tbox/platform/mach/semaphore.c 0000664 0000000 0000000 00000010211 14671175054 0021134 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file semaphore.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include
#include
#include
#include
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the semaphore type
typedef struct __tb_semaphore_impl_t
{
// the semaphore
semaphore_t semaphore;
// the value
tb_atomic32_t value;
}tb_semaphore_impl_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_semaphore_ref_t tb_semaphore_init(tb_size_t init)
{
// done
tb_bool_t ok = tb_false;
tb_semaphore_impl_t* impl = tb_null;
do
{
// make semaphore
impl = tb_malloc0_type(tb_semaphore_impl_t);
tb_assert_and_check_break(impl);
// init semaphore
if (KERN_SUCCESS != semaphore_create(mach_task_self(), &(impl->semaphore), SYNC_POLICY_FIFO, init)) break;
// init value
tb_atomic32_init(&impl->value, (tb_int32_t)init);
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (impl) tb_semaphore_exit((tb_semaphore_ref_t)impl);
impl = tb_null;
}
// ok
return (tb_semaphore_ref_t)impl;
}
tb_void_t tb_semaphore_exit(tb_semaphore_ref_t semaphore)
{
tb_semaphore_impl_t* impl = (tb_semaphore_impl_t*)semaphore;
if (semaphore)
{
// exit semaphore
semaphore_destroy(mach_task_self(), impl->semaphore);
// exit it
tb_free(semaphore);
}
}
tb_bool_t tb_semaphore_post(tb_semaphore_ref_t semaphore, tb_size_t post)
{
// check
tb_semaphore_impl_t* impl = (tb_semaphore_impl_t*)semaphore;
tb_assert_and_check_return_val(semaphore && post, tb_false);
// post
while (post--)
{
// +2 first
tb_atomic32_fetch_and_add(&impl->value, 2);
// signal
if (KERN_SUCCESS != semaphore_signal(impl->semaphore))
{
// restore
tb_atomic32_fetch_and_sub(&impl->value, 2);
return tb_false;
}
// -1
tb_atomic32_fetch_and_sub(&impl->value, 1);
}
// ok
return tb_true;
}
tb_long_t tb_semaphore_value(tb_semaphore_ref_t semaphore)
{
// check
tb_semaphore_impl_t* impl = (tb_semaphore_impl_t*)semaphore;
tb_assert_and_check_return_val(semaphore, -1);
// get value
return (tb_long_t)tb_atomic32_get(&impl->value);
}
tb_long_t tb_semaphore_wait(tb_semaphore_ref_t semaphore, tb_long_t timeout)
{
// check
tb_semaphore_impl_t* impl = (tb_semaphore_impl_t*)semaphore;
tb_assert_and_check_return_val(semaphore, -1);
// init timespec
mach_timespec_t spec = {0};
if (timeout > 0)
{
spec.tv_sec += timeout / 1000;
spec.tv_nsec += (timeout % 1000) * 1000000;
}
else if (timeout < 0) spec.tv_sec += 12 * 30 * 24 * 3600; // infinity: one year
// wait
tb_long_t ok = semaphore_timedwait(impl->semaphore, spec);
// timeout or interrupted?
tb_check_return_val(ok != KERN_OPERATION_TIMED_OUT && ok != KERN_ABORTED, 0);
// ok?
tb_check_return_val(ok == KERN_SUCCESS, -1);
// check value
tb_assert_and_check_return_val((tb_long_t)tb_atomic32_get(&impl->value) > 0, -1);
// value--
tb_atomic32_fetch_and_sub(&impl->value, 1);
// ok
return 1;
}
tbox-1.7.6/src/tbox/platform/mach/thread_affinity.c 0000664 0000000 0000000 00000005043 14671175054 0022320 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file thread_affinity.c
* @ingroup platform
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../thread.h"
#include
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_thread_setaffinity(tb_thread_ref_t thread, tb_cpuset_ref_t cpuset)
{
// check
tb_assert_and_check_return_val(cpuset, tb_false);
// get mach thread
pthread_t pthread = thread? *((pthread_t*)thread) : pthread_self();
thread_port_t mach_thread = pthread_mach_thread_np(pthread);
tb_assert_and_check_return_val(mach_thread != MACH_PORT_NULL, tb_false);
// get the first cpu core index
tb_int_t core = TB_CPUSET_FFS(cpuset);
// set thread affinity
thread_affinity_policy_data_t policy;
policy.affinity_tag = core;
return thread_policy_set(mach_thread, THREAD_AFFINITY_POLICY, (thread_policy_t)&policy, THREAD_AFFINITY_POLICY_COUNT) == KERN_SUCCESS;
}
tb_bool_t tb_thread_getaffinity(tb_thread_ref_t thread, tb_cpuset_ref_t cpuset)
{
// check
tb_assert_and_check_return_val(cpuset, tb_false);
// get mach thread
pthread_t pthread = thread? *((pthread_t*)thread) : pthread_self();
thread_port_t mach_thread = pthread_mach_thread_np(pthread);
tb_assert_and_check_return_val(mach_thread != MACH_PORT_NULL, tb_false);
// get thread affinity
boolean_t get_default = tb_false;
mach_msg_type_number_t count = THREAD_AFFINITY_POLICY_COUNT;
thread_affinity_policy_data_t policy;
policy.affinity_tag = 0;
if (thread_policy_get(mach_thread, THREAD_AFFINITY_POLICY, (thread_policy_t)&policy, &count, &get_default) != KERN_SUCCESS)
return tb_false;
// save to cpuset
TB_CPUSET_ZERO(cpuset);
TB_CPUSET_SET(policy.affinity_tag, cpuset);
return tb_true;
}
tbox-1.7.6/src/tbox/platform/mutex.c 0000664 0000000 0000000 00000007156 14671175054 0017421 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file mutex.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "mutex.h"
#include "spinlock.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#ifdef TB_CONFIG_OS_WINDOWS
# include "windows/mutex.c"
#elif defined(TB_CONFIG_POSIX_HAVE_PTHREAD_MUTEX_INIT)
# include "posix/mutex.c"
#else
# include "impl/mutex.h"
tb_mutex_ref_t tb_mutex_init_impl(tb_mutex_t* mutex)
{
// init mutex, @note we cannot use asset/trace because them will use mutex
tb_assert_static(sizeof(tb_spinlock_t) == sizeof(tb_mutex_t));
return (mutex && tb_spinlock_init(mutex))? ((tb_mutex_ref_t)mutex) : tb_null;
}
tb_void_t tb_mutex_exit_impl(tb_mutex_t* mutex)
{
// exit it
if (mutex) tb_spinlock_exit(mutex);
}
tb_bool_t tb_mutex_enter_without_profiler(tb_mutex_ref_t mutex)
{
// check, @note we cannot use asset/trace because them will use mutex
tb_check_return_val(mutex, tb_false);
// enter
tb_spinlock_enter_without_profiler((tb_spinlock_ref_t)mutex);
return tb_true;
}
tb_bool_t tb_mutex_entry_try_without_profiler(tb_mutex_ref_t mutex)
{
// check, @note we cannot use asset/trace because them will use mutex
tb_check_return_val(mutex, tb_false);
// try to enter
return tb_spinlock_enter_try_without_profiler((tb_spinlock_ref_t)mutex);
}
tb_mutex_ref_t tb_mutex_init()
{
// done
tb_bool_t ok = tb_false;
tb_spinlock_ref_t lock = tb_null;
do
{
// make lock
lock = tb_malloc0_type(tb_spinlock_t);
tb_assert_and_check_break(lock);
// init lock
if (!tb_spinlock_init(lock)) break;
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
tb_free(lock);
lock = tb_null;
}
// ok?
return (tb_mutex_ref_t)lock;
}
tb_void_t tb_mutex_exit(tb_mutex_ref_t mutex)
{
// check
tb_assert_and_check_return(mutex);
// exit it
tb_spinlock_ref_t lock = (tb_spinlock_ref_t)mutex;
if (lock)
{
// exit lock
tb_spinlock_exit(lock);
// free it
tb_free(lock);
}
}
tb_bool_t tb_mutex_enter(tb_mutex_ref_t mutex)
{
// check, @note we cannot use asset/trace because them will use mutex
tb_check_return_val(mutex, tb_false);
// enter
tb_spinlock_enter((tb_spinlock_ref_t)mutex);
return tb_true;
}
tb_bool_t tb_mutex_enter_try(tb_mutex_ref_t mutex)
{
// check, @note we cannot use asset/trace because them will use mutex
tb_check_return_val(mutex, tb_false);
// try to enter
return tb_spinlock_enter_try((tb_spinlock_ref_t)mutex);
}
tb_bool_t tb_mutex_leave(tb_mutex_ref_t mutex)
{
// check, @note we cannot use asset/trace because them will use mutex
tb_check_return_val(mutex, tb_false);
// leave
tb_spinlock_leave((tb_spinlock_ref_t)mutex);
return tb_true;
}
#endif
tbox-1.7.6/src/tbox/platform/mutex.h 0000664 0000000 0000000 00000003651 14671175054 0017422 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file mutex.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_MUTEX_H
#define TB_PLATFORM_MUTEX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init mutex
*
* @return the mutex
*/
tb_mutex_ref_t tb_mutex_init(tb_noarg_t);
/* exit mutex
*
* @param mutex the mutex
*/
tb_void_t tb_mutex_exit(tb_mutex_ref_t mutex);
/* enter mutex
*
* @param mutex the mutex
*
* @return tb_true or tb_false
*/
tb_bool_t tb_mutex_enter(tb_mutex_ref_t mutex);
/* try to enter mutex
*
* @param mutex the mutex
*
* @return tb_true or tb_false
*/
tb_bool_t tb_mutex_enter_try(tb_mutex_ref_t mutex);
/* leave mutex
*
* @param mutex the mutex
*
* @return tb_true or tb_false
*/
tb_bool_t tb_mutex_leave(tb_mutex_ref_t mutex);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/native_memory.c 0000664 0000000 0000000 00000002104 14671175054 0021121 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file native_memory.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "native_memory.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#ifdef TB_CONFIG_OS_WINDOWS
# include "windows/native_memory.c"
#else
# include "libc/native_memory.c"
#endif
tbox-1.7.6/src/tbox/platform/native_memory.h 0000664 0000000 0000000 00000005536 14671175054 0021142 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file native_memory.h
* @defgroup platform
*
*/
#ifndef TB_PLATFORM_NATIVE_MEMORY_H
#define TB_PLATFORM_NATIVE_MEMORY_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init native memory
*
* @note
* need support to be called repeatly
*
* @return tb_true or tb_false
*/
tb_bool_t tb_native_memory_init(tb_noarg_t);
/// exit native memory
tb_void_t tb_native_memory_exit(tb_noarg_t);
/*! malloc the native memory
*
* @param size the size
*
* @return the data address
*/
tb_pointer_t tb_native_memory_malloc(tb_size_t size);
/*! malloc the native memory and fill zero
*
* @param size the size
*
* @return the data address
*/
tb_pointer_t tb_native_memory_malloc0(tb_size_t size);
/*! malloc the native memory with the item count
*
* @param item the item count
* @param size the item size
*
* @return the data address
*/
tb_pointer_t tb_native_memory_nalloc(tb_size_t item, tb_size_t size);
/*! malloc the native memory with the item count and fill zero
*
* @param item the item count
* @param size the item size
*
* @return the data address
*/
tb_pointer_t tb_native_memory_nalloc0(tb_size_t item, tb_size_t size);
/*! realloc the native memory
*
* @param data the data address
* @param size the size
*
* @return the new data address
*/
tb_pointer_t tb_native_memory_ralloc(tb_pointer_t data, tb_size_t size);
/*! free the native memory
*
* @param data the data address
*
* @return tb_true or tb_false
*/
tb_bool_t tb_native_memory_free(tb_pointer_t data);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/page.c 0000664 0000000 0000000 00000002550 14671175054 0017164 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file page.c
* @ingroup platform
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "page"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#include "page.h"
#ifdef TB_CONFIG_OS_WINDOWS
# include "windows/page.c"
#elif defined(TB_CONFIG_POSIX_HAVE_GETPAGESIZE) || \
defined(TB_CONFIG_POSIX_HAVE_SYSCONF)
# include "posix/page.c"
#else
tb_bool_t tb_page_init()
{
return tb_true;
}
tb_void_t tb_page_exit()
{
}
tb_size_t tb_page_size()
{
// default: 4KB
return 4096;
}
#endif
tbox-1.7.6/src/tbox/platform/page.h 0000664 0000000 0000000 00000003134 14671175054 0017170 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file page.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_PAGE_H
#define TB_PLATFORM_PAGE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init page
*
* @note
* need support to be called repeatly
*
* @return tb_true or tb_false
*/
tb_bool_t tb_page_init(tb_noarg_t);
/*! exit page
*
*/
tb_void_t tb_page_exit(tb_noarg_t);
/*! get page size
*
* @return the page size
*/
tb_size_t tb_page_size(tb_noarg_t);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/path.c 0000664 0000000 0000000 00000035351 14671175054 0017211 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @path path.c
* @ingroup platform
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "path"
#define TB_TRACE_MODULE_DEBUG (0)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "path.h"
#include "directory.h"
#include "../libc/libc.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the path separator
#if defined(TB_CONFIG_OS_WINDOWS) && !defined(TB_COMPILER_LIKE_UNIX)
# define TB_PATH_SEPARATOR '\\'
#else
# define TB_PATH_SEPARATOR '/'
#endif
// is path separator?
#if defined(TB_CONFIG_OS_WINDOWS) && !defined(TB_COMPILER_LIKE_UNIX)
# define tb_path_is_sep(c) ('/' == (c) || '\\' == (c))
#else
# define tb_path_is_sep(c) ('/' == (c))
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#ifndef TB_CONFIG_MICRO_ENABLE
tb_size_t tb_path_translate(tb_char_t* path, tb_size_t size, tb_size_t maxn, tb_bool_t normalize)
{
return tb_path_translate_to(path, size, path, maxn, normalize);
}
tb_size_t tb_path_translate_to(tb_char_t const* path, tb_size_t size, tb_char_t* data, tb_size_t maxn, tb_bool_t normalize)
{
// check
tb_assert_and_check_return_val(path, 0);
// file://?
tb_char_t home[TB_PATH_MAXN];
tb_char_t const* p = path;
if (!tb_strnicmp(p, "file:", 5)) p += 5;
// is user directory?
else if (path[0] == '~')
{
// get the home directory
tb_size_t home_size = tb_directory_home(home, sizeof(home));
tb_assert_and_check_return_val(home_size, 0);
// check the path space
tb_size_t path_size = size? size : tb_strlen(path);
tb_assert_and_check_return_val(home_size + path_size - 1 < maxn, 0);
/* move the path and ensure the enough space for the home directory
*
* @note maybe path and data are same address
*/
tb_memcpy(home + home_size, path + 1, path_size - 1);
home[home_size + path_size - 1] = '\0';
size = home_size + path_size - 1;
// switch home as path source
path = home;
p = home;
}
if (!size) size = tb_strlen(path);
// copy root path
tb_char_t* dst = data;
tb_char_t const* src = p;
#ifdef TB_CONFIG_OS_WINDOWS
// e.g. c:/
if (tb_isalpha(src[0]) && src[1] == ':')
{
*(dst++) = src[0];
*(dst++) = ':';
src += 2;
}
// UNC path, e.g. `\\wsl.localhost`
else if (src[0] == '\\' && src[1] == '\\' && (tb_isalpha(src[2]) || tb_isdigit(src[2])))
{
*(dst++) = src[0];
*(dst++) = src[1];
src += 2;
}
// dos device path, e.g. `\\.\`, `\\?\`
else if (src[0] == '\\' && src[1] == '\\' && (src[2] == '.' || src[2] == '?') && src[3] == '\\')
{
*(dst++) = src[0];
*(dst++) = src[1];
*(dst++) = src[2];
*(dst++) = src[3];
src += 4;
}
// the absolute path on the root path of the current drive, e.g. `\Program files`
else if (src[0] == '\\' && src[1] != '\\')
{
*(dst++) = src[0];
src += 1;
}
#endif
tb_char_t const* src_root = src;
tb_char_t const* dst_root = dst;
if (tb_path_is_sep(*src))
{
++src;
*(dst++) = TB_PATH_SEPARATOR;
}
#define tb_path_is_end(__p) (__p >= src_end || (*__p) == '\0')
#define tb_path_is_sep_or_end(__p) (tb_path_is_end(__p) || tb_path_is_sep(*__p))
tb_char_t const* src_end = path + size;
tb_long_t folder_depth = 0;
while (!tb_path_is_end(src))
{
// reduce repeat separators and "/./" => "/"
while (tb_path_is_sep(*src) ||
(normalize && &src[-1] >= src_root && tb_path_is_sep(src[-1]) && src[0] == '.' && tb_path_is_sep_or_end(&src[1])))
++src;
if (tb_path_is_end(src))
break;
// reduce "foo/bar/../" => "foo"
if (normalize && src[0] == '.' && src[1] == '.' && tb_path_is_sep_or_end(&src[2]))
{
if (folder_depth > 0)
{
while (--dst != dst_root && !tb_path_is_sep(dst[-1]));
--folder_depth;
}
else if (&dst[-1] != dst_root || !tb_path_is_sep(dst[-1]))
{
/* "/foo/../.." => "/"
* "foo/../.." => "../"
*/
*(dst++) = '.';
*(dst++) = '.';
*(dst++) = TB_PATH_SEPARATOR;
}
src += 3;
}
else
{
while (!tb_path_is_sep_or_end(src))
*(dst++) = *(src++);
if (tb_path_is_sep(*src))
{
*(dst++) = TB_PATH_SEPARATOR;
++src;
++folder_depth;
}
}
}
#undef tb_path_is_end
#undef tb_path_is_sep_or_end
// remove the tail separator and not root: '/'
while (dst > data + 1 && tb_path_is_sep(dst[-1]))
--dst;
*dst = '\0';
tb_trace_d("translate: %s", data);
return dst - data;
}
#endif
tb_bool_t tb_path_is_absolute(tb_char_t const* path)
{
// check
tb_assert_and_check_return_val(path, tb_false);
#ifdef TB_CONFIG_OS_WINDOWS
// @see https://learn.microsoft.com/zh-cn/dotnet/standard/io/file-path-formats
return ( path[0] == '~'
|| path[0] == '\\' // The absolute path on the root path of the current drive, e.g. `\Program files`
|| (path[0] == '\\' && path[1] == '\\' && (tb_isalpha(path[2]) || tb_isdigit(path[2]))) // UNC path, e.g. `\\Server2\Share\Test\Foo.txt`
|| (path[0] == '\\' && path[1] == '\\' && (path[2] == '.' || path[2] == '?') && path[3] == '\\') // dos device path, e.g. `\\.\`, `\\?\`
# ifdef TB_COMPILER_LIKE_UNIX
|| path[0] == '/'
|| path[0] == '\\'
|| !tb_strnicmp(path, "file:", 5)
# endif
|| (tb_isalpha(path[0]) && path[1] == ':'));
#else
return ( path[0] == '/'
|| path[0] == '\\'
|| path[0] == '~'
|| !tb_strnicmp(path, "file:", 5));
#endif
}
tb_char_t const* tb_path_absolute(tb_char_t const* path, tb_char_t* data, tb_size_t maxn)
{
return tb_path_absolute_to(tb_null, path, data, maxn);
}
tb_char_t const* tb_path_absolute_to(tb_char_t const* root, tb_char_t const* path, tb_char_t* data, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(path && data && maxn, tb_null);
// trace
tb_trace_d("path: %s", path);
// empty path?
tb_check_return_val(path[0], tb_null);
#ifdef TB_CONFIG_MICRO_ENABLE
// the path is absolute?
if (tb_path_is_absolute(path)) return path;
// trace
tb_trace_e("absolute to %s to %s failed!", path, root);
return tb_null;
#else
// the path is absolute?
if (tb_path_is_absolute(path))
return tb_path_translate_to(path, 0, data, maxn, tb_false)? data : tb_null;
// get the root directory
tb_size_t size = 0;
if (root)
{
// copy it
size = tb_strlcpy(data, root, maxn);
tb_assert_and_check_return_val(size < maxn, tb_null);
}
else
{
// get the current directory
if (!(size = tb_directory_current(data, maxn))) return tb_null;
}
// translate the root directory
size = tb_path_translate(data, size, maxn, tb_false);
// trace
tb_trace_d("root: %s, size: %lu", data, size);
// is windows path? skip the drive prefix
tb_char_t* absolute = data;
if (size > 2 && tb_isalpha(absolute[0]) && absolute[1] == ':' && absolute[2] == TB_PATH_SEPARATOR)
{
// skip it
absolute += 2;
size -= 2;
}
// path => data
tb_char_t const* p = path;
tb_char_t const* t = p;
tb_char_t* q = absolute + size;
tb_char_t const* e = absolute + maxn - 1;
while (1)
{
if (tb_path_is_sep(*p) || !*p)
{
// the item size
tb_size_t n = p - t;
// ..? remove item
if (n == 2 && t[0] == '.' && t[1] == '.')
{
// find the last separator
for (; q > absolute && *q != TB_PATH_SEPARATOR; q--) ;
// strip it
*q = '\0';
}
// .? continue it
else if (n == 1 && t[0] == '.') ;
// append item
else if (n && q + 1 + n < e)
{
// append separator
*q++ = TB_PATH_SEPARATOR;
// append item
tb_strncpy(q, t, n);
q += n;
// strip it
*q = '\0';
}
// empty item? remove repeat
else if (!n) ;
// too small?
else
{
// trace
tb_trace_e("the data path is too small for %s", path);
return tb_null;
}
// break
tb_check_break(*p);
// next
t = p + 1;
}
// next
p++;
}
// end
if (q > absolute) *q = '\0';
// root?
else
{
*q++ = TB_PATH_SEPARATOR;
*q = '\0';
}
// trace
tb_trace_d("absolute: %s", data);
// ok?
return data;
#endif
}
#ifndef TB_CONFIG_MICRO_ENABLE
tb_char_t const* tb_path_relative(tb_char_t const* path, tb_char_t* data, tb_size_t maxn)
{
return tb_path_relative_to(tb_null, path, data, maxn);
}
tb_char_t const* tb_path_relative_to(tb_char_t const* root, tb_char_t const* path, tb_char_t* data, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(path && data && maxn, tb_null);
// trace
tb_trace_d("path: %s", path);
// the root is the current and the path is absolute? return path directly
if (!root && !tb_path_is_absolute(path))
return tb_path_translate_to(path, 0, data, maxn, tb_false)? data : tb_null;
// get the absolute path
tb_size_t path_size = 0;
tb_char_t path_absolute[TB_PATH_MAXN];
tb_size_t path_maxn = sizeof(path_absolute);
path = tb_path_absolute(path, path_absolute, path_maxn);
tb_check_return_val(path, tb_null);
path_size = tb_strlen(path);
tb_assert_and_check_return_val(path && path_size && path_size < path_maxn, tb_null);
// trace
tb_trace_d("path_absolute: %s", path);
// get the absolute root
tb_size_t root_size = 0;
tb_char_t root_absolute[TB_PATH_MAXN];
tb_size_t root_maxn = sizeof(root_absolute);
if (root)
{
// get the absolute root
root = tb_path_absolute(root, root_absolute, root_maxn);
root_size = tb_strlen(root);
}
else
{
// get the current directory
if (!(root_size = tb_directory_current(root_absolute, root_maxn))) return tb_null;
// translate it
if (!(root_size = tb_path_translate(root_absolute, root_size, root_maxn, tb_false))) return tb_null;
root = root_absolute;
}
tb_assert_and_check_return_val(root && root_size && root_size < root_maxn, tb_null);
// trace
tb_trace_d("root_absolute: %s", root);
// same directory? return "."
if (path_size == root_size && !tb_strncmp(path, root, root_size))
{
// check
tb_assert_and_check_return_val(maxn >= 2, ".");
// return "."
data[0] = '.';
data[1] = '\0';
return data;
}
// append separator
if (path_size + 1 < path_maxn)
{
path_absolute[path_size++] = TB_PATH_SEPARATOR;
path_absolute[path_size] = '\0';
}
if (root_size + 1 < root_maxn)
{
root_absolute[root_size++] = TB_PATH_SEPARATOR;
root_absolute[root_size] = '\0';
}
// trace
tb_trace_d("path: %s, root: %s", path_absolute, root_absolute);
// find the common leading directory
tb_char_t const* p = path_absolute;
tb_char_t const* q = root_absolute;
tb_long_t last = -1;
for (; *p && *q && *p == *q; q++, p++)
{
// save the last separator
if (*p == TB_PATH_SEPARATOR) last = q - root_absolute;
}
// is different directory or outside the windows drive root? using the absolute path
if (last <= 0 || (last == 2 && root_absolute[1] == ':' && root_size > 3))
{
// trace
tb_trace_d("no common root: %d", last);
// the path size
tb_size_t size = tb_min(path_size - 1, maxn);
// copy it
tb_strncpy(data, path, size);
data[size] = '\0';
}
// exists same root?
else
{
// count the remaining levels in root
tb_size_t count = 0;
tb_char_t const* l = root_absolute + last + 1;
for (; *l; l++)
{
if (*l == TB_PATH_SEPARATOR) count++;
}
// append "../" or "..\\"
tb_char_t* d = data;
tb_char_t* e = data + maxn;
while (count--)
{
if (d + 3 < e)
{
d[0] = '.';
d[1] = '.';
d[2] = TB_PATH_SEPARATOR;
d += 3;
}
}
// append the left path
l = path_absolute + last + 1;
while (*l && d < e) *d++ = *l++;
// remove the last separator
if (d > data) d--;
// end
*d = '\0';
}
// trace
tb_trace_d("relative: %s", data);
// ok?
return data;
}
#endif
tb_char_t const* tb_path_directory(tb_char_t const* path, tb_char_t* data, tb_size_t maxn)
{
tb_assert_and_check_return_val(path && data && maxn, tb_null);
tb_size_t n = tb_strlen(path);
tb_char_t const* e = path + n;
tb_char_t const* p = e - 1;
while (p >= path && *p && tb_path_is_sep(*p)) p--;
while (p >= path && *p && !tb_path_is_sep(*p)) p--;
if (p >= path)
{
if ((p == path || !tb_path_is_sep(*p)) && p < e) p++;
n = p - path;
if (n && n < maxn)
{
tb_strncpy(data, path, n);
data[n] = '\0';
return data;
}
else return tb_null;
}
return (n && path[0] != '.' && !tb_path_is_absolute(path))? "." : tb_null;
}
tbox-1.7.6/src/tbox/platform/path.h 0000664 0000000 0000000 00000010462 14671175054 0017212 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @path path.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_PATH_H
#define TB_PLATFORM_PATH_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// the path maximum
#define TB_PATH_MAXN (4096)
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! translate and normalize the path
*
* @param path the path
* @param size the path size, optional
* @param maxn the path maxn
* @param mode the translate mode
*
* @return the real path size
*/
tb_size_t tb_path_translate(tb_char_t* path, tb_size_t size, tb_size_t maxn, tb_bool_t normalize);
/*! translate and normalize the path to the given destinate path
*
* basic:
* - transform the path separator
* - expand the user directory with the prefix: ~
* - remove tail separator
* - reduce the repeat path separator, "////" => "/"
*
* normalize:
* - reduce "././" => "."
* - reduce "/xxx/.." => "/"
*
* @param path the path
* @param size the path size, optional
* @param data the data
* @param maxn the data maxn
* @param mode the translate mode
*
* @return the real path size
*/
tb_size_t tb_path_translate_to(tb_char_t const* path, tb_size_t size, tb_char_t* data, tb_size_t maxn, tb_bool_t normalize);
/*! the path is absolute?
*
* @param path the path
*
* @return tb_true or tb_false
*/
tb_bool_t tb_path_is_absolute(tb_char_t const* path);
/*! get the absolute path which relative to the current directory
*
* @param path the path
* @param data the path data
* @param maxn the path maxn
*
* @return the absolute path
*/
tb_char_t const* tb_path_absolute(tb_char_t const* path, tb_char_t* data, tb_size_t maxn);
/*! get the absolute path which relative to the given root directory
*
* @param root the root path
* @param path the path
* @param data the path data
* @param maxn the path maxn
*
* @return the absolute path
*/
tb_char_t const* tb_path_absolute_to(tb_char_t const* root, tb_char_t const* path, tb_char_t* data, tb_size_t maxn);
/*! get the path which relative to the current directory
*
* @param path the path
* @param data the path data
* @param maxn the path maxn
*
* @return the relative path
*/
tb_char_t const* tb_path_relative(tb_char_t const* path, tb_char_t* data, tb_size_t maxn);
/*! get the path which relative to the given root directory
*
* @param root the root path
* @param path the path
* @param data the path data
* @param maxn the path maxn
*
* @return the relative path
*/
tb_char_t const* tb_path_relative_to(tb_char_t const* root, tb_char_t const* path, tb_char_t* data, tb_size_t maxn);
/*! get the directory of path
*
* @param path the path
* @param data the path data
* @param maxn the path maxn
*
* @return the directory of path
*/
tb_char_t const* tb_path_directory(tb_char_t const* path, tb_char_t* data, tb_size_t maxn);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/pipe.c 0000664 0000000 0000000 00000007161 14671175054 0017210 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file pipe.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "pipe"
#define TB_TRACE_MODULE_DEBUG (1)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "pipe.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_OS_WINDOWS)
# include "windows/pipe.c"
#elif defined(TB_CONFIG_POSIX_HAVE_PIPE) || \
defined(TB_CONFIG_POSIX_HAVE_PIPE2) || \
defined(TB_CONFIG_POSIX_HAVE_MKFIFO)
# include "posix/pipe.c"
#else
tb_pipe_file_ref_t tb_pipe_file_init(tb_char_t const* name, tb_size_t mode, tb_size_t buffer_size)
{
tb_trace_noimpl();
return tb_null;
}
tb_bool_t tb_pipe_file_init_pair(tb_pipe_file_ref_t pair[2], tb_size_t mode[2], tb_size_t buffer_size)
{
tb_trace_noimpl();
return tb_false;
}
tb_bool_t tb_pipe_file_exit(tb_pipe_file_ref_t file)
{
tb_trace_noimpl();
return tb_false;
}
tb_long_t tb_pipe_file_read(tb_pipe_file_ref_t file, tb_byte_t* data, tb_size_t size)
{
tb_trace_noimpl();
return -1;
}
tb_long_t tb_pipe_file_write(tb_pipe_file_ref_t file, tb_byte_t const* data, tb_size_t size)
{
tb_trace_noimpl();
return -1;
}
tb_long_t tb_pipe_file_wait(tb_pipe_file_ref_t file, tb_size_t events, tb_long_t timeout)
{
tb_trace_noimpl();
return -1;
}
tb_long_t tb_pipe_file_connect(tb_pipe_file_ref_t file)
{
tb_trace_noimpl();
return -1;
}
#endif
tb_bool_t tb_pipe_file_bread(tb_pipe_file_ref_t file, tb_byte_t* data, tb_size_t size)
{
// read data
tb_size_t read = 0;
tb_long_t wait = 0;
while (read < size)
{
// read it
tb_long_t real = tb_pipe_file_read(file, data + read, tb_min(size - read, 8192));
// has data?
if (real > 0)
{
read += real;
wait = 0;
}
// no data? wait it
else if (!real && !wait)
{
// wait it
wait = tb_pipe_file_wait(file, TB_PIPE_EVENT_READ, -1);
tb_check_break(wait > 0);
}
// failed or end?
else break;
}
return read == size;
}
tb_bool_t tb_pipe_file_bwrit(tb_pipe_file_ref_t file, tb_byte_t const* data, tb_size_t size)
{
// writ data
tb_size_t writ = 0;
tb_long_t wait = 0;
while (writ < size)
{
// write it
tb_long_t real = tb_pipe_file_write(file, data + writ, tb_min(size - writ, 8192));
// has data?
if (real > 0)
{
writ += real;
wait = 0;
}
// no data? wait it
else if (!real && !wait)
{
// wait it
wait = tb_pipe_file_wait(file, TB_PIPE_EVENT_WRIT, -1);
tb_check_break(wait > 0);
}
// failed or end?
else break;
}
return writ == size;
}
tbox-1.7.6/src/tbox/platform/pipe.h 0000664 0000000 0000000 00000011452 14671175054 0017213 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file pipe.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_PIPE_H
#define TB_PLATFORM_PIPE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "socket.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the pipe file ref type
typedef __tb_typeref__(pipe_file);
/// the pipe mode type
typedef enum __tb_pipe_mode_t
{
TB_PIPE_MODE_RO = 1 //!< read only
, TB_PIPE_MODE_WO = 2 //!< write only
, TB_PIPE_MODE_BLOCK = 4 //!< block mode
}tb_pipe_mode_t;
/// the pipe file event enum
typedef enum __tb_event_event_e
{
TB_PIPE_EVENT_NONE = TB_SOCKET_EVENT_NONE
, TB_PIPE_EVENT_CONN = TB_SOCKET_EVENT_CONN
, TB_PIPE_EVENT_READ = TB_SOCKET_EVENT_RECV
, TB_PIPE_EVENT_WRIT = TB_SOCKET_EVENT_SEND
}tb_pipe_event_e;
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init the file of named pipe
*
* @note the pipe files will be inherited in child process and it will be blocked.
*
* @param name the pipe name
* @param mode the pipe mode
* @param buffer_size the buffer size of pipe, it will use the default size if pass zero
*
* @return the pipe file
*/
tb_pipe_file_ref_t tb_pipe_file_init(tb_char_t const* name, tb_size_t mode, tb_size_t buffer_size);
/*! init the file pair of anonymous pipe
*
* @note the pipe files will be inherited in child process.
*
* @param pair the pipe file pair, read: pair[0], write: pair[1]
* @param mode the pipe mode pair, only support TB_PIPE_MODE_BLOCK
* @param buffer_size the buffer size of pipe, it will use the default size if pass zero
*
* @return tb_true or tb_false
*/
tb_bool_t tb_pipe_file_init_pair(tb_pipe_file_ref_t pair[2], tb_size_t mode[2], tb_size_t buffer_size);
/*! exit the pipe file
*
* @param file the pipe file
*
* @return tb_true or tb_false
*/
tb_bool_t tb_pipe_file_exit(tb_pipe_file_ref_t file);
/*! connect the given named pipe file on server side
*
* @param file the pipe file
*
* @return ok: 1, continue: 0; failed: -1
*/
tb_long_t tb_pipe_file_connect(tb_pipe_file_ref_t file);
/*! read the pipe file data (non-block)
*
* @param file the pipe file
* @param data the data
* @param size the size
*
* @return the real size or -1
*/
tb_long_t tb_pipe_file_read(tb_pipe_file_ref_t file, tb_byte_t* data, tb_size_t size);
/*! writ the pipe file data (non-block)
*
* @param file the file
* @param data the data
* @param size the size
*
* @return the real size or -1
*/
tb_long_t tb_pipe_file_write(tb_pipe_file_ref_t file, tb_byte_t const* data, tb_size_t size);
/*! wait the pipe file events
*
* @param file the file
* @param events the pipe file events
* @param timeout the timeout, infinity: -1
*
* @return > 0: the events code, 0: timeout, -1: failed
*/
tb_long_t tb_pipe_file_wait(tb_pipe_file_ref_t file, tb_size_t events, tb_long_t timeout);
/*! read the pipe file data for tcp with block mode
*
* @param file the pipe file
* @param data the data
* @param size the size
*
* @return tb_true or tb_false
*/
tb_bool_t tb_pipe_file_bread(tb_pipe_file_ref_t file, tb_byte_t* data, tb_size_t size);
/*! writ the pipe file data for tcp with block mode
*
* @param file the pipe file
* @param data the data
* @param size the size
*
* @return tb_true or tb_false
*/
tb_bool_t tb_pipe_file_bwrit(tb_pipe_file_ref_t file, tb_byte_t const* data, tb_size_t size);
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/platform.h 0000664 0000000 0000000 00000003334 14671175054 0020102 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file platform.h
* @defgroup platform
*
*/
#ifndef TB_PLATFORM_H
#define TB_PLATFORM_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "cpu.h"
#include "page.h"
#include "path.h"
#include "file.h"
#include "time.h"
#include "pipe.h"
#include "mutex.h"
#include "event.h"
#include "timer.h"
#include "print.h"
#include "ltimer.h"
#include "socket.h"
#include "thread.h"
#include "atomic.h"
#include "poller.h"
#include "context.h"
#include "ifaddrs.h"
#include "dynamic.h"
#include "process.h"
#include "stdfile.h"
#include "fwatcher.h"
#include "filelock.h"
#include "syserror.h"
#include "addrinfo.h"
#include "spinlock.h"
#include "hostname.h"
#include "semaphore.h"
#include "backtrace.h"
#include "directory.h"
#include "exception.h"
#include "cache_time.h"
#include "environment.h"
#include "thread_pool.h"
#include "thread_local.h"
#include "native_memory.h"
#include "virtual_memory.h"
#ifdef TB_CONFIG_API_HAVE_DEPRECATED
# include "deprecated/deprecated.h"
#endif
#endif
tbox-1.7.6/src/tbox/platform/poller.c 0000664 0000000 0000000 00000026736 14671175054 0017561 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file poller.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* trace
*/
#define TB_TRACE_MODULE_NAME "poller"
#define TB_TRACE_MODULE_DEBUG (1)
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "poller.h"
#include "time.h"
#include "impl/poller.h"
#include "impl/pollerdata.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
#if defined(TB_CONFIG_OS_WINDOWS)
# ifndef TB_CONFIG_MICRO_ENABLE
# include "windows/poller_iocp.c"
# define TB_POLLER_ENABLE_IOCP
# else
# include "posix/poller_select.c"
# define TB_POLLER_ENABLE_SELECT
# endif
#elif defined(TB_CONFIG_POSIX_HAVE_EPOLL_CREATE) \
&& defined(TB_CONFIG_POSIX_HAVE_EPOLL_WAIT)
# include "linux/poller_epoll.c"
# define TB_POLLER_ENABLE_EPOLL
#elif defined(TB_CONFIG_OS_MACOSX) || defined(TB_CONFIG_OS_BSD)
# include "bsd/poller_kqueue.c"
# define TB_POLLER_ENABLE_KQUEUE
#elif defined(TB_CONFIG_POSIX_HAVE_POLL) && !defined(TB_CONFIG_MICRO_ENABLE) /* TODO remove vector for supporting the micro mode */
# include "posix/poller_poll.c"
# define TB_POLLER_ENABLE_POLL
#elif defined(TB_CONFIG_POSIX_HAVE_SELECT)
# include "posix/poller_select.c"
# define TB_POLLER_ENABLE_SELECT
#endif
#ifndef TB_CONFIG_MICRO_ENABLE
# if defined(TB_CONFIG_OS_WINDOWS)
# include "windows/poller_process.c"
# define TB_POLLER_ENABLE_PROCESS
# elif defined(TB_CONFIG_POSIX_HAVE_WAITPID) && defined(TB_CONFIG_LIBC_HAVE_SIGNAL)
# include "posix/poller_process.c"
# define TB_POLLER_ENABLE_PROCESS
# endif
#endif
#ifndef TB_CONFIG_MICRO_ENABLE
# if defined(TB_CONFIG_OS_WINDOWS) || \
defined(TB_CONFIG_LINUX_HAVE_INOTIFY_INIT) || \
defined(TB_CONFIG_OS_MACOSX) || \
defined(TB_CONFIG_OS_BSD)
# include "impl/poller_fwatcher.c"
# define TB_POLLER_ENABLE_FWATCHER
# endif
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_poller_ref_t tb_poller_init(tb_cpointer_t priv)
{
tb_bool_t ok = tb_false;
tb_poller_t* poller = tb_null;
do
{
// init poller
#if defined(TB_POLLER_ENABLE_EPOLL)
poller = tb_poller_epoll_init();
#elif defined(TB_POLLER_ENABLE_KQUEUE)
poller = tb_poller_kqueue_init();
#elif defined(TB_POLLER_ENABLE_IOCP)
poller = tb_poller_iocp_init();
#elif defined(TB_POLLER_ENABLE_POLL)
poller = tb_poller_poll_init();
#elif defined(TB_POLLER_ENABLE_SELECT)
poller = tb_poller_select_init();
#endif
tb_assert_and_check_break(poller);
// save the user private data
poller->priv = priv;
// ok
ok = tb_true;
} while (0);
// failed? exit the poller
if (!ok)
{
if (poller) tb_poller_exit((tb_poller_ref_t)poller);
poller = tb_null;
}
return (tb_poller_ref_t)poller;
}
tb_void_t tb_poller_exit(tb_poller_ref_t self)
{
// check
tb_poller_t* poller = (tb_poller_t*)self;
tb_assert_and_check_return(poller);
// kill the poller first
tb_poller_kill(self);
#ifdef TB_POLLER_ENABLE_PROCESS
// exit the process poller
if (poller->process_poller) tb_poller_process_exit(poller->process_poller);
poller->process_poller = tb_null;
#endif
#ifdef TB_POLLER_ENABLE_FWATCHER
// exit the fwatcher poller
if (poller->fwatcher_poller) tb_poller_fwatcher_exit(poller->fwatcher_poller);
poller->fwatcher_poller = tb_null;
#endif
// exit poller
if (poller->exit)
poller->exit(poller);
}
tb_cpointer_t tb_poller_priv(tb_poller_ref_t self)
{
tb_poller_t* poller = (tb_poller_t*)self;
tb_assert_and_check_return_val(poller, tb_null);
return poller->priv;
}
tb_size_t tb_poller_type(tb_poller_ref_t self)
{
tb_poller_t* poller = (tb_poller_t*)self;
tb_assert_and_check_return_val(poller, TB_POLLER_TYPE_NONE);
return poller->type;
}
tb_void_t tb_poller_kill(tb_poller_ref_t self)
{
// check
tb_poller_t* poller = (tb_poller_t*)self;
tb_assert_and_check_return(poller);
#ifdef TB_POLLER_ENABLE_PROCESS
// kill the process poller
if (poller->process_poller) tb_poller_process_kill(poller->process_poller);
#endif
#ifdef TB_POLLER_ENABLE_FWATCHER
// kill the fwatcher poller
if (poller->fwatcher_poller) tb_poller_fwatcher_kill(poller->fwatcher_poller);
#endif
// kill the poller
if (poller->kill) poller->kill(poller);
}
tb_void_t tb_poller_spak(tb_poller_ref_t self)
{
// check
tb_poller_t* poller = (tb_poller_t*)self;
tb_assert_and_check_return(poller);
#ifdef TB_POLLER_ENABLE_PROCESS
// spank the process poller
if (poller->process_poller) tb_poller_process_spak(poller->process_poller);
#endif
#ifdef TB_POLLER_ENABLE_FWATCHER
// spank the fwatcher poller
if (poller->fwatcher_poller) tb_poller_fwatcher_spak(poller->fwatcher_poller);
#endif
// spank the poller
if (poller->spak) poller->spak(poller);
}
tb_bool_t tb_poller_support(tb_poller_ref_t self, tb_size_t events)
{
tb_poller_t* poller = (tb_poller_t*)self;
tb_assert_and_check_return_val(poller, tb_false);
return (poller->supported_events & events) == events;
}
tb_bool_t tb_poller_insert(tb_poller_ref_t self, tb_poller_object_ref_t object, tb_size_t events, tb_cpointer_t priv)
{
// check
tb_poller_t* poller = (tb_poller_t*)self;
tb_assert_and_check_return_val(poller && poller->insert && object, tb_false);
#ifdef TB_POLLER_ENABLE_PROCESS
// is the process object?
if (object->type == TB_POLLER_OBJECT_PROC)
{
// init the process poller first
if (!poller->process_poller) poller->process_poller = tb_poller_process_init(poller);
tb_assert_and_check_return_val(poller->process_poller, tb_false);
// insert this process and the user private data
return tb_poller_process_insert(poller->process_poller, object->ref.proc, priv);
}
#else
tb_assert_and_check_return_val(object->type != TB_POLLER_OBJECT_PROC, tb_false);
#endif
#ifdef TB_POLLER_ENABLE_FWATCHER
// is the fwatcher object?
if (object->type == TB_POLLER_OBJECT_FWATCHER)
{
// init the fwatcher poller first
if (!poller->fwatcher_poller) poller->fwatcher_poller = tb_poller_fwatcher_init(poller);
tb_assert_and_check_return_val(poller->fwatcher_poller, tb_false);
// insert this fwatcher and the user private data
return tb_poller_fwatcher_insert(poller->fwatcher_poller, object->ref.fwatcher, priv);
}
#else
tb_assert_and_check_return_val(object->type != TB_POLLER_OBJECT_FWATCHER, tb_false);
#endif
// insert the poller object
return poller->insert(poller, object, events, priv);
}
tb_bool_t tb_poller_remove(tb_poller_ref_t self, tb_poller_object_ref_t object)
{
// check
tb_poller_t* poller = (tb_poller_t*)self;
tb_assert_and_check_return_val(poller && poller->remove && object, tb_false);
#ifdef TB_POLLER_ENABLE_PROCESS
// is the process object?
if (object->type == TB_POLLER_OBJECT_PROC)
{
// remove this process and the user private data
if (poller->process_poller)
return tb_poller_process_remove(poller->process_poller, object->ref.proc);
return tb_true;
}
#else
tb_assert_and_check_return_val(object->type != TB_POLLER_OBJECT_PROC, tb_false);
#endif
#ifdef TB_POLLER_ENABLE_FWATCHER
// is the fwatcher object?
if (object->type == TB_POLLER_OBJECT_FWATCHER)
{
// remove this fwatcher and the user private data
if (poller->fwatcher_poller)
return tb_poller_fwatcher_remove(poller->fwatcher_poller, object->ref.fwatcher);
return tb_true;
}
#else
tb_assert_and_check_return_val(object->type != TB_POLLER_OBJECT_FWATCHER, tb_false);
#endif
// remove the poller object
return poller->remove(poller, object);
}
tb_bool_t tb_poller_modify(tb_poller_ref_t self, tb_poller_object_ref_t object, tb_size_t events, tb_cpointer_t priv)
{
// check
tb_poller_t* poller = (tb_poller_t*)self;
tb_assert_and_check_return_val(poller && poller->modify && object, tb_false);
#ifdef TB_POLLER_ENABLE_PROCESS
// is the process object?
if (object->type == TB_POLLER_OBJECT_PROC)
{
// modify the user private data of this process
if (poller->process_poller)
return tb_poller_process_modify(poller->process_poller, object->ref.proc, priv);
return tb_true;
}
#else
tb_assert_and_check_return_val(object->type != TB_POLLER_OBJECT_PROC, tb_false);
#endif
#ifdef TB_POLLER_ENABLE_FWATCHER
// is the fwatcher object?
if (object->type == TB_POLLER_OBJECT_FWATCHER)
{
// modify the user private data of this fwatcher
if (poller->fwatcher_poller)
return tb_poller_fwatcher_modify(poller->fwatcher_poller, object->ref.fwatcher, priv);
return tb_true;
}
#else
tb_assert_and_check_return_val(object->type != TB_POLLER_OBJECT_FWATCHER, tb_false);
#endif
// modify the poller object
return poller->modify(poller, object, events, priv);
}
tb_long_t tb_poller_wait(tb_poller_ref_t self, tb_poller_event_func_t func, tb_long_t timeout)
{
// check
tb_poller_t* poller = (tb_poller_t*)self;
tb_assert_and_check_return_val(poller && poller->wait && func, -1);
#ifdef TB_POLLER_ENABLE_PROCESS
// prepare to wait the processes
if (poller->process_poller)
{
// prepare to wait processes
if (!tb_poller_process_wait_prepare(poller->process_poller))
return -1;
}
#endif
#ifdef TB_POLLER_ENABLE_FWATCHER
// prepare to wait the fwatchers
if (poller->fwatcher_poller)
{
// prepare to wait fwatchers
if (!tb_poller_fwatcher_wait_prepare(poller->fwatcher_poller))
return -1;
}
#endif
// wait the poller objects
tb_long_t wait = poller->wait(poller, func, timeout);
tb_check_return_val(wait >= 0, -1);
#ifdef TB_POLLER_ENABLE_PROCESS
// poll all waited processes
if (poller->process_poller)
{
tb_long_t proc_wait = tb_poller_process_wait_poll(poller->process_poller, func);
tb_check_return_val(proc_wait >= 0, -1);
wait += proc_wait;
}
#endif
#ifdef TB_POLLER_ENABLE_FWATCHER
// poll all waited fwatchers
if (poller->fwatcher_poller)
{
tb_long_t fwatcher_wait = tb_poller_fwatcher_wait_poll(poller->fwatcher_poller, func);
tb_check_return_val(fwatcher_wait >= 0, -1);
wait += fwatcher_wait;
}
#endif
return wait;
}
tb_void_t tb_poller_attach(tb_poller_ref_t self)
{
// check
tb_poller_t* poller = (tb_poller_t*)self;
tb_assert_and_check_return(poller);
// attach the poller to the current thread (only for windows/iocp now)
if (poller->attach) poller->attach(poller);
}
tbox-1.7.6/src/tbox/platform/poller.h 0000664 0000000 0000000 00000023137 14671175054 0017556 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file poller.h
* @ingroup platform
*
*/
#ifndef TB_PLATFORM_POLLER_H
#define TB_PLATFORM_POLLER_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "pipe.h"
#include "socket.h"
#include "process.h"
#include "fwatcher.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
/// the poller type enum
typedef enum __tb_poller_type_e
{
TB_POLLER_TYPE_NONE = 0
, TB_POLLER_TYPE_IOCP = 1
, TB_POLLER_TYPE_POLL = 2
, TB_POLLER_TYPE_EPOLL = 3
, TB_POLLER_TYPE_KQUEUE = 4
, TB_POLLER_TYPE_SELECT = 5
}tb_poller_type_e;
/// the poller event enum, only for sock
typedef enum __tb_poller_event_e
{
// the waited events
TB_POLLER_EVENT_NONE = TB_SOCKET_EVENT_NONE
, TB_POLLER_EVENT_CONN = TB_SOCKET_EVENT_CONN
, TB_POLLER_EVENT_ACPT = TB_SOCKET_EVENT_ACPT
, TB_POLLER_EVENT_RECV = TB_SOCKET_EVENT_RECV
, TB_POLLER_EVENT_SEND = TB_SOCKET_EVENT_SEND
, TB_POLLER_EVENT_EALL = TB_SOCKET_EVENT_EALL
// the event flags after waiting
, TB_POLLER_EVENT_CLEAR = 0x0010 //!< edge trigger. after the event is retrieved by the user, its state is reset
, TB_POLLER_EVENT_ONESHOT = 0x0020 //!< causes the event to return only the first occurrence of the filter being triggered
, TB_POLLER_EVENT_NOEXTRA = 0x0040 //!< do not pass and storage the extra userdata for events
/*! the event flag will be marked if the connection be closed in the edge trigger (TB_POLLER_EVENT_CLEAR)
*
* be similar to epoll.EPOLLRDHUP and kqueue.EV_EOF
*/
, TB_POLLER_EVENT_EOF = 0x0100
/// socket error after waiting
, TB_POLLER_EVENT_ERROR = 0x0200
}tb_poller_event_e;
/// the poller object type enum
typedef enum __tb_poller_object_type_e
{
TB_POLLER_OBJECT_NONE = 0
, TB_POLLER_OBJECT_SOCK = 1 //!< socket
, TB_POLLER_OBJECT_PIPE = 2 //!< pipe
, TB_POLLER_OBJECT_PROC = 3 //!< process
, TB_POLLER_OBJECT_FWATCHER = 4 //!< fwatcher
}tb_poller_object_type_e;
/// the poller ref type
typedef __tb_typeref__(poller);
/// the poller object type
typedef struct __tb_poller_object_t
{
/// the object type
tb_uint8_t type;
/// the object reference
union
{
tb_socket_ref_t sock;
tb_pipe_file_ref_t pipe;
tb_process_ref_t proc;
tb_fwatcher_ref_t fwatcher;
tb_pointer_t ptr;
}ref;
}tb_poller_object_t, *tb_poller_object_ref_t;
/*! the poller event func type
*
* @param poller the poller
* @param object the poller object
* @param events the poller events or process status
* @param priv the user private data for this socket
*/
typedef tb_void_t (*tb_poller_event_func_t)(tb_poller_ref_t poller, tb_poller_object_ref_t object, tb_long_t events, tb_cpointer_t priv);
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
/*! init poller
*
* @param priv the user private data
*
* @return the poller
*/
tb_poller_ref_t tb_poller_init(tb_cpointer_t priv);
/*! exit poller
*
* @param poller the poller
*/
tb_void_t tb_poller_exit(tb_poller_ref_t poller);
/*! get the poller type
*
* @param poller the poller
*
* @return the poller type
*/
tb_size_t tb_poller_type(tb_poller_ref_t poller);
/*! get the user private data
*
* @param poller the poller
*
* @return the user private data
*/
tb_cpointer_t tb_poller_priv(tb_poller_ref_t poller);
/*! kill all waited events, tb_poller_wait() will return -1
*
* @param poller the poller
*/
tb_void_t tb_poller_kill(tb_poller_ref_t poller);
/*! spank the poller, break the tb_poller_wait() and return all events
*
* @param poller the poller
*/
tb_void_t tb_poller_spak(tb_poller_ref_t poller);
/*! the events(clear, oneshot, ..) is supported for the poller?
*
* @param poller the poller
* @param events the poller events
*
* @return tb_true or tb_false
*/
tb_bool_t tb_poller_support(tb_poller_ref_t poller, tb_size_t events);
/*! insert object to poller
*
* @param poller the poller
* @param object the poller object
* @param events the poller events, it will be ignored if be process object
* @param priv the private data
*
* @return tb_true or tb_false
*/
tb_bool_t tb_poller_insert(tb_poller_ref_t poller, tb_poller_object_ref_t object, tb_size_t events, tb_cpointer_t priv);
/*! remove object from poller
*
* @param poller the poller
* @param object the poller object
*
* @return tb_true or tb_false
*/
tb_bool_t tb_poller_remove(tb_poller_ref_t poller, tb_poller_object_ref_t object);
/*! modify events for the given poller object
*
* @param poller the poller
* @param object the poller object
* @param events the poller events, it will be ignored if be process object
* @param priv the private data
*
* @return tb_true or tb_false
*/
tb_bool_t tb_poller_modify(tb_poller_ref_t poller, tb_poller_object_ref_t object, tb_size_t events, tb_cpointer_t priv);
/*! wait all sockets
*
* @param poller the poller
* @param func the events function
* @param timeout the timeout, infinity: -1
*
* @return > 0: the events number, 0: timeout or interrupted, -1: failed
*/
tb_long_t tb_poller_wait(tb_poller_ref_t poller, tb_poller_event_func_t func, tb_long_t timeout);
/*! attach the poller to the current thread (only for windows/iocp now)
*
* @param poller the poller
*/
tb_void_t tb_poller_attach(tb_poller_ref_t poller);
/* //////////////////////////////////////////////////////////////////////////////////////
* inline implementation
*/
/*! insert socket to poller
*
* @param poller the poller
* @param sock the socket
* @param events the poller events
* @param priv the private data
*
* @return tb_true or tb_false
*/
static __tb_inline__ tb_bool_t tb_poller_insert_sock(tb_poller_ref_t poller, tb_socket_ref_t sock, tb_size_t events, tb_cpointer_t priv)
{
tb_poller_object_t object;
object.type = TB_POLLER_OBJECT_SOCK;
object.ref.sock = sock;
return tb_poller_insert(poller, &object, events, priv);
}
/*! remove socket from poller
*
* @param poller the poller
* @param sock the socket
*
* @return tb_true or tb_false
*/
static __tb_inline__ tb_bool_t tb_poller_remove_sock(tb_poller_ref_t poller, tb_socket_ref_t sock)
{
tb_poller_object_t object;
object.type = TB_POLLER_OBJECT_SOCK;
object.ref.sock = sock;
return tb_poller_remove(poller, &object);
}
/*! modify events for the given socket
*
* @param poller the poller
* @param sock the socket
* @param events the poller events
* @param priv the private data
*
* @return tb_true or tb_false
*/
static __tb_inline__ tb_bool_t tb_poller_modify_sock(tb_poller_ref_t poller, tb_socket_ref_t sock, tb_size_t events, tb_cpointer_t priv)
{
tb_poller_object_t object;
object.type = TB_POLLER_OBJECT_SOCK;
object.ref.sock = sock;
return tb_poller_modify(poller, &object, events, priv);
}
/*! insert pipe to poller
*
* @param poller the poller
* @param pipe the pipe
* @param events the poller events
* @param priv the private data
*
* @return tb_true or tb_false
*/
static __tb_inline__ tb_bool_t tb_poller_insert_pipe(tb_poller_ref_t poller, tb_pipe_file_ref_t pipe, tb_size_t events, tb_cpointer_t priv)
{
tb_poller_object_t object;
object.type = TB_POLLER_OBJECT_PIPE;
object.ref.pipe = pipe;
return tb_poller_insert(poller, &object, events, priv);
}
/*! remove pipe from poller
*
* @param poller the poller
* @param pipe the pipe
*
* @return tb_true or tb_false
*/
static __tb_inline__ tb_bool_t tb_poller_remove_pipe(tb_poller_ref_t poller, tb_pipe_file_ref_t pipe)
{
tb_poller_object_t object;
object.type = TB_POLLER_OBJECT_PIPE;
object.ref.pipe = pipe;
return tb_poller_remove(poller, &object);
}
/*! modify events for the given pipe
*
* @param poller the poller
* @param pipe the pipe
* @param events the poller events
* @param priv the private data
*
* @return tb_true or tb_false
*/
static __tb_inline__ tb_bool_t tb_poller_modify_pipe(tb_poller_ref_t poller, tb_pipe_file_ref_t pipe, tb_size_t events, tb_cpointer_t priv)
{
tb_poller_object_t object;
object.type = TB_POLLER_OBJECT_PIPE;
object.ref.pipe = pipe;
return tb_poller_modify(poller, &object, events, priv);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_leave__
#endif
tbox-1.7.6/src/tbox/platform/posix/ 0000775 0000000 0000000 00000000000 14671175054 0017244 5 ustar 00root root 0000000 0000000 tbox-1.7.6/src/tbox/platform/posix/addrinfo.c 0000664 0000000 0000000 00000012417 14671175054 0021203 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file addrinfo.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include
#include
#include
#include "sockaddr.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
#if defined(TB_ADDRINFO_ADDR_IMPL) \
&& defined(TB_CONFIG_POSIX_HAVE_GETADDRINFO)
static __tb_inline__ tb_int_t tb_addrinfo_ai_family(tb_ipaddr_ref_t addr)
{
// get the ai family for getaddrinfo
switch (tb_ipaddr_family(addr))
{
case TB_IPADDR_FAMILY_IPV4:
return AF_INET;
case TB_IPADDR_FAMILY_IPV6:
return AF_INET6;
default:
return AF_UNSPEC;
}
}
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#ifdef TB_ADDRINFO_ADDR_IMPL
tb_bool_t tb_addrinfo_addr(tb_char_t const* name, tb_ipaddr_ref_t addr)
{
// check
tb_assert_and_check_return_val(name && addr, tb_false);
#ifndef TB_CONFIG_MICRO_ENABLE
// attempt to get address using dns looker
if (tb_ipaddr_family(addr) != TB_IPADDR_FAMILY_IPV6 && tb_dns_looker_done(name, addr))
return tb_true;
#endif
#if defined(TB_CONFIG_POSIX_HAVE_GETADDRINFO)
// done
tb_bool_t ok = tb_false;
struct addrinfo* answer = tb_null;
do
{
// init hints
struct addrinfo hints = {0};
hints.ai_family = tb_addrinfo_ai_family(addr);
hints.ai_socktype = SOCK_STREAM;
// init service
tb_char_t service[32] = {0};
tb_uint16_t port = tb_ipaddr_port(addr);
if (port) tb_snprintf(service, sizeof(service), "%u", port);
// get address info
if (getaddrinfo(name, port? service : tb_null, &hints, &answer)) break;
tb_assert_and_check_break(answer && answer->ai_addr);
// save address
ok = tb_sockaddr_save(addr, (struct sockaddr_storage const*)answer->ai_addr) != 0;
} while (0);
// exit answer
if (answer) freeaddrinfo(answer);
answer = tb_null;
// ok?
return ok;
#elif defined(TB_CONFIG_POSIX_HAVE_GETHOSTBYNAME)
// not support ipv6
tb_assert_and_check_return_val(tb_ipaddr_family(addr) != TB_IPADDR_FAMILY_IPV6, tb_false);
// get first host address
struct hostent* hostaddr = gethostbyname(name);
tb_check_return_val(hostaddr && hostaddr->h_addr && hostaddr->h_addrtype == AF_INET, tb_false);
// save family
tb_ipaddr_family_set(addr, TB_IPADDR_FAMILY_IPV4);
// make ipv4
tb_ipv4_t ipv4;
ipv4.u32 = (tb_uint32_t)((struct in_addr const*)hostaddr->h_addr)->s_addr;
// save ipv4
tb_ipaddr_ipv4_set(addr, &ipv4);
// ok
return tb_true;
#else
tb_trace_noimpl();
return tb_false;
#endif
}
#endif
#ifdef TB_ADDRINFO_NAME_IMPL
tb_char_t const* tb_addrinfo_name(tb_ipaddr_ref_t addr, tb_char_t* name, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(addr && name && maxn, tb_null);
#if defined(TB_CONFIG_POSIX_HAVE_GETNAMEINFO)
// load socket address
struct sockaddr_storage saddr;
socklen_t saddrlen = (socklen_t)tb_sockaddr_load(&saddr, addr);
tb_assert_and_check_return_val(saddrlen, tb_null);
// get host name from address
return !getnameinfo((struct sockaddr const*)&saddr, saddrlen, name, maxn, tb_null, 0, NI_NAMEREQD)? name : tb_null;
#elif defined(TB_CONFIG_POSIX_HAVE_GETHOSTBYNAME)
// done
struct hostent* hostaddr = tb_null;
switch (tb_ipaddr_family(addr))
{
case TB_IPADDR_FAMILY_IPV4:
{
// init ip address
struct in_addr ipaddr = {0};
ipaddr.s_addr = tb_ipaddr_ip_is_any(addr)? INADDR_ANY : addr->u.ipv4.u32;
// get host name from address
hostaddr = gethostbyaddr((tb_char_t const*)&ipaddr, sizeof(ipaddr), AF_INET);
}
break;
case TB_IPADDR_FAMILY_IPV6:
{
// init ip address
struct in6_addr ipaddr;
tb_memset(&ipaddr, 0, sizeof(ipaddr));
// save ipv6
if (tb_ipaddr_ip_is_any(addr)) ipaddr = in6addr_any;
else tb_memcpy(ipaddr.s6_addr, addr->u.ipv6.addr.u8, sizeof(ipaddr.s6_addr));
// get host name from address
hostaddr = gethostbyaddr((tb_char_t const*)&ipaddr, sizeof(ipaddr), AF_INET6);
}
break;
default:
break;
}
tb_check_return_val(hostaddr && hostaddr->h_name, tb_null);
// save name
tb_strlcpy(name, hostaddr->h_name, maxn);
// ok?
return name;
#else
tb_trace_noimpl();
return tb_null;
#endif
}
#endif
tbox-1.7.6/src/tbox/platform/posix/context.c 0000664 0000000 0000000 00000006646 14671175054 0021110 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file context.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#if defined(TB_CONFIG_POSIX_HAVE_GETCONTEXT) && \
defined(TB_CONFIG_POSIX_HAVE_SETCONTEXT) && \
defined(TB_CONFIG_POSIX_HAVE_MAKECONTEXT)
# include
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_context_size()
{
return sizeof(ucontext_t);
}
tb_context_ref_t tb_context_init(tb_byte_t* data, tb_size_t size)
{
// check size
tb_size_t context_size = tb_context_size();
tb_assert_and_check_return_val(data && context_size && context_size <= size, tb_null);
// get context
tb_context_ref_t context = (tb_context_ref_t)data;
// init context
tb_memset(data, 0, context_size);
#if defined(TB_CONFIG_POSIX_HAVE_GETCONTEXT) && \
defined(TB_CONFIG_POSIX_HAVE_SETCONTEXT) && \
defined(TB_CONFIG_POSIX_HAVE_MAKECONTEXT)
// init sigmask
sigset_t zero;
sigemptyset(&zero);
sigprocmask(SIG_BLOCK, &zero, &((ucontext_t*)context)->uc_sigmask);
#endif
// ok
return context;
}
tb_void_t tb_context_exit(tb_context_ref_t context)
{
// do nothing
}
tb_bool_t tb_context_save(tb_context_ref_t context)
{
// check
tb_assert(context);
// get it
return getcontext((ucontext_t*)context) == 0;
}
tb_void_t tb_context_switch(tb_context_ref_t context)
{
// check
tb_assert(context);
// set it
setcontext((ucontext_t*)context);
}
tb_bool_t tb_context_make(tb_context_ref_t context, tb_pointer_t stack, tb_size_t stacksize, tb_context_func_t func, tb_cpointer_t priv)
{
// check
ucontext_t* ucontext = (ucontext_t*)context;
tb_assert_and_check_return_val(ucontext && stack && stacksize && func, tb_false);
// get context first
if (getcontext(ucontext) == 0)
{
// init stack and size
ucontext->uc_stack.ss_sp = stack;
ucontext->uc_stack.ss_size = stacksize;
// init link
ucontext->uc_link = tb_null;
// make it
makecontext(ucontext, (tb_void_t(*)())func, 1, (tb_size_t)priv);
}
// ok
return tb_true;
}
#ifdef TB_CONFIG_POSIX_HAVE_SWAPCONTEXT
tb_void_t tb_context_swap(tb_context_ref_t context, tb_context_ref_t context_new)
{
// check
tb_assert(context && context_new);
// swap it
swapcontext((ucontext_t*)context, (ucontext_t*)context_new);
}
#else
tb_void_t tb_context_swap(tb_context_ref_t context, tb_context_ref_t context_new)
{
// check
tb_assert(context && context_new);
// swap it
if (getcontext((ucontext_t*)context) == 0)
setcontext((ucontext_t*)context_new);
}
#endif
tbox-1.7.6/src/tbox/platform/posix/cpu.c 0000664 0000000 0000000 00000002447 14671175054 0020206 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file cpu.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../platform.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_size_t tb_cpu_count()
{
// we will pre-initialize it in tb_platform_init()
static tb_size_t ncpu = -1;
if (ncpu == -1)
{
tb_size_t count = sysconf(_SC_NPROCESSORS_ONLN);
if (!count) count = sysconf(_SC_NPROCESSORS_CONF);
if (!count) count = 1;
ncpu = count;
}
return ncpu;
}
tbox-1.7.6/src/tbox/platform/posix/directory.c 0000664 0000000 0000000 00000023343 14671175054 0021421 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file directory.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../file.h"
#include "../path.h"
#include "../directory.h"
#include "../environment.h"
#include
#include
#include
#include
#include
#include
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_long_t tb_directory_walk_remove(tb_char_t const* path, tb_file_info_t const* info, tb_cpointer_t priv)
{
// check
tb_assert_and_check_return_val(path && info, TB_DIRECTORY_WALK_CODE_END);
// remove file, directory and dead symbol link (info->type is none, file not exists)
remove(path);
return TB_DIRECTORY_WALK_CODE_CONTINUE;
}
static tb_long_t tb_directory_walk_copy(tb_char_t const* path, tb_file_info_t const* info, tb_cpointer_t priv)
{
// check
tb_value_t* tuple = (tb_value_t*)priv;
tb_assert_and_check_return_val(path && info && priv, TB_DIRECTORY_WALK_CODE_END);
// the dest directory
tb_char_t const* dest = tuple[0].cstr;
tb_assert_and_check_return_val(dest, TB_DIRECTORY_WALK_CODE_END);
// the file name
tb_size_t size = tuple[1].ul;
tb_char_t const* name = path + size;
// the copy flags
tb_size_t flags = tuple[2].ul;
// the dest file path
tb_char_t dpath[8192] = {0};
tb_snprintf(dpath, 8192, "%s/%s", dest, name[0] == '/'? name + 1 : name);
// remove the dest file first
tb_file_info_t dinfo = {0};
if (tb_file_info(dpath, &dinfo))
{
if (dinfo.type == TB_FILE_TYPE_FILE)
tb_file_remove(dpath);
if (dinfo.type == TB_FILE_TYPE_DIRECTORY)
tb_directory_remove(dpath);
}
// do copy
tb_bool_t ok = tb_true;
tb_bool_t skip_recursion = tb_false;
switch (info->type)
{
case TB_FILE_TYPE_FILE:
ok = tb_file_copy(path, dpath, flags);
break;
case TB_FILE_TYPE_DIRECTORY:
{
// reserve symlink?
if ((flags & TB_FILE_COPY_LINK) && (info->flags & TB_FILE_FLAG_LINK))
{
// just copy link and skip recursion
ok = tb_file_copy(path, dpath, TB_FILE_COPY_LINK);
skip_recursion = tb_true;
}
else ok = tb_directory_create(dpath);
}
break;
default:
break;
}
tuple[3].b = ok;
tb_size_t retcode = TB_DIRECTORY_WALK_CODE_CONTINUE;
if (skip_recursion)
retcode |= TB_DIRECTORY_WALK_CODE_SKIP_RECURSION;
return retcode;
}
static tb_long_t tb_directory_walk_impl(tb_char_t const* path, tb_long_t recursion, tb_bool_t prefix, tb_directory_walk_func_t func, tb_cpointer_t priv)
{
// check
tb_assert_and_check_return_val(path && func, TB_DIRECTORY_WALK_CODE_END);
// last
tb_long_t last = tb_strlen(path) - 1;
tb_assert_and_check_return_val(last >= 0, TB_DIRECTORY_WALK_CODE_END);
// done
tb_long_t ok = TB_DIRECTORY_WALK_CODE_CONTINUE;
tb_char_t temp[4096] = {0};
DIR* directory = tb_null;
if ((directory = opendir(path)))
{
// walk
tb_char_t name[1024];
struct dirent* item = tb_null;
while ((item = readdir(directory)))
{
// get the item name
if (sizeof(name) == tb_strlcpy(name, item->d_name, sizeof(name)))
continue ;
if (tb_strcmp(name, ".") && tb_strcmp(name, ".."))
{
// the temp path
tb_long_t n = tb_snprintf(temp, 4095, "%s%s%s", path, path[last] == '/'? "" : "/", name);
if (n >= 0) temp[n] = '\0';
// get the file info (file maybe not exists, dead symbol link)
tb_file_info_t info = {0};
tb_file_info(temp, &info);
// do callback
if (prefix) ok = func(temp, &info, priv);
tb_check_break(ok);
// walk to the next directory
if (info.type == TB_FILE_TYPE_DIRECTORY && recursion && ok != TB_DIRECTORY_WALK_CODE_SKIP_RECURSION)
ok = tb_directory_walk_impl(temp, recursion > 0? recursion - 1 : recursion, prefix, func, priv);
tb_check_break(ok);
// do callback
if (!prefix) ok = func(temp, &info, priv);
tb_check_break(ok);
}
}
// exit directory
closedir(directory);
}
// continue ?
return ok;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_directory_create(tb_char_t const* path)
{
// check
tb_assert_and_check_return_val(path, tb_false);
// the full path
tb_char_t full[TB_PATH_MAXN];
path = tb_path_absolute(path, full, TB_PATH_MAXN);
tb_assert_and_check_return_val(path, tb_false);
// make it (0755: drwxr-xr-x)
tb_bool_t ok = !mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO);
if (!ok && (errno != EPERM && errno != EACCES))
{
// make directory
tb_char_t temp[TB_PATH_MAXN] = {0};
tb_char_t const* p = full;
tb_char_t* t = temp;
tb_char_t const* e = temp + TB_PATH_MAXN - 1;
for (; t < e && *p; t++)
{
*t = *p;
if (*p == '/')
{
// make directory if not exists
if (!tb_file_info(temp, tb_null))
{
if (mkdir(temp, S_IRWXU | S_IRWXG | S_IRWXO) != 0)
return tb_false;
}
// skip repeat '/'
while (*p && *p == '/') p++;
}
else p++;
}
// make it again
ok = !mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO);
}
return ok;
}
tb_bool_t tb_directory_remove(tb_char_t const* path)
{
// the full path
tb_char_t full[TB_PATH_MAXN];
path = tb_path_absolute(path, full, TB_PATH_MAXN);
tb_assert_and_check_return_val(path, tb_false);
// walk remove
tb_directory_walk_impl(path, -1, tb_false, tb_directory_walk_remove, tb_null);
// remove it
return !remove(path)? tb_true : tb_false;
}
tb_size_t tb_directory_current(tb_char_t* path, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(path && maxn, 0);
// the current directory
tb_size_t size = 0;
if (getcwd(path, maxn - 1)) size = tb_strlen(path);
// ok?
return size;
}
tb_bool_t tb_directory_current_set(tb_char_t const* path)
{
// the absolute path
tb_char_t full[TB_PATH_MAXN];
path = tb_path_absolute(path, full, TB_PATH_MAXN);
tb_assert_and_check_return_val(path, tb_false);
// change to the directory
return !chdir(path);
}
#if !defined(TB_CONFIG_OS_IOS) && !defined(TB_CONFIG_OS_ANDROID)
tb_size_t tb_directory_home(tb_char_t* path, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(path && maxn, 0);
// get the home directory
tb_size_t size = 0;
if (!(size = tb_environment_first("HOME", path, maxn)))
size = tb_environment_first("XDG_CONFIG_HOME", path, maxn);
return size;
}
tb_size_t tb_directory_temporary(tb_char_t* path, tb_size_t maxn)
{
// check
tb_assert_and_check_return_val(path && maxn > 4, 0);
// get the temporary directory
tb_size_t size = 0;
if (!(size = tb_environment_first("TMPDIR", path, maxn)))
size = tb_strlcpy(path, "/tmp", maxn);
return size;
}
#endif
tb_void_t tb_directory_walk(tb_char_t const* path, tb_long_t recursion, tb_bool_t prefix, tb_directory_walk_func_t func, tb_cpointer_t priv)
{
// check
tb_assert_and_check_return(path && func);
// walk it directly if rootdir is relative path
tb_file_info_t info = {0};
if (!tb_path_is_absolute(path) && tb_file_info(path, &info) && info.type == TB_FILE_TYPE_DIRECTORY)
tb_directory_walk_impl(path, recursion, prefix, func, priv);
else
{
// the absolute path (translate "~/")
tb_char_t full[TB_PATH_MAXN];
path = tb_path_absolute(path, full, TB_PATH_MAXN);
tb_assert_and_check_return(path);
// walk
tb_directory_walk_impl(path, recursion, prefix, func, priv);
}
}
tb_bool_t tb_directory_copy(tb_char_t const* path, tb_char_t const* dest, tb_size_t flags)
{
// the absolute path
tb_char_t full0[TB_PATH_MAXN];
path = tb_path_absolute(path, full0, TB_PATH_MAXN);
tb_assert_and_check_return_val(path, tb_false);
// the dest path
tb_char_t full1[TB_PATH_MAXN];
dest = tb_path_absolute(dest, full1, TB_PATH_MAXN);
tb_assert_and_check_return_val(dest, tb_false);
// walk copy
tb_value_t tuple[4];
tuple[0].cstr = dest;
tuple[1].ul = tb_strlen(path);
tuple[2].ul = flags;
tuple[3].b = tb_true;
tb_directory_walk_impl(path, -1, tb_true, tb_directory_walk_copy, tuple);
// copy empty directory?
tb_bool_t ok = tuple[3].b;
if (ok && !tb_file_info(dest, tb_null))
return tb_directory_create(dest);
return ok;
}
tbox-1.7.6/src/tbox/platform/posix/dynamic.c 0000664 0000000 0000000 00000004015 14671175054 0021034 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file dynamic.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../dynamic.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_dynamic_ref_t tb_dynamic_init(tb_char_t const* name)
{
// check
tb_assert_and_check_return_val(name, tb_null);
// clear error
dlerror();
// open
tb_handle_t dynamic = dlopen(name, RTLD_LAZY);
// error?
if (dlerror())
{
if (dynamic) dlclose(dynamic);
dynamic = tb_null;
}
// ok?
return (tb_dynamic_ref_t)dynamic;
}
tb_void_t tb_dynamic_exit(tb_dynamic_ref_t dynamic)
{
// check
tb_assert_and_check_return(dynamic);
// close it
dlclose((tb_handle_t)dynamic);
tb_assert(!dlerror());
}
tb_pointer_t tb_dynamic_func(tb_dynamic_ref_t dynamic, tb_char_t const* name)
{
// check
tb_assert_and_check_return_val(dynamic && name, tb_null);
// the func
return (tb_pointer_t)dlsym((tb_handle_t)dynamic, name);
}
tb_pointer_t tb_dynamic_pvar(tb_dynamic_ref_t dynamic, tb_char_t const* name)
{
// check
tb_assert_and_check_return_val(dynamic && name, tb_null);
// the variable address
return (tb_pointer_t)dlsym((tb_handle_t)dynamic, name);
}
tbox-1.7.6/src/tbox/platform/posix/event.c 0000664 0000000 0000000 00000003027 14671175054 0020533 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file event.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../platform.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_event_ref_t tb_event_init()
{
return (tb_event_ref_t)tb_semaphore_init(0);
}
tb_void_t tb_event_exit(tb_event_ref_t event)
{
if (event) tb_semaphore_exit((tb_semaphore_ref_t)event);
}
tb_bool_t tb_event_post(tb_event_ref_t event)
{
// check
tb_assert_and_check_return_val(event, tb_false);
// post
return tb_semaphore_post((tb_semaphore_ref_t)event, 1);
}
tb_long_t tb_event_wait(tb_event_ref_t event, tb_long_t timeout)
{
// check
tb_assert_and_check_return_val(event, -1);
// wait
return tb_semaphore_wait((tb_semaphore_ref_t)event, timeout);
}
tbox-1.7.6/src/tbox/platform/posix/file.c 0000664 0000000 0000000 00000050714 14671175054 0020336 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file file.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../file.h"
#include "../path.h"
#include "../directory.h"
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef TB_CONFIG_POSIX_HAVE_COPYFILE
# include
#endif
#ifdef TB_CONFIG_POSIX_HAVE_SENDFILE
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_file_ref_t tb_file_init(tb_char_t const* path, tb_size_t mode)
{
// check
tb_assert_and_check_return_val(path, tb_null);
// the full path
tb_char_t full[TB_PATH_MAXN];
path = tb_path_absolute(path, full, TB_PATH_MAXN);
tb_assert_and_check_return_val(path, tb_null);
// flags
tb_size_t flags = 0;
if (mode & TB_FILE_MODE_RO) flags |= O_RDONLY;
else if (mode & TB_FILE_MODE_WO) flags |= O_WRONLY;
else if (mode & TB_FILE_MODE_RW) flags |= O_RDWR;
if (mode & TB_FILE_MODE_CREAT) flags |= O_CREAT;
if (mode & TB_FILE_MODE_APPEND) flags |= O_APPEND;
if (mode & TB_FILE_MODE_TRUNC) flags |= O_TRUNC;
// dma mode, no cache
#if defined(TB_CONFIG_OS_LINUX) && defined(O_DIRECT)
if (mode & TB_FILE_MODE_DIRECT) flags |= O_DIRECT;
#endif
// noblock
flags |= O_NONBLOCK;
// modes
tb_size_t modes = 0;
if (mode & TB_FILE_MODE_CREAT)
{
// 0644: -rw-r--r--
modes = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
}
// open it, @note need absolute path
tb_long_t fd = open(path, flags, modes);
if (fd < 0 && (mode & TB_FILE_MODE_CREAT) && (errno != EPERM && errno != EACCES))
{
#ifndef TB_CONFIG_MICRO_ENABLE
// open it again after creating the file directory
tb_int_t errno_bak = errno;
tb_char_t dir[TB_PATH_MAXN];
if (tb_directory_create(tb_path_directory(path, dir, sizeof(dir))))
fd = open(path, flags, modes);
else errno = errno_bak;
#endif
}
tb_check_return_val(fd >= 0, tb_null);
// trace
tb_trace_d("open: %p", tb_fd2file(fd));
// ok?
return tb_fd2file(fd);
}
tb_bool_t tb_file_exit(tb_file_ref_t file)
{
// check
tb_assert_and_check_return_val(file, tb_false);
// trace
tb_trace_d("close: %p", file);
// close it
tb_bool_t ok = !close(tb_file2fd(file))? tb_true : tb_false;
// failed?
if (!ok)
{
// trace
tb_trace_e("close: %p failed, errno: %d", file, errno);
}
// ok?
return ok;
}
tb_long_t tb_file_read(tb_file_ref_t file, tb_byte_t* data, tb_size_t size)
{
// check
tb_assert_and_check_return_val(file && data, -1);
// read it
return read(tb_file2fd(file), data, size);
}
tb_long_t tb_file_writ(tb_file_ref_t file, tb_byte_t const* data, tb_size_t size)
{
// check
tb_assert_and_check_return_val(file && data, -1);
// writ it
return write(tb_file2fd(file), data, size);
}
tb_bool_t tb_file_sync(tb_file_ref_t file)
{
// check
tb_assert_and_check_return_val(file, tb_false);
// sync
#ifdef TB_CONFIG_POSIX_HAVE_FDATASYNC
return !fdatasync(tb_file2fd(file))? tb_true : tb_false;
#else
return !fsync(tb_file2fd(file))? tb_true : tb_false;
#endif
}
tb_hong_t tb_file_seek(tb_file_ref_t file, tb_hong_t offset, tb_size_t mode)
{
// check
tb_assert_and_check_return_val(file, -1);
// seek
return lseek(tb_file2fd(file), offset, mode);
}
tb_hong_t tb_file_offset(tb_file_ref_t file)
{
// check
tb_assert_and_check_return_val(file, -1);
// the offset
return tb_file_seek(file, (tb_hong_t)0, TB_FILE_SEEK_CUR);
}
tb_hize_t tb_file_size(tb_file_ref_t file)
{
// check
tb_assert_and_check_return_val(file, 0);
// the file size
tb_hize_t size = 0;
struct stat st = {0};
if (!fstat(tb_file2fd(file), &st))
size = st.st_size;
// ok?
return size;
}
tb_bool_t tb_file_info(tb_char_t const* path, tb_file_info_t* info)
{
// check
tb_assert_and_check_return_val(path, tb_false);
// the full path (need translate "~/")
tb_char_t full[TB_PATH_MAXN];
path = tb_path_absolute(path, full, TB_PATH_MAXN);
tb_assert_and_check_return_val(path, tb_false);
// get info
if (info)
{
// init info
tb_memset(info, 0, sizeof(tb_file_info_t));
// get stat, even if the file does not exist, it may be a dead symbolic link
#if defined(TB_CONFIG_POSIX_HAVE_LSTAT64)
struct stat64 st = {0};
if (!lstat64(path, &st))
#else
struct stat st = {0};
if (!lstat(path, &st))
#endif
{
// get file type
if (S_ISDIR(st.st_mode)) info->type = TB_FILE_TYPE_DIRECTORY;
else info->type = TB_FILE_TYPE_FILE;
// is symlink?
info->flags = TB_FILE_FLAG_NONE;
if (S_ISLNK(st.st_mode))
{
// we need get more file info about symlink, does it point to directory?
tb_memset(&st, 0, sizeof(st));
#if defined(TB_CONFIG_POSIX_HAVE_STAT64)
if (!stat64(path, &st))
#else
if (!stat(path, &st))
#endif
{
if (S_ISDIR(st.st_mode)) info->type = TB_FILE_TYPE_DIRECTORY;
else info->type = TB_FILE_TYPE_FILE;
}
info->flags |= TB_FILE_FLAG_LINK;
}
// file size
info->size = st.st_size >= 0? (tb_hize_t)st.st_size : 0;
// the last access time
info->atime = (tb_time_t)st.st_atime;
// the last modify time
info->mtime = (tb_time_t)st.st_mtime;
return tb_true;
}
}
else if (!access(path, F_OK))
{
return tb_true;
}
return tb_false;
}
#ifndef TB_CONFIG_MICRO_ENABLE
tb_long_t tb_file_pread(tb_file_ref_t file, tb_byte_t* data, tb_size_t size, tb_hize_t offset)
{
// check
tb_assert_and_check_return_val(file, -1);
// read it
#ifdef TB_CONFIG_POSIX_HAVE_PREAD64
return pread64(tb_file2fd(file), data, (size_t)size, offset);
#else
return pread(tb_file2fd(file), data, (size_t)size, offset);
#endif
}
tb_long_t tb_file_pwrit(tb_file_ref_t file, tb_byte_t const* data, tb_size_t size, tb_hize_t offset)
{
// check
tb_assert_and_check_return_val(file, -1);
// writ it
#ifdef TB_CONFIG_POSIX_HAVE_PWRITE64
return pwrite64(tb_file2fd(file), data, (size_t)size, offset);
#else
return pwrite(tb_file2fd(file), data, (size_t)size, offset);
#endif
}
tb_long_t tb_file_readv(tb_file_ref_t file, tb_iovec_t const* list, tb_size_t size)
{
// check
tb_assert_and_check_return_val(file && list && size, -1);
// check iovec
tb_assert_static(sizeof(tb_iovec_t) == sizeof(struct iovec));
tb_assert(tb_memberof_eq(tb_iovec_t, data, struct iovec, iov_base));
tb_assert(tb_memberof_eq(tb_iovec_t, size, struct iovec, iov_len));
// read it
return readv(tb_file2fd(file), (struct iovec const*)list, size);
}
tb_long_t tb_file_writv(tb_file_ref_t file, tb_iovec_t const* list, tb_size_t size)
{
// check
tb_assert_and_check_return_val(file && list && size, -1);
// check iovec
tb_assert_static(sizeof(tb_iovec_t) == sizeof(struct iovec));
tb_assert(tb_memberof_eq(tb_iovec_t, data, struct iovec, iov_base));
tb_assert(tb_memberof_eq(tb_iovec_t, size, struct iovec, iov_len));
// writ it
return writev(tb_file2fd(file), (struct iovec const*)list, size);
}
tb_hong_t tb_file_writf(tb_file_ref_t file, tb_file_ref_t ifile, tb_hize_t offset, tb_hize_t size)
{
// check
tb_assert_and_check_return_val(file && ifile && size, -1);
#ifdef TB_CONFIG_POSIX_HAVE_SENDFILE
// writ it
off_t seek = offset;
tb_hong_t real = sendfile(tb_file2fd(file), tb_file2fd(ifile), &seek, (size_t)size);
// ok?
if (real >= 0) return real;
// continue?
if (errno == EINTR || errno == EAGAIN) return 0;
// error
return -1;
#else
// read data
tb_byte_t data[8192];
tb_long_t read = tb_file_pread(ifile, data, sizeof(data), offset);
tb_check_return_val(read > 0, read);
// writ data
tb_size_t writ = 0;
while (writ < read)
{
tb_long_t real = tb_file_writ(file, data + writ, read - writ);
if (real > 0) writ += real;
else break;
}
// ok?
return writ == read? writ : -1;
#endif
}
tb_long_t tb_file_preadv(tb_file_ref_t file, tb_iovec_t const* list, tb_size_t size, tb_hize_t offset)
{
// check
tb_assert_and_check_return_val(file && list && size, -1);
// check iovec
tb_assert_static(sizeof(tb_iovec_t) == sizeof(struct iovec));
tb_assert(tb_memberof_eq(tb_iovec_t, data, struct iovec, iov_base));
tb_assert(tb_memberof_eq(tb_iovec_t, size, struct iovec, iov_len));
// read it
#ifdef TB_CONFIG_POSIX_HAVE_PREADV
# ifdef __COSMOPOLITAN__
return preadv(tb_file2fd(file), (struct iovec*)list, size, offset);
# else
return preadv(tb_file2fd(file), (struct iovec const*)list, size, offset);
# endif
#else
// FIXME: lock it
// save offset
tb_hong_t current = tb_file_offset(file);
tb_assert_and_check_return_val(current >= 0, -1);
// seek it
if (current != offset && tb_file_seek(file, offset, TB_FILE_SEEK_BEG) != offset) return -1;
// read it
tb_long_t real = tb_file_readv(file, list, size);
// restore offset
if (current != offset && tb_file_seek(file, current, TB_FILE_SEEK_BEG) != current) return -1;
// ok
return real;
#endif
}
tb_long_t tb_file_pwritv(tb_file_ref_t file, tb_iovec_t const* list, tb_size_t size, tb_hize_t offset)
{
// check
tb_assert_and_check_return_val(file && list && size, -1);
// check iovec
tb_assert_static(sizeof(tb_iovec_t) == sizeof(struct iovec));
tb_assert(tb_memberof_eq(tb_iovec_t, data, struct iovec, iov_base));
tb_assert(tb_memberof_eq(tb_iovec_t, size, struct iovec, iov_len));
// writ it
#ifdef TB_CONFIG_POSIX_HAVE_PWRITEV
return pwritev(tb_file2fd(file), (struct iovec const*)list, size, offset);
#else
// FIXME: lock it
// save offset
tb_hong_t current = tb_file_offset(file);
tb_assert_and_check_return_val(current >= 0, -1);
// seek it
if (current != offset && tb_file_seek(file, offset, TB_FILE_SEEK_BEG) != offset) return -1;
// writ it
tb_long_t real = tb_file_writv(file, list, size);
// restore offset
if (current != offset && tb_file_seek(file, current, TB_FILE_SEEK_BEG) != current) return -1;
// ok
return real;
#endif
}
tb_bool_t tb_file_copy(tb_char_t const* path, tb_char_t const* dest, tb_size_t flags)
{
// check
tb_assert_and_check_return_val(path && dest, tb_false);
// the full path
tb_char_t data[TB_PATH_MAXN];
path = tb_path_absolute(path, data, TB_PATH_MAXN);
tb_assert_and_check_return_val(path, tb_false);
// copy link
tb_file_info_t info = {0};
if (flags & TB_FILE_COPY_LINK && tb_file_info(path, &info) && info.flags & TB_FILE_FLAG_LINK)
{
// read link first
tb_char_t srcpath[TB_PATH_MAXN];
tb_long_t size = readlink(path, srcpath, TB_PATH_MAXN);
tb_char_t const* linkpath = srcpath;
if (size == TB_PATH_MAXN)
{
tb_size_t maxn = TB_PATH_MAXN * 2;
tb_char_t* buff = (tb_char_t*)tb_malloc(maxn);
if (buff)
{
tb_long_t size = readlink(path, buff, maxn);
if (size > 0 && size < maxn)
{
buff[size] = '\0';
linkpath = buff;
}
}
}
else if (size >= 0 && size < TB_PATH_MAXN)
srcpath[size] = '\0';
// do link
tb_bool_t ok = tb_file_link(linkpath, dest);
// free link path
if (linkpath && linkpath != srcpath)
{
tb_free((tb_pointer_t)linkpath);
linkpath = tb_null;
}
return ok;
}
#ifdef TB_CONFIG_POSIX_HAVE_COPYFILE
if (!(flags & TB_FILE_COPY_WRITEABLE))
{
// the dest path
tb_char_t full1[TB_PATH_MAXN];
dest = tb_path_absolute(dest, full1, TB_PATH_MAXN);
tb_assert_and_check_return_val(dest, tb_false);
// attempt to copy it directly
if (!copyfile(path, dest, 0, COPYFILE_ALL)) return tb_true;
else if (errno != EPERM && errno != EACCES)
{
// attempt to copy it again after creating directory
tb_char_t dir[TB_PATH_MAXN];
tb_int_t errno_bak = errno;
if (tb_directory_create(tb_path_directory(dest, dir, sizeof(dir))))
return !copyfile(path, dest, 0, COPYFILE_ALL);
else errno = errno_bak;
}
return tb_false;
}
#endif
tb_int_t ifd = -1;
tb_int_t ofd = -1;
tb_bool_t ok = tb_false;
do
{
// get stat.st_mode first
#ifdef TB_CONFIG_POSIX_HAVE_STAT64
struct stat64 st = {0};
if (stat64(path, &st)) break;
#else
struct stat st = {0};
if (stat(path, &st)) break;
#endif
// mark it as writeable
if (flags & TB_FILE_COPY_WRITEABLE)
st.st_mode |= S_IWUSR;
// open source file
ifd = open(path, O_RDONLY);
tb_check_break(ifd >= 0);
// get the absolute source path
dest = tb_path_absolute(dest, data, sizeof(data));
tb_assert_and_check_break(dest);
// open destinate file and copy file mode
ofd = open(dest, O_RDWR | O_CREAT | O_TRUNC, st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO));
if (ofd < 0 && (errno != EPERM && errno != EACCES))
{
// attempt to open it again after creating directory
tb_int_t errno_bak = errno;
tb_char_t dir[TB_PATH_MAXN];
if (tb_directory_create(tb_path_directory(dest, dir, sizeof(dir))))
ofd = open(dest, O_RDWR | O_CREAT | O_TRUNC, st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO));
else errno = errno_bak;
}
tb_check_break(ofd >= 0);
// get file size
tb_hize_t size = tb_file_size(tb_fd2file(ifd));
// init write size
tb_hize_t writ = 0;
// attempt to copy file using `sendfile`
#ifdef TB_CONFIG_POSIX_HAVE_SENDFILE
while (writ < size)
{
off_t seek = writ;
tb_hong_t real = sendfile(ofd, ifd, &seek, (size_t)(size - writ));
if (real > 0) writ += real;
else break;
}
/* attempt to copy file directly if sendfile failed
*
* sendfile() supports regular file only after "since Linux 2.6.33".
*/
if (writ != size)
{
lseek(ifd, 0, SEEK_SET);
lseek(ofd, 0, SEEK_SET);
}
else
{
ok = tb_true;
break;
}
#endif
// copy file using `read` and `write`
writ = 0;
while (writ < size)
{
// read some data
tb_int_t real = read(ifd, data, (size_t)tb_min(size - writ, sizeof(data)));
if (real > 0)
{
real = write(ofd, data, real);
if (real > 0) writ += real;
else break;
}
else break;
}
// ok?
ok = (writ == size);
} while (0);
// close source file
if (ifd >= 0) close(ifd);
ifd = -1;
// close destinate file
if (ofd >= 0) close(ofd);
ofd = -1;
return ok;
}
tb_bool_t tb_file_create(tb_char_t const* path)
{
tb_assert_and_check_return_val(path, tb_false);
tb_file_ref_t file = tb_file_init(path, TB_FILE_MODE_CREAT | TB_FILE_MODE_WO | TB_FILE_MODE_TRUNC);
if (file) tb_file_exit(file);
return file? tb_true : tb_false;
}
tb_bool_t tb_file_remove(tb_char_t const* path)
{
// check
tb_assert_and_check_return_val(path, tb_false);
// the full path
tb_char_t full[TB_PATH_MAXN];
path = tb_path_absolute(path, full, TB_PATH_MAXN);
tb_assert_and_check_return_val(path, tb_false);
// remove it
return !remove(path)? tb_true : tb_false;
}
tb_bool_t tb_file_rename(tb_char_t const* path, tb_char_t const* dest)
{
// check
tb_assert_and_check_return_val(path && dest, tb_false);
// the full path
tb_char_t full0[TB_PATH_MAXN];
path = tb_path_absolute(path, full0, TB_PATH_MAXN);
tb_assert_and_check_return_val(path, tb_false);
// the dest path
tb_char_t full1[TB_PATH_MAXN];
dest = tb_path_absolute(dest, full1, TB_PATH_MAXN);
tb_assert_and_check_return_val(dest, tb_false);
// attempt to rename it directly
if (!rename(path, dest)) return tb_true;
else if (errno != EPERM && errno != EACCES)
{
// attempt to rename it again after creating directory
tb_int_t errno_bak = errno;
tb_char_t dir[TB_PATH_MAXN];
if (tb_directory_create(tb_path_directory(dest, dir, sizeof(dir))))
return !rename(path, dest);
else errno = errno_bak;
}
return tb_false;
}
tb_bool_t tb_file_link(tb_char_t const* path, tb_char_t const* dest)
{
// check
tb_assert_and_check_return_val(path && dest, tb_false);
// the dest path
tb_char_t full1[TB_PATH_MAXN];
dest = tb_path_absolute(dest, full1, TB_PATH_MAXN);
tb_assert_and_check_return_val(dest, tb_false);
// attempt to link it directly
// @note we should not use absolute path, dest -> path (may be relative path)
if (!symlink(path, dest)) return tb_true;
else if (errno != EPERM && errno != EACCES)
{
// attempt to link it again after creating directory
tb_int_t errno_bak = errno;
tb_char_t dir[TB_PATH_MAXN];
if (tb_directory_create(tb_path_directory(dest, dir, sizeof(dir))))
return !symlink(path, dest);
else errno = errno_bak;
}
return tb_false;
}
tb_bool_t tb_file_access(tb_char_t const* path, tb_size_t mode)
{
// check
tb_assert_and_check_return_val(path, tb_false);
// the full path
tb_char_t full[TB_PATH_MAXN];
path = tb_path_absolute(path, full, TB_PATH_MAXN);
tb_assert_and_check_return_val(path, tb_false);
// flags
tb_size_t flags = 0;
if (mode & TB_FILE_MODE_RW) flags = R_OK | W_OK;
else
{
if (mode & TB_FILE_MODE_RO) flags |= R_OK;
if (mode & TB_FILE_MODE_WO) flags |= W_OK;
}
if (mode & TB_FILE_MODE_EXEC) flags |= X_OK;
return !access(full, flags);
}
tb_bool_t tb_file_touch(tb_char_t const* path, tb_time_t atime, tb_time_t mtime)
{
// check
tb_assert_and_check_return_val(path, tb_false);
// the full path
tb_char_t full[TB_PATH_MAXN];
path = tb_path_absolute(path, full, TB_PATH_MAXN);
tb_assert_and_check_return_val(path, tb_false);
// file exists?
tb_bool_t ok = tb_false;
struct timespec ts[2];
tb_memset(ts, 0, sizeof(ts));
if (!access(path, F_OK))
{
if (atime > 0 || mtime > 0)
{
#ifdef TB_CONFIG_POSIX_HAVE_UTIMENSAT
if (atime > 0) ts[0].tv_sec = atime;
else ts[0].tv_nsec = UTIME_OMIT;
if (mtime > 0) ts[1].tv_sec = mtime;
else ts[1].tv_nsec = UTIME_OMIT;
ok = !utimensat(AT_FDCWD, path, ts, 0);
#endif
}
else ok = tb_true;
}
else
{
// create a new file if not exists
tb_file_ref_t file = tb_file_init(path, TB_FILE_MODE_RW | TB_FILE_MODE_CREAT);
if (file)
{
if (atime > 0 || mtime > 0)
{
#ifdef TB_CONFIG_POSIX_HAVE_FUTIMENS
if (atime > 0) ts[0].tv_sec = atime;
else ts[0].tv_nsec = UTIME_OMIT;
if (mtime > 0) ts[1].tv_sec = mtime;
else ts[1].tv_nsec = UTIME_OMIT;
ok = !futimens(tb_file2fd(file), ts);
#endif
}
else ok = tb_true;
tb_file_exit(file);
}
}
return ok;
}
#endif
tbox-1.7.6/src/tbox/platform/posix/filelock.c 0000664 0000000 0000000 00000007454 14671175054 0021212 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file filelock.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../filelock.h"
#include
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the file lock type
typedef struct __tb_filelock_t
{
// the file reference
tb_file_ref_t file;
// is owner?
tb_bool_t owner;
}tb_filelock_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_filelock_ref_t tb_filelock_init_impl(tb_file_ref_t file, tb_bool_t owner)
{
// check
tb_assert_and_check_return_val(file, tb_null);
tb_filelock_t* lock = tb_null;
do
{
// init lock
lock = tb_malloc0_type(tb_filelock_t);
tb_assert_and_check_break(lock);
lock->file = file;
lock->owner = owner;
} while (0);
return (tb_filelock_ref_t)lock;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_filelock_ref_t tb_filelock_init(tb_file_ref_t file)
{
return tb_filelock_init_impl(file, tb_false);
}
tb_filelock_ref_t tb_filelock_init_from_path(tb_char_t const* path, tb_size_t mode)
{
tb_assert_and_check_return_val(path, tb_null);
return tb_filelock_init_impl(tb_file_init(path, mode), tb_true);
}
tb_void_t tb_filelock_exit(tb_filelock_ref_t self)
{
// check
tb_filelock_t* lock = (tb_filelock_t*)self;
tb_assert_and_check_return(lock);
// exit file
if (lock->file && lock->owner) tb_file_exit(lock->file);
lock->file = tb_null;
// exit lock
tb_free(lock);
}
tb_bool_t tb_filelock_enter(tb_filelock_ref_t self, tb_size_t mode)
{
// check
tb_filelock_t* lock = (tb_filelock_t*)self;
tb_assert_and_check_return_val(lock && lock->file, tb_false);
// lock it
struct flock flk = {0};
flk.l_type = (mode == TB_FILELOCK_MODE_EX)? F_WRLCK : F_RDLCK;
flk.l_start = 0;
flk.l_whence = SEEK_SET;
flk.l_len = 0;
flk.l_pid = getpid();
return fcntl(tb_file2fd(lock->file), F_SETLKW, &flk) == 0;
}
tb_bool_t tb_filelock_enter_try(tb_filelock_ref_t self, tb_size_t mode)
{
// check
tb_filelock_t* lock = (tb_filelock_t*)self;
tb_assert_and_check_return_val(lock && lock->file, tb_false);
// try to lock it
struct flock flk = {0};
flk.l_type = (mode == TB_FILELOCK_MODE_EX)? F_WRLCK : F_RDLCK;
flk.l_start = 0;
flk.l_whence = SEEK_SET;
flk.l_len = 0;
flk.l_pid = getpid();
return fcntl(tb_file2fd(lock->file), F_SETLK, &flk) == 0;
}
tb_bool_t tb_filelock_leave(tb_filelock_ref_t self)
{
// check
tb_filelock_t* lock = (tb_filelock_t*)self;
tb_assert_and_check_return_val(lock && lock->file, tb_false);
// unlock it
struct flock flk = {0};
flk.l_type = F_UNLCK;
flk.l_start = 0;
flk.l_whence = SEEK_SET;
flk.l_len = 0;
flk.l_pid = getpid();
return fcntl(tb_file2fd(lock->file), F_SETLK, &flk) == 0;
}
tbox-1.7.6/src/tbox/platform/posix/hostname.c 0000664 0000000 0000000 00000002117 14671175054 0021227 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file hostname.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_hostname(tb_char_t* name, tb_size_t size)
{
return !gethostname(name, size)? tb_true : tb_false;
}
tbox-1.7.6/src/tbox/platform/posix/ifaddrs.c 0000664 0000000 0000000 00000015560 14671175054 0021033 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file ifaddrs.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../ifaddrs.h"
#include
#ifdef TB_CONFIG_OS_LINUX
# include
#else
# include
#endif
#include
#include
#include "sockaddr.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_void_t tb_ifaddrs_interface_exit(tb_element_ref_t element, tb_pointer_t buff)
{
// check
tb_ifaddrs_interface_ref_t interface = (tb_ifaddrs_interface_ref_t)buff;
if (interface)
{
// exit the interface name
if (interface->name) tb_free(interface->name);
interface->name = tb_null;
}
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_ifaddrs_ref_t tb_ifaddrs_init()
{
// init it
return (tb_ifaddrs_ref_t)tb_list_init(8, tb_element_mem(sizeof(tb_ifaddrs_interface_t), tb_ifaddrs_interface_exit, tb_null));
}
tb_void_t tb_ifaddrs_exit(tb_ifaddrs_ref_t ifaddrs)
{
// exit it
if (ifaddrs) tb_list_exit((tb_list_ref_t)ifaddrs);
}
tb_iterator_ref_t tb_ifaddrs_itor(tb_ifaddrs_ref_t ifaddrs, tb_bool_t reload)
{
// check
tb_list_ref_t interfaces = (tb_list_ref_t)ifaddrs;
tb_assert_and_check_return_val(interfaces, tb_null);
// uses the cached interfaces?
tb_check_return_val(reload, (tb_iterator_ref_t)interfaces);
// clear interfaces first
tb_list_clear(interfaces);
// query the list of interfaces.
struct ifaddrs* list = tb_null;
if (!getifaddrs(&list) && list)
{
// done
struct ifaddrs* item = tb_null;
for (item = list; item; item = item->ifa_next)
{
// check
tb_check_continue(item->ifa_addr && item->ifa_name);
/* attempt to get the interface from the cached interfaces
* and make a new interface if no the cached interface
*/
tb_ifaddrs_interface_t interface_new = {0};
tb_ifaddrs_interface_ref_t interface = tb_ifaddrs_interface_find((tb_iterator_ref_t)interfaces, item->ifa_name);
if (!interface) interface = &interface_new;
// check
tb_assert(interface == &interface_new || interface->name);
// done
switch (item->ifa_addr->sa_family)
{
case AF_INET:
{
// the address
struct sockaddr_storage const* addr = (struct sockaddr_storage const*)item->ifa_addr;
// save ipaddr4
tb_ipaddr_t ipaddr4;
if (!tb_sockaddr_save(&ipaddr4, addr)) break;
interface->ipaddr4 = ipaddr4.u.ipv4;
// save flags
interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR4;
if ((item->ifa_flags & IFF_LOOPBACK) || tb_ipaddr_ip_is_loopback(&ipaddr4))
interface->flags |= TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK;
// new interface? save it
if (interface == &interface_new)
{
// save interface name
interface->name = tb_strdup(item->ifa_name);
tb_assert(interface->name);
// save interface
tb_list_insert_tail(interfaces, interface);
}
}
break;
case AF_INET6:
{
// the address
struct sockaddr_storage const* addr = (struct sockaddr_storage const*)item->ifa_addr;
// save ipaddr6
tb_ipaddr_t ipaddr6;
if (!tb_sockaddr_save(&ipaddr6, addr)) break;
interface->ipaddr6 = ipaddr6.u.ipv6;
// save flags
interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR6;
if ((item->ifa_flags & IFF_LOOPBACK) || tb_ipaddr_ip_is_loopback(&ipaddr6))
interface->flags |= TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK;
// new interface? save it
if (interface == &interface_new)
{
// save interface name
interface->name = tb_strdup(item->ifa_name);
tb_assert(interface->name);
// save interface
tb_list_insert_tail(interfaces, interface);
}
}
case AF_LINK:
{
// the address data
struct sockaddr_dl const* addr = (struct sockaddr_dl const*)item->ifa_addr;
tb_byte_t const* base = (tb_byte_t const*)(addr->sdl_data + addr->sdl_nlen);
// check
tb_check_break(addr->sdl_alen == sizeof(interface->hwaddr.u8));
// save flags
interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR;
if (item->ifa_flags & IFF_LOOPBACK) interface->flags |= TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK;
// save hwaddr
tb_memcpy(interface->hwaddr.u8, base, sizeof(interface->hwaddr.u8));
// new interface? save it
if (interface == &interface_new)
{
// save interface name
interface->name = tb_strdup(item->ifa_name);
tb_assert(interface->name);
// save interface
tb_list_insert_tail(interfaces, interface);
}
}
break;
default:
{
// trace
tb_trace_d("unknown family: %d", item->ifa_addr->sa_family);
}
break;
}
}
// exit the interface list
freeifaddrs(list);
}
// ok?
return (tb_iterator_ref_t)interfaces;
}
tbox-1.7.6/src/tbox/platform/posix/mutex.c 0000664 0000000 0000000 00000007012 14671175054 0020552 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file mutex.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../mutex.h"
#include "../impl/mutex.h"
#include "../../utils/utils.h"
#include
#include
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
tb_mutex_ref_t tb_mutex_init_impl(tb_mutex_t* mutex)
{
// init mutex, @note we cannot use asset/trace because them will use mutex
tb_assert_static(sizeof(pthread_mutex_t) == sizeof(tb_mutex_t));
return (mutex && !pthread_mutex_init(mutex, tb_null))? ((tb_mutex_ref_t)mutex) : tb_null;
}
tb_void_t tb_mutex_exit_impl(tb_mutex_t* mutex)
{
// exit it
if (mutex) pthread_mutex_destroy(mutex);
}
tb_bool_t tb_mutex_enter_without_profiler(tb_mutex_ref_t mutex)
{
// check, @note we cannot use asset/trace because them will use mutex
tb_check_return_val(mutex, tb_false);
// enter
return pthread_mutex_lock((pthread_mutex_t*)mutex) == 0;
}
tb_bool_t tb_mutex_entry_try_without_profiler(tb_mutex_ref_t mutex)
{
// check, @note we cannot use asset/trace because them will use mutex
tb_check_return_val(mutex, tb_false);
// try to enter
return pthread_mutex_trylock((pthread_mutex_t*)mutex) == 0;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_mutex_ref_t tb_mutex_init()
{
// make mutex
tb_mutex_t* pmutex = tb_malloc0(sizeof(tb_mutex_t));
tb_assert_and_check_return_val(pmutex, tb_null);
// init mutex
tb_mutex_ref_t mutex = tb_mutex_init_impl(pmutex);
if (mutex) return mutex;
else
{
if (pmutex) tb_free((tb_pointer_t)pmutex);
return tb_null;
}
}
tb_void_t tb_mutex_exit(tb_mutex_ref_t mutex)
{
// check
tb_assert_and_check_return(mutex);
// exit it
tb_mutex_t* pmutex = (tb_mutex_t*)mutex;
if (pmutex)
{
tb_mutex_exit_impl(pmutex);
tb_free((tb_pointer_t)pmutex);
}
}
tb_bool_t tb_mutex_enter(tb_mutex_ref_t mutex)
{
// try to enter for profiler
#ifdef TB_LOCK_PROFILER_ENABLE
if (tb_mutex_enter_try(mutex)) return tb_true;
#endif
// enter
return tb_mutex_enter_without_profiler(mutex);
}
tb_bool_t tb_mutex_enter_try(tb_mutex_ref_t mutex)
{
// try to enter
if (!tb_mutex_entry_try_without_profiler(mutex))
{
// occupied
#ifdef TB_LOCK_PROFILER_ENABLE
tb_lock_profiler_occupied(tb_lock_profiler(), (tb_handle_t)mutex);
#endif
return tb_false;
}
return tb_true;
}
tb_bool_t tb_mutex_leave(tb_mutex_ref_t mutex)
{
// check, @note we cannot use asset/trace because them will use mutex
tb_check_return_val(mutex, tb_false);
// leave
return pthread_mutex_unlock((pthread_mutex_t*)mutex) == 0;
}
tbox-1.7.6/src/tbox/platform/posix/page.c 0000664 0000000 0000000 00000003071 14671175054 0020325 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file page.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../platform.h"
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
// the page size
static tb_size_t g_page_size = 0;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_bool_t tb_page_init()
{
// init page size
if (!g_page_size)
{
#if defined(TB_CONFIG_POSIX_HAVE_SYSCONF) && defined(_SC_PAGESIZE)
g_page_size = (tb_size_t)sysconf(_SC_PAGESIZE);
#elif defined(TB_CONFIG_POSIX_HAVE_GETPAGESIZE)
g_page_size = (tb_size_t)getpagesize();
#endif
}
// ok?
return g_page_size? tb_true : tb_false;
}
tb_void_t tb_page_exit()
{
}
tb_size_t tb_page_size()
{
return g_page_size;
}
tbox-1.7.6/src/tbox/platform/posix/pipe.c 0000664 0000000 0000000 00000017454 14671175054 0020360 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file pipe.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../pipe.h"
#include "../file.h"
#include "../path.h"
#include "../socket.h"
#include "../directory.h"
#include "../../libc/libc.h"
#include
#include
#include
#include
#include
#if defined(TB_CONFIG_MODULE_HAVE_COROUTINE) \
&& !defined(TB_CONFIG_MICRO_ENABLE)
# include "../../coroutine/coroutine.h"
# include "../../coroutine/impl/impl.h"
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// fd to pipe file
#define tb_fd2pipefile(fd) ((fd) >= 0? (tb_pipe_file_ref_t)((tb_long_t)(fd) + 1) : tb_null)
// pipe file to fd
#define tb_pipefile2fd(file) (tb_int_t)((file)? (((tb_long_t)(file)) - 1) : -1)
/* //////////////////////////////////////////////////////////////////////////////////////
* declaration
*/
__tb_extern_c_enter__
tb_long_t tb_socket_wait_impl(tb_socket_ref_t sock, tb_size_t events, tb_long_t timeout);
__tb_extern_c_leave__
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
// get pipe file name
static __tb_inline__ tb_char_t const* tb_pipe_file_name(tb_char_t const* name, tb_char_t* data, tb_size_t maxn)
{
tb_size_t size = tb_directory_temporary(data, maxn);
if (size && size < maxn)
{
if (data[size - 1] != '/') data[size++] = '/';
if (size < maxn)
{
tb_strlcpy(data + size, name, maxn - size);
return data;
}
}
return tb_null;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#ifdef TB_CONFIG_POSIX_HAVE_MKFIFO
tb_pipe_file_ref_t tb_pipe_file_init(tb_char_t const* name, tb_size_t mode, tb_size_t buffer_size)
{
// check
tb_assert_and_check_return_val(name, tb_null);
tb_bool_t ok = tb_false;
tb_int_t fd = -1;
do
{
// get pipe name
tb_char_t buffer[TB_PATH_MAXN];
tb_char_t const* pipename = tb_pipe_file_name(name, buffer, tb_arrayn(buffer));
tb_assert_and_check_break(pipename);
// this pipe is not exists? we create it first
if (access(pipename, F_OK) != 0)
{
// 0644: -rw-r--r--
if (mkfifo(pipename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) != 0)
break;
}
// init flags
tb_size_t flags = 0;
if (mode & TB_PIPE_MODE_RO) flags |= O_RDONLY;
else if (mode & TB_PIPE_MODE_WO) flags |= O_WRONLY;
tb_assert_and_check_break(flags);
// open pipe file
fd = open(pipename, flags);
tb_assert_and_check_break(fd >= 0);
// set block mode
if (mode & TB_PIPE_MODE_BLOCK) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK);
else fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
// ok
ok = tb_true;
} while (0);
return ok? tb_fd2pipefile(fd) : tb_null;
}
#else
tb_pipe_file_ref_t tb_pipe_file_init(tb_char_t const* name, tb_size_t mode, tb_size_t buffer_size)
{
tb_trace_noimpl();
return tb_null;
}
#endif
#if defined(TB_CONFIG_POSIX_HAVE_PIPE) || defined(TB_CONFIG_POSIX_HAVE_PIPE2)
tb_bool_t tb_pipe_file_init_pair(tb_pipe_file_ref_t pair[2], tb_size_t mode[2], tb_size_t buffer_size)
{
// check
tb_assert_and_check_return_val(pair, tb_false);
tb_int_t pipefd[2] = {0};
tb_bool_t ok = tb_false;
do
{
// create pipe fd pair
#ifdef TB_CONFIG_POSIX_HAVE_PIPE2
if (pipe2(pipefd, O_NONBLOCK) == -1) break;
#else
if (pipe(pipefd) == -1) break;
#endif
// set block mode (default: non-block mode)
tb_size_t mode0 = mode? mode[0] : 0;
tb_size_t mode1 = mode? mode[1] : 0;
if (mode0 & TB_PIPE_MODE_BLOCK) fcntl(pipefd[0], F_SETFL, fcntl(pipefd[0], F_GETFL) & ~O_NONBLOCK);
else fcntl(pipefd[0], F_SETFL, fcntl(pipefd[0], F_GETFL) | O_NONBLOCK);
if (mode1 & TB_PIPE_MODE_BLOCK) fcntl(pipefd[1], F_SETFL, fcntl(pipefd[1], F_GETFL) & ~O_NONBLOCK);
else fcntl(pipefd[1], F_SETFL, fcntl(pipefd[1], F_GETFL) | O_NONBLOCK);
// save to file pair
pair[0] = tb_fd2pipefile(pipefd[0]);
pair[1] = tb_fd2pipefile(pipefd[1]);
// ok
ok = tb_true;
} while (0);
return ok;
}
#else
tb_bool_t tb_pipe_file_init_pair(tb_pipe_file_ref_t pair[2], tb_size_t mode[2], tb_size_t buffer_size)
{
tb_trace_noimpl();
return tb_false;
}
#endif
tb_bool_t tb_pipe_file_exit(tb_pipe_file_ref_t file)
{
// check
tb_assert_and_check_return_val(file, tb_false);
// trace
tb_trace_d("close: %p", file);
#ifdef TB_CONFIG_MODULE_HAVE_COROUTINE
// attempt to cancel waiting from coroutine first
tb_pointer_t scheduler_io = tb_null;
tb_poller_object_t object;
object.type = TB_POLLER_OBJECT_PIPE;
object.ref.pipe = file;
# ifndef TB_CONFIG_MICRO_ENABLE
if ((scheduler_io = tb_co_scheduler_io_self()) && tb_co_scheduler_io_cancel((tb_co_scheduler_io_ref_t)scheduler_io, &object)) {}
else
# endif
if ((scheduler_io = tb_lo_scheduler_io_self()) && tb_lo_scheduler_io_cancel((tb_lo_scheduler_io_ref_t)scheduler_io, &object)) {}
#endif
// close it
tb_bool_t ok = !close(tb_pipefile2fd(file));
if (!ok)
{
// trace
tb_trace_e("close: %p failed, errno: %d", file, errno);
}
return ok;
}
tb_long_t tb_pipe_file_connect(tb_pipe_file_ref_t file)
{
return 1;
}
tb_long_t tb_pipe_file_read(tb_pipe_file_ref_t file, tb_byte_t* data, tb_size_t size)
{
// check
tb_assert_and_check_return_val(file && data, -1);
tb_check_return_val(size, 0);
// read
tb_long_t real = read(tb_pipefile2fd(file), data, (tb_int_t)size);
// trace
tb_trace_d("read: %p %lu => %ld, errno: %d", file, size, real, errno);
// ok?
if (real >= 0) return real;
// continue?
if (errno == EINTR || errno == EAGAIN) return 0;
// error
return -1;
}
tb_long_t tb_pipe_file_write(tb_pipe_file_ref_t file, tb_byte_t const* data, tb_size_t size)
{
// check
tb_assert_and_check_return_val(file && data, -1);
tb_check_return_val(size, 0);
// write
tb_long_t real = write(tb_pipefile2fd(file), data, (tb_int_t)size);
// trace
tb_trace_d("write: %p %lu => %ld, errno: %d", file, size, real, errno);
// ok?
if (real >= 0) return real;
// continue?
if (errno == EINTR || errno == EAGAIN) return 0;
// error
return -1;
}
tb_long_t tb_pipe_file_wait(tb_pipe_file_ref_t file, tb_size_t events, tb_long_t timeout)
{
#if defined(TB_CONFIG_MODULE_HAVE_COROUTINE) \
&& !defined(TB_CONFIG_MICRO_ENABLE)
// attempt to wait it in coroutine if timeout is non-zero
if (timeout && tb_coroutine_self())
{
tb_poller_object_t object;
object.type = TB_POLLER_OBJECT_PIPE;
object.ref.pipe = file;
return tb_coroutine_waitio(&object, events, timeout);
}
#endif
// we use poll/select to wait pipe/fd events
return tb_socket_wait_impl((tb_socket_ref_t)file, events, timeout);
}
tbox-1.7.6/src/tbox/platform/posix/poller_poll.c 0000664 0000000 0000000 00000026236 14671175054 0021744 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file poller_poll.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../time.h"
#include "../../container/container.h"
#include "../../algorithm/algorithm.h"
#include
#include
#include
#if defined(TB_CONFIG_OS_HAIKU) || defined(__COSMOPOLITAN__)
# include
#elif !defined(TB_CONFIG_OS_ANDROID)
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the poller poll type
typedef struct __tb_poller_poll_t
{
// the poller base
tb_poller_t base;
// the pair sockets for spak, kill ..
tb_socket_ref_t pair[2];
// the poll fds
tb_vector_ref_t pfds;
// the copied poll fds
tb_vector_ref_t cfds;
// the socket data
tb_pollerdata_t pollerdata;
}tb_poller_poll_t, *tb_poller_poll_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_bool_t tb_poller_poll_walk_remove(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t priv)
{
// check
tb_assert(priv);
// the fd
tb_long_t fd = (tb_long_t)priv;
// the poll fd
struct pollfd* pfd = (struct pollfd*)item;
// remove it?
return (pfd && pfd->fd == fd);
}
static tb_bool_t tb_poller_poll_walk_modify(tb_iterator_ref_t iterator, tb_pointer_t item, tb_cpointer_t priv)
{
// check
tb_value_ref_t tuple = (tb_value_ref_t)priv;
tb_assert(tuple);
// the fd
tb_long_t fd = tuple[0].l;
// is this?
struct pollfd* pfd = (struct pollfd*)item;
if (pfd && pfd->fd == fd)
{
// the events
tb_size_t events = tuple[1].ul;
// modify events
pfd->events = 0;
if (events & TB_POLLER_EVENT_RECV) pfd->events |= POLLIN;
if (events & TB_POLLER_EVENT_SEND) pfd->events |= POLLOUT;
// break
return tb_false;
}
// ok
return tb_true;
}
static tb_void_t tb_poller_poll_exit(tb_poller_t* self)
{
// check
tb_poller_poll_ref_t poller = (tb_poller_poll_ref_t)self;
tb_assert_and_check_return(poller);
// exit pair sockets
if (poller->pair[0]) tb_socket_exit(poller->pair[0]);
if (poller->pair[1]) tb_socket_exit(poller->pair[1]);
poller->pair[0] = tb_null;
poller->pair[1] = tb_null;
// close pfds
if (poller->pfds) tb_vector_exit(poller->pfds);
poller->pfds = tb_null;
// close cfds
if (poller->cfds) tb_vector_exit(poller->cfds);
poller->cfds = tb_null;
// exit socket data
tb_pollerdata_exit(&poller->pollerdata);
// free it
tb_free(poller);
}
static tb_void_t tb_poller_poll_kill(tb_poller_t* self)
{
// check
tb_poller_poll_ref_t poller = (tb_poller_poll_ref_t)self;
tb_assert_and_check_return(poller);
// kill it
if (poller->pair[0]) tb_socket_send(poller->pair[0], (tb_byte_t const*)"k", 1);
}
static tb_void_t tb_poller_poll_spak(tb_poller_t* self)
{
// check
tb_poller_poll_ref_t poller = (tb_poller_poll_ref_t)self;
tb_assert_and_check_return(poller);
// post it
if (poller->pair[0]) tb_socket_send(poller->pair[0], (tb_byte_t const*)"p", 1);
}
static tb_bool_t tb_poller_poll_insert(tb_poller_t* self, tb_poller_object_ref_t object, tb_size_t events, tb_cpointer_t priv)
{
// check
tb_poller_poll_ref_t poller = (tb_poller_poll_ref_t)self;
tb_assert_and_check_return_val(poller && poller->pfds && object, tb_false);
// oneshot is not supported now
tb_assertf(!(events & TB_POLLER_EVENT_ONESHOT), "cannot insert events with oneshot, not supported!");
// init events
struct pollfd pfd = {0};
if (events & TB_POLLER_EVENT_RECV) pfd.events |= POLLIN;
if (events & TB_POLLER_EVENT_SEND) pfd.events |= POLLOUT;
// save fd, TODO uses binary search
pfd.fd = tb_ptr2fd(object->ref.ptr);
tb_vector_insert_tail(poller->pfds, &pfd);
// bind the object type to the private data
priv = tb_poller_priv_set_object_type(object, priv);
// bind user private data to socket
if (!(events & TB_POLLER_EVENT_NOEXTRA) || object->type == TB_POLLER_OBJECT_PIPE)
tb_pollerdata_set(&poller->pollerdata, object, priv);
// ok
return tb_true;
}
static tb_bool_t tb_poller_poll_remove(tb_poller_t* self, tb_poller_object_ref_t object)
{
// check
tb_poller_poll_ref_t poller = (tb_poller_poll_ref_t)self;
tb_assert_and_check_return_val(poller && poller->pfds && object, tb_false);
// remove this object and events, TODO uses binary search
tb_remove_first_if(poller->pfds, tb_poller_poll_walk_remove, (tb_cpointer_t)(tb_long_t)tb_ptr2fd(object->ref.ptr));
// remove user private data from this socket
tb_pollerdata_reset(&poller->pollerdata, object);
// ok
return tb_true;
}
static tb_bool_t tb_poller_poll_modify(tb_poller_t* self, tb_poller_object_ref_t object, tb_size_t events, tb_cpointer_t priv)
{
// check
tb_poller_poll_ref_t poller = (tb_poller_poll_ref_t)self;
tb_assert_and_check_return_val(poller && poller->pfds && object, tb_false);
// oneshot is not supported now
tb_assertf(!(events & TB_POLLER_EVENT_ONESHOT), "cannot insert events with oneshot, not supported!");
// modify events, TODO uses binary search
tb_value_t tuple[2];
tuple[0].l = tb_ptr2fd(object->ref.ptr);
tuple[1].ul = events;
tb_walk_all(poller->pfds, tb_poller_poll_walk_modify, tuple);
// bind the object type to the private data
priv = tb_poller_priv_set_object_type(object, priv);
// modify user private data to socket
if (!(events & TB_POLLER_EVENT_NOEXTRA) || object->type == TB_POLLER_OBJECT_PIPE)
tb_pollerdata_set(&poller->pollerdata, object, priv);
// ok
return tb_true;
}
static tb_long_t tb_poller_poll_wait(tb_poller_t* self, tb_poller_event_func_t func, tb_long_t timeout)
{
// check
tb_poller_poll_ref_t poller = (tb_poller_poll_ref_t)self;
tb_assert_and_check_return_val(poller && poller->pfds && poller->cfds && func, -1);
// loop
tb_long_t wait = 0;
tb_bool_t stop = tb_false;
tb_hong_t time = tb_mclock();
while (!wait && !stop && (timeout < 0 || tb_mclock() < time + timeout))
{
// pfds
struct pollfd* pfds = (struct pollfd*)tb_vector_data(poller->pfds);
tb_size_t pfdm = tb_vector_size(poller->pfds);
tb_assert_and_check_return_val(pfds && pfdm, -1);
// wait
tb_long_t pfdn = poll(pfds, pfdm, timeout);
// timeout or interrupted?
if (!pfdn || (pfdn == -1 && errno == EINTR))
return 0;
// error?
tb_assert_and_check_return_val(pfdn >= 0, -1);
// copy fds
tb_vector_copy(poller->cfds, poller->pfds);
// walk the copied fds
pfds = (struct pollfd*)tb_vector_data(poller->cfds);
pfdm = tb_vector_size(poller->cfds);
// sync
tb_size_t i = 0;
tb_poller_object_t object;
for (i = 0; i < pfdm; i++)
{
// get the object pointer
object.ref.ptr = tb_fd2ptr(pfds[i].fd);
tb_assert_and_check_return_val(object.ref.ptr, -1);
// the poll events
tb_size_t poll_events = pfds[i].revents;
tb_check_continue(poll_events);
// spak?
if (object.ref.sock == poller->pair[1] && (poll_events & POLLIN))
{
// read spak
tb_char_t spak = '\0';
if (1 != tb_socket_recv(poller->pair[1], (tb_byte_t*)&spak, 1)) return -1;
// killed?
if (spak == 'k') return -1;
// stop to wait
stop = tb_true;
// continue it
continue ;
}
// skip spak
tb_check_continue(object.ref.sock != poller->pair[1]);
// init events
tb_size_t events = TB_POLLER_EVENT_NONE;
if (poll_events & POLLIN) events |= TB_POLLER_EVENT_RECV;
if (poll_events & POLLOUT) events |= TB_POLLER_EVENT_SEND;
if ((poll_events & POLLHUP) && !(events & (TB_POLLER_EVENT_RECV | TB_POLLER_EVENT_SEND)))
events |= TB_POLLER_EVENT_RECV | TB_POLLER_EVENT_SEND;
// call event function
tb_cpointer_t priv = tb_pollerdata_get(&poller->pollerdata, &object);
object.type = tb_poller_priv_get_object_type(priv);
func((tb_poller_ref_t)self, &object, events, tb_poller_priv_get_original(priv));
// update the events count
wait++;
}
}
// ok
return wait;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_poller_t* tb_poller_poll_init()
{
tb_bool_t ok = tb_false;
tb_poller_poll_ref_t poller = tb_null;
do
{
// make poller
poller = tb_malloc0_type(tb_poller_poll_t);
tb_assert_and_check_break(poller);
// init base
poller->base.type = TB_POLLER_TYPE_POLL;
poller->base.exit = tb_poller_poll_exit;
poller->base.kill = tb_poller_poll_kill;
poller->base.spak = tb_poller_poll_spak;
poller->base.wait = tb_poller_poll_wait;
poller->base.insert = tb_poller_poll_insert;
poller->base.remove = tb_poller_poll_remove;
poller->base.modify = tb_poller_poll_modify;
poller->base.supported_events = TB_POLLER_EVENT_EALL;
// init poller data
tb_pollerdata_init(&poller->pollerdata);
// init poll fds
poller->pfds = tb_vector_init(0, tb_element_mem(sizeof(struct pollfd), tb_null, tb_null));
tb_assert_and_check_break(poller->pfds);
// init copied poll fds
poller->cfds = tb_vector_init(0, tb_element_mem(sizeof(struct pollfd), tb_null, tb_null));
tb_assert_and_check_break(poller->cfds);
// init pair sockets
if (!tb_socket_pair(TB_SOCKET_TYPE_TCP, poller->pair)) break;
// insert pair socket first
tb_poller_object_t object;
object.type = TB_POLLER_OBJECT_SOCK;
object.ref.sock = poller->pair[1];
if (!tb_poller_poll_insert((tb_poller_t*)poller, &object, TB_POLLER_EVENT_RECV, tb_null)) break;
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (poller) tb_poller_poll_exit((tb_poller_t*)poller);
poller = tb_null;
}
// ok?
return (tb_poller_t*)poller;
}
tbox-1.7.6/src/tbox/platform/posix/poller_process.c 0000664 0000000 0000000 00000033471 14671175054 0022453 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file poller_process.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../process.h"
#include "../thread.h"
#include "../atomic.h"
#include "../semaphore.h"
#include "../spinlock.h"
#include "../../algorithm/algorithm.h"
#include "../../container/container.h"
#include
#include
#include
#include
#include
#include
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the processes data type
typedef struct __tb_poller_processes_data_t
{
// the process reference
tb_process_ref_t process;
// the user private data
tb_cpointer_t priv;
}tb_poller_processes_data_t;
// the processes status type
typedef struct __tb_poller_processes_status_t
{
// the process id
tb_int_t pid;
// the process status
tb_int_t status;
}tb_poller_processes_status_t;
// the poller process type
typedef struct __tb_poller_process_t
{
// the main poller
tb_poller_t* main_poller;
// the process poller thread
tb_thread_ref_t thread;
// the waited processes data, pid => process and user private data
tb_hash_map_ref_t processes_data;
// the processes status
tb_vector_ref_t processes_status;
// the copied processes status
tb_vector_ref_t processes_status_copied;
// the semaphore
tb_semaphore_ref_t semaphore;
// is stopped?
tb_atomic32_t is_stopped;
// the lock
tb_spinlock_t lock;
}tb_poller_process_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* declaration
*/
__tb_extern_c_enter__
tb_int_t tb_process_pid(tb_process_ref_t self);
__tb_extern_c_leave__
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
// the global process poller
static tb_poller_process_t* g_process_poller = tb_null;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_int_t tb_poller_process_loop(tb_cpointer_t priv)
{
// check
tb_poller_process_t* poller = (tb_poller_process_t*)priv;
tb_assert_and_check_return_val(poller && poller->semaphore, -1);
while (!tb_atomic32_get(&poller->is_stopped))
{
// trace
tb_trace_d("process: waitpid ..");
// wait semaphore
tb_long_t wait = tb_semaphore_wait(poller->semaphore, -1);
tb_assert_and_check_break(wait >= 0);
// interrupted? continue to wait
tb_check_continue(wait != 0);
tb_int_t result = -1;
tb_bool_t has_exited = tb_false;
do
{
// poll processes
tb_int_t status = -1;
result = waitpid(-1, &status, WNOHANG | WUNTRACED);
// trace
tb_trace_d("process: finished: %d, status: %d", result, status);
// has exited process?
if (result != 0 && result != -1)
{
/* get status, only get 8bits retval
*
* tt's limited to 8-bits, which means 1 byte,
* which means the int from WEXITSTATUS can only range from 0-255.
*
* in fact, any unix program will only ever return a max of 255.
*/
tb_poller_processes_status_t object_event;
object_event.status = WIFEXITED(status)? WEXITSTATUS(status) : -1;
object_event.pid = result;
// save the process status
tb_spinlock_enter(&poller->lock);
tb_vector_insert_tail(poller->processes_status, &object_event);
has_exited = tb_true;
tb_spinlock_leave(&poller->lock);
}
} while (result != 0 && result != -1);
// has exited child processes? notify the main poller to poll them
if (has_exited)
{
tb_poller_t* main_poller = poller->main_poller;
if (main_poller && main_poller->spak)
main_poller->spak(main_poller);
}
}
// mark this thread is stopped
tb_atomic32_set(&poller->is_stopped, 1);
return 0;
}
static tb_void_t tb_poller_process_signal_handler(tb_int_t signo)
{
// post semaphore to wait processes
if (g_process_poller && g_process_poller->semaphore)
tb_semaphore_post(g_process_poller->semaphore, 1);
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
static tb_void_t tb_poller_process_kill(tb_poller_process_ref_t self)
{
// check
tb_poller_process_t* poller = (tb_poller_process_t*)self;
tb_assert_and_check_return(poller && poller->semaphore);
// trace
tb_trace_d("process: kill ..");
// stop thread and post it
if (!tb_atomic32_fetch_and_set(&poller->is_stopped, 1))
tb_semaphore_post(poller->semaphore, 1);
}
static tb_void_t tb_poller_process_exit(tb_poller_process_ref_t self)
{
// check
tb_poller_process_t* poller = (tb_poller_process_t*)self;
tb_assert_and_check_return(poller);
// kill the process poller first
tb_poller_process_kill(self);
// exit the process poller thread
if (poller->thread)
{
// wait it
tb_long_t wait = 0;
if ((wait = tb_thread_wait(poller->thread, 5000, tb_null)) <= 0)
{
// trace
tb_trace_e("wait process poller thread failed: %ld!", wait);
}
// exit it
tb_thread_exit(poller->thread);
poller->thread = tb_null;
}
// clear signal
signal(SIGCHLD, SIG_DFL);
g_process_poller = tb_null;
// exit the processes data
if (poller->processes_data) tb_hash_map_exit(poller->processes_data);
poller->processes_data = tb_null;
// exit the processes status
if (poller->processes_status) tb_vector_exit(poller->processes_status);
poller->processes_status = tb_null;
if (poller->processes_status_copied) tb_vector_exit(poller->processes_status_copied);
poller->processes_status_copied = tb_null;
// exit semaphore
if (poller->semaphore) tb_semaphore_exit(poller->semaphore);
poller->semaphore = tb_null;
// exit lock
tb_spinlock_exit(&poller->lock);
// exit poller
tb_free(poller);
}
static tb_poller_process_ref_t tb_poller_process_init(tb_poller_t* main_poller)
{
tb_bool_t ok = tb_false;
tb_poller_process_t* poller = tb_null;
do
{
// @note only support one process poller instance
static tb_size_t s_poller_process_num = 0;
if (s_poller_process_num++)
{
tb_trace_e("only support one process poller!");
break;
}
// make the process poller
poller = tb_malloc0_type(tb_poller_process_t);
tb_assert_and_check_break(poller);
// save the main poller
poller->main_poller = main_poller;
// init the processes data first
poller->processes_data = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_uint32(), tb_element_mem(sizeof(tb_poller_processes_data_t), tb_null, tb_null));
tb_assert_and_check_break(poller->processes_data);
// init semaphore
poller->semaphore = tb_semaphore_init(0);
tb_assert_and_check_break(poller->semaphore);
// init lock
tb_spinlock_init(&poller->lock);
// init the processes status
poller->processes_status = tb_vector_init(0, tb_element_mem(sizeof(tb_poller_processes_status_t), tb_null, tb_null));
tb_assert_and_check_break(poller->processes_status);
// init the copied processes status
poller->processes_status_copied = tb_vector_init(0, tb_element_mem(sizeof(tb_poller_processes_status_t), tb_null, tb_null));
tb_assert_and_check_break(poller->processes_status_copied);
// start the poller thread for processes first
poller->thread = tb_thread_init(tb_null, tb_poller_process_loop, poller, 0);
tb_assert_and_check_break(poller->thread);
// register signal
signal(SIGCHLD, tb_poller_process_signal_handler);
g_process_poller = poller;
// ok
ok = tb_true;
} while (0);
// failed? exit the poller
if (!ok)
{
if (poller) tb_poller_process_exit((tb_poller_process_ref_t)poller);
poller = tb_null;
}
return (tb_poller_process_ref_t)poller;
}
static tb_void_t tb_poller_process_spak(tb_poller_process_ref_t self)
{
// check
tb_poller_process_t* poller = (tb_poller_process_t*)self;
tb_assert_and_check_return(poller && poller->semaphore);
// trace
tb_trace_d("process: spak ..");
// post it
tb_semaphore_post(poller->semaphore, 1);
}
static tb_bool_t tb_poller_process_insert(tb_poller_process_ref_t self, tb_process_ref_t process, tb_cpointer_t priv)
{
// check
tb_poller_process_t* poller = (tb_poller_process_t*)self;
tb_assert_and_check_return_val(poller && poller->processes_data && process, tb_false);
// get pid
tb_int_t pid = tb_process_pid(process);
tb_assert_and_check_return_val(pid != -1, tb_false);
// trace
tb_trace_d("process: insert pid: %d with priv: %p", pid, priv);
// insert this process and the user private data
tb_poller_processes_data_t procdata;
procdata.process = process;
procdata.priv = priv;
tb_hash_map_insert(poller->processes_data, tb_i2p(pid), &procdata);
return tb_true;
}
static tb_bool_t tb_poller_process_modify(tb_poller_process_ref_t self, tb_process_ref_t process, tb_cpointer_t priv)
{
// check
tb_poller_process_t* poller = (tb_poller_process_t*)self;
tb_assert_and_check_return_val(poller && poller->processes_data && process, tb_false);
// get pid
tb_int_t pid = tb_process_pid(process);
tb_assert_and_check_return_val(pid != -1, tb_false);
// trace
tb_trace_d("process: modify pid: %d with priv: %p", pid, priv);
// modify the user private data of this process
if (tb_hash_map_find(poller->processes_data, tb_i2p(pid)) != tb_iterator_tail(poller->processes_data))
{
tb_poller_processes_data_t procdata;
procdata.process = process;
procdata.priv = priv;
tb_hash_map_insert(poller->processes_data, tb_i2p(pid), &procdata);
}
return tb_true;
}
static tb_bool_t tb_poller_process_remove(tb_poller_process_ref_t self, tb_process_ref_t process)
{
// check
tb_poller_process_t* poller = (tb_poller_process_t*)self;
tb_assert_and_check_return_val(poller && poller->processes_data && process, tb_false);
// get pid
tb_int_t pid = tb_process_pid(process);
tb_assert_and_check_return_val(pid != -1, tb_false);
// trace
tb_trace_d("process: remove pid: %d", pid);
// remove this process and the user private data
tb_hash_map_remove(poller->processes_data, tb_i2p(pid));
return tb_true;
}
static tb_bool_t tb_poller_process_wait_prepare(tb_poller_process_ref_t self)
{
// check
tb_poller_process_t* poller = (tb_poller_process_t*)self;
tb_assert_and_check_return_val(poller && poller->processes_data && poller->semaphore, tb_false);
// trace
tb_trace_d("process: prepare %lu", tb_hash_map_size(poller->processes_data));
// some processes maybe have been exited before starting the loop thread, so we need notify to waitpid
if (tb_hash_map_size(poller->processes_data) && !tb_semaphore_post(poller->semaphore, 1))
return tb_false;
// is stopped?
return !tb_atomic32_get(&poller->is_stopped);
}
static tb_long_t tb_poller_process_wait_poll(tb_poller_process_ref_t self, tb_poller_event_func_t func)
{
// check
tb_poller_process_t* poller = (tb_poller_process_t*)self;
tb_assert_and_check_return_val(poller && poller->processes_data && func, -1);
tb_assert_and_check_return_val(poller->processes_status && poller->processes_status_copied, -1);
// get all processes status
tb_vector_clear(poller->processes_status_copied);
tb_spinlock_enter(&poller->lock);
if (tb_vector_size(poller->processes_status))
{
tb_vector_copy(poller->processes_status_copied, poller->processes_status);
tb_vector_clear(poller->processes_status);
}
tb_spinlock_leave(&poller->lock);
// trace
tb_trace_d("process: poll %lu", tb_vector_size(poller->processes_status_copied));
// poll all waited processes status
tb_long_t wait = 0;
tb_poller_object_t object;
object.type = TB_POLLER_OBJECT_PROC;
tb_for_all_if (tb_poller_processes_status_t*, object_event, poller->processes_status_copied, object_event)
{
// trace
tb_trace_d("process: pid: %d", object_event->pid);
tb_poller_processes_data_t* proc_data = tb_hash_map_get(poller->processes_data, tb_i2p(object_event->pid));
if (proc_data)
{
object.ref.proc = proc_data->process;
func((tb_poller_ref_t)poller->main_poller, &object, object_event->status, proc_data->priv);
wait++;
}
}
// trace
tb_trace_d("process: poll wait %ld", wait);
return wait;
}
tbox-1.7.6/src/tbox/platform/posix/poller_select.c 0000664 0000000 0000000 00000034315 14671175054 0022252 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file poller_select.c
*
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../time.h"
#include "../../container/container.h"
#include "../../algorithm/algorithm.h"
#ifdef TB_CONFIG_OS_WINDOWS
# include "../windows/interface/interface.h"
#else
# include
# include
# include
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
// FD_ISSET
#ifdef TB_CONFIG_OS_WINDOWS
# undef FD_ISSET
# define FD_ISSET(fd, set) tb_ws2_32()->__WSAFDIsSet((SOCKET)(fd), (fd_set FAR *)(set))
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
// the poller private data type
typedef struct __tb_poller_select_data_t
{
// the fd
tb_long_t fd;
// the user private data
tb_cpointer_t priv;
// the socket events
tb_size_t events;
}tb_poller_select_data_t, *tb_poller_select_data_ref_t;
// the poller select type
typedef struct __tb_poller_select_t
{
// the poller base
tb_poller_t base;
// the pair sockets for spak, kill ..
tb_socket_ref_t pair[2];
// the select fd max
tb_size_t sfdm;
// the select fds
fd_set rfds;
fd_set wfds;
// the copied fds
fd_set rfdc;
fd_set wfdc;
// the socket count
tb_size_t count;
/* the user private data list
*
* do not use hash_map because it is too heavy in micro mode
*/
tb_poller_select_data_ref_t list;
// the user private data list size
tb_size_t list_size;
}tb_poller_select_t, *tb_poller_select_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_void_t tb_poller_select_list_set(tb_poller_select_ref_t poller, tb_long_t fd, tb_size_t events, tb_cpointer_t priv)
{
// check
tb_assert(poller);
// no list? init it first
if (!poller->list)
{
// init list
poller->list = tb_nalloc0_type(FD_SETSIZE, tb_poller_select_data_t);
tb_assert_and_check_return(poller->list);
}
// insert or update the user private data to the list in the increasing order (TODO binary search)
tb_size_t i = 0;
tb_size_t n = poller->list_size;
for (i = 0; i < n; i++) if (fd <= poller->list[i].fd) break;
// update the private data
if (i < n && fd == poller->list[i].fd)
{
poller->list[i].priv = priv;
poller->list[i].events = events;
}
else
{
// insert the private data
if (i < n) tb_memmov_(poller->list + i + 1, poller->list + i, (n - i) * sizeof(tb_poller_select_data_t));
poller->list[i].fd = fd;
poller->list[i].priv = priv;
poller->list[i].events = events;
// update the list size
poller->list_size++;
}
}
static tb_void_t tb_poller_select_list_del(tb_poller_select_ref_t poller, tb_long_t fd)
{
// check
tb_assert(poller);
// exists list?
if (poller->list)
{
// remove the user private data from the list (TODO binary search)
tb_size_t i = 0;
tb_size_t n = poller->list_size;
for (i = 0; i < n; i++) if (fd == poller->list[i].fd) break;
// found and remove it
if (i < n)
{
if (i + 1 < n) tb_memmov_(poller->list + i, poller->list + i + 1, (n - i - 1) * sizeof(tb_poller_select_data_t));
poller->list_size--;
}
}
}
static tb_void_t tb_poller_select_exit(tb_poller_t* self)
{
// check
tb_poller_select_ref_t poller = (tb_poller_select_ref_t)self;
tb_assert_and_check_return(poller);
// exit pair sockets
if (poller->pair[0]) tb_socket_exit(poller->pair[0]);
if (poller->pair[1]) tb_socket_exit(poller->pair[1]);
poller->pair[0] = tb_null;
poller->pair[1] = tb_null;
// exit list
if (poller->list) tb_free(poller->list);
poller->list = tb_null;
poller->list_size = 0;
// clear fds
FD_ZERO(&poller->rfds);
FD_ZERO(&poller->wfds);
FD_ZERO(&poller->rfdc);
FD_ZERO(&poller->wfdc);
// free it
tb_free(poller);
}
static tb_void_t tb_poller_select_kill(tb_poller_t* self)
{
// check
tb_poller_select_ref_t poller = (tb_poller_select_ref_t)self;
tb_assert_and_check_return(poller);
// kill it
if (poller->pair[0]) tb_socket_send(poller->pair[0], (tb_byte_t const*)"k", 1);
}
static tb_void_t tb_poller_select_spak(tb_poller_t* self)
{
// check
tb_poller_select_ref_t poller = (tb_poller_select_ref_t)self;
tb_assert_and_check_return(poller);
// post it
if (poller->pair[0]) tb_socket_send(poller->pair[0], (tb_byte_t const*)"p", 1);
}
static tb_bool_t tb_poller_select_insert(tb_poller_t* self, tb_poller_object_ref_t object, tb_size_t events, tb_cpointer_t priv)
{
// check
tb_poller_select_ref_t poller = (tb_poller_select_ref_t)self;
tb_assert_and_check_return_val(poller && object, tb_false);
// check size
tb_assert_and_check_return_val(poller->count < FD_SETSIZE, tb_false);
#ifdef TB_CONFIG_OS_WINDOWS
// do not support pipe fd on windows
tb_assert_and_check_return_val(object->type != TB_POLLER_OBJECT_PIPE, tb_false);
#endif
// save fd
tb_long_t fd = tb_ptr2fd(object->ref.ptr);
if (fd > (tb_long_t)poller->sfdm) poller->sfdm = (tb_size_t)fd;
if (events & TB_POLLER_EVENT_RECV) FD_SET(fd, &poller->rfds);
if (events & TB_POLLER_EVENT_SEND) FD_SET(fd, &poller->wfds);
// bind the object type to the private data
priv = tb_poller_priv_set_object_type(object, priv);
// bind user private data to socket
tb_poller_select_list_set(poller, fd, events, priv);
// update socket count
poller->count++;
// ok
return tb_true;
}
static tb_bool_t tb_poller_select_remove(tb_poller_t* self, tb_poller_object_ref_t object)
{
// check
tb_poller_select_ref_t poller = (tb_poller_select_ref_t)self;
tb_assert_and_check_return_val(poller && object, tb_false);
// remove fds
tb_long_t fd = tb_ptr2fd(object->ref.ptr);
FD_CLR(fd, &poller->rfds);
FD_CLR(fd, &poller->wfds);
// remove user private data from this socket
tb_poller_select_list_del(poller, fd);
// update socket count
if (poller->count > 0) poller->count--;
// ok
return tb_true;
}
static tb_bool_t tb_poller_select_modify(tb_poller_t* self, tb_poller_object_ref_t object, tb_size_t events, tb_cpointer_t priv)
{
// check
tb_poller_select_ref_t poller = (tb_poller_select_ref_t)self;
tb_assert_and_check_return_val(poller && object, tb_false);
// modify events
tb_long_t fd = tb_ptr2fd(object->ref.ptr);
if (events & TB_POLLER_EVENT_RECV) FD_SET(fd, &poller->rfds); else FD_CLR(fd, &poller->rfds);
if (events & TB_POLLER_EVENT_SEND) FD_SET(fd, &poller->wfds); else FD_CLR(fd, &poller->wfds);
// bind the object type to the private data
priv = tb_poller_priv_set_object_type(object, priv);
// modify user private data to socket
tb_poller_select_list_set(poller, fd, events, priv);
// ok
return tb_true;
}
static tb_long_t tb_poller_select_wait(tb_poller_t* self, tb_poller_event_func_t func, tb_long_t timeout)
{
// check
tb_poller_select_ref_t poller = (tb_poller_select_ref_t)self;
tb_assert_and_check_return_val(poller && func, -1);
// init time
struct timeval t = {0};
if (timeout > 0)
{
#ifdef TB_CONFIG_OS_WINDOWS
t.tv_sec = (LONG)(timeout / 1000);
#else
t.tv_sec = (timeout / 1000);
#endif
t.tv_usec = (timeout % 1000) * 1000;
}
// loop
tb_long_t wait = 0;
tb_bool_t stop = tb_false;
tb_hong_t time = tb_mclock();
tb_poller_select_data_t poller_events[512];
while (!wait && !stop && (timeout < 0 || tb_mclock() < time + timeout))
{
// copy fds
tb_memcpy(&poller->rfdc, &poller->rfds, sizeof(fd_set));
tb_memcpy(&poller->wfdc, &poller->wfds, sizeof(fd_set));
// wait
#ifdef TB_CONFIG_OS_WINDOWS
tb_long_t sfdn = tb_ws2_32()->select((tb_int_t) poller->sfdm + 1, &poller->rfdc, &poller->wfdc, tb_null, timeout >= 0? &t : tb_null);
if (!sfdn) return 0; // timeout
#else
tb_long_t sfdn = select(poller->sfdm + 1, &poller->rfdc, &poller->wfdc, tb_null, timeout >= 0? &t : tb_null);
if (!sfdn || (sfdn == -1 && errno == EINTR)) // timeout or interrupted?
return 0;
#endif
// error?
tb_assert_and_check_return_val(sfdn >= 0, -1);
// dispatch events
tb_size_t i = 0;
tb_size_t n = poller->list_size;
tb_size_t eventn = 0;
for (i = 0; i < n; i++)
{
// end?
tb_check_break(wait >= 0);
// check
tb_assert_and_check_return_val(poller->list, -1);
// get the object pointer
tb_long_t fd = poller->list[i].fd;
tb_cpointer_t ptr = tb_fd2ptr(fd);
tb_assert_and_check_return_val(ptr, -1);
// spank socket events?
if ((tb_socket_ref_t)ptr == poller->pair[1] && FD_ISSET(tb_sock2fd(poller->pair[1]), &poller->rfdc))
{
// read spak
tb_char_t spak = '\0';
if (1 != tb_socket_recv(poller->pair[1], (tb_byte_t*)&spak, 1)) wait = -1;
// killed?
if (spak == 'k') wait = -1;
tb_check_break(wait >= 0);
// stop to wait
stop = tb_true;
// continue it
continue ;
}
// filter spak
tb_check_continue((tb_socket_ref_t)ptr != poller->pair[1]);
// init events
tb_size_t events = TB_POLLER_EVENT_NONE;
if (FD_ISSET(fd, &poller->rfdc)) events |= TB_POLLER_EVENT_RECV;
if (FD_ISSET(fd, &poller->wfdc)) events |= TB_POLLER_EVENT_SEND;
// check socket error?
#ifdef TB_CONFIG_OS_WINDOWS
tb_int_t error = 0;
tb_int_t n = sizeof(tb_int_t);
if (!tb_ws2_32()->getsockopt(fd, SOL_SOCKET, SO_ERROR, (tb_char_t*)&error, &n) && error)
events |= TB_POLLER_EVENT_ERROR;
#else
tb_int_t error = 0;
socklen_t n = sizeof(socklen_t);
if (!getsockopt(fd, SOL_SOCKET, SO_ERROR, (tb_char_t*)&error, &n) && error)
events |= TB_POLLER_EVENT_ERROR;
#endif
// exists events?
if (events)
{
// oneshot?
if (poller->list[i].events & TB_POLLER_EVENT_ONESHOT)
events |= TB_POLLER_EVENT_ONESHOT;
// save triggered events
tb_assert_and_check_break(eventn < tb_arrayn(poller_events));
poller_events[eventn].fd = fd;
poller_events[eventn].priv = poller->list[i].priv;
poller_events[eventn].events = events;
eventn++;
// update the events count
wait++;
}
}
// call events function
tb_size_t eventi;
tb_poller_object_t object;
for (eventi = 0; eventi < eventn; eventi++)
{
// get events and private data
tb_size_t events = poller_events[eventi].events;
tb_cpointer_t priv = poller_events[eventi].priv;
// get the poller object
object.type = tb_poller_priv_get_object_type(priv);
object.ref.ptr = tb_fd2ptr(poller_events[eventi].fd);
if (events & TB_POLLER_EVENT_ONESHOT)
{
events &= ~TB_POLLER_EVENT_ONESHOT;
tb_poller_select_remove(self, &object);
}
func((tb_poller_ref_t)self, &object, events, tb_poller_priv_get_original(priv));
}
}
// ok
return wait;
}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
tb_poller_t* tb_poller_select_init()
{
tb_bool_t ok = tb_false;
tb_poller_select_ref_t poller = tb_null;
do
{
// make poller
poller = tb_malloc0_type(tb_poller_select_t);
tb_assert_and_check_break(poller);
// init base
poller->base.type = TB_POLLER_TYPE_SELECT;
poller->base.exit = tb_poller_select_exit;
poller->base.kill = tb_poller_select_kill;
poller->base.spak = tb_poller_select_spak;
poller->base.wait = tb_poller_select_wait;
poller->base.insert = tb_poller_select_insert;
poller->base.remove = tb_poller_select_remove;
poller->base.modify = tb_poller_select_modify;
poller->base.supported_events = TB_POLLER_EVENT_EALL | TB_POLLER_EVENT_ONESHOT;
// init fds
FD_ZERO(&poller->rfds);
FD_ZERO(&poller->wfds);
FD_ZERO(&poller->rfdc);
FD_ZERO(&poller->wfdc);
// init pair sockets
if (!tb_socket_pair(TB_SOCKET_TYPE_TCP, poller->pair)) break;
// insert pair socket first
tb_poller_object_t object;
object.type = TB_POLLER_OBJECT_SOCK;
object.ref.sock = poller->pair[1];
if (!tb_poller_select_insert((tb_poller_t*)poller, &object, TB_POLLER_EVENT_RECV, tb_null)) break;
// ok
ok = tb_true;
} while (0);
// failed?
if (!ok)
{
// exit it
if (poller) tb_poller_select_exit((tb_poller_t*)poller);
poller = tb_null;
}
// ok?
return (tb_poller_t*)poller;
}
tbox-1.7.6/src/tbox/platform/posix/prefix.h 0000664 0000000 0000000 00000001737 14671175054 0020722 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
* @ingroup platform
*/
#ifndef TB_PLATFORM_POSIX_PREFIX_H
#define TB_PLATFORM_POSIX_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
#include "../../libc/libc.h"
#include "../../utils/utils.h"
#endif
tbox-1.7.6/src/tbox/platform/posix/process.c 0000664 0000000 0000000 00000101446 14671175054 0021074 0 ustar 00root root 0000000 0000000 /*!The Treasure Box Library
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2009-present, TBOOX Open Source Group.
*
* @author ruki
* @file process.c
* @ingroup platform
*/
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
#include "../file.h"
#include "../path.h"
#include "../time.h"
#include "../process.h"
#include "../environment.h"
#include "../spinlock.h"
#include "../../container/container.h"
#include "../../algorithm/algorithm.h"
#include "../../libc/libc.h"
#include
#include
#include
#include
#include