summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2019-02-08 23:45:06 +0800
committerruki <[email protected]>2019-02-08 16:30:39 +0800
commit9342904338fe355892decb82b8b9fc4d3273d9be (patch)
tree5390b307c01374ea5722594dd1a0e682b45a8e4c
parent04f4888bf721d9d78b0feb56c392122966a36a4e (diff)
update tbox
-rw-r--r--core/src/tbox/makefile7
-rw-r--r--core/src/tbox/src/tbox/algorithm/algorithm.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/binary_find.c2
-rw-r--r--core/src/tbox/src/tbox/algorithm/binary_find.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/binary_find_if.c2
-rw-r--r--core/src/tbox/src/tbox/algorithm/binary_find_if.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/bubble_sort.c2
-rw-r--r--core/src/tbox/src/tbox/algorithm/bubble_sort.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/count.c2
-rw-r--r--core/src/tbox/src/tbox/algorithm/count.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/count_if.c2
-rw-r--r--core/src/tbox/src/tbox/algorithm/count_if.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/distance.c2
-rw-r--r--core/src/tbox/src/tbox/algorithm/distance.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/find.c2
-rw-r--r--core/src/tbox/src/tbox/algorithm/find.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/find_if.c2
-rw-r--r--core/src/tbox/src/tbox/algorithm/find_if.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/for.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/for_if.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/heap_sort.c2
-rw-r--r--core/src/tbox/src/tbox/algorithm/heap_sort.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/insert_sort.c2
-rw-r--r--core/src/tbox/src/tbox/algorithm/insert_sort.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/predicate.c2
-rw-r--r--core/src/tbox/src/tbox/algorithm/predicate.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/quick_sort.c2
-rw-r--r--core/src/tbox/src/tbox/algorithm/quick_sort.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/remove.c2
-rw-r--r--core/src/tbox/src/tbox/algorithm/remove.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/remove_first.c2
-rw-r--r--core/src/tbox/src/tbox/algorithm/remove_first.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/remove_first_if.c2
-rw-r--r--core/src/tbox/src/tbox/algorithm/remove_first_if.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/remove_if.c26
-rw-r--r--core/src/tbox/src/tbox/algorithm/remove_if.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/rfind.c2
-rw-r--r--core/src/tbox/src/tbox/algorithm/rfind.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/rfind_if.c2
-rw-r--r--core/src/tbox/src/tbox/algorithm/rfind_if.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/rfor.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/rfor_if.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/rwalk.c2
-rw-r--r--core/src/tbox/src/tbox/algorithm/rwalk.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/sort.c4
-rw-r--r--core/src/tbox/src/tbox/algorithm/sort.h2
-rw-r--r--core/src/tbox/src/tbox/algorithm/walk.c2
-rw-r--r--core/src/tbox/src/tbox/algorithm/walk.h2
-rw-r--r--core/src/tbox/src/tbox/charset/ascii.c2
-rw-r--r--core/src/tbox/src/tbox/charset/charset.c6
-rw-r--r--core/src/tbox/src/tbox/charset/charset.h2
-rw-r--r--core/src/tbox/src/tbox/charset/gb2312.c2
-rw-r--r--core/src/tbox/src/tbox/charset/gb2312.g2
-rw-r--r--core/src/tbox/src/tbox/charset/iso8859.c2
-rw-r--r--core/src/tbox/src/tbox/charset/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/charset/ucs2.c2
-rw-r--r--core/src/tbox/src/tbox/charset/ucs4.c2
-rw-r--r--core/src/tbox/src/tbox/charset/utf16.c2
-rw-r--r--core/src/tbox/src/tbox/charset/utf32.c2
-rw-r--r--core/src/tbox/src/tbox/charset/utf8.c2
-rw-r--r--core/src/tbox/src/tbox/config.h2
-rw-r--r--core/src/tbox/src/tbox/container/array_iterator.c319
-rw-r--r--core/src/tbox/src/tbox/container/array_iterator.h127
-rw-r--r--core/src/tbox/src/tbox/container/bloom_filter.c2
-rw-r--r--core/src/tbox/src/tbox/container/bloom_filter.h2
-rw-r--r--core/src/tbox/src/tbox/container/circle_queue.c30
-rw-r--r--core/src/tbox/src/tbox/container/circle_queue.h2
-rw-r--r--core/src/tbox/src/tbox/container/container.h3
-rw-r--r--core/src/tbox/src/tbox/container/element.h2
-rw-r--r--core/src/tbox/src/tbox/container/element/hash.c2
-rw-r--r--core/src/tbox/src/tbox/container/element/hash.h12
-rw-r--r--core/src/tbox/src/tbox/container/element/long.c2
-rw-r--r--core/src/tbox/src/tbox/container/element/mem.c2
-rw-r--r--core/src/tbox/src/tbox/container/element/null.c2
-rw-r--r--core/src/tbox/src/tbox/container/element/obj.c2
-rw-r--r--core/src/tbox/src/tbox/container/element/prefix.h3
-rw-r--r--core/src/tbox/src/tbox/container/element/ptr.c2
-rw-r--r--core/src/tbox/src/tbox/container/element/size.c2
-rw-r--r--core/src/tbox/src/tbox/container/element/str.c2
-rw-r--r--core/src/tbox/src/tbox/container/element/true.c2
-rw-r--r--core/src/tbox/src/tbox/container/element/uint16.c2
-rw-r--r--core/src/tbox/src/tbox/container/element/uint32.c2
-rw-r--r--core/src/tbox/src/tbox/container/element/uint8.c2
-rw-r--r--core/src/tbox/src/tbox/container/hash_map.c39
-rw-r--r--core/src/tbox/src/tbox/container/hash_map.h2
-rw-r--r--core/src/tbox/src/tbox/container/hash_set.c15
-rw-r--r--core/src/tbox/src/tbox/container/hash_set.h2
-rw-r--r--core/src/tbox/src/tbox/container/heap.c35
-rw-r--r--core/src/tbox/src/tbox/container/heap.h2
-rw-r--r--core/src/tbox/src/tbox/container/iterator.c50
-rw-r--r--core/src/tbox/src/tbox/container/iterator.h110
-rw-r--r--core/src/tbox/src/tbox/container/iterator/mem.c79
-rw-r--r--core/src/tbox/src/tbox/container/iterator/ptr.c118
-rw-r--r--core/src/tbox/src/tbox/container/iterator/str.c75
-rw-r--r--core/src/tbox/src/tbox/container/list.c38
-rw-r--r--core/src/tbox/src/tbox/container/list.h2
-rw-r--r--core/src/tbox/src/tbox/container/list_entry.c50
-rw-r--r--core/src/tbox/src/tbox/container/list_entry.h2
-rw-r--r--core/src/tbox/src/tbox/container/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/container/priority_queue.c2
-rw-r--r--core/src/tbox/src/tbox/container/priority_queue.h2
-rw-r--r--core/src/tbox/src/tbox/container/queue.c2
-rw-r--r--core/src/tbox/src/tbox/container/queue.h2
-rw-r--r--core/src/tbox/src/tbox/container/single_list.c36
-rw-r--r--core/src/tbox/src/tbox/container/single_list.h2
-rw-r--r--core/src/tbox/src/tbox/container/single_list_entry.c40
-rw-r--r--core/src/tbox/src/tbox/container/single_list_entry.h2
-rw-r--r--core/src/tbox/src/tbox/container/stack.c2
-rw-r--r--core/src/tbox/src/tbox/container/stack.h2
-rw-r--r--core/src/tbox/src/tbox/container/vector.c39
-rw-r--r--core/src/tbox/src/tbox/container/vector.h2
-rw-r--r--core/src/tbox/src/tbox/coroutine/channel.c487
-rw-r--r--core/src/tbox/src/tbox/coroutine/channel.h120
-rw-r--r--core/src/tbox/src/tbox/coroutine/coroutine.c99
-rw-r--r--core/src/tbox/src/tbox/coroutine/coroutine.h120
-rw-r--r--core/src/tbox/src/tbox/coroutine/impl/coroutine.c295
-rw-r--r--core/src/tbox/src/tbox/coroutine/impl/coroutine.h181
-rw-r--r--core/src/tbox/src/tbox/coroutine/impl/impl.h (renamed from core/src/tbox/src/tbox/stream/deprecated/deprecated.h)15
-rw-r--r--core/src/tbox/src/tbox/coroutine/impl/prefix.h (renamed from core/src/tbox/src/tbox/container/iterator/prefix.h)10
-rw-r--r--core/src/tbox/src/tbox/coroutine/impl/scheduler.c387
-rw-r--r--core/src/tbox/src/tbox/coroutine/impl/scheduler.h177
-rw-r--r--core/src/tbox/src/tbox/coroutine/impl/scheduler_io.c500
-rw-r--r--core/src/tbox/src/tbox/coroutine/impl/scheduler_io.h137
-rw-r--r--core/src/tbox/src/tbox/coroutine/impl/stackless/coroutine.h139
-rw-r--r--core/src/tbox/src/tbox/coroutine/impl/stackless/prefix.h36
-rw-r--r--core/src/tbox/src/tbox/coroutine/impl/stackless/scheduler.h122
-rw-r--r--core/src/tbox/src/tbox/coroutine/impl/stackless/scheduler_io.c513
-rw-r--r--core/src/tbox/src/tbox/coroutine/impl/stackless/scheduler_io.h137
-rw-r--r--core/src/tbox/src/tbox/coroutine/impl/stackless/stackless.h35
-rw-r--r--core/src/tbox/src/tbox/coroutine/lock.c66
-rw-r--r--core/src/tbox/src/tbox/coroutine/lock.h87
-rw-r--r--core/src/tbox/src/tbox/coroutine/prefix.h (renamed from core/src/tbox/src/tbox/stream/deprecated/prefix.h)7
-rw-r--r--core/src/tbox/src/tbox/coroutine/scheduler.c238
-rw-r--r--core/src/tbox/src/tbox/coroutine/scheduler.h87
-rw-r--r--core/src/tbox/src/tbox/coroutine/semaphore.c176
-rw-r--r--core/src/tbox/src/tbox/coroutine/semaphore.h95
-rw-r--r--core/src/tbox/src/tbox/coroutine/stackless/core.h171
-rw-r--r--core/src/tbox/src/tbox/coroutine/stackless/coroutine.c195
-rw-r--r--core/src/tbox/src/tbox/coroutine/stackless/coroutine.h413
-rw-r--r--core/src/tbox/src/tbox/coroutine/stackless/lock.h81
-rw-r--r--core/src/tbox/src/tbox/coroutine/stackless/prefix.h57
-rw-r--r--core/src/tbox/src/tbox/coroutine/stackless/scheduler.c426
-rw-r--r--core/src/tbox/src/tbox/coroutine/stackless/scheduler.h81
-rw-r--r--core/src/tbox/src/tbox/coroutine/stackless/semaphore.h104
-rw-r--r--core/src/tbox/src/tbox/coroutine/stackless/stackless.h38
-rw-r--r--core/src/tbox/src/tbox/database/database.h (renamed from core/src/tbox/src/tbox/platform/deprecated/deprecated.h)13
-rw-r--r--core/src/tbox/src/tbox/database/impl/mysql.c1723
-rw-r--r--core/src/tbox/src/tbox/database/impl/mysql.h (renamed from core/src/tbox/src/tbox/container/iterator/long.c)47
-rw-r--r--core/src/tbox/src/tbox/database/impl/prefix.h97
-rw-r--r--core/src/tbox/src/tbox/database/impl/sqlite3.c952
-rw-r--r--core/src/tbox/src/tbox/database/impl/sqlite3.h (renamed from core/src/tbox/src/tbox/platform/deprecated/aioo.c)55
-rw-r--r--core/src/tbox/src/tbox/database/prefix.h38
-rw-r--r--core/src/tbox/src/tbox/database/sql.c414
-rw-r--r--core/src/tbox/src/tbox/database/sql.h339
-rw-r--r--core/src/tbox/src/tbox/database/value.c496
-rw-r--r--core/src/tbox/src/tbox/database/value.h463
-rw-r--r--core/src/tbox/src/tbox/hash/adler32.h2
-rw-r--r--core/src/tbox/src/tbox/hash/ap.c2
-rw-r--r--core/src/tbox/src/tbox/hash/ap.h2
-rw-r--r--core/src/tbox/src/tbox/hash/arch/arm/crc32.S2
-rw-r--r--core/src/tbox/src/tbox/hash/arch/crc32.S2
-rw-r--r--core/src/tbox/src/tbox/hash/bkdr.c2
-rw-r--r--core/src/tbox/src/tbox/hash/bkdr.h2
-rw-r--r--core/src/tbox/src/tbox/hash/blizzard.c2
-rw-r--r--core/src/tbox/src/tbox/hash/blizzard.h2
-rw-r--r--core/src/tbox/src/tbox/hash/crc16.c2
-rw-r--r--core/src/tbox/src/tbox/hash/crc16.h2
-rw-r--r--core/src/tbox/src/tbox/hash/crc32.c2
-rw-r--r--core/src/tbox/src/tbox/hash/crc32.h2
-rw-r--r--core/src/tbox/src/tbox/hash/crc8.c2
-rw-r--r--core/src/tbox/src/tbox/hash/crc8.h2
-rw-r--r--core/src/tbox/src/tbox/hash/djb2.c2
-rw-r--r--core/src/tbox/src/tbox/hash/djb2.h2
-rw-r--r--core/src/tbox/src/tbox/hash/fnv32.c2
-rw-r--r--core/src/tbox/src/tbox/hash/fnv32.h2
-rw-r--r--core/src/tbox/src/tbox/hash/fnv64.c2
-rw-r--r--core/src/tbox/src/tbox/hash/fnv64.h2
-rw-r--r--core/src/tbox/src/tbox/hash/hash.h2
-rw-r--r--core/src/tbox/src/tbox/hash/md5.c2
-rw-r--r--core/src/tbox/src/tbox/hash/md5.h2
-rw-r--r--core/src/tbox/src/tbox/hash/murmur.c2
-rw-r--r--core/src/tbox/src/tbox/hash/murmur.h2
-rw-r--r--core/src/tbox/src/tbox/hash/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/hash/rs.c2
-rw-r--r--core/src/tbox/src/tbox/hash/rs.h2
-rw-r--r--core/src/tbox/src/tbox/hash/sdbm.c2
-rw-r--r--core/src/tbox/src/tbox/hash/sdbm.h2
-rw-r--r--core/src/tbox/src/tbox/hash/sha.c2
-rw-r--r--core/src/tbox/src/tbox/hash/sha.h2
-rw-r--r--core/src/tbox/src/tbox/hash/uuid.c2
-rw-r--r--core/src/tbox/src/tbox/hash/uuid.h2
-rw-r--r--core/src/tbox/src/tbox/libc/impl/impl.h2
-rw-r--r--core/src/tbox/src/tbox/libc/impl/libc.c2
-rw-r--r--core/src/tbox/src/tbox/libc/impl/libc.h2
-rw-r--r--core/src/tbox/src/tbox/libc/impl/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/libc/libc.h2
-rw-r--r--core/src/tbox/src/tbox/libc/misc/ctype.h2
-rw-r--r--core/src/tbox/src/tbox/libc/misc/limits.h2
-rw-r--r--core/src/tbox/src/tbox/libc/misc/misc.h2
-rw-r--r--core/src/tbox/src/tbox/libc/misc/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/libc/misc/setjmp.h2
-rw-r--r--core/src/tbox/src/tbox/libc/misc/signal.h2
-rw-r--r--core/src/tbox/src/tbox/libc/misc/stdarg.h2
-rw-r--r--core/src/tbox/src/tbox/libc/misc/time/gmmktime.c2
-rw-r--r--core/src/tbox/src/tbox/libc/misc/time/gmtime.c2
-rw-r--r--core/src/tbox/src/tbox/libc/misc/time/localtime.c2
-rw-r--r--core/src/tbox/src/tbox/libc/misc/time/mktime.c2
-rw-r--r--core/src/tbox/src/tbox/libc/misc/time/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/libc/misc/time/time.c2
-rw-r--r--core/src/tbox/src/tbox/libc/misc/time/time.h12
-rw-r--r--core/src/tbox/src/tbox/libc/misc/time/type.h2
-rw-r--r--core/src/tbox/src/tbox/libc/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/libc/stdio/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/libc/stdio/printf.c2
-rw-r--r--core/src/tbox/src/tbox/libc/stdio/printf_object.c4
-rw-r--r--core/src/tbox/src/tbox/libc/stdio/printf_object.h2
-rw-r--r--core/src/tbox/src/tbox/libc/stdio/puts.c2
-rw-r--r--core/src/tbox/src/tbox/libc/stdio/snprintf.c2
-rw-r--r--core/src/tbox/src/tbox/libc/stdio/sprintf.c4
-rw-r--r--core/src/tbox/src/tbox/libc/stdio/stdio.h2
-rw-r--r--core/src/tbox/src/tbox/libc/stdio/swprintf.c2
-rw-r--r--core/src/tbox/src/tbox/libc/stdio/vsnprintf.c2
-rw-r--r--core/src/tbox/src/tbox/libc/stdio/vswprintf.c2
-rw-r--r--core/src/tbox/src/tbox/libc/stdio/wprintf.c2
-rw-r--r--core/src/tbox/src/tbox/libc/stdio/wputs.c2
-rw-r--r--core/src/tbox/src/tbox/libc/stdlib/mbstowcs.c2
-rw-r--r--core/src/tbox/src/tbox/libc/stdlib/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/libc/stdlib/random.c2
-rw-r--r--core/src/tbox/src/tbox/libc/stdlib/stdlib.c22
-rw-r--r--core/src/tbox/src/tbox/libc/stdlib/stdlib.h2
-rw-r--r--core/src/tbox/src/tbox/libc/stdlib/wcstombs.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/arm/memcmp.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/arm/memcpy.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/arm/memmov.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/arm/memset.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/arm/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/arm/strcmp.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/arm/strcpy.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/arm/strlcpy.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/arm/strlen.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/arm/strncmp.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/arm/strncpy.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/arm/strnlen.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/sh4/memcmp.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/sh4/memcpy.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/sh4/memmov.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/sh4/memset.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/sh4/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/sh4/strcmp.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/sh4/strcpy.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/sh4/strlen.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/sh4/strncmp.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/sh4/strncpy.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/sh4/strnlen.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/x86/memcmp.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/x86/memcpy.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/x86/memmov.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/x86/memset.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/x86/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/x86/strcmp.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/x86/strcpy.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/x86/strlcpy.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/x86/strlen.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/x86/strncmp.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/x86/strncpy.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/impl/x86/strnlen.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/memcmp.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/memcpy.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/memdup.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/memmem.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/memmov.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/memset.c4
-rw-r--r--core/src/tbox/src/tbox/libc/string/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/libc/string/strcat.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/strchr.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/strcmp.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/strcpy.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/strdup.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/strichr.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/stricmp.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/string.h2
-rw-r--r--core/src/tbox/src/tbox/libc/string/strirchr.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/strirstr.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/stristr.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/strlcpy.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/strlen.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/strncat.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/strncmp.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/strncpy.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/strndup.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/strnicmp.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/strnirchr.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/strnirstr.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/strnistr.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/strnlen.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/strnrchr.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/strnrstr.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/strnstr.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/strrchr.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/strrstr.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/strstr.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/wcscat.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/wcschr.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/wcscmp.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/wcscpy.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/wcsdup.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/wcsichr.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/wcsicmp.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/wcsirchr.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/wcsirstr.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/wcsistr.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/wcslcpy.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/wcslen.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/wcsncat.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/wcsncmp.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/wcsncpy.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/wcsndup.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/wcsnicmp.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/wcsnirchr.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/wcsnirstr.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/wcsnlen.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/wcsnrchr.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/wcsnrstr.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/wcsrchr.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/wcsrstr.c2
-rw-r--r--core/src/tbox/src/tbox/libc/string/wcsstr.c2
-rw-r--r--core/src/tbox/src/tbox/libm/acos.c2
-rw-r--r--core/src/tbox/src/tbox/libm/acosf.c2
-rw-r--r--core/src/tbox/src/tbox/libm/asin.c2
-rw-r--r--core/src/tbox/src/tbox/libm/asinf.c2
-rw-r--r--core/src/tbox/src/tbox/libm/atan.c2
-rw-r--r--core/src/tbox/src/tbox/libm/atan2.c2
-rw-r--r--core/src/tbox/src/tbox/libm/atan2f.c2
-rw-r--r--core/src/tbox/src/tbox/libm/atanf.c2
-rw-r--r--core/src/tbox/src/tbox/libm/ceil.h2
-rw-r--r--core/src/tbox/src/tbox/libm/cos.c2
-rw-r--r--core/src/tbox/src/tbox/libm/cosf.c2
-rw-r--r--core/src/tbox/src/tbox/libm/exp.c2
-rw-r--r--core/src/tbox/src/tbox/libm/exp1.c2
-rw-r--r--core/src/tbox/src/tbox/libm/exp1f.c2
-rw-r--r--core/src/tbox/src/tbox/libm/expf.c2
-rw-r--r--core/src/tbox/src/tbox/libm/expi.c2
-rw-r--r--core/src/tbox/src/tbox/libm/expif.c2
-rw-r--r--core/src/tbox/src/tbox/libm/fabs.h2
-rw-r--r--core/src/tbox/src/tbox/libm/floor.h2
-rw-r--r--core/src/tbox/src/tbox/libm/fmod.c2
-rw-r--r--core/src/tbox/src/tbox/libm/fmodf.c2
-rw-r--r--core/src/tbox/src/tbox/libm/idivi8.c2
-rw-r--r--core/src/tbox/src/tbox/libm/ilog2i.c2
-rw-r--r--core/src/tbox/src/tbox/libm/impl/impl.h2
-rw-r--r--core/src/tbox/src/tbox/libm/impl/libm.c2
-rw-r--r--core/src/tbox/src/tbox/libm/impl/libm.h2
-rw-r--r--core/src/tbox/src/tbox/libm/impl/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/libm/inf.h2
-rw-r--r--core/src/tbox/src/tbox/libm/isfin.c2
-rw-r--r--core/src/tbox/src/tbox/libm/isfinf.c2
-rw-r--r--core/src/tbox/src/tbox/libm/isinf.c2
-rw-r--r--core/src/tbox/src/tbox/libm/isinff.c2
-rw-r--r--core/src/tbox/src/tbox/libm/isnan.c2
-rw-r--r--core/src/tbox/src/tbox/libm/isnanf.c2
-rw-r--r--core/src/tbox/src/tbox/libm/isqrti.c2
-rw-r--r--core/src/tbox/src/tbox/libm/isqrti64.c2
-rw-r--r--core/src/tbox/src/tbox/libm/libm.h2
-rw-r--r--core/src/tbox/src/tbox/libm/log2.c2
-rw-r--r--core/src/tbox/src/tbox/libm/log2f.c2
-rw-r--r--core/src/tbox/src/tbox/libm/maf.h2
-rw-r--r--core/src/tbox/src/tbox/libm/math.h2
-rw-r--r--core/src/tbox/src/tbox/libm/mif.h2
-rw-r--r--core/src/tbox/src/tbox/libm/nan.h2
-rw-r--r--core/src/tbox/src/tbox/libm/pi.h2
-rw-r--r--core/src/tbox/src/tbox/libm/pow.c2
-rw-r--r--core/src/tbox/src/tbox/libm/powf.c2
-rw-r--r--core/src/tbox/src/tbox/libm/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/libm/round.h2
-rw-r--r--core/src/tbox/src/tbox/libm/sin.c2
-rw-r--r--core/src/tbox/src/tbox/libm/sincos.c2
-rw-r--r--core/src/tbox/src/tbox/libm/sincosf.c2
-rw-r--r--core/src/tbox/src/tbox/libm/sinf.c2
-rw-r--r--core/src/tbox/src/tbox/libm/sqrt.c2
-rw-r--r--core/src/tbox/src/tbox/libm/sqrtf.c2
-rw-r--r--core/src/tbox/src/tbox/libm/tan.c2
-rw-r--r--core/src/tbox/src/tbox/libm/tanf.c2
-rw-r--r--core/src/tbox/src/tbox/math/fixed.h2
-rw-r--r--core/src/tbox/src/tbox/math/fixed16.c2
-rw-r--r--core/src/tbox/src/tbox/math/fixed16.h2
-rw-r--r--core/src/tbox/src/tbox/math/fixed30.h2
-rw-r--r--core/src/tbox/src/tbox/math/fixed6.h2
-rw-r--r--core/src/tbox/src/tbox/math/impl/fixed16_arm.h2
-rw-r--r--core/src/tbox/src/tbox/math/impl/fixed30_arm.h2
-rw-r--r--core/src/tbox/src/tbox/math/impl/impl.h2
-rw-r--r--core/src/tbox/src/tbox/math/impl/math.c2
-rw-r--r--core/src/tbox/src/tbox/math/impl/math.h2
-rw-r--r--core/src/tbox/src/tbox/math/impl/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/math/int32.c2
-rw-r--r--core/src/tbox/src/tbox/math/int32.h2
-rw-r--r--core/src/tbox/src/tbox/math/math.h2
-rw-r--r--core/src/tbox/src/tbox/math/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/math/random/linear.c2
-rw-r--r--core/src/tbox/src/tbox/math/random/linear.h2
-rw-r--r--core/src/tbox/src/tbox/math/random/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/math/random/random.c2
-rw-r--r--core/src/tbox/src/tbox/math/random/random.h2
-rw-r--r--core/src/tbox/src/tbox/memory/allocator.c46
-rw-r--r--core/src/tbox/src/tbox/memory/allocator.h27
-rw-r--r--core/src/tbox/src/tbox/memory/buffer.c2
-rw-r--r--core/src/tbox/src/tbox/memory/buffer.h2
-rw-r--r--core/src/tbox/src/tbox/memory/default_allocator.c5
-rw-r--r--core/src/tbox/src/tbox/memory/default_allocator.h2
-rw-r--r--core/src/tbox/src/tbox/memory/fixed_pool.c6
-rw-r--r--core/src/tbox/src/tbox/memory/fixed_pool.h2
-rw-r--r--core/src/tbox/src/tbox/memory/impl/impl.h2
-rw-r--r--core/src/tbox/src/tbox/memory/impl/memory.c2
-rw-r--r--core/src/tbox/src/tbox/memory/impl/memory.h2
-rw-r--r--core/src/tbox/src/tbox/memory/impl/native_large_allocator.c5
-rw-r--r--core/src/tbox/src/tbox/memory/impl/native_large_allocator.h2
-rw-r--r--core/src/tbox/src/tbox/memory/impl/prefix.c2
-rw-r--r--core/src/tbox/src/tbox/memory/impl/prefix.h11
-rw-r--r--core/src/tbox/src/tbox/memory/impl/static_fixed_pool.c2
-rw-r--r--core/src/tbox/src/tbox/memory/impl/static_fixed_pool.h2
-rw-r--r--core/src/tbox/src/tbox/memory/impl/static_large_allocator.c17
-rw-r--r--core/src/tbox/src/tbox/memory/impl/static_large_allocator.h2
-rw-r--r--core/src/tbox/src/tbox/memory/large_allocator.c2
-rw-r--r--core/src/tbox/src/tbox/memory/large_allocator.h2
-rw-r--r--core/src/tbox/src/tbox/memory/memory.h2
-rw-r--r--core/src/tbox/src/tbox/memory/native_allocator.c5
-rw-r--r--core/src/tbox/src/tbox/memory/native_allocator.h2
-rw-r--r--core/src/tbox/src/tbox/memory/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/memory/queue_buffer.c19
-rw-r--r--core/src/tbox/src/tbox/memory/queue_buffer.h2
-rw-r--r--core/src/tbox/src/tbox/memory/small_allocator.c5
-rw-r--r--core/src/tbox/src/tbox/memory/small_allocator.h2
-rw-r--r--core/src/tbox/src/tbox/memory/static_allocator.c4
-rw-r--r--core/src/tbox/src/tbox/memory/static_allocator.h2
-rw-r--r--core/src/tbox/src/tbox/memory/static_buffer.c4
-rw-r--r--core/src/tbox/src/tbox/memory/static_buffer.h2
-rw-r--r--core/src/tbox/src/tbox/memory/string_pool.c2
-rw-r--r--core/src/tbox/src/tbox/memory/string_pool.h2
-rw-r--r--core/src/tbox/src/tbox/micro.lua118
-rw-r--r--core/src/tbox/src/tbox/network/cookies.c41
-rw-r--r--core/src/tbox/src/tbox/network/cookies.h2
-rw-r--r--core/src/tbox/src/tbox/network/dns/cache.c2
-rw-r--r--core/src/tbox/src/tbox/network/dns/cache.h12
-rw-r--r--core/src/tbox/src/tbox/network/dns/dns.h2
-rw-r--r--core/src/tbox/src/tbox/network/dns/looker.c22
-rw-r--r--core/src/tbox/src/tbox/network/dns/looker.h14
-rw-r--r--core/src/tbox/src/tbox/network/dns/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/network/dns/server.c6
-rw-r--r--core/src/tbox/src/tbox/network/dns/server.h2
-rw-r--r--core/src/tbox/src/tbox/network/http.c53
-rw-r--r--core/src/tbox/src/tbox/network/http.h2
-rw-r--r--core/src/tbox/src/tbox/network/hwaddr.c2
-rw-r--r--core/src/tbox/src/tbox/network/hwaddr.h2
-rw-r--r--core/src/tbox/src/tbox/network/impl/http/date.c2
-rw-r--r--core/src/tbox/src/tbox/network/impl/http/date.h2
-rw-r--r--core/src/tbox/src/tbox/network/impl/http/method.c2
-rw-r--r--core/src/tbox/src/tbox/network/impl/http/method.h2
-rw-r--r--core/src/tbox/src/tbox/network/impl/http/option.c2
-rw-r--r--core/src/tbox/src/tbox/network/impl/http/option.h2
-rw-r--r--core/src/tbox/src/tbox/network/impl/http/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/network/impl/http/status.c2
-rw-r--r--core/src/tbox/src/tbox/network/impl/http/status.h2
-rw-r--r--core/src/tbox/src/tbox/network/impl/impl.h2
-rw-r--r--core/src/tbox/src/tbox/network/impl/network.c2
-rw-r--r--core/src/tbox/src/tbox/network/impl/network.h2
-rw-r--r--core/src/tbox/src/tbox/network/impl/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/network/impl/ssl/mbedtls.c4
-rw-r--r--core/src/tbox/src/tbox/network/impl/ssl/openssl.c61
-rw-r--r--core/src/tbox/src/tbox/network/impl/ssl/polarssl.c2
-rw-r--r--core/src/tbox/src/tbox/network/impl/ssl/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/network/ipaddr.c2
-rw-r--r--core/src/tbox/src/tbox/network/ipaddr.h2
-rw-r--r--core/src/tbox/src/tbox/network/ipv4.c2
-rw-r--r--core/src/tbox/src/tbox/network/ipv4.h2
-rw-r--r--core/src/tbox/src/tbox/network/ipv6.c2
-rw-r--r--core/src/tbox/src/tbox/network/ipv6.h2
-rw-r--r--core/src/tbox/src/tbox/network/network.h2
-rw-r--r--core/src/tbox/src/tbox/network/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/network/ssl.h2
-rw-r--r--core/src/tbox/src/tbox/network/url.c2
-rw-r--r--core/src/tbox/src/tbox/network/url.h2
-rw-r--r--core/src/tbox/src/tbox/object/array.c266
-rw-r--r--core/src/tbox/src/tbox/object/array.h130
-rw-r--r--core/src/tbox/src/tbox/object/boolean.c133
-rw-r--r--core/src/tbox/src/tbox/object/boolean.h78
-rw-r--r--core/src/tbox/src/tbox/object/data.c258
-rw-r--r--core/src/tbox/src/tbox/object/data.h117
-rw-r--r--core/src/tbox/src/tbox/object/date.c172
-rw-r--r--core/src/tbox/src/tbox/object/date.h88
-rw-r--r--core/src/tbox/src/tbox/object/dictionary.c259
-rw-r--r--core/src/tbox/src/tbox/object/dictionary.h163
-rw-r--r--core/src/tbox/src/tbox/object/impl/impl.h36
-rw-r--r--core/src/tbox/src/tbox/object/impl/object.c86
-rw-r--r--core/src/tbox/src/tbox/object/impl/object.h (renamed from core/src/tbox/src/tbox/platform/deprecated/aicp.c)48
-rw-r--r--core/src/tbox/src/tbox/object/impl/prefix.h77
-rw-r--r--core/src/tbox/src/tbox/object/impl/reader/bin.c550
-rw-r--r--core/src/tbox/src/tbox/object/impl/reader/bin.h90
-rw-r--r--core/src/tbox/src/tbox/object/impl/reader/bplist.c821
-rw-r--r--core/src/tbox/src/tbox/object/impl/reader/bplist.h87
-rw-r--r--core/src/tbox/src/tbox/object/impl/reader/json.c607
-rw-r--r--core/src/tbox/src/tbox/object/impl/reader/json.h87
-rw-r--r--core/src/tbox/src/tbox/object/impl/reader/prefix.h88
-rw-r--r--core/src/tbox/src/tbox/object/impl/reader/reader.c111
-rw-r--r--core/src/tbox/src/tbox/object/impl/reader/reader.h83
-rw-r--r--core/src/tbox/src/tbox/object/impl/reader/xml.c647
-rw-r--r--core/src/tbox/src/tbox/object/impl/reader/xml.h87
-rw-r--r--core/src/tbox/src/tbox/object/impl/reader/xplist.c653
-rw-r--r--core/src/tbox/src/tbox/object/impl/reader/xplist.h87
-rw-r--r--core/src/tbox/src/tbox/object/impl/writer/bin.c429
-rw-r--r--core/src/tbox/src/tbox/object/impl/writer/bin.h102
-rw-r--r--core/src/tbox/src/tbox/object/impl/writer/bplist.c806
-rw-r--r--core/src/tbox/src/tbox/object/impl/writer/bplist.h87
-rw-r--r--core/src/tbox/src/tbox/object/impl/writer/json.c331
-rw-r--r--core/src/tbox/src/tbox/object/impl/writer/json.h90
-rw-r--r--core/src/tbox/src/tbox/object/impl/writer/prefix.h114
-rw-r--r--core/src/tbox/src/tbox/object/impl/writer/writer.c94
-rw-r--r--core/src/tbox/src/tbox/object/impl/writer/writer.h86
-rw-r--r--core/src/tbox/src/tbox/object/impl/writer/xml.c432
-rw-r--r--core/src/tbox/src/tbox/object/impl/writer/xml.h90
-rw-r--r--core/src/tbox/src/tbox/object/impl/writer/xplist.c425
-rw-r--r--core/src/tbox/src/tbox/object/impl/writer/xplist.h90
-rw-r--r--core/src/tbox/src/tbox/object/null.c70
-rw-r--r--core/src/tbox/src/tbox/object/null.h55
-rw-r--r--core/src/tbox/src/tbox/object/number.c683
-rw-r--r--core/src/tbox/src/tbox/object/number.h334
-rw-r--r--core/src/tbox/src/tbox/object/object.c405
-rw-r--r--core/src/tbox/src/tbox/object/object.h255
-rw-r--r--core/src/tbox/src/tbox/object/prefix.h104
-rw-r--r--core/src/tbox/src/tbox/object/string.c232
-rw-r--r--core/src/tbox/src/tbox/object/string.h90
-rw-r--r--core/src/tbox/src/tbox/platform/addrinfo.c2
-rw-r--r--core/src/tbox/src/tbox/platform/addrinfo.h2
-rw-r--r--core/src/tbox/src/tbox/platform/android/android.c2
-rw-r--r--core/src/tbox/src/tbox/platform/android/android.h2
-rw-r--r--core/src/tbox/src/tbox/platform/android/backtrace.c2
-rw-r--r--core/src/tbox/src/tbox/platform/android/directory.c2
-rw-r--r--core/src/tbox/src/tbox/platform/android/dns.c2
-rw-r--r--core/src/tbox/src/tbox/platform/android/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/platform/android/print.c2
-rw-r--r--core/src/tbox/src/tbox/platform/arch/arm/frame.h2
-rw-r--r--core/src/tbox/src/tbox/platform/arch/arm/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/platform/arch/arm64/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/platform/arch/atomic.h2
-rw-r--r--core/src/tbox/src/tbox/platform/arch/barrier.h2
-rw-r--r--core/src/tbox/src/tbox/platform/arch/context.S2
-rw-r--r--core/src/tbox/src/tbox/platform/arch/frame.h2
-rw-r--r--core/src/tbox/src/tbox/platform/arch/mips/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/platform/arch/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/platform/arch/x64/atomic.h2
-rw-r--r--core/src/tbox/src/tbox/platform/arch/x64/barrier.h2
-rw-r--r--core/src/tbox/src/tbox/platform/arch/x64/context.S62
-rw-r--r--core/src/tbox/src/tbox/platform/arch/x64/context.asm49
-rw-r--r--core/src/tbox/src/tbox/platform/arch/x64/frame.h2
-rw-r--r--core/src/tbox/src/tbox/platform/arch/x64/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/platform/arch/x86/atomic.h2
-rw-r--r--core/src/tbox/src/tbox/platform/arch/x86/barrier.h2
-rw-r--r--core/src/tbox/src/tbox/platform/arch/x86/context.S72
-rw-r--r--core/src/tbox/src/tbox/platform/arch/x86/context.asm82
-rw-r--r--core/src/tbox/src/tbox/platform/arch/x86/frame.h2
-rw-r--r--core/src/tbox/src/tbox/platform/arch/x86/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/platform/atomic.h2
-rw-r--r--core/src/tbox/src/tbox/platform/atomic64.c2
-rw-r--r--core/src/tbox/src/tbox/platform/atomic64.h2
-rw-r--r--core/src/tbox/src/tbox/platform/backtrace.c2
-rw-r--r--core/src/tbox/src/tbox/platform/backtrace.h2
-rw-r--r--core/src/tbox/src/tbox/platform/barrier.h2
-rw-r--r--core/src/tbox/src/tbox/platform/cache_time.c2
-rw-r--r--core/src/tbox/src/tbox/platform/cache_time.h2
-rw-r--r--core/src/tbox/src/tbox/platform/compiler/gcc/atomic.h2
-rw-r--r--core/src/tbox/src/tbox/platform/compiler/gcc/atomic64.h2
-rw-r--r--core/src/tbox/src/tbox/platform/compiler/gcc/barrier.h2
-rw-r--r--core/src/tbox/src/tbox/platform/compiler/gcc/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/platform/compiler/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/platform/context.c2
-rw-r--r--core/src/tbox/src/tbox/platform/context.h2
-rw-r--r--core/src/tbox/src/tbox/platform/deprecated/aicp_iocp.c2729
-rw-r--r--core/src/tbox/src/tbox/platform/deprecated/aioo_poll.c76
-rw-r--r--core/src/tbox/src/tbox/platform/deprecated/aioo_select.c123
-rw-r--r--core/src/tbox/src/tbox/platform/deprecated/aiop.c69
-rw-r--r--core/src/tbox/src/tbox/platform/deprecated/aiop_epoll.c358
-rw-r--r--core/src/tbox/src/tbox/platform/deprecated/aiop_kqueue.c381
-rw-r--r--core/src/tbox/src/tbox/platform/deprecated/aiop_poll.c438
-rw-r--r--core/src/tbox/src/tbox/platform/deprecated/aiop_select.c454
-rw-r--r--core/src/tbox/src/tbox/platform/directory.c4
-rw-r--r--core/src/tbox/src/tbox/platform/directory.h4
-rw-r--r--core/src/tbox/src/tbox/platform/dynamic.c2
-rw-r--r--core/src/tbox/src/tbox/platform/dynamic.h2
-rw-r--r--core/src/tbox/src/tbox/platform/environment.c2
-rw-r--r--core/src/tbox/src/tbox/platform/environment.h2
-rw-r--r--core/src/tbox/src/tbox/platform/event.c2
-rw-r--r--core/src/tbox/src/tbox/platform/event.h2
-rw-r--r--core/src/tbox/src/tbox/platform/exception.c2
-rw-r--r--core/src/tbox/src/tbox/platform/exception.h2
-rw-r--r--core/src/tbox/src/tbox/platform/file.c2
-rw-r--r--core/src/tbox/src/tbox/platform/file.h5
-rw-r--r--core/src/tbox/src/tbox/platform/hostname.c2
-rw-r--r--core/src/tbox/src/tbox/platform/hostname.h2
-rw-r--r--core/src/tbox/src/tbox/platform/ifaddrs.c54
-rw-r--r--core/src/tbox/src/tbox/platform/ifaddrs.h2
-rw-r--r--core/src/tbox/src/tbox/platform/impl/dns.c2
-rw-r--r--core/src/tbox/src/tbox/platform/impl/dns.h2
-rw-r--r--core/src/tbox/src/tbox/platform/impl/exception.h2
-rw-r--r--core/src/tbox/src/tbox/platform/impl/impl.h3
-rw-r--r--core/src/tbox/src/tbox/platform/impl/platform.c3
-rw-r--r--core/src/tbox/src/tbox/platform/impl/platform.h2
-rw-r--r--core/src/tbox/src/tbox/platform/impl/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/platform/impl/sockdata.c172
-rw-r--r--core/src/tbox/src/tbox/platform/impl/sockdata.h115
-rw-r--r--core/src/tbox/src/tbox/platform/impl/socket.h2
-rw-r--r--core/src/tbox/src/tbox/platform/impl/thread_local.h2
-rw-r--r--core/src/tbox/src/tbox/platform/libc/backtrace.c2
-rw-r--r--core/src/tbox/src/tbox/platform/libc/environment.c2
-rw-r--r--core/src/tbox/src/tbox/platform/libc/exception.c2
-rw-r--r--core/src/tbox/src/tbox/platform/libc/exception.h2
-rw-r--r--core/src/tbox/src/tbox/platform/libc/memory.c2
-rw-r--r--core/src/tbox/src/tbox/platform/libc/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/platform/libc/print.c2
-rw-r--r--core/src/tbox/src/tbox/platform/libc/random.c2
-rw-r--r--core/src/tbox/src/tbox/platform/libc/syserror.c2
-rw-r--r--core/src/tbox/src/tbox/platform/linux/ifaddrs.c2
-rw-r--r--core/src/tbox/src/tbox/platform/linux/ifaddrs2.c2
-rw-r--r--core/src/tbox/src/tbox/platform/linux/poller_epoll.c103
-rw-r--r--core/src/tbox/src/tbox/platform/linux/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/platform/ltimer.c4
-rw-r--r--core/src/tbox/src/tbox/platform/ltimer.h2
-rw-r--r--core/src/tbox/src/tbox/platform/mach/barrier.h2
-rw-r--r--core/src/tbox/src/tbox/platform/mach/dns.c6
-rw-r--r--core/src/tbox/src/tbox/platform/mach/ios/directory.m2
-rw-r--r--core/src/tbox/src/tbox/platform/mach/ios/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/platform/mach/ios/print.c2
-rw-r--r--core/src/tbox/src/tbox/platform/mach/poller_kqueue.c116
-rw-r--r--core/src/tbox/src/tbox/platform/mach/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/platform/mach/semaphore.c2
-rw-r--r--core/src/tbox/src/tbox/platform/memory.c2
-rw-r--r--core/src/tbox/src/tbox/platform/memory.h2
-rw-r--r--core/src/tbox/src/tbox/platform/mutex.c2
-rw-r--r--core/src/tbox/src/tbox/platform/mutex.h2
-rw-r--r--core/src/tbox/src/tbox/platform/page.c2
-rw-r--r--core/src/tbox/src/tbox/platform/page.h2
-rw-r--r--core/src/tbox/src/tbox/platform/path.c2
-rw-r--r--core/src/tbox/src/tbox/platform/path.h2
-rw-r--r--core/src/tbox/src/tbox/platform/platform.h5
-rw-r--r--core/src/tbox/src/tbox/platform/poller.c22
-rw-r--r--core/src/tbox/src/tbox/platform/poller.h23
-rw-r--r--core/src/tbox/src/tbox/platform/posix/addrinfo.c2
-rw-r--r--core/src/tbox/src/tbox/platform/posix/context.c2
-rw-r--r--core/src/tbox/src/tbox/platform/posix/directory.c2
-rw-r--r--core/src/tbox/src/tbox/platform/posix/dynamic.c2
-rw-r--r--core/src/tbox/src/tbox/platform/posix/event.c2
-rw-r--r--core/src/tbox/src/tbox/platform/posix/file.c2
-rw-r--r--core/src/tbox/src/tbox/platform/posix/hostname.c2
-rw-r--r--core/src/tbox/src/tbox/platform/posix/ifaddrs.c2
-rw-r--r--core/src/tbox/src/tbox/platform/posix/mutex.c2
-rw-r--r--core/src/tbox/src/tbox/platform/posix/page.c2
-rw-r--r--core/src/tbox/src/tbox/platform/posix/poller_poll.c112
-rw-r--r--core/src/tbox/src/tbox/platform/posix/poller_select.c63
-rw-r--r--core/src/tbox/src/tbox/platform/posix/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/platform/posix/process.c2
-rw-r--r--core/src/tbox/src/tbox/platform/posix/processor.c2
-rw-r--r--core/src/tbox/src/tbox/platform/posix/regex.c2
-rw-r--r--core/src/tbox/src/tbox/platform/posix/sched.c2
-rw-r--r--core/src/tbox/src/tbox/platform/posix/semaphore.c6
-rw-r--r--core/src/tbox/src/tbox/platform/posix/sockaddr.h2
-rw-r--r--core/src/tbox/src/tbox/platform/posix/socket.c16
-rw-r--r--core/src/tbox/src/tbox/platform/posix/socket_poll.c2
-rw-r--r--core/src/tbox/src/tbox/platform/posix/socket_select.c15
-rw-r--r--core/src/tbox/src/tbox/platform/posix/thread.c2
-rw-r--r--core/src/tbox/src/tbox/platform/posix/thread_local.c6
-rw-r--r--core/src/tbox/src/tbox/platform/posix/time.c2
-rw-r--r--core/src/tbox/src/tbox/platform/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/platform/print.c2
-rw-r--r--core/src/tbox/src/tbox/platform/print.h2
-rw-r--r--core/src/tbox/src/tbox/platform/process.c2
-rw-r--r--core/src/tbox/src/tbox/platform/process.h2
-rw-r--r--core/src/tbox/src/tbox/platform/processor.c2
-rw-r--r--core/src/tbox/src/tbox/platform/processor.h2
-rw-r--r--core/src/tbox/src/tbox/platform/sched.c2
-rw-r--r--core/src/tbox/src/tbox/platform/sched.h2
-rw-r--r--core/src/tbox/src/tbox/platform/semaphore.c2
-rw-r--r--core/src/tbox/src/tbox/platform/semaphore.h2
-rw-r--r--core/src/tbox/src/tbox/platform/socket.c61
-rw-r--r--core/src/tbox/src/tbox/platform/socket.h30
-rw-r--r--core/src/tbox/src/tbox/platform/spinlock.h2
-rw-r--r--core/src/tbox/src/tbox/platform/syserror.c2
-rw-r--r--core/src/tbox/src/tbox/platform/syserror.h2
-rw-r--r--core/src/tbox/src/tbox/platform/systemv/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/platform/systemv/semaphore.c2
-rw-r--r--core/src/tbox/src/tbox/platform/thread.c2
-rw-r--r--core/src/tbox/src/tbox/platform/thread.h2
-rw-r--r--core/src/tbox/src/tbox/platform/thread_local.c8
-rw-r--r--core/src/tbox/src/tbox/platform/thread_local.h2
-rw-r--r--core/src/tbox/src/tbox/platform/thread_pool.c4
-rw-r--r--core/src/tbox/src/tbox/platform/thread_pool.h2
-rw-r--r--core/src/tbox/src/tbox/platform/time.c2
-rw-r--r--core/src/tbox/src/tbox/platform/time.h2
-rw-r--r--core/src/tbox/src/tbox/platform/timer.c2
-rw-r--r--core/src/tbox/src/tbox/platform/timer.h2
-rw-r--r--core/src/tbox/src/tbox/platform/unix/dns.c2
-rw-r--r--core/src/tbox/src/tbox/platform/unix/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/platform/unix/syscall.h2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/addrinfo.c10
-rw-r--r--core/src/tbox/src/tbox/platform/windows/atomic.h2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/atomic64.h2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/backtrace.c2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/barrier.h2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/context.c2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/directory.c2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/dns.c2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/dynamic.c2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/environment.c2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/event.c2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/exception.c2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/exception.h2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/file.c2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/hostname.c2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/ifaddrs.c82
-rw-r--r--core/src/tbox/src/tbox/platform/windows/interface/dbghelp.c4
-rw-r--r--core/src/tbox/src/tbox/platform/windows/interface/dbghelp.h2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/interface/interface.c2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/interface/interface.h2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/interface/iphlpapi.c4
-rw-r--r--core/src/tbox/src/tbox/platform/windows/interface/iphlpapi.h2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/interface/kernel32.c2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/interface/kernel32.h9
-rw-r--r--core/src/tbox/src/tbox/platform/windows/interface/mswsock.c2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/interface/mswsock.h2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/interface/ole32.c4
-rw-r--r--core/src/tbox/src/tbox/platform/windows/interface/ole32.h2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/interface/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/interface/shell32.c4
-rw-r--r--core/src/tbox/src/tbox/platform/windows/interface/shell32.h2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/interface/user32.c4
-rw-r--r--core/src/tbox/src/tbox/platform/windows/interface/user32.h2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/interface/ws2_32.c6
-rw-r--r--core/src/tbox/src/tbox/platform/windows/interface/ws2_32.h2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/iocp_object.c1350
-rw-r--r--core/src/tbox/src/tbox/platform/windows/iocp_object.h466
-rw-r--r--core/src/tbox/src/tbox/platform/windows/memory.c2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/mutex.c4
-rw-r--r--core/src/tbox/src/tbox/platform/windows/ntstatus.h2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/page.c2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/poller_iocp.c695
-rw-r--r--core/src/tbox/src/tbox/platform/windows/prefix.h13
-rw-r--r--core/src/tbox/src/tbox/platform/windows/print.c2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/process.c2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/processor.c2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/sched.c2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/semaphore.c2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/socket.c137
-rw-r--r--core/src/tbox/src/tbox/platform/windows/socket_pool.c2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/socket_pool.h2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/syserror.c2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/thread.c11
-rw-r--r--core/src/tbox/src/tbox/platform/windows/thread_local.c6
-rw-r--r--core/src/tbox/src/tbox/platform/windows/time.c2
-rw-r--r--core/src/tbox/src/tbox/platform/windows/uuid.c2
-rw-r--r--core/src/tbox/src/tbox/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/prefix/abort.h2
-rw-r--r--core/src/tbox/src/tbox/prefix/arch.h25
-rw-r--r--core/src/tbox/src/tbox/prefix/arm/prefix.S2
-rw-r--r--core/src/tbox/src/tbox/prefix/arm64/prefix.S2
-rw-r--r--core/src/tbox/src/tbox/prefix/assembler.h2
-rw-r--r--core/src/tbox/src/tbox/prefix/assert.h22
-rw-r--r--core/src/tbox/src/tbox/prefix/cache.h2
-rw-r--r--core/src/tbox/src/tbox/prefix/check.h2
-rw-r--r--core/src/tbox/src/tbox/prefix/compiler.h20
-rw-r--r--core/src/tbox/src/tbox/prefix/config.h2
-rw-r--r--core/src/tbox/src/tbox/prefix/cpu.h5
-rw-r--r--core/src/tbox/src/tbox/prefix/endian.h9
-rw-r--r--core/src/tbox/src/tbox/prefix/keyword.h29
-rw-r--r--core/src/tbox/src/tbox/prefix/limits.h2
-rw-r--r--core/src/tbox/src/tbox/prefix/malloc.h2
-rw-r--r--core/src/tbox/src/tbox/prefix/mips/prefix.S2
-rw-r--r--core/src/tbox/src/tbox/prefix/packed.h2
-rw-r--r--core/src/tbox/src/tbox/prefix/prefix.S2
-rw-r--r--core/src/tbox/src/tbox/prefix/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/prefix/state.c2
-rw-r--r--core/src/tbox/src/tbox/prefix/state.h2
-rw-r--r--core/src/tbox/src/tbox/prefix/trace.h15
-rw-r--r--core/src/tbox/src/tbox/prefix/type.h4
-rw-r--r--core/src/tbox/src/tbox/prefix/utils.h2
-rw-r--r--core/src/tbox/src/tbox/prefix/version.h8
-rw-r--r--core/src/tbox/src/tbox/prefix/x64/prefix.S2
-rw-r--r--core/src/tbox/src/tbox/prefix/x86/prefix.S2
-rw-r--r--core/src/tbox/src/tbox/regex/impl/impl.h (renamed from core/src/tbox/src/tbox/container/iterator/size.c)23
-rw-r--r--core/src/tbox/src/tbox/regex/impl/pcre.c358
-rw-r--r--core/src/tbox/src/tbox/regex/impl/pcre2.c352
-rw-r--r--core/src/tbox/src/tbox/regex/impl/prefix.h38
-rw-r--r--core/src/tbox/src/tbox/regex/prefix.h (renamed from core/src/tbox/src/tbox/platform/deprecated/prefix.h)9
-rw-r--r--core/src/tbox/src/tbox/regex/regex.c205
-rw-r--r--core/src/tbox/src/tbox/regex/regex.h422
-rw-r--r--core/src/tbox/src/tbox/stream/deprecated/async_stream.c1341
-rw-r--r--core/src/tbox/src/tbox/stream/deprecated/async_stream.h726
-rw-r--r--core/src/tbox/src/tbox/stream/deprecated/async_transfer.c1284
-rw-r--r--core/src/tbox/src/tbox/stream/deprecated/async_transfer.h323
-rw-r--r--core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/data.c710
-rw-r--r--core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/file.c648
-rw-r--r--core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/filter.c916
-rw-r--r--core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/http.c849
-rw-r--r--core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/prefix.c129
-rw-r--r--core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/prefix.h390
-rw-r--r--core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/sock.c1231
-rw-r--r--core/src/tbox/src/tbox/stream/deprecated/transfer_pool.c575
-rw-r--r--core/src/tbox/src/tbox/stream/deprecated/transfer_pool.h129
-rw-r--r--core/src/tbox/src/tbox/stream/filter.c2
-rw-r--r--core/src/tbox/src/tbox/stream/filter.h2
-rw-r--r--core/src/tbox/src/tbox/stream/impl/filter.h2
-rw-r--r--core/src/tbox/src/tbox/stream/impl/filter/cache.c2
-rw-r--r--core/src/tbox/src/tbox/stream/impl/filter/charset.c2
-rw-r--r--core/src/tbox/src/tbox/stream/impl/filter/chunked.c2
-rw-r--r--core/src/tbox/src/tbox/stream/impl/filter/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/stream/impl/filter/zip.c2
-rw-r--r--core/src/tbox/src/tbox/stream/impl/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/stream/impl/stream.h2
-rw-r--r--core/src/tbox/src/tbox/stream/impl/stream/data.c2
-rw-r--r--core/src/tbox/src/tbox/stream/impl/stream/file.c2
-rw-r--r--core/src/tbox/src/tbox/stream/impl/stream/filter.c2
-rw-r--r--core/src/tbox/src/tbox/stream/impl/stream/http.c2
-rw-r--r--core/src/tbox/src/tbox/stream/impl/stream/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/stream/impl/stream/sock.c257
-rw-r--r--core/src/tbox/src/tbox/stream/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/stream/static_stream.c2
-rw-r--r--core/src/tbox/src/tbox/stream/static_stream.h2
-rw-r--r--core/src/tbox/src/tbox/stream/stream.c4
-rw-r--r--core/src/tbox/src/tbox/stream/stream.h15
-rw-r--r--core/src/tbox/src/tbox/stream/transfer.c9
-rw-r--r--core/src/tbox/src/tbox/stream/transfer.h2
-rw-r--r--core/src/tbox/src/tbox/string/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/string/static_string.c8
-rw-r--r--core/src/tbox/src/tbox/string/static_string.h2
-rw-r--r--core/src/tbox/src/tbox/string/string.c8
-rw-r--r--core/src/tbox/src/tbox/string/string.h2
-rw-r--r--core/src/tbox/src/tbox/tbox.c3
-rw-r--r--core/src/tbox/src/tbox/tbox.config.h.in172
-rw-r--r--core/src/tbox/src/tbox/tbox.h7
-rw-r--r--core/src/tbox/src/tbox/utils/base32.c2
-rw-r--r--core/src/tbox/src/tbox/utils/base32.h2
-rw-r--r--core/src/tbox/src/tbox/utils/base64.c2
-rw-r--r--core/src/tbox/src/tbox/utils/base64.h2
-rw-r--r--core/src/tbox/src/tbox/utils/bits.c2
-rw-r--r--core/src/tbox/src/tbox/utils/bits.h2
-rw-r--r--core/src/tbox/src/tbox/utils/dump.c2
-rw-r--r--core/src/tbox/src/tbox/utils/dump.h2
-rw-r--r--core/src/tbox/src/tbox/utils/impl/bits_arm.h2
-rw-r--r--core/src/tbox/src/tbox/utils/impl/bits_gcc.h2
-rw-r--r--core/src/tbox/src/tbox/utils/impl/bits_sh4.h2
-rw-r--r--core/src/tbox/src/tbox/utils/impl/bits_x86.h2
-rw-r--r--core/src/tbox/src/tbox/utils/impl/impl.h2
-rw-r--r--core/src/tbox/src/tbox/utils/impl/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/utils/lock_profiler.c2
-rw-r--r--core/src/tbox/src/tbox/utils/lock_profiler.h2
-rw-r--r--core/src/tbox/src/tbox/utils/option.c6
-rw-r--r--core/src/tbox/src/tbox/utils/option.h2
-rw-r--r--core/src/tbox/src/tbox/utils/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/utils/singleton.c2
-rw-r--r--core/src/tbox/src/tbox/utils/singleton.h2
-rw-r--r--core/src/tbox/src/tbox/utils/trace.c6
-rw-r--r--core/src/tbox/src/tbox/utils/trace.h4
-rw-r--r--core/src/tbox/src/tbox/utils/url.c2
-rw-r--r--core/src/tbox/src/tbox/utils/url.h2
-rw-r--r--core/src/tbox/src/tbox/utils/used.c2
-rw-r--r--core/src/tbox/src/tbox/utils/used.h2
-rw-r--r--core/src/tbox/src/tbox/utils/utils.h2
-rw-r--r--core/src/tbox/src/tbox/xmake.lua31
-rw-r--r--core/src/tbox/src/tbox/xml/node.c466
-rw-r--r--core/src/tbox/src/tbox/xml/node.h333
-rw-r--r--core/src/tbox/src/tbox/xml/prefix.h41
-rw-r--r--core/src/tbox/src/tbox/xml/reader.c928
-rw-r--r--core/src/tbox/src/tbox/xml/reader.h298
-rw-r--r--core/src/tbox/src/tbox/xml/writer.c497
-rw-r--r--core/src/tbox/src/tbox/xml/writer.h198
-rw-r--r--core/src/tbox/src/tbox/xml/xml.h (renamed from core/src/tbox/src/tbox/stream/deprecated/impl/prefix.h)14
-rw-r--r--core/src/tbox/src/tbox/zip/gzip.c2
-rw-r--r--core/src/tbox/src/tbox/zip/gzip.h2
-rw-r--r--core/src/tbox/src/tbox/zip/prefix.h2
-rw-r--r--core/src/tbox/src/tbox/zip/zip.c2
-rw-r--r--core/src/tbox/src/tbox/zip/zip.h2
-rw-r--r--core/src/tbox/src/tbox/zip/zlib.c2
-rw-r--r--core/src/tbox/src/tbox/zip/zlib.h2
-rw-r--r--core/src/tbox/src/tbox/zip/zlibraw.c2
-rw-r--r--core/src/tbox/src/tbox/zip/zlibraw.h2
-rw-r--r--core/src/tbox/src/xmake.lua299
-rw-r--r--core/src/tbox/xmake.lua60
-rw-r--r--core/src/xmake/process/open.c4
-rw-r--r--core/src/xmake/process/openv.c4
-rw-r--r--core/src/xmake/process/waitlist.c2
-rw-r--r--core/src/xmake/string/convert.c2
-rw-r--r--core/src/xmake/xmake.config.h.in11
-rw-r--r--core/src/xmake/xmake.lua10
-rw-r--r--core/xmake.lua2
891 files changed, 31823 insertions, 16177 deletions
diff --git a/core/src/tbox/makefile b/core/src/tbox/makefile
index ca65a6d1c..d7f712558 100644
--- a/core/src/tbox/makefile
+++ b/core/src/tbox/makefile
@@ -188,11 +188,7 @@ tbox_C_FILES += \
src/tbox/container/hash_map \
src/tbox/container/hash_set \
src/tbox/container/heap \
- src/tbox/container/iterator/long \
- src/tbox/container/iterator/mem \
- src/tbox/container/iterator/ptr \
- src/tbox/container/iterator/size \
- src/tbox/container/iterator/str \
+ src/tbox/container/array_iterator \
src/tbox/container/iterator \
src/tbox/container/list \
src/tbox/container/list_entry \
@@ -234,6 +230,7 @@ tbox_C_FILES += \
src/tbox/platform/thread_local \
src/tbox/platform/time \
src/tbox/platform/timer \
+ src/tbox/platform/impl/sockdata \
src/tbox/platform/impl/dns \
src/tbox/platform/impl/platform \
src/tbox/libm/isfin \
diff --git a/core/src/tbox/src/tbox/algorithm/algorithm.h b/core/src/tbox/src/tbox/algorithm/algorithm.h
index 0f983d8c5..e3d10ce42 100644
--- a/core/src/tbox/src/tbox/algorithm/algorithm.h
+++ b/core/src/tbox/src/tbox/algorithm/algorithm.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file algorithm.h
diff --git a/core/src/tbox/src/tbox/algorithm/binary_find.c b/core/src/tbox/src/tbox/algorithm/binary_find.c
index 9c31e6772..13e35ec9e 100644
--- a/core/src/tbox/src/tbox/algorithm/binary_find.c
+++ b/core/src/tbox/src/tbox/algorithm/binary_find.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file binary_find.c
diff --git a/core/src/tbox/src/tbox/algorithm/binary_find.h b/core/src/tbox/src/tbox/algorithm/binary_find.h
index af36766b2..2213946ce 100644
--- a/core/src/tbox/src/tbox/algorithm/binary_find.h
+++ b/core/src/tbox/src/tbox/algorithm/binary_find.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file binary_find.h
diff --git a/core/src/tbox/src/tbox/algorithm/binary_find_if.c b/core/src/tbox/src/tbox/algorithm/binary_find_if.c
index ff5b7db6e..6fb19b516 100644
--- a/core/src/tbox/src/tbox/algorithm/binary_find_if.c
+++ b/core/src/tbox/src/tbox/algorithm/binary_find_if.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file binary_find_if.c
diff --git a/core/src/tbox/src/tbox/algorithm/binary_find_if.h b/core/src/tbox/src/tbox/algorithm/binary_find_if.h
index 4b264674b..cb316e8bf 100644
--- a/core/src/tbox/src/tbox/algorithm/binary_find_if.h
+++ b/core/src/tbox/src/tbox/algorithm/binary_find_if.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file binary_find_if.h
diff --git a/core/src/tbox/src/tbox/algorithm/bubble_sort.c b/core/src/tbox/src/tbox/algorithm/bubble_sort.c
index 3183b5918..49afffa18 100644
--- a/core/src/tbox/src/tbox/algorithm/bubble_sort.c
+++ b/core/src/tbox/src/tbox/algorithm/bubble_sort.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file bubble_sort.c
diff --git a/core/src/tbox/src/tbox/algorithm/bubble_sort.h b/core/src/tbox/src/tbox/algorithm/bubble_sort.h
index e45aeb359..ae98a9774 100644
--- a/core/src/tbox/src/tbox/algorithm/bubble_sort.h
+++ b/core/src/tbox/src/tbox/algorithm/bubble_sort.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file bubble_sort.h
diff --git a/core/src/tbox/src/tbox/algorithm/count.c b/core/src/tbox/src/tbox/algorithm/count.c
index fff1bcef7..0728b5cd7 100644
--- a/core/src/tbox/src/tbox/algorithm/count.c
+++ b/core/src/tbox/src/tbox/algorithm/count.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file count.c
diff --git a/core/src/tbox/src/tbox/algorithm/count.h b/core/src/tbox/src/tbox/algorithm/count.h
index f90114fa5..d00150e9c 100644
--- a/core/src/tbox/src/tbox/algorithm/count.h
+++ b/core/src/tbox/src/tbox/algorithm/count.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file count.h
diff --git a/core/src/tbox/src/tbox/algorithm/count_if.c b/core/src/tbox/src/tbox/algorithm/count_if.c
index 2afe74057..6f7404093 100644
--- a/core/src/tbox/src/tbox/algorithm/count_if.c
+++ b/core/src/tbox/src/tbox/algorithm/count_if.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file count_if.c
diff --git a/core/src/tbox/src/tbox/algorithm/count_if.h b/core/src/tbox/src/tbox/algorithm/count_if.h
index 880481e58..50dbf1202 100644
--- a/core/src/tbox/src/tbox/algorithm/count_if.h
+++ b/core/src/tbox/src/tbox/algorithm/count_if.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file count_if.h
diff --git a/core/src/tbox/src/tbox/algorithm/distance.c b/core/src/tbox/src/tbox/algorithm/distance.c
index 8e8b8b0ea..3d961c632 100644
--- a/core/src/tbox/src/tbox/algorithm/distance.c
+++ b/core/src/tbox/src/tbox/algorithm/distance.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file distance.c
diff --git a/core/src/tbox/src/tbox/algorithm/distance.h b/core/src/tbox/src/tbox/algorithm/distance.h
index 6653401bf..63a32f6a8 100644
--- a/core/src/tbox/src/tbox/algorithm/distance.h
+++ b/core/src/tbox/src/tbox/algorithm/distance.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file distance.h
diff --git a/core/src/tbox/src/tbox/algorithm/find.c b/core/src/tbox/src/tbox/algorithm/find.c
index 6bddb8c58..1f91b2a01 100644
--- a/core/src/tbox/src/tbox/algorithm/find.c
+++ b/core/src/tbox/src/tbox/algorithm/find.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file find.c
diff --git a/core/src/tbox/src/tbox/algorithm/find.h b/core/src/tbox/src/tbox/algorithm/find.h
index 784488743..942814123 100644
--- a/core/src/tbox/src/tbox/algorithm/find.h
+++ b/core/src/tbox/src/tbox/algorithm/find.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file find.h
diff --git a/core/src/tbox/src/tbox/algorithm/find_if.c b/core/src/tbox/src/tbox/algorithm/find_if.c
index 202f00f5c..8cf9d826f 100644
--- a/core/src/tbox/src/tbox/algorithm/find_if.c
+++ b/core/src/tbox/src/tbox/algorithm/find_if.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file find_if.c
diff --git a/core/src/tbox/src/tbox/algorithm/find_if.h b/core/src/tbox/src/tbox/algorithm/find_if.h
index 14833e05f..6e485fb58 100644
--- a/core/src/tbox/src/tbox/algorithm/find_if.h
+++ b/core/src/tbox/src/tbox/algorithm/find_if.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file find_if.h
diff --git a/core/src/tbox/src/tbox/algorithm/for.h b/core/src/tbox/src/tbox/algorithm/for.h
index 06451dd2a..a27fb36b4 100644
--- a/core/src/tbox/src/tbox/algorithm/for.h
+++ b/core/src/tbox/src/tbox/algorithm/for.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file for.h
diff --git a/core/src/tbox/src/tbox/algorithm/for_if.h b/core/src/tbox/src/tbox/algorithm/for_if.h
index 2550fad7f..e425dc5bd 100644
--- a/core/src/tbox/src/tbox/algorithm/for_if.h
+++ b/core/src/tbox/src/tbox/algorithm/for_if.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file for_if.h
diff --git a/core/src/tbox/src/tbox/algorithm/heap_sort.c b/core/src/tbox/src/tbox/algorithm/heap_sort.c
index 40b1de203..74b6ab9ab 100644
--- a/core/src/tbox/src/tbox/algorithm/heap_sort.c
+++ b/core/src/tbox/src/tbox/algorithm/heap_sort.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file heap_sort.c
diff --git a/core/src/tbox/src/tbox/algorithm/heap_sort.h b/core/src/tbox/src/tbox/algorithm/heap_sort.h
index 79a0239eb..6bc52b4b0 100644
--- a/core/src/tbox/src/tbox/algorithm/heap_sort.h
+++ b/core/src/tbox/src/tbox/algorithm/heap_sort.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file heap_sort.h
diff --git a/core/src/tbox/src/tbox/algorithm/insert_sort.c b/core/src/tbox/src/tbox/algorithm/insert_sort.c
index 73e08ec05..d31992ec7 100644
--- a/core/src/tbox/src/tbox/algorithm/insert_sort.c
+++ b/core/src/tbox/src/tbox/algorithm/insert_sort.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file insert_sort.c
diff --git a/core/src/tbox/src/tbox/algorithm/insert_sort.h b/core/src/tbox/src/tbox/algorithm/insert_sort.h
index b2a0035e8..8b0ffe2bb 100644
--- a/core/src/tbox/src/tbox/algorithm/insert_sort.h
+++ b/core/src/tbox/src/tbox/algorithm/insert_sort.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file insert_sort.h
diff --git a/core/src/tbox/src/tbox/algorithm/predicate.c b/core/src/tbox/src/tbox/algorithm/predicate.c
index 379258254..057e04e64 100644
--- a/core/src/tbox/src/tbox/algorithm/predicate.c
+++ b/core/src/tbox/src/tbox/algorithm/predicate.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file predicate.c
diff --git a/core/src/tbox/src/tbox/algorithm/predicate.h b/core/src/tbox/src/tbox/algorithm/predicate.h
index 43ee6edee..b25a81089 100644
--- a/core/src/tbox/src/tbox/algorithm/predicate.h
+++ b/core/src/tbox/src/tbox/algorithm/predicate.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file predicate.h
diff --git a/core/src/tbox/src/tbox/algorithm/prefix.h b/core/src/tbox/src/tbox/algorithm/prefix.h
index 38aea0c48..637c625bd 100644
--- a/core/src/tbox/src/tbox/algorithm/prefix.h
+++ b/core/src/tbox/src/tbox/algorithm/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/algorithm/quick_sort.c b/core/src/tbox/src/tbox/algorithm/quick_sort.c
index 1ed4030b7..4cc563f86 100644
--- a/core/src/tbox/src/tbox/algorithm/quick_sort.c
+++ b/core/src/tbox/src/tbox/algorithm/quick_sort.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file quick_sort.c
diff --git a/core/src/tbox/src/tbox/algorithm/quick_sort.h b/core/src/tbox/src/tbox/algorithm/quick_sort.h
index 38841fd6a..236b41b05 100644
--- a/core/src/tbox/src/tbox/algorithm/quick_sort.h
+++ b/core/src/tbox/src/tbox/algorithm/quick_sort.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file quick_sort.h
diff --git a/core/src/tbox/src/tbox/algorithm/remove.c b/core/src/tbox/src/tbox/algorithm/remove.c
index 1985c1d11..ac9138a75 100644
--- a/core/src/tbox/src/tbox/algorithm/remove.c
+++ b/core/src/tbox/src/tbox/algorithm/remove.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file remove.c
diff --git a/core/src/tbox/src/tbox/algorithm/remove.h b/core/src/tbox/src/tbox/algorithm/remove.h
index 7ce4d3ae8..5b995bd3c 100644
--- a/core/src/tbox/src/tbox/algorithm/remove.h
+++ b/core/src/tbox/src/tbox/algorithm/remove.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file remove.h
diff --git a/core/src/tbox/src/tbox/algorithm/remove_first.c b/core/src/tbox/src/tbox/algorithm/remove_first.c
index e89b5d0fc..5ef511edd 100644
--- a/core/src/tbox/src/tbox/algorithm/remove_first.c
+++ b/core/src/tbox/src/tbox/algorithm/remove_first.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file remove_first.c
diff --git a/core/src/tbox/src/tbox/algorithm/remove_first.h b/core/src/tbox/src/tbox/algorithm/remove_first.h
index d101fc7ba..0edcc0835 100644
--- a/core/src/tbox/src/tbox/algorithm/remove_first.h
+++ b/core/src/tbox/src/tbox/algorithm/remove_first.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file remove_first.h
diff --git a/core/src/tbox/src/tbox/algorithm/remove_first_if.c b/core/src/tbox/src/tbox/algorithm/remove_first_if.c
index 4076e4db7..902a7ed4f 100644
--- a/core/src/tbox/src/tbox/algorithm/remove_first_if.c
+++ b/core/src/tbox/src/tbox/algorithm/remove_first_if.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file remove_first_if.c
diff --git a/core/src/tbox/src/tbox/algorithm/remove_first_if.h b/core/src/tbox/src/tbox/algorithm/remove_first_if.h
index ecb9886b1..510894317 100644
--- a/core/src/tbox/src/tbox/algorithm/remove_first_if.h
+++ b/core/src/tbox/src/tbox/algorithm/remove_first_if.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file remove_first_if.h
diff --git a/core/src/tbox/src/tbox/algorithm/remove_if.c b/core/src/tbox/src/tbox/algorithm/remove_if.c
index 4930770b6..27991bfeb 100644
--- a/core/src/tbox/src/tbox/algorithm/remove_if.c
+++ b/core/src/tbox/src/tbox/algorithm/remove_if.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file remove_if.c
@@ -79,7 +79,7 @@ tb_void_t tb_remove_if_until(tb_iterator_ref_t iterator, tb_predicate_break_ref_
{
// save next
next = tb_iterator_next(iterator, itor);
-
+
// done predicate
ok = pred(iterator, tb_iterator_item(iterator, itor), value, &is_break);
@@ -113,7 +113,7 @@ tb_void_t tb_remove_if_until(tb_iterator_ref_t iterator, tb_predicate_break_ref_
tb_size_t prev_tail = tb_iterator_tail(iterator);
// remove items
- tb_iterator_remove_range(iterator, base, ok? next : itor, size);
+ tb_iterator_nremove(iterator, base, ok? next : itor, size);
// reset state
need = tb_false;
@@ -126,21 +126,17 @@ tb_void_t tb_remove_if_until(tb_iterator_ref_t iterator, tb_predicate_break_ref_
prev = base;
// the body items are removed?
- if (base != prev_tail)
- {
- // the next itor
- itor = tb_iterator_next(iterator, base);
-
- // the last item be not removed? skip the last walked item
- if (!ok)
- {
- prev = itor;
- itor = tb_iterator_next(iterator, itor);
- }
- }
+ 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);
diff --git a/core/src/tbox/src/tbox/algorithm/remove_if.h b/core/src/tbox/src/tbox/algorithm/remove_if.h
index 1c0ef5c68..de2164e2a 100644
--- a/core/src/tbox/src/tbox/algorithm/remove_if.h
+++ b/core/src/tbox/src/tbox/algorithm/remove_if.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file remove_if.h
diff --git a/core/src/tbox/src/tbox/algorithm/rfind.c b/core/src/tbox/src/tbox/algorithm/rfind.c
index 694d76e84..9c22ade6d 100644
--- a/core/src/tbox/src/tbox/algorithm/rfind.c
+++ b/core/src/tbox/src/tbox/algorithm/rfind.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file rfind.c
diff --git a/core/src/tbox/src/tbox/algorithm/rfind.h b/core/src/tbox/src/tbox/algorithm/rfind.h
index 151a261c3..a73bcb112 100644
--- a/core/src/tbox/src/tbox/algorithm/rfind.h
+++ b/core/src/tbox/src/tbox/algorithm/rfind.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file rfind.h
diff --git a/core/src/tbox/src/tbox/algorithm/rfind_if.c b/core/src/tbox/src/tbox/algorithm/rfind_if.c
index de7e0fc9d..1473c9b49 100644
--- a/core/src/tbox/src/tbox/algorithm/rfind_if.c
+++ b/core/src/tbox/src/tbox/algorithm/rfind_if.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file rfind_if.c
diff --git a/core/src/tbox/src/tbox/algorithm/rfind_if.h b/core/src/tbox/src/tbox/algorithm/rfind_if.h
index 4488fc9b1..de0c8d320 100644
--- a/core/src/tbox/src/tbox/algorithm/rfind_if.h
+++ b/core/src/tbox/src/tbox/algorithm/rfind_if.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file rfind_if.h
diff --git a/core/src/tbox/src/tbox/algorithm/rfor.h b/core/src/tbox/src/tbox/algorithm/rfor.h
index 0597b98ec..e455420a8 100644
--- a/core/src/tbox/src/tbox/algorithm/rfor.h
+++ b/core/src/tbox/src/tbox/algorithm/rfor.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file rfor.h
diff --git a/core/src/tbox/src/tbox/algorithm/rfor_if.h b/core/src/tbox/src/tbox/algorithm/rfor_if.h
index 494e114a9..f4b4ea79f 100644
--- a/core/src/tbox/src/tbox/algorithm/rfor_if.h
+++ b/core/src/tbox/src/tbox/algorithm/rfor_if.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file rfor_if.h
diff --git a/core/src/tbox/src/tbox/algorithm/rwalk.c b/core/src/tbox/src/tbox/algorithm/rwalk.c
index 144206d03..234b439fe 100644
--- a/core/src/tbox/src/tbox/algorithm/rwalk.c
+++ b/core/src/tbox/src/tbox/algorithm/rwalk.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file rwalk.c
diff --git a/core/src/tbox/src/tbox/algorithm/rwalk.h b/core/src/tbox/src/tbox/algorithm/rwalk.h
index f056d1975..23c2a8e89 100644
--- a/core/src/tbox/src/tbox/algorithm/rwalk.h
+++ b/core/src/tbox/src/tbox/algorithm/rwalk.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file rwalk.h
diff --git a/core/src/tbox/src/tbox/algorithm/sort.c b/core/src/tbox/src/tbox/algorithm/sort.c
index 28df91a7c..692cbf7ae 100644
--- a/core/src/tbox/src/tbox/algorithm/sort.c
+++ b/core/src/tbox/src/tbox/algorithm/sort.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file sort.c
@@ -62,7 +62,7 @@ tb_void_t tb_sort(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb
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_bubble_sort(iterator, head, tail, comp);
+ 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)
diff --git a/core/src/tbox/src/tbox/algorithm/sort.h b/core/src/tbox/src/tbox/algorithm/sort.h
index 3f32271af..78509feb0 100644
--- a/core/src/tbox/src/tbox/algorithm/sort.h
+++ b/core/src/tbox/src/tbox/algorithm/sort.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file sort.h
diff --git a/core/src/tbox/src/tbox/algorithm/walk.c b/core/src/tbox/src/tbox/algorithm/walk.c
index cf708c82b..2974d28e6 100644
--- a/core/src/tbox/src/tbox/algorithm/walk.c
+++ b/core/src/tbox/src/tbox/algorithm/walk.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file walk.c
diff --git a/core/src/tbox/src/tbox/algorithm/walk.h b/core/src/tbox/src/tbox/algorithm/walk.h
index 8386f76d2..7925dc50a 100644
--- a/core/src/tbox/src/tbox/algorithm/walk.h
+++ b/core/src/tbox/src/tbox/algorithm/walk.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file walk.h
diff --git a/core/src/tbox/src/tbox/charset/ascii.c b/core/src/tbox/src/tbox/charset/ascii.c
index de4995d3d..2f2fcb8af 100644
--- a/core/src/tbox/src/tbox/charset/ascii.c
+++ b/core/src/tbox/src/tbox/charset/ascii.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ascii.c
diff --git a/core/src/tbox/src/tbox/charset/charset.c b/core/src/tbox/src/tbox/charset/charset.c
index c41b97a4c..505cafd8d 100644
--- a/core/src/tbox/src/tbox/charset/charset.c
+++ b/core/src/tbox/src/tbox/charset/charset.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file charset.c
@@ -106,7 +106,7 @@ 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_iterator_make_for_mem(&array_iterator, g_charsets, tb_arrayn(g_charsets), sizeof(tb_charset_t));
+ 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
@@ -121,7 +121,7 @@ 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_iterator_make_for_mem(&array_iterator, g_charsets, tb_arrayn(g_charsets), sizeof(tb_charset_t));
+ 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
diff --git a/core/src/tbox/src/tbox/charset/charset.h b/core/src/tbox/src/tbox/charset/charset.h
index 8fa2b648d..0f725e8ce 100644
--- a/core/src/tbox/src/tbox/charset/charset.h
+++ b/core/src/tbox/src/tbox/charset/charset.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file charset.h
diff --git a/core/src/tbox/src/tbox/charset/gb2312.c b/core/src/tbox/src/tbox/charset/gb2312.c
index 26ab8d90f..b1de04745 100644
--- a/core/src/tbox/src/tbox/charset/gb2312.c
+++ b/core/src/tbox/src/tbox/charset/gb2312.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file gb2312.c
diff --git a/core/src/tbox/src/tbox/charset/gb2312.g b/core/src/tbox/src/tbox/charset/gb2312.g
index 36fe90126..4f969a51c 100644
--- a/core/src/tbox/src/tbox/charset/gb2312.g
+++ b/core/src/tbox/src/tbox/charset/gb2312.g
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file gb2312.g
diff --git a/core/src/tbox/src/tbox/charset/iso8859.c b/core/src/tbox/src/tbox/charset/iso8859.c
index 38345a89c..295cfd595 100644
--- a/core/src/tbox/src/tbox/charset/iso8859.c
+++ b/core/src/tbox/src/tbox/charset/iso8859.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file iso8859.c
diff --git a/core/src/tbox/src/tbox/charset/prefix.h b/core/src/tbox/src/tbox/charset/prefix.h
index b7ad9fc63..5aff189fe 100644
--- a/core/src/tbox/src/tbox/charset/prefix.h
+++ b/core/src/tbox/src/tbox/charset/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/charset/ucs2.c b/core/src/tbox/src/tbox/charset/ucs2.c
index f4937f689..e8afa4725 100644
--- a/core/src/tbox/src/tbox/charset/ucs2.c
+++ b/core/src/tbox/src/tbox/charset/ucs2.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ucs2.c
diff --git a/core/src/tbox/src/tbox/charset/ucs4.c b/core/src/tbox/src/tbox/charset/ucs4.c
index f60d1f321..0ce20716e 100644
--- a/core/src/tbox/src/tbox/charset/ucs4.c
+++ b/core/src/tbox/src/tbox/charset/ucs4.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ucs4.c
diff --git a/core/src/tbox/src/tbox/charset/utf16.c b/core/src/tbox/src/tbox/charset/utf16.c
index 862d92459..0a6ea8b07 100644
--- a/core/src/tbox/src/tbox/charset/utf16.c
+++ b/core/src/tbox/src/tbox/charset/utf16.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file utf16.c
diff --git a/core/src/tbox/src/tbox/charset/utf32.c b/core/src/tbox/src/tbox/charset/utf32.c
index 33ed1181e..9cb96b92b 100644
--- a/core/src/tbox/src/tbox/charset/utf32.c
+++ b/core/src/tbox/src/tbox/charset/utf32.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file utf32.c
diff --git a/core/src/tbox/src/tbox/charset/utf8.c b/core/src/tbox/src/tbox/charset/utf8.c
index 669adde10..ba82361c7 100644
--- a/core/src/tbox/src/tbox/charset/utf8.c
+++ b/core/src/tbox/src/tbox/charset/utf8.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file utf8.c
diff --git a/core/src/tbox/src/tbox/config.h b/core/src/tbox/src/tbox/config.h
index bcf623fe6..3c1cfc7b7 100644
--- a/core/src/tbox/src/tbox/config.h
+++ b/core/src/tbox/src/tbox/config.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file config.h
diff --git a/core/src/tbox/src/tbox/container/array_iterator.c b/core/src/tbox/src/tbox/container/array_iterator.c
new file mode 100644
index 000000000..1d50c7823
--- /dev/null
+++ b/core/src/tbox/src/tbox/container/array_iterator.c
@@ -0,0 +1,319 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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.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.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.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.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.op = &op;
+ iterator->items = items;
+ iterator->count = count;
+
+ // ok
+ return (tb_iterator_ref_t)iterator;
+}
diff --git a/core/src/tbox/src/tbox/container/array_iterator.h b/core/src/tbox/src/tbox/container/array_iterator.h
new file mode 100644
index 000000000..7d8ae68a9
--- /dev/null
+++ b/core/src/tbox/src/tbox/container/array_iterator.h
@@ -0,0 +1,127 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
diff --git a/core/src/tbox/src/tbox/container/bloom_filter.c b/core/src/tbox/src/tbox/container/bloom_filter.c
index 737b61639..aa9314fae 100644
--- a/core/src/tbox/src/tbox/container/bloom_filter.c
+++ b/core/src/tbox/src/tbox/container/bloom_filter.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file bloom_filter.c
diff --git a/core/src/tbox/src/tbox/container/bloom_filter.h b/core/src/tbox/src/tbox/container/bloom_filter.h
index 933ad14c1..920462ead 100644
--- a/core/src/tbox/src/tbox/container/bloom_filter.h
+++ b/core/src/tbox/src/tbox/container/bloom_filter.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file bloom_filter.h
diff --git a/core/src/tbox/src/tbox/container/circle_queue.c b/core/src/tbox/src/tbox/container/circle_queue.c
index 77159149b..48df9a3fe 100644
--- a/core/src/tbox/src/tbox/container/circle_queue.c
+++ b/core/src/tbox/src/tbox/container/circle_queue.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file circle_queue.c
@@ -183,19 +183,27 @@ tb_circle_queue_ref_t tb_circle_queue_init(tb_size_t maxn, tb_element_t element)
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.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE | TB_ITERATOR_MODE_MUTABLE;
queue->itor.priv = tb_null;
queue->itor.step = element.size;
- queue->itor.size = tb_circle_queue_itor_size;
- queue->itor.head = tb_circle_queue_itor_head;
- queue->itor.last = tb_circle_queue_itor_last;
- queue->itor.tail = tb_circle_queue_itor_tail;
- queue->itor.prev = tb_circle_queue_itor_prev;
- queue->itor.next = tb_circle_queue_itor_next;
- queue->itor.item = tb_circle_queue_itor_item;
- queue->itor.copy = tb_circle_queue_itor_copy;
- queue->itor.comp = tb_circle_queue_itor_comp;
+ queue->itor.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE | TB_ITERATOR_MODE_MUTABLE;
+ queue->itor.op = &op;
// make data
queue->data = (tb_byte_t*)tb_nalloc0(queue->maxn, element.size);
diff --git a/core/src/tbox/src/tbox/container/circle_queue.h b/core/src/tbox/src/tbox/container/circle_queue.h
index 9a83994a9..05281b49c 100644
--- a/core/src/tbox/src/tbox/container/circle_queue.h
+++ b/core/src/tbox/src/tbox/container/circle_queue.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file queue.h
diff --git a/core/src/tbox/src/tbox/container/container.h b/core/src/tbox/src/tbox/container/container.h
index b6f03d8ba..13ef87343 100644
--- a/core/src/tbox/src/tbox/container/container.h
+++ b/core/src/tbox/src/tbox/container/container.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file container.h
@@ -32,6 +32,7 @@
#include "prefix.h"
#include "element.h"
#include "iterator.h"
+#include "array_iterator.h"
#include "heap.h"
#include "stack.h"
#include "vector.h"
diff --git a/core/src/tbox/src/tbox/container/element.h b/core/src/tbox/src/tbox/container/element.h
index 0e4e94af6..5f58f91f7 100644
--- a/core/src/tbox/src/tbox/container/element.h
+++ b/core/src/tbox/src/tbox/container/element.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file element.h
diff --git a/core/src/tbox/src/tbox/container/element/hash.c b/core/src/tbox/src/tbox/container/element/hash.c
index febc3a61c..5dca91764 100644
--- a/core/src/tbox/src/tbox/container/element/hash.c
+++ b/core/src/tbox/src/tbox/container/element/hash.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file hash.c
diff --git a/core/src/tbox/src/tbox/container/element/hash.h b/core/src/tbox/src/tbox/container/element/hash.h
index 19e28a94b..898d63160 100644
--- a/core/src/tbox/src/tbox/container/element/hash.h
+++ b/core/src/tbox/src/tbox/container/element/hash.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file hash.h
@@ -31,6 +31,11 @@
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_enter__
+
+/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
@@ -95,4 +100,9 @@ tb_size_t tb_element_hash_data(tb_byte_t const* data, tb_size_t size,
*/
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
diff --git a/core/src/tbox/src/tbox/container/element/long.c b/core/src/tbox/src/tbox/container/element/long.c
index e5fef1c61..011edabac 100644
--- a/core/src/tbox/src/tbox/container/element/long.c
+++ b/core/src/tbox/src/tbox/container/element/long.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file long.c
diff --git a/core/src/tbox/src/tbox/container/element/mem.c b/core/src/tbox/src/tbox/container/element/mem.c
index 32531ca0d..6984a5df1 100644
--- a/core/src/tbox/src/tbox/container/element/mem.c
+++ b/core/src/tbox/src/tbox/container/element/mem.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file mem.c
diff --git a/core/src/tbox/src/tbox/container/element/null.c b/core/src/tbox/src/tbox/container/element/null.c
index a300eabd4..1233ff267 100644
--- a/core/src/tbox/src/tbox/container/element/null.c
+++ b/core/src/tbox/src/tbox/container/element/null.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file null.c
diff --git a/core/src/tbox/src/tbox/container/element/obj.c b/core/src/tbox/src/tbox/container/element/obj.c
index 9240e1464..e8fae3cf1 100644
--- a/core/src/tbox/src/tbox/container/element/obj.c
+++ b/core/src/tbox/src/tbox/container/element/obj.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file obj.c
diff --git a/core/src/tbox/src/tbox/container/element/prefix.h b/core/src/tbox/src/tbox/container/element/prefix.h
index 27678adcb..bee889796 100644
--- a/core/src/tbox/src/tbox/container/element/prefix.h
+++ b/core/src/tbox/src/tbox/container/element/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
@@ -33,6 +33,7 @@
#include "../../libc/libc.h"
#include "../../utils/utils.h"
#include "../../memory/memory.h"
+#include "../../object/object.h"
#include "../../stream/stream.h"
#include "../../platform/platform.h"
diff --git a/core/src/tbox/src/tbox/container/element/ptr.c b/core/src/tbox/src/tbox/container/element/ptr.c
index d00d25446..491cc4202 100644
--- a/core/src/tbox/src/tbox/container/element/ptr.c
+++ b/core/src/tbox/src/tbox/container/element/ptr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ptr.c
diff --git a/core/src/tbox/src/tbox/container/element/size.c b/core/src/tbox/src/tbox/container/element/size.c
index 883fd2a8e..306cf880b 100644
--- a/core/src/tbox/src/tbox/container/element/size.c
+++ b/core/src/tbox/src/tbox/container/element/size.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file size.c
diff --git a/core/src/tbox/src/tbox/container/element/str.c b/core/src/tbox/src/tbox/container/element/str.c
index 761074d0a..a0fbd033f 100644
--- a/core/src/tbox/src/tbox/container/element/str.c
+++ b/core/src/tbox/src/tbox/container/element/str.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file str.c
diff --git a/core/src/tbox/src/tbox/container/element/true.c b/core/src/tbox/src/tbox/container/element/true.c
index bbed6d932..3389a9a51 100644
--- a/core/src/tbox/src/tbox/container/element/true.c
+++ b/core/src/tbox/src/tbox/container/element/true.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file true.c
diff --git a/core/src/tbox/src/tbox/container/element/uint16.c b/core/src/tbox/src/tbox/container/element/uint16.c
index 2355afd88..1accd2b61 100644
--- a/core/src/tbox/src/tbox/container/element/uint16.c
+++ b/core/src/tbox/src/tbox/container/element/uint16.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file uint16.c
diff --git a/core/src/tbox/src/tbox/container/element/uint32.c b/core/src/tbox/src/tbox/container/element/uint32.c
index 60179fb8c..9a1d2c207 100644
--- a/core/src/tbox/src/tbox/container/element/uint32.c
+++ b/core/src/tbox/src/tbox/container/element/uint32.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file uint32.c
diff --git a/core/src/tbox/src/tbox/container/element/uint8.c b/core/src/tbox/src/tbox/container/element/uint8.c
index fe5262a82..c8cdc031d 100644
--- a/core/src/tbox/src/tbox/container/element/uint8.c
+++ b/core/src/tbox/src/tbox/container/element/uint8.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file uint8.c
diff --git a/core/src/tbox/src/tbox/container/hash_map.c b/core/src/tbox/src/tbox/container/hash_map.c
index 436e1be6b..2bea04a7b 100644
--- a/core/src/tbox/src/tbox/container/hash_map.c
+++ b/core/src/tbox/src/tbox/container/hash_map.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file hash_map.c
@@ -392,7 +392,7 @@ static tb_void_t tb_hash_map_itor_remove(tb_iterator_ref_t iterator, tb_size_t i
// update the hash_map item size
hash_map->item_size--;
}
-static tb_void_t tb_hash_map_itor_remove_range(tb_iterator_ref_t iterator, tb_size_t prev, tb_size_t next, tb_size_t 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;
@@ -503,20 +503,27 @@ tb_hash_map_ref_t tb_hash_map_init(tb_size_t bucket_size, tb_element_t element_n
hash_map->element_name = element_name;
hash_map->element_data = element_data;
- // init item itor
- hash_map->itor.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_MUTABLE;
- hash_map->itor.priv = tb_null;
- hash_map->itor.step = sizeof(tb_hash_map_item_t);
- hash_map->itor.size = tb_hash_map_itor_size;
- hash_map->itor.head = tb_hash_map_itor_head;
- hash_map->itor.tail = tb_hash_map_itor_tail;
- hash_map->itor.prev = tb_null;
- hash_map->itor.next = tb_hash_map_itor_next;
- hash_map->itor.item = tb_hash_map_itor_item;
- hash_map->itor.copy = tb_hash_map_itor_copy;
- hash_map->itor.comp = tb_hash_map_itor_comp;
- hash_map->itor.remove = tb_hash_map_itor_remove;
- hash_map->itor.remove_range = tb_hash_map_itor_remove_range;
+ // 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);
diff --git a/core/src/tbox/src/tbox/container/hash_map.h b/core/src/tbox/src/tbox/container/hash_map.h
index 71837c066..9594e0366 100644
--- a/core/src/tbox/src/tbox/container/hash_map.h
+++ b/core/src/tbox/src/tbox/container/hash_map.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file hash_map.h
diff --git a/core/src/tbox/src/tbox/container/hash_set.c b/core/src/tbox/src/tbox/container/hash_set.c
index cd036e4bf..718631743 100644
--- a/core/src/tbox/src/tbox/container/hash_set.c
+++ b/core/src/tbox/src/tbox/container/hash_set.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file hash_set.c
@@ -66,13 +66,22 @@ 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->item;
- hash_set->item = tb_hash_set_itor_item;
+ hash_set->priv = (tb_pointer_t)hash_set->op->item;
+ hash_set->op = &op;
// ok?
return (tb_hash_set_ref_t)hash_set;
diff --git a/core/src/tbox/src/tbox/container/hash_set.h b/core/src/tbox/src/tbox/container/hash_set.h
index a36c65d2f..6959f7dc6 100644
--- a/core/src/tbox/src/tbox/container/hash_set.h
+++ b/core/src/tbox/src/tbox/container/hash_set.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file hash_set.h
diff --git a/core/src/tbox/src/tbox/container/heap.c b/core/src/tbox/src/tbox/container/heap.c
index dbae7c4e8..cab0fc135 100644
--- a/core/src/tbox/src/tbox/container/heap.c
+++ b/core/src/tbox/src/tbox/container/heap.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file heap.c
@@ -497,20 +497,27 @@ tb_heap_ref_t tb_heap_init(tb_size_t grow, tb_element_t element)
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.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE | TB_ITERATOR_MODE_RACCESS | TB_ITERATOR_MODE_MUTABLE;
- heap->itor.priv = tb_null;
- heap->itor.step = element.size;
- heap->itor.size = tb_heap_itor_size;
- heap->itor.head = tb_heap_itor_head;
- heap->itor.last = tb_heap_itor_last;
- heap->itor.tail = tb_heap_itor_tail;
- heap->itor.prev = tb_heap_itor_prev;
- heap->itor.next = tb_heap_itor_next;
- heap->itor.item = tb_heap_itor_item;
- heap->itor.copy = tb_heap_itor_copy;
- heap->itor.comp = tb_heap_itor_comp;
- heap->itor.remove = tb_heap_itor_remove;
+ 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;
// make data
heap->data = (tb_byte_t*)tb_nalloc0(heap->maxn, element.size);
diff --git a/core/src/tbox/src/tbox/container/heap.h b/core/src/tbox/src/tbox/container/heap.h
index 54141dedb..3ebee7f31 100644
--- a/core/src/tbox/src/tbox/container/heap.h
+++ b/core/src/tbox/src/tbox/container/heap.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file heap.h
diff --git a/core/src/tbox/src/tbox/container/iterator.c b/core/src/tbox/src/tbox/container/iterator.c
index 526cf7755..b1febfb2a 100644
--- a/core/src/tbox/src/tbox/container/iterator.c
+++ b/core/src/tbox/src/tbox/container/iterator.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX op->n Source Group.
*
* @author ruki
* @file iterator.c
@@ -52,89 +52,89 @@ tb_size_t tb_iterator_step(tb_iterator_ref_t iterator)
tb_size_t tb_iterator_size(tb_iterator_ref_t iterator)
{
// check
- tb_assert(iterator && iterator->size);
+ tb_assert(iterator && iterator->op && iterator->op->size);
// size
- return iterator->size(iterator);
+ return iterator->op->size(iterator);
}
tb_size_t tb_iterator_head(tb_iterator_ref_t iterator)
{
// check
- tb_assert(iterator && iterator->head);
+ tb_assert(iterator && iterator->op && iterator->op->head);
// head
- return iterator->head(iterator);
+ return iterator->op->head(iterator);
}
tb_size_t tb_iterator_last(tb_iterator_ref_t iterator)
{
// check
- tb_assert(iterator && iterator->last);
+ tb_assert(iterator && iterator->op && iterator->op->last);
// last
- return iterator->last(iterator);
+ return iterator->op->last(iterator);
}
tb_size_t tb_iterator_tail(tb_iterator_ref_t iterator)
{
// check
- tb_assert(iterator && iterator->tail);
+ tb_assert(iterator && iterator->op && iterator->op->tail);
// tail
- return iterator->tail(iterator);
+ return iterator->op->tail(iterator);
}
tb_size_t tb_iterator_prev(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
- tb_assert(iterator && iterator->prev);
+ tb_assert(iterator && iterator->op && iterator->op->prev);
// prev
- return iterator->prev(iterator, itor);
+ return iterator->op->prev(iterator, itor);
}
tb_size_t tb_iterator_next(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
- tb_assert(iterator && iterator->next);
+ tb_assert(iterator && iterator->op && iterator->op->next);
// next
- return iterator->next(iterator, itor);
+ return iterator->op->next(iterator, itor);
}
tb_pointer_t tb_iterator_item(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
- tb_assert(iterator && iterator->item);
+ tb_assert(iterator && iterator->op && iterator->op->item);
// item
- return iterator->item(iterator, itor);
+ return iterator->op->item(iterator, itor);
}
tb_void_t tb_iterator_remove(tb_iterator_ref_t iterator, tb_size_t itor)
{
// check
- tb_assert(iterator && iterator->remove);
+ tb_assert(iterator && iterator->op && iterator->op->remove);
// remove
- return iterator->remove(iterator, itor);
+ return iterator->op->remove(iterator, itor);
}
-tb_void_t tb_iterator_remove_range(tb_iterator_ref_t iterator, tb_size_t prev, tb_size_t next, tb_size_t size)
+tb_void_t tb_iterator_nremove(tb_iterator_ref_t iterator, tb_size_t prev, tb_size_t next, tb_size_t size)
{
// check
- tb_assert(iterator && iterator->remove_range);
+ tb_assert(iterator && iterator->op && iterator->op->nremove);
- // remove range
- return iterator->remove_range(iterator, prev, next, size);
+ // 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)
{
// check
- tb_assert(iterator && iterator->copy);
+ tb_assert(iterator && iterator->op && iterator->op->copy);
// copy
- return iterator->copy(iterator, itor, item);
+ 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)
{
// check
- tb_assert(iterator && iterator->comp);
+ tb_assert(iterator && iterator->op && iterator->op->comp);
// comp
- return iterator->comp(iterator, litem, ritem);
+ return iterator->op->comp(iterator, litem, ritem);
}
diff --git a/core/src/tbox/src/tbox/container/iterator.h b/core/src/tbox/src/tbox/container/iterator.h
index ae64e2b2a..625811573 100644
--- a/core/src/tbox/src/tbox/container/iterator.h
+++ b/core/src/tbox/src/tbox/container/iterator.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file iterator.h
@@ -51,18 +51,10 @@ typedef enum __tb_iterator_mode_t
}tb_iterator_mode_t;
-/// the iterator type
-typedef struct __tb_iterator_t
+/// the iterator operation type
+struct __tb_iterator_t;
+typedef struct __tb_iterator_op_t
{
- /// the iterator mode
- tb_size_t mode;
-
- /// the iterator step
- tb_size_t step;
-
- /// the iterator priv
- tb_pointer_t priv;
-
/// the iterator size
tb_size_t (*size)(struct __tb_iterator_t* iterator);
@@ -93,27 +85,30 @@ typedef struct __tb_iterator_t
/// the iterator remove
tb_void_t (*remove)(struct __tb_iterator_t* iterator, tb_size_t itor);
- /// the iterator remove range
- tb_void_t (*remove_range)(struct __tb_iterator_t* iterator, tb_size_t prev, tb_size_t next, tb_size_t size);
+ /// 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;
-}tb_iterator_t;
+/// the iterator operation ref type
+typedef tb_iterator_op_t const* tb_iterator_op_ref_t;
-/// the array iterator type
-typedef struct __tb_array_iterator_t
+/// the iterator type
+typedef struct __tb_iterator_t
{
- /// the iterator base
- tb_iterator_t base;
+ /// the iterator mode
+ tb_size_t mode;
- /// the items
- tb_pointer_t items;
+ /// the iterator step
+ tb_size_t step;
- /// the items count
- tb_size_t count;
+ /// the iterator priv
+ tb_pointer_t priv;
-}tb_array_iterator_t, *tb_array_iterator_ref_t;
+ /// the iterator operation
+ tb_iterator_op_ref_t op;
-/// the iterator ref type
-typedef tb_iterator_t* tb_iterator_ref_t;
+}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);
@@ -122,67 +117,6 @@ typedef tb_long_t (*tb_iterator_comp_t)(tb_iterator_ref_t iterator, tb
* interfaces
*/
-/*! make iterator for the long array
- *
- * @param iterator the iterator
- * @param items the items
- * @param count the count
- *
- * @return the iterator
- */
-tb_iterator_ref_t tb_iterator_make_for_long(tb_array_iterator_ref_t iterator, tb_long_t* items, tb_size_t count);
-
-/*! make iterator for the size array
- *
- * @param iterator the iterator
- * @param items the items
- * @param count the count
- *
- * @return the iterator
- */
-tb_iterator_ref_t tb_iterator_make_for_size(tb_array_iterator_ref_t iterator, tb_size_t* items, tb_size_t count);
-
-/*! make iterator for the c-string array
- *
- * @param iterator the iterator
- * @param items the items
- * @param count the count
- *
- * @return the iterator
- */
-tb_iterator_ref_t tb_iterator_make_for_str(tb_array_iterator_ref_t iterator, tb_char_t** items, tb_size_t count);
-
-/*! make iterator for the c-string array and ignore case
- *
- * @param iterator the iterator
- * @param items the items
- * @param count the count
- *
- * @return the iterator
- */
-tb_iterator_ref_t tb_iterator_make_for_istr(tb_array_iterator_ref_t iterator, tb_char_t** items, tb_size_t count);
-
-/*! make iterator for the pointer array
- *
- * @param iterator the iterator
- * @param items the items
- * @param count the count
- *
- * @return the iterator
- */
-tb_iterator_ref_t tb_iterator_make_for_ptr(tb_array_iterator_ref_t iterator, tb_pointer_t* items, tb_size_t count);
-
-/*! make iterator for the memory array
- *
- * @param iterator the iterator
- * @param items the items
- * @param count the count
- * @param size the element size
- *
- * @return the iterator
- */
-tb_iterator_ref_t tb_iterator_make_for_mem(tb_array_iterator_ref_t iterator, tb_pointer_t items, tb_size_t count, tb_size_t size);
-
/*! the iterator mode
*
* @param iterator the iterator
@@ -272,7 +206,7 @@ tb_void_t tb_iterator_remove(tb_iterator_ref_t iterator, tb_size_t ito
* @param next the next item
* @param size the removed size
*/
-tb_void_t tb_iterator_remove_range(tb_iterator_ref_t iterator, tb_size_t prev, tb_size_t next, tb_size_t 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
*
diff --git a/core/src/tbox/src/tbox/container/iterator/mem.c b/core/src/tbox/src/tbox/container/iterator/mem.c
deleted file mode 100644
index 1dd19d2aa..000000000
--- a/core/src/tbox/src/tbox/container/iterator/mem.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*!The Treasure Box Library
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
- *
- * @author ruki
- * @file mem.c
- * @ingroup container
- *
- */
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
- */
-#include "prefix.h"
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * private implementation
- */
-static tb_pointer_t tb_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_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_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);
-}
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
- */
-tb_iterator_ref_t tb_iterator_make_for_mem(tb_array_iterator_ref_t iterator, tb_pointer_t items, tb_size_t count, tb_size_t size)
-{
- // check
- tb_assert_and_check_return_val(size, tb_null);
-
- // make iterator for the pointer array
- if (!tb_iterator_make_for_ptr(iterator, (tb_pointer_t*)items, count)) return tb_null;
-
- // init
- iterator->base.step = size;
- iterator->base.item = tb_iterator_mem_item;
- iterator->base.copy = tb_iterator_mem_copy;
- iterator->base.comp = tb_iterator_mem_comp;
-
- // ok
- return (tb_iterator_ref_t)iterator;
-}
diff --git a/core/src/tbox/src/tbox/container/iterator/ptr.c b/core/src/tbox/src/tbox/container/iterator/ptr.c
deleted file mode 100644
index caf80c40e..000000000
--- a/core/src/tbox/src/tbox/container/iterator/ptr.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*!The Treasure Box Library
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
- *
- * @author ruki
- * @file ptr.c
- * @ingroup container
- *
- */
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
- */
-#include "prefix.h"
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * private implementation
- */
-static tb_size_t tb_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_iterator_ptr_head(tb_iterator_ref_t iterator)
-{
- return 0;
-}
-static tb_size_t tb_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_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_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_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_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_iterator_ptr_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem)
-{
- return (litem < ritem)? -1 : (litem > ritem);
-}
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
- */
-tb_iterator_ref_t tb_iterator_make_for_ptr(tb_array_iterator_ref_t iterator, tb_pointer_t* items, tb_size_t count)
-{
- // check
- tb_assert(iterator && items && count);
-
- // init
- iterator->base.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE | TB_ITERATOR_MODE_RACCESS | TB_ITERATOR_MODE_MUTABLE;
- iterator->base.priv = tb_null;
- iterator->base.step = sizeof(tb_pointer_t);
- iterator->base.size = tb_iterator_ptr_size;
- iterator->base.head = tb_iterator_ptr_head;
- iterator->base.tail = tb_iterator_ptr_tail;
- iterator->base.prev = tb_iterator_ptr_prev;
- iterator->base.next = tb_iterator_ptr_next;
- iterator->base.item = tb_iterator_ptr_item;
- iterator->base.copy = tb_iterator_ptr_copy;
- iterator->base.comp = tb_iterator_ptr_comp;
- iterator->items = items;
- iterator->count = count;
-
- // ok
- return (tb_iterator_ref_t)iterator;
-}
-
diff --git a/core/src/tbox/src/tbox/container/iterator/str.c b/core/src/tbox/src/tbox/container/iterator/str.c
deleted file mode 100644
index f424b3203..000000000
--- a/core/src/tbox/src/tbox/container/iterator/str.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*!The Treasure Box Library
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
- *
- * @author ruki
- * @file str.c
- * @ingroup container
- */
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
- */
-#include "prefix.h"
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * private implementation
- */
-static tb_long_t tb_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_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);
-}
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
- */
-tb_iterator_ref_t tb_iterator_make_for_str(tb_array_iterator_ref_t iterator, tb_char_t** items, tb_size_t count)
-{
- // make iterator for the pointer array
- if (!tb_iterator_make_for_ptr(iterator, (tb_pointer_t*)items, count)) return tb_null;
-
- // init
- iterator->base.comp = tb_iterator_str_comp;
-
- // ok
- return (tb_iterator_ref_t)iterator;
-}
-tb_iterator_ref_t tb_iterator_make_for_istr(tb_array_iterator_ref_t iterator, tb_char_t** items, tb_size_t count)
-{
- // make iterator for the pointer array
- if (!tb_iterator_make_for_ptr(iterator, (tb_pointer_t*)items, count)) return tb_null;
-
- // init
- iterator->base.comp = tb_iterator_istr_comp;
-
- // ok
- return (tb_iterator_ref_t)iterator;
-}
diff --git a/core/src/tbox/src/tbox/container/list.c b/core/src/tbox/src/tbox/container/list.c
index 890ead2fd..51718c188 100644
--- a/core/src/tbox/src/tbox/container/list.c
+++ b/core/src/tbox/src/tbox/container/list.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file list.c
@@ -164,7 +164,7 @@ 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_remove_range(tb_iterator_ref_t iterator, tb_size_t prev, tb_size_t next, tb_size_t size)
+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);
@@ -221,21 +221,27 @@ tb_list_ref_t tb_list_init(tb_size_t grow, tb_element_t element)
// 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.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE;
- list->itor.priv = tb_null;
- list->itor.step = element.size;
- list->itor.size = tb_list_itor_size;
- list->itor.head = tb_list_itor_head;
- list->itor.last = tb_list_itor_last;
- list->itor.tail = tb_list_itor_tail;
- list->itor.prev = tb_list_itor_prev;
- list->itor.next = tb_list_itor_next;
- list->itor.item = tb_list_itor_item;
- list->itor.copy = tb_list_itor_copy;
- list->itor.comp = tb_list_itor_comp;
- list->itor.remove = tb_list_itor_remove;
- list->itor.remove_range = tb_list_itor_remove_range;
+ 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;
// 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);
diff --git a/core/src/tbox/src/tbox/container/list.h b/core/src/tbox/src/tbox/container/list.h
index ebc39fc70..e00270ab9 100644
--- a/core/src/tbox/src/tbox/container/list.h
+++ b/core/src/tbox/src/tbox/container/list.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file list.h
diff --git a/core/src/tbox/src/tbox/container/list_entry.c b/core/src/tbox/src/tbox/container/list_entry.c
index 55303aaf0..e682476ee 100644
--- a/core/src/tbox/src/tbox/container/list_entry.c
+++ b/core/src/tbox/src/tbox/container/list_entry.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file list_entry.c
@@ -113,7 +113,7 @@ static tb_void_t tb_list_entry_itor_remove(tb_iterator_ref_t iterator, tb_size_t
// remove it
tb_list_entry_remove(list, (tb_list_entry_ref_t)itor);
}
-static tb_void_t tb_list_entry_itor_remove_range(tb_iterator_ref_t iterator, tb_size_t prev, tb_size_t next, tb_size_t size)
+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);
@@ -150,28 +150,34 @@ tb_void_t tb_list_entry_init_(tb_list_entry_head_ref_t list, tb_size_t entry_off
// check
tb_assert_and_check_return(list && entry_size > sizeof(tb_list_entry_t));
- // init it
- 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 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.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE;
- list->itor.priv = tb_null;
- list->itor.step = entry_size;
- list->itor.size = tb_list_entry_itor_size;
- list->itor.head = tb_list_entry_itor_head;
- list->itor.last = tb_list_entry_itor_last;
- list->itor.tail = tb_list_entry_itor_tail;
- list->itor.prev = tb_list_entry_itor_prev;
- list->itor.next = tb_list_entry_itor_next;
- list->itor.item = tb_list_entry_itor_item;
- list->itor.copy = tb_list_entry_itor_copy;
- list->itor.remove = tb_list_entry_itor_remove;
- list->itor.remove_range = tb_list_entry_itor_remove_range;
- list->itor.comp = tb_null;
+ list->itor.priv = tb_null;
+ list->itor.step = entry_size;
+ list->itor.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE;
+ list->itor.op = &op;
}
tb_void_t tb_list_entry_exit(tb_list_entry_head_ref_t list)
{
diff --git a/core/src/tbox/src/tbox/container/list_entry.h b/core/src/tbox/src/tbox/container/list_entry.h
index 7abebdd53..058c5a76f 100644
--- a/core/src/tbox/src/tbox/container/list_entry.h
+++ b/core/src/tbox/src/tbox/container/list_entry.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file list_entry.h
diff --git a/core/src/tbox/src/tbox/container/prefix.h b/core/src/tbox/src/tbox/container/prefix.h
index 4e24d0261..8de0eee9f 100644
--- a/core/src/tbox/src/tbox/container/prefix.h
+++ b/core/src/tbox/src/tbox/container/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/container/priority_queue.c b/core/src/tbox/src/tbox/container/priority_queue.c
index 0cc522db6..ef2531d58 100644
--- a/core/src/tbox/src/tbox/container/priority_queue.c
+++ b/core/src/tbox/src/tbox/container/priority_queue.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file priority_queue.c
diff --git a/core/src/tbox/src/tbox/container/priority_queue.h b/core/src/tbox/src/tbox/container/priority_queue.h
index 41484aaf4..9250de49c 100644
--- a/core/src/tbox/src/tbox/container/priority_queue.h
+++ b/core/src/tbox/src/tbox/container/priority_queue.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file priority_queue.h
diff --git a/core/src/tbox/src/tbox/container/queue.c b/core/src/tbox/src/tbox/container/queue.c
index 3b465e0bf..2069d78fa 100644
--- a/core/src/tbox/src/tbox/container/queue.c
+++ b/core/src/tbox/src/tbox/container/queue.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file queue.c
diff --git a/core/src/tbox/src/tbox/container/queue.h b/core/src/tbox/src/tbox/container/queue.h
index 9eb67fac3..783d8ba2b 100644
--- a/core/src/tbox/src/tbox/container/queue.h
+++ b/core/src/tbox/src/tbox/container/queue.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file queue.h
diff --git a/core/src/tbox/src/tbox/container/single_list.c b/core/src/tbox/src/tbox/container/single_list.c
index 00077987a..978c5c37f 100644
--- a/core/src/tbox/src/tbox/container/single_list.c
+++ b/core/src/tbox/src/tbox/container/single_list.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file single_list.c
@@ -151,7 +151,7 @@ static tb_long_t tb_single_list_itor_comp(tb_iterator_ref_t iterator, tb_cpointe
// comp
return list->element.comp(&list->element, litem, ritem);
}
-static tb_void_t tb_single_list_itor_remove_range(tb_iterator_ref_t iterator, tb_size_t prev, tb_size_t next, tb_size_t size)
+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);
@@ -216,19 +216,27 @@ tb_single_list_ref_t tb_single_list_init(tb_size_t grow, tb_element_t element)
// 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.mode = TB_ITERATOR_MODE_FORWARD;
- list->itor.priv = tb_null;
- list->itor.step = element.size;
- list->itor.size = tb_single_list_itor_size;
- list->itor.head = tb_single_list_itor_head;
- list->itor.last = tb_single_list_itor_last;
- list->itor.tail = tb_single_list_itor_tail;
- list->itor.next = tb_single_list_itor_next;
- list->itor.item = tb_single_list_itor_item;
- list->itor.copy = tb_single_list_itor_copy;
- list->itor.comp = tb_single_list_itor_comp;
- list->itor.remove_range = tb_single_list_itor_remove_range;
+ list->itor.priv = tb_null;
+ list->itor.step = element.size;
+ list->itor.mode = TB_ITERATOR_MODE_FORWARD;
+ list->itor.op = &op;
// 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);
diff --git a/core/src/tbox/src/tbox/container/single_list.h b/core/src/tbox/src/tbox/container/single_list.h
index ca6b00882..031e66799 100644
--- a/core/src/tbox/src/tbox/container/single_list.h
+++ b/core/src/tbox/src/tbox/container/single_list.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file single_list.h
diff --git a/core/src/tbox/src/tbox/container/single_list_entry.c b/core/src/tbox/src/tbox/container/single_list_entry.c
index b5948c970..c6046681a 100644
--- a/core/src/tbox/src/tbox/container/single_list_entry.c
+++ b/core/src/tbox/src/tbox/container/single_list_entry.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file single_list_entry.c
@@ -92,7 +92,7 @@ static tb_void_t tb_single_list_entry_itor_copy(tb_iterator_ref_t iterator, tb_s
// copy it
list->copy((tb_pointer_t)(itor - list->eoff), (tb_pointer_t)item);
}
-static tb_void_t tb_single_list_entry_itor_remove_range(tb_iterator_ref_t iterator, tb_size_t prev, tb_size_t next, tb_size_t size)
+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);
@@ -128,26 +128,34 @@ tb_void_t tb_single_list_entry_init_(tb_single_list_entry_head_ref_t list, tb_si
// check
tb_assert_and_check_return(list && entry_size > sizeof(tb_single_list_entry_t));
- // init it
+ // 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.mode = TB_ITERATOR_MODE_FORWARD;
- list->itor.priv = tb_null;
- list->itor.step = entry_size;
- list->itor.size = tb_single_list_entry_itor_size;
- list->itor.head = tb_single_list_entry_itor_head;
- list->itor.last = tb_single_list_entry_itor_last;
- list->itor.tail = tb_single_list_entry_itor_tail;
- list->itor.next = tb_single_list_entry_itor_next;
- list->itor.item = tb_single_list_entry_itor_item;
- list->itor.copy = tb_single_list_entry_itor_copy;
- list->itor.remove_range = tb_single_list_entry_itor_remove_range;
- list->itor.comp = tb_null;
+ list->itor.priv = tb_null;
+ list->itor.step = entry_size;
+ list->itor.mode = TB_ITERATOR_MODE_FORWARD;
+ list->itor.op = &op;
}
tb_void_t tb_single_list_entry_exit(tb_single_list_entry_head_ref_t list)
{
diff --git a/core/src/tbox/src/tbox/container/single_list_entry.h b/core/src/tbox/src/tbox/container/single_list_entry.h
index 13606d59a..a0261bc50 100644
--- a/core/src/tbox/src/tbox/container/single_list_entry.h
+++ b/core/src/tbox/src/tbox/container/single_list_entry.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file single_list_entry.h
diff --git a/core/src/tbox/src/tbox/container/stack.c b/core/src/tbox/src/tbox/container/stack.c
index 2ca0aff6b..1ce5500d4 100644
--- a/core/src/tbox/src/tbox/container/stack.c
+++ b/core/src/tbox/src/tbox/container/stack.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file stack.c
diff --git a/core/src/tbox/src/tbox/container/stack.h b/core/src/tbox/src/tbox/container/stack.h
index 7de5efb42..e4b03e614 100644
--- a/core/src/tbox/src/tbox/container/stack.h
+++ b/core/src/tbox/src/tbox/container/stack.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file stack.h
diff --git a/core/src/tbox/src/tbox/container/vector.c b/core/src/tbox/src/tbox/container/vector.c
index 1be56429d..54eac2dda 100644
--- a/core/src/tbox/src/tbox/container/vector.c
+++ b/core/src/tbox/src/tbox/container/vector.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file vector.c
@@ -173,7 +173,7 @@ static tb_void_t tb_vector_itor_remove(tb_iterator_ref_t iterator, tb_size_t ito
// remove it
tb_vector_remove((tb_vector_ref_t)iterator, itor);
}
-static tb_void_t tb_vector_itor_remove_range(tb_iterator_ref_t iterator, tb_size_t prev, tb_size_t next, tb_size_t size)
+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;
@@ -210,21 +210,27 @@ tb_vector_ref_t tb_vector_init(tb_size_t grow, tb_element_t element)
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.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_REVERSE | TB_ITERATOR_MODE_RACCESS | TB_ITERATOR_MODE_MUTABLE;
- vector->itor.priv = tb_null;
- vector->itor.step = element.size;
- vector->itor.size = tb_vector_itor_size;
- vector->itor.head = tb_vector_itor_head;
- vector->itor.last = tb_vector_itor_last;
- vector->itor.tail = tb_vector_itor_tail;
- vector->itor.prev = tb_vector_itor_prev;
- vector->itor.next = tb_vector_itor_next;
- vector->itor.item = tb_vector_itor_item;
- vector->itor.copy = tb_vector_itor_copy;
- vector->itor.comp = tb_vector_itor_comp;
- vector->itor.remove = tb_vector_itor_remove;
- vector->itor.remove_range = tb_vector_itor_remove_range;
+ 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;
// make data
vector->data = (tb_byte_t*)tb_nalloc0(vector->maxn, element.size);
@@ -287,7 +293,6 @@ tb_void_t tb_vector_copy(tb_vector_ref_t self, tb_vector_ref_t copy)
tb_assert_and_check_return(vector->element.size == vector_copy->element.size);
// check itor
- tb_assert_and_check_return(vector->itor.mode == vector_copy->itor.mode);
tb_assert_and_check_return(vector->itor.step == vector_copy->itor.step);
// null? clear it
diff --git a/core/src/tbox/src/tbox/container/vector.h b/core/src/tbox/src/tbox/container/vector.h
index 7532ce1c3..3c9e61b4b 100644
--- a/core/src/tbox/src/tbox/container/vector.h
+++ b/core/src/tbox/src/tbox/container/vector.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file vector.h
diff --git a/core/src/tbox/src/tbox/coroutine/channel.c b/core/src/tbox/src/tbox/coroutine/channel.c
new file mode 100644
index 000000000..96b86c185
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/channel.c
@@ -0,0 +1,487 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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;
+}
+
diff --git a/core/src/tbox/src/tbox/coroutine/channel.h b/core/src/tbox/src/tbox/coroutine/channel.h
new file mode 100644
index 000000000..cef4c4c68
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/channel.h
@@ -0,0 +1,120 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
diff --git a/core/src/tbox/src/tbox/coroutine/coroutine.c b/core/src/tbox/src/tbox/coroutine/coroutine.c
new file mode 100644
index 000000000..e04bd3b71
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/coroutine.c
@@ -0,0 +1,99 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * 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_socket_ref_t sock, 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, sock, events, 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;
+}
+
diff --git a/core/src/tbox/src/tbox/coroutine/coroutine.h b/core/src/tbox/src/tbox/coroutine/coroutine.h
new file mode 100644
index 000000000..4027f053e
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/coroutine.h
@@ -0,0 +1,120 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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 "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 sock the socket
+ * @param events the waited events, will remove this socket 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_socket_ref_t sock, tb_size_t events, 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
diff --git a/core/src/tbox/src/tbox/coroutine/impl/coroutine.c b/core/src/tbox/src/tbox/coroutine/impl/coroutine.c
new file mode 100644
index 000000000..83e47961a
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/impl/coroutine.c
@@ -0,0 +1,295 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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"
+#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
+#define TB_COROUTINE_STACK_DEFSIZE (8192 << 1)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * 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);
+
+#ifdef __tb_debug__
+ // check it
+ tb_coroutine_check(coroutine);
+#endif
+
+ // trace
+ tb_trace_d("entry: %p stack: %p - %p from coroutine(%p)", coroutine, coroutine->stackbase - coroutine->stacksize, coroutine->stackbase, coroutine_from);
+
+ // 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
+
+ // 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(coroutine->stackbase - coroutine->stacksize, coroutine->stacksize);
+
+ // 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 - coroutine->stacksize, coroutine->stacksize);
+
+ // abort
+ tb_abort();
+ }
+
+ // check
+ tb_assert(coroutine->context);
+}
+#endif
+
diff --git a/core/src/tbox/src/tbox/coroutine/impl/coroutine.h b/core/src/tbox/src/tbox/coroutine/impl/coroutine.h
new file mode 100644
index 000000000..187eac9ab
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/impl/coroutine.h
@@ -0,0 +1,181 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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 timer task pointer for ltimer or timer
+ *
+ * for ltimer: task
+ * for timer: task & 0x1
+ */
+ tb_cpointer_t task;
+
+ // the socket
+ tb_socket_ref_t sock;
+
+ // the waiting events
+ tb_uint16_t events : 6;
+
+ // the cached events
+ tb_uint16_t events_cache : 6;
+
+ // is waiting?
+ tb_uint16_t waiting : 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
diff --git a/core/src/tbox/src/tbox/stream/deprecated/deprecated.h b/core/src/tbox/src/tbox/coroutine/impl/impl.h
index f7d91682a..c001a1738 100644
--- a/core/src/tbox/src/tbox/stream/deprecated/deprecated.h
+++ b/core/src/tbox/src/tbox/coroutine/impl/impl.h
@@ -16,21 +16,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
- * @file deprecated.h
- * @ingroup stream
+ * @file impl.h
*
*/
-#ifndef TB_STREAM_DEPRECATED_H
-#define TB_STREAM_DEPRECATED_H
+#ifndef TB_COROUTINE_IMPL_H
+#define TB_COROUTINE_IMPL_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
-#include "async_stream.h"
-#include "transfer_pool.h"
+#include "coroutine.h"
+#include "scheduler.h"
+#include "scheduler_io.h"
+#include "stackless/stackless.h"
#endif
diff --git a/core/src/tbox/src/tbox/container/iterator/prefix.h b/core/src/tbox/src/tbox/coroutine/impl/prefix.h
index 2ba954c74..2347de410 100644
--- a/core/src/tbox/src/tbox/container/iterator/prefix.h
+++ b/core/src/tbox/src/tbox/coroutine/impl/prefix.h
@@ -16,24 +16,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
-#ifndef TB_CONTAINER_ITERATOR_PREFIX_H
-#define TB_CONTAINER_ITERATOR_PREFIX_H
+#ifndef TB_COROUTINE_IMPL_PREFIX_H
+#define TB_COROUTINE_IMPL_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
-#include "../iterator.h"
+#include "../coroutine.h"
#include "../../libc/libc.h"
#include "../../utils/utils.h"
-#include "../../memory/memory.h"
#include "../../platform/platform.h"
+#include "../../container/container.h"
#endif
diff --git a/core/src/tbox/src/tbox/coroutine/impl/scheduler.c b/core/src/tbox/src/tbox/coroutine/impl/scheduler.c
new file mode 100644
index 000000000..042d7bbef
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/impl/scheduler.c
@@ -0,0 +1,387 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
+ *
+ * @author ruki
+ * @file scheduler.c
+ * @ingroup coroutine
+ *
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * trace
+ */
+#define TB_TRACE_MODULE_NAME "scheduler"
+#define TB_TRACE_MODULE_DEBUG (0)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * 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_socket_ref_t sock, 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;
+
+ // sleep it
+ return tb_co_scheduler_io_wait(scheduler->scheduler_io, sock, events, timeout);
+}
+
diff --git a/core/src/tbox/src/tbox/coroutine/impl/scheduler.h b/core/src/tbox/src/tbox/coroutine/impl/scheduler.h
new file mode 100644
index 000000000..774a4bb7c
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/impl/scheduler.h
@@ -0,0 +1,177 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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 sock the socket
+ * @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_socket_ref_t sock, tb_size_t events, tb_long_t timeout);
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_leave__
+
+#endif
diff --git a/core/src/tbox/src/tbox/coroutine/impl/scheduler_io.c b/core/src/tbox/src/tbox/coroutine/impl/scheduler_io.c
new file mode 100644
index 000000000..253dd7f24
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/impl/scheduler_io.c
@@ -0,0 +1,500 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * 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)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * private implementation
+ */
+static tb_void_t tb_co_scheduler_io_resume(tb_co_scheduler_t* scheduler, tb_coroutine_t* coroutine, tb_cpointer_t priv)
+{
+ // 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);
+
+ // is high-precision timer?
+ tb_size_t is_timer = (tb_size_t)(task) & 0x1;
+
+ // check
+ tb_assert((tb_size_t)task & (tb_size_t)~0x1);
+
+ // remove the timer task
+ if (__tb_unlikely__(is_timer)) tb_timer_task_exit(scheduler_io->timer, (tb_timer_task_ref_t)((tb_size_t)task & (tb_size_t)~0x1));
+ else tb_ltimer_task_exit(scheduler_io->ltimer, (tb_ltimer_task_ref_t)task);
+ coroutine->rs.wait.task = tb_null;
+ }
+
+ // clear waiting state
+ coroutine->rs.wait.waiting = 0;
+
+ // resume the coroutine
+ tb_co_scheduler_resume(scheduler, coroutine, priv);
+}
+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", coroutine, killed? "killed" : "timeout");
+
+ // resume the coroutine
+ tb_co_scheduler_io_resume(scheduler, coroutine, tb_null);
+}
+static tb_void_t tb_co_scheduler_io_events(tb_poller_ref_t poller, tb_socket_ref_t sock, tb_size_t events, tb_cpointer_t priv)
+{
+ // check
+ tb_coroutine_t* coroutine = (tb_coroutine_t*)priv;
+ tb_assert(coroutine && poller && sock);
+
+ // get scheduler
+ tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_coroutine_scheduler(coroutine);
+ tb_assert(scheduler);
+
+ // trace
+ tb_trace_d("coroutine(%p): socket: %p, events %lu", coroutine, sock, events);
+
+ // waiting now?
+ if (coroutine->rs.wait.waiting)
+ {
+ // eof for edge trigger?
+ if (events & TB_POLLER_EVENT_EOF)
+ {
+ // cache this eof as next recv/send event
+ events &= ~TB_POLLER_EVENT_EOF;
+ coroutine->rs.wait.events_cache |= coroutine->rs.wait.events;
+ }
+
+ // resume the coroutine and pass the events to suspend()
+ tb_co_scheduler_io_resume(scheduler, coroutine, (tb_cpointer_t)((events & TB_POLLER_EVENT_ERROR)? -1 : events));
+ }
+ // cache this events
+ else coroutine->rs.wait.events_cache = events;
+}
+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) 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(tb_null);
+ tb_assert_and_check_break(scheduler_io->poller);
+
+ // 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
+ 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;
+
+ // 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_socket_ref_t sock, tb_size_t events, tb_long_t timeout)
+{
+ // check
+ tb_assert(scheduler_io && sock && 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 socket(%p) ..", coroutine, events, timeout, sock);
+
+ // enable edge-trigger mode if be supported
+ if (tb_poller_support(poller, TB_POLLER_EVENT_CLEAR))
+ events |= TB_POLLER_EVENT_CLEAR;
+
+ // @note avoid to write rs.single_entry (channel/suspend) and erase rs.wait.{sock, events, events_cache}
+ tb_assert_static(sizeof(tb_single_list_entry_t) <= tb_offsetof(tb_coroutine_rs_wait_t, sock));
+
+ // exists this socket? only modify events
+ tb_socket_ref_t sock_prev = coroutine->rs.wait.sock;
+ if (sock_prev == sock)
+ {
+ // return the cached events directly if the waiting events exists cache
+ tb_size_t events_prev = coroutine->rs.wait.events;
+ tb_size_t events_cache = coroutine->rs.wait.events_cache;
+ if (events_cache && (events_prev & events))
+ {
+ // check error?
+ if (events_cache & TB_POLLER_EVENT_ERROR)
+ {
+ coroutine->rs.wait.events_cache = 0;
+ return -1;
+ }
+
+ // clear cache events
+ coroutine->rs.wait.events_cache &= ~events;
+
+ // return the cached events
+ return events_cache & events;
+ }
+
+ // modify socket from poller for waiting events if the waiting events has been changed
+ if (events_prev != events && !tb_poller_modify(poller, sock, events, coroutine))
+ {
+ // trace
+ tb_trace_e("failed to modify sock(%p) to poller on coroutine(%p)!", sock, coroutine);
+
+ // failed
+ return -1;
+ }
+ }
+ else
+ {
+ // remove the previous socket first if exists
+ if (sock_prev && !tb_poller_remove(poller, sock_prev))
+ {
+ // trace
+ tb_trace_e("failed to remove sock(%p) to poller on coroutine(%p)!", sock_prev, coroutine);
+
+ // failed
+ return -1;
+ }
+
+ // insert socket to poller for waiting events
+ if (!tb_poller_insert(poller, sock, events, coroutine))
+ {
+ // trace
+ tb_trace_e("failed to insert sock(%p) to poller on coroutine(%p)!", sock, coroutine);
+
+ // failed
+ 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;
+ }
+ }
+
+ // check
+ tb_assert(!((tb_size_t)(task) & 0x1));
+
+ // save the timer task to coroutine
+ coroutine->rs.wait.task = (is_ltimer || !task)? task : (tb_cpointer_t)((tb_size_t)(task) | 0x1);
+
+ // save the socket to coroutine for the timer function
+ coroutine->rs.wait.sock = sock;
+
+ // save waiting events to coroutine
+ coroutine->rs.wait.events = (tb_uint16_t)events;
+ coroutine->rs.wait.events_cache = 0;
+
+ // mark as waiting state
+ coroutine->rs.wait.waiting = 1;
+
+ // suspend the current coroutine and return the waited result
+ return (tb_long_t)tb_co_scheduler_suspend(scheduler_io->scheduler, tb_null);
+}
+tb_bool_t tb_co_scheduler_io_cancel(tb_co_scheduler_io_ref_t scheduler_io, tb_socket_ref_t sock)
+{
+ // check
+ tb_assert(scheduler_io && sock && 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 socket(%p) ..", coroutine, sock);
+
+ // remove the this socket from poller
+ if (coroutine->rs.wait.sock == sock)
+ {
+ // remove the previous socket first if exists
+ if (!tb_poller_remove(scheduler_io->poller, sock))
+ {
+ // trace
+ tb_trace_e("failed to remove sock(%p) to poller on coroutine(%p)!", sock, coroutine);
+
+ // failed
+ return tb_false;
+ }
+
+ // clear waited socket
+ coroutine->rs.wait.sock = tb_null;
+
+ // remove ok
+ return tb_true;
+ }
+
+ // no this socket
+ 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;
+}
+
diff --git a/core/src/tbox/src/tbox/coroutine/impl/scheduler_io.h b/core/src/tbox/src/tbox/coroutine/impl/scheduler_io.h
new file mode 100644
index 000000000..9ea16909b
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/impl/scheduler_io.h
@@ -0,0 +1,137 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_enter__
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * types
+ */
+
+// 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;
+
+}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 sock the socket
+ * @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_socket_ref_t sock, tb_size_t events, tb_long_t timeout);
+
+/*! cancel io events for the given socket
+ *
+ * @param scheduler_io the io scheduler
+ * @param sock the socket
+ *
+ * @return tb_true or tb_false
+ */
+tb_bool_t tb_co_scheduler_io_cancel(tb_co_scheduler_io_ref_t scheduler_io, tb_socket_ref_t sock);
+
+/* 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
diff --git a/core/src/tbox/src/tbox/coroutine/impl/stackless/coroutine.h b/core/src/tbox/src/tbox/coroutine/impl/stackless/coroutine.h
new file mode 100644
index 000000000..92a0e40d5
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/impl/stackless/coroutine.h
@@ -0,0 +1,139 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
+{
+#ifndef TB_CONFIG_MICRO_ENABLE
+ /* the timer task pointer for ltimer or timer
+ *
+ * for ltimer: task
+ * for timer: task & 0x1
+ */
+ tb_cpointer_t task;
+#endif
+
+ // the socket
+ tb_socket_ref_t sock;
+
+ // the waiting events
+ tb_sint32_t events : 6;
+
+ // the cached events
+ tb_sint32_t events_cache : 6;
+
+ // the events result (may be -1)
+ tb_sint32_t events_result : 6;
+
+ // is waiting?
+ tb_sint32_t waiting : 1;
+
+}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
diff --git a/core/src/tbox/src/tbox/coroutine/impl/stackless/prefix.h b/core/src/tbox/src/tbox/coroutine/impl/stackless/prefix.h
new file mode 100644
index 000000000..09cf02ad6
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/impl/stackless/prefix.h
@@ -0,0 +1,36 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
diff --git a/core/src/tbox/src/tbox/coroutine/impl/stackless/scheduler.h b/core/src/tbox/src/tbox/coroutine/impl/stackless/scheduler.h
new file mode 100644
index 000000000..5bf6ac304
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/impl/stackless/scheduler.h
@@ -0,0 +1,122 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
diff --git a/core/src/tbox/src/tbox/coroutine/impl/stackless/scheduler_io.c b/core/src/tbox/src/tbox/coroutine/impl/stackless/scheduler_io.c
new file mode 100644
index 000000000..66576970e
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/impl/stackless/scheduler_io.c
@@ -0,0 +1,513 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * 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)
+{
+ // clear waiting state
+ coroutine->rs.wait.waiting = 0;
+
+ // return events
+ coroutine->rs.wait.events_result = (tb_sint32_t)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", coroutine, killed? "killed" : "timeout");
+
+ // 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_socket_ref_t sock, tb_size_t events, tb_cpointer_t priv)
+{
+ // check
+ tb_lo_coroutine_t* coroutine = (tb_lo_coroutine_t*)priv;
+ tb_assert(coroutine && poller && sock && priv);
+
+ // get scheduler
+ tb_lo_scheduler_t* scheduler = (tb_lo_scheduler_t*)coroutine->scheduler;
+ tb_assert(scheduler);
+
+ // trace
+ tb_trace_d("coroutine(%p): socket: %p, events %lu", coroutine, sock, events);
+
+ // waiting now?
+ if (coroutine->rs.wait.waiting)
+ {
+ // eof for edge trigger?
+ if (events & TB_POLLER_EVENT_EOF)
+ {
+ // cache this eof as next recv/send event
+ events &= ~TB_POLLER_EVENT_EOF;
+ coroutine->rs.wait.events_cache |= coroutine->rs.wait.events;
+ }
+
+ // resume the coroutine and pass the events to suspend()
+ tb_lo_scheduler_io_resume(scheduler, coroutine, ((events & TB_POLLER_EVENT_ERROR)? -1 : events));
+ }
+ // cache this events
+ else coroutine->rs.wait.events_cache = events;
+}
+#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(tb_null);
+ tb_assert_and_check_break(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
+
+ // 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
+ 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);
+
+ // 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_socket_ref_t sock, tb_size_t events, tb_long_t timeout)
+{
+ // check
+ tb_assert(scheduler_io && sock && 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 socket(%p) ..", coroutine, events, timeout, sock);
+
+ // enable edge-trigger mode if be supported
+ if (tb_poller_support(poller, TB_POLLER_EVENT_CLEAR))
+ events |= TB_POLLER_EVENT_CLEAR;
+
+ // exists this socket? only modify events
+ tb_socket_ref_t sock_prev = coroutine->rs.wait.sock;
+ if (sock_prev == sock)
+ {
+ // return the cached events directly if the waiting events exists cache
+ tb_size_t events_prev = coroutine->rs.wait.events;
+ tb_size_t events_cache = coroutine->rs.wait.events_cache;
+ if (events_cache && (events_prev & events))
+ {
+ // check error?
+ if (events_cache & TB_POLLER_EVENT_ERROR)
+ {
+ coroutine->rs.wait.events_cache = 0;
+ return -1;
+ }
+
+ // clear cache events
+ coroutine->rs.wait.events_cache &= ~events;
+
+ // return the cached events
+ coroutine->rs.wait.events_result = events_cache & events;
+ return tb_false;
+ }
+
+ // modify socket from poller for waiting events if the waiting events has been changed
+ if (events_prev != events && !tb_poller_modify(poller, sock, events, coroutine))
+ {
+ // trace
+ tb_trace_e("failed to modify sock(%p) to poller on coroutine(%p)!", sock, coroutine);
+
+ // failed
+ coroutine->rs.wait.events_result = -1;
+ return tb_false;
+ }
+ }
+ else
+ {
+ // remove the previous socket first if exists
+ if (sock_prev && !tb_poller_remove(poller, sock_prev))
+ {
+ // trace
+ tb_trace_e("failed to remove sock(%p) to poller on coroutine(%p)!", sock_prev, coroutine);
+
+ // failed
+ coroutine->rs.wait.events_result = -1;
+ return tb_false;
+ }
+
+ // insert socket to poller for waiting events
+ if (!tb_poller_insert(poller, sock, events, coroutine))
+ {
+ // trace
+ tb_trace_e("failed to insert sock(%p) to poller on coroutine(%p)!", sock, coroutine);
+
+ // failed
+ coroutine->rs.wait.events_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;
+ }
+ }
+
+ // check
+ tb_assert(!((tb_size_t)(task) & 0x1));
+
+ // save the timer task to coroutine
+ coroutine->rs.wait.task = (is_ltimer || !task)? task : (tb_cpointer_t)((tb_size_t)(task) | 0x1);
+#endif
+
+ // save the socket to coroutine for the timer function
+ coroutine->rs.wait.sock = sock;
+
+ // save waiting events to coroutine
+ coroutine->rs.wait.events = (tb_sint32_t)events;
+ coroutine->rs.wait.events_cache = 0;
+ coroutine->rs.wait.events_result = 0;
+
+ // mark as waiting state
+ coroutine->rs.wait.waiting = 1;
+
+ // suspend it
+ return tb_true;
+}
+tb_bool_t tb_lo_scheduler_io_cancel(tb_lo_scheduler_io_ref_t scheduler_io, tb_socket_ref_t sock)
+{
+ // check
+ tb_assert(scheduler_io && sock && 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 socket(%p) ..", coroutine, sock);
+
+ // remove the this socket from poller
+ if (coroutine->rs.wait.sock == sock)
+ {
+ // remove the previous socket first if exists
+ if (!tb_poller_remove(scheduler_io->poller, sock))
+ {
+ // trace
+ tb_trace_e("failed to remove sock(%p) to poller on coroutine(%p)!", sock, coroutine);
+
+ // failed
+ coroutine->rs.wait.events_result = -1;
+ return tb_false;
+ }
+
+ // clear waited socket
+ coroutine->rs.wait.sock = tb_null;
+
+ // remove ok
+ coroutine->rs.wait.events_result = 0;
+ return tb_true;
+ }
+
+ // no this socket
+ 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;
+}
+
diff --git a/core/src/tbox/src/tbox/coroutine/impl/stackless/scheduler_io.h b/core/src/tbox/src/tbox/coroutine/impl/stackless/scheduler_io.h
new file mode 100644
index 000000000..fcd21ad7c
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/impl/stackless/scheduler_io.h
@@ -0,0 +1,137 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_enter__
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * types
+ */
+
+// 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
+
+}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 sock the socket
+ * @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_socket_ref_t sock, tb_size_t events, tb_long_t timeout);
+
+/*! cancel io events for the given socket
+ *
+ * @param scheduler_io the io scheduler
+ * @param sock the socket
+ *
+ * return tb_true or tb_false
+ */
+tb_bool_t tb_lo_scheduler_io_cancel(tb_lo_scheduler_io_ref_t scheduler_io, tb_socket_ref_t sock);
+
+/* 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
diff --git a/core/src/tbox/src/tbox/coroutine/impl/stackless/stackless.h b/core/src/tbox/src/tbox/coroutine/impl/stackless/stackless.h
new file mode 100644
index 000000000..f6749812f
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/impl/stackless/stackless.h
@@ -0,0 +1,35 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
diff --git a/core/src/tbox/src/tbox/coroutine/lock.c b/core/src/tbox/src/tbox/coroutine/lock.c
new file mode 100644
index 000000000..b075e4443
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/lock.c
@@ -0,0 +1,66 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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);
+}
diff --git a/core/src/tbox/src/tbox/coroutine/lock.h b/core/src/tbox/src/tbox/coroutine/lock.h
new file mode 100644
index 000000000..ceb8b920a
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/lock.h
@@ -0,0 +1,87 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
diff --git a/core/src/tbox/src/tbox/stream/deprecated/prefix.h b/core/src/tbox/src/tbox/coroutine/prefix.h
index 1c559c09b..8dc390ee2 100644
--- a/core/src/tbox/src/tbox/stream/deprecated/prefix.h
+++ b/core/src/tbox/src/tbox/coroutine/prefix.h
@@ -16,18 +16,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
*
*/
-#ifndef TB_STREAM_DEPRECATED_PREFIX_H
-#define TB_STREAM_DEPRECATED_PREFIX_H
+#ifndef TB_COROUTINE_PREFIX_H
+#define TB_COROUTINE_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
+
#endif
diff --git a/core/src/tbox/src/tbox/coroutine/scheduler.c b/core/src/tbox/src/tbox/coroutine/scheduler.c
new file mode 100644
index 000000000..3c0c4b3cd
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/scheduler.c
@@ -0,0 +1,238 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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"
+#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
+
+ // 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
+}
diff --git a/core/src/tbox/src/tbox/coroutine/scheduler.h b/core/src/tbox/src/tbox/coroutine/scheduler.h
new file mode 100644
index 000000000..f6c944063
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/scheduler.h
@@ -0,0 +1,87 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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 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_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
diff --git a/core/src/tbox/src/tbox/coroutine/semaphore.c b/core/src/tbox/src/tbox/coroutine/semaphore.c
new file mode 100644
index 000000000..f93826090
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/semaphore.c
@@ -0,0 +1,176 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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;
+}
diff --git a/core/src/tbox/src/tbox/coroutine/semaphore.h b/core/src/tbox/src/tbox/coroutine/semaphore.h
new file mode 100644
index 000000000..aa4be2a28
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/semaphore.h
@@ -0,0 +1,95 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
+ *
+ * @return the 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
+ *
+ * @return tb_true or tb_false
+ */
+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
diff --git a/core/src/tbox/src/tbox/coroutine/stackless/core.h b/core/src/tbox/src/tbox/coroutine/stackless/core.h
new file mode 100644
index 000000000..b97498912
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/stackless/core.h
@@ -0,0 +1,171 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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 <[email protected]>
+ *
+ * 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 <[email protected]>
+ *
+ * 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
diff --git a/core/src/tbox/src/tbox/coroutine/stackless/coroutine.c b/core/src/tbox/src/tbox/coroutine/stackless/coroutine.c
new file mode 100644
index 000000000..98fa0f780
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/stackless/coroutine.c
@@ -0,0 +1,195 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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_socket_ref_t sock, 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, sock, events, timeout);
+}
+tb_long_t tb_lo_coroutine_events_(tb_lo_coroutine_ref_t self)
+{
+ // check
+ tb_lo_coroutine_t* coroutine = (tb_lo_coroutine_t*)self;
+ tb_assert(coroutine);
+
+ // get events
+ return coroutine->rs.wait.events_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);
+}
diff --git a/core/src/tbox/src/tbox/coroutine/stackless/coroutine.h b/core/src/tbox/src/tbox/coroutine/stackless/coroutine.h
new file mode 100644
index 000000000..e2175feba
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/stackless/coroutine.h
@@ -0,0 +1,413 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * 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_waitio(sock, events, interval) \
+do \
+{ \
+ if (tb_lo_coroutine_waitio_(tb_lo_coroutine_self(), sock, events, 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 socket events after waiting
+#define tb_lo_coroutine_events() tb_lo_coroutine_events_(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 sock the socket
+ * @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_socket_ref_t sock, tb_size_t events, tb_long_t timeout);
+
+/* get the events after waiting socket
+ *
+ * @param coroutine the coroutine
+ *
+ * @return events: > 0, failed: -1, timeout: 0
+ */
+tb_long_t tb_lo_coroutine_events_(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
diff --git a/core/src/tbox/src/tbox/coroutine/stackless/lock.h b/core/src/tbox/src/tbox/coroutine/stackless/lock.h
new file mode 100644
index 000000000..232ec8753
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/stackless/lock.h
@@ -0,0 +1,81 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
diff --git a/core/src/tbox/src/tbox/coroutine/stackless/prefix.h b/core/src/tbox/src/tbox/coroutine/stackless/prefix.h
new file mode 100644
index 000000000..96cb2e83c
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/stackless/prefix.h
@@ -0,0 +1,57 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
diff --git a/core/src/tbox/src/tbox/coroutine/stackless/scheduler.c b/core/src/tbox/src/tbox/coroutine/stackless/scheduler.c
new file mode 100644
index 000000000..c80b6c18a
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/stackless/scheduler.c
@@ -0,0 +1,426 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
+
+ // 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
+}
+
diff --git a/core/src/tbox/src/tbox/coroutine/stackless/scheduler.h b/core/src/tbox/src/tbox/coroutine/stackless/scheduler.h
new file mode 100644
index 000000000..cbbac042c
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/stackless/scheduler.h
@@ -0,0 +1,81 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
diff --git a/core/src/tbox/src/tbox/coroutine/stackless/semaphore.h b/core/src/tbox/src/tbox/coroutine/stackless/semaphore.h
new file mode 100644
index 000000000..b198a88c6
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/stackless/semaphore.h
@@ -0,0 +1,104 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
diff --git a/core/src/tbox/src/tbox/coroutine/stackless/stackless.h b/core/src/tbox/src/tbox/coroutine/stackless/stackless.h
new file mode 100644
index 000000000..96f783da9
--- /dev/null
+++ b/core/src/tbox/src/tbox/coroutine/stackless/stackless.h
@@ -0,0 +1,38 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
diff --git a/core/src/tbox/src/tbox/platform/deprecated/deprecated.h b/core/src/tbox/src/tbox/database/database.h
index 19bf52e10..a7534bb6e 100644
--- a/core/src/tbox/src/tbox/platform/deprecated/deprecated.h
+++ b/core/src/tbox/src/tbox/database/database.h
@@ -16,18 +16,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
- * @file deprecated.h
- *
+ * @file database.h
+ * @defgroup database
*/
-#ifndef TB_PLATFORM_DEPRECATED_H
-#define TB_PLATFORM_DEPRECATED_H
+#ifndef TB_DATABASE_H
+#define TB_DATABASE_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "prefix.h"
+#include "sql.h"
+
+
#endif
diff --git a/core/src/tbox/src/tbox/database/impl/mysql.c b/core/src/tbox/src/tbox/database/impl/mysql.c
new file mode 100644
index 000000000..cebed6991
--- /dev/null
+++ b/core/src/tbox/src/tbox/database/impl/mysql.c
@@ -0,0 +1,1723 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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 <mysql.h>
+#include <errmsg.h>
+#include <mysqld_error.h>
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * 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;
+}
+
diff --git a/core/src/tbox/src/tbox/container/iterator/long.c b/core/src/tbox/src/tbox/database/impl/mysql.h
index 9d6c3829f..dae8a9cb1 100644
--- a/core/src/tbox/src/tbox/container/iterator/long.c
+++ b/core/src/tbox/src/tbox/database/impl/mysql.h
@@ -16,13 +16,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
- * @file long.c
- * @ingroup container
- *
+ * @file mysql.h
*/
+#ifndef TB_DATABASE_IMPL_MYSQL_H
+#define TB_DATABASE_IMPL_MYSQL_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
@@ -30,24 +30,33 @@
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
- * private implementation
+ * extern
*/
-static tb_long_t tb_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);
-}
+__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
+ * interfaces
+ */
+
+/* probe mysql from the url
+ *
+ * @param url the database url
+ *
+ * @return the score
*/
-tb_iterator_ref_t tb_iterator_make_for_long(tb_array_iterator_ref_t iterator, tb_long_t* items, tb_size_t count)
-{
- // make iterator for the pointer array
- if (!tb_iterator_make_for_ptr(iterator, (tb_pointer_t*)items, count)) return tb_null;
+tb_size_t tb_database_mysql_probe(tb_url_ref_t url);
- // init
- iterator->base.comp = tb_iterator_long_comp;
+/* 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__
- // ok
- return (tb_iterator_ref_t)iterator;
-}
+#endif
diff --git a/core/src/tbox/src/tbox/database/impl/prefix.h b/core/src/tbox/src/tbox/database/impl/prefix.h
new file mode 100644
index 000000000..7e0bfc103
--- /dev/null
+++ b/core/src/tbox/src/tbox/database/impl/prefix.h
@@ -0,0 +1,97 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
diff --git a/core/src/tbox/src/tbox/database/impl/sqlite3.c b/core/src/tbox/src/tbox/database/impl/sqlite3.c
new file mode 100644
index 000000000..716ca6a21
--- /dev/null
+++ b/core/src/tbox/src/tbox/database/impl/sqlite3.c
@@ -0,0 +1,952 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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 <sqlite3.h>
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * 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;
+}
diff --git a/core/src/tbox/src/tbox/platform/deprecated/aioo.c b/core/src/tbox/src/tbox/database/impl/sqlite3.h
index e97110308..e6c1c4bab 100644
--- a/core/src/tbox/src/tbox/platform/deprecated/aioo.c
+++ b/core/src/tbox/src/tbox/database/impl/sqlite3.h
@@ -16,46 +16,47 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
- * @file aioo.c
- * @ingroup platform
+ * @file sqlite3.h
*/
+#ifndef TB_DATABASE_IMPL_SQLITE3_H
+#define TB_DATABASE_IMPL_SQLITE3_H
/* //////////////////////////////////////////////////////////////////////////////////////
- * trace
+ * includes
*/
-#define TB_TRACE_MODULE_NAME "platform_aioo"
-#define TB_TRACE_MODULE_DEBUG (0)
+#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
+ * extern
*/
-#include "prefix.h"
-#include "../../asio/deprecated/aioe.h"
+__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
- * declaration
+ * interfaces
+ */
+
+/* probe sqlite3 from the url
+ *
+ * @param url the database url
+ *
+ * @return the score
*/
-tb_long_t tb_aioo_rtor_wait(tb_socket_ref_t sock, tb_size_t code, tb_long_t timeout);
+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);
/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
+ * extern
*/
-#if defined(TB_CONFIG_OS_WINDOWS)
-# include "../deprecated/aioo_select.c"
- tb_long_t tb_aioo_rtor_wait(tb_socket_ref_t sock, tb_size_t code, tb_long_t timeout)
- {
- return tb_aioo_rtor_select_wait(sock, code, timeout);
- }
-#elif defined(TB_CONFIG_POSIX_HAVE_POLL)
-# include "../deprecated/aioo_poll.c"
- tb_long_t tb_aioo_rtor_wait(tb_socket_ref_t sock, tb_size_t code, tb_long_t timeout)
- {
- return tb_aioo_rtor_poll_wait(sock, code, timeout);
- }
-#else
-# error have not available event mode
-#endif
+__tb_extern_c_leave__
+#endif
diff --git a/core/src/tbox/src/tbox/database/prefix.h b/core/src/tbox/src/tbox/database/prefix.h
new file mode 100644
index 000000000..553d173b9
--- /dev/null
+++ b/core/src/tbox/src/tbox/database/prefix.h
@@ -0,0 +1,38 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
diff --git a/core/src/tbox/src/tbox/database/sql.c b/core/src/tbox/src/tbox/database/sql.c
new file mode 100644
index 000000000..338a5a663
--- /dev/null
+++ b/core/src/tbox/src/tbox/database/sql.c
@@ -0,0 +1,414 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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;
+}
diff --git a/core/src/tbox/src/tbox/database/sql.h b/core/src/tbox/src/tbox/database/sql.h
new file mode 100644
index 000000000..a1af24a69
--- /dev/null
+++ b/core/src/tbox/src/tbox/database/sql.h
@@ -0,0 +1,339 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
diff --git a/core/src/tbox/src/tbox/database/value.c b/core/src/tbox/src/tbox/database/value.c
new file mode 100644
index 000000000..74ea60420
--- /dev/null
+++ b/core/src/tbox/src/tbox/database/value.c
@@ -0,0 +1,496 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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);
+}
diff --git a/core/src/tbox/src/tbox/database/value.h b/core/src/tbox/src/tbox/database/value.h
new file mode 100644
index 000000000..d77d17a54
--- /dev/null
+++ b/core/src/tbox/src/tbox/database/value.h
@@ -0,0 +1,463 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
+ * @param number the number
+ */
+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
diff --git a/core/src/tbox/src/tbox/hash/adler32.h b/core/src/tbox/src/tbox/hash/adler32.h
index 2afb5c57c..5faf7ffca 100644
--- a/core/src/tbox/src/tbox/hash/adler32.h
+++ b/core/src/tbox/src/tbox/hash/adler32.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file adler32.h
diff --git a/core/src/tbox/src/tbox/hash/ap.c b/core/src/tbox/src/tbox/hash/ap.c
index 4764eceb4..ae055269e 100644
--- a/core/src/tbox/src/tbox/hash/ap.c
+++ b/core/src/tbox/src/tbox/hash/ap.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ap.c
diff --git a/core/src/tbox/src/tbox/hash/ap.h b/core/src/tbox/src/tbox/hash/ap.h
index 173014759..c11d9cc8a 100644
--- a/core/src/tbox/src/tbox/hash/ap.h
+++ b/core/src/tbox/src/tbox/hash/ap.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ap.h
diff --git a/core/src/tbox/src/tbox/hash/arch/arm/crc32.S b/core/src/tbox/src/tbox/hash/arch/arm/crc32.S
index 221011d3c..1bc2770d5 100644
--- a/core/src/tbox/src/tbox/hash/arch/arm/crc32.S
+++ b/core/src/tbox/src/tbox/hash/arch/arm/crc32.S
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file crc32.S
diff --git a/core/src/tbox/src/tbox/hash/arch/crc32.S b/core/src/tbox/src/tbox/hash/arch/crc32.S
index fb612f3e2..7ac1c69e7 100644
--- a/core/src/tbox/src/tbox/hash/arch/crc32.S
+++ b/core/src/tbox/src/tbox/hash/arch/crc32.S
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file crc32.S
diff --git a/core/src/tbox/src/tbox/hash/bkdr.c b/core/src/tbox/src/tbox/hash/bkdr.c
index 884ccf716..54fbd5993 100644
--- a/core/src/tbox/src/tbox/hash/bkdr.c
+++ b/core/src/tbox/src/tbox/hash/bkdr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file bkdr.c
diff --git a/core/src/tbox/src/tbox/hash/bkdr.h b/core/src/tbox/src/tbox/hash/bkdr.h
index e10724327..5da91d38f 100644
--- a/core/src/tbox/src/tbox/hash/bkdr.h
+++ b/core/src/tbox/src/tbox/hash/bkdr.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file bkdr.h
diff --git a/core/src/tbox/src/tbox/hash/blizzard.c b/core/src/tbox/src/tbox/hash/blizzard.c
index 0480b247b..50f8f7528 100644
--- a/core/src/tbox/src/tbox/hash/blizzard.c
+++ b/core/src/tbox/src/tbox/hash/blizzard.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file blizzard.c
diff --git a/core/src/tbox/src/tbox/hash/blizzard.h b/core/src/tbox/src/tbox/hash/blizzard.h
index 429622a7f..4d9743558 100644
--- a/core/src/tbox/src/tbox/hash/blizzard.h
+++ b/core/src/tbox/src/tbox/hash/blizzard.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file blizzard.h
diff --git a/core/src/tbox/src/tbox/hash/crc16.c b/core/src/tbox/src/tbox/hash/crc16.c
index 40da8ddb6..eca2cc00e 100644
--- a/core/src/tbox/src/tbox/hash/crc16.c
+++ b/core/src/tbox/src/tbox/hash/crc16.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file crc16.c
diff --git a/core/src/tbox/src/tbox/hash/crc16.h b/core/src/tbox/src/tbox/hash/crc16.h
index b27a3f9ec..258c5c47a 100644
--- a/core/src/tbox/src/tbox/hash/crc16.h
+++ b/core/src/tbox/src/tbox/hash/crc16.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file crc16.h
diff --git a/core/src/tbox/src/tbox/hash/crc32.c b/core/src/tbox/src/tbox/hash/crc32.c
index 4f9dd821b..dedc91f0c 100644
--- a/core/src/tbox/src/tbox/hash/crc32.c
+++ b/core/src/tbox/src/tbox/hash/crc32.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file crc32.c
diff --git a/core/src/tbox/src/tbox/hash/crc32.h b/core/src/tbox/src/tbox/hash/crc32.h
index e6dec3804..aa2118aaa 100644
--- a/core/src/tbox/src/tbox/hash/crc32.h
+++ b/core/src/tbox/src/tbox/hash/crc32.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file crc32.h
diff --git a/core/src/tbox/src/tbox/hash/crc8.c b/core/src/tbox/src/tbox/hash/crc8.c
index 865aaab25..86db8070e 100644
--- a/core/src/tbox/src/tbox/hash/crc8.c
+++ b/core/src/tbox/src/tbox/hash/crc8.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file crc8.c
diff --git a/core/src/tbox/src/tbox/hash/crc8.h b/core/src/tbox/src/tbox/hash/crc8.h
index fb69f6b04..ded4f4290 100644
--- a/core/src/tbox/src/tbox/hash/crc8.h
+++ b/core/src/tbox/src/tbox/hash/crc8.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file crc8.h
diff --git a/core/src/tbox/src/tbox/hash/djb2.c b/core/src/tbox/src/tbox/hash/djb2.c
index 032662295..a8db441aa 100644
--- a/core/src/tbox/src/tbox/hash/djb2.c
+++ b/core/src/tbox/src/tbox/hash/djb2.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file djb2.c
diff --git a/core/src/tbox/src/tbox/hash/djb2.h b/core/src/tbox/src/tbox/hash/djb2.h
index 53600b95d..388929019 100644
--- a/core/src/tbox/src/tbox/hash/djb2.h
+++ b/core/src/tbox/src/tbox/hash/djb2.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file djb2.h
diff --git a/core/src/tbox/src/tbox/hash/fnv32.c b/core/src/tbox/src/tbox/hash/fnv32.c
index 03800fc1a..378f85ad7 100644
--- a/core/src/tbox/src/tbox/hash/fnv32.c
+++ b/core/src/tbox/src/tbox/hash/fnv32.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author alexyer, ruki
* @file fnv32.c
diff --git a/core/src/tbox/src/tbox/hash/fnv32.h b/core/src/tbox/src/tbox/hash/fnv32.h
index 859947604..921812ffc 100644
--- a/core/src/tbox/src/tbox/hash/fnv32.h
+++ b/core/src/tbox/src/tbox/hash/fnv32.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author alexyer, ruki
* @file fnv32.h
diff --git a/core/src/tbox/src/tbox/hash/fnv64.c b/core/src/tbox/src/tbox/hash/fnv64.c
index 9c7efe312..0ba81f321 100644
--- a/core/src/tbox/src/tbox/hash/fnv64.c
+++ b/core/src/tbox/src/tbox/hash/fnv64.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author alexyer, ruki
* @file fnv64.c
diff --git a/core/src/tbox/src/tbox/hash/fnv64.h b/core/src/tbox/src/tbox/hash/fnv64.h
index 870f4dd42..39e77de38 100644
--- a/core/src/tbox/src/tbox/hash/fnv64.h
+++ b/core/src/tbox/src/tbox/hash/fnv64.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author alexyer, ruki
* @file fnv64.h
diff --git a/core/src/tbox/src/tbox/hash/hash.h b/core/src/tbox/src/tbox/hash/hash.h
index d39ccdc25..c30d34304 100644
--- a/core/src/tbox/src/tbox/hash/hash.h
+++ b/core/src/tbox/src/tbox/hash/hash.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file hash.h
diff --git a/core/src/tbox/src/tbox/hash/md5.c b/core/src/tbox/src/tbox/hash/md5.c
index 32890e3af..67e399bfc 100644
--- a/core/src/tbox/src/tbox/hash/md5.c
+++ b/core/src/tbox/src/tbox/hash/md5.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file md5.c
diff --git a/core/src/tbox/src/tbox/hash/md5.h b/core/src/tbox/src/tbox/hash/md5.h
index 571d6f327..1f9128082 100644
--- a/core/src/tbox/src/tbox/hash/md5.h
+++ b/core/src/tbox/src/tbox/hash/md5.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file md5.h
diff --git a/core/src/tbox/src/tbox/hash/murmur.c b/core/src/tbox/src/tbox/hash/murmur.c
index 24e442805..f62c3da3a 100644
--- a/core/src/tbox/src/tbox/hash/murmur.c
+++ b/core/src/tbox/src/tbox/hash/murmur.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file murmur.c
diff --git a/core/src/tbox/src/tbox/hash/murmur.h b/core/src/tbox/src/tbox/hash/murmur.h
index feac3f547..55f75ee7f 100644
--- a/core/src/tbox/src/tbox/hash/murmur.h
+++ b/core/src/tbox/src/tbox/hash/murmur.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file murmur.h
diff --git a/core/src/tbox/src/tbox/hash/prefix.h b/core/src/tbox/src/tbox/hash/prefix.h
index a526eab89..6d6a1229e 100644
--- a/core/src/tbox/src/tbox/hash/prefix.h
+++ b/core/src/tbox/src/tbox/hash/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/hash/rs.c b/core/src/tbox/src/tbox/hash/rs.c
index 75af13bc0..e02f0895e 100644
--- a/core/src/tbox/src/tbox/hash/rs.c
+++ b/core/src/tbox/src/tbox/hash/rs.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file rs.c
diff --git a/core/src/tbox/src/tbox/hash/rs.h b/core/src/tbox/src/tbox/hash/rs.h
index a689508ec..08b6c878a 100644
--- a/core/src/tbox/src/tbox/hash/rs.h
+++ b/core/src/tbox/src/tbox/hash/rs.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file rs.h
diff --git a/core/src/tbox/src/tbox/hash/sdbm.c b/core/src/tbox/src/tbox/hash/sdbm.c
index 4113a8a30..60db070cc 100644
--- a/core/src/tbox/src/tbox/hash/sdbm.c
+++ b/core/src/tbox/src/tbox/hash/sdbm.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file sdbm.c
diff --git a/core/src/tbox/src/tbox/hash/sdbm.h b/core/src/tbox/src/tbox/hash/sdbm.h
index c84ac2fd8..6251d4276 100644
--- a/core/src/tbox/src/tbox/hash/sdbm.h
+++ b/core/src/tbox/src/tbox/hash/sdbm.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file sdbm.h
diff --git a/core/src/tbox/src/tbox/hash/sha.c b/core/src/tbox/src/tbox/hash/sha.c
index eace2e8fb..d6f96e910 100644
--- a/core/src/tbox/src/tbox/hash/sha.c
+++ b/core/src/tbox/src/tbox/hash/sha.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file sha.c
diff --git a/core/src/tbox/src/tbox/hash/sha.h b/core/src/tbox/src/tbox/hash/sha.h
index 8d2d580c1..8db9846ab 100644
--- a/core/src/tbox/src/tbox/hash/sha.h
+++ b/core/src/tbox/src/tbox/hash/sha.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file sha.h
diff --git a/core/src/tbox/src/tbox/hash/uuid.c b/core/src/tbox/src/tbox/hash/uuid.c
index 95967f2d4..91918fda2 100644
--- a/core/src/tbox/src/tbox/hash/uuid.c
+++ b/core/src/tbox/src/tbox/hash/uuid.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file uuid.c
diff --git a/core/src/tbox/src/tbox/hash/uuid.h b/core/src/tbox/src/tbox/hash/uuid.h
index 63024bc49..ef202da61 100644
--- a/core/src/tbox/src/tbox/hash/uuid.h
+++ b/core/src/tbox/src/tbox/hash/uuid.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file uuid.h
diff --git a/core/src/tbox/src/tbox/libc/impl/impl.h b/core/src/tbox/src/tbox/libc/impl/impl.h
index 8bf8730c0..977a549aa 100644
--- a/core/src/tbox/src/tbox/libc/impl/impl.h
+++ b/core/src/tbox/src/tbox/libc/impl/impl.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file libc.h
diff --git a/core/src/tbox/src/tbox/libc/impl/libc.c b/core/src/tbox/src/tbox/libc/impl/libc.c
index ef5612ef9..b5c320e19 100644
--- a/core/src/tbox/src/tbox/libc/impl/libc.c
+++ b/core/src/tbox/src/tbox/libc/impl/libc.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file libc.c
diff --git a/core/src/tbox/src/tbox/libc/impl/libc.h b/core/src/tbox/src/tbox/libc/impl/libc.h
index 6337abc14..6e7f08408 100644
--- a/core/src/tbox/src/tbox/libc/impl/libc.h
+++ b/core/src/tbox/src/tbox/libc/impl/libc.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file libc.h
diff --git a/core/src/tbox/src/tbox/libc/impl/prefix.h b/core/src/tbox/src/tbox/libc/impl/prefix.h
index c01efd4b1..846e12b8a 100644
--- a/core/src/tbox/src/tbox/libc/impl/prefix.h
+++ b/core/src/tbox/src/tbox/libc/impl/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/libc/libc.h b/core/src/tbox/src/tbox/libc/libc.h
index eeeec15ee..cda918a75 100644
--- a/core/src/tbox/src/tbox/libc/libc.h
+++ b/core/src/tbox/src/tbox/libc/libc.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file libc.h
diff --git a/core/src/tbox/src/tbox/libc/misc/ctype.h b/core/src/tbox/src/tbox/libc/misc/ctype.h
index 77afa9995..0f6983bf5 100644
--- a/core/src/tbox/src/tbox/libc/misc/ctype.h
+++ b/core/src/tbox/src/tbox/libc/misc/ctype.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ctype.h
diff --git a/core/src/tbox/src/tbox/libc/misc/limits.h b/core/src/tbox/src/tbox/libc/misc/limits.h
index 74afbaa7c..095f6286f 100644
--- a/core/src/tbox/src/tbox/libc/misc/limits.h
+++ b/core/src/tbox/src/tbox/libc/misc/limits.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file limits.h
diff --git a/core/src/tbox/src/tbox/libc/misc/misc.h b/core/src/tbox/src/tbox/libc/misc/misc.h
index ba01c95f9..0420c5df1 100644
--- a/core/src/tbox/src/tbox/libc/misc/misc.h
+++ b/core/src/tbox/src/tbox/libc/misc/misc.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file misc.h
diff --git a/core/src/tbox/src/tbox/libc/misc/prefix.h b/core/src/tbox/src/tbox/libc/misc/prefix.h
index 7a2c6ea2f..0c6c10b11 100644
--- a/core/src/tbox/src/tbox/libc/misc/prefix.h
+++ b/core/src/tbox/src/tbox/libc/misc/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/libc/misc/setjmp.h b/core/src/tbox/src/tbox/libc/misc/setjmp.h
index ba59bd2ad..b14c3a112 100644
--- a/core/src/tbox/src/tbox/libc/misc/setjmp.h
+++ b/core/src/tbox/src/tbox/libc/misc/setjmp.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file setjmp.h
diff --git a/core/src/tbox/src/tbox/libc/misc/signal.h b/core/src/tbox/src/tbox/libc/misc/signal.h
index e4dbc67d8..d5f408181 100644
--- a/core/src/tbox/src/tbox/libc/misc/signal.h
+++ b/core/src/tbox/src/tbox/libc/misc/signal.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file signal.h
diff --git a/core/src/tbox/src/tbox/libc/misc/stdarg.h b/core/src/tbox/src/tbox/libc/misc/stdarg.h
index 7ea425a58..b0d945ea5 100644
--- a/core/src/tbox/src/tbox/libc/misc/stdarg.h
+++ b/core/src/tbox/src/tbox/libc/misc/stdarg.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file stdarg.h
diff --git a/core/src/tbox/src/tbox/libc/misc/time/gmmktime.c b/core/src/tbox/src/tbox/libc/misc/time/gmmktime.c
index 91069a654..d9a073522 100644
--- a/core/src/tbox/src/tbox/libc/misc/time/gmmktime.c
+++ b/core/src/tbox/src/tbox/libc/misc/time/gmmktime.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file gmmktime.c
diff --git a/core/src/tbox/src/tbox/libc/misc/time/gmtime.c b/core/src/tbox/src/tbox/libc/misc/time/gmtime.c
index 893ad9298..e1cf4069e 100644
--- a/core/src/tbox/src/tbox/libc/misc/time/gmtime.c
+++ b/core/src/tbox/src/tbox/libc/misc/time/gmtime.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file gmtime.c
diff --git a/core/src/tbox/src/tbox/libc/misc/time/localtime.c b/core/src/tbox/src/tbox/libc/misc/time/localtime.c
index 69a3bf898..b0ee45a31 100644
--- a/core/src/tbox/src/tbox/libc/misc/time/localtime.c
+++ b/core/src/tbox/src/tbox/libc/misc/time/localtime.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file localtime.c
diff --git a/core/src/tbox/src/tbox/libc/misc/time/mktime.c b/core/src/tbox/src/tbox/libc/misc/time/mktime.c
index 4fce98498..685ded269 100644
--- a/core/src/tbox/src/tbox/libc/misc/time/mktime.c
+++ b/core/src/tbox/src/tbox/libc/misc/time/mktime.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file mktime.c
diff --git a/core/src/tbox/src/tbox/libc/misc/time/prefix.h b/core/src/tbox/src/tbox/libc/misc/time/prefix.h
index 4eaf5ccd3..f7662bfcf 100644
--- a/core/src/tbox/src/tbox/libc/misc/time/prefix.h
+++ b/core/src/tbox/src/tbox/libc/misc/time/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/libc/misc/time/time.c b/core/src/tbox/src/tbox/libc/misc/time/time.c
index b7a98eaf6..aca6c4efb 100644
--- a/core/src/tbox/src/tbox/libc/misc/time/time.c
+++ b/core/src/tbox/src/tbox/libc/misc/time/time.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file time.c
diff --git a/core/src/tbox/src/tbox/libc/misc/time/time.h b/core/src/tbox/src/tbox/libc/misc/time/time.h
index 0e508aa7a..b09cfcfd5 100644
--- a/core/src/tbox/src/tbox/libc/misc/time/time.h
+++ b/core/src/tbox/src/tbox/libc/misc/time/time.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file time.h
@@ -32,6 +32,11 @@
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_enter__
+
+/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
@@ -75,4 +80,9 @@ tb_time_t tb_mktime(tb_tm_t const* tm);
*/
tb_time_t tb_gmmktime(tb_tm_t const* tm);
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_leave__
+
#endif
diff --git a/core/src/tbox/src/tbox/libc/misc/time/type.h b/core/src/tbox/src/tbox/libc/misc/time/type.h
index 989215185..94fff1c33 100644
--- a/core/src/tbox/src/tbox/libc/misc/time/type.h
+++ b/core/src/tbox/src/tbox/libc/misc/time/type.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file type.h
diff --git a/core/src/tbox/src/tbox/libc/prefix.h b/core/src/tbox/src/tbox/libc/prefix.h
index 918b7548c..9169ed257 100644
--- a/core/src/tbox/src/tbox/libc/prefix.h
+++ b/core/src/tbox/src/tbox/libc/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/libc/stdio/prefix.h b/core/src/tbox/src/tbox/libc/stdio/prefix.h
index feb039c4a..eff00d598 100644
--- a/core/src/tbox/src/tbox/libc/stdio/prefix.h
+++ b/core/src/tbox/src/tbox/libc/stdio/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/libc/stdio/printf.c b/core/src/tbox/src/tbox/libc/stdio/printf.c
index a78bcd9bd..f1f3875a9 100644
--- a/core/src/tbox/src/tbox/libc/stdio/printf.c
+++ b/core/src/tbox/src/tbox/libc/stdio/printf.c
@@ -14,7 +14,7 @@
* along with TArch;
* If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a>
*
- * Copyright (C) 2009 - 2017, ruki All rights reserved.
+ * Copyright (C) 2009 - 2019, ruki All rights reserved.
*
* @author ruki
* @file printf.c
diff --git a/core/src/tbox/src/tbox/libc/stdio/printf_object.c b/core/src/tbox/src/tbox/libc/stdio/printf_object.c
index 3714c4def..f82bb71ef 100644
--- a/core/src/tbox/src/tbox/libc/stdio/printf_object.c
+++ b/core/src/tbox/src/tbox/libc/stdio/printf_object.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file printf_object.c
@@ -131,7 +131,7 @@ tb_printf_object_func_t tb_printf_object_find(tb_char_t const* name)
// init the iterator
tb_array_iterator_t array_iterator;
- tb_iterator_ref_t iterator = tb_iterator_make_for_mem(&array_iterator, g_list, g_size, sizeof(tb_printf_object_entry_t));
+ 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
diff --git a/core/src/tbox/src/tbox/libc/stdio/printf_object.h b/core/src/tbox/src/tbox/libc/stdio/printf_object.h
index 0e6906b8c..cff75235a 100644
--- a/core/src/tbox/src/tbox/libc/stdio/printf_object.h
+++ b/core/src/tbox/src/tbox/libc/stdio/printf_object.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file printf_object.h
diff --git a/core/src/tbox/src/tbox/libc/stdio/puts.c b/core/src/tbox/src/tbox/libc/stdio/puts.c
index 3cb121f4c..1710e1056 100644
--- a/core/src/tbox/src/tbox/libc/stdio/puts.c
+++ b/core/src/tbox/src/tbox/libc/stdio/puts.c
@@ -14,7 +14,7 @@
* along with TArch;
* If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a>
*
- * Copyright (C) 2009 - 2017, ruki All rights reserved.
+ * Copyright (C) 2009 - 2019, ruki All rights reserved.
*
* @author ruki
* @file puts.c
diff --git a/core/src/tbox/src/tbox/libc/stdio/snprintf.c b/core/src/tbox/src/tbox/libc/stdio/snprintf.c
index f6534ac4f..57722fad2 100644
--- a/core/src/tbox/src/tbox/libc/stdio/snprintf.c
+++ b/core/src/tbox/src/tbox/libc/stdio/snprintf.c
@@ -14,7 +14,7 @@
* along with TArch;
* If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a>
*
- * Copyright (C) 2009 - 2017, ruki All rights reserved.
+ * Copyright (C) 2009 - 2019, ruki All rights reserved.
*
* @author ruki
* @file snprintf.c
diff --git a/core/src/tbox/src/tbox/libc/stdio/sprintf.c b/core/src/tbox/src/tbox/libc/stdio/sprintf.c
index ff3ce711c..89c94f7e9 100644
--- a/core/src/tbox/src/tbox/libc/stdio/sprintf.c
+++ b/core/src/tbox/src/tbox/libc/stdio/sprintf.c
@@ -14,7 +14,7 @@
* along with TArch;
* If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a>
*
- * Copyright (C) 2009 - 2017, ruki All rights reserved.
+ * Copyright (C) 2009 - 2019, ruki All rights reserved.
*
* @author ruki
* @file sprintf.c
@@ -34,6 +34,6 @@
tb_long_t tb_sprintf(tb_char_t* s, tb_char_t const* fmt, ...)
{
tb_long_t ret = 0;
- tb_vsnprintf_format(s, TB_MAXU32, fmt, &ret);
+ tb_vsnprintf_format(s, TB_MAXU16, fmt, &ret);
return ret;
}
diff --git a/core/src/tbox/src/tbox/libc/stdio/stdio.h b/core/src/tbox/src/tbox/libc/stdio/stdio.h
index 3ca44f7b7..dba288439 100644
--- a/core/src/tbox/src/tbox/libc/stdio/stdio.h
+++ b/core/src/tbox/src/tbox/libc/stdio/stdio.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file stdio.h
diff --git a/core/src/tbox/src/tbox/libc/stdio/swprintf.c b/core/src/tbox/src/tbox/libc/stdio/swprintf.c
index 33e95fbd2..796467a39 100644
--- a/core/src/tbox/src/tbox/libc/stdio/swprintf.c
+++ b/core/src/tbox/src/tbox/libc/stdio/swprintf.c
@@ -14,7 +14,7 @@
* along with TArch;
* If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a>
*
- * Copyright (C) 2009 - 2017, ruki All rights reserved.
+ * Copyright (C) 2009 - 2019, ruki All rights reserved.
*
* @author ruki
* @file swprintf.c
diff --git a/core/src/tbox/src/tbox/libc/stdio/vsnprintf.c b/core/src/tbox/src/tbox/libc/stdio/vsnprintf.c
index 7a069f199..922f26fb3 100644
--- a/core/src/tbox/src/tbox/libc/stdio/vsnprintf.c
+++ b/core/src/tbox/src/tbox/libc/stdio/vsnprintf.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2018, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file vsnprintf.c
diff --git a/core/src/tbox/src/tbox/libc/stdio/vswprintf.c b/core/src/tbox/src/tbox/libc/stdio/vswprintf.c
index 6e503cf81..cffa1a22a 100644
--- a/core/src/tbox/src/tbox/libc/stdio/vswprintf.c
+++ b/core/src/tbox/src/tbox/libc/stdio/vswprintf.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2018, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file vswprintf.c
diff --git a/core/src/tbox/src/tbox/libc/stdio/wprintf.c b/core/src/tbox/src/tbox/libc/stdio/wprintf.c
index 2aa885e79..30ff1388c 100644
--- a/core/src/tbox/src/tbox/libc/stdio/wprintf.c
+++ b/core/src/tbox/src/tbox/libc/stdio/wprintf.c
@@ -14,7 +14,7 @@
* along with TArch;
* If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a>
*
- * Copyright (C) 2009 - 2017, ruki All rights reserved.
+ * Copyright (C) 2009 - 2019, ruki All rights reserved.
*
* @author ruki
* @file wprintf.c
diff --git a/core/src/tbox/src/tbox/libc/stdio/wputs.c b/core/src/tbox/src/tbox/libc/stdio/wputs.c
index 2d0c42602..07bc46aff 100644
--- a/core/src/tbox/src/tbox/libc/stdio/wputs.c
+++ b/core/src/tbox/src/tbox/libc/stdio/wputs.c
@@ -14,7 +14,7 @@
* along with TArch;
* If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a>
*
- * Copyright (C) 2009 - 2017, ruki All rights reserved.
+ * Copyright (C) 2009 - 2019, ruki All rights reserved.
*
* @author ruki
* @file wputs.c
diff --git a/core/src/tbox/src/tbox/libc/stdlib/mbstowcs.c b/core/src/tbox/src/tbox/libc/stdlib/mbstowcs.c
index f4fd6f5ab..00545f85e 100644
--- a/core/src/tbox/src/tbox/libc/stdlib/mbstowcs.c
+++ b/core/src/tbox/src/tbox/libc/stdlib/mbstowcs.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file mbstowcs.c
diff --git a/core/src/tbox/src/tbox/libc/stdlib/prefix.h b/core/src/tbox/src/tbox/libc/stdlib/prefix.h
index ab25e3b8c..de2a248ec 100644
--- a/core/src/tbox/src/tbox/libc/stdlib/prefix.h
+++ b/core/src/tbox/src/tbox/libc/stdlib/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/libc/stdlib/random.c b/core/src/tbox/src/tbox/libc/stdlib/random.c
index b836543e7..066a951eb 100644
--- a/core/src/tbox/src/tbox/libc/stdlib/random.c
+++ b/core/src/tbox/src/tbox/libc/stdlib/random.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file random.c
diff --git a/core/src/tbox/src/tbox/libc/stdlib/stdlib.c b/core/src/tbox/src/tbox/libc/stdlib/stdlib.c
index ccee39412..7e127fe61 100644
--- a/core/src/tbox/src/tbox/libc/stdlib/stdlib.c
+++ b/core/src/tbox/src/tbox/libc/stdlib/stdlib.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file stdlib.c
@@ -48,6 +48,8 @@ tb_uint64_t tb_s2tou64(tb_char_t const* s)
sign = 1;
s++;
}
+ // skip '+'
+ else if (*s == '+') s++;
// skip "0b"
if (s[0] == '0' && (s[1] == 'b' || s[1] == 'B'))
@@ -89,6 +91,8 @@ tb_uint64_t tb_s8tou64(tb_char_t const* s)
sign = 1;
s++;
}
+ // skip '+'
+ else if (*s == '+') s++;
// skip '0'
while ((*s) == '0') s++;
@@ -126,6 +130,8 @@ tb_uint64_t tb_s10tou64(tb_char_t const* s)
sign = 1;
s++;
}
+ // skip '+'
+ else if (*s == '+') s++;
// skip '0'
while ((*s) == '0') s++;
@@ -163,6 +169,8 @@ tb_uint64_t tb_s16tou64(tb_char_t const* s)
sign = 1;
s++;
}
+ // skip '+'
+ else if (*s == '+') s++;
// skip "0x"
if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
@@ -203,7 +211,7 @@ tb_uint64_t tb_stou64(tb_char_t const* s)
while (tb_isspace(*p)) p++;
// has sign?
- if (*p == '-') p++;
+ if (*p == '-' || *p == '+') p++;
// is hex?
if (*p++ == '0')
@@ -263,6 +271,8 @@ tb_double_t tb_s2tod(tb_char_t const* s)
sign = 1;
s++;
}
+ // skip '+'
+ else if (*s == '+') s++;
// nan?
if (s[0] == 'n' && s[1] == 'a' && s[2] == 'n')
@@ -350,6 +360,8 @@ tb_double_t tb_s8tod(tb_char_t const* s)
sign = 1;
s++;
}
+ // skip '+'
+ else if (*s == '+') s++;
// nan?
if (s[0] == 'n' && s[1] == 'a' && s[2] == 'n')
@@ -437,6 +449,8 @@ tb_double_t tb_s10tod(tb_char_t const* s)
sign = 1;
s++;
}
+ // skip '+'
+ else if (*s == '+') s++;
// nan?
if (s[0] == 'n' && s[1] == 'a' && s[2] == 'n')
@@ -524,6 +538,8 @@ tb_double_t tb_s16tod(tb_char_t const* s)
sign = 1;
s++;
}
+ // skip '+'
+ else if (*s == '+') s++;
// nan?
if (s[0] == 'n' && s[1] == 'a' && s[2] == 'n')
@@ -649,7 +665,7 @@ tb_double_t tb_stod(tb_char_t const* s)
while (tb_isspace(*p)) p++;
// has sign?
- if (*p == '-') p++;
+ if (*p == '-' || *p == '+') p++;
// is hex?
if (*p++ == '0')
diff --git a/core/src/tbox/src/tbox/libc/stdlib/stdlib.h b/core/src/tbox/src/tbox/libc/stdlib/stdlib.h
index 201551853..02cd2aaf0 100644
--- a/core/src/tbox/src/tbox/libc/stdlib/stdlib.h
+++ b/core/src/tbox/src/tbox/libc/stdlib/stdlib.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file stdlib.h
diff --git a/core/src/tbox/src/tbox/libc/stdlib/wcstombs.c b/core/src/tbox/src/tbox/libc/stdlib/wcstombs.c
index c013c203c..e118dacb1 100644
--- a/core/src/tbox/src/tbox/libc/stdlib/wcstombs.c
+++ b/core/src/tbox/src/tbox/libc/stdlib/wcstombs.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcstombs.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/arm/memcmp.c b/core/src/tbox/src/tbox/libc/string/impl/arm/memcmp.c
index dee67f4c0..1a3d613ca 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/arm/memcmp.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/arm/memcmp.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file memcmp.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/arm/memcpy.c b/core/src/tbox/src/tbox/libc/string/impl/arm/memcpy.c
index 705e0d283..2753c6b2f 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/arm/memcpy.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/arm/memcpy.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file memcpy.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/arm/memmov.c b/core/src/tbox/src/tbox/libc/string/impl/arm/memmov.c
index 61f847c32..ce8157741 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/arm/memmov.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/arm/memmov.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file memmov.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/arm/memset.c b/core/src/tbox/src/tbox/libc/string/impl/arm/memset.c
index 723addfac..9abaecc77 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/arm/memset.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/arm/memset.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file memset.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/arm/prefix.h b/core/src/tbox/src/tbox/libc/string/impl/arm/prefix.h
index 9d9d6b14b..8b73941da 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/arm/prefix.h
+++ b/core/src/tbox/src/tbox/libc/string/impl/arm/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/libc/string/impl/arm/strcmp.c b/core/src/tbox/src/tbox/libc/string/impl/arm/strcmp.c
index 9155ff238..44eab3078 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/arm/strcmp.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/arm/strcmp.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strcmp.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/arm/strcpy.c b/core/src/tbox/src/tbox/libc/string/impl/arm/strcpy.c
index a5d1b7bf8..41eb0e733 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/arm/strcpy.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/arm/strcpy.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strcpy.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/arm/strlcpy.c b/core/src/tbox/src/tbox/libc/string/impl/arm/strlcpy.c
index ef6a7298f..fd6e6d5b7 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/arm/strlcpy.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/arm/strlcpy.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strncpy.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/arm/strlen.c b/core/src/tbox/src/tbox/libc/string/impl/arm/strlen.c
index f5b3e5ec1..2d4be80ca 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/arm/strlen.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/arm/strlen.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strlen.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/arm/strncmp.c b/core/src/tbox/src/tbox/libc/string/impl/arm/strncmp.c
index 1222d7fb9..df0bfb11a 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/arm/strncmp.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/arm/strncmp.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strncmp.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/arm/strncpy.c b/core/src/tbox/src/tbox/libc/string/impl/arm/strncpy.c
index 8cf9b9026..10622411b 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/arm/strncpy.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/arm/strncpy.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strncpy.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/arm/strnlen.c b/core/src/tbox/src/tbox/libc/string/impl/arm/strnlen.c
index 9b8adcb88..51c42e81e 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/arm/strnlen.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/arm/strnlen.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strnlen.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/prefix.h b/core/src/tbox/src/tbox/libc/string/impl/prefix.h
index 1c17ad993..bb8fc3c78 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/prefix.h
+++ b/core/src/tbox/src/tbox/libc/string/impl/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/libc/string/impl/sh4/memcmp.c b/core/src/tbox/src/tbox/libc/string/impl/sh4/memcmp.c
index f6f77d9c4..477fc3b91 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/sh4/memcmp.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/sh4/memcmp.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file memcmp.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/sh4/memcpy.c b/core/src/tbox/src/tbox/libc/string/impl/sh4/memcpy.c
index 9175b1cc2..94d716d0d 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/sh4/memcpy.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/sh4/memcpy.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file memcpy.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/sh4/memmov.c b/core/src/tbox/src/tbox/libc/string/impl/sh4/memmov.c
index 3da53a8c5..d03c2269d 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/sh4/memmov.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/sh4/memmov.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file memmov.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/sh4/memset.c b/core/src/tbox/src/tbox/libc/string/impl/sh4/memset.c
index cc086fc4a..c3caa5331 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/sh4/memset.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/sh4/memset.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file memset.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/sh4/prefix.h b/core/src/tbox/src/tbox/libc/string/impl/sh4/prefix.h
index 3aa501e71..8aa43343a 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/sh4/prefix.h
+++ b/core/src/tbox/src/tbox/libc/string/impl/sh4/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/libc/string/impl/sh4/strcmp.c b/core/src/tbox/src/tbox/libc/string/impl/sh4/strcmp.c
index 2a785d3c8..f23f10e9b 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/sh4/strcmp.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/sh4/strcmp.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strcmp.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/sh4/strcpy.c b/core/src/tbox/src/tbox/libc/string/impl/sh4/strcpy.c
index a5d1b7bf8..41eb0e733 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/sh4/strcpy.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/sh4/strcpy.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strcpy.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/sh4/strlen.c b/core/src/tbox/src/tbox/libc/string/impl/sh4/strlen.c
index 6d95a1b28..e09aad46b 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/sh4/strlen.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/sh4/strlen.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strlen.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/sh4/strncmp.c b/core/src/tbox/src/tbox/libc/string/impl/sh4/strncmp.c
index 1222d7fb9..df0bfb11a 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/sh4/strncmp.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/sh4/strncmp.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strncmp.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/sh4/strncpy.c b/core/src/tbox/src/tbox/libc/string/impl/sh4/strncpy.c
index 8cf9b9026..10622411b 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/sh4/strncpy.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/sh4/strncpy.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strncpy.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/sh4/strnlen.c b/core/src/tbox/src/tbox/libc/string/impl/sh4/strnlen.c
index 9b8adcb88..51c42e81e 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/sh4/strnlen.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/sh4/strnlen.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strnlen.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/x86/memcmp.c b/core/src/tbox/src/tbox/libc/string/impl/x86/memcmp.c
index 2f3cdca35..24498ade7 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/x86/memcmp.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/x86/memcmp.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file memcmp.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/x86/memcpy.c b/core/src/tbox/src/tbox/libc/string/impl/x86/memcpy.c
index 3e8092521..f98374734 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/x86/memcpy.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/x86/memcpy.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file memcpy.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/x86/memmov.c b/core/src/tbox/src/tbox/libc/string/impl/x86/memmov.c
index da5ad0bb2..4ac4da97c 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/x86/memmov.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/x86/memmov.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file memmov.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/x86/memset.c b/core/src/tbox/src/tbox/libc/string/impl/x86/memset.c
index f2571911a..97d992158 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/x86/memset.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/x86/memset.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file memset.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/x86/prefix.h b/core/src/tbox/src/tbox/libc/string/impl/x86/prefix.h
index 0ec31cb48..05ebfbc0e 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/x86/prefix.h
+++ b/core/src/tbox/src/tbox/libc/string/impl/x86/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/libc/string/impl/x86/strcmp.c b/core/src/tbox/src/tbox/libc/string/impl/x86/strcmp.c
index 8be16a65c..c48a4d8f4 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/x86/strcmp.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/x86/strcmp.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strcmp.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/x86/strcpy.c b/core/src/tbox/src/tbox/libc/string/impl/x86/strcpy.c
index d65b3fa29..6f5f22258 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/x86/strcpy.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/x86/strcpy.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strcpy.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/x86/strlcpy.c b/core/src/tbox/src/tbox/libc/string/impl/x86/strlcpy.c
index a794bd6eb..696259d9b 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/x86/strlcpy.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/x86/strlcpy.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strlcpy.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/x86/strlen.c b/core/src/tbox/src/tbox/libc/string/impl/x86/strlen.c
index f04b4244e..52ec3880d 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/x86/strlen.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/x86/strlen.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strlen.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/x86/strncmp.c b/core/src/tbox/src/tbox/libc/string/impl/x86/strncmp.c
index 7b40b8ab3..c793bd53c 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/x86/strncmp.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/x86/strncmp.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strncmp.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/x86/strncpy.c b/core/src/tbox/src/tbox/libc/string/impl/x86/strncpy.c
index 301f06eab..be9afb50f 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/x86/strncpy.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/x86/strncpy.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strncpy.c
diff --git a/core/src/tbox/src/tbox/libc/string/impl/x86/strnlen.c b/core/src/tbox/src/tbox/libc/string/impl/x86/strnlen.c
index cacbf58b4..265f50615 100644
--- a/core/src/tbox/src/tbox/libc/string/impl/x86/strnlen.c
+++ b/core/src/tbox/src/tbox/libc/string/impl/x86/strnlen.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strnlen.c
diff --git a/core/src/tbox/src/tbox/libc/string/memcmp.c b/core/src/tbox/src/tbox/libc/string/memcmp.c
index ec4588e31..1474bf182 100644
--- a/core/src/tbox/src/tbox/libc/string/memcmp.c
+++ b/core/src/tbox/src/tbox/libc/string/memcmp.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file memcmp.c
diff --git a/core/src/tbox/src/tbox/libc/string/memcpy.c b/core/src/tbox/src/tbox/libc/string/memcpy.c
index cca104d3c..655bd3624 100644
--- a/core/src/tbox/src/tbox/libc/string/memcpy.c
+++ b/core/src/tbox/src/tbox/libc/string/memcpy.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file memcpy.c
diff --git a/core/src/tbox/src/tbox/libc/string/memdup.c b/core/src/tbox/src/tbox/libc/string/memdup.c
index c2804c436..1539a8c04 100644
--- a/core/src/tbox/src/tbox/libc/string/memdup.c
+++ b/core/src/tbox/src/tbox/libc/string/memdup.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file memdup.c
diff --git a/core/src/tbox/src/tbox/libc/string/memmem.c b/core/src/tbox/src/tbox/libc/string/memmem.c
index a9d95de0c..ee9b316d0 100644
--- a/core/src/tbox/src/tbox/libc/string/memmem.c
+++ b/core/src/tbox/src/tbox/libc/string/memmem.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file memmem.c
diff --git a/core/src/tbox/src/tbox/libc/string/memmov.c b/core/src/tbox/src/tbox/libc/string/memmov.c
index 331e70770..50533a8c0 100644
--- a/core/src/tbox/src/tbox/libc/string/memmov.c
+++ b/core/src/tbox/src/tbox/libc/string/memmov.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file memmov.c
diff --git a/core/src/tbox/src/tbox/libc/string/memset.c b/core/src/tbox/src/tbox/libc/string/memset.c
index 642a8a242..083833311 100644
--- a/core/src/tbox/src/tbox/libc/string/memset.c
+++ b/core/src/tbox/src/tbox/libc/string/memset.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file memset.c
@@ -63,7 +63,7 @@ static tb_pointer_t tb_memset_impl(tb_pointer_t s, tb_byte_t c, tb_size_t n)
tb_check_return_val(n, s);
// init
- __tb_register__ tb_byte_t* p = s;
+ __tb_register__ tb_byte_t* p = (tb_byte_t*)s;
// done
#ifdef __tb_small__
diff --git a/core/src/tbox/src/tbox/libc/string/prefix.h b/core/src/tbox/src/tbox/libc/string/prefix.h
index a92de642b..86dd9a44a 100644
--- a/core/src/tbox/src/tbox/libc/string/prefix.h
+++ b/core/src/tbox/src/tbox/libc/string/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/libc/string/strcat.c b/core/src/tbox/src/tbox/libc/string/strcat.c
index cc98178f7..1a659f12a 100644
--- a/core/src/tbox/src/tbox/libc/string/strcat.c
+++ b/core/src/tbox/src/tbox/libc/string/strcat.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strcat.c
diff --git a/core/src/tbox/src/tbox/libc/string/strchr.c b/core/src/tbox/src/tbox/libc/string/strchr.c
index d5f0e3104..926b3283e 100644
--- a/core/src/tbox/src/tbox/libc/string/strchr.c
+++ b/core/src/tbox/src/tbox/libc/string/strchr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strchr.c
diff --git a/core/src/tbox/src/tbox/libc/string/strcmp.c b/core/src/tbox/src/tbox/libc/string/strcmp.c
index c08da1fcc..5fb28c9d4 100644
--- a/core/src/tbox/src/tbox/libc/string/strcmp.c
+++ b/core/src/tbox/src/tbox/libc/string/strcmp.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strcmp.c
diff --git a/core/src/tbox/src/tbox/libc/string/strcpy.c b/core/src/tbox/src/tbox/libc/string/strcpy.c
index 72742243b..c9f4f3138 100644
--- a/core/src/tbox/src/tbox/libc/string/strcpy.c
+++ b/core/src/tbox/src/tbox/libc/string/strcpy.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strcpy.c
diff --git a/core/src/tbox/src/tbox/libc/string/strdup.c b/core/src/tbox/src/tbox/libc/string/strdup.c
index 24e97c8ee..b103ea5da 100644
--- a/core/src/tbox/src/tbox/libc/string/strdup.c
+++ b/core/src/tbox/src/tbox/libc/string/strdup.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strdup.c
diff --git a/core/src/tbox/src/tbox/libc/string/strichr.c b/core/src/tbox/src/tbox/libc/string/strichr.c
index afcec4a67..9df718cd3 100644
--- a/core/src/tbox/src/tbox/libc/string/strichr.c
+++ b/core/src/tbox/src/tbox/libc/string/strichr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strichr.c
diff --git a/core/src/tbox/src/tbox/libc/string/stricmp.c b/core/src/tbox/src/tbox/libc/string/stricmp.c
index f20c074e7..e576dd582 100644
--- a/core/src/tbox/src/tbox/libc/string/stricmp.c
+++ b/core/src/tbox/src/tbox/libc/string/stricmp.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file stricmp.c
diff --git a/core/src/tbox/src/tbox/libc/string/string.h b/core/src/tbox/src/tbox/libc/string/string.h
index 84f672570..e9716646b 100644
--- a/core/src/tbox/src/tbox/libc/string/string.h
+++ b/core/src/tbox/src/tbox/libc/string/string.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file string.h
diff --git a/core/src/tbox/src/tbox/libc/string/strirchr.c b/core/src/tbox/src/tbox/libc/string/strirchr.c
index 4b84d4c48..d74cf68b3 100644
--- a/core/src/tbox/src/tbox/libc/string/strirchr.c
+++ b/core/src/tbox/src/tbox/libc/string/strirchr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strirchr.c
diff --git a/core/src/tbox/src/tbox/libc/string/strirstr.c b/core/src/tbox/src/tbox/libc/string/strirstr.c
index 9b8d1dc34..415eb7581 100644
--- a/core/src/tbox/src/tbox/libc/string/strirstr.c
+++ b/core/src/tbox/src/tbox/libc/string/strirstr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strirstr.c
diff --git a/core/src/tbox/src/tbox/libc/string/stristr.c b/core/src/tbox/src/tbox/libc/string/stristr.c
index f3e10893f..64142d419 100644
--- a/core/src/tbox/src/tbox/libc/string/stristr.c
+++ b/core/src/tbox/src/tbox/libc/string/stristr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file stristr.c
diff --git a/core/src/tbox/src/tbox/libc/string/strlcpy.c b/core/src/tbox/src/tbox/libc/string/strlcpy.c
index 81bc2e5b1..9c182f29e 100644
--- a/core/src/tbox/src/tbox/libc/string/strlcpy.c
+++ b/core/src/tbox/src/tbox/libc/string/strlcpy.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strlcpy.c
diff --git a/core/src/tbox/src/tbox/libc/string/strlen.c b/core/src/tbox/src/tbox/libc/string/strlen.c
index ae1e6e705..2d57a0dd2 100644
--- a/core/src/tbox/src/tbox/libc/string/strlen.c
+++ b/core/src/tbox/src/tbox/libc/string/strlen.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strlen.c
diff --git a/core/src/tbox/src/tbox/libc/string/strncat.c b/core/src/tbox/src/tbox/libc/string/strncat.c
index 246bd75f1..f81ad1331 100644
--- a/core/src/tbox/src/tbox/libc/string/strncat.c
+++ b/core/src/tbox/src/tbox/libc/string/strncat.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strncat.c
diff --git a/core/src/tbox/src/tbox/libc/string/strncmp.c b/core/src/tbox/src/tbox/libc/string/strncmp.c
index 0eb075dd7..43f08bcd9 100644
--- a/core/src/tbox/src/tbox/libc/string/strncmp.c
+++ b/core/src/tbox/src/tbox/libc/string/strncmp.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strncmp.c
diff --git a/core/src/tbox/src/tbox/libc/string/strncpy.c b/core/src/tbox/src/tbox/libc/string/strncpy.c
index 9c03d2e94..3fb957791 100644
--- a/core/src/tbox/src/tbox/libc/string/strncpy.c
+++ b/core/src/tbox/src/tbox/libc/string/strncpy.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strncpy.c
diff --git a/core/src/tbox/src/tbox/libc/string/strndup.c b/core/src/tbox/src/tbox/libc/string/strndup.c
index f3928f545..b562ca120 100644
--- a/core/src/tbox/src/tbox/libc/string/strndup.c
+++ b/core/src/tbox/src/tbox/libc/string/strndup.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strndup.c
diff --git a/core/src/tbox/src/tbox/libc/string/strnicmp.c b/core/src/tbox/src/tbox/libc/string/strnicmp.c
index e00f0cc81..001026910 100644
--- a/core/src/tbox/src/tbox/libc/string/strnicmp.c
+++ b/core/src/tbox/src/tbox/libc/string/strnicmp.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strnicmp.c
diff --git a/core/src/tbox/src/tbox/libc/string/strnirchr.c b/core/src/tbox/src/tbox/libc/string/strnirchr.c
index 54510bbb3..2d7a9fd2e 100644
--- a/core/src/tbox/src/tbox/libc/string/strnirchr.c
+++ b/core/src/tbox/src/tbox/libc/string/strnirchr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strnirchr.c
diff --git a/core/src/tbox/src/tbox/libc/string/strnirstr.c b/core/src/tbox/src/tbox/libc/string/strnirstr.c
index 0a302835f..2476940b7 100644
--- a/core/src/tbox/src/tbox/libc/string/strnirstr.c
+++ b/core/src/tbox/src/tbox/libc/string/strnirstr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strnirstr.c
diff --git a/core/src/tbox/src/tbox/libc/string/strnistr.c b/core/src/tbox/src/tbox/libc/string/strnistr.c
index 07b9b04df..0e9d7172f 100644
--- a/core/src/tbox/src/tbox/libc/string/strnistr.c
+++ b/core/src/tbox/src/tbox/libc/string/strnistr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strnistr.c
diff --git a/core/src/tbox/src/tbox/libc/string/strnlen.c b/core/src/tbox/src/tbox/libc/string/strnlen.c
index 47366a7b7..5de733d50 100644
--- a/core/src/tbox/src/tbox/libc/string/strnlen.c
+++ b/core/src/tbox/src/tbox/libc/string/strnlen.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strnlen.c
diff --git a/core/src/tbox/src/tbox/libc/string/strnrchr.c b/core/src/tbox/src/tbox/libc/string/strnrchr.c
index 0ad56e766..5f198dc12 100644
--- a/core/src/tbox/src/tbox/libc/string/strnrchr.c
+++ b/core/src/tbox/src/tbox/libc/string/strnrchr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strnrchr.c
diff --git a/core/src/tbox/src/tbox/libc/string/strnrstr.c b/core/src/tbox/src/tbox/libc/string/strnrstr.c
index d21223281..856beddf1 100644
--- a/core/src/tbox/src/tbox/libc/string/strnrstr.c
+++ b/core/src/tbox/src/tbox/libc/string/strnrstr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strnrstr.c
diff --git a/core/src/tbox/src/tbox/libc/string/strnstr.c b/core/src/tbox/src/tbox/libc/string/strnstr.c
index c57def17b..ba35e2590 100644
--- a/core/src/tbox/src/tbox/libc/string/strnstr.c
+++ b/core/src/tbox/src/tbox/libc/string/strnstr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strnstr.c
diff --git a/core/src/tbox/src/tbox/libc/string/strrchr.c b/core/src/tbox/src/tbox/libc/string/strrchr.c
index a9aa32734..da3c191ce 100644
--- a/core/src/tbox/src/tbox/libc/string/strrchr.c
+++ b/core/src/tbox/src/tbox/libc/string/strrchr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strrchr.c
diff --git a/core/src/tbox/src/tbox/libc/string/strrstr.c b/core/src/tbox/src/tbox/libc/string/strrstr.c
index 808c4eeff..610e292f3 100644
--- a/core/src/tbox/src/tbox/libc/string/strrstr.c
+++ b/core/src/tbox/src/tbox/libc/string/strrstr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strrstr.c
diff --git a/core/src/tbox/src/tbox/libc/string/strstr.c b/core/src/tbox/src/tbox/libc/string/strstr.c
index 48e97674e..c0cdab7d7 100644
--- a/core/src/tbox/src/tbox/libc/string/strstr.c
+++ b/core/src/tbox/src/tbox/libc/string/strstr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file strstr.c
diff --git a/core/src/tbox/src/tbox/libc/string/wcscat.c b/core/src/tbox/src/tbox/libc/string/wcscat.c
index 6ff4a8659..792648298 100644
--- a/core/src/tbox/src/tbox/libc/string/wcscat.c
+++ b/core/src/tbox/src/tbox/libc/string/wcscat.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcscat.c
diff --git a/core/src/tbox/src/tbox/libc/string/wcschr.c b/core/src/tbox/src/tbox/libc/string/wcschr.c
index 06a1b36bf..2bdfb6dc6 100644
--- a/core/src/tbox/src/tbox/libc/string/wcschr.c
+++ b/core/src/tbox/src/tbox/libc/string/wcschr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcschr.c
diff --git a/core/src/tbox/src/tbox/libc/string/wcscmp.c b/core/src/tbox/src/tbox/libc/string/wcscmp.c
index ad6fac6c9..6229d3ff9 100644
--- a/core/src/tbox/src/tbox/libc/string/wcscmp.c
+++ b/core/src/tbox/src/tbox/libc/string/wcscmp.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcscmp.c
diff --git a/core/src/tbox/src/tbox/libc/string/wcscpy.c b/core/src/tbox/src/tbox/libc/string/wcscpy.c
index 0768be20b..b86640812 100644
--- a/core/src/tbox/src/tbox/libc/string/wcscpy.c
+++ b/core/src/tbox/src/tbox/libc/string/wcscpy.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcscpy.c
diff --git a/core/src/tbox/src/tbox/libc/string/wcsdup.c b/core/src/tbox/src/tbox/libc/string/wcsdup.c
index 2e88d0b2f..a84ec35d9 100644
--- a/core/src/tbox/src/tbox/libc/string/wcsdup.c
+++ b/core/src/tbox/src/tbox/libc/string/wcsdup.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcsdup.c
diff --git a/core/src/tbox/src/tbox/libc/string/wcsichr.c b/core/src/tbox/src/tbox/libc/string/wcsichr.c
index 8da8bb622..b6cf6a6d8 100644
--- a/core/src/tbox/src/tbox/libc/string/wcsichr.c
+++ b/core/src/tbox/src/tbox/libc/string/wcsichr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcsichr.c
diff --git a/core/src/tbox/src/tbox/libc/string/wcsicmp.c b/core/src/tbox/src/tbox/libc/string/wcsicmp.c
index 97d524949..4ed087533 100644
--- a/core/src/tbox/src/tbox/libc/string/wcsicmp.c
+++ b/core/src/tbox/src/tbox/libc/string/wcsicmp.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcsicmp.c
diff --git a/core/src/tbox/src/tbox/libc/string/wcsirchr.c b/core/src/tbox/src/tbox/libc/string/wcsirchr.c
index 4f190a16e..690cca4dc 100644
--- a/core/src/tbox/src/tbox/libc/string/wcsirchr.c
+++ b/core/src/tbox/src/tbox/libc/string/wcsirchr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcsirchr.c
diff --git a/core/src/tbox/src/tbox/libc/string/wcsirstr.c b/core/src/tbox/src/tbox/libc/string/wcsirstr.c
index 78acd3ed4..1c6c812cd 100644
--- a/core/src/tbox/src/tbox/libc/string/wcsirstr.c
+++ b/core/src/tbox/src/tbox/libc/string/wcsirstr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcsirstr.c
diff --git a/core/src/tbox/src/tbox/libc/string/wcsistr.c b/core/src/tbox/src/tbox/libc/string/wcsistr.c
index 92aca5dc5..ef860d88c 100644
--- a/core/src/tbox/src/tbox/libc/string/wcsistr.c
+++ b/core/src/tbox/src/tbox/libc/string/wcsistr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcsistr.c
diff --git a/core/src/tbox/src/tbox/libc/string/wcslcpy.c b/core/src/tbox/src/tbox/libc/string/wcslcpy.c
index 82715c908..e7f9b3252 100644
--- a/core/src/tbox/src/tbox/libc/string/wcslcpy.c
+++ b/core/src/tbox/src/tbox/libc/string/wcslcpy.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcslcpy.c
diff --git a/core/src/tbox/src/tbox/libc/string/wcslen.c b/core/src/tbox/src/tbox/libc/string/wcslen.c
index cf5143d5d..1b690eb3b 100644
--- a/core/src/tbox/src/tbox/libc/string/wcslen.c
+++ b/core/src/tbox/src/tbox/libc/string/wcslen.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcslen.c
diff --git a/core/src/tbox/src/tbox/libc/string/wcsncat.c b/core/src/tbox/src/tbox/libc/string/wcsncat.c
index 73950a3b5..900df122a 100644
--- a/core/src/tbox/src/tbox/libc/string/wcsncat.c
+++ b/core/src/tbox/src/tbox/libc/string/wcsncat.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcsncat.c
diff --git a/core/src/tbox/src/tbox/libc/string/wcsncmp.c b/core/src/tbox/src/tbox/libc/string/wcsncmp.c
index 18619992a..9143f6ccb 100644
--- a/core/src/tbox/src/tbox/libc/string/wcsncmp.c
+++ b/core/src/tbox/src/tbox/libc/string/wcsncmp.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcsncmp.c
diff --git a/core/src/tbox/src/tbox/libc/string/wcsncpy.c b/core/src/tbox/src/tbox/libc/string/wcsncpy.c
index 8c6abf62f..e56074c9a 100644
--- a/core/src/tbox/src/tbox/libc/string/wcsncpy.c
+++ b/core/src/tbox/src/tbox/libc/string/wcsncpy.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcsncpy.c
diff --git a/core/src/tbox/src/tbox/libc/string/wcsndup.c b/core/src/tbox/src/tbox/libc/string/wcsndup.c
index 1259166f3..88272f908 100644
--- a/core/src/tbox/src/tbox/libc/string/wcsndup.c
+++ b/core/src/tbox/src/tbox/libc/string/wcsndup.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcsndup.c
diff --git a/core/src/tbox/src/tbox/libc/string/wcsnicmp.c b/core/src/tbox/src/tbox/libc/string/wcsnicmp.c
index e9a0365db..aeb929dbe 100644
--- a/core/src/tbox/src/tbox/libc/string/wcsnicmp.c
+++ b/core/src/tbox/src/tbox/libc/string/wcsnicmp.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcsnicmp.c
diff --git a/core/src/tbox/src/tbox/libc/string/wcsnirchr.c b/core/src/tbox/src/tbox/libc/string/wcsnirchr.c
index dbc47e6a9..52c5f333c 100644
--- a/core/src/tbox/src/tbox/libc/string/wcsnirchr.c
+++ b/core/src/tbox/src/tbox/libc/string/wcsnirchr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcsnirchr.c
diff --git a/core/src/tbox/src/tbox/libc/string/wcsnirstr.c b/core/src/tbox/src/tbox/libc/string/wcsnirstr.c
index 605b0ad3f..4124d760d 100644
--- a/core/src/tbox/src/tbox/libc/string/wcsnirstr.c
+++ b/core/src/tbox/src/tbox/libc/string/wcsnirstr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcsnirstr.c
diff --git a/core/src/tbox/src/tbox/libc/string/wcsnlen.c b/core/src/tbox/src/tbox/libc/string/wcsnlen.c
index 345df86a2..accab1a5f 100644
--- a/core/src/tbox/src/tbox/libc/string/wcsnlen.c
+++ b/core/src/tbox/src/tbox/libc/string/wcsnlen.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcsnlen.c
diff --git a/core/src/tbox/src/tbox/libc/string/wcsnrchr.c b/core/src/tbox/src/tbox/libc/string/wcsnrchr.c
index f1d686063..6834b853c 100644
--- a/core/src/tbox/src/tbox/libc/string/wcsnrchr.c
+++ b/core/src/tbox/src/tbox/libc/string/wcsnrchr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcsnrchr.c
diff --git a/core/src/tbox/src/tbox/libc/string/wcsnrstr.c b/core/src/tbox/src/tbox/libc/string/wcsnrstr.c
index 0682eec74..a26b1ac00 100644
--- a/core/src/tbox/src/tbox/libc/string/wcsnrstr.c
+++ b/core/src/tbox/src/tbox/libc/string/wcsnrstr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcsnrstr.c
diff --git a/core/src/tbox/src/tbox/libc/string/wcsrchr.c b/core/src/tbox/src/tbox/libc/string/wcsrchr.c
index c7b08db8e..c9f57496b 100644
--- a/core/src/tbox/src/tbox/libc/string/wcsrchr.c
+++ b/core/src/tbox/src/tbox/libc/string/wcsrchr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcsrchr.c
diff --git a/core/src/tbox/src/tbox/libc/string/wcsrstr.c b/core/src/tbox/src/tbox/libc/string/wcsrstr.c
index 2e26f8d5f..a9bf28561 100644
--- a/core/src/tbox/src/tbox/libc/string/wcsrstr.c
+++ b/core/src/tbox/src/tbox/libc/string/wcsrstr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcsrstr.c
diff --git a/core/src/tbox/src/tbox/libc/string/wcsstr.c b/core/src/tbox/src/tbox/libc/string/wcsstr.c
index ae4d87af4..783f7fd8a 100644
--- a/core/src/tbox/src/tbox/libc/string/wcsstr.c
+++ b/core/src/tbox/src/tbox/libc/string/wcsstr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file wcsstr.c
diff --git a/core/src/tbox/src/tbox/libm/acos.c b/core/src/tbox/src/tbox/libm/acos.c
index d2f3516e7..7db77cc35 100644
--- a/core/src/tbox/src/tbox/libm/acos.c
+++ b/core/src/tbox/src/tbox/libm/acos.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file acos.c
diff --git a/core/src/tbox/src/tbox/libm/acosf.c b/core/src/tbox/src/tbox/libm/acosf.c
index 851cd57e2..e17a875b4 100644
--- a/core/src/tbox/src/tbox/libm/acosf.c
+++ b/core/src/tbox/src/tbox/libm/acosf.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file acosf.c
diff --git a/core/src/tbox/src/tbox/libm/asin.c b/core/src/tbox/src/tbox/libm/asin.c
index a5f7453f7..a7b3de7c5 100644
--- a/core/src/tbox/src/tbox/libm/asin.c
+++ b/core/src/tbox/src/tbox/libm/asin.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file asin.c
diff --git a/core/src/tbox/src/tbox/libm/asinf.c b/core/src/tbox/src/tbox/libm/asinf.c
index df5486cd5..7e671d24c 100644
--- a/core/src/tbox/src/tbox/libm/asinf.c
+++ b/core/src/tbox/src/tbox/libm/asinf.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file asinf.c
diff --git a/core/src/tbox/src/tbox/libm/atan.c b/core/src/tbox/src/tbox/libm/atan.c
index 144d2445b..b38722891 100644
--- a/core/src/tbox/src/tbox/libm/atan.c
+++ b/core/src/tbox/src/tbox/libm/atan.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file atan.c
diff --git a/core/src/tbox/src/tbox/libm/atan2.c b/core/src/tbox/src/tbox/libm/atan2.c
index 6ec7d7e9b..d23509161 100644
--- a/core/src/tbox/src/tbox/libm/atan2.c
+++ b/core/src/tbox/src/tbox/libm/atan2.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file atan2.c
diff --git a/core/src/tbox/src/tbox/libm/atan2f.c b/core/src/tbox/src/tbox/libm/atan2f.c
index 6e5d4db74..a22e7f339 100644
--- a/core/src/tbox/src/tbox/libm/atan2f.c
+++ b/core/src/tbox/src/tbox/libm/atan2f.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file atan2f.c
diff --git a/core/src/tbox/src/tbox/libm/atanf.c b/core/src/tbox/src/tbox/libm/atanf.c
index 4b48beb60..15f1ca479 100644
--- a/core/src/tbox/src/tbox/libm/atanf.c
+++ b/core/src/tbox/src/tbox/libm/atanf.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file atanf.c
diff --git a/core/src/tbox/src/tbox/libm/ceil.h b/core/src/tbox/src/tbox/libm/ceil.h
index 50470c26b..ec01e46d2 100644
--- a/core/src/tbox/src/tbox/libm/ceil.h
+++ b/core/src/tbox/src/tbox/libm/ceil.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ceil.h
diff --git a/core/src/tbox/src/tbox/libm/cos.c b/core/src/tbox/src/tbox/libm/cos.c
index 3fffaae54..7304a8f8f 100644
--- a/core/src/tbox/src/tbox/libm/cos.c
+++ b/core/src/tbox/src/tbox/libm/cos.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file cos.c
diff --git a/core/src/tbox/src/tbox/libm/cosf.c b/core/src/tbox/src/tbox/libm/cosf.c
index fcc2b8e77..3c881165e 100644
--- a/core/src/tbox/src/tbox/libm/cosf.c
+++ b/core/src/tbox/src/tbox/libm/cosf.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file cosf.c
diff --git a/core/src/tbox/src/tbox/libm/exp.c b/core/src/tbox/src/tbox/libm/exp.c
index feda6e469..3b99a32bf 100644
--- a/core/src/tbox/src/tbox/libm/exp.c
+++ b/core/src/tbox/src/tbox/libm/exp.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file exp.c
diff --git a/core/src/tbox/src/tbox/libm/exp1.c b/core/src/tbox/src/tbox/libm/exp1.c
index 0e0863349..5ad6ae991 100644
--- a/core/src/tbox/src/tbox/libm/exp1.c
+++ b/core/src/tbox/src/tbox/libm/exp1.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file exp1.c
diff --git a/core/src/tbox/src/tbox/libm/exp1f.c b/core/src/tbox/src/tbox/libm/exp1f.c
index 4bbdeb9b7..803b2ab89 100644
--- a/core/src/tbox/src/tbox/libm/exp1f.c
+++ b/core/src/tbox/src/tbox/libm/exp1f.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file exp1f.c
diff --git a/core/src/tbox/src/tbox/libm/expf.c b/core/src/tbox/src/tbox/libm/expf.c
index 11c091dc0..ab5b67a18 100644
--- a/core/src/tbox/src/tbox/libm/expf.c
+++ b/core/src/tbox/src/tbox/libm/expf.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file expf.c
diff --git a/core/src/tbox/src/tbox/libm/expi.c b/core/src/tbox/src/tbox/libm/expi.c
index a21389ce5..48dcccd0b 100644
--- a/core/src/tbox/src/tbox/libm/expi.c
+++ b/core/src/tbox/src/tbox/libm/expi.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file expi.c
diff --git a/core/src/tbox/src/tbox/libm/expif.c b/core/src/tbox/src/tbox/libm/expif.c
index 4b45028a1..13f14a65c 100644
--- a/core/src/tbox/src/tbox/libm/expif.c
+++ b/core/src/tbox/src/tbox/libm/expif.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file expif.c
diff --git a/core/src/tbox/src/tbox/libm/fabs.h b/core/src/tbox/src/tbox/libm/fabs.h
index c7549ee2a..17fe56de2 100644
--- a/core/src/tbox/src/tbox/libm/fabs.h
+++ b/core/src/tbox/src/tbox/libm/fabs.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file fabs.h
diff --git a/core/src/tbox/src/tbox/libm/floor.h b/core/src/tbox/src/tbox/libm/floor.h
index e04b09a81..63bae06af 100644
--- a/core/src/tbox/src/tbox/libm/floor.h
+++ b/core/src/tbox/src/tbox/libm/floor.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file floor.h
diff --git a/core/src/tbox/src/tbox/libm/fmod.c b/core/src/tbox/src/tbox/libm/fmod.c
index 588ed63d9..b8f2d3c52 100644
--- a/core/src/tbox/src/tbox/libm/fmod.c
+++ b/core/src/tbox/src/tbox/libm/fmod.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file fmod.c
diff --git a/core/src/tbox/src/tbox/libm/fmodf.c b/core/src/tbox/src/tbox/libm/fmodf.c
index 39bbab593..641ca98c2 100644
--- a/core/src/tbox/src/tbox/libm/fmodf.c
+++ b/core/src/tbox/src/tbox/libm/fmodf.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file fmodf.c
diff --git a/core/src/tbox/src/tbox/libm/idivi8.c b/core/src/tbox/src/tbox/libm/idivi8.c
index 704ec9742..14dca6d99 100644
--- a/core/src/tbox/src/tbox/libm/idivi8.c
+++ b/core/src/tbox/src/tbox/libm/idivi8.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file idivi8.c
diff --git a/core/src/tbox/src/tbox/libm/ilog2i.c b/core/src/tbox/src/tbox/libm/ilog2i.c
index 0ff7243d4..14e9dcadc 100644
--- a/core/src/tbox/src/tbox/libm/ilog2i.c
+++ b/core/src/tbox/src/tbox/libm/ilog2i.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ilog2i.c
diff --git a/core/src/tbox/src/tbox/libm/impl/impl.h b/core/src/tbox/src/tbox/libm/impl/impl.h
index 0dd641a01..caf87103f 100644
--- a/core/src/tbox/src/tbox/libm/impl/impl.h
+++ b/core/src/tbox/src/tbox/libm/impl/impl.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file libm.h
diff --git a/core/src/tbox/src/tbox/libm/impl/libm.c b/core/src/tbox/src/tbox/libm/impl/libm.c
index 76c0cc072..b4a1822d4 100644
--- a/core/src/tbox/src/tbox/libm/impl/libm.c
+++ b/core/src/tbox/src/tbox/libm/impl/libm.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file libm.c
diff --git a/core/src/tbox/src/tbox/libm/impl/libm.h b/core/src/tbox/src/tbox/libm/impl/libm.h
index 09b1ee924..d6013576c 100644
--- a/core/src/tbox/src/tbox/libm/impl/libm.h
+++ b/core/src/tbox/src/tbox/libm/impl/libm.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file libm.h
diff --git a/core/src/tbox/src/tbox/libm/impl/prefix.h b/core/src/tbox/src/tbox/libm/impl/prefix.h
index 6281e53c2..69cd8df69 100644
--- a/core/src/tbox/src/tbox/libm/impl/prefix.h
+++ b/core/src/tbox/src/tbox/libm/impl/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/libm/inf.h b/core/src/tbox/src/tbox/libm/inf.h
index 7d4ee644c..911192b97 100644
--- a/core/src/tbox/src/tbox/libm/inf.h
+++ b/core/src/tbox/src/tbox/libm/inf.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file inf.h
diff --git a/core/src/tbox/src/tbox/libm/isfin.c b/core/src/tbox/src/tbox/libm/isfin.c
index cfc9735c6..cc5175b10 100644
--- a/core/src/tbox/src/tbox/libm/isfin.c
+++ b/core/src/tbox/src/tbox/libm/isfin.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file isfin.c
diff --git a/core/src/tbox/src/tbox/libm/isfinf.c b/core/src/tbox/src/tbox/libm/isfinf.c
index 3863afe07..6495b7aaa 100644
--- a/core/src/tbox/src/tbox/libm/isfinf.c
+++ b/core/src/tbox/src/tbox/libm/isfinf.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file isfinf.c
diff --git a/core/src/tbox/src/tbox/libm/isinf.c b/core/src/tbox/src/tbox/libm/isinf.c
index 2527f49d5..587230d7b 100644
--- a/core/src/tbox/src/tbox/libm/isinf.c
+++ b/core/src/tbox/src/tbox/libm/isinf.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file isinf.c
diff --git a/core/src/tbox/src/tbox/libm/isinff.c b/core/src/tbox/src/tbox/libm/isinff.c
index 21aaf4833..ea7a42094 100644
--- a/core/src/tbox/src/tbox/libm/isinff.c
+++ b/core/src/tbox/src/tbox/libm/isinff.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file isinff.c
diff --git a/core/src/tbox/src/tbox/libm/isnan.c b/core/src/tbox/src/tbox/libm/isnan.c
index 646bf91e6..3879145b8 100644
--- a/core/src/tbox/src/tbox/libm/isnan.c
+++ b/core/src/tbox/src/tbox/libm/isnan.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file isnan.c
diff --git a/core/src/tbox/src/tbox/libm/isnanf.c b/core/src/tbox/src/tbox/libm/isnanf.c
index 720c0afcc..7bf6771e5 100644
--- a/core/src/tbox/src/tbox/libm/isnanf.c
+++ b/core/src/tbox/src/tbox/libm/isnanf.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file isnanf.c
diff --git a/core/src/tbox/src/tbox/libm/isqrti.c b/core/src/tbox/src/tbox/libm/isqrti.c
index 16dabad00..f488b6786 100644
--- a/core/src/tbox/src/tbox/libm/isqrti.c
+++ b/core/src/tbox/src/tbox/libm/isqrti.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file isqrti.c
diff --git a/core/src/tbox/src/tbox/libm/isqrti64.c b/core/src/tbox/src/tbox/libm/isqrti64.c
index d1c8df55c..f8d6f5f4e 100644
--- a/core/src/tbox/src/tbox/libm/isqrti64.c
+++ b/core/src/tbox/src/tbox/libm/isqrti64.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file isqrti.c
diff --git a/core/src/tbox/src/tbox/libm/libm.h b/core/src/tbox/src/tbox/libm/libm.h
index 7d8d89b44..38bcac104 100644
--- a/core/src/tbox/src/tbox/libm/libm.h
+++ b/core/src/tbox/src/tbox/libm/libm.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file libm.h
diff --git a/core/src/tbox/src/tbox/libm/log2.c b/core/src/tbox/src/tbox/libm/log2.c
index ef7a35372..4c95be8e3 100644
--- a/core/src/tbox/src/tbox/libm/log2.c
+++ b/core/src/tbox/src/tbox/libm/log2.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file log2f.c
diff --git a/core/src/tbox/src/tbox/libm/log2f.c b/core/src/tbox/src/tbox/libm/log2f.c
index cefc25a14..89102f15b 100644
--- a/core/src/tbox/src/tbox/libm/log2f.c
+++ b/core/src/tbox/src/tbox/libm/log2f.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file log2f.c
diff --git a/core/src/tbox/src/tbox/libm/maf.h b/core/src/tbox/src/tbox/libm/maf.h
index 8c96d150c..1a8eafa0f 100644
--- a/core/src/tbox/src/tbox/libm/maf.h
+++ b/core/src/tbox/src/tbox/libm/maf.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file maf.h
diff --git a/core/src/tbox/src/tbox/libm/math.h b/core/src/tbox/src/tbox/libm/math.h
index 99ef382ca..e753a4288 100644
--- a/core/src/tbox/src/tbox/libm/math.h
+++ b/core/src/tbox/src/tbox/libm/math.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file math.h
diff --git a/core/src/tbox/src/tbox/libm/mif.h b/core/src/tbox/src/tbox/libm/mif.h
index 926904a20..1aa374bc3 100644
--- a/core/src/tbox/src/tbox/libm/mif.h
+++ b/core/src/tbox/src/tbox/libm/mif.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file mif.h
diff --git a/core/src/tbox/src/tbox/libm/nan.h b/core/src/tbox/src/tbox/libm/nan.h
index 05d8dafbc..b07d4ad8f 100644
--- a/core/src/tbox/src/tbox/libm/nan.h
+++ b/core/src/tbox/src/tbox/libm/nan.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file nan.h
diff --git a/core/src/tbox/src/tbox/libm/pi.h b/core/src/tbox/src/tbox/libm/pi.h
index b415d6fcc..de9799466 100644
--- a/core/src/tbox/src/tbox/libm/pi.h
+++ b/core/src/tbox/src/tbox/libm/pi.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file pi.h
diff --git a/core/src/tbox/src/tbox/libm/pow.c b/core/src/tbox/src/tbox/libm/pow.c
index 0e4c42a50..ab3e4b26d 100644
--- a/core/src/tbox/src/tbox/libm/pow.c
+++ b/core/src/tbox/src/tbox/libm/pow.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file pow.c
diff --git a/core/src/tbox/src/tbox/libm/powf.c b/core/src/tbox/src/tbox/libm/powf.c
index a39ce04e8..4298c3f14 100644
--- a/core/src/tbox/src/tbox/libm/powf.c
+++ b/core/src/tbox/src/tbox/libm/powf.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file powf.c
diff --git a/core/src/tbox/src/tbox/libm/prefix.h b/core/src/tbox/src/tbox/libm/prefix.h
index 0d4b654b7..ccf603062 100644
--- a/core/src/tbox/src/tbox/libm/prefix.h
+++ b/core/src/tbox/src/tbox/libm/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/libm/round.h b/core/src/tbox/src/tbox/libm/round.h
index 509c836ed..f42cd91a9 100644
--- a/core/src/tbox/src/tbox/libm/round.h
+++ b/core/src/tbox/src/tbox/libm/round.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file round.h
diff --git a/core/src/tbox/src/tbox/libm/sin.c b/core/src/tbox/src/tbox/libm/sin.c
index 3d6248088..774b6507f 100644
--- a/core/src/tbox/src/tbox/libm/sin.c
+++ b/core/src/tbox/src/tbox/libm/sin.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file sin.c
diff --git a/core/src/tbox/src/tbox/libm/sincos.c b/core/src/tbox/src/tbox/libm/sincos.c
index 73e2b6799..6415b11dc 100644
--- a/core/src/tbox/src/tbox/libm/sincos.c
+++ b/core/src/tbox/src/tbox/libm/sincos.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file sincos.c
diff --git a/core/src/tbox/src/tbox/libm/sincosf.c b/core/src/tbox/src/tbox/libm/sincosf.c
index d71c74671..ff8d7ffe9 100644
--- a/core/src/tbox/src/tbox/libm/sincosf.c
+++ b/core/src/tbox/src/tbox/libm/sincosf.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file sincosf.c
diff --git a/core/src/tbox/src/tbox/libm/sinf.c b/core/src/tbox/src/tbox/libm/sinf.c
index 9e4a67df8..5e89f6f99 100644
--- a/core/src/tbox/src/tbox/libm/sinf.c
+++ b/core/src/tbox/src/tbox/libm/sinf.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file sinf.c
diff --git a/core/src/tbox/src/tbox/libm/sqrt.c b/core/src/tbox/src/tbox/libm/sqrt.c
index 2f91baaa6..bb5d95216 100644
--- a/core/src/tbox/src/tbox/libm/sqrt.c
+++ b/core/src/tbox/src/tbox/libm/sqrt.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file sqrt.c
diff --git a/core/src/tbox/src/tbox/libm/sqrtf.c b/core/src/tbox/src/tbox/libm/sqrtf.c
index 508f96d7c..592d98bbf 100644
--- a/core/src/tbox/src/tbox/libm/sqrtf.c
+++ b/core/src/tbox/src/tbox/libm/sqrtf.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file sqrtf.c
diff --git a/core/src/tbox/src/tbox/libm/tan.c b/core/src/tbox/src/tbox/libm/tan.c
index 94e6c44d4..25628fd1e 100644
--- a/core/src/tbox/src/tbox/libm/tan.c
+++ b/core/src/tbox/src/tbox/libm/tan.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file tan.c
diff --git a/core/src/tbox/src/tbox/libm/tanf.c b/core/src/tbox/src/tbox/libm/tanf.c
index ec1d5c9c1..2ad06dac9 100644
--- a/core/src/tbox/src/tbox/libm/tanf.c
+++ b/core/src/tbox/src/tbox/libm/tanf.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file tanf.c
diff --git a/core/src/tbox/src/tbox/math/fixed.h b/core/src/tbox/src/tbox/math/fixed.h
index e3239e070..345c5f869 100644
--- a/core/src/tbox/src/tbox/math/fixed.h
+++ b/core/src/tbox/src/tbox/math/fixed.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file fixed.h
diff --git a/core/src/tbox/src/tbox/math/fixed16.c b/core/src/tbox/src/tbox/math/fixed16.c
index de36162b4..0637b4873 100644
--- a/core/src/tbox/src/tbox/math/fixed16.c
+++ b/core/src/tbox/src/tbox/math/fixed16.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file fixed16.c
diff --git a/core/src/tbox/src/tbox/math/fixed16.h b/core/src/tbox/src/tbox/math/fixed16.h
index be772f9ac..c51b59543 100644
--- a/core/src/tbox/src/tbox/math/fixed16.h
+++ b/core/src/tbox/src/tbox/math/fixed16.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file fixed16.h
diff --git a/core/src/tbox/src/tbox/math/fixed30.h b/core/src/tbox/src/tbox/math/fixed30.h
index 67bbd13a4..ecab8d96d 100644
--- a/core/src/tbox/src/tbox/math/fixed30.h
+++ b/core/src/tbox/src/tbox/math/fixed30.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file fixed30.h
diff --git a/core/src/tbox/src/tbox/math/fixed6.h b/core/src/tbox/src/tbox/math/fixed6.h
index 25e6386b6..567923c16 100644
--- a/core/src/tbox/src/tbox/math/fixed6.h
+++ b/core/src/tbox/src/tbox/math/fixed6.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file fixed6.h
diff --git a/core/src/tbox/src/tbox/math/impl/fixed16_arm.h b/core/src/tbox/src/tbox/math/impl/fixed16_arm.h
index 5c559606e..8568f3aa9 100644
--- a/core/src/tbox/src/tbox/math/impl/fixed16_arm.h
+++ b/core/src/tbox/src/tbox/math/impl/fixed16_arm.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file fixed16_arm.h
diff --git a/core/src/tbox/src/tbox/math/impl/fixed30_arm.h b/core/src/tbox/src/tbox/math/impl/fixed30_arm.h
index 1d756c220..7d9ba73ca 100644
--- a/core/src/tbox/src/tbox/math/impl/fixed30_arm.h
+++ b/core/src/tbox/src/tbox/math/impl/fixed30_arm.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file fixed30_arm.h
diff --git a/core/src/tbox/src/tbox/math/impl/impl.h b/core/src/tbox/src/tbox/math/impl/impl.h
index 771022e32..7e4107c36 100644
--- a/core/src/tbox/src/tbox/math/impl/impl.h
+++ b/core/src/tbox/src/tbox/math/impl/impl.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file impl.h
diff --git a/core/src/tbox/src/tbox/math/impl/math.c b/core/src/tbox/src/tbox/math/impl/math.c
index b2f0b7c9d..a1e91faed 100644
--- a/core/src/tbox/src/tbox/math/impl/math.c
+++ b/core/src/tbox/src/tbox/math/impl/math.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file math.c
diff --git a/core/src/tbox/src/tbox/math/impl/math.h b/core/src/tbox/src/tbox/math/impl/math.h
index 6dfcba93e..098b2c3d2 100644
--- a/core/src/tbox/src/tbox/math/impl/math.h
+++ b/core/src/tbox/src/tbox/math/impl/math.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file math.h
diff --git a/core/src/tbox/src/tbox/math/impl/prefix.h b/core/src/tbox/src/tbox/math/impl/prefix.h
index ac06401aa..7350b9484 100644
--- a/core/src/tbox/src/tbox/math/impl/prefix.h
+++ b/core/src/tbox/src/tbox/math/impl/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/math/int32.c b/core/src/tbox/src/tbox/math/int32.c
index a5eafb0ef..b1eb634f8 100644
--- a/core/src/tbox/src/tbox/math/int32.c
+++ b/core/src/tbox/src/tbox/math/int32.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file int32.c
diff --git a/core/src/tbox/src/tbox/math/int32.h b/core/src/tbox/src/tbox/math/int32.h
index ec0468187..8e102dda0 100644
--- a/core/src/tbox/src/tbox/math/int32.h
+++ b/core/src/tbox/src/tbox/math/int32.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file int32.h
diff --git a/core/src/tbox/src/tbox/math/math.h b/core/src/tbox/src/tbox/math/math.h
index 53d0c1084..1e197ab15 100644
--- a/core/src/tbox/src/tbox/math/math.h
+++ b/core/src/tbox/src/tbox/math/math.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file math.h
diff --git a/core/src/tbox/src/tbox/math/prefix.h b/core/src/tbox/src/tbox/math/prefix.h
index 4dcf53d7f..c56932fa7 100644
--- a/core/src/tbox/src/tbox/math/prefix.h
+++ b/core/src/tbox/src/tbox/math/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/math/random/linear.c b/core/src/tbox/src/tbox/math/random/linear.c
index 2dc60b15b..6fd323544 100644
--- a/core/src/tbox/src/tbox/math/random/linear.c
+++ b/core/src/tbox/src/tbox/math/random/linear.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file linear.c
diff --git a/core/src/tbox/src/tbox/math/random/linear.h b/core/src/tbox/src/tbox/math/random/linear.h
index fbbd67348..be059c3dc 100644
--- a/core/src/tbox/src/tbox/math/random/linear.h
+++ b/core/src/tbox/src/tbox/math/random/linear.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file linear.h
diff --git a/core/src/tbox/src/tbox/math/random/prefix.h b/core/src/tbox/src/tbox/math/random/prefix.h
index c6ed41ff5..29b099648 100644
--- a/core/src/tbox/src/tbox/math/random/prefix.h
+++ b/core/src/tbox/src/tbox/math/random/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/math/random/random.c b/core/src/tbox/src/tbox/math/random/random.c
index 229d48e41..a84725c9d 100644
--- a/core/src/tbox/src/tbox/math/random/random.c
+++ b/core/src/tbox/src/tbox/math/random/random.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file random.c
diff --git a/core/src/tbox/src/tbox/math/random/random.h b/core/src/tbox/src/tbox/math/random/random.h
index 24e407c4e..419a8b9c6 100644
--- a/core/src/tbox/src/tbox/math/random/random.h
+++ b/core/src/tbox/src/tbox/math/random/random.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file random.h
diff --git a/core/src/tbox/src/tbox/memory/allocator.c b/core/src/tbox/src/tbox/memory/allocator.c
index 415ecbeb1..d80a31144 100644
--- a/core/src/tbox/src/tbox/memory/allocator.c
+++ b/core/src/tbox/src/tbox/memory/allocator.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file allocator.c
@@ -56,10 +56,10 @@ tb_allocator_ref_t tb_allocator()
tb_size_t tb_allocator_type(tb_allocator_ref_t allocator)
{
// check
- tb_assert_and_check_return_val(allocator, TB_ALLOCATOR_DEFAULT);
+ tb_assert_and_check_return_val(allocator, TB_ALLOCATOR_TYPE_DEFAULT);
// get it
- return allocator->type;
+ return (tb_size_t)allocator->type;
}
tb_pointer_t tb_allocator_malloc_(tb_allocator_ref_t allocator, tb_size_t size __tb_debug_decl__)
{
@@ -67,7 +67,8 @@ tb_pointer_t tb_allocator_malloc_(tb_allocator_ref_t allocator, tb_size_t size _
tb_assert_and_check_return_val(allocator, tb_null);
// enter
- tb_spinlock_enter(&allocator->lock);
+ 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;
@@ -82,7 +83,7 @@ tb_pointer_t tb_allocator_malloc_(tb_allocator_ref_t allocator, tb_size_t size _
tb_assertf(!(((tb_size_t)data) & (TB_POOL_DATA_ALIGN - 1)), "malloc(%lu): unaligned data: %p", size, data);
// leave
- tb_spinlock_leave(&allocator->lock);
+ if (lockit) tb_spinlock_leave(&allocator->lock);
// ok?
return data;
@@ -129,7 +130,8 @@ tb_pointer_t tb_allocator_ralloc_(tb_allocator_ref_t allocator, tb_pointer_t dat
tb_assert_and_check_return_val(allocator, tb_null);
// enter
- tb_spinlock_enter(&allocator->lock);
+ 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;
@@ -158,7 +160,7 @@ tb_pointer_t tb_allocator_ralloc_(tb_allocator_ref_t allocator, tb_pointer_t dat
tb_assertf(!(((tb_size_t)data_new) & (TB_POOL_DATA_ALIGN - 1)), "ralloc(%lu): unaligned data: %p", size, data);
// leave
- tb_spinlock_leave(&allocator->lock);
+ if (lockit) tb_spinlock_leave(&allocator->lock);
// ok?
return data_new;
@@ -169,7 +171,8 @@ tb_bool_t tb_allocator_free_(tb_allocator_ref_t allocator, tb_pointer_t data __t
tb_assert_and_check_return_val(allocator, tb_false);
// enter
- tb_spinlock_enter(&allocator->lock);
+ 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__);
@@ -195,7 +198,7 @@ tb_bool_t tb_allocator_free_(tb_allocator_ref_t allocator, tb_pointer_t data __t
#endif
// leave
- tb_spinlock_leave(&allocator->lock);
+ if (lockit) tb_spinlock_leave(&allocator->lock);
// ok?
return ok;
@@ -206,7 +209,8 @@ tb_pointer_t tb_allocator_large_malloc_(tb_allocator_ref_t allocator, tb_size_t
tb_assert_and_check_return_val(allocator, tb_null);
// enter
- tb_spinlock_enter(&allocator->lock);
+ 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;
@@ -227,7 +231,7 @@ tb_pointer_t tb_allocator_large_malloc_(tb_allocator_ref_t allocator, tb_size_t
tb_assert(!real || *real >= size);
// leave
- tb_spinlock_leave(&allocator->lock);
+ if (lockit) tb_spinlock_leave(&allocator->lock);
// ok?
return data;
@@ -274,7 +278,8 @@ tb_pointer_t tb_allocator_large_ralloc_(tb_allocator_ref_t allocator, tb_pointer
tb_assert_and_check_return_val(allocator, tb_null);
// enter
- tb_spinlock_enter(&allocator->lock);
+ 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;
@@ -309,7 +314,7 @@ tb_pointer_t tb_allocator_large_ralloc_(tb_allocator_ref_t allocator, tb_pointer
tb_assertf(!(((tb_size_t)data_new) & (TB_POOL_DATA_ALIGN - 1)), "ralloc(%lu): unaligned data: %p", size, data);
// leave
- tb_spinlock_leave(&allocator->lock);
+ if (lockit) tb_spinlock_leave(&allocator->lock);
// ok?
return data_new;
@@ -320,7 +325,8 @@ tb_bool_t tb_allocator_large_free_(tb_allocator_ref_t allocator, tb_pointer_t da
tb_assert_and_check_return_val(allocator, tb_false);
// enter
- tb_spinlock_enter(&allocator->lock);
+ 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__);
@@ -346,7 +352,7 @@ tb_bool_t tb_allocator_large_free_(tb_allocator_ref_t allocator, tb_pointer_t da
#endif
// leave
- tb_spinlock_leave(&allocator->lock);
+ if (lockit) tb_spinlock_leave(&allocator->lock);
// ok?
return ok;
@@ -472,13 +478,14 @@ tb_void_t tb_allocator_clear(tb_allocator_ref_t allocator)
tb_assert_and_check_return(allocator);
// enter
- tb_spinlock_enter(&allocator->lock);
+ 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
- tb_spinlock_leave(&allocator->lock);
+ if (lockit) tb_spinlock_leave(&allocator->lock);
}
tb_void_t tb_allocator_exit(tb_allocator_ref_t allocator)
{
@@ -498,13 +505,14 @@ tb_void_t tb_allocator_dump(tb_allocator_ref_t allocator)
tb_assert_and_check_return(allocator);
// enter
- tb_spinlock_enter(&allocator->lock);
+ 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
- tb_spinlock_leave(&allocator->lock);
+ if (lockit) tb_spinlock_leave(&allocator->lock);
}
tb_bool_t tb_allocator_have(tb_allocator_ref_t allocator, tb_cpointer_t data)
{
diff --git a/core/src/tbox/src/tbox/memory/allocator.h b/core/src/tbox/src/tbox/memory/allocator.h
index cef68a383..a8b433740 100644
--- a/core/src/tbox/src/tbox/memory/allocator.h
+++ b/core/src/tbox/src/tbox/memory/allocator.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file allocator.h
@@ -74,20 +74,31 @@ __tb_extern_c_enter__
/// the allocator type enum
typedef enum __tb_allocator_type_e
{
- TB_ALLOCATOR_NONE = 0
-, TB_ALLOCATOR_DEFAULT = 1
-, TB_ALLOCATOR_NATIVE = 2
-, TB_ALLOCATOR_STATIC = 4
-, TB_ALLOCATOR_LARGE = 5
-, TB_ALLOCATOR_SMALL = 6
+ TB_ALLOCATOR_TYPE_NONE = 0
+, TB_ALLOCATOR_TYPE_DEFAULT = 1
+, TB_ALLOCATOR_TYPE_NATIVE = 2
+, 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_size_t type;
+ tb_uint32_t type : 16;
+
+ /// the flag
+ tb_uint32_t flag : 16;
/// the lock
tb_spinlock_t lock;
diff --git a/core/src/tbox/src/tbox/memory/buffer.c b/core/src/tbox/src/tbox/memory/buffer.c
index be8ab42c7..10708dba4 100644
--- a/core/src/tbox/src/tbox/memory/buffer.c
+++ b/core/src/tbox/src/tbox/memory/buffer.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file buffer.c
diff --git a/core/src/tbox/src/tbox/memory/buffer.h b/core/src/tbox/src/tbox/memory/buffer.h
index 2a7389bac..ca478b849 100644
--- a/core/src/tbox/src/tbox/memory/buffer.h
+++ b/core/src/tbox/src/tbox/memory/buffer.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file buffer.h
diff --git a/core/src/tbox/src/tbox/memory/default_allocator.c b/core/src/tbox/src/tbox/memory/default_allocator.c
index 5828434ee..556e14f32 100644
--- a/core/src/tbox/src/tbox/memory/default_allocator.c
+++ b/core/src/tbox/src/tbox/memory/default_allocator.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file default_allocator.c
@@ -320,7 +320,8 @@ tb_allocator_ref_t tb_default_allocator_init(tb_allocator_ref_t large_allocator)
tb_assert_and_check_break(allocator);
// init base
- allocator->base.type = TB_ALLOCATOR_DEFAULT;
+ 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;
diff --git a/core/src/tbox/src/tbox/memory/default_allocator.h b/core/src/tbox/src/tbox/memory/default_allocator.h
index 445ce2335..2b14e8ea2 100644
--- a/core/src/tbox/src/tbox/memory/default_allocator.h
+++ b/core/src/tbox/src/tbox/memory/default_allocator.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file default_allocator.h
diff --git a/core/src/tbox/src/tbox/memory/fixed_pool.c b/core/src/tbox/src/tbox/memory/fixed_pool.c
index 25d164994..d89f51535 100644
--- a/core/src/tbox/src/tbox/memory/fixed_pool.c
+++ b/core/src/tbox/src/tbox/memory/fixed_pool.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file fixed_pool.c
@@ -139,7 +139,7 @@ static tb_void_t tb_fixed_pool_slot_exit(tb_fixed_pool_t* pool, tb_fixed_pool_sl
// make the iterator
tb_array_iterator_t array_iterator;
- tb_iterator_ref_t iterator = tb_iterator_make_for_ptr(&array_iterator, (tb_pointer_t*)pool->slot_list, pool->slot_count);
+ 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
@@ -314,7 +314,7 @@ static tb_fixed_pool_slot_t* tb_fixed_pool_slot_find(tb_fixed_pool_t* pool, tb_p
// make the iterator
tb_array_iterator_t array_iterator;
- tb_iterator_ref_t iterator = tb_iterator_make_for_ptr(&array_iterator, (tb_pointer_t*)pool->slot_list, pool->slot_count);
+ 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
diff --git a/core/src/tbox/src/tbox/memory/fixed_pool.h b/core/src/tbox/src/tbox/memory/fixed_pool.h
index 4458596b7..fb04a463f 100644
--- a/core/src/tbox/src/tbox/memory/fixed_pool.h
+++ b/core/src/tbox/src/tbox/memory/fixed_pool.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file fixed_pool.h
diff --git a/core/src/tbox/src/tbox/memory/impl/impl.h b/core/src/tbox/src/tbox/memory/impl/impl.h
index 1cfba53b4..750dbe4e0 100644
--- a/core/src/tbox/src/tbox/memory/impl/impl.h
+++ b/core/src/tbox/src/tbox/memory/impl/impl.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file impl.h
diff --git a/core/src/tbox/src/tbox/memory/impl/memory.c b/core/src/tbox/src/tbox/memory/impl/memory.c
index f313f3312..d859fb729 100644
--- a/core/src/tbox/src/tbox/memory/impl/memory.c
+++ b/core/src/tbox/src/tbox/memory/impl/memory.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file memory.c
diff --git a/core/src/tbox/src/tbox/memory/impl/memory.h b/core/src/tbox/src/tbox/memory/impl/memory.h
index b91b0c90a..61482fb0b 100644
--- a/core/src/tbox/src/tbox/memory/impl/memory.h
+++ b/core/src/tbox/src/tbox/memory/impl/memory.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file memory.h
diff --git a/core/src/tbox/src/tbox/memory/impl/native_large_allocator.c b/core/src/tbox/src/tbox/memory/impl/native_large_allocator.c
index bbd505aa6..a8e23ecb8 100644
--- a/core/src/tbox/src/tbox/memory/impl/native_large_allocator.c
+++ b/core/src/tbox/src/tbox/memory/impl/native_large_allocator.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file native_large_allocator.c
@@ -606,7 +606,8 @@ tb_allocator_ref_t tb_native_large_allocator_init()
tb_assert_and_check_break(allocator);
// init base
- allocator->base.type = TB_ALLOCATOR_LARGE;
+ 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;
diff --git a/core/src/tbox/src/tbox/memory/impl/native_large_allocator.h b/core/src/tbox/src/tbox/memory/impl/native_large_allocator.h
index 030d5b76b..2f67f6805 100644
--- a/core/src/tbox/src/tbox/memory/impl/native_large_allocator.h
+++ b/core/src/tbox/src/tbox/memory/impl/native_large_allocator.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file native_large_allocator.h
diff --git a/core/src/tbox/src/tbox/memory/impl/prefix.c b/core/src/tbox/src/tbox/memory/impl/prefix.c
index 05a0e2d9c..549ad6b18 100644
--- a/core/src/tbox/src/tbox/memory/impl/prefix.c
+++ b/core/src/tbox/src/tbox/memory/impl/prefix.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.c
diff --git a/core/src/tbox/src/tbox/memory/impl/prefix.h b/core/src/tbox/src/tbox/memory/impl/prefix.h
index bbd79ca45..cfc4dbd8f 100644
--- a/core/src/tbox/src/tbox/memory/impl/prefix.h
+++ b/core/src/tbox/src/tbox/memory/impl/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
@@ -39,6 +39,11 @@
#include "../../algorithm/algorithm.h"
/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_enter__
+
+/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
@@ -148,5 +153,9 @@ tb_void_t tb_pool_data_save_backtrace(tb_pool_data_debug_h
#endif
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_leave__
#endif
diff --git a/core/src/tbox/src/tbox/memory/impl/static_fixed_pool.c b/core/src/tbox/src/tbox/memory/impl/static_fixed_pool.c
index 9248339c7..a75b95421 100644
--- a/core/src/tbox/src/tbox/memory/impl/static_fixed_pool.c
+++ b/core/src/tbox/src/tbox/memory/impl/static_fixed_pool.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file static_fixed_pool.c
diff --git a/core/src/tbox/src/tbox/memory/impl/static_fixed_pool.h b/core/src/tbox/src/tbox/memory/impl/static_fixed_pool.h
index ca8bd9df5..335546352 100644
--- a/core/src/tbox/src/tbox/memory/impl/static_fixed_pool.h
+++ b/core/src/tbox/src/tbox/memory/impl/static_fixed_pool.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file static_fixed_pool.h
diff --git a/core/src/tbox/src/tbox/memory/impl/static_large_allocator.c b/core/src/tbox/src/tbox/memory/impl/static_large_allocator.c
index bbbf3eea8..3e84de935 100644
--- a/core/src/tbox/src/tbox/memory/impl/static_large_allocator.c
+++ b/core/src/tbox/src/tbox/memory/impl/static_large_allocator.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file static_large_allocator.c
@@ -53,6 +53,14 @@ typedef __tb_pool_data_aligned__ struct __tb_static_large_data_head_t
// 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)];
@@ -461,7 +469,7 @@ static tb_static_large_data_head_t* tb_static_large_allocator_malloc_done(tb_sta
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_DEFAULT)? 6 : 3;
+ 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);
@@ -583,7 +591,7 @@ static tb_static_large_data_head_t* tb_static_large_allocator_ralloc_fast(tb_sta
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_DEFAULT)? 6 : 3;
+ 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);
@@ -913,7 +921,8 @@ tb_allocator_ref_t tb_static_large_allocator_init(tb_byte_t* data, tb_size_t siz
tb_memset_(allocator, 0, sizeof(tb_static_large_allocator_t));
// init base
- allocator->base.type = TB_ALLOCATOR_LARGE;
+ 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;
diff --git a/core/src/tbox/src/tbox/memory/impl/static_large_allocator.h b/core/src/tbox/src/tbox/memory/impl/static_large_allocator.h
index 5594ef1ac..c576e82b2 100644
--- a/core/src/tbox/src/tbox/memory/impl/static_large_allocator.h
+++ b/core/src/tbox/src/tbox/memory/impl/static_large_allocator.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file static_large_allocator.h
diff --git a/core/src/tbox/src/tbox/memory/large_allocator.c b/core/src/tbox/src/tbox/memory/large_allocator.c
index 60eba1795..91f0f5e28 100644
--- a/core/src/tbox/src/tbox/memory/large_allocator.c
+++ b/core/src/tbox/src/tbox/memory/large_allocator.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file large_allocator.c
diff --git a/core/src/tbox/src/tbox/memory/large_allocator.h b/core/src/tbox/src/tbox/memory/large_allocator.h
index 877199fc1..a8be11400 100644
--- a/core/src/tbox/src/tbox/memory/large_allocator.h
+++ b/core/src/tbox/src/tbox/memory/large_allocator.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file large_allocator.h
diff --git a/core/src/tbox/src/tbox/memory/memory.h b/core/src/tbox/src/tbox/memory/memory.h
index 9fb592eff..2cf5be91f 100644
--- a/core/src/tbox/src/tbox/memory/memory.h
+++ b/core/src/tbox/src/tbox/memory/memory.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file memory.h
diff --git a/core/src/tbox/src/tbox/memory/native_allocator.c b/core/src/tbox/src/tbox/memory/native_allocator.c
index 1ce2b8fbf..a79dd830a 100644
--- a/core/src/tbox/src/tbox/memory/native_allocator.c
+++ b/core/src/tbox/src/tbox/memory/native_allocator.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file native_allocator.c
@@ -76,7 +76,8 @@ static tb_bool_t tb_native_allocator_instance_init(tb_handle_t instance, tb_cpoi
if (!tb_native_memory_init()) return tb_false;
// init allocator
- allocator->type = TB_ALLOCATOR_NATIVE;
+ 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;
diff --git a/core/src/tbox/src/tbox/memory/native_allocator.h b/core/src/tbox/src/tbox/memory/native_allocator.h
index e4989bfb5..5425ea66f 100644
--- a/core/src/tbox/src/tbox/memory/native_allocator.h
+++ b/core/src/tbox/src/tbox/memory/native_allocator.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file native_allocator.h
diff --git a/core/src/tbox/src/tbox/memory/prefix.h b/core/src/tbox/src/tbox/memory/prefix.h
index ddf458fff..58feff23c 100644
--- a/core/src/tbox/src/tbox/memory/prefix.h
+++ b/core/src/tbox/src/tbox/memory/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/memory/queue_buffer.c b/core/src/tbox/src/tbox/memory/queue_buffer.c
index aef52cc3d..7e7d7d668 100644
--- a/core/src/tbox/src/tbox/memory/queue_buffer.c
+++ b/core/src/tbox/src/tbox/memory/queue_buffer.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file queue_buffer.c
@@ -224,10 +224,19 @@ tb_long_t tb_queue_buffer_writ(tb_queue_buffer_ref_t buffer, tb_byte_t const* da
}
tb_assert_and_check_return_val(buffer->data && buffer->head, -1);
- // no left?
+ // 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)
{
@@ -235,7 +244,7 @@ tb_long_t tb_queue_buffer_writ(tb_queue_buffer_ref_t buffer, tb_byte_t const* da
buffer->head = buffer->data;
}
- // writ data
+ // write data
tb_size_t writ = left > size? size : left;
tb_memcpy(buffer->data + buffer->size, data, writ);
buffer->size += writ;
@@ -288,11 +297,11 @@ tb_byte_t* tb_queue_buffer_push_init(tb_queue_buffer_ref_t buffer, tb_size_t* si
}
tb_assert_and_check_return_val(buffer->data && buffer->head, tb_null);
- // no left?
+ // full?
tb_size_t left = buffer->maxn - buffer->size;
tb_check_return_val(left, tb_null);
- // move data to head
+ // 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);
diff --git a/core/src/tbox/src/tbox/memory/queue_buffer.h b/core/src/tbox/src/tbox/memory/queue_buffer.h
index f5993cffc..c79923133 100644
--- a/core/src/tbox/src/tbox/memory/queue_buffer.h
+++ b/core/src/tbox/src/tbox/memory/queue_buffer.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file queue_buffer.h
diff --git a/core/src/tbox/src/tbox/memory/small_allocator.c b/core/src/tbox/src/tbox/memory/small_allocator.c
index 9c2e8fa8d..8f50c0308 100644
--- a/core/src/tbox/src/tbox/memory/small_allocator.c
+++ b/core/src/tbox/src/tbox/memory/small_allocator.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file small_allocator.c
@@ -440,7 +440,8 @@ tb_allocator_ref_t tb_small_allocator_init(tb_allocator_ref_t large_allocator)
allocator->large_allocator = large_allocator;
// init base
- allocator->base.type = TB_ALLOCATOR_SMALL;
+ 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;
diff --git a/core/src/tbox/src/tbox/memory/small_allocator.h b/core/src/tbox/src/tbox/memory/small_allocator.h
index 8203e8ff0..0f753d4bf 100644
--- a/core/src/tbox/src/tbox/memory/small_allocator.h
+++ b/core/src/tbox/src/tbox/memory/small_allocator.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file small_allocator.h
diff --git a/core/src/tbox/src/tbox/memory/static_allocator.c b/core/src/tbox/src/tbox/memory/static_allocator.c
index a9d014f02..dec210fb5 100644
--- a/core/src/tbox/src/tbox/memory/static_allocator.c
+++ b/core/src/tbox/src/tbox/memory/static_allocator.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file static_allocator.c
@@ -90,7 +90,7 @@ tb_allocator_ref_t tb_static_allocator_init(tb_byte_t* data, tb_size_t size)
tb_assert_and_check_return_val(allocator, tb_null);
// init type
- allocator->type = TB_ALLOCATOR_STATIC;
+ allocator->type = TB_ALLOCATOR_TYPE_STATIC;
// ok
return allocator;
diff --git a/core/src/tbox/src/tbox/memory/static_allocator.h b/core/src/tbox/src/tbox/memory/static_allocator.h
index 463b03203..0da28d12a 100644
--- a/core/src/tbox/src/tbox/memory/static_allocator.h
+++ b/core/src/tbox/src/tbox/memory/static_allocator.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file static_allocator.h
diff --git a/core/src/tbox/src/tbox/memory/static_buffer.c b/core/src/tbox/src/tbox/memory/static_buffer.c
index b1e4d7312..f8426f488 100644
--- a/core/src/tbox/src/tbox/memory/static_buffer.c
+++ b/core/src/tbox/src/tbox/memory/static_buffer.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file static_buffer.c
@@ -73,7 +73,7 @@ tb_byte_t* tb_static_buffer_data(tb_static_buffer_ref_t buffer)
tb_assert_and_check_return_val(buffer, tb_null);
// the buffer data
- return buffer->size? buffer->data : tb_null;
+ return buffer->data;
}
tb_size_t tb_static_buffer_size(tb_static_buffer_ref_t buffer)
{
diff --git a/core/src/tbox/src/tbox/memory/static_buffer.h b/core/src/tbox/src/tbox/memory/static_buffer.h
index f44458007..e6ee9cfeb 100644
--- a/core/src/tbox/src/tbox/memory/static_buffer.h
+++ b/core/src/tbox/src/tbox/memory/static_buffer.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file static_buffer.h
diff --git a/core/src/tbox/src/tbox/memory/string_pool.c b/core/src/tbox/src/tbox/memory/string_pool.c
index e27cb0237..cca69496d 100644
--- a/core/src/tbox/src/tbox/memory/string_pool.c
+++ b/core/src/tbox/src/tbox/memory/string_pool.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file string_pool.c
diff --git a/core/src/tbox/src/tbox/memory/string_pool.h b/core/src/tbox/src/tbox/memory/string_pool.h
index 8d4f3d465..55a6be17f 100644
--- a/core/src/tbox/src/tbox/memory/string_pool.h
+++ b/core/src/tbox/src/tbox/memory/string_pool.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file string_pool.h
diff --git a/core/src/tbox/src/tbox/micro.lua b/core/src/tbox/src/tbox/micro.lua
new file mode 100644
index 000000000..93a41652d
--- /dev/null
+++ b/core/src/tbox/src/tbox/micro.lua
@@ -0,0 +1,118 @@
+-- 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("..")
+ add_includedirs("$(buildir)/$(plat)/$(arch)/$(mode)")
+
+ -- add public header directories
+ add_headerdirs("..")
+ add_headerdirs("$(buildir)/$(plat)/$(arch)/$(mode)")
+
+ -- 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/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/impl/static_large_allocator.c")
+ add_files("memory/impl/memory.c")
+ add_files("network/ipv4.c")
+ add_files("network/ipv6.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/memory.c")
+ add_files("platform/thread.c")
+ add_files("platform/socket.c")
+ add_files("platform/addrinfo.c")
+ add_files("platform/poller.c")
+ add_files("platform/impl/sockdata.c")
+ add_files("platform/impl/platform.c")
+ add_files("container/iterator.c")
+ add_files("container/list_entry.c")
+ add_files("container/single_list_entry.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/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
+ check_interfaces()
diff --git a/core/src/tbox/src/tbox/network/cookies.c b/core/src/tbox/src/tbox/network/cookies.c
index 01d9d9181..dc416d650 100644
--- a/core/src/tbox/src/tbox/network/cookies.c
+++ b/core/src/tbox/src/tbox/network/cookies.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file cookies.c
@@ -235,7 +235,7 @@ static tb_size_t tb_cookies_entry_hash(tb_element_ref_t element, tb_cpointer_t d
{
// check
tb_cookies_entry_ref_t entry = (tb_cookies_entry_ref_t)data;
- tb_assert_and_check_return_val(element && entry && entry->domain && entry->path && entry->name, 0);
+ tb_assert_and_check_return_val(element && entry && entry->domain, 0);
// the cookies
tb_cookies_t* cookies = (tb_cookies_t*)element->priv;
@@ -243,8 +243,8 @@ static tb_size_t tb_cookies_entry_hash(tb_element_ref_t element, tb_cpointer_t d
// compute the three hash values
tb_size_t v0 = cookies->string_element.hash(&cookies->string_element, entry->domain, mask, index);
- tb_size_t v1 = cookies->string_element.hash(&cookies->string_element, entry->path, mask, index);
- tb_size_t v2 = cookies->string_element.hash(&cookies->string_element, entry->name, 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;
@@ -254,19 +254,19 @@ static tb_long_t tb_cookies_entry_comp(tb_element_ref_t element, tb_cpointer_t l
// 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 && lentry->path && lentry->name, 0);
- tb_assert_and_check_return_val(rentry && rentry->domain && rentry->path && rentry->name, 0);
+ 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, rentry->path);
+ ok = tb_strcmp(lentry->path? lentry->path : "", rentry->path? rentry->path : "");
tb_check_return_val(!ok, ok);
// compare name
- return tb_strcmp(lentry->name, rentry->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)
{
@@ -291,7 +291,7 @@ static tb_bool_t tb_cookies_entry_init(tb_cookies_t* cookies, tb_cookies_entry_r
tb_check_break(b);
// trace
- tb_trace_d("entry: %s: %s", b? b : "", v? v : "");
+ tb_trace_d("entry: %s => %s", b? b : "", v? v : "");
// done value
if (!tb_strnicmp(b, "expires", 7))
@@ -346,12 +346,8 @@ static tb_bool_t tb_cookies_entry_init(tb_cookies_t* cookies, tb_cookies_entry_r
{
// must have value
tb_assert_and_check_return_val(v, tb_false);
-
}
- else if (!tb_strnicmp(b, "secure", 6))
- {
- entry->secure = 1;
- }
+ else if (!tb_strnicmp(b, "secure", 6)) entry->secure = 1;
// ignore it
else if (!tb_strnicmp(b, "HttpOnly", 8)) ;
// key=value
@@ -374,6 +370,9 @@ static tb_bool_t tb_cookies_entry_init(tb_cookies_t* cookies, tb_cookies_entry_r
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
@@ -396,9 +395,6 @@ static tb_bool_t tb_cookies_entry_init(tb_cookies_t* cookies, tb_cookies_entry_r
else p++;
}
- // check name
- tb_assert_and_check_return_val(entry->name, tb_false);
-
// domain not exists? using the given domain
if (!entry->domain && domain)
{
@@ -443,7 +439,7 @@ static tb_bool_t tb_cookies_entry_walk(tb_iterator_ref_t iterator, tb_cpointer_t
// the entry
tb_cookies_entry_ref_t entry = (tb_cookies_entry_ref_t)item;
- tb_assert(entry && entry->domain && entry->path && entry->name);
+ tb_assert(entry && entry->domain);
// the domain
tb_char_t const* domain = tuple[0].cstr;
@@ -462,7 +458,7 @@ static tb_bool_t tb_cookies_entry_walk(tb_iterator_ref_t iterator, tb_cpointer_t
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->name, entry->value? entry->value : "");
+ 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;
@@ -470,6 +466,7 @@ static tb_bool_t tb_cookies_entry_walk(tb_iterator_ref_t iterator, tb_cpointer_t
// 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)
{
@@ -486,7 +483,7 @@ static tb_bool_t tb_cookies_entry_walk(tb_iterator_ref_t iterator, tb_cpointer_t
*/
static tb_handle_t tb_cookies_instance_init(tb_cpointer_t* ppriv)
{
- return tb_cookies_init();
+ return (tb_handle_t)tb_cookies_init();
}
static tb_void_t tb_cookies_instance_exit(tb_handle_t cookies, tb_cpointer_t priv)
{
@@ -762,14 +759,14 @@ tb_void_t tb_cookies_dump(tb_cookies_ref_t self)
tb_for_all_if (tb_cookies_entry_ref_t, entry, cookies->cookie_pool, entry)
{
// the entry
- tb_assert_and_check_continue(entry->domain && entry->path && entry->name);
+ 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->name, entry->value? entry->value : "", date.year, date.month, date.mday, date.hour, date.minute, date.second, date.week);
+ 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
diff --git a/core/src/tbox/src/tbox/network/cookies.h b/core/src/tbox/src/tbox/network/cookies.h
index b71cdc40b..7cd69ed47 100644
--- a/core/src/tbox/src/tbox/network/cookies.h
+++ b/core/src/tbox/src/tbox/network/cookies.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file cookies.h
diff --git a/core/src/tbox/src/tbox/network/dns/cache.c b/core/src/tbox/src/tbox/network/dns/cache.c
index 01f4cbcc9..848c48123 100644
--- a/core/src/tbox/src/tbox/network/dns/cache.c
+++ b/core/src/tbox/src/tbox/network/dns/cache.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file cache.c
diff --git a/core/src/tbox/src/tbox/network/dns/cache.h b/core/src/tbox/src/tbox/network/dns/cache.h
index c4de13bb0..37472346c 100644
--- a/core/src/tbox/src/tbox/network/dns/cache.h
+++ b/core/src/tbox/src/tbox/network/dns/cache.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file cache.h
@@ -32,6 +32,11 @@
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_enter__
+
+/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
@@ -62,4 +67,9 @@ tb_bool_t tb_dns_cache_get(tb_char_t const* name, tb_ipaddr_ref_t addr
*/
tb_void_t tb_dns_cache_set(tb_char_t const* name, tb_ipaddr_ref_t addr);
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_leave__
+
#endif
diff --git a/core/src/tbox/src/tbox/network/dns/dns.h b/core/src/tbox/src/tbox/network/dns/dns.h
index 755042b22..c0db853f4 100644
--- a/core/src/tbox/src/tbox/network/dns/dns.h
+++ b/core/src/tbox/src/tbox/network/dns/dns.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file dns.h
diff --git a/core/src/tbox/src/tbox/network/dns/looker.c b/core/src/tbox/src/tbox/network/dns/looker.c
index 7462f37c3..a4cfd1874 100644
--- a/core/src/tbox/src/tbox/network/dns/looker.c
+++ b/core/src/tbox/src/tbox/network/dns/looker.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file looker.c
@@ -236,7 +236,6 @@ static tb_long_t tb_dns_looker_reqt(tb_dns_looker_t* looker)
{
// writ data
tb_long_t writ = tb_socket_usend(looker->sock, addr, data + looker->size, size - looker->size);
- //tb_trace_d("writ: %d", writ);
tb_assert_and_check_return_val(writ >= 0, -1);
// no data?
@@ -481,12 +480,13 @@ static tb_long_t tb_dns_looker_resp(tb_dns_looker_t* looker, tb_ipaddr_ref_t add
looker->step &= ~TB_DNS_LOOKER_STEP_NEVT;
// recv response data
- tb_byte_t rpkt[4096];
- while (1)
+ 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, rpkt, 4096);
- //tb_trace_d("read %d", read);
+ 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?
@@ -506,8 +506,9 @@ static tb_long_t tb_dns_looker_resp(tb_dns_looker_t* looker, tb_ipaddr_ref_t add
}
else looker->tryn = 0;
- // copy data
- tb_static_buffer_memncat(&looker->rpkt, rpkt, read);
+ // update buffer size
+ tb_static_buffer_resize(&looker->rpkt, size + read);
+ size = tb_static_buffer_size(&looker->rpkt);
}
// done
@@ -643,7 +644,7 @@ tb_long_t tb_dns_looker_wait(tb_dns_looker_ref_t self, tb_long_t timeout)
tb_dns_looker_t* looker = (tb_dns_looker_t*)self;
tb_assert_and_check_return_val(looker && looker->sock, -1);
- // has asio event?
+ // has io event?
tb_size_t e = TB_SOCKET_EVENT_NONE;
if (!(looker->step & TB_DNS_LOOKER_STEP_NEVT))
{
@@ -655,6 +656,9 @@ tb_long_t tb_dns_looker_wait(tb_dns_looker_ref_t self, tb_long_t timeout)
tb_long_t r = 0;
if (e)
{
+ // trace
+ tb_trace_d("waiting %p ..", looker->sock);
+
// wait
r = tb_socket_wait(looker->sock, e, timeout);
diff --git a/core/src/tbox/src/tbox/network/dns/looker.h b/core/src/tbox/src/tbox/network/dns/looker.h
index 215e7c9a5..e6e4a8e81 100644
--- a/core/src/tbox/src/tbox/network/dns/looker.h
+++ b/core/src/tbox/src/tbox/network/dns/looker.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file looker.h
@@ -32,6 +32,11 @@
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_enter__
+
+/* //////////////////////////////////////////////////////////////////////////////////////
* types
*/
@@ -74,7 +79,7 @@ tb_long_t tb_dns_looker_wait(tb_dns_looker_ref_t looker, tb_long_t tim
*/
tb_void_t tb_dns_looker_exit(tb_dns_looker_ref_t looker);
-/*! look address from the host name, block
+/*! lookup address from the host name, block
*
* try to look it from cache first
*
@@ -85,4 +90,9 @@ tb_void_t tb_dns_looker_exit(tb_dns_looker_ref_t looker);
*/
tb_bool_t tb_dns_looker_done(tb_char_t const* name, tb_ipaddr_ref_t addr);
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_leave__
+
#endif
diff --git a/core/src/tbox/src/tbox/network/dns/prefix.h b/core/src/tbox/src/tbox/network/dns/prefix.h
index 8b3c16854..2d125f0c1 100644
--- a/core/src/tbox/src/tbox/network/dns/prefix.h
+++ b/core/src/tbox/src/tbox/network/dns/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/network/dns/server.c b/core/src/tbox/src/tbox/network/dns/server.c
index 8689f5662..623d8652b 100644
--- a/core/src/tbox/src/tbox/network/dns/server.c
+++ b/core/src/tbox/src/tbox/network/dns/server.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file server.c
@@ -246,7 +246,7 @@ static tb_long_t tb_dns_server_test(tb_ipaddr_ref_t addr)
tb_long_t r = tb_socket_urecv(sock, tb_null, rpkt + read, TB_DNS_RPKT_MAXN - read);
// trace
- tb_trace_d("read %d", r);
+ tb_trace_d("read %ld", r);
// check
tb_check_break(r >= 0);
@@ -261,7 +261,7 @@ static tb_long_t tb_dns_server_test(tb_ipaddr_ref_t addr)
r = tb_socket_wait(sock, TB_SOCKET_EVENT_RECV, TB_DNS_SERVER_TEST_TIMEOUT);
// trace
- tb_trace_d("wait %d", r);
+ tb_trace_d("wait %ld", r);
// fail or timeout?
tb_check_break(r > 0);
diff --git a/core/src/tbox/src/tbox/network/dns/server.h b/core/src/tbox/src/tbox/network/dns/server.h
index 81f0fa7e3..eb3abb098 100644
--- a/core/src/tbox/src/tbox/network/dns/server.h
+++ b/core/src/tbox/src/tbox/network/dns/server.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file server.h
diff --git a/core/src/tbox/src/tbox/network/http.c b/core/src/tbox/src/tbox/network/http.c
index 29cbcc869..dd4e38fe2 100644
--- a/core/src/tbox/src/tbox/network/http.c
+++ b/core/src/tbox/src/tbox/network/http.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file http.c
@@ -85,6 +85,9 @@ typedef struct __tb_http_t
// the cookies
tb_string_t cookies;
+ // the request/response data for decreasing stack size
+ tb_char_t data[8192];
+
}tb_http_t;
/* //////////////////////////////////////////////////////////////////////////////////////
@@ -109,10 +112,13 @@ static tb_bool_t tb_http_connect(tb_http_t* http)
// trace
tb_trace_d("connect: host: %s", host_changed? "changed" : "keep");
- // ctrl stream
+ // 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);
@@ -127,9 +133,6 @@ static tb_bool_t tb_http_connect(tb_http_t* http)
// open stream
if (!tb_stream_open(http->stream)) break;
- // trace
- tb_trace_d("connect: ok");
-
// ok
ok = tb_true;
@@ -139,6 +142,9 @@ static tb_bool_t tb_http_connect(tb_http_t* http)
// 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;
}
@@ -173,9 +179,8 @@ static tb_bool_t tb_http_request(tb_http_t* http)
tb_string_clear(&http->request);
// init the head value
- tb_char_t data[8192];
- tb_static_string_t value;
- if (!tb_static_string_init(&value, data, sizeof(data))) break;
+ 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);
@@ -303,8 +308,8 @@ static tb_bool_t tb_http_request(tb_http_t* http)
tb_string_chrcat(&http->request, ' ');
// encode path
- tb_url_encode2(path, tb_strlen(path), data, sizeof(data) - 1);
- path = data;
+ tb_url_encode2(path, tb_strlen(path), http->data, sizeof(http->data) - 1);
+ path = http->data;
// append path
tb_string_cstrcat(&http->request, path);
@@ -316,8 +321,8 @@ static tb_bool_t tb_http_request(tb_http_t* http)
tb_string_chrcat(&http->request, '?');
// encode args
- tb_url_encode2(args, tb_strlen(args), data, sizeof(data) - 1);
- args = data;
+ tb_url_encode2(args, tb_strlen(args), http->data, sizeof(http->data) - 1);
+ args = http->data;
// append args
tb_string_cstrcat(&http->request, args);
@@ -557,16 +562,15 @@ static tb_bool_t tb_http_response(tb_http_t* http)
do
{
// read line
- tb_char_t line[8192];
tb_long_t real = 0;
tb_size_t indx = 0;
- while ((real = tb_stream_bread_line(http->stream, line, sizeof(line) - 1)) >= 0)
+ while ((real = tb_stream_bread_line(http->stream, http->data, sizeof(http->data) - 1)) >= 0)
{
// trace
- tb_trace_d("response: %s", line);
+ tb_trace_d("response: %s", http->data);
// do callback
- if (http->option.head_func && !http->option.head_func(line, http->option.head_priv)) break;
+ if (http->option.head_func && !http->option.head_func(http->data, http->option.head_priv)) break;
// end?
if (!real)
@@ -647,7 +651,7 @@ static tb_bool_t tb_http_response(tb_http_t* http)
}
// done it
- if (!tb_http_response_done(http, line, indx++)) break;
+ if (!tb_http_response_done(http, http->data, indx++)) break;
}
} while (0);
@@ -662,6 +666,7 @@ static tb_bool_t tb_http_redirect(tb_http_t* http)
// 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
@@ -692,7 +697,7 @@ static tb_bool_t tb_http_redirect(tb_http_t* http)
// switch to sstream
http->stream = http->sstream;
- // done location url
+ // get location url
tb_char_t const* location = tb_string_cstr(&http->status.location);
tb_assert_and_check_break(location);
@@ -716,17 +721,17 @@ static tb_bool_t tb_http_redirect(tb_http_t* http)
}
// connect it
- if (!tb_http_connect(http)) break;
+ if (!(ok = tb_http_connect(http))) break;
// request it
- if (!tb_http_request(http)) break;
+ if (!(ok = tb_http_request(http))) break;
// response it
- if (!tb_http_response(http)) break;
+ if (!(ok = tb_http_response(http))) break;
}
// ok?
- return (i < http->option.redirect && tb_string_size(&http->status.location))? tb_false : tb_true;
+ return ok && !tb_string_size(&http->status.location);
}
/* //////////////////////////////////////////////////////////////////////////////////////
@@ -735,8 +740,8 @@ static tb_bool_t tb_http_redirect(tb_http_t* http)
tb_http_ref_t tb_http_init()
{
// done
- tb_bool_t ok = tb_false;
- tb_http_t* http = tb_null;
+ tb_bool_t ok = tb_false;
+ tb_http_t* http = tb_null;
do
{
// make http
diff --git a/core/src/tbox/src/tbox/network/http.h b/core/src/tbox/src/tbox/network/http.h
index f7b31030e..f72b89ccc 100644
--- a/core/src/tbox/src/tbox/network/http.h
+++ b/core/src/tbox/src/tbox/network/http.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file http.h
diff --git a/core/src/tbox/src/tbox/network/hwaddr.c b/core/src/tbox/src/tbox/network/hwaddr.c
index 315568a8b..92961d6c9 100644
--- a/core/src/tbox/src/tbox/network/hwaddr.c
+++ b/core/src/tbox/src/tbox/network/hwaddr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file hwaddr.c
diff --git a/core/src/tbox/src/tbox/network/hwaddr.h b/core/src/tbox/src/tbox/network/hwaddr.h
index 04013efce..0cd51847d 100644
--- a/core/src/tbox/src/tbox/network/hwaddr.h
+++ b/core/src/tbox/src/tbox/network/hwaddr.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file hwaddr.h
diff --git a/core/src/tbox/src/tbox/network/impl/http/date.c b/core/src/tbox/src/tbox/network/impl/http/date.c
index b3b1786cc..e2365684a 100644
--- a/core/src/tbox/src/tbox/network/impl/http/date.c
+++ b/core/src/tbox/src/tbox/network/impl/http/date.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file date.c
diff --git a/core/src/tbox/src/tbox/network/impl/http/date.h b/core/src/tbox/src/tbox/network/impl/http/date.h
index 248df282e..f4a862974 100644
--- a/core/src/tbox/src/tbox/network/impl/http/date.h
+++ b/core/src/tbox/src/tbox/network/impl/http/date.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file date.h
diff --git a/core/src/tbox/src/tbox/network/impl/http/method.c b/core/src/tbox/src/tbox/network/impl/http/method.c
index 8d320ba7d..7ebfd2b6b 100644
--- a/core/src/tbox/src/tbox/network/impl/http/method.c
+++ b/core/src/tbox/src/tbox/network/impl/http/method.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file method.c
diff --git a/core/src/tbox/src/tbox/network/impl/http/method.h b/core/src/tbox/src/tbox/network/impl/http/method.h
index 45e79739f..3a8c0d376 100644
--- a/core/src/tbox/src/tbox/network/impl/http/method.h
+++ b/core/src/tbox/src/tbox/network/impl/http/method.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file method.h
diff --git a/core/src/tbox/src/tbox/network/impl/http/option.c b/core/src/tbox/src/tbox/network/impl/http/option.c
index 956685d23..8c298c8e9 100644
--- a/core/src/tbox/src/tbox/network/impl/http/option.c
+++ b/core/src/tbox/src/tbox/network/impl/http/option.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file option.c
diff --git a/core/src/tbox/src/tbox/network/impl/http/option.h b/core/src/tbox/src/tbox/network/impl/http/option.h
index b3f6ee3b1..77cc5a77d 100644
--- a/core/src/tbox/src/tbox/network/impl/http/option.h
+++ b/core/src/tbox/src/tbox/network/impl/http/option.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file option.h
diff --git a/core/src/tbox/src/tbox/network/impl/http/prefix.h b/core/src/tbox/src/tbox/network/impl/http/prefix.h
index ceb74bc61..6a9e5d1fa 100644
--- a/core/src/tbox/src/tbox/network/impl/http/prefix.h
+++ b/core/src/tbox/src/tbox/network/impl/http/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/network/impl/http/status.c b/core/src/tbox/src/tbox/network/impl/http/status.c
index 37e4b13ab..a8bad766d 100644
--- a/core/src/tbox/src/tbox/network/impl/http/status.c
+++ b/core/src/tbox/src/tbox/network/impl/http/status.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file status.c
diff --git a/core/src/tbox/src/tbox/network/impl/http/status.h b/core/src/tbox/src/tbox/network/impl/http/status.h
index 29e70dea5..6cbcc1416 100644
--- a/core/src/tbox/src/tbox/network/impl/http/status.h
+++ b/core/src/tbox/src/tbox/network/impl/http/status.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file status.h
diff --git a/core/src/tbox/src/tbox/network/impl/impl.h b/core/src/tbox/src/tbox/network/impl/impl.h
index c6d9da6f4..485d36773 100644
--- a/core/src/tbox/src/tbox/network/impl/impl.h
+++ b/core/src/tbox/src/tbox/network/impl/impl.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file network.h
diff --git a/core/src/tbox/src/tbox/network/impl/network.c b/core/src/tbox/src/tbox/network/impl/network.c
index a9c81f921..dddf3add0 100644
--- a/core/src/tbox/src/tbox/network/impl/network.c
+++ b/core/src/tbox/src/tbox/network/impl/network.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file network.c
diff --git a/core/src/tbox/src/tbox/network/impl/network.h b/core/src/tbox/src/tbox/network/impl/network.h
index b9c2b6e64..4303a77a4 100644
--- a/core/src/tbox/src/tbox/network/impl/network.h
+++ b/core/src/tbox/src/tbox/network/impl/network.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file network.h
diff --git a/core/src/tbox/src/tbox/network/impl/prefix.h b/core/src/tbox/src/tbox/network/impl/prefix.h
index 2d0fa402a..d63d2ba62 100644
--- a/core/src/tbox/src/tbox/network/impl/prefix.h
+++ b/core/src/tbox/src/tbox/network/impl/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/network/impl/ssl/mbedtls.c b/core/src/tbox/src/tbox/network/impl/ssl/mbedtls.c
index e0ea40a8c..b5fcced35 100644
--- a/core/src/tbox/src/tbox/network/impl/ssl/mbedtls.c
+++ b/core/src/tbox/src/tbox/network/impl/ssl/mbedtls.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file mbedtls.c
@@ -30,12 +30,12 @@
* includes
*/
#include "prefix.h"
-#include <mbedtls/net.h>
#include <mbedtls/ssl.h>
#include <mbedtls/certs.h>
#include <mbedtls/debug.h>
#include <mbedtls/entropy.h>
#include <mbedtls/ctr_drbg.h>
+#include <mbedtls/net_sockets.h>
#include "../../../libc/libc.h"
#include "../../../platform/platform.h"
diff --git a/core/src/tbox/src/tbox/network/impl/ssl/openssl.c b/core/src/tbox/src/tbox/network/impl/ssl/openssl.c
index b2a98c44b..9c8745a5b 100644
--- a/core/src/tbox/src/tbox/network/impl/ssl/openssl.c
+++ b/core/src/tbox/src/tbox/network/impl/ssl/openssl.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file openssl.c
@@ -92,19 +92,7 @@ static tb_int_t tb_ssl_bio_method_gets(BIO* bio, tb_char_t* data, tb_int
/* //////////////////////////////////////////////////////////////////////////////////////
* globals
*/
-static BIO_METHOD g_ssl_bio_method =
-{
- BIO_TYPE_SOURCE_SINK | 100
-, "ssl_bio"
-, tb_ssl_bio_method_writ
-, tb_ssl_bio_method_read
-, tb_ssl_bio_method_puts
-, tb_ssl_bio_method_gets
-, tb_ssl_bio_method_ctrl
-, tb_ssl_bio_method_init
-, tb_ssl_bio_method_exit
-, tb_null
-};
+static BIO_METHOD* g_ssl_bio_method = tb_null;
/* //////////////////////////////////////////////////////////////////////////////////////
* library implementation
@@ -114,11 +102,26 @@ 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()
{
@@ -195,11 +198,9 @@ static tb_int_t tb_ssl_bio_method_init(BIO* bio)
tb_trace_d("bio: init");
// init
- bio->init = 1;
- bio->num = 0;
- bio->ptr = tb_null;
- bio->flags = 0;
- bio->shutdown = 1;
+ BIO_set_init(bio, 1);
+ BIO_set_data(bio, tb_null);
+ BIO_set_shutdown(bio, 1);
// ok
return 1;
@@ -213,10 +214,9 @@ static tb_int_t tb_ssl_bio_method_exit(BIO* bio)
tb_trace_d("bio: exit");
// exit
- bio->init = 0;
- bio->num = 0;
- bio->ptr = tb_null;
- bio->flags = 0;
+ BIO_set_init(bio, 0);
+ BIO_set_data(bio, tb_null);
+ BIO_set_shutdown(bio, 0);
// ok
return 1;
@@ -227,7 +227,7 @@ static tb_int_t tb_ssl_bio_method_read(BIO* bio, tb_char_t* data, tb_int_t size)
tb_assert_and_check_return_val(bio && data && size >= 0, -1);
// the ssl
- tb_ssl_t* ssl = (tb_ssl_t*)bio->ptr;
+ tb_ssl_t* ssl = (tb_ssl_t*)BIO_get_data(bio);
tb_assert_and_check_return_val(ssl && ssl->read, -1);
// writ
@@ -267,7 +267,7 @@ static tb_int_t tb_ssl_bio_method_writ(BIO* bio, tb_char_t const* data, tb_int_t
tb_assert_and_check_return_val(bio && data && size >= 0, -1);
// the ssl
- tb_ssl_t* ssl = (tb_ssl_t*)bio->ptr;
+ tb_ssl_t* ssl = (tb_ssl_t*)BIO_get_data(bio);
tb_assert_and_check_return_val(ssl && ssl->writ, -1);
// writ
@@ -307,7 +307,7 @@ static tb_long_t tb_ssl_bio_method_ctrl(BIO* bio, tb_int_t cmd, tb_long_t num, t
tb_assert_and_check_return_val(bio, -1);
// the ssl
- tb_ssl_t* ssl = (tb_ssl_t*)bio->ptr;
+ tb_ssl_t* ssl = (tb_ssl_t*)BIO_get_data(bio);
tb_assert_and_check_return_val(ssl, -1);
// done
@@ -369,6 +369,9 @@ tb_ssl_ref_t tb_ssl_init(tb_bool_t bserver)
// 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);
@@ -377,7 +380,7 @@ tb_ssl_ref_t tb_ssl_init(tb_bool_t bserver)
ssl->timeout = 30000;
// init ctx
- ssl->ctx = SSL_CTX_new(SSLv3_method());
+ ssl->ctx = SSL_CTX_new(SSLv23_method());
tb_assert_and_check_break(ssl->ctx);
// make ssl
@@ -392,11 +395,11 @@ tb_ssl_ref_t tb_ssl_init(tb_bool_t bserver)
SSL_set_verify(ssl->ssl, 0, tb_ssl_verify);
// init bio
- ssl->bio = BIO_new(&g_ssl_bio_method);
+ ssl->bio = BIO_new(g_ssl_bio_method);
tb_assert_and_check_break(ssl->bio);
// set bio to ssl
- ssl->bio->ptr = ssl;
+ BIO_set_data(ssl->bio, ssl);
SSL_set_bio(ssl->ssl, ssl->bio, ssl->bio);
// init state
diff --git a/core/src/tbox/src/tbox/network/impl/ssl/polarssl.c b/core/src/tbox/src/tbox/network/impl/ssl/polarssl.c
index 68caa1ebc..7160f4736 100644
--- a/core/src/tbox/src/tbox/network/impl/ssl/polarssl.c
+++ b/core/src/tbox/src/tbox/network/impl/ssl/polarssl.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file polarssl.c
diff --git a/core/src/tbox/src/tbox/network/impl/ssl/prefix.h b/core/src/tbox/src/tbox/network/impl/ssl/prefix.h
index 1475fa9e1..e91b938b5 100644
--- a/core/src/tbox/src/tbox/network/impl/ssl/prefix.h
+++ b/core/src/tbox/src/tbox/network/impl/ssl/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/network/ipaddr.c b/core/src/tbox/src/tbox/network/ipaddr.c
index 471d431ae..78c7af167 100644
--- a/core/src/tbox/src/tbox/network/ipaddr.c
+++ b/core/src/tbox/src/tbox/network/ipaddr.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ipaddr.c
diff --git a/core/src/tbox/src/tbox/network/ipaddr.h b/core/src/tbox/src/tbox/network/ipaddr.h
index 66072b324..b7b96ba62 100644
--- a/core/src/tbox/src/tbox/network/ipaddr.h
+++ b/core/src/tbox/src/tbox/network/ipaddr.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ipaddr.h
diff --git a/core/src/tbox/src/tbox/network/ipv4.c b/core/src/tbox/src/tbox/network/ipv4.c
index cafacd53a..97deb9412 100644
--- a/core/src/tbox/src/tbox/network/ipv4.c
+++ b/core/src/tbox/src/tbox/network/ipv4.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ipv4.c
diff --git a/core/src/tbox/src/tbox/network/ipv4.h b/core/src/tbox/src/tbox/network/ipv4.h
index af27912dc..3e45b109e 100644
--- a/core/src/tbox/src/tbox/network/ipv4.h
+++ b/core/src/tbox/src/tbox/network/ipv4.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ipv4.h
diff --git a/core/src/tbox/src/tbox/network/ipv6.c b/core/src/tbox/src/tbox/network/ipv6.c
index f330730f2..c4165b44d 100644
--- a/core/src/tbox/src/tbox/network/ipv6.c
+++ b/core/src/tbox/src/tbox/network/ipv6.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ipv6.c
diff --git a/core/src/tbox/src/tbox/network/ipv6.h b/core/src/tbox/src/tbox/network/ipv6.h
index bf631d067..90de2fa96 100644
--- a/core/src/tbox/src/tbox/network/ipv6.h
+++ b/core/src/tbox/src/tbox/network/ipv6.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ipv6.h
diff --git a/core/src/tbox/src/tbox/network/network.h b/core/src/tbox/src/tbox/network/network.h
index b1db5758a..dbc473b89 100644
--- a/core/src/tbox/src/tbox/network/network.h
+++ b/core/src/tbox/src/tbox/network/network.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file network.h
diff --git a/core/src/tbox/src/tbox/network/prefix.h b/core/src/tbox/src/tbox/network/prefix.h
index b0e30d241..1bd1aee91 100644
--- a/core/src/tbox/src/tbox/network/prefix.h
+++ b/core/src/tbox/src/tbox/network/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/network/ssl.h b/core/src/tbox/src/tbox/network/ssl.h
index b6586d579..8317b7100 100644
--- a/core/src/tbox/src/tbox/network/ssl.h
+++ b/core/src/tbox/src/tbox/network/ssl.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ssl.h
diff --git a/core/src/tbox/src/tbox/network/url.c b/core/src/tbox/src/tbox/network/url.c
index 2b544d60e..7d1bf078e 100644
--- a/core/src/tbox/src/tbox/network/url.c
+++ b/core/src/tbox/src/tbox/network/url.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file url.c
diff --git a/core/src/tbox/src/tbox/network/url.h b/core/src/tbox/src/tbox/network/url.h
index 68902e95d..92166a8e3 100644
--- a/core/src/tbox/src/tbox/network/url.h
+++ b/core/src/tbox/src/tbox/network/url.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file url.h
diff --git a/core/src/tbox/src/tbox/object/array.c b/core/src/tbox/src/tbox/object/array.c
new file mode 100644
index 000000000..0bdf8575b
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/array.c
@@ -0,0 +1,266 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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;
+}
diff --git a/core/src/tbox/src/tbox/object/array.h b/core/src/tbox/src/tbox/object/array.h
new file mode 100644
index 000000000..f1a4574f7
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/array.h
@@ -0,0 +1,130 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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 index the array index
+ */
+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
+
diff --git a/core/src/tbox/src/tbox/object/boolean.c b/core/src/tbox/src/tbox/object/boolean.c
new file mode 100644
index 000000000..c846fd487
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/boolean.c
@@ -0,0 +1,133 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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;
+}
+
diff --git a/core/src/tbox/src/tbox/object/boolean.h b/core/src/tbox/src/tbox/object/boolean.h
new file mode 100644
index 000000000..e79980bd7
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/boolean.h
@@ -0,0 +1,78 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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 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
+
diff --git a/core/src/tbox/src/tbox/object/data.c b/core/src/tbox/src/tbox/object/data.c
new file mode 100644
index 000000000..3ecfaa7df
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/data.c
@@ -0,0 +1,258 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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;
+}
diff --git a/core/src/tbox/src/tbox/object/data.h b/core/src/tbox/src/tbox/object/data.h
new file mode 100644
index 000000000..a8c0393b9
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/data.h
@@ -0,0 +1,117 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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 data the data
+ * @param size the size
+ *
+ * @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
+
diff --git a/core/src/tbox/src/tbox/object/date.c b/core/src/tbox/src/tbox/object/date.c
new file mode 100644
index 000000000..57d4afca2
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/date.c
@@ -0,0 +1,172 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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;
+}
diff --git a/core/src/tbox/src/tbox/object/date.h b/core/src/tbox/src/tbox/object/date.h
new file mode 100644
index 000000000..b65338b11
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/date.h
@@ -0,0 +1,88 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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 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 the date object
+ *
+ * @return the date time
+ */
+tb_time_t tb_oc_date_time(tb_object_ref_t date);
+
+/*! set the date time
+ *
+ * @param the date object
+ * @param 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 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
+
diff --git a/core/src/tbox/src/tbox/object/dictionary.c b/core/src/tbox/src/tbox/object/dictionary.c
new file mode 100644
index 000000000..9dec38995
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/dictionary.c
@@ -0,0 +1,259 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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;
+}
diff --git a/core/src/tbox/src/tbox/object/dictionary.h b/core/src/tbox/src/tbox/object/dictionary.h
new file mode 100644
index 000000000..714e84ded
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/dictionary.h
@@ -0,0 +1,163 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
+
diff --git a/core/src/tbox/src/tbox/object/impl/impl.h b/core/src/tbox/src/tbox/object/impl/impl.h
new file mode 100644
index 000000000..e1f998c1d
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/impl.h
@@ -0,0 +1,36 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
diff --git a/core/src/tbox/src/tbox/object/impl/object.c b/core/src/tbox/src/tbox/object/impl/object.c
new file mode 100644
index 000000000..5e65d18c2
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/object.c
@@ -0,0 +1,86 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
+}
+
diff --git a/core/src/tbox/src/tbox/platform/deprecated/aicp.c b/core/src/tbox/src/tbox/object/impl/object.h
index 0ab676e2c..08c8a1e22 100644
--- a/core/src/tbox/src/tbox/platform/deprecated/aicp.c
+++ b/core/src/tbox/src/tbox/object/impl/object.h
@@ -16,39 +16,43 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
- * @file aicp.c
- * @ingroup platform
+ * @file object.h
+ * @ingroup object
+ *
*/
+#ifndef TB_OBJECT_IMPL_OBJECT_H
+#define TB_OBJECT_IMPL_OBJECT_H
/* //////////////////////////////////////////////////////////////////////////////////////
- * trace
+ * includes
*/
-#define TB_TRACE_MODULE_NAME "platform_aicp"
-#define TB_TRACE_MODULE_DEBUG (1)
+#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
+ * extern
*/
-#include "prefix.h"
-#include "../../asio/deprecated/impl/prefix.h"
+__tb_extern_c_enter__
/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
+ * interfaces
*/
-#if defined(TB_CONFIG_OS_WINDOWS)
-# include "../deprecated/aicp_iocp.c"
- tb_aicp_ptor_impl_t* tb_aicp_ptor_impl_init(tb_aicp_impl_t* aicp)
- {
- return tb_iocp_ptor_init(aicp);
- }
-#else
-# include "../../asio/deprecated/impl/aicp_aiop.c"
- tb_aicp_ptor_impl_t* tb_aicp_ptor_impl_init(tb_aicp_impl_t* aicp)
- {
- return tb_aiop_ptor_init(aicp);
- }
+
+/* init object envirnoment
+ *
+ * @return tb_true or tb_false
+ */
+tb_bool_t tb_object_init_env(tb_noarg_t);
+
+// exit object envirnoment
+tb_void_t tb_object_exit_env(tb_noarg_t);
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_leave__
+
#endif
diff --git a/core/src/tbox/src/tbox/object/impl/prefix.h b/core/src/tbox/src/tbox/object/impl/prefix.h
new file mode 100644
index 000000000..b103d23d6
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/prefix.h
@@ -0,0 +1,77 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
diff --git a/core/src/tbox/src/tbox/object/impl/reader/bin.c b/core/src/tbox/src/tbox/object/impl/reader/bin.c
new file mode 100644
index 000000000..f7f98c9b1
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/reader/bin.c
@@ -0,0 +1,550 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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);
+}
+
diff --git a/core/src/tbox/src/tbox/object/impl/reader/bin.h b/core/src/tbox/src/tbox/object/impl/reader/bin.h
new file mode 100644
index 000000000..433b10f4e
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/reader/bin.h
@@ -0,0 +1,90 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
+
diff --git a/core/src/tbox/src/tbox/object/impl/reader/bplist.c b/core/src/tbox/src/tbox/object/impl/reader/bplist.c
new file mode 100644
index 000000000..c57a164f3
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/reader/bplist.c
@@ -0,0 +1,821 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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);
+}
+
diff --git a/core/src/tbox/src/tbox/object/impl/reader/bplist.h b/core/src/tbox/src/tbox/object/impl/reader/bplist.h
new file mode 100644
index 000000000..6a2735525
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/reader/bplist.h
@@ -0,0 +1,87 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
+
diff --git a/core/src/tbox/src/tbox/object/impl/reader/json.c b/core/src/tbox/src/tbox/object/impl/reader/json.c
new file mode 100644
index 000000000..7ab7489ed
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/reader/json.c
@@ -0,0 +1,607 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
+ }
+ // 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);
+}
+
diff --git a/core/src/tbox/src/tbox/object/impl/reader/json.h b/core/src/tbox/src/tbox/object/impl/reader/json.h
new file mode 100644
index 000000000..75d436392
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/reader/json.h
@@ -0,0 +1,87 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
+
diff --git a/core/src/tbox/src/tbox/object/impl/reader/prefix.h b/core/src/tbox/src/tbox/object/impl/reader/prefix.h
new file mode 100644
index 000000000..9e4f5030a
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/reader/prefix.h
@@ -0,0 +1,88 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
diff --git a/core/src/tbox/src/tbox/object/impl/reader/reader.c b/core/src/tbox/src/tbox/object/impl/reader/reader.c
new file mode 100644
index 000000000..2e530ec27
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/reader/reader.c
@@ -0,0 +1,111 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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;
+}
diff --git a/core/src/tbox/src/tbox/object/impl/reader/reader.h b/core/src/tbox/src/tbox/object/impl/reader/reader.h
new file mode 100644
index 000000000..c7f6d5e26
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/reader/reader.h
@@ -0,0 +1,83 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
diff --git a/core/src/tbox/src/tbox/object/impl/reader/xml.c b/core/src/tbox/src/tbox/object/impl/reader/xml.c
new file mode 100644
index 000000000..afd944a0a
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/reader/xml.c
@@ -0,0 +1,647 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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, "<?xml", 5)? 50 : 0;
+}
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * interfaces
+ */
+tb_oc_reader_t* tb_oc_xml_reader()
+{
+ // the reader
+ static tb_oc_reader_t s_reader = {0};
+
+ // init reader
+ s_reader.read = tb_oc_xml_reader_done;
+ s_reader.probe = tb_oc_xml_reader_probe;
+
+ // init hooker
+ s_reader.hooker = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_str(tb_false), 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, "null", tb_oc_xml_reader_func_null);
+ tb_hash_map_insert(s_reader.hooker, "date", tb_oc_xml_reader_func_date);
+ tb_hash_map_insert(s_reader.hooker, "data", tb_oc_xml_reader_func_data);
+ tb_hash_map_insert(s_reader.hooker, "array", tb_oc_xml_reader_func_array);
+ tb_hash_map_insert(s_reader.hooker, "string", tb_oc_xml_reader_func_string);
+ tb_hash_map_insert(s_reader.hooker, "number", tb_oc_xml_reader_func_number);
+ tb_hash_map_insert(s_reader.hooker, "true", tb_oc_xml_reader_func_boolean);
+ tb_hash_map_insert(s_reader.hooker, "false", tb_oc_xml_reader_func_boolean);
+ tb_hash_map_insert(s_reader.hooker, "dict", tb_oc_xml_reader_func_dictionary);
+
+ // ok
+ return &s_reader;
+}
+tb_bool_t tb_oc_xml_reader_hook(tb_char_t const* type, tb_oc_xml_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_XML);
+ tb_assert_and_check_return_val(reader && reader->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);
+}
+
diff --git a/core/src/tbox/src/tbox/object/impl/reader/xml.h b/core/src/tbox/src/tbox/object/impl/reader/xml.h
new file mode 100644
index 000000000..fb2cefaea
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/reader/xml.h
@@ -0,0 +1,87 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
+
diff --git a/core/src/tbox/src/tbox/object/impl/reader/xplist.c b/core/src/tbox/src/tbox/object/impl/reader/xplist.c
new file mode 100644
index 000000000..1a7230b47
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/reader/xplist.c
@@ -0,0 +1,653 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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);
+
+ // <plist/> ?
+ 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, "<?xml", 5))
+ {
+ // need more data
+ if (!tb_stream_need(stream, &p, 256)) return 5;
+ tb_assert_and_check_return_val(p, 5);
+
+ // is xplist?
+ return tb_strnistr((tb_char_t const*)p, 256, "DOCTYPE plist")? 80 : 10;
+ }
+
+ // ok?
+ return 0;
+}
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * interfaces
+ */
+tb_oc_reader_t* tb_oc_xplist_reader()
+{
+ // the reader
+ static tb_oc_reader_t s_reader = {0};
+
+ // init reader
+ s_reader.read = tb_oc_xplist_reader_done;
+ s_reader.probe = tb_oc_xplist_reader_probe;
+
+ // init hooker
+ s_reader.hooker = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_str(tb_false), 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, "date", tb_oc_xplist_reader_func_date);
+ tb_hash_map_insert(s_reader.hooker, "data", tb_oc_xplist_reader_func_data);
+ tb_hash_map_insert(s_reader.hooker, "array", tb_oc_xplist_reader_func_array);
+ tb_hash_map_insert(s_reader.hooker, "string", tb_oc_xplist_reader_func_string);
+ tb_hash_map_insert(s_reader.hooker, "integer", tb_oc_xplist_reader_func_number);
+ tb_hash_map_insert(s_reader.hooker, "real", tb_oc_xplist_reader_func_number);
+ tb_hash_map_insert(s_reader.hooker, "true", tb_oc_xplist_reader_func_boolean);
+ tb_hash_map_insert(s_reader.hooker, "false", tb_oc_xplist_reader_func_boolean);
+ tb_hash_map_insert(s_reader.hooker, "dict", tb_oc_xplist_reader_func_dictionary);
+
+ // ok
+ return &s_reader;
+}
+tb_bool_t tb_oc_xplist_reader_hook(tb_char_t const* type, tb_oc_xplist_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_XPLIST);
+ tb_assert_and_check_return_val(reader && reader->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);
+}
+
diff --git a/core/src/tbox/src/tbox/object/impl/reader/xplist.h b/core/src/tbox/src/tbox/object/impl/reader/xplist.h
new file mode 100644
index 000000000..4e100cf7b
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/reader/xplist.h
@@ -0,0 +1,87 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
+
diff --git a/core/src/tbox/src/tbox/object/impl/writer/bin.c b/core/src/tbox/src/tbox/object/impl/writer/bin.c
new file mode 100644
index 000000000..d819f1095
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/writer/bin.c
@@ -0,0 +1,429 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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);
+
+ // writ 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);
+
+ // writ 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);
+
+ // writ 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;
+
+ // writ 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);
+
+ // writ 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)
+ {
+ // writ 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);
+
+ // writ 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);
+
+ // writ 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;
+
+ // writ 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);
+
+ // writ type
+ if (!tb_oc_writer_bin_type_size(writer->stream, object->type, (tb_uint64_t)tb_oc_number_type(object))) return tb_false;
+
+ // writ 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);
+
+ // writ 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);
+
+ // writ 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)
+ {
+ // writ key
+ {
+ // exists?
+ tb_size_t index = (tb_size_t)tb_hash_map_get(writer->shash, key);
+ if (index)
+ {
+ // writ 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);
+
+ // writ 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));
+ }
+ }
+
+ // writ val
+ {
+ // exists?
+ tb_size_t index = (tb_size_t)tb_hash_map_get(writer->ohash, val);
+ if (index)
+ {
+ // writ 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);
+
+ // writ 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);
+
+ // writ 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);
+
+ // writ
+ 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);
+}
+
diff --git a/core/src/tbox/src/tbox/object/impl/writer/bin.h b/core/src/tbox/src/tbox/object/impl/writer/bin.h
new file mode 100644
index 000000000..6591ade43
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/writer/bin.h
@@ -0,0 +1,102 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
+
diff --git a/core/src/tbox/src/tbox/object/impl/writer/bplist.c b/core/src/tbox/src/tbox/object/impl/writer/bplist.c
new file mode 100644
index 000000000..9ddf3bee0
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/writer/bplist.c
@@ -0,0 +1,806 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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);
+
+ // writ flag
+ tb_uint8_t flag = bype | (tb_uint8_t)(size < 15 ? size : 0xf);
+ if (!tb_stream_bwrit_u8(writer->stream, flag)) return tb_false;
+
+ // writ 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);
+
+ // writ 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;
+
+ // writ 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
+ // writ 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);
+
+ // writ
+ 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);
+
+ // writ 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;
+
+ // writ 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);
+
+ // writ 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);
+ }
+
+ // writ 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
+ // writ 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
+ // writ 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? writ 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);
+ // writ 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
+ // writ 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;
+ }
+ // writ 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);
+
+ // writ 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);
+
+ // writ 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;
+
+ // writ 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);
+
+ // writ 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);
+ }
+
+ // writ 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);
+
+ // writ magic & version
+ if (!tb_stream_bwrit(stream, (tb_byte_t const*)"bplist00", 8)) break;
+
+ // writ 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);
+
+ // writ 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);
+
+ // writ 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);
+
+ // writ pad, like apple?
+ if (!tb_stream_bwrit(stream, pad, 6)) break;
+
+ // writ 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);
+}
+
diff --git a/core/src/tbox/src/tbox/object/impl/writer/bplist.h b/core/src/tbox/src/tbox/object/impl/writer/bplist.h
new file mode 100644
index 000000000..964dce1e0
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/writer/bplist.h
@@ -0,0 +1,87 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
+
diff --git a/core/src/tbox/src/tbox/object/impl/writer/json.c b/core/src/tbox/src/tbox/object/impl/writer/json.c
new file mode 100644
index 000000000..15996cfb3
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/writer/json.c
@@ -0,0 +1,331 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * 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);
+
+ // writ
+ if (tb_stream_printf(writer->stream, "null") < 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_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);
+
+ // writ
+ if (tb_oc_array_size(object))
+ {
+ // writ 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_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);
+
+ // writ tab
+ if (item_itor != item_head)
+ {
+ 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_tab(writer->stream, writer->deflate, 1)) return tb_false;
+ }
+ else if (!tb_oc_writer_tab(writer->stream, writer->deflate, level + 1)) return tb_false;
+
+ // writ
+ if (!func(writer, item, level + 1)) return tb_false;
+ }
+ }
+
+ // writ 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_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_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);
+
+ // writ
+ 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_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);
+
+ // writ
+ 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;
+ }
+
+ // ok
+ 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);
+
+ // writ
+ 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_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);
+
+ // writ
+ if (tb_oc_dictionary_size(object))
+ {
+ // writ 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);
+
+ // writ tab
+ if (item_itor != item_head)
+ {
+ 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_tab(writer->stream, writer->deflate, 1)) return tb_false;
+ }
+ else if (!tb_oc_writer_tab(writer->stream, writer->deflate, level + 1)) return tb_false;
+
+ // writ key
+ if (tb_stream_printf(writer->stream, "\"%s\":", item->key) < 0) return tb_false;
+
+ // writ 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_tab(writer->stream, writer->deflate, level + 1)) return tb_false;
+ }
+
+ // writ val
+ if (!func(writer, item->val, level + 1)) return tb_false;
+ }
+ }
+
+ // writ 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_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_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);
+
+ // writ
+ 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_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);
+
+ // ok
+ return &s_writer;
+}
+tb_bool_t tb_oc_json_writer_hook(tb_size_t type, tb_oc_json_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_JSON);
+ 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_json_writer_func_t tb_oc_json_writer_func(tb_size_t type)
+{
+ // the writer
+ tb_oc_writer_t* writer = tb_oc_writer_get(TB_OBJECT_FORMAT_JSON);
+ tb_assert_and_check_return_val(writer && writer->hooker, tb_null);
+
+ // the func
+ return (tb_oc_json_writer_func_t)tb_hash_map_get(writer->hooker, (tb_pointer_t)type);
+}
+
diff --git a/core/src/tbox/src/tbox/object/impl/writer/json.h b/core/src/tbox/src/tbox/object/impl/writer/json.h
new file mode 100644
index 000000000..5f280c4ad
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/writer/json.h
@@ -0,0 +1,90 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
+
diff --git a/core/src/tbox/src/tbox/object/impl/writer/prefix.h b/core/src/tbox/src/tbox/object/impl/writer/prefix.h
new file mode 100644
index 000000000..82d3fe377
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/writer/prefix.h
@@ -0,0 +1,114 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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_tab(tb_stream_ref_t stream, tb_bool_t deflate, tb_size_t tab)
+{
+ // writ tab
+ if (!deflate)
+ {
+ while (tab--) if (tb_stream_printf(stream, " ") < 0) return tb_false;
+ }
+
+ // ok
+ return tb_true;
+}
+static __tb_inline__ tb_bool_t tb_oc_writer_newline(tb_stream_ref_t stream, tb_bool_t deflate)
+{
+ // writ newline
+ if (!deflate && tb_stream_printf(stream, __tb_newline__) < 0) return tb_false;
+
+ // ok
+ 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);
+
+ // writ 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("writ: type: %lu, size: %llu", type, size);
+
+ // writ type
+ if (type >= 0xf) if (!tb_stream_bwrit_u8(stream, (tb_uint8_t)type)) return tb_false;
+
+ // writ 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;
+ }
+ }
+
+ // ok
+ return tb_true;
+}
+
+#endif
diff --git a/core/src/tbox/src/tbox/object/impl/writer/writer.c b/core/src/tbox/src/tbox/object/impl/writer/writer.c
new file mode 100644
index 000000000..1b180325b
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/writer/writer.c
@@ -0,0 +1,94 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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);
+}
diff --git a/core/src/tbox/src/tbox/object/impl/writer/writer.h b/core/src/tbox/src/tbox/object/impl/writer/writer.h
new file mode 100644
index 000000000..c0ab46723
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/writer/writer.h
@@ -0,0 +1,86 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
diff --git a/core/src/tbox/src/tbox/object/impl/writer/xml.c b/core/src/tbox/src/tbox/object/impl/writer/xml.c
new file mode 100644
index 000000000..6dcfa1c5b
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/writer/xml.c
@@ -0,0 +1,432 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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);
+
+ // writ
+ if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
+ if (tb_stream_printf(writer->stream, "<null/>") < 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)
+ {
+ // writ beg
+ if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
+ if (tb_stream_printf(writer->stream, "<date>") < 0) return tb_false;
+
+ // writ 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;
+ }
+
+ // writ end
+ if (tb_stream_printf(writer->stream, "</date>") < 0) return tb_false;
+ if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
+ }
+ else
+ {
+ // writ
+ if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
+ if (tb_stream_printf(writer->stream, "<date/>") < 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))
+ {
+ // writ beg
+ if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
+ if (tb_stream_printf(writer->stream, "<data>") < 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);
+
+ // writ 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);
+
+ // writ newline
+ if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
+
+ // writ end
+ if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
+ if (tb_stream_printf(writer->stream, "</data>") < 0) return tb_false;
+ if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
+ }
+ else
+ {
+ // writ
+ if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
+ if (tb_stream_printf(writer->stream, "<data/>") < 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);
+
+ // writ
+ if (tb_oc_array_size(object))
+ {
+ // writ beg
+ if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
+ if (tb_stream_printf(writer->stream, "<array>") < 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);
+
+ // writ
+ if (!func(writer, item, level + 1)) return tb_false;
+ }
+ }
+
+ // writ end
+ if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
+ if (tb_stream_printf(writer->stream, "</array>") < 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, "<array/>") < 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);
+
+ // writ
+ 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, "<string>%s</string>", tb_oc_string_cstr(object)) < 0) return tb_false;
+ }
+ else if (tb_stream_printf(writer->stream, "<string/>") < 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);
+
+ // writ
+ 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, "<number>%llu</number>", 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, "<number>%lld</number>", 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, "<number>%u</number>", 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, "<number>%d</number>", 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, "<number>%u</number>", 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, "<number>%d</number>", 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, "<number>%u</number>", 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, "<number>%d</number>", 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, "<number>%f</number>", 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, "<number>%lf</number>", 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);
+
+ // writ
+ 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);
+
+ // writ
+ if (tb_oc_dictionary_size(object))
+ {
+ // writ beg
+ if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
+ if (tb_stream_printf(writer->stream, "<dict>") < 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);
+
+ // writ key
+ if (!tb_oc_writer_tab(writer->stream, writer->deflate, level + 1)) return tb_false;
+ if (tb_stream_printf(writer->stream, "<key>%s</key>", item->key) < 0) return tb_false;
+ if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
+
+ // writ val
+ if (!func(writer, item->val, level + 1)) return tb_false;
+ }
+ }
+
+ // writ end
+ if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
+ if (tb_stream_printf(writer->stream, "</dict>") < 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, "<dict/>") < 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);
+
+ // writ xml header
+ if (tb_stream_printf(stream, "<?xml version=\"2.0\" encoding=\"utf-8\"?>") < 0) return -1;
+ if (!tb_oc_writer_newline(stream, deflate)) return -1;
+
+ // writ
+ 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);
+}
+
diff --git a/core/src/tbox/src/tbox/object/impl/writer/xml.h b/core/src/tbox/src/tbox/object/impl/writer/xml.h
new file mode 100644
index 000000000..98d2ba8c6
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/writer/xml.h
@@ -0,0 +1,90 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
+
diff --git a/core/src/tbox/src/tbox/object/impl/writer/xplist.c b/core/src/tbox/src/tbox/object/impl/writer/xplist.c
new file mode 100644
index 000000000..f05fe587b
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/writer/xplist.c
@@ -0,0 +1,425 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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)
+ {
+ // writ beg
+ if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
+ if (tb_stream_printf(writer->stream, "<date>") < 0) return tb_false;
+
+ // writ 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;
+ }
+
+ // writ end
+ if (tb_stream_printf(writer->stream, "</date>") < 0) return tb_false;
+ if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
+ }
+ else
+ {
+ // writ
+ if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
+ if (tb_stream_printf(writer->stream, "<date/>") < 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))
+ {
+ // writ beg
+ if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
+ if (tb_stream_printf(writer->stream, "<data>") < 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);
+
+ // writ 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);
+
+ // writ end
+ if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
+ if (tb_stream_printf(writer->stream, "</data>") < 0) return tb_false;
+ if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
+ }
+ else
+ {
+ // writ
+ if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
+ if (tb_stream_printf(writer->stream, "<data>") < 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, "</data>") < 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);
+
+ // writ
+ if (tb_oc_array_size(object))
+ {
+ // writ beg
+ if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
+ if (tb_stream_printf(writer->stream, "<array>") < 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);
+
+ // writ
+ if (!func(writer, item, level + 1)) return tb_false;
+ }
+ }
+
+ // writ end
+ if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
+ if (tb_stream_printf(writer->stream, "</array>") < 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, "<array/>") < 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);
+
+ // writ
+ 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, "<string>%s</string>", tb_oc_string_cstr(object)) < 0) return tb_false;
+ }
+ else if (tb_stream_printf(writer->stream, "<string/>") < 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);
+
+ // writ
+ 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, "<integer>%llu</integer>", 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, "<integer>%lld</integer>", 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, "<integer>%u</integer>", 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, "<integer>%d</integer>", 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, "<integer>%u</integer>", 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, "<integer>%d</integer>", 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, "<integer>%u</integer>", 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, "<integer>%d</integer>", 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, "<real>%f</real>", 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, "<real>%lf</real>", 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);
+
+ // writ
+ 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);
+
+ // writ
+ if (tb_oc_dictionary_size(object))
+ {
+ // writ beg
+ if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
+ if (tb_stream_printf(writer->stream, "<dict>") < 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);
+
+ // writ key
+ tb_oc_writer_tab(writer->stream, writer->deflate, level + 1);
+ if (tb_stream_printf(writer->stream, "<key>%s</key>", item->key) < 0) return tb_false;
+ if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false;
+
+ // writ val
+ if (!func(writer, item->val, level + 1)) return tb_false;
+ }
+ }
+
+ // writ end
+ if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false;
+ if (tb_stream_printf(writer->stream, "</dict>") < 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, "<dict/>") < 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);
+
+ // writ xplist header
+ if (tb_stream_printf(stream, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>") < 0) return -1;
+ if (!tb_oc_writer_newline(stream, deflate)) return -1;
+ if (tb_stream_printf(stream, "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">") < 0) return -1;
+ if (!tb_oc_writer_newline(stream, deflate)) return -1;
+ if (tb_stream_printf(stream, "<plist version=\"1.0\">") < 0) return -1;
+ if (!tb_oc_writer_newline(stream, deflate)) return -1;
+
+ // writ
+ if (!func(&writer, object, 0)) return -1;
+
+ // writ xplist end
+ if (tb_stream_printf(stream, "</plist>") < 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);
+}
+
diff --git a/core/src/tbox/src/tbox/object/impl/writer/xplist.h b/core/src/tbox/src/tbox/object/impl/writer/xplist.h
new file mode 100644
index 000000000..41cdffdd7
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/impl/writer/xplist.h
@@ -0,0 +1,90 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
+
diff --git a/core/src/tbox/src/tbox/object/null.c b/core/src/tbox/src/tbox/object/null.c
new file mode 100644
index 000000000..9efd5652b
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/null.c
@@ -0,0 +1,70 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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;
+}
+
diff --git a/core/src/tbox/src/tbox/object/null.h b/core/src/tbox/src/tbox/object/null.h
new file mode 100644
index 000000000..9edbe1cd7
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/null.h
@@ -0,0 +1,55 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
+
diff --git a/core/src/tbox/src/tbox/object/number.c b/core/src/tbox/src/tbox/object/number.c
new file mode 100644
index 000000000..302d1c973
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/number.c
@@ -0,0 +1,683 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
diff --git a/core/src/tbox/src/tbox/object/number.h b/core/src/tbox/src/tbox/object/number.h
new file mode 100644
index 000000000..15bdce7e1
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/number.h
@@ -0,0 +1,334 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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 object 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 object 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 object 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 object 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 object 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 object 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 object 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 object 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 object 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 object 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 object 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 object 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 object 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 object 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 object 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 object 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 object 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 object 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 object 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 object 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 object 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
+
diff --git a/core/src/tbox/src/tbox/object/object.c b/core/src/tbox/src/tbox/object/object.c
new file mode 100644
index 000000000..9c35d0931
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/object.c
@@ -0,0 +1,405 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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;
+}
+
diff --git a/core/src/tbox/src/tbox/object/object.h b/core/src/tbox/src/tbox/object/object.h
new file mode 100644
index 000000000..bc10a40bd
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/object.h
@@ -0,0 +1,255 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
+ *
+ * <pre>
+ *
+ 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!"
+
+ *
+ * </pre>
+ *
+ * @param object the object
+ * @param path the object path
+ * @param bmacro enable macro(like "$.path")?
+ *
+ * <code>
+ * 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));
+ * }
+ * <endcode>
+ *
+ *
+ * @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
+
diff --git a/core/src/tbox/src/tbox/object/prefix.h b/core/src/tbox/src/tbox/object/prefix.h
new file mode 100644
index 000000000..ea8beb979
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/prefix.h
@@ -0,0 +1,104 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
diff --git a/core/src/tbox/src/tbox/object/string.c b/core/src/tbox/src/tbox/object/string.c
new file mode 100644
index 000000000..adb50c4a2
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/string.c
@@ -0,0 +1,232 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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);
+}
+
diff --git a/core/src/tbox/src/tbox/object/string.h b/core/src/tbox/src/tbox/object/string.h
new file mode 100644
index 000000000..0f39493c4
--- /dev/null
+++ b/core/src/tbox/src/tbox/object/string.h
@@ -0,0 +1,90 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, 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
+
diff --git a/core/src/tbox/src/tbox/platform/addrinfo.c b/core/src/tbox/src/tbox/platform/addrinfo.c
index 989ca65b1..424f6002c 100644
--- a/core/src/tbox/src/tbox/platform/addrinfo.c
+++ b/core/src/tbox/src/tbox/platform/addrinfo.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file addrinfo.c
diff --git a/core/src/tbox/src/tbox/platform/addrinfo.h b/core/src/tbox/src/tbox/platform/addrinfo.h
index aa7bbb2d8..19bbf661e 100644
--- a/core/src/tbox/src/tbox/platform/addrinfo.h
+++ b/core/src/tbox/src/tbox/platform/addrinfo.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file addrinfo.h
diff --git a/core/src/tbox/src/tbox/platform/android/android.c b/core/src/tbox/src/tbox/platform/android/android.c
index 091fa2955..e7e316c8b 100644
--- a/core/src/tbox/src/tbox/platform/android/android.c
+++ b/core/src/tbox/src/tbox/platform/android/android.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file android.c
diff --git a/core/src/tbox/src/tbox/platform/android/android.h b/core/src/tbox/src/tbox/platform/android/android.h
index 905f1d5bb..c7dad652b 100644
--- a/core/src/tbox/src/tbox/platform/android/android.h
+++ b/core/src/tbox/src/tbox/platform/android/android.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file android.h
diff --git a/core/src/tbox/src/tbox/platform/android/backtrace.c b/core/src/tbox/src/tbox/platform/android/backtrace.c
index f2bef22b7..0699eda8a 100644
--- a/core/src/tbox/src/tbox/platform/android/backtrace.c
+++ b/core/src/tbox/src/tbox/platform/android/backtrace.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file backtrace.c
diff --git a/core/src/tbox/src/tbox/platform/android/directory.c b/core/src/tbox/src/tbox/platform/android/directory.c
index bd2a29d4b..ef56a18ec 100644
--- a/core/src/tbox/src/tbox/platform/android/directory.c
+++ b/core/src/tbox/src/tbox/platform/android/directory.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file directory.c
diff --git a/core/src/tbox/src/tbox/platform/android/dns.c b/core/src/tbox/src/tbox/platform/android/dns.c
index aba39df7c..d7c6e47e1 100644
--- a/core/src/tbox/src/tbox/platform/android/dns.c
+++ b/core/src/tbox/src/tbox/platform/android/dns.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file dns.c
diff --git a/core/src/tbox/src/tbox/platform/android/prefix.h b/core/src/tbox/src/tbox/platform/android/prefix.h
index a3b9a9f44..d9b3956aa 100644
--- a/core/src/tbox/src/tbox/platform/android/prefix.h
+++ b/core/src/tbox/src/tbox/platform/android/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/platform/android/print.c b/core/src/tbox/src/tbox/platform/android/print.c
index 8c2eefec6..b0cb1ef34 100644
--- a/core/src/tbox/src/tbox/platform/android/print.c
+++ b/core/src/tbox/src/tbox/platform/android/print.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file print.c
diff --git a/core/src/tbox/src/tbox/platform/arch/arm/frame.h b/core/src/tbox/src/tbox/platform/arch/arm/frame.h
index 7d84bc33c..9812834fa 100644
--- a/core/src/tbox/src/tbox/platform/arch/arm/frame.h
+++ b/core/src/tbox/src/tbox/platform/arch/arm/frame.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file frame.h
diff --git a/core/src/tbox/src/tbox/platform/arch/arm/prefix.h b/core/src/tbox/src/tbox/platform/arch/arm/prefix.h
index 442d92602..591cb18fd 100644
--- a/core/src/tbox/src/tbox/platform/arch/arm/prefix.h
+++ b/core/src/tbox/src/tbox/platform/arch/arm/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/platform/arch/arm64/prefix.h b/core/src/tbox/src/tbox/platform/arch/arm64/prefix.h
index 0eb321e2b..52caa82a0 100644
--- a/core/src/tbox/src/tbox/platform/arch/arm64/prefix.h
+++ b/core/src/tbox/src/tbox/platform/arch/arm64/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/platform/arch/atomic.h b/core/src/tbox/src/tbox/platform/arch/atomic.h
index 9ec0f99d4..c1323b506 100644
--- a/core/src/tbox/src/tbox/platform/arch/atomic.h
+++ b/core/src/tbox/src/tbox/platform/arch/atomic.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file atomic.h
diff --git a/core/src/tbox/src/tbox/platform/arch/barrier.h b/core/src/tbox/src/tbox/platform/arch/barrier.h
index 21037035f..c2f14115f 100644
--- a/core/src/tbox/src/tbox/platform/arch/barrier.h
+++ b/core/src/tbox/src/tbox/platform/arch/barrier.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file barrier.h
diff --git a/core/src/tbox/src/tbox/platform/arch/context.S b/core/src/tbox/src/tbox/platform/arch/context.S
index c45025a0a..b6c2c5d27 100644
--- a/core/src/tbox/src/tbox/platform/arch/context.S
+++ b/core/src/tbox/src/tbox/platform/arch/context.S
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file context.S
diff --git a/core/src/tbox/src/tbox/platform/arch/frame.h b/core/src/tbox/src/tbox/platform/arch/frame.h
index 2a0e16e77..fa778c32a 100644
--- a/core/src/tbox/src/tbox/platform/arch/frame.h
+++ b/core/src/tbox/src/tbox/platform/arch/frame.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file frame.h
diff --git a/core/src/tbox/src/tbox/platform/arch/mips/prefix.h b/core/src/tbox/src/tbox/platform/arch/mips/prefix.h
index d784b6573..23f7356b8 100644
--- a/core/src/tbox/src/tbox/platform/arch/mips/prefix.h
+++ b/core/src/tbox/src/tbox/platform/arch/mips/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/platform/arch/prefix.h b/core/src/tbox/src/tbox/platform/arch/prefix.h
index c55a5e9c6..52c11e7aa 100644
--- a/core/src/tbox/src/tbox/platform/arch/prefix.h
+++ b/core/src/tbox/src/tbox/platform/arch/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/platform/arch/x64/atomic.h b/core/src/tbox/src/tbox/platform/arch/x64/atomic.h
index 69ad484d8..1f742820a 100644
--- a/core/src/tbox/src/tbox/platform/arch/x64/atomic.h
+++ b/core/src/tbox/src/tbox/platform/arch/x64/atomic.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file atomic.h
diff --git a/core/src/tbox/src/tbox/platform/arch/x64/barrier.h b/core/src/tbox/src/tbox/platform/arch/x64/barrier.h
index 9972c1915..e67b10963 100644
--- a/core/src/tbox/src/tbox/platform/arch/x64/barrier.h
+++ b/core/src/tbox/src/tbox/platform/arch/x64/barrier.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file barrier.h
diff --git a/core/src/tbox/src/tbox/platform/arch/x64/context.S b/core/src/tbox/src/tbox/platform/arch/x64/context.S
index 599ff5ee3..b3a9e6db3 100644
--- a/core/src/tbox/src/tbox/platform/arch/x64/context.S
+++ b/core/src/tbox/src/tbox/platform/arch/x64/context.S
@@ -37,16 +37,16 @@
/* make context (refer to boost.context)
*
- * -------------------------------------------------------------------------------
- * stackdata: | | context |||||||
- * -------------------------------------------------------------------------|-----
+ * ------------------------------------------------------------------------------------------
+ * stackdata: | | context |||||||
+ * ------------------------------------------------------------------------------------|-----
* (16-align for macosx)
*
- *
- * -------------------------------------------------------------------------------
- * context: | r12 | r13 | r14 | r15 | rbx | rbp | rip | end | args | padding ...
- * -------------------------------------------------------------------------------
- * 0 8 16 24 32 40 48 56 |
+ * 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
@@ -68,18 +68,41 @@ function(tb_context_make)
andq %r8, %rax
// reserve space for context-data on context-stack
- leaq -64(%rax), %rax
+ leaq -56(%rax), %rax
+
+ // context.rbx = func
+ movq %rdx, 32(%rax)
- // context.rip = func
- movq %rdx, 48(%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, 56(%rax)
+ 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
@@ -129,17 +152,14 @@ function(tb_context_jump)
// return from-context(context: rax, priv: rdx) from jump
movq %rsi, %rdx
- // pass old-context(context: rdi, priv: rsi) argument to the context function
- movq %rax, %rdi
-
/* jump to the return or function address(rip)
*
- * -------------------------------
- * context: .. | end | args | padding ... |
- * -------------------------------
- * 0 8
- * | |
- * rsp 16-align for macosx
+ * ---------------------
+ * context: .. | args | padding ... |
+ * ---------------------
+ * 0 8
+ * | 16-align for macosx
+ * rsp
*/
jmp *%r8
diff --git a/core/src/tbox/src/tbox/platform/arch/x64/context.asm b/core/src/tbox/src/tbox/platform/arch/x64/context.asm
index 47fea8353..1b1e7536d 100644
--- a/core/src/tbox/src/tbox/platform/arch/x64/context.asm
+++ b/core/src/tbox/src/tbox/platform/arch/x64/context.asm
@@ -58,15 +58,15 @@ extern _exit:proc
; ---------------------------------------
; | r12 | r13 | r14 | r15 |
; ---------------------------------------
-; 32 40 48 56 --------------------------------------------------------
-; | |
-; | func __end arguments retval(from)
-; -----------------------------------------------------------------------------------------------------------------------------------
-; | rdi | rsi | rbx | rbp | retval(saved) | rip | end | unused | context(unused) | priv(unused) | padding |
-; -----------------------------------------------------------------------------------------------------------------------------------
-; 64 72 80 88 96 104 112 120 128 136
-; | |
-; | 16-align
+; 32 40 48 56 ---------------------------------------
+; | |
+; func __end | __entry arguments retval(from)
+; --------------------------------------------------------------------------------------------------------------------------
+; | rdi | rsi | rbx | rbp | retval(saved) | rip | unused | context(unused) | priv(unused) | padding |
+; --------------------------------------------------------------------------------------------------------------------------
+; 64 72 80 88 96 104 112 120 128 136
+; |
+; | 16-align
; |
; rsp when jump to function
;
@@ -94,10 +94,10 @@ tb_context_make proc frame
and rax, -16
; reserve space for context-data on context-stack
- sub rax, 120
+ sub rax, 112
- ; context.rip = func
- mov [rax + 104], r8
+ ; context.rbx = func
+ mov [rax + 80], r8
; save bottom address of context stack as 'limit'
mov [rax + 16], rcx
@@ -120,13 +120,36 @@ tb_context_make proc frame
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 + 112], rcx
+ 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
diff --git a/core/src/tbox/src/tbox/platform/arch/x64/frame.h b/core/src/tbox/src/tbox/platform/arch/x64/frame.h
index 163ef71f2..f17e3bfc1 100644
--- a/core/src/tbox/src/tbox/platform/arch/x64/frame.h
+++ b/core/src/tbox/src/tbox/platform/arch/x64/frame.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file frame.h
diff --git a/core/src/tbox/src/tbox/platform/arch/x64/prefix.h b/core/src/tbox/src/tbox/platform/arch/x64/prefix.h
index 48da70eb9..5751d42fd 100644
--- a/core/src/tbox/src/tbox/platform/arch/x64/prefix.h
+++ b/core/src/tbox/src/tbox/platform/arch/x64/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/platform/arch/x86/atomic.h b/core/src/tbox/src/tbox/platform/arch/x86/atomic.h
index 6583ae5f7..2ac0b9df7 100644
--- a/core/src/tbox/src/tbox/platform/arch/x86/atomic.h
+++ b/core/src/tbox/src/tbox/platform/arch/x86/atomic.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file atomic.h
diff --git a/core/src/tbox/src/tbox/platform/arch/x86/barrier.h b/core/src/tbox/src/tbox/platform/arch/x86/barrier.h
index 5263f83a3..141a440f7 100644
--- a/core/src/tbox/src/tbox/platform/arch/x86/barrier.h
+++ b/core/src/tbox/src/tbox/platform/arch/x86/barrier.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file barrier.h
diff --git a/core/src/tbox/src/tbox/platform/arch/x86/context.S b/core/src/tbox/src/tbox/platform/arch/x86/context.S
index 9fcbc5095..8b7ab8af9 100644
--- a/core/src/tbox/src/tbox/platform/arch/x86/context.S
+++ b/core/src/tbox/src/tbox/platform/arch/x86/context.S
@@ -52,12 +52,12 @@
* (16-align for macosx)
*
*
- * func __end from
- * ------------------------------------------------------------------------------------------
- * context: | edi | esi | ebx | ebp | eip | end | context | priv | padding |
- * ------------------------------------------------------------------------------------------
+ * 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
@@ -81,21 +81,57 @@ function(tb_context_make)
andl $-16, %eax
// reserve space for context-data on context-stack
- leal -24(%eax), %eax
+ leal -20(%eax), %eax
- // context.eip = func
+ /* context.ebx = func
+ *
+ * @note ebp will be affected only when enter into the context function first
+ */
movl 12(%esp), %edx
- movl %edx, 16(%eax)
+ movl %edx, 8(%eax)
- // context.ebp = the address of label __end
+ // context.eip = the address of label __entry
call 1f
1: popl %ecx
- addl $__end - 1b, %ecx
- movl %ecx, 20(%eax)
+ 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
@@ -148,19 +184,15 @@ function(tb_context_jump)
// return from-context(context: eax, priv: edx) from jump
// ...
- // pass old-context(context: eax, priv: edx) arguments to the context function
- movl %eax, 4(%esp)
- movl %edx, 8(%esp)
-
/* jump to the return or function address(eip)
*
*
- * old-context
- * ------------------------------------------
- * context: .. | end | context | priv | padding |
- * ------------------------------------------
+ * old-context
+ * --------------------------------
+ * context: .. | context | priv | padding |
+ * --------------------------------
* 0 4 arguments
- * | |
+ * |
* esp 16-align for macosx
* (now)
*/
diff --git a/core/src/tbox/src/tbox/platform/arch/x86/context.asm b/core/src/tbox/src/tbox/platform/arch/x86/context.asm
index 19cc53c8b..6e636f68a 100644
--- a/core/src/tbox/src/tbox/platform/arch/x86/context.asm
+++ b/core/src/tbox/src/tbox/platform/arch/x86/context.asm
@@ -117,11 +117,6 @@ _exit proto, value:sdword
; make 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
-;
-;
; -----------------------------------------------------------------------------------------
; stackdata: | | context |||||||
; -----------------------------------------------------------------------------------|-----
@@ -129,18 +124,18 @@ _exit proto, value:sdword
;
;
; -------------------------------------------------
-; context: | fiber | dealloc | limit | base | seh | ------------------------------------------
-; ------------------------------------------------- |
-; 0 4 8 12 16 | seh chain for context function
-; |
-; |
-; func __end arguments(from) \|/
+; 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 | end | context | priv | unused | seh.prev (0xffffffff) | seh.handler | padding |
+; | 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
+; 20 24 28 32 36 40 44 48 52 56 60
+; |
+; | 16-align
; |
; esp when jump to function
;
@@ -165,7 +160,7 @@ tb_context_make proc
and eax, -16
; reserve space for context-data on context-stack
- lea eax, [eax - 44]
+ lea eax, [eax - 40]
; save top address of context stack as 'base'
mov [eax + 12], ecx
@@ -177,13 +172,21 @@ tb_context_make proc
; save bottom address of context-stack as 'dealloction stack'
mov [eax + 4], ecx
- ; context.eip = func
+ ; 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.end = the address of label __end
+ ; context.ebp = the address of label __end
mov ecx, __end
- mov [eax + 40], ecx
+ mov [eax + 32], ecx
; install seh chain when enter into the context function
;
@@ -228,6 +231,29 @@ __found:
; 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)
@@ -329,20 +355,16 @@ tb_context_jump proc
;
mov edx, [eax + 44]
- ; pass old-context(context: eax, priv: edx) arguments to the context function
- mov [esp + 4], eax
- mov [esp + 8], edx
-
; jump to the return or function address(eip)
;
;
- ; old-context
- ; ------------------------------------------
- ; context: .. | end | context | priv | ... |
- ; ------------------------------------------
- ; 0 4 arguments
- ; | |
- ; esp 16-align
+ ; old-context
+ ; --------------------------------
+ ; context: .. | context | priv | ... |
+ ; --------------------------------
+ ; 0 arguments
+ ; |
+ ; esp
; (now)
;;
jmp ecx
diff --git a/core/src/tbox/src/tbox/platform/arch/x86/frame.h b/core/src/tbox/src/tbox/platform/arch/x86/frame.h
index 5a50383d6..d0893d35f 100644
--- a/core/src/tbox/src/tbox/platform/arch/x86/frame.h
+++ b/core/src/tbox/src/tbox/platform/arch/x86/frame.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file frame.h
diff --git a/core/src/tbox/src/tbox/platform/arch/x86/prefix.h b/core/src/tbox/src/tbox/platform/arch/x86/prefix.h
index 5e55325ac..42c7ae33f 100644
--- a/core/src/tbox/src/tbox/platform/arch/x86/prefix.h
+++ b/core/src/tbox/src/tbox/platform/arch/x86/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/platform/atomic.h b/core/src/tbox/src/tbox/platform/atomic.h
index 3fcb25e46..8af240280 100644
--- a/core/src/tbox/src/tbox/platform/atomic.h
+++ b/core/src/tbox/src/tbox/platform/atomic.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file atomic.h
diff --git a/core/src/tbox/src/tbox/platform/atomic64.c b/core/src/tbox/src/tbox/platform/atomic64.c
index ec3760958..f6830ba27 100644
--- a/core/src/tbox/src/tbox/platform/atomic64.c
+++ b/core/src/tbox/src/tbox/platform/atomic64.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file atomic64.c
diff --git a/core/src/tbox/src/tbox/platform/atomic64.h b/core/src/tbox/src/tbox/platform/atomic64.h
index cee148961..2a581a14d 100644
--- a/core/src/tbox/src/tbox/platform/atomic64.h
+++ b/core/src/tbox/src/tbox/platform/atomic64.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file atomic64.h
diff --git a/core/src/tbox/src/tbox/platform/backtrace.c b/core/src/tbox/src/tbox/platform/backtrace.c
index 375b0732e..2a4565c7b 100644
--- a/core/src/tbox/src/tbox/platform/backtrace.c
+++ b/core/src/tbox/src/tbox/platform/backtrace.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file backtrace.c
diff --git a/core/src/tbox/src/tbox/platform/backtrace.h b/core/src/tbox/src/tbox/platform/backtrace.h
index c93cc909e..99d3a39de 100644
--- a/core/src/tbox/src/tbox/platform/backtrace.h
+++ b/core/src/tbox/src/tbox/platform/backtrace.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file backtrace.h
diff --git a/core/src/tbox/src/tbox/platform/barrier.h b/core/src/tbox/src/tbox/platform/barrier.h
index d8ac67740..321f13e69 100644
--- a/core/src/tbox/src/tbox/platform/barrier.h
+++ b/core/src/tbox/src/tbox/platform/barrier.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file barrier.h
diff --git a/core/src/tbox/src/tbox/platform/cache_time.c b/core/src/tbox/src/tbox/platform/cache_time.c
index f124d4cdd..58aec2350 100644
--- a/core/src/tbox/src/tbox/platform/cache_time.c
+++ b/core/src/tbox/src/tbox/platform/cache_time.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file cache_time.c
diff --git a/core/src/tbox/src/tbox/platform/cache_time.h b/core/src/tbox/src/tbox/platform/cache_time.h
index 1c33b806f..8c63b0ada 100644
--- a/core/src/tbox/src/tbox/platform/cache_time.h
+++ b/core/src/tbox/src/tbox/platform/cache_time.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file cache_time.h
diff --git a/core/src/tbox/src/tbox/platform/compiler/gcc/atomic.h b/core/src/tbox/src/tbox/platform/compiler/gcc/atomic.h
index 78d21e8e3..df14be328 100644
--- a/core/src/tbox/src/tbox/platform/compiler/gcc/atomic.h
+++ b/core/src/tbox/src/tbox/platform/compiler/gcc/atomic.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file atomic.h
diff --git a/core/src/tbox/src/tbox/platform/compiler/gcc/atomic64.h b/core/src/tbox/src/tbox/platform/compiler/gcc/atomic64.h
index 0c6364a64..f5db47e1b 100644
--- a/core/src/tbox/src/tbox/platform/compiler/gcc/atomic64.h
+++ b/core/src/tbox/src/tbox/platform/compiler/gcc/atomic64.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file atomic64.h
diff --git a/core/src/tbox/src/tbox/platform/compiler/gcc/barrier.h b/core/src/tbox/src/tbox/platform/compiler/gcc/barrier.h
index 355b13539..67b3ec943 100644
--- a/core/src/tbox/src/tbox/platform/compiler/gcc/barrier.h
+++ b/core/src/tbox/src/tbox/platform/compiler/gcc/barrier.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file barrier.h
diff --git a/core/src/tbox/src/tbox/platform/compiler/gcc/prefix.h b/core/src/tbox/src/tbox/platform/compiler/gcc/prefix.h
index d7c2e8f94..e08305427 100644
--- a/core/src/tbox/src/tbox/platform/compiler/gcc/prefix.h
+++ b/core/src/tbox/src/tbox/platform/compiler/gcc/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/platform/compiler/prefix.h b/core/src/tbox/src/tbox/platform/compiler/prefix.h
index 4466b8e95..7f1a0bda6 100644
--- a/core/src/tbox/src/tbox/platform/compiler/prefix.h
+++ b/core/src/tbox/src/tbox/platform/compiler/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/platform/context.c b/core/src/tbox/src/tbox/platform/context.c
index d6781c735..932b37cd7 100644
--- a/core/src/tbox/src/tbox/platform/context.c
+++ b/core/src/tbox/src/tbox/platform/context.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file context.c
diff --git a/core/src/tbox/src/tbox/platform/context.h b/core/src/tbox/src/tbox/platform/context.h
index 13fd69979..65e9ad4f7 100644
--- a/core/src/tbox/src/tbox/platform/context.h
+++ b/core/src/tbox/src/tbox/platform/context.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file context.h
diff --git a/core/src/tbox/src/tbox/platform/deprecated/aicp_iocp.c b/core/src/tbox/src/tbox/platform/deprecated/aicp_iocp.c
deleted file mode 100644
index 5343d2e68..000000000
--- a/core/src/tbox/src/tbox/platform/deprecated/aicp_iocp.c
+++ /dev/null
@@ -1,2729 +0,0 @@
-/*!The Treasure Box Library
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
- *
- * @author ruki
- * @file aicp_iocp.c
- *
- */
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
- */
-#include "prefix.h"
-#include "../windows/interface/interface.h"
-#include "../posix/sockaddr.h"
-#include "../windows/ntstatus.h"
-#include "../windows/socket_pool.h"
-#include "../ltimer.h"
-#include "../posix/sockaddr.h"
-#include "../../asio/deprecated/asio.h"
-#include "../../asio/deprecated/impl/prefix.h"
-#include "../../libc/libc.h"
-#include "../../math/math.h"
-#include "../../utils/utils.h"
-#include "../../memory/memory.h"
-#include "../../platform/platform.h"
-#include "../../algorithm/algorithm.h"
-#include "../../container/container.h"
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * macros
- */
-
-// update connect context
-#ifndef SO_UPDATE_CONNECT_CONTEXT
-# define SO_UPDATE_CONNECT_CONTEXT (0x7010)
-#endif
-
-// update accept context
-#ifndef SO_UPDATE_ACCEPT_CONTEXT
-# define SO_UPDATE_ACCEPT_CONTEXT (0x700B)
-#endif
-
-// enable socket pool? only for the accepted socket
-#define TB_IOCP_SOCKET_POOL_ENABLE
-
-// the olap list maxn for GetQueuedCompletionStatusEx
-#ifdef __tb_small__
-# define TB_IOCP_OLAP_LIST_MAXN (63)
-#else
-# define TB_IOCP_OLAP_LIST_MAXN (255)
-#endif
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * types
- */
-
-// the iocp func type
-typedef struct __tb_iocp_func_t
-{
- // the AcceptEx func
- tb_mswsock_AcceptEx_t AcceptEx;
-
- // the ConnectEx func
- tb_mswsock_ConnectEx_t ConnectEx;
-
- // the DisconnectEx func
- tb_mswsock_DisconnectEx_t DisconnectEx;
-
- // the TransmitFile func
- tb_mswsock_TransmitFile_t TransmitFile;
-
- // the GetAcceptExSockaddrs func
- tb_mswsock_GetAcceptExSockaddrs_t GetAcceptExSockaddrs;
-
- // the GetQueuedCompletionStatusEx func
- tb_kernel32_GetQueuedCompletionStatusEx_t GetQueuedCompletionStatusEx;
-
- // WSAGetLastError
- tb_ws2_32_WSAGetLastError_t WSAGetLastError;
-
- // WSASend
- tb_ws2_32_WSASend_t WSASend;
-
- // WSARecv
- tb_ws2_32_WSARecv_t WSARecv;
-
- // WSASendTo
- tb_ws2_32_WSASendTo_t WSASendTo;
-
- // WSARecvFrom
- tb_ws2_32_WSARecvFrom_t WSARecvFrom;
-
- // bind
- tb_ws2_32_bind_t bind;
-
-}tb_iocp_func_t;
-
-// the iocp impl type
-typedef struct __tb_iocp_ptor_impl_t
-{
- // the ptor base
- tb_aicp_ptor_impl_t base;
-
- // the i/o completion port
- HANDLE port;
-
- // the timer for task
- tb_timer_ref_t timer;
-
- // the low precision timer for timeout
- tb_ltimer_ref_t ltimer;
-
- // the post loop
- tb_thread_ref_t loop;
-
- // the post wait
- tb_event_ref_t wait;
-
- /* the aice post
- *
- * index: 0: higher priority for conn, acpt and task
- * index: 1: lower priority for io aice
- */
- tb_queue_ref_t post[2];
-
- // the killing aico list
- tb_vector_ref_t kill;
-
- // the post lock
- tb_spinlock_t lock;
-
- // the post func
- tb_iocp_func_t func;
-
-}tb_iocp_ptor_impl_t;
-
-// the iocp olap type
-typedef struct __tb_iocp_olap_t
-{
- // the base
- OVERLAPPED base;
-
- /* the aice
- *
- * @note (WSABUF*)&aice.u.xxxx must be aligned
- */
- __tb_cpu_aligned__ tb_aice_t aice;
-
-}tb_iocp_olap_t;
-
-// the iocp aico type
-typedef __tb_cpu_aligned__ struct __tb_iocp_aico_t
-{
- // the base
- tb_aico_impl_t base;
-
- // the impl
- tb_iocp_ptor_impl_t* impl;
-
- // the olap
- __tb_cpu_aligned__ tb_iocp_olap_t olap;
-
- // the task
- tb_handle_t task;
-
- // the address data for acpt, urecv and urecvv
- tb_cpointer_t addr;
-
- // is ltimer?
- tb_uint8_t bltimer : 1;
-
- // DisconnectEx it
- tb_uint8_t bDisconnectEx : 1;
-
-}tb_iocp_aico_t;
-
-// the iocp loop type
-typedef struct __tb_iocp_loop_t
-{
- // the self
- tb_size_t self;
-
- // the olap list
- tb_OVERLAPPED_ENTRY_t list[TB_IOCP_OLAP_LIST_MAXN];
-
- // the aice spak
- tb_queue_ref_t spak;
-
-}tb_iocp_loop_t;
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * timeout
- */
-static tb_void_t tb_iocp_spak_timeout(tb_bool_t killed, tb_cpointer_t priv)
-{
- // the aico
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)priv;
- tb_assert_and_check_return(aico);
-
- // the impl
- tb_iocp_ptor_impl_t* impl = aico->impl;
- tb_assert_and_check_return(impl);
-
- // cancel it
- switch (aico->base.type)
- {
- case TB_AICO_TYPE_SOCK:
- case TB_AICO_TYPE_FILE:
- {
- // check
- tb_assert_and_check_break(aico->base.handle);
-
- // trace
- tb_trace_d("spak[%p]: code: %lu: timeout", aico, aico->olap.aice.code);
-
- // the handle
- HANDLE handle = aico->base.type == TB_AICO_TYPE_SOCK? (HANDLE)((SOCKET)aico->base.handle - 1) : aico->base.handle;
-
- // CancelIo it
- if (!CancelIo(handle))
- {
- // trace
- tb_trace_e("cancel[%p]: failed: %u", aico, GetLastError());
- }
- }
- break;
- default:
- tb_assert(0);
- break;
- }
-}
-static tb_void_t tb_iocp_spak_timeout_runtask(tb_bool_t killed, tb_cpointer_t priv)
-{
- // the aico
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)priv;
- tb_assert_and_check_return(aico);
-
- // the impl
- tb_iocp_ptor_impl_t* impl = aico->impl;
- tb_assert_and_check_return(impl);
-
- // trace
- tb_trace_d("runtask: timeout: when: %llu", aico->olap.aice.u.runtask.when);
-
- // post ok
- aico->olap.aice.state = killed? TB_STATE_KILLED : TB_STATE_OK;
- PostQueuedCompletionStatus(impl->port, 0, (ULONG_PTR)aico, (LPOVERLAPPED)&aico->olap);
-}
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * spak
- */
-static tb_bool_t tb_iocp_post_acpt(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t aice);
-static tb_long_t tb_iocp_spak_acpt(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t resp, tb_size_t real, tb_size_t error)
-{
- // check?
- tb_assert_and_check_return_val(impl && resp, -1);
-
- // trace
- tb_trace_d("acpt[%p]: spak: %lu", resp->aico, error);
-
- // check
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)resp->aico;
- tb_assert(aico && aico->addr && resp->u.acpt.priv[0]);
-
- // done
- switch (error)
- {
- // ok or pending?
- case ERROR_SUCCESS:
- case WAIT_TIMEOUT:
- case ERROR_IO_PENDING:
- {
- // done state
- switch (resp->state)
- {
- case TB_STATE_OK:
- case TB_STATE_PENDING:
- resp->state = resp->u.acpt.priv[0]? TB_STATE_OK : TB_STATE_FAILED;
- break;
- default:
- // using the self state here
- break;
- }
-
- // ok?
- if (resp->state == TB_STATE_OK)
- {
- // init aico
- resp->u.acpt.aico = tb_aico_init(tb_aico_aicp(resp->aico));
- if (!resp->u.acpt.aico)
- {
- resp->state = TB_STATE_FAILED;
- break;
- }
-
-#ifdef TB_IOCP_SOCKET_POOL_ENABLE
- // DisconnectEx it
- ((tb_iocp_aico_t*)resp->u.acpt.aico)->bDisconnectEx = 1;
-#endif
-
- // open aico
- if (!tb_aico_open_sock(resp->u.acpt.aico, (tb_socket_ref_t)resp->u.acpt.priv[0]))
- {
- resp->state = TB_STATE_FAILED;
- break;
- }
-
- // update the accept context, otherwise shutdown and getsockname will be failed
- SOCKET acpt = (SOCKET)tb_aico_sock(resp->aico) - 1;
- tb_long_t update_ok = setsockopt((SOCKET)resp->u.acpt.priv[0] - 1, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (tb_char_t*)&acpt, sizeof(acpt));
- tb_assert(!update_ok); tb_used(update_ok);
-
- // clear sock
- resp->u.acpt.priv[0] = tb_null;
-
- // done GetAcceptExSockaddrs
- INT server_size = 0;
- INT client_size = 0;
- struct sockaddr_storage* server_addr = tb_null;
- struct sockaddr_storage* client_addr = tb_null;
- if (impl->func.GetAcceptExSockaddrs)
- {
- // done it
- impl->func.GetAcceptExSockaddrs( (tb_byte_t*)aico->addr
- , 0
- , sizeof(struct sockaddr_storage)
- , sizeof(struct sockaddr_storage)
- , (LPSOCKADDR*)&server_addr
- , &server_size
- , (LPSOCKADDR*)&client_addr
- , &client_size);
-
- // exists client address?
- if (client_addr)
- {
- // save address
- tb_sockaddr_save(&resp->u.acpt.addr, client_addr);
-
- // trace
- tb_trace_d("acpt[%p]: client_addr: %{ipaddr}", resp->aico, &resp->u.acpt.addr);
- }
- }
- }
- }
- break;
- // canceled? timeout?
- case WSAEINTR:
- case ERROR_OPERATION_ABORTED:
- {
- resp->state = TB_STATE_TIMEOUT;
- }
- break;
- // unknown error
- default:
- {
- resp->state = TB_STATE_FAILED;
-
- // trace
- tb_trace_e("acpt[%p]: unknown error: %u", resp->aico, error);
- }
- break;
- }
-
- // continue to post acpt if ok
- if (resp->state == TB_STATE_OK) tb_iocp_post_acpt(impl, resp);
-
- // ok
- return 1;
-}
-static tb_long_t tb_iocp_spak_conn(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t resp, tb_size_t real, tb_size_t error)
-{
- // check?
- tb_assert_and_check_return_val(resp, -1);
-
- // the aico
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)resp->aico;
- tb_assert_and_check_return_val(aico, -1);
-
- // trace
- tb_trace_d("conn[%p]: spak: %lu", resp->aico, error);
-
- // done
- switch (error)
- {
- // ok or pending?
- case ERROR_SUCCESS:
- case WAIT_TIMEOUT:
- case ERROR_IO_PENDING:
- {
- // done state
- switch (resp->state)
- {
- case TB_STATE_OK:
- case TB_STATE_PENDING:
- resp->state = TB_STATE_OK;
- break;
- default:
- // using the self state here
- break;
- }
- }
- break;
- // failed?
- case WSAENOTCONN:
- case WSAECONNREFUSED:
- case ERROR_CONNECTION_REFUSED:
- {
- resp->state = TB_STATE_FAILED;
- }
- break;
- // timeout?
- case WSAEINTR:
- case ERROR_SEM_TIMEOUT:
- case ERROR_OPERATION_ABORTED:
- {
- resp->state = TB_STATE_TIMEOUT;
- }
- break;
- // unknown error
- default:
- {
- resp->state = TB_STATE_FAILED;
-
- // trace
- tb_trace_e("conn: unknown error: %u", error);
- }
- break;
- }
-
- // ok?
- if (resp->state == TB_STATE_OK)
- {
-#if 0
- // update the connect context, otherwise shutdown and getsockname will be failed
- tb_long_t update_ok = setsockopt((SOCKET)tb_aico_sock(resp->aico)- 1, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, tb_null, 0);
- tb_assert(!update_ok); tb_used(update_ok);
-
- // DisconnectEx it
- aico->bDisconnectEx = 1;
-#endif
- }
-
- // ok
- return 1;
-}
-static tb_long_t tb_iocp_spak_iorw(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t resp, tb_size_t real, tb_size_t error)
-{
- // check?
- tb_assert_and_check_return_val(resp, -1);
-
- // ok?
- if (real)
- {
- // trace
- tb_trace_d("iorw[%p]: code: %lu, real: %lu", resp->aico, resp->code, real);
-
- // save address for urecv or urecvv
- if (resp->code == TB_AICE_CODE_URECV || resp->code == TB_AICE_CODE_URECVV)
- {
- // the aico
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)resp->aico;
- tb_assert_and_check_return_val(aico, -1);
-
- // the address
- struct sockaddr_storage* addr = (struct sockaddr_storage*)aico->addr;
- tb_assert_and_check_return_val(addr, -1);
-
- // save address
- tb_sockaddr_save(resp->code == TB_AICE_CODE_URECV? &resp->u.urecv.addr : &resp->u.urecvv.addr, addr);
- }
-
- // save the real size, @note: hack the real offset for the other io aice
- resp->u.recv.real = real;
-
- // ok
- resp->state = TB_STATE_OK;
- return 1;
- }
-
- // error?
- switch (error)
- {
- // ok or pending?
- case ERROR_SUCCESS:
- case WAIT_TIMEOUT:
- case ERROR_IO_PENDING:
- {
- // done state
- switch (resp->state)
- {
- case TB_STATE_OK:
- case TB_STATE_PENDING:
- resp->state = TB_STATE_CLOSED;
- break;
- default:
- // using the self state here
- break;
- }
- }
- break;
- // closed?
- case WSAECONNRESET:
- case ERROR_HANDLE_EOF:
- case ERROR_NETNAME_DELETED:
- case ERROR_BAD_COMMAND:
- {
- resp->state = TB_STATE_CLOSED;
- }
- break;
- // canceled? timeout
- case WSAEINTR:
- case ERROR_OPERATION_ABORTED:
- {
- resp->state = TB_STATE_TIMEOUT;
- }
- break;
- // unknown error
- default:
- {
- // trace
- tb_trace_e("iorw[%p]: code: %lu, unknown error: %lu", resp->aico, resp->code, error);
-
- // failed
- resp->state = TB_STATE_FAILED;
- }
- break;
- }
-
- // ok
- return 1;
-}
-static tb_long_t tb_iocp_spak_fsync(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t resp, tb_size_t real, tb_size_t error)
-{
- // check?
- tb_assert_and_check_return_val(resp, -1);
-
- // trace
- tb_trace_d("fsync[%p]: spak: %lu", resp->aico, error);
-
- // done
- switch (error)
- {
- // ok or pending?
- case ERROR_SUCCESS:
- case WAIT_TIMEOUT:
- case ERROR_IO_PENDING:
- {
- // done state
- switch (resp->state)
- {
- case TB_STATE_OK:
- case TB_STATE_PENDING:
- resp->state = TB_STATE_OK;
- break;
- default:
- break;
- }
- }
- break;
- // closed?
- case ERROR_HANDLE_EOF:
- case ERROR_NETNAME_DELETED:
- {
- resp->state = TB_STATE_CLOSED;
- }
- break;
- // unknown error
- default:
- {
- resp->state = TB_STATE_FAILED;
- tb_trace_e("fsync: unknown error: %u", error);
- }
- break;
- }
-
- // ok
- return 1;
-}
-static tb_long_t tb_iocp_spak_runtask(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t resp, tb_size_t real, tb_size_t error)
-{
- // check?
- tb_assert_and_check_return_val(resp, -1);
-
- // trace
- tb_trace_d("runtask[%p]: spak: %lu", resp->aico, error);
-
- // done
- switch (error)
- {
- // ok or pending?
- case ERROR_SUCCESS:
- case WAIT_TIMEOUT:
- case ERROR_IO_PENDING:
- {
- // done state
- switch (resp->state)
- {
- case TB_STATE_OK:
- case TB_STATE_PENDING:
- resp->state = TB_STATE_OK;
- break;
- default:
- break;
- }
- }
- break;
- // unknown error
- default:
- {
- resp->state = TB_STATE_FAILED;
-
- // trace
- tb_trace_e("runtask: unknown error: %u", error);
- }
- break;
- }
-
- // ok
- return 1;
-}
-static tb_long_t tb_iocp_spak_clos(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t resp, tb_size_t real, tb_size_t error)
-{
- // check?
- tb_assert_and_check_return_val(resp, -1);
-
- // the aico
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)resp->aico;
- tb_assert_and_check_return_val(aico, -1);
-
- // trace
- tb_trace_d("clos[%p]: spak: %lu", resp->aico, error);
-
- // done
- switch (error)
- {
- // ok or pending?
- case ERROR_SUCCESS:
- case WAIT_TIMEOUT:
- case ERROR_IO_PENDING:
- {
- // trace
- tb_trace_d("clos[%p]: push to the socket pool", resp->aico);
-
- // put the socket to the socket pool
- if (aico->base.handle)
- {
- if (!tb_socket_pool_put((tb_socket_ref_t)aico->base.handle))
- tb_socket_exit((tb_socket_ref_t)aico->base.handle);
- }
- aico->base.handle = tb_null;
- }
- break;
- // unknown error
- default:
- {
- // trace
- tb_trace_e("clos[%p]: unknown error: %u", resp->aico, error);
-
- // close the socket handle
- if (aico->base.handle) tb_socket_exit((tb_socket_ref_t)aico->base.handle);
- aico->base.handle = tb_null;
- }
- break;
- }
-
- // clear impl
- aico->impl = tb_null;
-
- // clear type
- aico->base.type = TB_AICO_TYPE_NONE;
-
- // clear timeout
- tb_size_t i = 0;
- tb_size_t n = tb_arrayn(aico->base.timeout);
- for (i = 0; i < n; i++) aico->base.timeout[i] = -1;
-
- // closed
- tb_atomic_set(&aico->base.state, TB_STATE_CLOSED);
-
- // clear bDisconnectEx
- aico->bDisconnectEx = 0;
-
- // clear olap
- tb_memset(&aico->olap, 0, sizeof(tb_iocp_olap_t));
-
- // ok
- resp->state = TB_STATE_OK;
- return 1;
-}
-static tb_long_t tb_iocp_spak_done(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t resp, tb_size_t real, tb_size_t error)
-{
- // check?
- tb_assert_and_check_return_val(resp && resp->aico, -1);
-
- // killed?
- if (tb_aico_impl_is_killed((tb_aico_impl_t*)resp->aico) && resp->code != TB_AICE_CODE_CLOS)
- {
- // save state
- resp->state = TB_STATE_KILLED;
-
- // trace
- tb_trace_d("spak: code: %u: killed", resp->code);
-
- // ok
- return 1;
- }
-
- // no pending? spak it directly
- tb_check_return_val(resp->state == TB_STATE_PENDING, 1);
-
- // init spak
- static tb_long_t (*s_spak[])(tb_iocp_ptor_impl_t* , tb_aice_ref_t , tb_size_t , tb_size_t ) =
- {
- tb_null
- , tb_iocp_spak_acpt
- , tb_iocp_spak_conn
- , tb_iocp_spak_iorw
- , tb_iocp_spak_iorw
- , tb_iocp_spak_iorw
- , tb_iocp_spak_iorw
- , tb_iocp_spak_iorw
- , tb_iocp_spak_iorw
- , tb_iocp_spak_iorw
- , tb_iocp_spak_iorw
- , tb_iocp_spak_iorw
- , tb_iocp_spak_iorw
- , tb_iocp_spak_iorw
- , tb_iocp_spak_iorw
- , tb_iocp_spak_iorw
- , tb_iocp_spak_fsync
- , tb_iocp_spak_runtask
- , tb_iocp_spak_clos
- };
- tb_assert_and_check_return_val(resp->code < tb_arrayn(s_spak), -1);
-
- // trace
- tb_trace_d("spak[%p], code: %u: done: ..", resp->aico, resp->code);
-
- // done spak
- return (s_spak[resp->code])? s_spak[resp->code](impl, resp, real, error) : -1;
-}
-/* //////////////////////////////////////////////////////////////////////////////////////
- * post
- */
-static tb_void_t tb_iocp_post_timeout(tb_iocp_ptor_impl_t* impl, tb_iocp_aico_t* aico)
-{
- // check
- tb_assert_and_check_return(impl && impl->ltimer && aico);
-
- // only for sock
- tb_check_return(aico->base.type == TB_AICO_TYPE_SOCK);
-
- // add timeout task
- tb_long_t timeout = tb_aico_impl_timeout_from_code((tb_aico_impl_t*)aico, aico->olap.aice.code);
- if (timeout >= 0)
- {
- // trace
- tb_trace_d("post: timeout[%p], code: %lu: ..", aico, aico->olap.aice.code);
-
- // check
- tb_assert_and_check_return(!aico->task);
-
- // add the new task
- aico->task = tb_ltimer_task_init(impl->ltimer, timeout, tb_false, tb_iocp_spak_timeout, aico);
- aico->bltimer = 1;
- }
-}
-static tb_void_t tb_iocp_post_timeout_cancel(tb_iocp_ptor_impl_t* impl, tb_iocp_aico_t* aico)
-{
- // check
- tb_assert_and_check_return(impl && impl->ltimer && aico);
-
- // remove timeout task
- if (aico->task)
- {
- if (aico->bltimer) tb_ltimer_task_exit(impl->ltimer, (tb_ltimer_task_ref_t)aico->task);
- else tb_timer_task_exit(impl->timer, (tb_timer_task_ref_t)aico->task);
- aico->bltimer = 0;
- }
- aico->task = tb_null;
-}
-static tb_bool_t tb_iocp_post_acpt(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(impl && impl->port && impl->func.AcceptEx && impl->base.aicp, tb_false);
-
- // check aice
- tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_ACPT, tb_false);
-
- // the aico
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)aice->aico;
- tb_assert_and_check_return_val(aico && aico->base.handle, tb_false);
-
- // trace
- tb_trace_d("accept[%p]: ..", aico);
-
- // done
- tb_bool_t ok = tb_false;
- tb_bool_t init_ok = tb_false;
- tb_bool_t AcceptEx_ok = tb_false;
- do
- {
- // make address
- if (!aico->addr) aico->addr = tb_malloc0(((sizeof(struct sockaddr_storage)) << 1));
- tb_assert_and_check_break(aico->addr);
-
- // init olap
- tb_memset(&aico->olap, 0, sizeof(tb_iocp_olap_t));
-
- // attempt to get the socket from the socket pool
- tb_socket_ref_t sock = tb_socket_pool_get();
-
- // init aice, hack: sizeof(tb_iocp_olap_t) >= (sizeof(struct sockaddr_storage) << 1)
- aico->olap.aice = *aice;
- aico->olap.aice.state = TB_STATE_PENDING;
- aico->olap.aice.u.acpt.priv[0] = sock? sock : tb_socket_init(TB_SOCKET_TYPE_TCP, TB_IPADDR_FAMILY_IPV4);
- tb_assert_static(tb_arrayn(aico->olap.aice.u.acpt.priv));
- tb_assert_and_check_break(aico->olap.aice.u.acpt.priv[0]);
- init_ok = tb_true;
-
- // post timeout first
- tb_iocp_post_timeout(impl, aico);
-
- // done AcceptEx
- DWORD real = 0;
- AcceptEx_ok = impl->func.AcceptEx( (SOCKET)aico->base.handle - 1
- , (SOCKET)aico->olap.aice.u.acpt.priv[0] - 1
- , (tb_byte_t*)aico->addr
- , 0
- , sizeof(struct sockaddr_storage)
- , sizeof(struct sockaddr_storage)
- , &real
- , (LPOVERLAPPED)&aico->olap)? tb_true : tb_false;
- tb_trace_d("accept[%p]: AcceptEx: %d, error: %d", aico, AcceptEx_ok, impl->func.WSAGetLastError());
- tb_check_break(AcceptEx_ok);
-
- // post ok
- aico->olap.aice.state = TB_STATE_OK;
- if (!PostQueuedCompletionStatus(impl->port, 0, (ULONG_PTR)aico, (LPOVERLAPPED)&aico->olap)) break;
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // AcceptEx failed?
- if (init_ok && !AcceptEx_ok)
- {
- // pending? continue it
- if (WSA_IO_PENDING == impl->func.WSAGetLastError())
- {
- // ok
- ok = tb_true;
- }
- // failed?
- else
- {
- // post failed
- aico->olap.aice.state = TB_STATE_FAILED;
- if (PostQueuedCompletionStatus(impl->port, 0, (ULONG_PTR)aico, (LPOVERLAPPED)&aico->olap)) ok = tb_true;
-
- // trace
- tb_trace_d("accept[%p]: AcceptEx: unknown error: %d", aico, impl->func.WSAGetLastError());
- }
- }
-
- // error?
- if (!ok)
- {
- // exit sock
- if (aico->olap.aice.u.acpt.priv[0]) tb_socket_exit((tb_socket_ref_t)aico->olap.aice.u.acpt.priv[0]);
- aico->olap.aice.u.acpt.priv[0] = tb_null;
-
- // remove timeout task
- tb_iocp_post_timeout_cancel(impl, aico);
- }
-
- // ok?
- return ok;
-}
-static tb_bool_t tb_iocp_post_conn(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(impl && impl->port && impl->base.aicp, tb_false);
-
- // check aice
- tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_CONN, tb_false);
-
- // the aico
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)aice->aico;
- tb_assert_and_check_return_val(aico && aico->base.handle && !aico->bDisconnectEx, tb_false);
-
- // trace
- tb_trace_d("connect[%p]: %{ipaddr}: ..", aico, &aice->u.conn.addr);
-
- // done
- tb_bool_t ok = tb_false;
- tb_bool_t init_ok = tb_false;
- tb_bool_t ConnectEx_ok = tb_false;
- do
- {
- // init olap
- tb_memset(&aico->olap, 0, sizeof(tb_iocp_olap_t));
-
- // init aice
- aico->olap.aice = *aice;
-
- // load local address
- tb_size_t laddr_size = 0;
- struct sockaddr_storage laddr_data = {0};
- tb_ipaddr_t laddr;
- if (!tb_ipaddr_set(&laddr, tb_null, 0, (tb_uint8_t)tb_ipaddr_family(&aice->u.conn.addr))) break;
- if (!(laddr_size = tb_sockaddr_load(&laddr_data, &laddr))) break;
-
- // bind it first for ConnectEx
- if (SOCKET_ERROR == impl->func.bind((SOCKET)aico->base.handle - 1, (LPSOCKADDR)&laddr_data, (tb_int_t)laddr_size))
- {
- // trace
- tb_trace_e("connect[%p]: bind failed, error: %u", aico, GetLastError());
- break;
- }
- init_ok = tb_true;
-
- // post timeout first
- tb_iocp_post_timeout(impl, aico);
-
- // load client address
- tb_size_t caddr_size = 0;
- struct sockaddr_storage caddr_data = {0};
- if (!(caddr_size = tb_sockaddr_load(&caddr_data, &aice->u.conn.addr))) break;
-
- // done ConnectEx
- DWORD real = 0;
- ConnectEx_ok = impl->func.ConnectEx( (SOCKET)aico->base.handle - 1
- , (struct sockaddr const*)&caddr_data
- , (tb_int_t)caddr_size
- , tb_null
- , 0
- , &real
- , (LPOVERLAPPED)&aico->olap)? tb_true : tb_false;
- tb_trace_d("connect[%p]: ConnectEx: %d, error: %d", aico, ConnectEx_ok, impl->func.WSAGetLastError());
- tb_check_break(ConnectEx_ok);
-
- // post ok
- aico->olap.aice.state = TB_STATE_OK;
- if (!PostQueuedCompletionStatus(impl->port, 0, (ULONG_PTR)aico, (LPOVERLAPPED)&aico->olap)) break;
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // ConnectEx failed?
- if (init_ok && !ConnectEx_ok)
- {
- // pending? continue it
- if (WSA_IO_PENDING == impl->func.WSAGetLastError())
- {
- // ok
- ok = tb_true;
- }
- // failed?
- else
- {
- // post failed
- aico->olap.aice.state = TB_STATE_FAILED;
- if (PostQueuedCompletionStatus(impl->port, 0, (ULONG_PTR)aico, (LPOVERLAPPED)&aico->olap)) ok = tb_true;
-
- // trace
- tb_trace_d("connect[%p]: ConnectEx: unknown error: %d", aico, impl->func.WSAGetLastError());
- }
- }
-
- // error? remove timeout task
- if (!ok) tb_iocp_post_timeout_cancel(impl, aico);
-
- // ok?
- return ok;
-}
-static tb_bool_t tb_iocp_post_recv(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(impl && impl->port && impl->base.aicp, tb_false);
-
- // check aice
- tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_RECV, tb_false);
- tb_assert_and_check_return_val(aice->u.recv.data && aice->u.recv.size, tb_false);
-
- // the aico
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)aice->aico;
- tb_assert_and_check_return_val(aico && aico->base.handle, tb_false);
-
- // init olap
- tb_memset(&aico->olap, 0, sizeof(tb_iocp_olap_t));
-
- // init aice
- aico->olap.aice = *aice;
-
- // trace
- tb_trace_d("recv[%p]: ..", aico);
-
- // post timeout first
- tb_iocp_post_timeout(impl, aico);
-
- // done recv
- DWORD flag = 0;
- tb_long_t ok = impl->func.WSARecv((SOCKET)aico->base.handle - 1, (WSABUF*)&aico->olap.aice.u.recv, 1, tb_null, &flag, (LPOVERLAPPED)&aico->olap, tb_null);
- tb_trace_d("recv[%p]: WSARecv: %ld, error: %d", aico, ok, impl->func.WSAGetLastError());
-
- // ok or pending? continue it
- if (!ok || ((ok == SOCKET_ERROR) && (WSA_IO_PENDING == impl->func.WSAGetLastError()))) return tb_true;
-
- // error?
- if (ok == SOCKET_ERROR)
- {
- // done error
- switch (impl->func.WSAGetLastError())
- {
- // closed?
- case WSAECONNABORTED:
- case WSAECONNRESET:
- aico->olap.aice.state = TB_STATE_CLOSED;
- break;
- // failed?
- default:
- aico->olap.aice.state = TB_STATE_FAILED;
- break;
- }
-
- // post closed or failed
- if (PostQueuedCompletionStatus(impl->port, 0, (ULONG_PTR)aico, (LPOVERLAPPED)&aico->olap)) return tb_true;
- }
-
- // remove timeout task
- tb_iocp_post_timeout_cancel(impl, aico);
-
- // failed
- return tb_false;
-}
-static tb_bool_t tb_iocp_post_send(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(impl && impl->port && impl->base.aicp, tb_false);
-
- // check aice
- tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_SEND, tb_false);
- tb_assert_and_check_return_val(aice->u.send.data && aice->u.send.size, tb_false);
-
- // the aico
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)aice->aico;
- tb_assert_and_check_return_val(aico && aico->base.handle, tb_false);
-
- // init olap
- tb_memset(&aico->olap, 0, sizeof(tb_iocp_olap_t));
-
- // init aice
- aico->olap.aice = *aice;
-
- // trace
- tb_trace_d("send[%p]: ..", aico);
-
- // post timeout first
- tb_iocp_post_timeout(impl, aico);
-
- // done send
- tb_long_t ok = impl->func.WSASend((SOCKET)aico->base.handle - 1, (WSABUF*)&aico->olap.aice.u.send, 1, tb_null, 0, (LPOVERLAPPED)&aico->olap, tb_null);
- tb_trace_d("send[%p]: WSASend: %ld, error: %d", aico, ok, impl->func.WSAGetLastError());
-
- // ok or pending? continue it
- if (!ok || ((ok == SOCKET_ERROR) && (WSA_IO_PENDING == impl->func.WSAGetLastError()))) return tb_true;
-
- // error?
- if (ok == SOCKET_ERROR)
- {
- // done error
- switch (impl->func.WSAGetLastError())
- {
- // closed?
- case WSAECONNABORTED:
- case WSAECONNRESET:
- aico->olap.aice.state = TB_STATE_CLOSED;
- break;
- // failed?
- default:
- aico->olap.aice.state = TB_STATE_FAILED;
- break;
- }
-
- // post closed or failed
- if (PostQueuedCompletionStatus(impl->port, 0, (ULONG_PTR)aico, (LPOVERLAPPED)&aico->olap)) return tb_true;
- }
-
- // remove timeout task
- tb_iocp_post_timeout_cancel(impl, aico);
-
- // failed
- return tb_false;
-}
-static tb_bool_t tb_iocp_post_urecv(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(impl && impl->port && impl->base.aicp, tb_false);
-
- // check aice
- tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_URECV, tb_false);
- tb_assert_and_check_return_val(aice->u.urecv.data && aice->u.urecv.size, tb_false);
-
- // the aico
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)aice->aico;
- tb_assert_and_check_return_val(aico && aico->base.handle, tb_false);
-
- // init olap
- tb_memset(&aico->olap, 0, sizeof(tb_iocp_olap_t));
-
- // init aice
- aico->olap.aice = *aice;
-
- // make addr
- if (!aico->addr) aico->addr = tb_malloc(sizeof(struct sockaddr_storage) + sizeof(tb_int_t) + sizeof(DWORD));
- tb_assert_and_check_return_val(aico->addr, tb_false);
-
- // init addr
- tb_memset((tb_pointer_t)aico->addr, 0, sizeof(struct sockaddr_storage));
-
- // init size
- tb_int_t* psize = (tb_int_t*)((tb_byte_t*)aico->addr + sizeof(struct sockaddr_storage));
- *psize = sizeof(struct sockaddr_storage);
-
- // init flag
- DWORD* pflag = (DWORD*)((tb_byte_t*)aico->addr + sizeof(struct sockaddr_storage) + sizeof(tb_int_t));
- *pflag = 0;
-
- // trace
- tb_trace_d("urecv[%p]: ..", aico);
-
- // post timeout first
- tb_iocp_post_timeout(impl, aico);
-
- // done recv
- tb_long_t ok = impl->func.WSARecvFrom((SOCKET)aico->base.handle - 1, (WSABUF*)&aico->olap.aice.u.urecv, 1, tb_null, pflag, (struct sockaddr*)aico->addr, psize, (LPOVERLAPPED)&aico->olap, tb_null);
- tb_trace_d("urecv[%p]: WSARecvFrom: %ld, error: %d", aico, ok, impl->func.WSAGetLastError());
-
- // ok or pending? continue it
- if (!ok || ((ok == SOCKET_ERROR) && (WSA_IO_PENDING == impl->func.WSAGetLastError()))) return tb_true;
-
- // error?
- if (ok == SOCKET_ERROR)
- {
- // done error
- switch (impl->func.WSAGetLastError())
- {
- // closed?
- case WSAECONNABORTED:
- case WSAECONNRESET:
- aico->olap.aice.state = TB_STATE_CLOSED;
- break;
- // failed?
- default:
- aico->olap.aice.state = TB_STATE_FAILED;
- break;
- }
-
- // post closed or failed
- if (PostQueuedCompletionStatus(impl->port, 0, (ULONG_PTR)aico, (LPOVERLAPPED)&aico->olap)) return tb_true;
- }
-
- // remove timeout task
- tb_iocp_post_timeout_cancel(impl, aico);
-
- // failed
- return tb_false;
-}
-static tb_bool_t tb_iocp_post_usend(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(impl && impl->port && impl->base.aicp, tb_false);
-
- // check aice
- tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_USEND, tb_false);
- tb_assert_and_check_return_val(aice->u.usend.data && aice->u.usend.size, tb_false);
-
- // the aico
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)aice->aico;
- tb_assert_and_check_return_val(aico && aico->base.handle, tb_false);
-
- // init olap
- tb_memset(&aico->olap, 0, sizeof(tb_iocp_olap_t));
-
- // init aice
- aico->olap.aice = *aice;
-
- // trace
- tb_trace_d("usend[%p]: ..", aico);
-
- // load addr
- tb_size_t n = 0;
- struct sockaddr_storage d = {0};
- if (!(n = tb_sockaddr_load(&d, &aice->u.usend.addr))) return tb_false;
-
- // post timeout first
- tb_iocp_post_timeout(impl, aico);
-
- // done send
- tb_long_t ok = impl->func.WSASendTo((SOCKET)aico->base.handle - 1, (WSABUF*)&aico->olap.aice.u.usend, 1, tb_null, 0, (struct sockaddr*)&d, (tb_int_t)n, (LPOVERLAPPED)&aico->olap, tb_null);
- tb_trace_d("usend[%p]: WSASendTo: %ld, error: %d", aico, ok, impl->func.WSAGetLastError());
-
- // ok or pending? continue it
- if (!ok || ((ok == SOCKET_ERROR) && (WSA_IO_PENDING == impl->func.WSAGetLastError()))) return tb_true;
-
- // error?
- if (ok == SOCKET_ERROR)
- {
- // done error
- switch (impl->func.WSAGetLastError())
- {
- // closed?
- case WSAECONNABORTED:
- case WSAECONNRESET:
- aico->olap.aice.state = TB_STATE_CLOSED;
- break;
- // failed?
- default:
- aico->olap.aice.state = TB_STATE_FAILED;
- break;
- }
-
- // post closed or failed
- if (PostQueuedCompletionStatus(impl->port, 0, (ULONG_PTR)aico, (LPOVERLAPPED)&aico->olap)) return tb_true;
- }
-
- // remove timeout task
- tb_iocp_post_timeout_cancel(impl, aico);
-
- // failed
- return tb_false;
-}
-static tb_bool_t tb_iocp_post_recvv(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(impl && impl->port && impl->base.aicp, tb_false);
-
- // check aice
- tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_RECVV, tb_false);
- tb_assert_and_check_return_val(aice->u.recvv.list && aice->u.recvv.size, tb_false);
-
- // the aico
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)aice->aico;
- tb_assert_and_check_return_val(aico && aico->base.handle, tb_false);
-
- // init olap
- tb_memset(&aico->olap, 0, sizeof(tb_iocp_olap_t));
-
- // init aice
- aico->olap.aice = *aice;
-
- // trace
- tb_trace_d("recvv[%p]: ..", aico);
-
- // post timeout first
- tb_iocp_post_timeout(impl, aico);
-
- // done recv
- DWORD flag = 0;
- tb_long_t ok = impl->func.WSARecv((SOCKET)aico->base.handle - 1, (WSABUF*)aico->olap.aice.u.recvv.list, (DWORD)aico->olap.aice.u.recvv.size, tb_null, &flag, (LPOVERLAPPED)&aico->olap, tb_null);
- tb_trace_d("recvv[%p]: WSARecv: %ld, error: %d", aico, ok, impl->func.WSAGetLastError());
-
- // ok or pending? continue it
- if (!ok || ((ok == SOCKET_ERROR) && (WSA_IO_PENDING == impl->func.WSAGetLastError()))) return tb_true;
-
- // error?
- if (ok == SOCKET_ERROR)
- {
- // done error
- switch (impl->func.WSAGetLastError())
- {
- // closed?
- case WSAECONNABORTED:
- case WSAECONNRESET:
- aico->olap.aice.state = TB_STATE_CLOSED;
- break;
- // failed?
- default:
- aico->olap.aice.state = TB_STATE_FAILED;
- break;
- }
-
- // post closed or failed
- if (PostQueuedCompletionStatus(impl->port, 0, (ULONG_PTR)aico, (LPOVERLAPPED)&aico->olap)) return tb_true;
- }
-
- // remove timeout task
- tb_iocp_post_timeout_cancel(impl, aico);
-
- // failed
- return tb_false;
-}
-static tb_bool_t tb_iocp_post_sendv(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(impl && impl->port && impl->base.aicp, tb_false);
-
- // check aice
- tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_SENDV, tb_false);
- tb_assert_and_check_return_val(aice->u.sendv.list && aice->u.sendv.size, tb_false);
-
- // the aico
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)aice->aico;
- tb_assert_and_check_return_val(aico && aico->base.handle, tb_false);
-
- // init olap
- tb_memset(&aico->olap, 0, sizeof(tb_iocp_olap_t));
-
- // init aice
- aico->olap.aice = *aice;
-
- // trace
- tb_trace_d("sendv[%p]: ..", aico);
-
- // post timeout first
- tb_iocp_post_timeout(impl, aico);
-
- // done send
- tb_long_t ok = impl->func.WSASend((SOCKET)aico->base.handle - 1, (WSABUF*)aico->olap.aice.u.sendv.list, (DWORD)aico->olap.aice.u.sendv.size, tb_null, 0, (LPOVERLAPPED)&aico->olap, tb_null);
- tb_trace_d("sendv[%p]: WSASend: %ld, error: %d", aico, ok, impl->func.WSAGetLastError());
-
- // ok or pending? continue it
- if (!ok || ((ok == SOCKET_ERROR) && (WSA_IO_PENDING == impl->func.WSAGetLastError()))) return tb_true;
-
- // error?
- if (ok == SOCKET_ERROR)
- {
- // done error
- switch (impl->func.WSAGetLastError())
- {
- // closed?
- case WSAECONNABORTED:
- case WSAECONNRESET:
- aico->olap.aice.state = TB_STATE_CLOSED;
- break;
- // failed?
- default:
- aico->olap.aice.state = TB_STATE_FAILED;
- break;
- }
-
- // post closed or failed
- if (PostQueuedCompletionStatus(impl->port, 0, (ULONG_PTR)aico, (LPOVERLAPPED)&aico->olap)) return tb_true;
- }
-
- // remove timeout task
- tb_iocp_post_timeout_cancel(impl, aico);
-
- // failed
- return tb_false;
-}
-static tb_bool_t tb_iocp_post_urecvv(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(impl && impl->port && impl->base.aicp, tb_false);
-
- // check aice
- tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_URECVV, tb_false);
- tb_assert_and_check_return_val(aice->u.urecvv.list && aice->u.urecvv.size, tb_false);
-
- // the aico
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)aice->aico;
- tb_assert_and_check_return_val(aico && aico->base.handle, tb_false);
-
- // init olap
- tb_memset(&aico->olap, 0, sizeof(tb_iocp_olap_t));
-
- // init aice
- aico->olap.aice = *aice;
-
- // make addr
- if (!aico->addr) aico->addr = tb_malloc0(sizeof(sockaddr_storage) + sizeof(tb_int_t) + sizeof(DWORD));
- tb_assert_and_check_return_val(aico->addr, tb_false);
-
- // init addr
- tb_memset((tb_pointer_t)aico->addr, 0, sizeof(sockaddr_storage));
-
- // init size
- tb_int_t* psize = (tb_int_t*)((tb_byte_t*)aico->addr + sizeof(sockaddr_storage));
- *psize = sizeof(sockaddr_storage);
-
- // init flag
- DWORD* pflag = (DWORD*)((tb_byte_t*)aico->addr + sizeof(sockaddr_storage) + sizeof(tb_int_t));
- *pflag = 0;
-
- // trace
- tb_trace_d("urecvv[%p]: ..", aico);
-
- // post timeout first
- tb_iocp_post_timeout(impl, aico);
-
- // done recv
- tb_long_t ok = impl->func.WSARecvFrom((SOCKET)aico->base.handle - 1, (WSABUF*)aico->olap.aice.u.urecvv.list, (DWORD)aico->olap.aice.u.urecvv.size, tb_null, pflag, (struct sockaddr*)aico->addr, psize, (LPOVERLAPPED)&aico->olap, tb_null);
- tb_trace_d("urecvv[%p]: WSARecvFrom: %ld, error: %d", aico, ok, impl->func.WSAGetLastError());
-
- // ok or pending? continue it
- if (!ok || ((ok == SOCKET_ERROR) && (WSA_IO_PENDING == impl->func.WSAGetLastError()))) return tb_true;
-
- // error?
- if (ok == SOCKET_ERROR)
- {
- // done error
- switch (impl->func.WSAGetLastError())
- {
- // closed?
- case WSAECONNABORTED:
- case WSAECONNRESET:
- aico->olap.aice.state = TB_STATE_CLOSED;
- break;
- // failed?
- default:
- aico->olap.aice.state = TB_STATE_FAILED;
- break;
- }
-
- // post closed or failed
- if (PostQueuedCompletionStatus(impl->port, 0, (ULONG_PTR)aico, (LPOVERLAPPED)&aico->olap)) return tb_true;
- }
-
- // remove timeout task
- tb_iocp_post_timeout_cancel(impl, aico);
-
- // failed
- return tb_false;
-}
-static tb_bool_t tb_iocp_post_usendv(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(impl && impl->port && impl->base.aicp, tb_false);
-
- // check aice
- tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_USENDV, tb_false);
- tb_assert_and_check_return_val(aice->u.usendv.list && aice->u.usendv.size, tb_false);
-
- // the aico
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)aice->aico;
- tb_assert_and_check_return_val(aico && aico->base.handle, tb_false);
-
- // init olap
- tb_memset(&aico->olap, 0, sizeof(tb_iocp_olap_t));
-
- // init aice
- aico->olap.aice = *aice;
-
- // trace
- tb_trace_d("usendv[%p]: ..", aico);
-
- // load addr
- tb_size_t n = 0;
- struct sockaddr_storage d = {0};
- if (!(n = tb_sockaddr_load(&d, &aice->u.usendv.addr))) return tb_false;
-
- // post timeout first
- tb_iocp_post_timeout(impl, aico);
-
- // done send
- tb_long_t ok = impl->func.WSASendTo((SOCKET)aico->base.handle - 1, (WSABUF*)aico->olap.aice.u.usendv.list, (DWORD)aico->olap.aice.u.usendv.size, tb_null, 0, (struct sockaddr*)&d, (tb_int_t)n, (LPOVERLAPPED)&aico->olap, tb_null);
- tb_trace_d("usendv[%p]: WSASendTo: %ld, error: %d", aico, ok, impl->func.WSAGetLastError());
-
- // ok or pending? continue it
- if (!ok || ((ok == SOCKET_ERROR) && (WSA_IO_PENDING == impl->func.WSAGetLastError()))) return tb_true;
-
- // error?
- if (ok == SOCKET_ERROR)
- {
- // done error
- switch (impl->func.WSAGetLastError())
- {
- // closed?
- case WSAECONNABORTED:
- case WSAECONNRESET:
- aico->olap.aice.state = TB_STATE_CLOSED;
- break;
- // failed?
- default:
- aico->olap.aice.state = TB_STATE_FAILED;
- break;
- }
-
- // post closed or failed
- if (PostQueuedCompletionStatus(impl->port, 0, (ULONG_PTR)aico, (LPOVERLAPPED)&aico->olap)) return tb_true;
- }
-
- // remove timeout task
- tb_iocp_post_timeout_cancel(impl, aico);
-
- // failed
- return tb_false;
-}
-static tb_bool_t tb_iocp_post_sendf(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(impl && impl->port && impl->base.aicp, tb_false);
-
- // check aice
- tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_SENDF, tb_false);
- tb_assert_and_check_return_val(aice->u.sendf.file && aice->u.sendf.size, tb_false);
-
- // the aico
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)aice->aico;
- tb_assert_and_check_return_val(aico && aico->base.handle, tb_false);
-
- // init olap
- tb_memset(&aico->olap, 0, sizeof(tb_iocp_olap_t));
- aico->olap.base.Offset = (DWORD)aice->u.sendf.seek;
-
- // init aice
- aico->olap.aice = *aice;
-
- // trace
- tb_trace_d("sendf[%p]: ..", aico);
-
- // not supported?
- if (!impl->func.TransmitFile)
- {
- // post not supported
- aico->olap.aice.state = TB_STATE_NOT_SUPPORTED;
- return PostQueuedCompletionStatus(impl->port, 0, (ULONG_PTR)aico, (LPOVERLAPPED)&aico->olap)? tb_true : tb_false;
- }
-
- // post timeout first
- tb_iocp_post_timeout(impl, aico);
-
- // done send
- tb_long_t real = impl->func.TransmitFile((SOCKET)aico->base.handle - 1, (HANDLE)aice->u.sendf.file, (DWORD)aice->u.sendf.size, (1 << 16), (LPOVERLAPPED)&aico->olap, tb_null, 0);
- tb_trace_d("sendf[%p]: TransmitFile: %ld, size: %llu, error: %d", aico, real, aice->u.sendf.size, impl->func.WSAGetLastError());
-
- // pending? continue it
- if (!real || WSA_IO_PENDING == impl->func.WSAGetLastError()) return tb_true;
-
- // ok?
- if (real > 0)
- {
- // post ok
- aico->olap.aice.state = TB_STATE_OK;
- aico->olap.aice.u.sendf.real = real;
- if (PostQueuedCompletionStatus(impl->port, 0, (ULONG_PTR)aico, (LPOVERLAPPED)&aico->olap)) return tb_true;
- }
- else
- {
- // done error
- switch (impl->func.WSAGetLastError())
- {
- // closed?
- case WSAECONNABORTED:
- case WSAECONNRESET:
- aico->olap.aice.state = TB_STATE_CLOSED;
- break;
- // failed?
- default:
- aico->olap.aice.state = TB_STATE_FAILED;
- break;
- }
-
- // post closed or failed
- if (PostQueuedCompletionStatus(impl->port, 0, (ULONG_PTR)aico, (LPOVERLAPPED)&aico->olap)) return tb_true;
- }
-
- // remove timeout task
- tb_iocp_post_timeout_cancel(impl, aico);
-
- // failed
- return tb_false;
-}
-static tb_bool_t tb_iocp_post_read(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(impl && impl->port && impl->base.aicp, tb_false);
-
- // check aice
- tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_READ, tb_false);
- tb_assert_and_check_return_val(aice->u.read.data && aice->u.read.size, tb_false);
-
- // the aico
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)aice->aico;
- tb_assert_and_check_return_val(aico && aico->base.handle, tb_false);
-
- // init olap
- tb_memset(&aico->olap, 0, sizeof(tb_iocp_olap_t));
- aico->olap.base.Offset = (DWORD)aice->u.read.seek;
-
- // init aice
- aico->olap.aice = *aice;
-
- // trace
- tb_trace_d("read[%p]: ..", aico);
-
- // done read
- DWORD real = 0;
- BOOL ok = ReadFile((HANDLE)aico->base.handle, aice->u.read.data, (DWORD)aice->u.read.size, &real, (LPOVERLAPPED)&aico->olap);
- tb_trace_d("read[%p]: ReadFile: %u, size: %lu, error: %d, ok: %d", aico, real, aice->u.read.size, GetLastError(), ok);
-
- // finished or pending? continue it
- if (ok || ERROR_IO_PENDING == GetLastError()) return tb_true;
-
- // post failed
- aico->olap.aice.state = TB_STATE_FAILED;
- if (PostQueuedCompletionStatus(impl->port, 0, (ULONG_PTR)aico, (LPOVERLAPPED)&aico->olap)) return tb_true;
-
- // failed
- return tb_false;
-}
-static tb_bool_t tb_iocp_post_writ(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(impl && impl->port && impl->base.aicp, tb_false);
-
- // check aice
- tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_WRIT, tb_false);
- tb_assert_and_check_return_val(aice->u.writ.data && aice->u.writ.size, tb_false);
-
- // the aico
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)aice->aico;
- tb_assert_and_check_return_val(aico && aico->base.handle, tb_false);
-
- // init olap
- tb_memset(&aico->olap, 0, sizeof(tb_iocp_olap_t));
- aico->olap.base.Offset = (DWORD)aice->u.writ.seek;
-
- // init aice
- aico->olap.aice = *aice;
-
- // trace
- tb_trace_d("writ[%p]: ..", aico);
-
- // done writ
- DWORD real = 0;
- BOOL ok = WriteFile((HANDLE)aico->base.handle, aice->u.writ.data, (DWORD)aice->u.writ.size, &real, (LPOVERLAPPED)&aico->olap);
- tb_trace_d("writ[%p]: WriteFile: %u, size: %lu, error: %d, ok: %d", aico, real, aice->u.writ.size, GetLastError(), ok);
-
- // finished or pending? continue it
- if (ok || ERROR_IO_PENDING == GetLastError()) return tb_true;
-
- // post failed
- aico->olap.aice.state = TB_STATE_FAILED;
- if (PostQueuedCompletionStatus(impl->port, 0, (ULONG_PTR)aico, (LPOVERLAPPED)&aico->olap)) return tb_true;
-
- // failed
- return tb_false;
-}
-static tb_bool_t tb_iocp_post_readv(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(impl && impl->port && impl->base.aicp, tb_false);
-
- // check aice
- tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_READV, tb_false);
- tb_assert_and_check_return_val(aice->u.readv.list && aice->u.readv.size, tb_false);
-
- // the aico
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)aice->aico;
- tb_assert_and_check_return_val(aico && aico->base.handle, tb_false);
-
- // init olap
- tb_memset(&aico->olap, 0, sizeof(tb_iocp_olap_t));
- aico->olap.base.Offset = (DWORD)aice->u.readv.seek;
-
- // init aice
- aico->olap.aice = *aice;
-
- // trace
- tb_trace_d("readv[%p]: ..", aico);
-
- // done read
- DWORD real = 0;
- BOOL ok = ReadFile((HANDLE)aico->base.handle, aice->u.readv.list[0].data, (DWORD)aice->u.readv.list[0].size, &real, (LPOVERLAPPED)&aico->olap);
- tb_trace_d("readv[%p]: ReadFile: %u, error: %d", aico, real, GetLastError());
-
- // finished or pending? continue it
- if (ok || ERROR_IO_PENDING == GetLastError()) return tb_true;
-
- // post failed
- aico->olap.aice.state = TB_STATE_FAILED;
- if (PostQueuedCompletionStatus(impl->port, 0, (ULONG_PTR)aico, (LPOVERLAPPED)&aico->olap)) return tb_true;
-
- // failed
- return tb_false;
-}
-static tb_bool_t tb_iocp_post_writv(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(impl && impl->port && impl->base.aicp, tb_false);
-
- // check aice
- tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_WRITV, tb_false);
- tb_assert_and_check_return_val(aice->u.writv.list && aice->u.writv.size, tb_false);
-
- // the aico
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)aice->aico;
- tb_assert_and_check_return_val(aico && aico->base.handle, tb_false);
-
- // init olap
- tb_memset(&aico->olap, 0, sizeof(tb_iocp_olap_t));
- aico->olap.base.Offset = (DWORD)aice->u.writv.seek;
-
- // init aice
- aico->olap.aice = *aice;
-
- // trace
- tb_trace_d("writv[%p]: ..", aico);
-
- // done writ
- DWORD real = 0;
- BOOL ok = WriteFile((HANDLE)aico->base.handle, aice->u.writv.list[0].data, (DWORD)aice->u.writv.list[0].size, &real, (LPOVERLAPPED)&aico->olap);
- tb_trace_d("writv[%p]: WriteFile: %u, error: %d", aico, real, GetLastError());
-
- // finished or pending? continue it
- if (ok || ERROR_IO_PENDING == GetLastError()) return tb_true;
-
- // post failed
- aico->olap.aice.state = TB_STATE_FAILED;
- if (PostQueuedCompletionStatus(impl->port, 0, (ULONG_PTR)aico, (LPOVERLAPPED)&aico->olap)) return tb_true;
-
- // failed
- return tb_false;
-}
-static tb_bool_t tb_iocp_post_fsync(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(impl && impl->port && impl->base.aicp, tb_false);
-
- // check aice
- tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_FSYNC, tb_false);
-
- // the aico
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)aice->aico;
- tb_assert_and_check_return_val(aico && aico->base.handle, tb_false);
-
- // trace
- tb_trace_d("fsync[%p]: ..", aico);
-
- // init olap
- tb_memset(&aico->olap, 0, sizeof(tb_iocp_olap_t));
-
- // init aice
- aico->olap.aice = *aice;
-
- // post ok
- aico->olap.aice.state = TB_STATE_OK;
- if (PostQueuedCompletionStatus(impl->port, 0, (ULONG_PTR)aico, (LPOVERLAPPED)&aico->olap)) return tb_true;
-
- // failed
- return tb_false;
-}
-static tb_bool_t tb_iocp_post_runtask(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(impl && impl->port && impl->timer && impl->ltimer && impl->wait && impl->base.aicp, tb_false);
-
- // check aice
- tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_RUNTASK, tb_false);
- tb_assert_and_check_return_val(aice->state == TB_STATE_PENDING, tb_false);
- tb_assert_and_check_return_val(aice->u.runtask.when, tb_false);
-
- // the aico
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)aice->aico;
- tb_assert_and_check_return_val(aico && !aico->task, tb_false);
-
- // must be not acpt aico
- tb_assert_and_check_return_val(aico->olap.aice.code != TB_AICE_CODE_ACPT, tb_false);
-
- // init olap
- tb_memset(&aico->olap, 0, sizeof(tb_iocp_olap_t));
-
- // init aice
- aico->olap.aice = *aice;
-
- // now
- tb_hong_t now = tb_cache_time_mclock();
-
- // timeout?
- if (aice->u.runtask.when <= (tb_hize_t)now)
- {
- // trace
- tb_trace_d("runtask: when: %llu, now: %lld: ok", aice->u.runtask.when, now);
-
- // post ok
- aico->olap.aice.state = TB_STATE_OK;
- if (PostQueuedCompletionStatus(impl->port, 0, (ULONG_PTR)aico, (LPOVERLAPPED)&aico->olap)) return tb_true;
- }
- else
- {
- // trace
- tb_trace_d("runtask: when: %llu, now: %lld: ..", aice->u.runtask.when, now);
-
- // add timeout task, is the higher precision timer?
- if (aico->base.handle)
- {
- // the top when
- tb_hize_t top = tb_timer_top(impl->timer);
-
- // add task
- aico->task = tb_timer_task_init_at(impl->timer, aice->u.runtask.when, 0, tb_false, tb_iocp_spak_timeout_runtask, aico);
- aico->bltimer = 0;
-
- // the top task is changed? spak the timer
- if (aico->task && aice->u.runtask.when < top)
- tb_event_post(impl->wait);
- }
- else
- {
- aico->task = tb_ltimer_task_init_at(impl->ltimer, aice->u.runtask.when, 0, tb_false, tb_iocp_spak_timeout_runtask, aico);
- aico->bltimer = 1;
- }
-
- // pending
- return tb_true;
- }
-
- // failed
- return tb_false;
-}
-static tb_bool_t tb_iocp_post_clos(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(impl && impl->port && impl->timer && impl->ltimer && impl->base.aicp, tb_false);
-
- // check aice
- tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_CLOS, tb_false);
-
- // the aico
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)aice->aico;
- tb_assert_and_check_return_val(aico, tb_false);
-
- // trace
- tb_trace_d("clos[%p]: handle: %p, state: %s", aico, aico->base.handle, tb_state_cstr(tb_atomic_get(&aico->base.state)));
-
- // remove the timeout task
- tb_iocp_post_timeout_cancel(impl, aico);
-
- // exit address
- if (aico->addr) tb_free(aico->addr);
- aico->addr = tb_null;
-
- // exit the private data for acpt aice
- if (aico->olap.aice.code == TB_AICE_CODE_ACPT)
- {
- // exit sock
- if (aico->olap.aice.u.acpt.priv[0]) tb_socket_exit((tb_socket_ref_t)aico->olap.aice.u.acpt.priv[0]);
- aico->olap.aice.u.acpt.priv[0] = tb_null;
- }
- // disconnect the socket for reusing it
- else if ( impl->func.DisconnectEx
- && aico->bDisconnectEx
- && !tb_aico_impl_is_killed((tb_aico_impl_t*)aico)) //< disable it if be killed, because DisconnectEx maybe cannot return immediately after calling CancelIo
- {
- // init aice
- aico->olap.aice = *aice;
-
- // disconnect it
- tb_bool_t ok = impl->func.DisconnectEx((SOCKET)aico->base.handle - 1, (LPOVERLAPPED)&aico->olap, TF_REUSE_SOCKET, 0);
- tb_trace_d("clos[%p]: DisconnectEx: %d, error: %d", aico, ok, impl->func.WSAGetLastError());
- if (!ok)
- {
- // pending? continue it
- if (WSA_IO_PENDING == impl->func.WSAGetLastError()) return tb_true;
-
- // trace
- tb_trace_d("clos[%p]: DisconnectEx: unknown error: %d", aico, impl->func.WSAGetLastError());
- }
- else
- {
- // post ok
- aico->olap.aice.state = TB_STATE_OK;
- if (PostQueuedCompletionStatus(impl->port, 0, (ULONG_PTR)aico, (LPOVERLAPPED)&aico->olap)) return tb_true;
- }
- }
-
- // exit the sock
- if (aico->base.type == TB_AICO_TYPE_SOCK)
- {
- // close the socket handle
- if (aico->base.handle) tb_socket_exit((tb_socket_ref_t)aico->base.handle);
- aico->base.handle = tb_null;
- }
- // exit file
- else if (aico->base.type == TB_AICO_TYPE_FILE)
- {
- // exit the file handle
- if (aico->base.handle) tb_file_exit((tb_file_ref_t)aico->base.handle);
- aico->base.handle = tb_null;
- }
-
- // clear impl
- aico->impl = tb_null;
-
- // clear type
- aico->base.type = TB_AICO_TYPE_NONE;
-
- // clear timeout
- tb_size_t i = 0;
- tb_size_t n = tb_arrayn(aico->base.timeout);
- for (i = 0; i < n; i++) aico->base.timeout[i] = -1;
-
- // closed
- tb_atomic_set(&aico->base.state, TB_STATE_CLOSED);
-
- // clear bDisconnectEx
- aico->bDisconnectEx = 0;
-
- // clear olap
- tb_memset(&aico->olap, 0, sizeof(tb_iocp_olap_t));
-
- // init aice
- aico->olap.aice = *aice;
-
- // clos ok
- aico->olap.aice.state = TB_STATE_OK;
-
- // done the aice response function
- aice->func(&aico->olap.aice);
-
- // post ok
- return tb_true;
-}
-static tb_bool_t tb_iocp_post_done(tb_iocp_ptor_impl_t* impl, tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(impl && impl->port && impl->base.aicp && aice, tb_false);
-
- // the aico
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)aice->aico;
- tb_assert_and_check_return_val(aico, tb_false);
-
- // killed?
- if (tb_aico_impl_is_killed((tb_aico_impl_t*)aico) && aice->code != TB_AICE_CODE_CLOS)
- {
- // trace
- tb_trace_d("post[%p]: done: code: %u, type: %lu: killed", aico, aice->code, aico->base.type);
-
- // post the killed state
- aico->olap.aice = *aice;
- aico->olap.aice.state = TB_STATE_KILLED;
- return PostQueuedCompletionStatus(impl->port, 0, (ULONG_PTR)aico, (LPOVERLAPPED)&aico->olap)? tb_true : tb_false;
- }
-
- // no pending? post it directly
- if (aice->state != TB_STATE_PENDING)
- {
- // trace
- tb_trace_d("post[%p]: done: code: %u, type: %lu: directly", aico, aice->code, aico->base.type);
-
- // post it directly
- aico->olap.aice = *aice;
- return PostQueuedCompletionStatus(impl->port, 0, (ULONG_PTR)aico, (LPOVERLAPPED)&aico->olap)? tb_true : tb_false;
- }
-
- // init post
- static tb_bool_t (*s_post[])(tb_iocp_ptor_impl_t* , tb_aice_ref_t) =
- {
- tb_null
- , tb_iocp_post_acpt
- , tb_iocp_post_conn
- , tb_iocp_post_recv
- , tb_iocp_post_send
- , tb_iocp_post_urecv
- , tb_iocp_post_usend
- , tb_iocp_post_recvv
- , tb_iocp_post_sendv
- , tb_iocp_post_urecvv
- , tb_iocp_post_usendv
- , tb_iocp_post_sendf
- , tb_iocp_post_read
- , tb_iocp_post_writ
- , tb_iocp_post_readv
- , tb_iocp_post_writv
- , tb_iocp_post_fsync
- , tb_iocp_post_runtask
- , tb_iocp_post_clos
- };
- tb_assert_and_check_return_val(aice->code < tb_arrayn(s_post) && s_post[aice->code], tb_false);
-
- // trace
- tb_trace_d("post[%p]: done: code: %u, type: %lu: ..", aico, aice->code, aico->base.type);
-
- // post aice
- tb_bool_t ok = s_post[aice->code](impl, aice);
- if (!ok)
- {
- // trace
- tb_trace_e("post[%p]: done: code: %u, type: %lu: failed", aico, aice->code, aico->base.type);
- }
-
- // ok?
- return ok;
-}
-static tb_int_t tb_iocp_post_loop(tb_cpointer_t priv)
-{
- // check
- tb_iocp_ptor_impl_t* impl = (tb_iocp_ptor_impl_t*)priv;
- tb_aicp_impl_t* aicp = impl? impl->base.aicp : tb_null;
- tb_assert_and_check_return_val(impl && impl->wait && aicp, -1);
- tb_assert_and_check_return_val(impl->timer && impl->ltimer, -1);
- tb_assert_and_check_return_val(impl->kill && impl->post[0] && impl->post[1], -1);
-
- // trace
- tb_trace_d("loop: init");
-
- // loop
- tb_aice_t post = {0};
- while (1)
- {
- // clear post
- post.code = TB_AICE_CODE_NONE;
-
- // enter
- tb_spinlock_enter(&impl->lock);
-
- // post aice from the higher priority queue first
- if (!tb_queue_null(impl->post[0]))
- {
- // get resp
- tb_aice_ref_t aice = (tb_aice_ref_t)tb_queue_get(impl->post[0]);
- if (aice)
- {
- // save post
- post = *aice;
-
- // trace
- tb_trace_d("loop: post: code: %lu, priority: 0, size: %lu", aice->code, tb_queue_size(impl->post[0]));
-
- // pop it
- tb_queue_pop(impl->post[0]);
- }
- }
-
- // no aice? post aice from the lower priority queue next
- if (post.code == TB_AICE_CODE_NONE && !tb_queue_null(impl->post[1]))
- {
- // get resp
- tb_aice_ref_t aice = (tb_aice_ref_t)tb_queue_get(impl->post[1]);
- if (aice)
- {
- // save post
- post = *aice;
-
- // trace
- tb_trace_d("loop: post: code: %lu, priority: 1, size: %lu", aice->code, tb_queue_size(impl->post[1]));
-
- // pop it
- tb_queue_pop(impl->post[1]);
- }
- }
-
- // kill some handles
- tb_for_all (HANDLE, handle, impl->kill)
- {
- // trace
- tb_trace_d("loop: cancel[%p]: ..", handle);
-
- // CancelIo it
- if (!CancelIo(handle))
- {
- // trace
- tb_trace_e("loop: cancel[%p]: failed: %u", handle, GetLastError());
- }
- }
-
- // clear the killed list
- tb_vector_clear(impl->kill);
-
- // leave
- tb_spinlock_leave(&impl->lock);
-
- // done post
- if (post.code != TB_AICE_CODE_NONE && !tb_iocp_post_done(impl, &post)) break;
-
- // spak ctime
- tb_cache_time_spak();
-
- // spak timer
- if (!tb_timer_spak(impl->timer)) break;
-
- // spak ltimer
- if (!tb_ltimer_spak(impl->ltimer)) break;
-
- // null? wait it
- tb_check_continue(post.code == TB_AICE_CODE_NONE);
-
- // killed? break it
- tb_check_break(!tb_atomic_get(&aicp->kill));
-
- // the delay
- tb_size_t delay = tb_timer_delay(impl->timer);
-
- // the ldelay
- tb_size_t ldelay = tb_ltimer_delay(impl->ltimer);
- tb_assert_and_check_break(ldelay != -1);
-
- // using the min delay
- if (ldelay < delay) delay = ldelay;
-
- // trace
- tb_trace_d("loop: wait: %lu ms: ..", delay);
-
- // wait some time
- if (delay && tb_event_wait(impl->wait, delay) < 0) break;
- }
-
- // trace
- tb_trace_d("loop: exit");
-
- // kill
- tb_atomic_set(&aicp->kill, 1);
-
- // exit
- return 0;
-}
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
- */
-static tb_bool_t tb_iocp_ptor_addo(tb_aicp_ptor_impl_t* ptor, tb_aico_impl_t* aico)
-{
- // check
- tb_iocp_ptor_impl_t* impl = (tb_iocp_ptor_impl_t*)ptor;
- tb_assert_and_check_return_val(impl && aico, tb_false);
-
- // check alignment
- tb_assert_and_check_return_val(!((tb_size_t)aico & (TB_CPU_BITBYTE - 1)), tb_false);
-
- // trace
- tb_trace_d("addo[%p], handle: %p", aico, aico->handle);
-
- // done
- switch (aico->type)
- {
- case TB_AICO_TYPE_SOCK:
- {
- // check
- tb_assert_and_check_return_val(impl->port && aico->handle, tb_false);
-
- // add aico to port
- HANDLE port = CreateIoCompletionPort((HANDLE)((SOCKET)aico->handle - 1), impl->port, (ULONG_PTR)aico, 0);
- if ( port != impl->port
- && !( impl->func.DisconnectEx
- && ((tb_iocp_aico_t*)aico)->bDisconnectEx))
- {
- // trace
- tb_trace_e("CreateIoCompletionPort failed: %d, aico: %p, handle: %p", GetLastError(), aico, aico->handle);
- return tb_false;
- }
- }
- break;
- case TB_AICO_TYPE_FILE:
- {
- // check
- tb_assert_and_check_return_val(impl->port && aico->handle, tb_false);
-
- // add aico to port
- HANDLE port = CreateIoCompletionPort((HANDLE)aico->handle, impl->port, (ULONG_PTR)aico, 0);
- if (port != impl->port)
- {
- // trace
- tb_trace_e("CreateIoCompletionPort failed: %d, aico: %p, handle: %p", GetLastError(), aico, aico->handle);
- return tb_false;
- }
- }
- break;
- case TB_AICO_TYPE_TASK:
- {
- }
- break;
- default:
- tb_assert_and_check_return_val(0, tb_false);
- break;
- }
-
- // init the iocp aico
- tb_iocp_aico_t* iocp_aico = (tb_iocp_aico_t*)aico;
- iocp_aico->impl = impl;
- iocp_aico->addr = tb_null;
-
- // ok
- return tb_true;
-}
-static tb_void_t tb_iocp_ptor_kilo(tb_aicp_ptor_impl_t* ptor, tb_aico_impl_t* aico)
-{
- // check
- tb_iocp_ptor_impl_t* impl = (tb_iocp_ptor_impl_t*)ptor;
- tb_assert_and_check_return(impl && impl->wait && impl->kill && aico);
-
- // trace
- tb_trace_d("kill[%p]: handle: %p, type: %u", aico, aico->handle, aico->type);
-
- // the handle
- HANDLE handle = aico->type == TB_AICO_TYPE_SOCK? (HANDLE)((SOCKET)aico->handle - 1) : aico->handle;
-
- // the iocp aico
- tb_iocp_aico_t* iocp_aico = (tb_iocp_aico_t*)aico;
-
- // kill the task
- if (iocp_aico->task)
- {
- // trace
- tb_trace_d("kill: aico: %p, type: %u, task: %p: ..", aico, aico->type, iocp_aico->task);
-
- // kill task
- if (iocp_aico->bltimer) tb_ltimer_task_kill(impl->ltimer, (tb_ltimer_task_ref_t)iocp_aico->task);
- else tb_timer_task_kill(impl->timer, (tb_timer_task_ref_t)iocp_aico->task);
- }
- // append the killing handle
- else
- {
- // trace
- tb_trace_d("kill: aico: %p, type: %u, handle: %p: ..", aico, aico->type, handle);
-
- // kill handle
- tb_spinlock_enter(&impl->lock);
- tb_vector_insert_tail(impl->kill, (tb_cpointer_t)handle);
- tb_spinlock_leave(&impl->lock);
- }
-
- /* the iocp will wait long time if the lastest task wait period is too long
- * so spak the iocp manually for spak the timer
- */
- tb_event_post(impl->wait);
-}
-static tb_bool_t tb_iocp_ptor_post(tb_aicp_ptor_impl_t* ptor, tb_aice_ref_t aice)
-{
- // check
- tb_iocp_ptor_impl_t* impl = (tb_iocp_ptor_impl_t*)ptor;
- tb_assert_and_check_return_val(impl && impl->wait && aice && aice->aico, tb_false);
-
- // the priority
- tb_size_t priority = tb_aice_impl_priority(aice);
- tb_assert_and_check_return_val(priority < tb_arrayn(impl->post) && impl->post[priority], tb_false);
-
- // enter
- tb_spinlock_enter(&impl->lock);
-
- // done
- tb_bool_t ok = tb_false;
- do
- {
- // post aice
- if (tb_queue_full(impl->post[priority]))
- {
- // trace
- tb_trace_e("post: code: %lu, priority: %lu, size: %lu: failed", aice->code, priority, tb_queue_size(impl->post[priority]));
- break;
- }
-
- // put
- tb_queue_put(impl->post[priority], aice);
-
- // trace
- tb_trace_d("post: code: %lu, priority: %lu, size: %lu: ..", aice->code, priority, tb_queue_size(impl->post[priority]));
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // leave
- tb_spinlock_leave(&impl->lock);
-
- // work it
- if (ok) tb_event_post(impl->wait);
-
- // ok?
- return ok;
-}
-static tb_void_t tb_iocp_ptor_kill(tb_aicp_ptor_impl_t* ptor)
-{
- // check
- tb_iocp_ptor_impl_t* impl = (tb_iocp_ptor_impl_t*)ptor;
- tb_assert_and_check_return(impl && impl->port && impl->wait && ptor->aicp);
-
- // the workers
- tb_size_t work = tb_atomic_get(&ptor->aicp->work);
-
- // trace
- tb_trace_d("kill: %lu", work);
-
- // post the timer wait
- tb_event_post(impl->wait);
-
- // using GetQueuedCompletionStatusEx?
- if (impl->func.GetQueuedCompletionStatusEx)
- {
- // kill workers
- while (work--)
- {
- // post kill
- PostQueuedCompletionStatus(impl->port, 0, 0, tb_null);
-
- // wait some time
- tb_msleep(200);
- }
- }
- else
- {
- // kill workers
- while (work--) PostQueuedCompletionStatus(impl->port, 0, 0, tb_null);
- }
-}
-static tb_void_t tb_iocp_ptor_exit(tb_aicp_ptor_impl_t* ptor)
-{
- tb_iocp_ptor_impl_t* impl = (tb_iocp_ptor_impl_t*)ptor;
- if (impl)
- {
- // trace
- tb_trace_d("exit");
-
- // post the timer wait
- if (impl->wait) tb_event_post(impl->wait);
-
- // exit loop
- if (impl->loop)
- {
- tb_long_t wait = 0;
- if ((wait = tb_thread_wait(impl->loop, 5000, tb_null)) <= 0)
- {
- // trace
- tb_trace_e("loop[%p]: wait failed: %ld!", impl->loop, wait);
- }
- tb_thread_exit(impl->loop);
- impl->loop = tb_null;
- }
-
- // enter
- tb_spinlock_enter(&impl->lock);
-
- // exit post
- if (impl->post[0]) tb_queue_exit(impl->post[0]);
- if (impl->post[1]) tb_queue_exit(impl->post[1]);
- impl->post[0] = tb_null;
- impl->post[1] = tb_null;
-
- // exit kill
- if (impl->kill) tb_vector_exit(impl->kill);
- impl->kill = tb_null;
-
- // leave
- tb_spinlock_leave(&impl->lock);
-
- // exit port
- if (impl->port) CloseHandle(impl->port);
- impl->port = tb_null;
-
- // exit timer
- if (impl->timer) tb_timer_exit(impl->timer);
- impl->timer = tb_null;
-
- // exit ltimer
- if (impl->ltimer) tb_ltimer_exit(impl->ltimer);
- impl->ltimer = tb_null;
-
- // exit wait
- if (impl->wait) tb_event_exit(impl->wait);
- impl->wait = tb_null;
-
- // exit lock
- tb_spinlock_exit(&impl->lock);
-
- // free it
- tb_free(impl);
- }
-}
-static tb_void_t tb_iocp_ptor_loop_exit(tb_aicp_ptor_impl_t* ptor, tb_handle_t hloop)
-{
- // check
- tb_iocp_ptor_impl_t* impl = (tb_iocp_ptor_impl_t*)ptor;
- tb_assert_and_check_return(impl);
-
- // the loop
- tb_iocp_loop_t* loop = (tb_iocp_loop_t*)hloop;
- tb_assert_and_check_return(loop);
-
- // exit spak
- if (loop->spak) tb_queue_exit(loop->spak);
- loop->spak = tb_null;
-
- // exit self
- loop->self = 0;
-
- // exit loop
- tb_free(loop);
-}
-static tb_handle_t tb_iocp_ptor_loop_init(tb_aicp_ptor_impl_t* ptor)
-{
- // check
- tb_iocp_ptor_impl_t* impl = (tb_iocp_ptor_impl_t*)ptor;
- tb_assert_and_check_return_val(impl, tb_null);
-
- // done
- tb_bool_t ok = tb_false;
- tb_iocp_loop_t* loop = tb_null;
- do
- {
- // make loop
- loop = tb_malloc0_type(tb_iocp_loop_t);
- tb_assert_and_check_break(loop);
-
- // init self
- loop->self = tb_thread_self();
- tb_assert_and_check_break(loop->self);
-
- // init spak
- if (impl->func.GetQueuedCompletionStatusEx)
- {
- loop->spak = tb_queue_init(64, tb_element_mem(sizeof(tb_OVERLAPPED_ENTRY_t), tb_null, tb_null));
- tb_assert_and_check_break(loop->spak);
- }
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // failed?
- if (!ok)
- {
- // exit it
- if (loop) tb_iocp_ptor_loop_exit(ptor, (tb_handle_t)loop);
- loop = tb_null;
- }
-
- // ok?
- return (tb_handle_t)loop;
-}
-static tb_long_t tb_iocp_ptor_loop_spak(tb_aicp_ptor_impl_t* ptor, tb_handle_t hloop, tb_aice_ref_t resp, tb_long_t timeout)
-{
- // check
- tb_iocp_ptor_impl_t* impl = (tb_iocp_ptor_impl_t*)ptor;
- tb_assert_and_check_return_val(impl && impl->port && impl->timer && resp, -1);
-
- // the loop
- tb_iocp_loop_t* loop = (tb_iocp_loop_t*)hloop;
- tb_assert_and_check_return_val(loop, -1);
-
- // trace
- tb_trace_d("spak[%lu]: ..", loop->self);
-
- // exists GetQueuedCompletionStatusEx? using it
- if (impl->func.GetQueuedCompletionStatusEx)
- {
- // check
- tb_assert_and_check_return_val(loop->spak, -1);
-
- // exists olap? spak it first
- if (!tb_queue_null(loop->spak))
- {
- // the top entry
- tb_LPOVERLAPPED_ENTRY_t entry = (tb_LPOVERLAPPED_ENTRY_t)tb_queue_get(loop->spak);
- tb_assert_and_check_return_val(entry, -1);
-
- // init
- tb_size_t real = (tb_size_t)entry->dwNumberOfBytesTransferred;
- tb_iocp_aico_t* aico = (tb_iocp_aico_t*)entry->lpCompletionKey;
- tb_iocp_olap_t* olap = (tb_iocp_olap_t*)entry->lpOverlapped;
- tb_size_t error = tb_ntstatus_to_winerror((tb_size_t)entry->Internal);
- tb_trace_d("spak[%lu]: aico: %p, ntstatus: %lx, winerror: %lu", loop->self, aico, (tb_size_t)entry->Internal, error);
-
- // pop the entry
- tb_queue_pop(loop->spak);
-
- // check
- tb_assert_and_check_return_val(olap && aico, -1);
-
- // save resp
- *resp = olap->aice;
-
- // spak resp
- return tb_iocp_spak_done(impl, resp, real, error);
- }
- else
- {
- // clear error first
- SetLastError(ERROR_SUCCESS);
-
- // wait
- DWORD size = 0;
- BOOL wait = impl->func.GetQueuedCompletionStatusEx(impl->port, loop->list, (DWORD)tb_arrayn(loop->list), &size, (DWORD)timeout, FALSE);
-
- // the last error
- tb_size_t error = (tb_size_t)GetLastError();
-
- // trace
- tb_trace_d("spak[%lu]: wait: %d, size: %u, error: %lu", loop->self, wait, size, error);
-
- // timeout?
- if (!wait && error == WAIT_TIMEOUT) return 0;
-
- // error?
- tb_assert_and_check_return_val(wait, -1);
-
- // put entries to the spak queue
- tb_size_t i = 0;
- for (i = 0; i < size; i++)
- {
- // the aico and olap
- tb_iocp_aico_t* aico = (tb_iocp_aico_t* )loop->list[i].lpCompletionKey;
- tb_iocp_olap_t* olap = (tb_iocp_olap_t*)loop->list[i].lpOverlapped;
-
- // aicp killed?
- tb_check_return_val(aico, -1);
-
- /* update aico
- *
- * the aico cannot be binded again if using DisconnectEx
- */
- if ( impl->func.DisconnectEx
- && olap
- && olap->aice.aico
- && ((tb_iocp_aico_t*)olap->aice.aico)->bDisconnectEx)
- {
- aico = (tb_iocp_aico_t*)olap->aice.aico;
- loop->list[i].lpCompletionKey = (ULONG_PTR)aico;
- }
-
- // remove task first
- tb_iocp_post_timeout_cancel(impl, aico);
-
- // full?
- if (!tb_queue_full(loop->spak))
- {
- // put it
- tb_queue_put(loop->spak, &loop->list[i]);
- }
- else
- {
- // full
- tb_assert_and_check_return_val(0, -1);
- }
- }
-
- // continue
- return 0;
- }
- }
- else
- {
- // clear error first
- SetLastError(ERROR_SUCCESS);
-
- // wait
- DWORD real = 0;
- tb_iocp_aico_t* aico = tb_null;
- tb_iocp_olap_t* olap = tb_null;
- BOOL wait = GetQueuedCompletionStatus(impl->port, (LPDWORD)&real, (PULONG_PTR)&aico, (LPOVERLAPPED*)&olap, (DWORD)(timeout < 0? INFINITE : timeout));
-
- // the last error
- tb_size_t error = (tb_size_t)GetLastError();
-
- // trace
- tb_trace_d("spak[%lu]: aico: %p, wait: %d, real: %u, error: %lu", loop->self, aico, wait, real, error);
-
- // timeout?
- if (!wait && error == WAIT_TIMEOUT) return 0;
-
- // aicp killed?
- if (wait && !aico) return -1;
-
- /* update aico
- *
- * the aico cannot be binded again if using DisconnectEx
- */
- if ( impl->func.DisconnectEx
- && olap
- && olap->aice.aico
- && ((tb_iocp_aico_t*)olap->aice.aico)->bDisconnectEx)
- {
- aico = (tb_iocp_aico_t*)olap->aice.aico;
- }
-
- // exit the aico task
- if (aico)
- {
- // remove task
- if (aico->task)
- {
- if (aico->bltimer) tb_ltimer_task_exit(impl->ltimer, (tb_ltimer_task_ref_t)aico->task);
- else tb_timer_task_exit(impl->timer, (tb_timer_task_ref_t)aico->task);
- aico->bltimer = 0;
- }
- aico->task = tb_null;
- }
-
- // check
- tb_assert_and_check_return_val(olap, -1);
-
- // check
- tb_assert(aico == (tb_iocp_aico_t*)olap->aice.aico);
-
- // save resp
- *resp = olap->aice;
-
- // spak resp
- return tb_iocp_spak_done(impl, resp, (tb_size_t)real, error);
- }
-
- // failed
- return -1;
-}
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * interfaces
- */
-static tb_aicp_ptor_impl_t* tb_iocp_ptor_init(tb_aicp_impl_t* aicp)
-{
- // check
- tb_assert_and_check_return_val(aicp && aicp->maxn, tb_null);
-
- // check iovec
- tb_assert_static(sizeof(tb_iovec_t) == sizeof(WSABUF));
- tb_assert_and_check_return_val(tb_memberof_eq(tb_iovec_t, data, WSABUF, buf), tb_null);
- tb_assert_and_check_return_val(tb_memberof_eq(tb_iovec_t, size, WSABUF, len), tb_null);
-
- // done
- tb_bool_t ok = tb_false;
- tb_iocp_ptor_impl_t* impl = tb_null;
- do
- {
- // make ptor
- impl = tb_malloc0_type(tb_iocp_ptor_impl_t);
- tb_assert_and_check_break(impl);
-
- // init base
- impl->base.aicp = aicp;
- impl->base.step = sizeof(tb_iocp_aico_t);
- impl->base.kill = tb_iocp_ptor_kill;
- impl->base.exit = tb_iocp_ptor_exit;
- impl->base.addo = tb_iocp_ptor_addo;
- impl->base.kilo = tb_iocp_ptor_kilo;
- impl->base.post = tb_iocp_ptor_post;
- impl->base.loop_init = tb_iocp_ptor_loop_init;
- impl->base.loop_exit = tb_iocp_ptor_loop_exit;
- impl->base.loop_spak = tb_iocp_ptor_loop_spak;
-
- // init func
- impl->func.AcceptEx = tb_mswsock()->AcceptEx;
- impl->func.ConnectEx = tb_mswsock()->ConnectEx;
- impl->func.DisconnectEx = tb_mswsock()->DisconnectEx;
- impl->func.TransmitFile = tb_mswsock()->TransmitFile;
- impl->func.GetAcceptExSockaddrs = tb_mswsock()->GetAcceptExSockaddrs;
- impl->func.GetQueuedCompletionStatusEx = tb_kernel32()->GetQueuedCompletionStatusEx;
- impl->func.WSAGetLastError = tb_ws2_32()->WSAGetLastError;
- impl->func.WSASend = tb_ws2_32()->WSASend;
- impl->func.WSARecv = tb_ws2_32()->WSARecv;
- impl->func.WSASendTo = tb_ws2_32()->WSASendTo;
- impl->func.WSARecvFrom = tb_ws2_32()->WSARecvFrom;
- impl->func.bind = tb_ws2_32()->bind;
- tb_assert_and_check_break(impl->func.AcceptEx);
- tb_assert_and_check_break(impl->func.ConnectEx);
- tb_assert_and_check_break(impl->func.WSAGetLastError);
- tb_assert_and_check_break(impl->func.WSASend);
- tb_assert_and_check_break(impl->func.WSARecv);
- tb_assert_and_check_break(impl->func.WSASendTo);
- tb_assert_and_check_break(impl->func.WSARecvFrom);
- tb_assert_and_check_break(impl->func.bind);
-
- // init lock
- if (!tb_spinlock_init(&impl->lock)) break;
-
- // init port
- impl->port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, tb_null, 0, 0);
- tb_assert_and_check_break(impl->port && impl->port != INVALID_HANDLE_VALUE);
-
- // init timer and using cache time
- impl->timer = tb_timer_init(aicp->maxn >> 8, tb_true);
- tb_assert_and_check_break(impl->timer);
-
- // init ltimer and using cache time
- impl->ltimer = tb_ltimer_init(aicp->maxn >> 8, TB_LTIMER_TICK_S, tb_true);
- tb_assert_and_check_break(impl->ltimer);
-
- // init wait
- impl->wait = tb_event_init();
- tb_assert_and_check_break(impl->wait);
-
- // init post
- impl->post[0] = tb_queue_init((aicp->maxn >> 4) + 16, tb_element_mem(sizeof(tb_aice_t), tb_null, tb_null));
- impl->post[1] = tb_queue_init((aicp->maxn >> 4) + 16, tb_element_mem(sizeof(tb_aice_t), tb_null, tb_null));
- tb_assert_and_check_break(impl->post[0] && impl->post[1]);
-
- // init kill
- impl->kill = tb_vector_init((aicp->maxn >> 6) + 16, tb_element_ptr(tb_null, tb_null));
- tb_assert_and_check_break(impl->kill);
-
- // register lock profiler
-#ifdef TB_LOCK_PROFILER_ENABLE
- tb_lock_profiler_register(tb_lock_profiler(), (tb_pointer_t)&impl->lock, "aicp_iocp");
-#endif
-
- // init the timer loop
- impl->loop = tb_thread_init(tb_null, tb_iocp_post_loop, impl, 0);
- tb_assert_and_check_break(impl->loop);
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // failed?
- if (!ok)
- {
- // exit it
- if (impl) tb_iocp_ptor_exit((tb_aicp_ptor_impl_t*)impl);
- return tb_null;
- }
-
- // ok?
- return (tb_aicp_ptor_impl_t*)impl;
-}
-
diff --git a/core/src/tbox/src/tbox/platform/deprecated/aioo_poll.c b/core/src/tbox/src/tbox/platform/deprecated/aioo_poll.c
deleted file mode 100644
index ae54773b0..000000000
--- a/core/src/tbox/src/tbox/platform/deprecated/aioo_poll.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*!The Treasure Box Library
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
- *
- * @author ruki
- * @file aioo_poll.c
- *
- */
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
- */
-#include "prefix.h"
-#include <sys/poll.h>
-#include <sys/socket.h>
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
- */
-static tb_long_t tb_aioo_rtor_poll_wait(tb_socket_ref_t sock, tb_size_t code, tb_long_t timeout)
-{
- // check
- tb_assert_and_check_return_val(sock, -1);
-
- // init
- struct pollfd pfd = {0};
- pfd.fd = tb_sock2fd(sock);
- if (code & TB_AIOE_CODE_RECV || code & TB_AIOE_CODE_ACPT) pfd.events |= POLLIN;
- if (code & TB_AIOE_CODE_SEND || code & TB_AIOE_CODE_CONN) pfd.events |= POLLOUT;
-
- // poll
- tb_long_t r = poll(&pfd, 1, timeout);
- tb_assert_and_check_return_val(r >= 0, -1);
-
- // timeout?
- tb_check_return_val(r, 0);
-
- // error?
- tb_int_t o = 0;
- socklen_t n = sizeof(socklen_t);
- getsockopt(pfd.fd, SOL_SOCKET, SO_ERROR, &o, &n);
- if (o) return -1;
-
- // ok
- tb_long_t e = 0;
- if (pfd.revents & POLLIN)
- {
- e |= TB_AIOE_CODE_RECV;
- if (code & TB_AIOE_CODE_ACPT) e |= TB_AIOE_CODE_ACPT;
- }
- if (pfd.revents & POLLOUT)
- {
- e |= TB_AIOE_CODE_SEND;
- if (code & TB_AIOE_CODE_CONN) e |= TB_AIOE_CODE_CONN;
- }
- if ((pfd.revents & POLLHUP) && !(e & (TB_AIOE_CODE_RECV | TB_AIOE_CODE_SEND)))
- e |= TB_AIOE_CODE_RECV | TB_AIOE_CODE_SEND;
- return e;
-}
-
diff --git a/core/src/tbox/src/tbox/platform/deprecated/aioo_select.c b/core/src/tbox/src/tbox/platform/deprecated/aioo_select.c
deleted file mode 100644
index 40dd65910..000000000
--- a/core/src/tbox/src/tbox/platform/deprecated/aioo_select.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*!The Treasure Box Library
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
- *
- * @author ruki
- * @file aioo_select.c
- *
- */
-/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
- */
-#include "prefix.h"
-#ifdef TB_CONFIG_OS_WINDOWS
-# include "../windows/interface/interface.h"
-#else
-# include <sys/select.h>
-#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
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
- */
-static tb_long_t tb_aioo_rtor_select_wait(tb_socket_ref_t sock, tb_size_t code, tb_long_t timeout)
-{
- // check
- tb_assert_and_check_return_val(sock, -1);
-
- // fd
- tb_long_t fd = tb_sock2fd(sock);
- tb_assert_and_check_return_val(fd >= 0, -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;
- }
-
- // init fds
- fd_set rfds;
- fd_set wfds;
- fd_set* prfds = (code & TB_AIOE_CODE_RECV || code & TB_AIOE_CODE_ACPT)? &rfds : tb_null;
- fd_set* pwfds = (code & TB_AIOE_CODE_SEND || code & TB_AIOE_CODE_CONN)? &wfds : tb_null;
-
- if (prfds)
- {
- FD_ZERO(prfds);
- FD_SET(fd, prfds);
- }
-
- if (pwfds)
- {
- FD_ZERO(pwfds);
- FD_SET(fd, pwfds);
- }
-
- // select
-#ifdef TB_CONFIG_OS_WINDOWS
- tb_long_t r = tb_ws2_32()->select((tb_int_t)fd + 1, prfds, pwfds, tb_null, timeout >= 0? &t : tb_null);
-#else
- tb_long_t r = select(fd + 1, prfds, pwfds, tb_null, timeout >= 0? &t : tb_null);
-#endif
- tb_assert_and_check_return_val(r >= 0, -1);
-
- // timeout?
- tb_check_return_val(r, 0);
-
- // error?
- tb_int_t o = 0;
-#ifdef TB_CONFIG_OS_WINDOWS
- tb_int_t n = sizeof(tb_int_t);
- tb_ws2_32()->getsockopt(fd, SOL_SOCKET, SO_ERROR, (tb_char_t*)&o, &n);
-#else
- socklen_t n = sizeof(socklen_t);
- getsockopt(fd, SOL_SOCKET, SO_ERROR, (tb_char_t*)&o, &n);
-#endif
- if (o) return -1;
-
- // ok
- tb_long_t e = 0;
- if (prfds && FD_ISSET(fd, &rfds))
- {
- e |= TB_AIOE_CODE_RECV;
- if (code & TB_AIOE_CODE_ACPT) e |= TB_AIOE_CODE_ACPT;
- }
- if (pwfds && FD_ISSET(fd, &wfds))
- {
- e |= TB_AIOE_CODE_SEND;
- if (code & TB_AIOE_CODE_CONN) e |= TB_AIOE_CODE_CONN;
- }
- return e;
-}
-
diff --git a/core/src/tbox/src/tbox/platform/deprecated/aiop.c b/core/src/tbox/src/tbox/platform/deprecated/aiop.c
deleted file mode 100644
index daa50f27f..000000000
--- a/core/src/tbox/src/tbox/platform/deprecated/aiop.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*!The Treasure Box Library
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
- *
- * @author ruki
- * @file aiop.c
- * @ingroup platform
- */
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * trace
- */
-#define TB_TRACE_MODULE_NAME "platform_aiop"
-#define TB_TRACE_MODULE_DEBUG (0)
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
- */
-#include "prefix.h"
-#include "../../asio/deprecated/impl/prefix.h"
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
- */
-#if defined(TB_CONFIG_OS_WINDOWS)
-# include "../deprecated/aiop_select.c"
- tb_aiop_rtor_impl_t* tb_aiop_rtor_impl_init(tb_aiop_impl_t* aiop)
- {
- return tb_aiop_rtor_select_init(aiop);
- }
-#elif defined(TB_CONFIG_POSIX_HAVE_EPOLL_CREATE) \
- && defined(TB_CONFIG_POSIX_HAVE_EPOLL_WAIT)
-# include "../deprecated/aiop_epoll.c"
- tb_aiop_rtor_impl_t* tb_aiop_rtor_impl_init(tb_aiop_impl_t* aiop)
- {
- return tb_aiop_rtor_epoll_init(aiop);
- }
-#elif defined(TB_CONFIG_OS_MACOSX)
-# include "../deprecated/aiop_kqueue.c"
- tb_aiop_rtor_impl_t* tb_aiop_rtor_impl_init(tb_aiop_impl_t* aiop)
- {
- return tb_aiop_rtor_kqueue_init(aiop);
- }
-#elif defined(TB_CONFIG_POSIX_HAVE_POLL)
-# include "../deprecated/aiop_poll.c"
- tb_aiop_rtor_impl_t* tb_aiop_rtor_impl_init(tb_aiop_impl_t* aiop)
- {
- return tb_aiop_rtor_poll_init(aiop);
- }
-#else
-# error have not available event mode
-#endif
-
diff --git a/core/src/tbox/src/tbox/platform/deprecated/aiop_epoll.c b/core/src/tbox/src/tbox/platform/deprecated/aiop_epoll.c
deleted file mode 100644
index 59fe00186..000000000
--- a/core/src/tbox/src/tbox/platform/deprecated/aiop_epoll.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/*!The Treasure Box Library
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
- *
- * @author ruki
- * @file aiop_epoll.c
- *
- */
-/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
- */
-#include "prefix.h"
-#include "../../asio/deprecated/impl/prefix.h"
-#include <sys/epoll.h>
-#include <fcntl.h>
-#include <errno.h>
-#ifndef TB_CONFIG_OS_ANDROID
-# include <sys/unistd.h>
-#endif
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * types
- */
-
-// the epoll rtor type
-typedef struct __tb_aiop_rtor_epoll_impl_t
-{
- // the rtor base
- tb_aiop_rtor_impl_t base;
-
- // the fd
- tb_long_t epfd;
-
- // the events
- struct epoll_event* evts;
- tb_size_t evtn;
-
- // the kill
- tb_handle_t kill[2];
-
-}tb_aiop_rtor_epoll_impl_t;
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
- */
-static tb_bool_t tb_aiop_rtor_epoll_addo(tb_aiop_rtor_impl_t* rtor, tb_aioo_impl_t const* aioo)
-{
- // check
- tb_aiop_rtor_epoll_impl_t* impl = (tb_aiop_rtor_epoll_impl_t*)rtor;
- tb_assert_and_check_return_val(impl && impl->epfd > 0 && aioo && aioo->sock, tb_false);
-
- // the code
- tb_size_t code = aioo->code;
-
- // init event
- struct epoll_event e = {0};
- if (code & TB_AIOE_CODE_RECV || code & TB_AIOE_CODE_ACPT) e.events |= EPOLLIN;
- if (code & TB_AIOE_CODE_SEND || code & TB_AIOE_CODE_CONN) e.events |= EPOLLOUT;
- if (code & TB_AIOE_CODE_CLEAR) e.events |= EPOLLET;
-#ifdef EPOLLONESHOT
- if (code & TB_AIOE_CODE_ONESHOT) e.events |= EPOLLONESHOT;
-#endif
- e.data.u64 = tb_p2u64(aioo);
-
- // add aioo
- if (epoll_ctl(impl->epfd, EPOLL_CTL_ADD, tb_sock2fd(aioo->sock), &e) < 0)
- {
- // trace
- tb_trace_e("addo aioo[%p], code: %lu failed, errno: %d", aioo, code, errno);
- return tb_false;
- }
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_aiop_rtor_epoll_delo(tb_aiop_rtor_impl_t* rtor, tb_aioo_impl_t const* aioo)
-{
- // check
- tb_aiop_rtor_epoll_impl_t* impl = (tb_aiop_rtor_epoll_impl_t*)rtor;
- tb_assert_and_check_return_val(impl && impl->epfd > 0 && aioo && aioo->sock, tb_false);
-
- // init event
- struct epoll_event e = {0};
- if (epoll_ctl(impl->epfd, EPOLL_CTL_DEL, tb_sock2fd(aioo->sock), &e) < 0)
- {
- // trace
- tb_trace_e("delo aioo[%p] failed, errno: %d", aioo, errno);
- return tb_false;
- }
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_aiop_rtor_epoll_post(tb_aiop_rtor_impl_t* rtor, tb_aioe_ref_t aioe)
-{
- // check
- tb_aiop_rtor_epoll_impl_t* impl = (tb_aiop_rtor_epoll_impl_t*)rtor;
- tb_assert_and_check_return_val(impl && impl->epfd > 0 && aioe, tb_false);
-
- // the code
- tb_size_t code = aioe->code;
-
- // the priv
- tb_cpointer_t priv = aioe->priv;
-
- // the aioo
- tb_aioo_impl_t* aioo = (tb_aioo_impl_t*)aioe->aioo;
- tb_assert_and_check_return_val(aioo && aioo->sock, tb_false);
-
- // init event
- struct epoll_event e = {0};
- if (code & TB_AIOE_CODE_RECV || code & TB_AIOE_CODE_ACPT) e.events |= EPOLLIN;
- if (code & TB_AIOE_CODE_SEND || code & TB_AIOE_CODE_CONN) e.events |= EPOLLOUT;
- if (code & TB_AIOE_CODE_CLEAR) e.events |= EPOLLET;
-#ifdef EPOLLONESHOT
- if (code & TB_AIOE_CODE_ONESHOT) e.events |= EPOLLONESHOT;
-#endif
- e.data.u64 = tb_p2u64(aioo);
-
- // save aioo
- tb_aioo_impl_t prev = *aioo;
- aioo->code = code;
- aioo->priv = priv;
-
- // sete
- if (epoll_ctl(impl->epfd, EPOLL_CTL_MOD, tb_sock2fd(aioo->sock), &e) < 0)
- {
- // re-add it
-#ifndef EPOLLONESHOT
- if (errno == ENOENT && epoll_ctl(impl->epfd, EPOLL_CTL_ADD, tb_sock2fd(aioo->sock), &e) >= 0)
- return tb_true;
-#endif
-
- // trace
- tb_trace_e("post aice code: %lu failed, errno: %d", code, errno);
-
- // restore aioo
- *aioo = prev;
- return tb_false;
- }
-
- // ok
- return tb_true;
-}
-static tb_long_t tb_aiop_rtor_epoll_wait(tb_aiop_rtor_impl_t* rtor, tb_aioe_ref_t list, tb_size_t maxn, tb_long_t timeout)
-{
- // check
- tb_aiop_rtor_epoll_impl_t* impl = (tb_aiop_rtor_epoll_impl_t*)rtor;
- tb_assert_and_check_return_val(impl && impl->epfd > 0, -1);
-
- // the aiop
- tb_aiop_impl_t* aiop = rtor->aiop;
- tb_assert_and_check_return_val(aiop, -1);
-
- // init grow
- tb_size_t grow = tb_align8((rtor->aiop->maxn >> 3) + 1);
-
- // init events
- if (!impl->evts)
- {
- impl->evtn = grow;
- impl->evts = tb_nalloc0(impl->evtn, sizeof(struct epoll_event));
- tb_assert_and_check_return_val(impl->evts, -1);
- }
-
- // wait events
- tb_long_t evtn = epoll_wait(impl->epfd, impl->evts, impl->evtn, timeout);
-
- // interrupted?(for gdb?) continue it
- if (evtn < 0 && errno == EINTR) return 0;
-
- // check error?
- tb_assert_and_check_return_val(evtn >= 0 && evtn <= impl->evtn, -1);
-
- // timeout?
- tb_check_return_val(evtn, 0);
-
- // grow it if events is full
- if (evtn == impl->evtn)
- {
- // grow size
- impl->evtn += grow;
- if (impl->evtn > rtor->aiop->maxn) impl->evtn = rtor->aiop->maxn;
-
- // grow data
- impl->evts = tb_ralloc(impl->evts, impl->evtn * sizeof(struct epoll_event));
- tb_assert_and_check_return_val(impl->evts, -1);
- }
- tb_assert(evtn <= impl->evtn);
-
- // limit
- evtn = tb_min(evtn, maxn);
-
- // sync
- tb_size_t i = 0;
- tb_size_t wait = 0;
- for (i = 0; i < evtn; i++)
- {
- // the aioo
- tb_aioo_impl_t* aioo = (tb_aioo_impl_t*)tb_u2p(impl->evts[i].data.u64);
- tb_assert_and_check_return_val(aioo, -1);
-
- // the sock
- tb_socket_ref_t sock = aioo->sock;
- tb_assert_and_check_return_val(sock, -1);
-
- // the events
- tb_size_t events = impl->evts[i].events;
-
- // spak?
- if (sock == aiop->spak[1] && (events & EPOLLIN))
- {
- // read spak
- tb_char_t spak = '\0';
- if (1 != tb_socket_recv(aiop->spak[1], (tb_byte_t*)&spak, 1)) return -1;
-
- // killed?
- if (spak == 'k') return -1;
-
- // continue it
- continue ;
- }
-
- // skip spak
- tb_check_continue(sock != aiop->spak[1]);
-
- // save aioe
- tb_aioe_ref_t aioe = &list[wait++];
- aioe->code = TB_AIOE_CODE_NONE;
- aioe->priv = aioo->priv;
- aioe->aioo = (tb_aioo_ref_t)aioo;
- if (events & EPOLLIN)
- {
- aioe->code |= TB_AIOE_CODE_RECV;
- if (aioo->code & TB_AIOE_CODE_ACPT) aioe->code |= TB_AIOE_CODE_ACPT;
- }
- if (events & EPOLLOUT)
- {
- aioe->code |= TB_AIOE_CODE_SEND;
- if (aioo->code & TB_AIOE_CODE_CONN) aioe->code |= TB_AIOE_CODE_CONN;
- }
- if (events & (EPOLLHUP | EPOLLERR) && !(aioe->code & (TB_AIOE_CODE_RECV | TB_AIOE_CODE_SEND)))
- aioe->code |= TB_AIOE_CODE_RECV | TB_AIOE_CODE_SEND;
-
- // oneshot? clear it
- if (aioo->code & TB_AIOE_CODE_ONESHOT)
- {
- // clear code
- aioo->code = TB_AIOE_CODE_NONE;
- aioo->priv = tb_null;
-
- // clear events manually if no epoll oneshot
-#ifndef EPOLLONESHOT
- struct epoll_event e = {0};
- if (epoll_ctl(impl->epfd, EPOLL_CTL_DEL, tb_sock2fd(aioo->sock), &e) < 0)
- {
- // trace
- tb_trace_e("clear aioo[%p] failed manually for oneshot, error: %d", aioo, errno);
- }
-#endif
- }
- }
-
- // ok
- return wait;
-}
-static tb_void_t tb_aiop_rtor_epoll_exit(tb_aiop_rtor_impl_t* rtor)
-{
- tb_aiop_rtor_epoll_impl_t* impl = (tb_aiop_rtor_epoll_impl_t*)rtor;
- if (impl)
- {
- // exit events
- if (impl->evts) tb_free(impl->evts);
- impl->evts = tb_null;
-
- // exit fd
- if (impl->epfd) close(impl->epfd);
- impl->epfd = 0;
-
- // exit it
- tb_free(impl);
- }
-}
-static tb_void_t tb_aiop_rtor_epoll_cler(tb_aiop_rtor_impl_t* rtor)
-{
- tb_aiop_rtor_epoll_impl_t* impl = (tb_aiop_rtor_epoll_impl_t*)rtor;
- if (impl)
- {
- // close fd
- if (impl->epfd > 0) close(impl->epfd);
- impl->epfd = 0;
-
- // re-init it
- if (impl->base.aiop) impl->epfd = epoll_create(impl->base.aiop->maxn);
- tb_assert(impl->epfd > 0);
- }
-}
-static tb_aiop_rtor_impl_t* tb_aiop_rtor_epoll_init(tb_aiop_impl_t* aiop)
-{
- // check
- tb_assert_and_check_return_val(aiop && aiop->maxn, tb_null);
-
- // done
- tb_bool_t ok = tb_false;
- tb_aiop_rtor_epoll_impl_t* impl = tb_null;
- do
- {
- // make impl
- impl = tb_malloc0_type(tb_aiop_rtor_epoll_impl_t);
- tb_assert_and_check_break(impl);
-
- // init base
- impl->base.aiop = aiop;
- impl->base.code = TB_AIOE_CODE_EALL | TB_AIOE_CODE_CLEAR | TB_AIOE_CODE_ONESHOT;
- impl->base.exit = tb_aiop_rtor_epoll_exit;
- impl->base.cler = tb_aiop_rtor_epoll_cler;
- impl->base.addo = tb_aiop_rtor_epoll_addo;
- impl->base.delo = tb_aiop_rtor_epoll_delo;
- impl->base.post = tb_aiop_rtor_epoll_post;
- impl->base.wait = tb_aiop_rtor_epoll_wait;
-
- // init epoll
- impl->epfd = epoll_create(aiop->maxn);
- tb_assert_and_check_break(impl->epfd > 0);
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // failed?
- if (!ok)
- {
- // exit it
- if (impl) tb_aiop_rtor_epoll_exit((tb_aiop_rtor_impl_t*)impl);
- impl = tb_null;
- }
-
- // ok?
- return (tb_aiop_rtor_impl_t*)impl;
-}
-
diff --git a/core/src/tbox/src/tbox/platform/deprecated/aiop_kqueue.c b/core/src/tbox/src/tbox/platform/deprecated/aiop_kqueue.c
deleted file mode 100644
index 4141478ea..000000000
--- a/core/src/tbox/src/tbox/platform/deprecated/aiop_kqueue.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/*!The Treasure Box Library
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
- *
- * @author ruki
- * @file aiop_kqueue.c
- *
- */
-/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
- */
-#include "prefix.h"
-#include "../../asio/deprecated/impl/prefix.h"
-#include <errno.h>
-#include <sys/event.h>
-#include <sys/time.h>
-#include <unistd.h>
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * macros
- */
-
-#ifndef EV_ENABLE
-# define EV_ENABLE (0)
-#endif
-
-#ifndef NOTE_EOF
-# define NOTE_EOF (0)
-#endif
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * types
- */
-
-// the kqueue impl impl type
-typedef struct __tb_aiop_rtor_kqueue_impl_t
-{
- // the rtor base
- tb_aiop_rtor_impl_t base;
-
- // the kqueue fd
- tb_long_t kqfd;
-
- // the events
- struct kevent* evts;
- tb_size_t evtn;
-
-}tb_aiop_rtor_kqueue_impl_t;
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
- */
-static tb_bool_t tb_aiop_rtor_kqueue_sync(tb_aiop_rtor_impl_t* rtor, struct kevent* evts, tb_size_t evtn)
-{
- // check
- tb_aiop_rtor_kqueue_impl_t* impl = (tb_aiop_rtor_kqueue_impl_t*)rtor;
- tb_assert_and_check_return_val(impl && impl->kqfd >= 0, tb_false);
- tb_assert_and_check_return_val(evts && evtn, tb_false);
-
- // change events
- struct timespec t = {0};
- if (kevent(impl->kqfd, evts, evtn, tb_null, 0, &t) < 0)
- {
- // trace
- tb_trace_e("sync failed, errno: %d", errno);
-
- // failed
- return tb_false;
- }
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_aiop_rtor_kqueue_addo(tb_aiop_rtor_impl_t* rtor, tb_aioo_impl_t const* aioo)
-{
- // check
- tb_aiop_rtor_kqueue_impl_t* impl = (tb_aiop_rtor_kqueue_impl_t*)rtor;
- tb_assert_and_check_return_val(impl && impl->kqfd >= 0 && aioo && aioo->sock, tb_false);
-
- // the code
- tb_size_t code = aioo->code;
-
- // init the add event
- tb_size_t add_event = EV_ADD | EV_ENABLE;
- if (code & TB_AIOE_CODE_CLEAR) add_event |= EV_CLEAR;
- if (code & TB_AIOE_CODE_ONESHOT) add_event |= EV_ONESHOT;
-
- // add event
- struct kevent e[2];
- tb_size_t n = 0;
- tb_int_t fd = tb_sock2fd(aioo->sock);
- if ((code & TB_AIOE_CODE_RECV) || (code & TB_AIOE_CODE_ACPT))
- {
- EV_SET(&e[n], fd, EVFILT_READ, add_event, NOTE_EOF, 0, (tb_pointer_t)aioo); n++;
- }
- if ((code & TB_AIOE_CODE_SEND) || (code & TB_AIOE_CODE_CONN))
- {
- EV_SET(&e[n], fd, EVFILT_WRITE, add_event, NOTE_EOF, 0, (tb_pointer_t)aioo); n++;
- }
-
- // ok?
- return n? tb_aiop_rtor_kqueue_sync(rtor, e, n) : tb_true;
-}
-static tb_bool_t tb_aiop_rtor_kqueue_delo(tb_aiop_rtor_impl_t* rtor, tb_aioo_impl_t const* aioo)
-{
- // check
- tb_aiop_rtor_kqueue_impl_t* impl = (tb_aiop_rtor_kqueue_impl_t*)rtor;
- tb_assert_and_check_return_val(impl && impl->kqfd >= 0 && aioo && aioo->sock, tb_false);
-
- // the code
- tb_size_t code = aioo->code;
-
- // delete event
- struct kevent e[2];
- tb_size_t n = 0;
- tb_int_t fd = tb_sock2fd(aioo->sock);
- if ((code & TB_AIOE_CODE_RECV) || (code & TB_AIOE_CODE_ACPT))
- {
- EV_SET(&e[n], fd, EVFILT_READ, EV_DELETE, 0, 0, (tb_pointer_t)aioo); n++;
- }
- if ((code & TB_AIOE_CODE_SEND) || (code & TB_AIOE_CODE_CONN))
- {
- EV_SET(&e[n], fd, EVFILT_WRITE, EV_DELETE, 0, 0, (tb_pointer_t)aioo); n++;
- }
-
- // ok?
- return n? tb_aiop_rtor_kqueue_sync(rtor, e, n) : tb_true;
-}
-static tb_bool_t tb_aiop_rtor_kqueue_post(tb_aiop_rtor_impl_t* rtor, tb_aioe_ref_t aioe)
-{
- // check
- tb_aiop_rtor_kqueue_impl_t* impl = (tb_aiop_rtor_kqueue_impl_t*)rtor;
- tb_assert_and_check_return_val(impl && aioe, tb_false);
-
- // the aioo
- tb_aioo_impl_t* aioo = (tb_aioo_impl_t*)aioe->aioo;
- tb_assert_and_check_return_val(aioo && aioo->sock, tb_false);
-
- // change
- tb_size_t adde = aioe->code & ~aioo->code;
- tb_size_t dele = ~aioe->code & aioo->code;
-
- // init the add event
- tb_size_t add_event = EV_ADD | EV_ENABLE;
- if (aioe->code & TB_AIOE_CODE_CLEAR) add_event |= EV_CLEAR;
- if (aioe->code & TB_AIOE_CODE_ONESHOT) add_event |= EV_ONESHOT;
-
- // save aioo
- aioo->code = aioe->code;
- aioo->priv = aioe->priv;
-
- // add event
- struct kevent e[2];
- tb_size_t n = 0;
- tb_int_t fd = tb_sock2fd(aioo->sock);
- if (adde & TB_AIOE_CODE_RECV || adde & TB_AIOE_CODE_ACPT)
- {
- EV_SET(&e[n], fd, EVFILT_READ, add_event, NOTE_EOF, 0, aioo);
- n++;
- }
- else if (dele & TB_AIOE_CODE_RECV || dele & TB_AIOE_CODE_ACPT)
- {
- EV_SET(&e[n], fd, EVFILT_READ, EV_DELETE, 0, 0, aioo);
- n++;
- }
- if (adde & TB_AIOE_CODE_SEND || adde & TB_AIOE_CODE_CONN)
- {
- EV_SET(&e[n], fd, EVFILT_WRITE, add_event, NOTE_EOF, 0, aioo);
- n++;
- }
- else if (dele & TB_AIOE_CODE_SEND || dele & TB_AIOE_CODE_CONN)
- {
- EV_SET(&e[n], fd, EVFILT_WRITE, EV_DELETE, 0, 0, aioo);
- n++;
- }
-
- // ok?
- return n? tb_aiop_rtor_kqueue_sync(rtor, e, n) : tb_true;
-}
-static tb_long_t tb_aiop_rtor_kqueue_wait(tb_aiop_rtor_impl_t* rtor, tb_aioe_ref_t list, tb_size_t maxn, tb_long_t timeout)
-{
- // check
- tb_aiop_rtor_kqueue_impl_t* impl = (tb_aiop_rtor_kqueue_impl_t*)rtor;
- tb_assert_and_check_return_val(impl && impl->kqfd >= 0 && rtor->aiop && list && maxn, -1);
-
- // the aiop
- tb_aiop_impl_t* aiop = rtor->aiop;
- tb_assert_and_check_return_val(aiop, -1);
-
- // init time
- struct timespec t = {0};
- if (timeout > 0)
- {
- t.tv_sec = timeout / 1000;
- t.tv_nsec = (timeout % 1000) * 1000000;
- }
-
- // init grow
- tb_size_t grow = tb_align8((rtor->aiop->maxn >> 3) + 1);
-
- // init events
- if (!impl->evts)
- {
- impl->evtn = grow;
- impl->evts = tb_nalloc0(impl->evtn, sizeof(struct kevent));
- tb_assert_and_check_return_val(impl->evts, -1);
- }
-
- // wait events
- tb_long_t evtn = kevent(impl->kqfd, tb_null, 0, impl->evts, impl->evtn, timeout >= 0? &t : tb_null);
- tb_assert_and_check_return_val(evtn >= 0 && evtn <= impl->evtn, -1);
-
- // timeout?
- tb_check_return_val(evtn, 0);
-
- // grow it if events is full
- if (evtn == impl->evtn)
- {
- // grow size
- impl->evtn += grow;
- if (impl->evtn > rtor->aiop->maxn) impl->evtn = rtor->aiop->maxn;
-
- // grow data
- impl->evts = tb_ralloc(impl->evts, impl->evtn * sizeof(struct kevent));
- tb_assert_and_check_return_val(impl->evts, -1);
- }
- tb_assert(evtn <= impl->evtn);
-
- // limit
- evtn = tb_min(evtn, maxn);
-
- // sync
- tb_size_t i = 0;
- tb_size_t wait = 0;
- for (i = 0; i < evtn; i++)
- {
- // the kevents
- struct kevent* e = impl->evts + i;
-
- // the aioo
- tb_aioo_impl_t* aioo = (tb_aioo_impl_t*)e->udata;
- tb_assert_and_check_return_val(aioo && aioo->sock, -1);
-
- // the sock
- tb_socket_ref_t sock = aioo->sock;
-
- // spak?
- if (sock == aiop->spak[1] && e->filter == EVFILT_READ)
- {
- // read spak
- tb_char_t spak = '\0';
- if (1 != tb_socket_recv(aiop->spak[1], (tb_byte_t*)&spak, 1)) return -1;
-
- // killed?
- if (spak == 'k') return -1;
-
- // continue it
- continue ;
- }
-
- // skip spak
- tb_check_continue(sock != aiop->spak[1]);
-
- // init the aioe
- tb_aioe_ref_t aioe = &list[wait++];
- aioe->code = TB_AIOE_CODE_NONE;
- aioe->aioo = (tb_aioo_ref_t)aioo;
- aioe->priv = aioo->priv;
- if (e->filter == EVFILT_READ)
- {
- aioe->code |= TB_AIOE_CODE_RECV;
- if (aioo->code & TB_AIOE_CODE_ACPT) aioe->code |= TB_AIOE_CODE_ACPT;
- }
- if (e->filter == EVFILT_WRITE)
- {
- aioe->code |= TB_AIOE_CODE_SEND;
- if (aioo->code & TB_AIOE_CODE_CONN) aioe->code |= TB_AIOE_CODE_CONN;
- }
- if ((e->flags & EV_ERROR) && !(aioe->code & (TB_AIOE_CODE_RECV | TB_AIOE_CODE_SEND)))
- aioe->code |= TB_AIOE_CODE_RECV | TB_AIOE_CODE_SEND;
-
- // oneshot? clear it
- if (aioo->code & TB_AIOE_CODE_ONESHOT)
- {
- aioo->code = TB_AIOE_CODE_NONE;
- aioo->priv = tb_null;
- }
- }
-
- // ok
- return wait;
-}
-static tb_void_t tb_aiop_rtor_kqueue_exit(tb_aiop_rtor_impl_t* rtor)
-{
- tb_aiop_rtor_kqueue_impl_t* impl = (tb_aiop_rtor_kqueue_impl_t*)rtor;
- if (impl)
- {
- // free events
- if (impl->evts) tb_free(impl->evts);
-
- // close kqfd
- if (impl->kqfd >= 0) close(impl->kqfd);
-
- // free it
- tb_free(impl);
- }
-}
-static tb_void_t tb_aiop_rtor_kqueue_cler(tb_aiop_rtor_impl_t* rtor)
-{
- tb_aiop_rtor_kqueue_impl_t* impl = (tb_aiop_rtor_kqueue_impl_t*)rtor;
- if (impl)
- {
- // close kqfd
- if (impl->kqfd >= 0)
- {
- close(impl->kqfd);
- impl->kqfd = kqueue();
- }
- }
-}
-static tb_aiop_rtor_impl_t* tb_aiop_rtor_kqueue_init(tb_aiop_impl_t* aiop)
-{
- // check
- tb_assert_and_check_return_val(aiop && aiop->maxn, tb_null);
-
- // done
- tb_bool_t ok = tb_false;
- tb_aiop_rtor_kqueue_impl_t* impl = tb_null;
- do
- {
- // make impl
- impl = tb_malloc0(sizeof(tb_aiop_rtor_kqueue_impl_t));
- tb_assert_and_check_break(impl);
-
- // init base
- impl->base.aiop = aiop;
- impl->base.code = TB_AIOE_CODE_EALL | TB_AIOE_CODE_CLEAR | TB_AIOE_CODE_ONESHOT;
- impl->base.exit = tb_aiop_rtor_kqueue_exit;
- impl->base.cler = tb_aiop_rtor_kqueue_cler;
- impl->base.addo = tb_aiop_rtor_kqueue_addo;
- impl->base.delo = tb_aiop_rtor_kqueue_delo;
- impl->base.post = tb_aiop_rtor_kqueue_post;
- impl->base.wait = tb_aiop_rtor_kqueue_wait;
-
- // init kqueue
- impl->kqfd = kqueue();
- tb_assert_and_check_break(impl->kqfd >= 0);
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // failed?
- if (!ok)
- {
- // exit it
- if (impl) tb_aiop_rtor_kqueue_exit((tb_aiop_rtor_impl_t*)impl);
- impl = tb_null;
- }
-
- // ok?
- return (tb_aiop_rtor_impl_t*)impl;
-}
-
diff --git a/core/src/tbox/src/tbox/platform/deprecated/aiop_poll.c b/core/src/tbox/src/tbox/platform/deprecated/aiop_poll.c
deleted file mode 100644
index d763e9a52..000000000
--- a/core/src/tbox/src/tbox/platform/deprecated/aiop_poll.c
+++ /dev/null
@@ -1,438 +0,0 @@
-/*!The Treasure Box Library
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
- *
- * @author ruki
- * @file aiop_poll.c
- *
- */
-/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
- */
-#include "prefix.h"
-#include <sys/poll.h>
-#include "../spinlock.h"
-#include "../../asio/deprecated/impl/prefix.h"
-#include "../../algorithm/algorithm.h"
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * types
- */
-
-// the poll lock type
-typedef struct __tb_poll_lock_t
-{
- // the pfds
- tb_spinlock_t pfds;
-
- // the hash
- tb_spinlock_t hash;
-
-}tb_poll_lock_t;
-
-// the poll rtor impl type
-typedef struct __tb_aiop_rtor_poll_impl_t
-{
- // the rtor base
- tb_aiop_rtor_impl_t base;
-
- // the poll fds
- tb_vector_ref_t pfds;
-
- // the copy fds
- tb_vector_ref_t cfds;
-
- // the hash
- tb_hash_map_ref_t hash;
-
- // the lock
- tb_poll_lock_t lock;
-
-}tb_aiop_rtor_poll_impl_t;
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
- */
-static tb_bool_t tb_poll_walk_delo(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_poll_walk_sete(tb_iterator_ref_t iterator, tb_pointer_t item, tb_cpointer_t priv)
-{
- // check
- tb_assert_and_check_return_val(iterator, tb_false);
-
- // the aioe
- tb_aioe_ref_t aioe = (tb_aioe_ref_t)priv;
- tb_assert_and_check_return_val(aioe, tb_false);
-
- // the aioo
- tb_aioo_impl_t const* aioo = (tb_aioo_impl_t const*)aioe->aioo;
- tb_assert_and_check_return_val(aioo && aioo->sock, tb_false);
-
- // is this?
- struct pollfd* pfd = (struct pollfd*)item;
- if (pfd && pfd->fd == ((tb_long_t)aioo->sock - 1))
- {
- pfd->events = 0;
- if (aioe->code & TB_AIOE_CODE_RECV || aioe->code & TB_AIOE_CODE_ACPT) pfd->events |= POLLIN;
- if (aioe->code & TB_AIOE_CODE_SEND || aioe->code & TB_AIOE_CODE_CONN) pfd->events |= POLLOUT;
-
- // break
- return tb_false;
- }
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_aiop_rtor_poll_addo(tb_aiop_rtor_impl_t* rtor, tb_aioo_impl_t const* aioo)
-{
- // check
- tb_aiop_rtor_poll_impl_t* impl = (tb_aiop_rtor_poll_impl_t*)rtor;
- tb_assert_and_check_return_val(impl && impl->pfds && impl->cfds && aioo && aioo->sock, tb_false);
-
- // the aiop
- tb_aiop_impl_t* aiop = rtor->aiop;
- tb_assert_and_check_return_val(aiop, tb_false);
-
- // add sock => aioo
- tb_bool_t ok = tb_false;
- tb_spinlock_enter(&impl->lock.hash);
- if (impl->hash)
- {
- tb_hash_map_insert(impl->hash, aioo->sock, aioo);
- ok = tb_true;
- }
- tb_spinlock_leave(&impl->lock.hash);
- tb_assert_and_check_return_val(ok, tb_false);
-
- // the code
- tb_size_t code = aioo->code;
-
- // init pfd
- struct pollfd pfd = {0};
- pfd.fd = ((tb_long_t)aioo->sock) - 1;
- if (code & TB_AIOE_CODE_RECV || code & TB_AIOE_CODE_ACPT) pfd.events |= POLLIN;
- if (code & TB_AIOE_CODE_SEND || code & TB_AIOE_CODE_CONN) pfd.events |= POLLOUT;
-
- // add pfd, TODO: addo by binary search
- tb_spinlock_enter(&impl->lock.pfds);
- tb_vector_insert_tail(impl->pfds, &pfd);
- tb_spinlock_leave(&impl->lock.pfds);
-
- // spak it
- if (aiop->spak[0] && code) tb_socket_send(aiop->spak[0], (tb_byte_t const*)"p", 1);
-
- // ok?
- return ok;
-}
-static tb_bool_t tb_aiop_rtor_poll_delo(tb_aiop_rtor_impl_t* rtor, tb_aioo_impl_t const* aioo)
-{
- // check
- tb_aiop_rtor_poll_impl_t* impl = (tb_aiop_rtor_poll_impl_t*)rtor;
- tb_assert_and_check_return_val(impl && impl->pfds && impl->cfds && aioo && aioo->sock, tb_false);
-
- // the aiop
- tb_aiop_impl_t* aiop = rtor->aiop;
- tb_assert_and_check_return_val(aiop, tb_false);
-
- // delo it, TODO: delo by binary search
- tb_spinlock_enter(&impl->lock.pfds);
- tb_remove_first_if(impl->pfds, tb_poll_walk_delo, (tb_pointer_t)(((tb_long_t)aioo->sock) - 1));
- tb_spinlock_leave(&impl->lock.pfds);
-
- // del sock => aioo
- tb_spinlock_enter(&impl->lock.hash);
- if (impl->hash) tb_hash_map_remove(impl->hash, aioo->sock);
- tb_spinlock_leave(&impl->lock.hash);
-
- // spak it
- if (aiop->spak[0]) tb_socket_send(aiop->spak[0], (tb_byte_t const*)"p", 1);
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_aiop_rtor_poll_post(tb_aiop_rtor_impl_t* rtor, tb_aioe_ref_t aioe)
-{
- // check
- tb_aiop_rtor_poll_impl_t* impl = (tb_aiop_rtor_poll_impl_t*)rtor;
- tb_assert_and_check_return_val(impl && impl->pfds && impl->cfds && aioe, tb_false);
-
- // the aiop
- tb_aiop_impl_t* aiop = rtor->aiop;
- tb_assert_and_check_return_val(aiop, tb_false);
-
- // the aioo
- tb_aioo_impl_t* aioo = (tb_aioo_impl_t*)aioe->aioo;
- tb_assert_and_check_return_val(aioo, tb_false);
-
- // save aioo
- aioo->code = aioe->code;
- aioo->priv = aioe->priv;
-
- // sete it, TODO: sete by binary search
- tb_spinlock_enter(&impl->lock.pfds);
- tb_walk_all(impl->pfds, tb_poll_walk_sete, (tb_pointer_t)aioe);
- tb_spinlock_leave(&impl->lock.pfds);
-
- // spak it
- if (aiop->spak[0]) tb_socket_send(aiop->spak[0], (tb_byte_t const*)"p", 1);
-
- // ok
- return tb_true;
-}
-static tb_long_t tb_aiop_rtor_poll_wait(tb_aiop_rtor_impl_t* rtor, tb_aioe_ref_t list, tb_size_t maxn, tb_long_t timeout)
-{
- // check
- tb_aiop_rtor_poll_impl_t* impl = (tb_aiop_rtor_poll_impl_t*)rtor;
- tb_assert_and_check_return_val(impl && impl->pfds && impl->cfds && list && maxn, -1);
-
- // the aiop
- tb_aiop_impl_t* aiop = rtor->aiop;
- tb_assert_and_check_return_val(aiop, tb_false);
-
- // 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))
- {
- // copy pfds
- tb_spinlock_enter(&impl->lock.pfds);
- tb_vector_copy(impl->cfds, impl->pfds);
- tb_spinlock_leave(&impl->lock.pfds);
-
- // cfds
- struct pollfd* cfds = (struct pollfd*)tb_vector_data(impl->cfds);
- tb_size_t cfdm = tb_vector_size(impl->cfds);
- tb_assert_and_check_return_val(cfds && cfdm, -1);
-
- // wait
- tb_long_t cfdn = poll(cfds, cfdm, timeout);
- tb_assert_and_check_return_val(cfdn >= 0, -1);
-
- // timeout?
- tb_check_return_val(cfdn, 0);
-
- // sync
- tb_size_t i = 0;
- for (i = 0; i < cfdm && wait < maxn; i++)
- {
- // the sock
- tb_socket_ref_t sock = tb_fd2sock(cfds[i].fd);
- tb_assert_and_check_return_val(sock, -1);
-
- // the events
- tb_size_t events = cfds[i].revents;
- tb_check_continue(events);
-
- // spak?
- if (sock == aiop->spak[1] && (events & POLLIN))
- {
- // read spak
- tb_char_t spak = '\0';
- if (1 != tb_socket_recv(aiop->spak[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(sock != aiop->spak[1]);
-
- // the aioo
- tb_size_t code = TB_AIOE_CODE_NONE;
- tb_cpointer_t priv = tb_null;
- tb_aioo_impl_t* aioo = tb_null;
- tb_spinlock_enter(&impl->lock.hash);
- if (impl->hash)
- {
- aioo = (tb_aioo_impl_t*)tb_hash_map_get(impl->hash, sock);
- if (aioo)
- {
- // save code & data
- code = aioo->code;
- priv = aioo->priv;
-
- // oneshot? clear it
- if (aioo->code & TB_AIOE_CODE_ONESHOT)
- {
- aioo->code = TB_AIOE_CODE_NONE;
- aioo->priv = tb_null;
- }
- }
- }
- tb_spinlock_leave(&impl->lock.hash);
- tb_check_continue(aioo && code);
-
- // init aioe
- tb_aioe_t aioe = {0};
- aioe.priv = priv;
- aioe.aioo = (tb_aioo_ref_t)aioo;
- if (events & POLLIN)
- {
- aioe.code |= TB_AIOE_CODE_RECV;
- if (code & TB_AIOE_CODE_ACPT) aioe.code |= TB_AIOE_CODE_ACPT;
- }
- if (events & POLLOUT)
- {
- aioe.code |= TB_AIOE_CODE_SEND;
- if (code & TB_AIOE_CODE_CONN) aioe.code |= TB_AIOE_CODE_CONN;
- }
- if ((events & POLLHUP) && !(code & (TB_AIOE_CODE_RECV | TB_AIOE_CODE_SEND)))
- aioe.code |= TB_AIOE_CODE_RECV | TB_AIOE_CODE_SEND;
-
- // save aioe
- list[wait++] = aioe;
-
- // oneshot?
- if (code & TB_AIOE_CODE_ONESHOT)
- {
- tb_spinlock_enter(&impl->lock.pfds);
- struct pollfd* pfds = (struct pollfd*)tb_vector_data(impl->pfds);
- if (pfds) pfds[i].events = 0;
- tb_spinlock_leave(&impl->lock.pfds);
- }
- }
- }
-
- // ok
- return wait;
-}
-static tb_void_t tb_aiop_rtor_poll_exit(tb_aiop_rtor_impl_t* rtor)
-{
- tb_aiop_rtor_poll_impl_t* impl = (tb_aiop_rtor_poll_impl_t*)rtor;
- if (impl)
- {
- // exit pfds
- tb_spinlock_enter(&impl->lock.pfds);
- if (impl->pfds) tb_vector_exit(impl->pfds);
- impl->pfds = tb_null;
- tb_spinlock_leave(&impl->lock.pfds);
-
- // exit cfds
- if (impl->cfds) tb_vector_exit(impl->cfds);
- impl->cfds = tb_null;
-
- // exit hash
- tb_spinlock_enter(&impl->lock.hash);
- if (impl->hash) tb_hash_map_exit(impl->hash);
- impl->hash = tb_null;
- tb_spinlock_leave(&impl->lock.hash);
-
- // exit lock
- tb_spinlock_exit(&impl->lock.pfds);
- tb_spinlock_exit(&impl->lock.hash);
-
- // free it
- tb_free(impl);
- }
-}
-static tb_void_t tb_aiop_rtor_poll_cler(tb_aiop_rtor_impl_t* rtor)
-{
- tb_aiop_rtor_poll_impl_t* impl = (tb_aiop_rtor_poll_impl_t*)rtor;
- if (impl)
- {
- // clear pfds
- tb_spinlock_enter(&impl->lock.pfds);
- if (impl->pfds) tb_vector_clear(impl->pfds);
- tb_spinlock_leave(&impl->lock.pfds);
-
- // clear hash
- tb_spinlock_enter(&impl->lock.hash);
- if (impl->hash) tb_hash_map_clear(impl->hash);
- tb_spinlock_leave(&impl->lock.hash);
-
- // spak it
- if (rtor->aiop && rtor->aiop->spak[0])
- tb_socket_send(rtor->aiop->spak[0], (tb_byte_t const*)"p", 1);
- }
-}
-static tb_aiop_rtor_impl_t* tb_aiop_rtor_poll_init(tb_aiop_impl_t* aiop)
-{
- // check
- tb_assert_and_check_return_val(aiop && aiop->maxn, tb_null);
-
- // done
- tb_bool_t ok = tb_false;
- tb_aiop_rtor_poll_impl_t* impl = tb_null;
- do
- {
- // make rtor
- impl = tb_malloc0_type(tb_aiop_rtor_poll_impl_t);
- tb_assert_and_check_break(impl);
-
- // init base
- impl->base.aiop = aiop;
- impl->base.code = TB_AIOE_CODE_EALL | TB_AIOE_CODE_ONESHOT;
- impl->base.exit = tb_aiop_rtor_poll_exit;
- impl->base.cler = tb_aiop_rtor_poll_cler;
- impl->base.addo = tb_aiop_rtor_poll_addo;
- impl->base.delo = tb_aiop_rtor_poll_delo;
- impl->base.post = tb_aiop_rtor_poll_post;
- impl->base.wait = tb_aiop_rtor_poll_wait;
-
- // init lock
- if (!tb_spinlock_init(&impl->lock.pfds)) break;
- if (!tb_spinlock_init(&impl->lock.hash)) break;
-
- // init pfds
- impl->pfds = tb_vector_init(tb_align8((aiop->maxn >> 3) + 1), tb_element_mem(sizeof(struct pollfd), tb_null, tb_null));
- tb_assert_and_check_break(impl->pfds);
-
- // init cfds
- impl->cfds = tb_vector_init(tb_align8((aiop->maxn >> 3) + 1), tb_element_mem(sizeof(struct pollfd), tb_null, tb_null));
- tb_assert_and_check_break(impl->cfds);
-
- // init hash
- impl->hash = tb_hash_map_init(tb_align8(tb_isqrti(aiop->maxn) + 1), tb_element_ptr(tb_null, tb_null), tb_element_ptr(tb_null, tb_null));
- tb_assert_and_check_break(impl->hash);
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // failed?
- if (!ok)
- {
- // exit it
- if (impl) tb_aiop_rtor_poll_exit((tb_aiop_rtor_impl_t*)impl);
- impl = tb_null;
- }
-
- // ok
- return (tb_aiop_rtor_impl_t*)impl;
-}
diff --git a/core/src/tbox/src/tbox/platform/deprecated/aiop_select.c b/core/src/tbox/src/tbox/platform/deprecated/aiop_select.c
deleted file mode 100644
index aeb655ffa..000000000
--- a/core/src/tbox/src/tbox/platform/deprecated/aiop_select.c
+++ /dev/null
@@ -1,454 +0,0 @@
-/*!The Treasure Box Library
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
- *
- * @author ruki
- * @file aiop_select.c
- *
- */
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
- */
-#include "prefix.h"
-#include "../../asio/deprecated/impl/prefix.h"
-#include "../spinlock.h"
-#ifdef TB_CONFIG_OS_WINDOWS
-# include "../windows/interface/interface.h"
-#else
-# include <sys/select.h>
-#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 poll lock type
-typedef struct __tb_select_lock_t
-{
- // the pfds
- tb_spinlock_t pfds;
-
- // the hash
- tb_spinlock_t hash;
-
-}tb_select_lock_t;
-
-// the select rtor type
-typedef struct __tb_aiop_rtor_select_impl_t
-{
- // the rtor base
- tb_aiop_rtor_impl_t base;
-
- // the fd max
- tb_size_t sfdm;
-
- // the select fds
- fd_set rfdi;
- fd_set wfdi;
- fd_set rfdo;
- fd_set wfdo;
-
- // the hash
- tb_hash_map_ref_t hash;
-
- // the lock
- tb_select_lock_t lock;
-
-}tb_aiop_rtor_select_impl_t;
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
- */
-static tb_bool_t tb_aiop_rtor_select_addo(tb_aiop_rtor_impl_t* rtor, tb_aioo_impl_t const* aioo)
-{
- // check
- tb_aiop_rtor_select_impl_t* impl = (tb_aiop_rtor_select_impl_t*)rtor;
- tb_assert_and_check_return_val(impl && rtor->aiop && aioo && aioo->sock, tb_false);
-
- // the aiop
- tb_aiop_impl_t* aiop = rtor->aiop;
- tb_assert_and_check_return_val(aiop, tb_false);
-
- // check size
- tb_spinlock_enter(&impl->lock.hash);
- tb_size_t size = tb_hash_map_size(impl->hash);
- tb_spinlock_leave(&impl->lock.hash);
- tb_assert_and_check_return_val(size < FD_SETSIZE, tb_false);
-
- // add sock => aioo
- tb_bool_t ok = tb_false;
- tb_spinlock_enter(&impl->lock.hash);
- if (impl->hash)
- {
- tb_hash_map_insert(impl->hash, aioo->sock, aioo);
- ok = tb_true;
- }
- tb_spinlock_leave(&impl->lock.hash);
- tb_assert_and_check_return_val(ok, tb_false);
-
- // the fd
- tb_long_t fd = ((tb_long_t)aioo->sock) - 1;
-
- // the code
- tb_size_t code = aioo->code;
-
- // enter
- tb_spinlock_enter(&impl->lock.pfds);
-
- // update fd max
- if (fd > (tb_long_t)impl->sfdm) impl->sfdm = (tb_size_t)fd;
-
- // init fds
- if (code & (TB_AIOE_CODE_RECV | TB_AIOE_CODE_ACPT)) FD_SET(fd, &impl->rfdi);
- if (code & (TB_AIOE_CODE_SEND | TB_AIOE_CODE_CONN)) FD_SET(fd, &impl->wfdi);
-
- // leave
- tb_spinlock_leave(&impl->lock.pfds);
-
- // spak it
- if (aiop->spak[0] && code) tb_socket_send(aiop->spak[0], (tb_byte_t const*)"p", 1);
-
- // ok?
- return ok;
-}
-static tb_bool_t tb_aiop_rtor_select_delo(tb_aiop_rtor_impl_t* rtor, tb_aioo_impl_t const* aioo)
-{
- // check
- tb_aiop_rtor_select_impl_t* impl = (tb_aiop_rtor_select_impl_t*)rtor;
- tb_assert_and_check_return_val(impl && aioo && aioo->sock, tb_false);
-
- // the aiop
- tb_aiop_impl_t* aiop = rtor->aiop;
- tb_assert_and_check_return_val(aiop, tb_false);
-
- // fd
- tb_long_t fd = tb_sock2fd(aioo->sock);
-
- // enter
- tb_spinlock_enter(&impl->lock.pfds);
-
- // del fds
- FD_CLR(fd, &impl->rfdi);
- FD_CLR(fd, &impl->wfdi);
-
- // leave
- tb_spinlock_leave(&impl->lock.pfds);
-
- // del sock => aioo
- tb_spinlock_enter(&impl->lock.hash);
- if (impl->hash) tb_hash_map_remove(impl->hash, aioo->sock);
- tb_spinlock_leave(&impl->lock.hash);
-
- // spak it
- if (aiop->spak[0]) tb_socket_send(aiop->spak[0], (tb_byte_t const*)"p", 1);
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_aiop_rtor_select_post(tb_aiop_rtor_impl_t* rtor, tb_aioe_ref_t aioe)
-{
- // check
- tb_aiop_rtor_select_impl_t* impl = (tb_aiop_rtor_select_impl_t*)rtor;
- tb_assert_and_check_return_val(impl && aioe, tb_false);
-
- // the aiop
- tb_aiop_impl_t* aiop = rtor->aiop;
- tb_assert_and_check_return_val(aiop, tb_false);
-
- // the aioo
- tb_aioo_impl_t* aioo = (tb_aioo_impl_t*)aioe->aioo;
- tb_assert_and_check_return_val(aioo && aioo->sock, tb_false);
-
- // save aioo
- aioo->code = aioe->code;
- aioo->priv = aioe->priv;
-
- // fd
- tb_long_t fd = tb_sock2fd(aioo->sock);
-
- // enter
- tb_spinlock_enter(&impl->lock.pfds);
-
- // set fds
- if (aioe->code & (TB_AIOE_CODE_RECV | TB_AIOE_CODE_ACPT)) FD_SET(fd, &impl->rfdi); else FD_CLR(fd, &impl->rfdi);
- if (aioe->code & (TB_AIOE_CODE_SEND | TB_AIOE_CODE_CONN)) FD_SET(fd, &impl->wfdi); else FD_CLR(fd, &impl->wfdi);
-
- // leave
- tb_spinlock_leave(&impl->lock.pfds);
-
- // spak it
- if (aiop->spak[0]) tb_socket_send(aiop->spak[0], (tb_byte_t const*)"p", 1);
-
- // ok
- return tb_true;
-}
-static tb_long_t tb_aiop_rtor_select_wait(tb_aiop_rtor_impl_t* rtor, tb_aioe_ref_t list, tb_size_t maxn, tb_long_t timeout)
-{
- // check
- tb_aiop_rtor_select_impl_t* impl = (tb_aiop_rtor_select_impl_t*)rtor;
- tb_assert_and_check_return_val(impl && rtor->aiop && list && maxn, -1);
-
- // the aiop
- tb_aiop_impl_t* aiop = rtor->aiop;
- tb_assert_and_check_return_val(aiop, tb_false);
-
- // 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();
- while (!wait && !stop && (timeout < 0 || tb_mclock() < time + timeout))
- {
- // enter
- tb_spinlock_enter(&impl->lock.pfds);
-
- // init fdo
- tb_size_t sfdm = impl->sfdm;
- tb_memcpy(&impl->rfdo, &impl->rfdi, sizeof(fd_set));
- tb_memcpy(&impl->wfdo, &impl->wfdi, sizeof(fd_set));
-
- // leave
- tb_spinlock_leave(&impl->lock.pfds);
-
- // wait
-#ifdef TB_CONFIG_OS_WINDOWS
- tb_long_t sfdn = tb_ws2_32()->select((tb_int_t)sfdm + 1, &impl->rfdo, &impl->wfdo, tb_null, timeout >= 0? &t : tb_null);
-#else
- tb_long_t sfdn = select(sfdm + 1, &impl->rfdo, &impl->wfdo, tb_null, timeout >= 0? &t : tb_null);
-#endif
- tb_assert_and_check_return_val(sfdn >= 0, -1);
-
- // timeout?
- tb_check_return_val(sfdn, 0);
-
- // enter
- tb_spinlock_enter(&impl->lock.hash);
-
- // sync
- tb_size_t itor = tb_iterator_head(impl->hash);
- tb_size_t tail = tb_iterator_tail(impl->hash);
- for (; itor != tail && wait >= 0 && (tb_size_t)wait < maxn; itor = tb_iterator_next(impl->hash, itor))
- {
- tb_hash_map_item_ref_t item = (tb_hash_map_item_ref_t)tb_iterator_item(impl->hash, itor);
- if (item)
- {
- // the sock
- tb_socket_ref_t sock = (tb_socket_ref_t)item->name;
- tb_assert_and_check_return_val(sock, -1);
-
- // spak?
- if (sock == aiop->spak[1] && FD_ISSET(((tb_long_t)aiop->spak[1] - 1), &impl->rfdo))
- {
- // read spak
- tb_char_t spak = '\0';
- if (1 != tb_socket_recv(aiop->spak[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(sock != aiop->spak[1]);
-
- // the fd
- tb_long_t fd = (tb_long_t)item->name - 1;
-
- // the aioo
- tb_aioo_impl_t* aioo = (tb_aioo_impl_t*)item->data;
- tb_assert_and_check_return_val(aioo && aioo->sock == sock, -1);
-
- // init aioe
- tb_aioe_t aioe = {0};
- aioe.priv = aioo->priv;
- aioe.aioo = (tb_aioo_ref_t)aioo;
- if (FD_ISSET(fd, &impl->rfdo))
- {
- aioe.code |= TB_AIOE_CODE_RECV;
- if (aioo->code & TB_AIOE_CODE_ACPT) aioe.code |= TB_AIOE_CODE_ACPT;
- }
- if (FD_ISSET(fd, &impl->wfdo))
- {
- aioe.code |= TB_AIOE_CODE_SEND;
- if (aioo->code & TB_AIOE_CODE_CONN) aioe.code |= TB_AIOE_CODE_CONN;
- }
-
- // ok?
- if (aioe.code)
- {
- // save aioe
- list[wait++] = aioe;
-
- // oneshot? clear it
- if (aioo->code & TB_AIOE_CODE_ONESHOT)
- {
- // clear aioo
- aioo->code = TB_AIOE_CODE_NONE;
- aioo->priv = tb_null;
-
- // clear events
- tb_spinlock_enter(&impl->lock.pfds);
- FD_CLR(fd, &impl->rfdi);
- FD_CLR(fd, &impl->wfdi);
- tb_spinlock_leave(&impl->lock.pfds);
- }
- }
- }
- }
-
- // leave
- tb_spinlock_leave(&impl->lock.hash);
- }
-
- // ok
- return wait;
-}
-static tb_void_t tb_aiop_rtor_select_exit(tb_aiop_rtor_impl_t* rtor)
-{
- tb_aiop_rtor_select_impl_t* impl = (tb_aiop_rtor_select_impl_t*)rtor;
- if (impl)
- {
- // free fds
- tb_spinlock_enter(&impl->lock.pfds);
- FD_ZERO(&impl->rfdi);
- FD_ZERO(&impl->wfdi);
- FD_ZERO(&impl->rfdo);
- FD_ZERO(&impl->wfdo);
- tb_spinlock_leave(&impl->lock.pfds);
-
- // exit hash
- tb_spinlock_enter(&impl->lock.hash);
- if (impl->hash) tb_hash_map_exit(impl->hash);
- impl->hash = tb_null;
- tb_spinlock_leave(&impl->lock.hash);
-
- // exit lock
- tb_spinlock_exit(&impl->lock.pfds);
- tb_spinlock_exit(&impl->lock.hash);
-
- // free it
- tb_free(impl);
- }
-}
-static tb_void_t tb_aiop_rtor_select_cler(tb_aiop_rtor_impl_t* rtor)
-{
- tb_aiop_rtor_select_impl_t* impl = (tb_aiop_rtor_select_impl_t*)rtor;
- if (impl)
- {
- // free fds
- tb_spinlock_enter(&impl->lock.pfds);
- impl->sfdm = 0;
- FD_ZERO(&impl->rfdi);
- FD_ZERO(&impl->wfdi);
- FD_ZERO(&impl->rfdo);
- FD_ZERO(&impl->wfdo);
- tb_spinlock_leave(&impl->lock.pfds);
-
- // clear hash
- tb_spinlock_enter(&impl->lock.hash);
- if (impl->hash) tb_hash_map_clear(impl->hash);
- tb_spinlock_leave(&impl->lock.hash);
-
- // spak it
- if (rtor->aiop && rtor->aiop->spak[0]) tb_socket_send(rtor->aiop->spak[0], (tb_byte_t const*)"p", 1);
- }
-}
-static tb_aiop_rtor_impl_t* tb_aiop_rtor_select_init(tb_aiop_impl_t* aiop)
-{
- // check
- tb_assert_and_check_return_val(aiop && aiop->maxn, tb_null);
-
- // done
- tb_bool_t ok = tb_false;
- tb_aiop_rtor_select_impl_t* impl = tb_null;
- do
- {
- // make rtor
- impl = tb_malloc0_type(tb_aiop_rtor_select_impl_t);
- tb_assert_and_check_break(impl);
-
- // init base
- impl->base.aiop = aiop;
- impl->base.code = TB_AIOE_CODE_EALL | TB_AIOE_CODE_ONESHOT;
- impl->base.exit = tb_aiop_rtor_select_exit;
- impl->base.cler = tb_aiop_rtor_select_cler;
- impl->base.addo = tb_aiop_rtor_select_addo;
- impl->base.delo = tb_aiop_rtor_select_delo;
- impl->base.post = tb_aiop_rtor_select_post;
- impl->base.wait = tb_aiop_rtor_select_wait;
-
- // init fds
- FD_ZERO(&impl->rfdi);
- FD_ZERO(&impl->wfdi);
- FD_ZERO(&impl->rfdo);
- FD_ZERO(&impl->wfdo);
-
- // init lock
- if (!tb_spinlock_init(&impl->lock.pfds)) break;
- if (!tb_spinlock_init(&impl->lock.hash)) break;
-
- // init hash
- impl->hash = tb_hash_map_init(tb_align8(tb_isqrti((tb_uint32_t)aiop->maxn) + 1), tb_element_ptr(tb_null, tb_null), tb_element_ptr(tb_null, tb_null));
- tb_assert_and_check_break(impl->hash);
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // failed?
- if (!ok)
- {
- // exit it
- if (impl) tb_aiop_rtor_select_exit((tb_aiop_rtor_impl_t*)impl);
- impl = tb_null;
- }
-
- // ok?
- return (tb_aiop_rtor_impl_t*)impl;
-}
-
diff --git a/core/src/tbox/src/tbox/platform/directory.c b/core/src/tbox/src/tbox/platform/directory.c
index 9346c13cc..9537ce3f6 100644
--- a/core/src/tbox/src/tbox/platform/directory.c
+++ b/core/src/tbox/src/tbox/platform/directory.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file directory.c
@@ -66,7 +66,7 @@ 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_bool_t recursion, tb_bool_t prefix, tb_directory_walk_func_t func, tb_cpointer_t 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)
{
tb_trace_noimpl();
}
diff --git a/core/src/tbox/src/tbox/platform/directory.h b/core/src/tbox/src/tbox/platform/directory.h
index d5e3b49b9..e805b5dfd 100644
--- a/core/src/tbox/src/tbox/platform/directory.h
+++ b/core/src/tbox/src/tbox/platform/directory.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file directory.h
@@ -109,7 +109,7 @@ 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 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 data the callback data
diff --git a/core/src/tbox/src/tbox/platform/dynamic.c b/core/src/tbox/src/tbox/platform/dynamic.c
index 29bbf85c8..75d2e3224 100644
--- a/core/src/tbox/src/tbox/platform/dynamic.c
+++ b/core/src/tbox/src/tbox/platform/dynamic.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file dynamic.c
diff --git a/core/src/tbox/src/tbox/platform/dynamic.h b/core/src/tbox/src/tbox/platform/dynamic.h
index 03ab5d927..30e372153 100644
--- a/core/src/tbox/src/tbox/platform/dynamic.h
+++ b/core/src/tbox/src/tbox/platform/dynamic.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file mutex.h
diff --git a/core/src/tbox/src/tbox/platform/environment.c b/core/src/tbox/src/tbox/platform/environment.c
index 9a6152da2..704a48848 100644
--- a/core/src/tbox/src/tbox/platform/environment.c
+++ b/core/src/tbox/src/tbox/platform/environment.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file environment.c
diff --git a/core/src/tbox/src/tbox/platform/environment.h b/core/src/tbox/src/tbox/platform/environment.h
index a580c6f68..c728fb516 100644
--- a/core/src/tbox/src/tbox/platform/environment.h
+++ b/core/src/tbox/src/tbox/platform/environment.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file environment.h
diff --git a/core/src/tbox/src/tbox/platform/event.c b/core/src/tbox/src/tbox/platform/event.c
index 15d8698cd..3bf61ee61 100644
--- a/core/src/tbox/src/tbox/platform/event.c
+++ b/core/src/tbox/src/tbox/platform/event.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file event.c
diff --git a/core/src/tbox/src/tbox/platform/event.h b/core/src/tbox/src/tbox/platform/event.h
index 19b4104c5..853129c6a 100644
--- a/core/src/tbox/src/tbox/platform/event.h
+++ b/core/src/tbox/src/tbox/platform/event.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file event.h
diff --git a/core/src/tbox/src/tbox/platform/exception.c b/core/src/tbox/src/tbox/platform/exception.c
index 51311897b..2722ea294 100644
--- a/core/src/tbox/src/tbox/platform/exception.c
+++ b/core/src/tbox/src/tbox/platform/exception.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file exception.c
diff --git a/core/src/tbox/src/tbox/platform/exception.h b/core/src/tbox/src/tbox/platform/exception.h
index 05373c4b8..f3352faad 100644
--- a/core/src/tbox/src/tbox/platform/exception.h
+++ b/core/src/tbox/src/tbox/platform/exception.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file exception.h
diff --git a/core/src/tbox/src/tbox/platform/file.c b/core/src/tbox/src/tbox/platform/file.c
index d8f8ea54d..886ef55ca 100644
--- a/core/src/tbox/src/tbox/platform/file.c
+++ b/core/src/tbox/src/tbox/platform/file.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file file.c
diff --git a/core/src/tbox/src/tbox/platform/file.h b/core/src/tbox/src/tbox/platform/file.h
index 4bc7bd59f..2467dede6 100644
--- a/core/src/tbox/src/tbox/platform/file.h
+++ b/core/src/tbox/src/tbox/platform/file.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file file.h
@@ -64,9 +64,6 @@ typedef enum __tb_file_mode_t
, 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_ASIO = 128 //!< support for asio
-
-, TB_FILE_MODE_BINARY = 256 //!< binary (deprecated)
}tb_file_mode_t;
diff --git a/core/src/tbox/src/tbox/platform/hostname.c b/core/src/tbox/src/tbox/platform/hostname.c
index aadbe0dda..02a52c036 100644
--- a/core/src/tbox/src/tbox/platform/hostname.c
+++ b/core/src/tbox/src/tbox/platform/hostname.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file hostname.c
diff --git a/core/src/tbox/src/tbox/platform/hostname.h b/core/src/tbox/src/tbox/platform/hostname.h
index fa6caefa1..1258ea9a2 100644
--- a/core/src/tbox/src/tbox/platform/hostname.h
+++ b/core/src/tbox/src/tbox/platform/hostname.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file hostname.h
diff --git a/core/src/tbox/src/tbox/platform/ifaddrs.c b/core/src/tbox/src/tbox/platform/ifaddrs.c
index 9af7d136e..0483be782 100644
--- a/core/src/tbox/src/tbox/platform/ifaddrs.c
+++ b/core/src/tbox/src/tbox/platform/ifaddrs.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ifaddrs.c
@@ -42,7 +42,7 @@
static tb_handle_t tb_ifaddrs_instance_init(tb_cpointer_t* ppriv)
{
// init it
- return tb_ifaddrs_init();
+ return (tb_handle_t)tb_ifaddrs_init();
}
static tb_void_t tb_ifaddrs_instance_exit(tb_handle_t ifaddrs, tb_cpointer_t priv)
{
@@ -135,17 +135,17 @@ tb_bool_t tb_ifaddrs_hwaddr(tb_ifaddrs_ref_t ifaddrs, tb_char_t const* name, tb_
// done
tb_bool_t ok = tb_false;
- tb_for_all_if (tb_ifaddrs_interface_ref_t, interface, iterator, interface)
+ tb_for_all_if (tb_ifaddrs_interface_ref_t, iface, iterator, iface)
{
- // get hwaddr from the given interface name?
+ // get hwaddr from the given iface name?
if (name)
{
// is this?
- if ( (interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR)
- && (interface->name && !tb_strcmp(interface->name, name)))
+ if ( (iface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR)
+ && (iface->name && !tb_strcmp(iface->name, name)))
{
// save hwaddr
- tb_hwaddr_copy(hwaddr, &interface->hwaddr);
+ tb_hwaddr_copy(hwaddr, &iface->hwaddr);
// ok
ok = tb_true;
@@ -155,12 +155,12 @@ tb_bool_t tb_ifaddrs_hwaddr(tb_ifaddrs_ref_t ifaddrs, tb_char_t const* name, tb_
else
{
// is this?
- if ( (interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR)
- && (interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR)
- && !(interface->flags & TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK))
+ 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, &interface->hwaddr);
+ tb_hwaddr_copy(hwaddr, &iface->hwaddr);
// ok
ok = tb_true;
@@ -194,30 +194,30 @@ tb_bool_t tb_ifaddrs_ipaddr(tb_ifaddrs_ref_t ifaddrs, tb_char_t const* name, tb_
// done
tb_bool_t ok = tb_false;
- tb_for_all_if (tb_ifaddrs_interface_ref_t, interface, iterator, interface)
+ tb_for_all_if (tb_ifaddrs_interface_ref_t, iface, iterator, iface)
{
// is this?
- if ( (name || !(interface->flags & TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK))
- && (interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR)
- && (!name || (interface->name && !tb_strcmp(interface->name, name))))
+ 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 ( interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR4
+ if ( iface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR4
&& (!family || family == TB_IPADDR_FAMILY_IPV4))
{
// save ipaddr4
- tb_ipaddr_ipv4_set(ipaddr, &interface->ipaddr4);
+ tb_ipaddr_ipv4_set(ipaddr, &iface->ipaddr4);
// ok
ok = tb_true;
break;
}
// ipv6?
- else if ( interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR6
+ else if ( iface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR6
&& (!family || family == TB_IPADDR_FAMILY_IPV6))
{
// save ipaddr6
- tb_ipaddr_ipv6_set(ipaddr, &interface->ipaddr6);
+ tb_ipaddr_ipv6_set(ipaddr, &iface->ipaddr6);
// ok
ok = tb_true;
@@ -236,16 +236,16 @@ tb_void_t tb_ifaddrs_dump(tb_ifaddrs_ref_t ifaddrs)
tb_trace_i("");
// done
- tb_for_all_if (tb_ifaddrs_interface_ref_t, interface, tb_ifaddrs_itor(ifaddrs, tb_true), interface)
+ tb_for_all_if (tb_ifaddrs_interface_ref_t, iface, tb_ifaddrs_itor(ifaddrs, tb_true), iface)
{
// trace
- tb_trace_i("name: %s%s", interface->name, (interface->flags & TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK)? "[loopback]" : "");
- if (interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR4)
- tb_trace_i(" ipaddr4: %{ipv4}", &interface->ipaddr4);
- if (interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR6)
- tb_trace_i(" ipaddr6: %{ipv6}", &interface->ipaddr6);
- if (interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR)
- tb_trace_i(" hwaddr: %{hwaddr}", &interface->hwaddr);
+ 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
diff --git a/core/src/tbox/src/tbox/platform/ifaddrs.h b/core/src/tbox/src/tbox/platform/ifaddrs.h
index 3969885de..c6243285e 100644
--- a/core/src/tbox/src/tbox/platform/ifaddrs.h
+++ b/core/src/tbox/src/tbox/platform/ifaddrs.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ifaddrs.h
diff --git a/core/src/tbox/src/tbox/platform/impl/dns.c b/core/src/tbox/src/tbox/platform/impl/dns.c
index aa4e7256f..25c976f53 100644
--- a/core/src/tbox/src/tbox/platform/impl/dns.c
+++ b/core/src/tbox/src/tbox/platform/impl/dns.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file dns.c
diff --git a/core/src/tbox/src/tbox/platform/impl/dns.h b/core/src/tbox/src/tbox/platform/impl/dns.h
index 1c47bd029..ce1acdaa8 100644
--- a/core/src/tbox/src/tbox/platform/impl/dns.h
+++ b/core/src/tbox/src/tbox/platform/impl/dns.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file dns.h
diff --git a/core/src/tbox/src/tbox/platform/impl/exception.h b/core/src/tbox/src/tbox/platform/impl/exception.h
index 9c1492d2c..0d644d949 100644
--- a/core/src/tbox/src/tbox/platform/impl/exception.h
+++ b/core/src/tbox/src/tbox/platform/impl/exception.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file exception.h
diff --git a/core/src/tbox/src/tbox/platform/impl/impl.h b/core/src/tbox/src/tbox/platform/impl/impl.h
index 3f909bbef..90b8da63b 100644
--- a/core/src/tbox/src/tbox/platform/impl/impl.h
+++ b/core/src/tbox/src/tbox/platform/impl/impl.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file impl.h
@@ -30,6 +30,7 @@
*/
#include "dns.h"
#include "socket.h"
+#include "sockdata.h"
#include "exception.h"
#include "thread_local.h"
#include "platform.h"
diff --git a/core/src/tbox/src/tbox/platform/impl/platform.c b/core/src/tbox/src/tbox/platform/impl/platform.c
index 3b431b840..6ee70a35e 100644
--- a/core/src/tbox/src/tbox/platform/impl/platform.c
+++ b/core/src/tbox/src/tbox/platform/impl/platform.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file platform.c
@@ -32,7 +32,6 @@
#include "../exception.h"
#include "../cache_time.h"
#include "../../network/network.h"
-#include "../deprecated/deprecated.h"
#ifdef TB_CONFIG_OS_ANDROID
# include "../android/android.h"
#endif
diff --git a/core/src/tbox/src/tbox/platform/impl/platform.h b/core/src/tbox/src/tbox/platform/impl/platform.h
index 09e101c67..47b2b02d0 100644
--- a/core/src/tbox/src/tbox/platform/impl/platform.h
+++ b/core/src/tbox/src/tbox/platform/impl/platform.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file platform.h
diff --git a/core/src/tbox/src/tbox/platform/impl/prefix.h b/core/src/tbox/src/tbox/platform/impl/prefix.h
index aab0a0952..34a6df13e 100644
--- a/core/src/tbox/src/tbox/platform/impl/prefix.h
+++ b/core/src/tbox/src/tbox/platform/impl/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/platform/impl/sockdata.c b/core/src/tbox/src/tbox/platform/impl/sockdata.c
new file mode 100644
index 000000000..e2981483d
--- /dev/null
+++ b/core/src/tbox/src/tbox/platform/impl/sockdata.c
@@ -0,0 +1,172 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
+ *
+ * @author ruki
+ * @file sockdata.c
+ * @ingroup platform
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "sockdata.h"
+#include "../thread_local.h"
+#include "../../libc/libc.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * macros
+ */
+#ifdef __tb_small__
+# define TB_SOCKDATA_GROW (64)
+#else
+# define TB_SOCKDATA_GROW (256)
+#endif
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * globals
+ */
+
+// the global socket data in the local thread
+#ifndef TB_CONFIG_MICRO_ENABLE
+static tb_thread_local_t g_sockdata_local = TB_THREAD_LOCAL_INIT;
+#endif
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * private implementation
+ */
+#ifndef TB_CONFIG_MICRO_ENABLE
+static tb_void_t tb_sockdata_local_free(tb_cpointer_t priv)
+{
+ tb_sockdata_ref_t sockdata = (tb_sockdata_ref_t)priv;
+ if (sockdata)
+ {
+ tb_sockdata_exit(sockdata);
+ tb_free(sockdata);
+ }
+}
+#endif
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * implementation
+ */
+tb_sockdata_ref_t tb_sockdata()
+{
+#ifndef TB_CONFIG_MICRO_ENABLE
+ // init local socket data
+ if (!tb_thread_local_init(&g_sockdata_local, tb_sockdata_local_free)) return tb_null;
+
+ // init socket data
+ tb_sockdata_ref_t sockdata = (tb_sockdata_ref_t)tb_thread_local_get(&g_sockdata_local);
+ if (!sockdata)
+ {
+ // make socket data
+ sockdata = tb_malloc0_type(tb_sockdata_t);
+ if (sockdata)
+ {
+ // init socket data
+ tb_sockdata_init(sockdata);
+
+ // save socket data to local thread
+ tb_thread_local_set(&g_sockdata_local, sockdata);
+ }
+ }
+
+ // ok?
+ return sockdata;
+#else
+ return tb_null;
+#endif
+}
+tb_void_t tb_sockdata_init(tb_sockdata_ref_t sockdata)
+{
+ // check
+ tb_assert(sockdata);
+
+ // init it
+ sockdata->data = tb_null;
+ sockdata->maxn = 0;
+}
+tb_void_t tb_sockdata_exit(tb_sockdata_ref_t sockdata)
+{
+ // check
+ tb_assert(sockdata);
+
+ // exit socket data
+ if (sockdata->data) tb_free(sockdata->data);
+ sockdata->data = tb_null;
+ sockdata->maxn = 0;
+}
+tb_void_t tb_sockdata_clear(tb_sockdata_ref_t sockdata)
+{
+ // check
+ tb_assert(sockdata);
+
+ // clear data
+ if (sockdata->data) tb_memset(sockdata->data, 0, sockdata->maxn * sizeof(tb_cpointer_t));
+}
+tb_void_t tb_sockdata_insert(tb_sockdata_ref_t sockdata, tb_socket_ref_t sock, tb_cpointer_t priv)
+{
+ // check
+ tb_long_t fd = tb_sock2fd(sock);
+ tb_assert(sockdata && fd > 0 && fd < TB_MAXS32);
+
+ // not null?
+ if (priv)
+ {
+ // no data? init it first
+ tb_size_t need = fd + 1;
+ if (!sockdata->data)
+ {
+ // init data
+ need += TB_SOCKDATA_GROW;
+ sockdata->data = tb_nalloc0_type(need, tb_cpointer_t);
+ tb_assert_and_check_return(sockdata->data);
+
+ // init data size
+ sockdata->maxn = need;
+ }
+ else if (need > sockdata->maxn)
+ {
+ // grow data
+ need += TB_SOCKDATA_GROW;
+ sockdata->data = (tb_cpointer_t*)tb_ralloc(sockdata->data, need * sizeof(tb_cpointer_t));
+ tb_assert_and_check_return(sockdata->data);
+
+ // init growed space
+ tb_memset(sockdata->data + sockdata->maxn, 0, (need - sockdata->maxn) * sizeof(tb_cpointer_t));
+
+ // grow data size
+ sockdata->maxn = need;
+ }
+
+ // save the socket private data
+ sockdata->data[fd] = priv;
+ }
+}
+tb_void_t tb_sockdata_remove(tb_sockdata_ref_t sockdata, tb_socket_ref_t sock)
+{
+ // check
+ tb_long_t fd = tb_sock2fd(sock);
+ tb_assert(sockdata && sockdata->data);
+ tb_assert(fd > 0 && fd < TB_MAXS32);
+
+ // remove the socket private data
+ if (fd < sockdata->maxn) sockdata->data[fd] = tb_null;
+}
diff --git a/core/src/tbox/src/tbox/platform/impl/sockdata.h b/core/src/tbox/src/tbox/platform/impl/sockdata.h
new file mode 100644
index 000000000..c0b070f36
--- /dev/null
+++ b/core/src/tbox/src/tbox/platform/impl/sockdata.h
@@ -0,0 +1,115 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
+ *
+ * @author ruki
+ * @file sockdata.h
+ * @ingroup platform
+ *
+ */
+#ifndef TB_PLATFORM_IMPL_SOCKDATA_H
+#define TB_PLATFORM_IMPL_SOCKDATA_H
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "socket.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_enter__
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * types
+ */
+
+// the socket data type
+typedef struct __tb_sockdata_t
+{
+ // the socket data (sock => priv)
+ tb_cpointer_t* data;
+
+ // the socket data maximum count
+ tb_size_t maxn;
+
+}tb_sockdata_t, *tb_sockdata_ref_t;
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * interfaces
+ */
+
+/* get socket data instance in local thread
+ *
+ * @return sockdata the sockdata
+ */
+tb_sockdata_ref_t tb_sockdata(tb_noarg_t);
+
+/* init socket data
+ *
+ * @param sockdata the sockdata
+ */
+tb_void_t tb_sockdata_init(tb_sockdata_ref_t sockdata);
+
+/* exit socket data
+ *
+ * @param sockdata the sockdata
+ */
+tb_void_t tb_sockdata_exit(tb_sockdata_ref_t sockdata);
+
+/* clear socket data
+ *
+ * @param sockdata the sockdata
+ */
+tb_void_t tb_sockdata_clear(tb_sockdata_ref_t sockdata);
+
+/* insert socket data
+ *
+ * @param sockdata the sockdata
+ * @param sock the socket
+ * @param priv the socket private data
+ */
+tb_void_t tb_sockdata_insert(tb_sockdata_ref_t sockdata, tb_socket_ref_t sock, tb_cpointer_t priv);
+
+/* remove socket data
+ *
+ * @param sockdata the sockdata
+ * @param sock the socket
+ */
+tb_void_t tb_sockdata_remove(tb_sockdata_ref_t sockdata, tb_socket_ref_t sock);
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * inline implementation
+ */
+static __tb_inline__ tb_cpointer_t tb_sockdata_get(tb_sockdata_ref_t sockdata, tb_socket_ref_t sock)
+{
+ // check
+ tb_long_t fd = tb_sock2fd(sock);
+ tb_assert(sockdata && fd > 0 && fd < TB_MAXS32);
+
+ // get the socket private data
+ return (sockdata->data && fd < sockdata->maxn)? sockdata->data[fd] : tb_null;
+}
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_leave__
+
+#endif
diff --git a/core/src/tbox/src/tbox/platform/impl/socket.h b/core/src/tbox/src/tbox/platform/impl/socket.h
index 66e732904..345216602 100644
--- a/core/src/tbox/src/tbox/platform/impl/socket.h
+++ b/core/src/tbox/src/tbox/platform/impl/socket.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file socket.h
diff --git a/core/src/tbox/src/tbox/platform/impl/thread_local.h b/core/src/tbox/src/tbox/platform/impl/thread_local.h
index e06365360..8384219ff 100644
--- a/core/src/tbox/src/tbox/platform/impl/thread_local.h
+++ b/core/src/tbox/src/tbox/platform/impl/thread_local.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file thread_local.h
diff --git a/core/src/tbox/src/tbox/platform/libc/backtrace.c b/core/src/tbox/src/tbox/platform/libc/backtrace.c
index 32878ade6..66d27044b 100644
--- a/core/src/tbox/src/tbox/platform/libc/backtrace.c
+++ b/core/src/tbox/src/tbox/platform/libc/backtrace.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file backtrace.c
diff --git a/core/src/tbox/src/tbox/platform/libc/environment.c b/core/src/tbox/src/tbox/platform/libc/environment.c
index ae0f622bd..c753b0f77 100644
--- a/core/src/tbox/src/tbox/platform/libc/environment.c
+++ b/core/src/tbox/src/tbox/platform/libc/environment.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file environment.c
diff --git a/core/src/tbox/src/tbox/platform/libc/exception.c b/core/src/tbox/src/tbox/platform/libc/exception.c
index 684f8eb90..3d3c1f47d 100644
--- a/core/src/tbox/src/tbox/platform/libc/exception.c
+++ b/core/src/tbox/src/tbox/platform/libc/exception.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file exception.c
diff --git a/core/src/tbox/src/tbox/platform/libc/exception.h b/core/src/tbox/src/tbox/platform/libc/exception.h
index 58e97ca70..e7a1ed49c 100644
--- a/core/src/tbox/src/tbox/platform/libc/exception.h
+++ b/core/src/tbox/src/tbox/platform/libc/exception.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file exception.h
diff --git a/core/src/tbox/src/tbox/platform/libc/memory.c b/core/src/tbox/src/tbox/platform/libc/memory.c
index f5355f34d..7d1a28153 100644
--- a/core/src/tbox/src/tbox/platform/libc/memory.c
+++ b/core/src/tbox/src/tbox/platform/libc/memory.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file memory.c
diff --git a/core/src/tbox/src/tbox/platform/libc/prefix.h b/core/src/tbox/src/tbox/platform/libc/prefix.h
index 7664333df..580db7268 100644
--- a/core/src/tbox/src/tbox/platform/libc/prefix.h
+++ b/core/src/tbox/src/tbox/platform/libc/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/platform/libc/print.c b/core/src/tbox/src/tbox/platform/libc/print.c
index 0fe867d8f..b7b0bb617 100644
--- a/core/src/tbox/src/tbox/platform/libc/print.c
+++ b/core/src/tbox/src/tbox/platform/libc/print.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file print.c
diff --git a/core/src/tbox/src/tbox/platform/libc/random.c b/core/src/tbox/src/tbox/platform/libc/random.c
index 735119619..19b0f9021 100644
--- a/core/src/tbox/src/tbox/platform/libc/random.c
+++ b/core/src/tbox/src/tbox/platform/libc/random.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file random.c
diff --git a/core/src/tbox/src/tbox/platform/libc/syserror.c b/core/src/tbox/src/tbox/platform/libc/syserror.c
index 9c25efd53..4350b487b 100644
--- a/core/src/tbox/src/tbox/platform/libc/syserror.c
+++ b/core/src/tbox/src/tbox/platform/libc/syserror.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file syserror.c
diff --git a/core/src/tbox/src/tbox/platform/linux/ifaddrs.c b/core/src/tbox/src/tbox/platform/linux/ifaddrs.c
index b8837277a..eb67d2646 100644
--- a/core/src/tbox/src/tbox/platform/linux/ifaddrs.c
+++ b/core/src/tbox/src/tbox/platform/linux/ifaddrs.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ifaddrs.c
diff --git a/core/src/tbox/src/tbox/platform/linux/ifaddrs2.c b/core/src/tbox/src/tbox/platform/linux/ifaddrs2.c
index 406105bb6..d28efccc6 100644
--- a/core/src/tbox/src/tbox/platform/linux/ifaddrs2.c
+++ b/core/src/tbox/src/tbox/platform/linux/ifaddrs2.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ifaddrs.c
diff --git a/core/src/tbox/src/tbox/platform/linux/poller_epoll.c b/core/src/tbox/src/tbox/platform/linux/poller_epoll.c
index 8a05b5e80..57f9decec 100644
--- a/core/src/tbox/src/tbox/platform/linux/poller_epoll.c
+++ b/core/src/tbox/src/tbox/platform/linux/poller_epoll.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file poller_epoll.c
@@ -29,9 +29,7 @@
#include <sys/epoll.h>
#include <fcntl.h>
#include <errno.h>
-#ifndef TB_CONFIG_OS_ANDROID
-# include <sys/unistd.h>
-#endif
+#include <unistd.h>
#ifdef TB_CONFIG_POSIX_HAVE_GETRLIMIT
# include <sys/resource.h>
#endif
@@ -61,11 +59,8 @@ typedef struct __tb_poller_epoll_t
// the events count
tb_size_t events_count;
- // the user private data hash (socket => priv)
- tb_cpointer_t* hash;
-
- // the user private data hash size
- tb_size_t hash_size;
+ // the socket data
+ tb_sockdata_t sockdata;
}tb_poller_epoll_t, *tb_poller_epoll_ref_t;
@@ -93,60 +88,6 @@ static tb_size_t tb_poller_maxfds()
// ok?
return maxfds;
}
-static tb_void_t tb_poller_hash_set(tb_poller_epoll_ref_t poller, tb_long_t fd, tb_cpointer_t priv)
-{
- // check
- tb_assert(poller && fd > 0 && fd < TB_MAXS32);
-
- // not null?
- if (priv)
- {
- // no hash? init it first
- tb_size_t need = fd + 1;
- if (!poller->hash)
- {
- // init hash
- poller->hash = tb_nalloc0_type(need, tb_cpointer_t);
- tb_assert_and_check_return(poller->hash);
-
- // init hash size
- poller->hash_size = need;
- }
- else if (need > poller->hash_size)
- {
- // grow hash
- poller->hash = (tb_cpointer_t*)tb_ralloc(poller->hash, need * sizeof(tb_cpointer_t));
- tb_assert_and_check_return(poller->hash);
-
- // init growed space
- tb_memset(poller->hash + poller->hash_size, 0, (need - poller->hash_size) * sizeof(tb_cpointer_t));
-
- // grow hash size
- poller->hash_size = need;
- }
-
- // save the user private data
- poller->hash[fd] = priv;
- }
-}
-static __tb_inline__ tb_cpointer_t tb_poller_hash_get(tb_poller_epoll_ref_t poller, tb_long_t fd)
-{
- // check
- tb_assert(poller && poller->hash);
- tb_assert(fd > 0 && fd < TB_MAXS32);
-
- // get the user private data
- return fd < poller->hash_size? poller->hash[fd] : tb_null;
-}
-static __tb_inline__ tb_void_t tb_poller_hash_del(tb_poller_epoll_ref_t poller, tb_long_t fd)
-{
- // check
- tb_assert(poller && poller->hash);
- tb_assert(fd > 0 && fd < TB_MAXS32);
-
- // remove the user private data
- if (fd < poller->hash_size) poller->hash[fd] = tb_null;
-}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
@@ -162,6 +103,9 @@ tb_poller_ref_t tb_poller_init(tb_cpointer_t priv)
poller = tb_malloc0_type(tb_poller_epoll_t);
tb_assert_and_check_break(poller);
+ // init socket data
+ tb_sockdata_init(&poller->sockdata);
+
// init maxn
poller->maxn = tb_poller_maxfds();
tb_assert_and_check_break(poller->maxn);
@@ -207,11 +151,6 @@ tb_void_t tb_poller_exit(tb_poller_ref_t self)
poller->pair[0] = tb_null;
poller->pair[1] = tb_null;
- // exit hash
- if (poller->hash) tb_free(poller->hash);
- poller->hash = tb_null;
- poller->hash_size = 0;
-
// exit events
if (poller->events) tb_free(poller->events);
poller->events = tb_null;
@@ -221,21 +160,15 @@ tb_void_t tb_poller_exit(tb_poller_ref_t self)
if (poller->epfd > 0) close(poller->epfd);
poller->epfd = 0;
+ // exit socket data
+ tb_sockdata_exit(&poller->sockdata);
+
// free it
tb_free(poller);
}
-tb_void_t tb_poller_clear(tb_poller_ref_t self)
+tb_size_t tb_poller_type(tb_poller_ref_t poller)
{
- // check
- tb_poller_epoll_ref_t poller = (tb_poller_epoll_ref_t)self;
- tb_assert_and_check_return(poller);
-
- // close the previous epoll fd first
- if (poller->epfd > 0) close(poller->epfd);
-
- // recreate a new epoll
- poller->epfd = epoll_create(poller->maxn);
- tb_assert(poller->epfd > 0);
+ return TB_POLLER_TYPE_EPOLL;
}
tb_cpointer_t tb_poller_priv(tb_poller_ref_t self)
{
@@ -268,9 +201,9 @@ tb_bool_t tb_poller_support(tb_poller_ref_t self, tb_size_t events)
{
// all supported events
#ifdef EPOLLONESHOT
- static tb_size_t events_supported = TB_POLLER_EVENT_EALL | TB_POLLER_EVENT_CLEAR | TB_POLLER_EVENT_ONESHOT;
+ static const tb_size_t events_supported = TB_POLLER_EVENT_EALL | TB_POLLER_EVENT_CLEAR | TB_POLLER_EVENT_ONESHOT;
#else
- static tb_size_t events_supported = TB_POLLER_EVENT_EALL | TB_POLLER_EVENT_CLEAR;
+ static const tb_size_t events_supported = TB_POLLER_EVENT_EALL | TB_POLLER_EVENT_CLEAR;
#endif
// is supported?
@@ -304,7 +237,7 @@ tb_bool_t tb_poller_insert(tb_poller_ref_t self, tb_socket_ref_t sock, tb_size_t
e.data.fd = (tb_int_t)tb_sock2fd(sock);
// bind user private data to socket
- tb_poller_hash_set(poller, e.data.fd, priv);
+ tb_sockdata_insert(&poller->sockdata, sock, priv);
// add socket and events
if (epoll_ctl(poller->epfd, EPOLL_CTL_ADD, e.data.fd, &e) < 0)
@@ -338,7 +271,7 @@ tb_bool_t tb_poller_remove(tb_poller_ref_t self, tb_socket_ref_t sock)
}
// remove user private data from this socket
- tb_poller_hash_del(poller, fd);
+ tb_sockdata_remove(&poller->sockdata, sock);
// ok
return tb_true;
@@ -371,7 +304,7 @@ tb_bool_t tb_poller_modify(tb_poller_ref_t self, tb_socket_ref_t sock, tb_size_t
e.data.fd = (tb_int_t)tb_sock2fd(sock);
// modify user private data to socket
- tb_poller_hash_set(poller, e.data.fd, priv);
+ tb_sockdata_insert(&poller->sockdata, sock, priv);
// modify events
if (epoll_ctl(poller->epfd, EPOLL_CTL_MOD, e.data.fd, &e) < 0)
@@ -476,7 +409,7 @@ tb_long_t tb_poller_wait(tb_poller_ref_t self, tb_poller_event_func_t func, tb_l
#endif
// call event function
- func(self, sock, events, tb_poller_hash_get(poller, fd));
+ func(self, sock, events, tb_sockdata_get(&poller->sockdata, sock));
// update the events count
wait++;
diff --git a/core/src/tbox/src/tbox/platform/linux/prefix.h b/core/src/tbox/src/tbox/platform/linux/prefix.h
index c8ab5f081..fd7ec0f83 100644
--- a/core/src/tbox/src/tbox/platform/linux/prefix.h
+++ b/core/src/tbox/src/tbox/platform/linux/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/platform/ltimer.c b/core/src/tbox/src/tbox/platform/ltimer.c
index e376124a0..c8451f1c7 100644
--- a/core/src/tbox/src/tbox/platform/ltimer.c
+++ b/core/src/tbox/src/tbox/platform/ltimer.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ltimer.c
@@ -563,7 +563,7 @@ tb_bool_t tb_ltimer_spak(tb_ltimer_ref_t self)
tb_spinlock_enter(&timer->lock);
// exit the expired task
- tb_pointer_t data[2]; data[0] = self; data[1] = &now;
+ 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
diff --git a/core/src/tbox/src/tbox/platform/ltimer.h b/core/src/tbox/src/tbox/platform/ltimer.h
index 32941e2ba..e87382a98 100644
--- a/core/src/tbox/src/tbox/platform/ltimer.h
+++ b/core/src/tbox/src/tbox/platform/ltimer.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ltimer.h
diff --git a/core/src/tbox/src/tbox/platform/mach/barrier.h b/core/src/tbox/src/tbox/platform/mach/barrier.h
index 2d67fb1fd..2944dc072 100644
--- a/core/src/tbox/src/tbox/platform/mach/barrier.h
+++ b/core/src/tbox/src/tbox/platform/mach/barrier.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file barrier.h
diff --git a/core/src/tbox/src/tbox/platform/mach/dns.c b/core/src/tbox/src/tbox/platform/mach/dns.c
index 5ac33ba59..7401141b0 100644
--- a/core/src/tbox/src/tbox/platform/mach/dns.c
+++ b/core/src/tbox/src/tbox/platform/mach/dns.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file dns.c
@@ -50,8 +50,8 @@ typedef tb_int_t (*tb_dns_res_ninit_func_t)(res_state);
tb_bool_t tb_dns_init_env()
{
// done
- tb_size_t count = 0;
- tb_handle_t library = tb_dynamic_init("libresolv.dylib");
+ tb_size_t count = 0;
+ tb_dynamic_ref_t library = tb_dynamic_init("libresolv.dylib");
if (library)
{
// the res_ninit func
diff --git a/core/src/tbox/src/tbox/platform/mach/ios/directory.m b/core/src/tbox/src/tbox/platform/mach/ios/directory.m
index 55b0674fa..34667fe64 100644
--- a/core/src/tbox/src/tbox/platform/mach/ios/directory.m
+++ b/core/src/tbox/src/tbox/platform/mach/ios/directory.m
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file directory.m
diff --git a/core/src/tbox/src/tbox/platform/mach/ios/prefix.h b/core/src/tbox/src/tbox/platform/mach/ios/prefix.h
index 159ff9f7e..4db9f253b 100644
--- a/core/src/tbox/src/tbox/platform/mach/ios/prefix.h
+++ b/core/src/tbox/src/tbox/platform/mach/ios/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/platform/mach/ios/print.c b/core/src/tbox/src/tbox/platform/mach/ios/print.c
index 5a87c4f3f..06236f2de 100644
--- a/core/src/tbox/src/tbox/platform/mach/ios/print.c
+++ b/core/src/tbox/src/tbox/platform/mach/ios/print.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file print.c
diff --git a/core/src/tbox/src/tbox/platform/mach/poller_kqueue.c b/core/src/tbox/src/tbox/platform/mach/poller_kqueue.c
index 6ca4e74ca..424b0eaba 100644
--- a/core/src/tbox/src/tbox/platform/mach/poller_kqueue.c
+++ b/core/src/tbox/src/tbox/platform/mach/poller_kqueue.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file poller_kqueue.c
@@ -70,13 +70,10 @@ typedef struct __tb_poller_kqueue_t
// the events count
tb_size_t events_count;
-
- // the events hash (socket => events)
- tb_size_t* hash;
+
+ // the socket data
+ tb_sockdata_t sockdata;
- // the events hash size
- tb_size_t hash_size;
-
}tb_poller_kqueue_t, *tb_poller_kqueue_ref_t;
/* //////////////////////////////////////////////////////////////////////////////////////
@@ -122,70 +119,6 @@ static tb_bool_t tb_poller_change(tb_poller_kqueue_ref_t poller, struct kevent*
// ok
return tb_true;
}
-static tb_void_t tb_poller_hash_set(tb_poller_kqueue_ref_t poller, tb_socket_ref_t sock, tb_size_t events)
-{
- // check
- tb_assert(poller && sock);
-
- // the socket fd
- tb_long_t fd = tb_sock2fd(sock);
- tb_assert(fd > 0 && fd < TB_MAXS32);
-
- // not empty events?
- if (events)
- {
- // no hash? init it first
- tb_size_t need = fd + 1;
- if (!poller->hash)
- {
- // init hash
- poller->hash = tb_nalloc0_type(need, tb_size_t);
- tb_assert_and_check_return(poller->hash);
-
- // init hash size
- poller->hash_size = need;
- }
- else if (need > poller->hash_size)
- {
- // grow hash
- poller->hash = (tb_size_t*)tb_ralloc(poller->hash, need * sizeof(tb_size_t));
- tb_assert_and_check_return(poller->hash);
-
- // init growed space
- tb_memset(poller->hash + poller->hash_size, 0, (need - poller->hash_size) * sizeof(tb_size_t));
-
- // grow hash size
- poller->hash_size = need;
- }
-
- // save events
- poller->hash[fd] = events;
- }
-}
-static __tb_inline__ tb_size_t tb_poller_hash_get(tb_poller_kqueue_ref_t poller, tb_socket_ref_t sock)
-{
- // check
- tb_assert(poller && poller->hash && sock);
-
- // the socket fd
- tb_long_t fd = tb_sock2fd(sock);
- tb_assert(fd > 0 && fd < TB_MAXS32);
-
- // get the user private data
- return fd < poller->hash_size? poller->hash[fd] : 0;
-}
-static __tb_inline__ tb_void_t tb_poller_hash_del(tb_poller_kqueue_ref_t poller, tb_socket_ref_t sock)
-{
- // check
- tb_assert(poller && poller->hash && sock);
-
- // the socket fd
- tb_long_t fd = tb_sock2fd(sock);
- tb_assert(fd > 0 && fd < TB_MAXS32);
-
- // remove the user private data
- if (fd < poller->hash_size) poller->hash[fd] = 0;
-}
/* //////////////////////////////////////////////////////////////////////////////////////
@@ -202,6 +135,9 @@ tb_poller_ref_t tb_poller_init(tb_cpointer_t priv)
poller = tb_malloc0_type(tb_poller_kqueue_t);
tb_assert_and_check_break(poller);
+ // init socket data
+ tb_sockdata_init(&poller->sockdata);
+
// init kqueue
poller->kqfd = kqueue();
tb_assert_and_check_break(poller->kqfd > 0);
@@ -247,11 +183,6 @@ tb_void_t tb_poller_exit(tb_poller_ref_t self)
poller->pair[0] = tb_null;
poller->pair[1] = tb_null;
- // exit hash
- if (poller->hash) tb_free(poller->hash);
- poller->hash = tb_null;
- poller->hash_size = 0;
-
// exit events
if (poller->events) tb_free(poller->events);
poller->events = tb_null;
@@ -261,24 +192,15 @@ tb_void_t tb_poller_exit(tb_poller_ref_t self)
if (poller->kqfd > 0) close(poller->kqfd);
poller->kqfd = 0;
+ // exit socket data
+ tb_sockdata_exit(&poller->sockdata);
+
// free it
tb_free(poller);
}
-tb_void_t tb_poller_clear(tb_poller_ref_t self)
+tb_size_t tb_poller_type(tb_poller_ref_t poller)
{
- // check
- tb_poller_kqueue_ref_t poller = (tb_poller_kqueue_ref_t)self;
- tb_assert_and_check_return(poller);
-
- // clear hash
- if (poller->hash) tb_memset(poller->hash, 0, poller->hash_size * sizeof(tb_size_t));
-
- // close the previous kqueue fd first
- if (poller->kqfd > 0) close(poller->kqfd);
-
- // recreate a new kqueue
- poller->kqfd = kqueue();
- tb_assert(poller->kqfd > 0);
+ return TB_POLLER_TYPE_KQUEUE;
}
tb_cpointer_t tb_poller_priv(tb_poller_ref_t self)
{
@@ -310,7 +232,7 @@ tb_void_t tb_poller_spak(tb_poller_ref_t self)
tb_bool_t tb_poller_support(tb_poller_ref_t self, tb_size_t events)
{
// all supported events
- static tb_size_t events_supported = TB_POLLER_EVENT_EALL | TB_POLLER_EVENT_CLEAR | TB_POLLER_EVENT_ONESHOT;
+ static const tb_size_t events_supported = TB_POLLER_EVENT_EALL | TB_POLLER_EVENT_CLEAR | TB_POLLER_EVENT_ONESHOT;
// is supported?
return (events_supported & events) == events;
@@ -343,7 +265,7 @@ tb_bool_t tb_poller_insert(tb_poller_ref_t self, tb_socket_ref_t sock, tb_size_t
tb_bool_t ok = n? tb_poller_change(poller, e, n) : tb_true;
// save events to socket
- if (ok) tb_poller_hash_set(poller, sock, events);
+ if (ok) tb_sockdata_insert(&poller->sockdata, sock, (tb_cpointer_t)events);
// ok?
return ok;
@@ -355,7 +277,7 @@ tb_bool_t tb_poller_remove(tb_poller_ref_t self, tb_socket_ref_t sock)
tb_assert_and_check_return_val(poller && poller->kqfd > 0 && sock, tb_false);
// get the previous events
- tb_size_t events = tb_poller_hash_get(poller, sock);
+ tb_size_t events = (tb_size_t)tb_sockdata_get(&poller->sockdata, sock);
// remove this socket and events
struct kevent e[2];
@@ -376,7 +298,7 @@ tb_bool_t tb_poller_remove(tb_poller_ref_t self, tb_socket_ref_t sock)
tb_bool_t ok = n? tb_poller_change(poller, e, n) : tb_true;
// remove events from socket
- if (ok) tb_poller_hash_del(poller, sock);
+ if (ok) tb_sockdata_remove(&poller->sockdata, sock);
// ok?
return ok;
@@ -388,9 +310,9 @@ tb_bool_t tb_poller_modify(tb_poller_ref_t self, tb_socket_ref_t sock, tb_size_t
tb_assert_and_check_return_val(poller && poller->kqfd > 0 && sock, tb_false);
// get the previous events
- tb_size_t events_old = tb_poller_hash_get(poller, sock);
+ tb_size_t events_old = (tb_size_t)tb_sockdata_get(&poller->sockdata, sock);
- // change
+ // get changed events
tb_size_t adde = events & ~events_old;
tb_size_t dele = ~events & events_old;
@@ -428,7 +350,7 @@ tb_bool_t tb_poller_modify(tb_poller_ref_t self, tb_socket_ref_t sock, tb_size_t
tb_bool_t ok = n? tb_poller_change(poller, e, n) : tb_true;
// save events to socket
- if (ok) tb_poller_hash_set(poller, sock, events);
+ if (ok) tb_sockdata_insert(&poller->sockdata, sock, (tb_cpointer_t)events);
// ok?
return ok;
diff --git a/core/src/tbox/src/tbox/platform/mach/prefix.h b/core/src/tbox/src/tbox/platform/mach/prefix.h
index 27c5d5ac2..e64375743 100644
--- a/core/src/tbox/src/tbox/platform/mach/prefix.h
+++ b/core/src/tbox/src/tbox/platform/mach/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/platform/mach/semaphore.c b/core/src/tbox/src/tbox/platform/mach/semaphore.c
index 8673b452c..8a559f31a 100644
--- a/core/src/tbox/src/tbox/platform/mach/semaphore.c
+++ b/core/src/tbox/src/tbox/platform/mach/semaphore.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file semaphore.c
diff --git a/core/src/tbox/src/tbox/platform/memory.c b/core/src/tbox/src/tbox/platform/memory.c
index 6104594f8..e52065793 100644
--- a/core/src/tbox/src/tbox/platform/memory.c
+++ b/core/src/tbox/src/tbox/platform/memory.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file memory.c
diff --git a/core/src/tbox/src/tbox/platform/memory.h b/core/src/tbox/src/tbox/platform/memory.h
index dae8196fc..956fa7b13 100644
--- a/core/src/tbox/src/tbox/platform/memory.h
+++ b/core/src/tbox/src/tbox/platform/memory.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file memory.h
diff --git a/core/src/tbox/src/tbox/platform/mutex.c b/core/src/tbox/src/tbox/platform/mutex.c
index fe09b803b..701282fb0 100644
--- a/core/src/tbox/src/tbox/platform/mutex.c
+++ b/core/src/tbox/src/tbox/platform/mutex.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file mutex.c
diff --git a/core/src/tbox/src/tbox/platform/mutex.h b/core/src/tbox/src/tbox/platform/mutex.h
index d7e6a3dc7..ed2114d9a 100644
--- a/core/src/tbox/src/tbox/platform/mutex.h
+++ b/core/src/tbox/src/tbox/platform/mutex.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file mutex.h
diff --git a/core/src/tbox/src/tbox/platform/page.c b/core/src/tbox/src/tbox/platform/page.c
index ce7d54965..a9a85a624 100644
--- a/core/src/tbox/src/tbox/platform/page.c
+++ b/core/src/tbox/src/tbox/platform/page.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file page.c
diff --git a/core/src/tbox/src/tbox/platform/page.h b/core/src/tbox/src/tbox/platform/page.h
index dea46471e..38eb32fa4 100644
--- a/core/src/tbox/src/tbox/platform/page.h
+++ b/core/src/tbox/src/tbox/platform/page.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file page.h
diff --git a/core/src/tbox/src/tbox/platform/path.c b/core/src/tbox/src/tbox/platform/path.c
index c17bfd62a..72a1d1f11 100644
--- a/core/src/tbox/src/tbox/platform/path.c
+++ b/core/src/tbox/src/tbox/platform/path.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @path path.c
diff --git a/core/src/tbox/src/tbox/platform/path.h b/core/src/tbox/src/tbox/platform/path.h
index fdd2f1ab0..d97d014ab 100644
--- a/core/src/tbox/src/tbox/platform/path.h
+++ b/core/src/tbox/src/tbox/platform/path.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @path path.h
diff --git a/core/src/tbox/src/tbox/platform/platform.h b/core/src/tbox/src/tbox/platform/platform.h
index 190b31e9c..dd85e7b89 100644
--- a/core/src/tbox/src/tbox/platform/platform.h
+++ b/core/src/tbox/src/tbox/platform/platform.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file platform.h
@@ -63,8 +63,5 @@
#include "environment.h"
#include "thread_pool.h"
#include "thread_local.h"
-#ifdef TB_CONFIG_API_HAVE_DEPRECATED
-# include "deprecated/deprecated.h"
-#endif
#endif
diff --git a/core/src/tbox/src/tbox/platform/poller.c b/core/src/tbox/src/tbox/platform/poller.c
index d7b015150..0b8a3157b 100644
--- a/core/src/tbox/src/tbox/platform/poller.c
+++ b/core/src/tbox/src/tbox/platform/poller.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file poller.c
@@ -24,22 +24,32 @@
*/
/* //////////////////////////////////////////////////////////////////////////////////////
+ * trace
+ */
+#define TB_TRACE_MODULE_NAME "poller"
+#define TB_TRACE_MODULE_DEBUG (1)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "poller.h"
+#include "impl/sockdata.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
#if defined(TB_CONFIG_OS_WINDOWS)
-# include "posix/poller_select.c"
+# if defined(TB_CONFIG_MODULE_HAVE_COROUTINE) && !defined(TB_CONFIG_MICRO_ENABLE)
+# include "windows/poller_iocp.c"
+# else
+# include "posix/poller_select.c"
+# endif
#elif defined(TB_CONFIG_POSIX_HAVE_EPOLL_CREATE) \
&& defined(TB_CONFIG_POSIX_HAVE_EPOLL_WAIT)
# include "linux/poller_epoll.c"
#elif defined(TB_CONFIG_OS_MACOSX)
# include "mach/poller_kqueue.c"
-#elif defined(TB_CONFIG_POSIX_HAVE_POLL) \
- && !defined(TB_CONFIG_MICRO_ENABLE) /* TODO remove vector for supporting the micro mode */
+#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"
#elif defined(TB_CONFIG_POSIX_HAVE_SELECT)
# include "posix/poller_select.c"
@@ -53,10 +63,6 @@ tb_void_t tb_poller_exit(tb_poller_ref_t poller)
{
tb_trace_noimpl();
}
-tb_void_t tb_poller_clear(tb_poller_ref_t poller)
-{
- tb_trace_noimpl();
-}
tb_cpointer_t tb_poller_priv(tb_poller_ref_t poller)
{
tb_trace_noimpl();
diff --git a/core/src/tbox/src/tbox/platform/poller.h b/core/src/tbox/src/tbox/platform/poller.h
index 3212f279c..3f58335ed 100644
--- a/core/src/tbox/src/tbox/platform/poller.h
+++ b/core/src/tbox/src/tbox/platform/poller.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file poller.h
@@ -40,6 +40,18 @@ __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
{
@@ -61,6 +73,9 @@ typedef enum __tb_poller_event_e
*/
, TB_POLLER_EVENT_EOF = 0x0100
+ /// socket error after waiting
+, TB_POLLER_EVENT_ERROR = 0x0200
+
}tb_poller_event_e;
/// the poller ref type
@@ -93,11 +108,13 @@ tb_poller_ref_t tb_poller_init(tb_cpointer_t priv);
*/
tb_void_t tb_poller_exit(tb_poller_ref_t poller);
-/*! clear all sockets
+/*! get the poller type
*
* @param poller the poller
+ *
+ * @return the poller type
*/
-tb_void_t tb_poller_clear(tb_poller_ref_t poller);
+tb_size_t tb_poller_type(tb_poller_ref_t poller);
/*! get the user private data
*
diff --git a/core/src/tbox/src/tbox/platform/posix/addrinfo.c b/core/src/tbox/src/tbox/platform/posix/addrinfo.c
index db388225a..0baec8adc 100644
--- a/core/src/tbox/src/tbox/platform/posix/addrinfo.c
+++ b/core/src/tbox/src/tbox/platform/posix/addrinfo.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file addrinfo.c
diff --git a/core/src/tbox/src/tbox/platform/posix/context.c b/core/src/tbox/src/tbox/platform/posix/context.c
index 6aaee4a6a..b84d8ab40 100644
--- a/core/src/tbox/src/tbox/platform/posix/context.c
+++ b/core/src/tbox/src/tbox/platform/posix/context.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file context.c
diff --git a/core/src/tbox/src/tbox/platform/posix/directory.c b/core/src/tbox/src/tbox/platform/posix/directory.c
index fddbc428d..3b1fbd923 100644
--- a/core/src/tbox/src/tbox/platform/posix/directory.c
+++ b/core/src/tbox/src/tbox/platform/posix/directory.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file directory.c
diff --git a/core/src/tbox/src/tbox/platform/posix/dynamic.c b/core/src/tbox/src/tbox/platform/posix/dynamic.c
index 9457ff179..2e10bdd28 100644
--- a/core/src/tbox/src/tbox/platform/posix/dynamic.c
+++ b/core/src/tbox/src/tbox/platform/posix/dynamic.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file dynamic.c
diff --git a/core/src/tbox/src/tbox/platform/posix/event.c b/core/src/tbox/src/tbox/platform/posix/event.c
index 1437728dd..615bc17d0 100644
--- a/core/src/tbox/src/tbox/platform/posix/event.c
+++ b/core/src/tbox/src/tbox/platform/posix/event.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file event.c
diff --git a/core/src/tbox/src/tbox/platform/posix/file.c b/core/src/tbox/src/tbox/platform/posix/file.c
index bc592e54d..1141adff0 100644
--- a/core/src/tbox/src/tbox/platform/posix/file.c
+++ b/core/src/tbox/src/tbox/platform/posix/file.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2018, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file file.c
diff --git a/core/src/tbox/src/tbox/platform/posix/hostname.c b/core/src/tbox/src/tbox/platform/posix/hostname.c
index c019067b3..03de29fcb 100644
--- a/core/src/tbox/src/tbox/platform/posix/hostname.c
+++ b/core/src/tbox/src/tbox/platform/posix/hostname.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file hostname.c
diff --git a/core/src/tbox/src/tbox/platform/posix/ifaddrs.c b/core/src/tbox/src/tbox/platform/posix/ifaddrs.c
index 26bab65e7..46a357860 100644
--- a/core/src/tbox/src/tbox/platform/posix/ifaddrs.c
+++ b/core/src/tbox/src/tbox/platform/posix/ifaddrs.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ifaddrs.c
diff --git a/core/src/tbox/src/tbox/platform/posix/mutex.c b/core/src/tbox/src/tbox/platform/posix/mutex.c
index b9302c10b..d7072f69c 100644
--- a/core/src/tbox/src/tbox/platform/posix/mutex.c
+++ b/core/src/tbox/src/tbox/platform/posix/mutex.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file mutex.c
diff --git a/core/src/tbox/src/tbox/platform/posix/page.c b/core/src/tbox/src/tbox/platform/posix/page.c
index 9bce491cf..9eaf4b1f5 100644
--- a/core/src/tbox/src/tbox/platform/posix/page.c
+++ b/core/src/tbox/src/tbox/platform/posix/page.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file page.c
diff --git a/core/src/tbox/src/tbox/platform/posix/poller_poll.c b/core/src/tbox/src/tbox/platform/posix/poller_poll.c
index a26e9b23a..24b6428c3 100644
--- a/core/src/tbox/src/tbox/platform/posix/poller_poll.c
+++ b/core/src/tbox/src/tbox/platform/posix/poller_poll.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file poller_poll.c
@@ -54,11 +54,8 @@ typedef struct __tb_poller_poll_t
// the copied poll fds
tb_vector_ref_t cfds;
- // the user private data hash (socket => priv)
- tb_cpointer_t* hash;
-
- // the user private data hash size
- tb_size_t hash_size;
+ // the socket data
+ tb_sockdata_t sockdata;
}tb_poller_poll_t, *tb_poller_poll_ref_t;
@@ -107,70 +104,6 @@ static tb_bool_t tb_poller_walk_modify(tb_iterator_ref_t iterator, tb_pointer_t
// ok
return tb_true;
}
-static tb_void_t tb_poller_hash_set(tb_poller_poll_ref_t poller, tb_socket_ref_t sock, tb_cpointer_t priv)
-{
- // check
- tb_assert(poller && sock);
-
- // the socket fd
- tb_long_t fd = tb_sock2fd(sock);
- tb_assert(fd > 0 && fd < TB_MAXS32);
-
- // not null?
- if (priv)
- {
- // no hash? init it first
- tb_size_t need = fd + 1;
- if (!poller->hash)
- {
- // init hash
- poller->hash = tb_nalloc0_type(need, tb_cpointer_t);
- tb_assert_and_check_return(poller->hash);
-
- // init hash size
- poller->hash_size = need;
- }
- else if (need > poller->hash_size)
- {
- // grow hash
- poller->hash = (tb_cpointer_t*)tb_ralloc(poller->hash, need * sizeof(tb_cpointer_t));
- tb_assert_and_check_return(poller->hash);
-
- // init growed space
- tb_memset(poller->hash + poller->hash_size, 0, (need - poller->hash_size) * sizeof(tb_cpointer_t));
-
- // grow hash size
- poller->hash_size = need;
- }
-
- // save the user private data
- poller->hash[fd] = priv;
- }
-}
-static __tb_inline__ tb_cpointer_t tb_poller_hash_get(tb_poller_poll_ref_t poller, tb_socket_ref_t sock)
-{
- // check
- tb_assert(poller && poller->hash && sock);
-
- // the socket fd
- tb_long_t fd = tb_sock2fd(sock);
- tb_assert(fd > 0 && fd < TB_MAXS32);
-
- // get the user private data
- return fd < poller->hash_size? poller->hash[fd] : tb_null;
-}
-static __tb_inline__ tb_void_t tb_poller_hash_del(tb_poller_poll_ref_t poller, tb_socket_ref_t sock)
-{
- // check
- tb_assert(poller && poller->hash && sock);
-
- // the socket fd
- tb_long_t fd = tb_sock2fd(sock);
- tb_assert(fd > 0 && fd < TB_MAXS32);
-
- // remove the user private data
- if (fd < poller->hash_size) poller->hash[fd] = tb_null;
-}
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
@@ -186,6 +119,9 @@ tb_poller_ref_t tb_poller_init(tb_cpointer_t priv)
poller = tb_malloc0_type(tb_poller_poll_t);
tb_assert_and_check_break(poller);
+ // init socket data
+ tb_sockdata_init(&poller->sockdata);
+
// 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);
@@ -231,11 +167,6 @@ tb_void_t tb_poller_exit(tb_poller_ref_t self)
poller->pair[0] = tb_null;
poller->pair[1] = tb_null;
- // exit hash
- if (poller->hash) tb_free(poller->hash);
- poller->hash = tb_null;
- poller->hash_size = 0;
-
// close pfds
if (poller->pfds) tb_vector_exit(poller->pfds);
poller->pfds = tb_null;
@@ -244,26 +175,15 @@ tb_void_t tb_poller_exit(tb_poller_ref_t self)
if (poller->cfds) tb_vector_exit(poller->cfds);
poller->cfds = tb_null;
+ // exit socket data
+ tb_sockdata_exit(&poller->sockdata);
+
// free it
tb_free(poller);
}
-tb_void_t tb_poller_clear(tb_poller_ref_t self)
+tb_size_t tb_poller_type(tb_poller_ref_t poller)
{
- // check
- tb_poller_poll_ref_t poller = (tb_poller_poll_ref_t)self;
- tb_assert_and_check_return(poller);
-
- // clear hash
- if (poller->hash) tb_memset(poller->hash, 0, poller->hash_size * sizeof(tb_cpointer_t));
-
- // clear pfds
- if (poller->pfds) tb_vector_clear(poller->pfds);
-
- // clear cfds
- if (poller->cfds) tb_vector_clear(poller->cfds);
-
- // spak it
- if (poller->pair[0]) tb_socket_send(poller->pair[0], (tb_byte_t const*)"p", 1);
+ return TB_POLLER_TYPE_POLL;
}
tb_cpointer_t tb_poller_priv(tb_poller_ref_t self)
{
@@ -295,7 +215,7 @@ tb_void_t tb_poller_spak(tb_poller_ref_t self)
tb_bool_t tb_poller_support(tb_poller_ref_t self, tb_size_t events)
{
// all supported events
- static tb_size_t events_supported = TB_POLLER_EVENT_EALL;
+ static const tb_size_t events_supported = TB_POLLER_EVENT_EALL;
// is supported?
return (events_supported & events) == events;
@@ -319,7 +239,7 @@ tb_bool_t tb_poller_insert(tb_poller_ref_t self, tb_socket_ref_t sock, tb_size_t
tb_vector_insert_tail(poller->pfds, &pfd);
// bind user private data to socket
- tb_poller_hash_set(poller, sock, priv);
+ tb_sockdata_insert(&poller->sockdata, sock, priv);
// ok
return tb_true;
@@ -334,7 +254,7 @@ tb_bool_t tb_poller_remove(tb_poller_ref_t self, tb_socket_ref_t sock)
tb_remove_first_if(poller->pfds, tb_poller_walk_remove, (tb_cpointer_t)(tb_long_t)tb_sock2fd(sock));
// remove user private data from this socket
- tb_poller_hash_del(poller, sock);
+ tb_sockdata_remove(&poller->sockdata, sock);
// ok
return tb_true;
@@ -355,7 +275,7 @@ tb_bool_t tb_poller_modify(tb_poller_ref_t self, tb_socket_ref_t sock, tb_size_t
tb_walk_all(poller->pfds, tb_poller_walk_modify, tuple);
// modify user private data to socket
- tb_poller_hash_set(poller, sock, priv);
+ tb_sockdata_insert(&poller->sockdata, sock, priv);
// ok
return tb_true;
@@ -431,7 +351,7 @@ tb_long_t tb_poller_wait(tb_poller_ref_t self, tb_poller_event_func_t func, tb_l
events |= TB_POLLER_EVENT_RECV | TB_POLLER_EVENT_SEND;
// call event function
- func(self, sock, events, tb_poller_hash_get(poller, sock));
+ func(self, sock, events, tb_sockdata_get(&poller->sockdata, sock));
// update the events count
wait++;
diff --git a/core/src/tbox/src/tbox/platform/posix/poller_select.c b/core/src/tbox/src/tbox/platform/posix/poller_select.c
index 99853e1bb..86dde2c95 100644
--- a/core/src/tbox/src/tbox/platform/posix/poller_select.c
+++ b/core/src/tbox/src/tbox/platform/posix/poller_select.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file poller_select.c
@@ -31,6 +31,7 @@
#ifdef TB_CONFIG_OS_WINDOWS
# include "../windows/interface/interface.h"
#else
+# include <sys/socket.h>
# include <sys/select.h>
#endif
@@ -107,7 +108,7 @@ static tb_void_t tb_poller_list_set(tb_poller_select_ref_t poller, tb_socket_ref
// no list? init it first
if (!poller->list)
{
- // init hash
+ // init list
poller->list = tb_nalloc0_type(FD_SETSIZE, tb_poller_data_t);
tb_assert_and_check_return(poller->list);
}
@@ -122,13 +123,13 @@ static tb_void_t tb_poller_list_set(tb_poller_select_ref_t poller, tb_socket_ref
else
{
// insert the private data
- if (i < n) tb_memmov(poller->list + i + 1, poller->list + i, (n - i) * sizeof(tb_poller_data_t));
+ if (i < n) tb_memmov_(poller->list + i + 1, poller->list + i, (n - i) * sizeof(tb_poller_data_t));
poller->list[i].sock = sock;
poller->list[i].priv = priv;
- }
- // update the list size
- poller->list_size++;
+ // update the list size
+ poller->list_size++;
+ }
}
}
static tb_void_t tb_poller_list_del(tb_poller_select_ref_t poller, tb_socket_ref_t sock)
@@ -143,10 +144,13 @@ static tb_void_t tb_poller_list_del(tb_poller_select_ref_t poller, tb_socket_ref
tb_size_t i = 0;
tb_size_t n = poller->list_size;
for (i = 0; i < n; i++) if (sock == poller->list[i].sock) break;
- if (i + 1 < n) tb_memmov(poller->list + i, poller->list + i + 1, (n - i - 1) * sizeof(tb_poller_data_t));
- // update the list size
- poller->list_size--;
+ // 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_data_t));
+ poller->list_size--;
+ }
}
}
@@ -221,24 +225,9 @@ tb_void_t tb_poller_exit(tb_poller_ref_t self)
// free it
tb_free(poller);
}
-tb_void_t tb_poller_clear(tb_poller_ref_t self)
+tb_size_t tb_poller_type(tb_poller_ref_t poller)
{
- // check
- tb_poller_select_ref_t poller = (tb_poller_select_ref_t)self;
- tb_assert_and_check_return(poller);
-
- // clear fds
- poller->sfdm = 0;
- FD_ZERO(&poller->rfds);
- FD_ZERO(&poller->wfds);
- FD_ZERO(&poller->rfdc);
- FD_ZERO(&poller->wfdc);
-
- // clear list
- poller->list_size = 0;
-
- // spak it
- if (poller->pair[0]) tb_socket_send(poller->pair[0], (tb_byte_t const*)"p", 1);
+ return TB_POLLER_TYPE_SELECT;
}
tb_cpointer_t tb_poller_priv(tb_poller_ref_t self)
{
@@ -270,7 +259,7 @@ tb_void_t tb_poller_spak(tb_poller_ref_t self)
tb_bool_t tb_poller_support(tb_poller_ref_t self, tb_size_t events)
{
// all supported events
- static tb_size_t events_supported = TB_POLLER_EVENT_EALL;
+ static const tb_size_t events_supported = TB_POLLER_EVENT_EALL;
// is supported?
return (events_supported & events) == events;
@@ -314,7 +303,7 @@ tb_bool_t tb_poller_remove(tb_poller_ref_t self, tb_socket_ref_t sock)
tb_poller_list_del(poller, sock);
// update socket count
- poller->count--;
+ if (poller->count > 0) poller->count--;
// ok
return tb_true;
@@ -340,7 +329,7 @@ tb_long_t tb_poller_wait(tb_poller_ref_t self, tb_poller_event_func_t func, tb_l
{
// check
tb_poller_select_ref_t poller = (tb_poller_select_ref_t)self;
- tb_assert_and_check_return_val(poller && poller->list && func, -1);
+ tb_assert_and_check_return_val(poller && func, -1);
// init time
struct timeval t = {0};
@@ -383,6 +372,9 @@ tb_long_t tb_poller_wait(tb_poller_ref_t self, tb_poller_event_func_t func, tb_l
// end?
tb_check_break(wait >= 0);
+ // check
+ tb_assert_and_check_return_val(poller->list, -1);
+
// the sock
tb_socket_ref_t sock = (tb_socket_ref_t)poller->list[i].sock;
tb_assert_and_check_return_val(sock, -1);
@@ -414,6 +406,19 @@ tb_long_t tb_poller_wait(tb_poller_ref_t self, tb_poller_event_func_t func, tb_l
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)
{
diff --git a/core/src/tbox/src/tbox/platform/posix/prefix.h b/core/src/tbox/src/tbox/platform/posix/prefix.h
index 04de119b7..5bfdaee5e 100644
--- a/core/src/tbox/src/tbox/platform/posix/prefix.h
+++ b/core/src/tbox/src/tbox/platform/posix/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/platform/posix/process.c b/core/src/tbox/src/tbox/platform/posix/process.c
index 34d606a27..b316ea0af 100644
--- a/core/src/tbox/src/tbox/platform/posix/process.c
+++ b/core/src/tbox/src/tbox/platform/posix/process.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file process.c
diff --git a/core/src/tbox/src/tbox/platform/posix/processor.c b/core/src/tbox/src/tbox/platform/posix/processor.c
index 1f8a847e8..4a0433328 100644
--- a/core/src/tbox/src/tbox/platform/posix/processor.c
+++ b/core/src/tbox/src/tbox/platform/posix/processor.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file processor.c
diff --git a/core/src/tbox/src/tbox/platform/posix/regex.c b/core/src/tbox/src/tbox/platform/posix/regex.c
index ec10a585b..054691363 100644
--- a/core/src/tbox/src/tbox/platform/posix/regex.c
+++ b/core/src/tbox/src/tbox/platform/posix/regex.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file regex.c
diff --git a/core/src/tbox/src/tbox/platform/posix/sched.c b/core/src/tbox/src/tbox/platform/posix/sched.c
index 76454e887..218a81ed2 100644
--- a/core/src/tbox/src/tbox/platform/posix/sched.c
+++ b/core/src/tbox/src/tbox/platform/posix/sched.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file sched.c
diff --git a/core/src/tbox/src/tbox/platform/posix/semaphore.c b/core/src/tbox/src/tbox/platform/posix/semaphore.c
index 63f0b1cdd..274783e7a 100644
--- a/core/src/tbox/src/tbox/platform/posix/semaphore.c
+++ b/core/src/tbox/src/tbox/platform/posix/semaphore.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file semaphore.c
@@ -37,8 +37,8 @@
tb_semaphore_ref_t tb_semaphore_init(tb_size_t init)
{
// done
- tb_bool_t ok = tb_false;
- sem_t* semaphore = tb_null;
+ tb_bool_t ok = tb_false;
+ sem_t* semaphore = tb_null;
do
{
// make semaphore
diff --git a/core/src/tbox/src/tbox/platform/posix/sockaddr.h b/core/src/tbox/src/tbox/platform/posix/sockaddr.h
index 44ca87714..bbc79e51b 100644
--- a/core/src/tbox/src/tbox/platform/posix/sockaddr.h
+++ b/core/src/tbox/src/tbox/platform/posix/sockaddr.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file sockaddr.h
diff --git a/core/src/tbox/src/tbox/platform/posix/socket.c b/core/src/tbox/src/tbox/platform/posix/socket.c
index 7e0dbe80c..4597b7df5 100644
--- a/core/src/tbox/src/tbox/platform/posix/socket.c
+++ b/core/src/tbox/src/tbox/platform/posix/socket.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file socket.c
@@ -210,10 +210,7 @@ tb_bool_t tb_socket_ctrl(tb_socket_ref_t sock, tb_size_t ctrl, ...)
// enable the nagle's algorithm
tb_int_t enable = (tb_int_t)tb_va_arg(args, tb_bool_t);
if (!setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (tb_char_t*)&enable, sizeof(enable)))
- {
- // ok
ok = tb_true;
- }
}
break;
case TB_SOCKET_CTRL_GET_TCP_NODELAY:
@@ -244,10 +241,7 @@ tb_bool_t tb_socket_ctrl(tb_socket_ref_t sock, tb_size_t ctrl, ...)
// set the recv buffer size
tb_int_t real = (tb_int_t)buff_size;
if (!setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (tb_char_t*)&real, sizeof(real)))
- {
- // ok
ok = tb_true;
- }
}
break;
case TB_SOCKET_CTRL_GET_RECV_BUFF_SIZE:
@@ -278,10 +272,7 @@ tb_bool_t tb_socket_ctrl(tb_socket_ref_t sock, tb_size_t ctrl, ...)
// set the send buffer size
tb_int_t real = (tb_int_t)buff_size;
if (!setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (tb_char_t*)&real, sizeof(real)))
- {
- // ok
ok = tb_true;
- }
}
break;
case TB_SOCKET_CTRL_GET_SEND_BUFF_SIZE:
@@ -414,7 +405,6 @@ tb_socket_ref_t tb_socket_accept(tb_socket_ref_t sock, tb_ipaddr_ref_t addr)
// non-block
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
-#ifdef TB_CONFIG_OS_LINUX
/* disable the nagle's algorithm to fix 40ms ack delay in some case (.e.g send-send-40ms-recv)
*
* 40ms is the tcp ack delay on linux, which indicates that you are likely
@@ -433,8 +423,8 @@ tb_socket_ref_t tb_socket_accept(tb_socket_ref_t sock, tb_ipaddr_ref_t addr)
*
* so we set TCP_NODELAY to reduce response delay for the accepted socket in the server by default
*/
- tb_socket_ctrl(sock, TB_SOCKET_CTRL_SET_TCP_NODELAY, tb_true);
-#endif
+ tb_int_t enable = 1;
+ setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (tb_char_t*)&enable, sizeof(enable));
// save address
if (addr) tb_sockaddr_save(addr, &d);
diff --git a/core/src/tbox/src/tbox/platform/posix/socket_poll.c b/core/src/tbox/src/tbox/platform/posix/socket_poll.c
index 2d3df6947..46b3af912 100644
--- a/core/src/tbox/src/tbox/platform/posix/socket_poll.c
+++ b/core/src/tbox/src/tbox/platform/posix/socket_poll.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file socket_poll.c
diff --git a/core/src/tbox/src/tbox/platform/posix/socket_select.c b/core/src/tbox/src/tbox/platform/posix/socket_select.c
index 9dd3f6f6f..a2f567e6b 100644
--- a/core/src/tbox/src/tbox/platform/posix/socket_select.c
+++ b/core/src/tbox/src/tbox/platform/posix/socket_select.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file socket_select.c
@@ -29,6 +29,7 @@
#ifdef TB_CONFIG_OS_WINDOWS
# include "../windows/interface/interface.h"
#else
+# include <sys/socket.h>
# include <sys/select.h>
#endif
#if defined(TB_CONFIG_MODULE_HAVE_COROUTINE) \
@@ -109,16 +110,18 @@ tb_long_t tb_socket_wait(tb_socket_ref_t sock, tb_size_t events, tb_long_t timeo
// timeout?
tb_check_return_val(r, 0);
- // error?
- tb_int_t o = 0;
+ // check socket error?
#ifdef TB_CONFIG_OS_WINDOWS
+ tb_int_t error = 0;
tb_int_t n = sizeof(tb_int_t);
- tb_ws2_32()->getsockopt(fd, SOL_SOCKET, SO_ERROR, (tb_char_t*)&o, &n);
+ if (!tb_ws2_32()->getsockopt(fd, SOL_SOCKET, SO_ERROR, (tb_char_t*)&error, &n) && error)
+ return -1;
#else
+ tb_int_t error = 0;
socklen_t n = sizeof(socklen_t);
- getsockopt(fd, SOL_SOCKET, SO_ERROR, (tb_char_t*)&o, &n);
+ if (!getsockopt(fd, SOL_SOCKET, SO_ERROR, (tb_char_t*)&error, &n) && error)
+ return -1;
#endif
- if (o) return -1;
// ok
tb_long_t e = TB_SOCKET_EVENT_NONE;
diff --git a/core/src/tbox/src/tbox/platform/posix/thread.c b/core/src/tbox/src/tbox/platform/posix/thread.c
index ba2613ce8..9b2432863 100644
--- a/core/src/tbox/src/tbox/platform/posix/thread.c
+++ b/core/src/tbox/src/tbox/platform/posix/thread.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file thread.c
diff --git a/core/src/tbox/src/tbox/platform/posix/thread_local.c b/core/src/tbox/src/tbox/platform/posix/thread_local.c
index 933a3a65b..dea394f96 100644
--- a/core/src/tbox/src/tbox/platform/posix/thread_local.c
+++ b/core/src/tbox/src/tbox/platform/posix/thread_local.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @tlocal thread_local.c
@@ -96,6 +96,10 @@ tb_void_t tb_thread_local_exit(tb_thread_local_ref_t local)
// check
tb_assert(local);
+ // free the previous data first
+ if (local->free && tb_thread_local_has(local))
+ local->free(tb_thread_local_get(local));
+
// exit it
pthread_key_delete(((pthread_key_t*)local->priv)[0]);
pthread_key_delete(((pthread_key_t*)local->priv)[1]);
diff --git a/core/src/tbox/src/tbox/platform/posix/time.c b/core/src/tbox/src/tbox/platform/posix/time.c
index bcff9f826..793fb93c1 100644
--- a/core/src/tbox/src/tbox/platform/posix/time.c
+++ b/core/src/tbox/src/tbox/platform/posix/time.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file time.c
diff --git a/core/src/tbox/src/tbox/platform/prefix.h b/core/src/tbox/src/tbox/platform/prefix.h
index 79e536679..2b01f8532 100644
--- a/core/src/tbox/src/tbox/platform/prefix.h
+++ b/core/src/tbox/src/tbox/platform/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/platform/print.c b/core/src/tbox/src/tbox/platform/print.c
index 7f92bfaf3..0cceeefc0 100644
--- a/core/src/tbox/src/tbox/platform/print.c
+++ b/core/src/tbox/src/tbox/platform/print.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file print.c
diff --git a/core/src/tbox/src/tbox/platform/print.h b/core/src/tbox/src/tbox/platform/print.h
index 0862fefc1..31f657a07 100644
--- a/core/src/tbox/src/tbox/platform/print.h
+++ b/core/src/tbox/src/tbox/platform/print.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file print.h
diff --git a/core/src/tbox/src/tbox/platform/process.c b/core/src/tbox/src/tbox/platform/process.c
index c784ffae7..7b4021cc1 100644
--- a/core/src/tbox/src/tbox/platform/process.c
+++ b/core/src/tbox/src/tbox/platform/process.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file process.c
diff --git a/core/src/tbox/src/tbox/platform/process.h b/core/src/tbox/src/tbox/platform/process.h
index d49596331..34fe4d638 100644
--- a/core/src/tbox/src/tbox/platform/process.h
+++ b/core/src/tbox/src/tbox/platform/process.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file process.h
diff --git a/core/src/tbox/src/tbox/platform/processor.c b/core/src/tbox/src/tbox/platform/processor.c
index 96cec6f23..856a38dcb 100644
--- a/core/src/tbox/src/tbox/platform/processor.c
+++ b/core/src/tbox/src/tbox/platform/processor.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file processor.c
diff --git a/core/src/tbox/src/tbox/platform/processor.h b/core/src/tbox/src/tbox/platform/processor.h
index a08750488..e62a1de38 100644
--- a/core/src/tbox/src/tbox/platform/processor.h
+++ b/core/src/tbox/src/tbox/platform/processor.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file processor.h
diff --git a/core/src/tbox/src/tbox/platform/sched.c b/core/src/tbox/src/tbox/platform/sched.c
index ea90526ab..8907896b7 100644
--- a/core/src/tbox/src/tbox/platform/sched.c
+++ b/core/src/tbox/src/tbox/platform/sched.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file sched.c
diff --git a/core/src/tbox/src/tbox/platform/sched.h b/core/src/tbox/src/tbox/platform/sched.h
index 29445b038..77f4c8fe2 100644
--- a/core/src/tbox/src/tbox/platform/sched.h
+++ b/core/src/tbox/src/tbox/platform/sched.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file sched.h
diff --git a/core/src/tbox/src/tbox/platform/semaphore.c b/core/src/tbox/src/tbox/platform/semaphore.c
index 925c76739..6ac9a6af3 100644
--- a/core/src/tbox/src/tbox/platform/semaphore.c
+++ b/core/src/tbox/src/tbox/platform/semaphore.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file semaphore.c
diff --git a/core/src/tbox/src/tbox/platform/semaphore.h b/core/src/tbox/src/tbox/platform/semaphore.h
index c63e12439..64c79a8f0 100644
--- a/core/src/tbox/src/tbox/platform/semaphore.h
+++ b/core/src/tbox/src/tbox/platform/semaphore.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file semaphore.h
diff --git a/core/src/tbox/src/tbox/platform/socket.c b/core/src/tbox/src/tbox/platform/socket.c
index e6dbdf3d4..da74f7d60 100644
--- a/core/src/tbox/src/tbox/platform/socket.c
+++ b/core/src/tbox/src/tbox/platform/socket.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file socket.c
@@ -152,6 +152,8 @@ tb_long_t tb_socket_usendv(tb_socket_ref_t sock, tb_ipaddr_ref_t addr, tb_iovec_
# include "posix/socket_select.c"
#elif defined(TB_CONFIG_POSIX_HAVE_POLL)
# include "posix/socket_poll.c"
+#elif defined(TB_CONFIG_POSIX_HAVE_SELECT)
+# include "posix/socket_select.c"
#else
tb_long_t tb_socket_wait(tb_socket_ref_t sock, tb_size_t events, tb_long_t timeout)
{
@@ -159,3 +161,60 @@ tb_long_t tb_socket_wait(tb_socket_ref_t sock, tb_size_t events, tb_long_t timeo
return -1;
}
#endif
+
+tb_bool_t tb_socket_brecv(tb_socket_ref_t sock, tb_byte_t* data, tb_size_t size)
+{
+ // recv data
+ tb_size_t recv = 0;
+ tb_long_t wait = 0;
+ while (recv < size)
+ {
+ // recv it
+ tb_long_t real = tb_socket_recv(sock, data + recv, size - recv);
+
+ // has data?
+ if (real > 0)
+ {
+ recv += real;
+ wait = 0;
+ }
+ // no data? wait it
+ else if (!real && !wait)
+ {
+ // wait it
+ wait = tb_socket_wait(sock, TB_SOCKET_EVENT_RECV, -1);
+ tb_check_break(wait > 0);
+ }
+ // failed or end?
+ else break;
+ }
+ return recv == size;
+}
+tb_bool_t tb_socket_bsend(tb_socket_ref_t sock, tb_byte_t const* data, tb_size_t size)
+{
+ // send data
+ tb_size_t send = 0;
+ tb_long_t wait = 0;
+ while (send < size)
+ {
+ // send it
+ tb_long_t real = tb_socket_send(sock, data + send, size - send);
+
+ // has data?
+ if (real > 0)
+ {
+ send += real;
+ wait = 0;
+ }
+ // no data? wait it
+ else if (!real && !wait)
+ {
+ // wait it
+ wait = tb_socket_wait(sock, TB_SOCKET_EVENT_SEND, -1);
+ tb_check_break(wait > 0);
+ }
+ // failed or end?
+ else break;
+ }
+ return send == size;
+}
diff --git a/core/src/tbox/src/tbox/platform/socket.h b/core/src/tbox/src/tbox/platform/socket.h
index 8fc8ec2f0..2125837d2 100644
--- a/core/src/tbox/src/tbox/platform/socket.h
+++ b/core/src/tbox/src/tbox/platform/socket.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file socket.h
@@ -101,7 +101,7 @@ typedef enum __tb_socket_event_e
TB_SOCKET_EVENT_NONE = 0x0000
, TB_SOCKET_EVENT_RECV = 0x0001
, TB_SOCKET_EVENT_SEND = 0x0002
-, TB_SOCKET_EVENT_CONN = TB_SOCKET_EVENT_SEND
+, TB_SOCKET_EVENT_CONN = TB_SOCKET_EVENT_SEND
, TB_SOCKET_EVENT_ACPT = TB_SOCKET_EVENT_RECV
, TB_SOCKET_EVENT_EALL = TB_SOCKET_EVENT_RECV | TB_SOCKET_EVENT_SEND
@@ -144,10 +144,10 @@ tb_bool_t tb_socket_pair(tb_size_t type, tb_socket_ref_t pair[2]);
*/
tb_bool_t tb_socket_ctrl(tb_socket_ref_t sock, tb_size_t ctrl, ...);
-/*! connect socket
+/*! connect the given client address
*
* @param sock the socket
- * @param addr the address
+ * @param addr the client address
*
* @return ok: 1, continue: 0; failed: -1
*/
@@ -221,6 +221,26 @@ tb_long_t tb_socket_recv(tb_socket_ref_t sock, tb_byte_t* data, tb_siz
*/
tb_long_t tb_socket_send(tb_socket_ref_t sock, tb_byte_t const* data, tb_size_t size);
+/*! recv the socket data for tcp with block mode
+ *
+ * @param sock the socket
+ * @param data the data
+ * @param size the size
+ *
+ * @return tb_true or tb_false
+ */
+tb_bool_t tb_socket_brecv(tb_socket_ref_t sock, tb_byte_t* data, tb_size_t size);
+
+/*! send the socket data for tcp with block mode
+ *
+ * @param sock the socket
+ * @param data the data
+ * @param size the size
+ *
+ * @return tb_true or tb_false
+ */
+tb_bool_t tb_socket_bsend(tb_socket_ref_t sock, tb_byte_t const* data, tb_size_t size);
+
/*! recvv the socket data for tcp
*
* @param sock the socket
@@ -241,7 +261,7 @@ tb_long_t tb_socket_recvv(tb_socket_ref_t sock, tb_iovec_t const* list
*/
tb_long_t tb_socket_sendv(tb_socket_ref_t sock, tb_iovec_t const* list, tb_size_t size);
-/*! sendf the socket data
+/*! send file data
*
* @param sock the socket
* @param file the file
diff --git a/core/src/tbox/src/tbox/platform/spinlock.h b/core/src/tbox/src/tbox/platform/spinlock.h
index 4d734a15e..3513d65d7 100644
--- a/core/src/tbox/src/tbox/platform/spinlock.h
+++ b/core/src/tbox/src/tbox/platform/spinlock.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file spinlock.h
diff --git a/core/src/tbox/src/tbox/platform/syserror.c b/core/src/tbox/src/tbox/platform/syserror.c
index 80012d740..c24b65ce3 100644
--- a/core/src/tbox/src/tbox/platform/syserror.c
+++ b/core/src/tbox/src/tbox/platform/syserror.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file syserror.c
diff --git a/core/src/tbox/src/tbox/platform/syserror.h b/core/src/tbox/src/tbox/platform/syserror.h
index e19bfda1d..178256622 100644
--- a/core/src/tbox/src/tbox/platform/syserror.h
+++ b/core/src/tbox/src/tbox/platform/syserror.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file syserror.h
diff --git a/core/src/tbox/src/tbox/platform/systemv/prefix.h b/core/src/tbox/src/tbox/platform/systemv/prefix.h
index 2cd49391f..800abd7db 100644
--- a/core/src/tbox/src/tbox/platform/systemv/prefix.h
+++ b/core/src/tbox/src/tbox/platform/systemv/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/platform/systemv/semaphore.c b/core/src/tbox/src/tbox/platform/systemv/semaphore.c
index 43ebc55d8..d80d1182b 100644
--- a/core/src/tbox/src/tbox/platform/systemv/semaphore.c
+++ b/core/src/tbox/src/tbox/platform/systemv/semaphore.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file semaphore.c
diff --git a/core/src/tbox/src/tbox/platform/thread.c b/core/src/tbox/src/tbox/platform/thread.c
index a2a19cfdb..4930c6f38 100644
--- a/core/src/tbox/src/tbox/platform/thread.c
+++ b/core/src/tbox/src/tbox/platform/thread.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file thread.c
diff --git a/core/src/tbox/src/tbox/platform/thread.h b/core/src/tbox/src/tbox/platform/thread.h
index f847459b8..46ef9c342 100644
--- a/core/src/tbox/src/tbox/platform/thread.h
+++ b/core/src/tbox/src/tbox/platform/thread.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file thread.h
diff --git a/core/src/tbox/src/tbox/platform/thread_local.c b/core/src/tbox/src/tbox/platform/thread_local.c
index 47051e13b..4fa888cde 100644
--- a/core/src/tbox/src/tbox/platform/thread_local.c
+++ b/core/src/tbox/src/tbox/platform/thread_local.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @tlocal thread_local.c
@@ -98,13 +98,13 @@ tb_void_t tb_thread_local_walk(tb_walk_func_t func, tb_cpointer_t priv)
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
-#if defined(TB_CONFIG_POSIX_HAVE_PTHREAD_SETSPECIFIC) && \
+#if defined(TB_CONFIG_OS_WINDOWS)
+# include "windows/thread_local.c"
+#elif defined(TB_CONFIG_POSIX_HAVE_PTHREAD_SETSPECIFIC) && \
defined(TB_CONFIG_POSIX_HAVE_PTHREAD_GETSPECIFIC) && \
defined(TB_CONFIG_POSIX_HAVE_PTHREAD_KEY_CREATE) && \
defined(TB_CONFIG_POSIX_HAVE_PTHREAD_KEY_DELETE)
# include "posix/thread_local.c"
-#elif defined(TB_CONFIG_OS_WINDOWS)
-# include "windows/thread_local.c"
#else
tb_bool_t tb_thread_local_init(tb_thread_local_ref_t local, tb_thread_local_free_t func)
{
diff --git a/core/src/tbox/src/tbox/platform/thread_local.h b/core/src/tbox/src/tbox/platform/thread_local.h
index 8943a17e6..2270873d6 100644
--- a/core/src/tbox/src/tbox/platform/thread_local.h
+++ b/core/src/tbox/src/tbox/platform/thread_local.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file thread_local.h
diff --git a/core/src/tbox/src/tbox/platform/thread_pool.c b/core/src/tbox/src/tbox/platform/thread_pool.c
index 369a5aef0..df7351f10 100644
--- a/core/src/tbox/src/tbox/platform/thread_pool.c
+++ b/core/src/tbox/src/tbox/platform/thread_pool.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file thread_pool.c
@@ -201,7 +201,7 @@ typedef struct __tb_thread_pool_impl_t
static tb_handle_t tb_thread_pool_instance_init(tb_cpointer_t* ppriv)
{
// init it
- return tb_thread_pool_init(0, 0);
+ return (tb_handle_t)tb_thread_pool_init(0, 0);
}
static tb_void_t tb_thread_pool_instance_exit(tb_handle_t pool, tb_cpointer_t priv)
{
diff --git a/core/src/tbox/src/tbox/platform/thread_pool.h b/core/src/tbox/src/tbox/platform/thread_pool.h
index a0023ab6b..a5d71a19c 100644
--- a/core/src/tbox/src/tbox/platform/thread_pool.h
+++ b/core/src/tbox/src/tbox/platform/thread_pool.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file thread_pool.h
diff --git a/core/src/tbox/src/tbox/platform/time.c b/core/src/tbox/src/tbox/platform/time.c
index 054a4d57b..d0085dc13 100644
--- a/core/src/tbox/src/tbox/platform/time.c
+++ b/core/src/tbox/src/tbox/platform/time.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file time.c
diff --git a/core/src/tbox/src/tbox/platform/time.h b/core/src/tbox/src/tbox/platform/time.h
index c99a91146..8b1a17aa2 100644
--- a/core/src/tbox/src/tbox/platform/time.h
+++ b/core/src/tbox/src/tbox/platform/time.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file time.h
diff --git a/core/src/tbox/src/tbox/platform/timer.c b/core/src/tbox/src/tbox/platform/timer.c
index 7906a6014..74b4998b5 100644
--- a/core/src/tbox/src/tbox/platform/timer.c
+++ b/core/src/tbox/src/tbox/platform/timer.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file timer.c
diff --git a/core/src/tbox/src/tbox/platform/timer.h b/core/src/tbox/src/tbox/platform/timer.h
index b7a0cc806..0bab213a1 100644
--- a/core/src/tbox/src/tbox/platform/timer.h
+++ b/core/src/tbox/src/tbox/platform/timer.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file timer.h
diff --git a/core/src/tbox/src/tbox/platform/unix/dns.c b/core/src/tbox/src/tbox/platform/unix/dns.c
index 80a3dbb07..a6847f83a 100644
--- a/core/src/tbox/src/tbox/platform/unix/dns.c
+++ b/core/src/tbox/src/tbox/platform/unix/dns.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file dns.c
diff --git a/core/src/tbox/src/tbox/platform/unix/prefix.h b/core/src/tbox/src/tbox/platform/unix/prefix.h
index 2b33cf427..074507327 100644
--- a/core/src/tbox/src/tbox/platform/unix/prefix.h
+++ b/core/src/tbox/src/tbox/platform/unix/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/platform/unix/syscall.h b/core/src/tbox/src/tbox/platform/unix/syscall.h
index 26296e43a..14781fa52 100644
--- a/core/src/tbox/src/tbox/platform/unix/syscall.h
+++ b/core/src/tbox/src/tbox/platform/unix/syscall.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file syscall.h
diff --git a/core/src/tbox/src/tbox/platform/windows/addrinfo.c b/core/src/tbox/src/tbox/platform/windows/addrinfo.c
index 75f10699f..13270b2c5 100644
--- a/core/src/tbox/src/tbox/platform/windows/addrinfo.c
+++ b/core/src/tbox/src/tbox/platform/windows/addrinfo.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file addrinfo.c
@@ -46,7 +46,7 @@ static __tb_inline__ tb_int_t tb_addrinfo_ai_family(tb_ipaddr_ref_t addr)
return AF_UNSPEC;
}
}
-tb_bool_t tb_addrinfo_addr_impl_1(tb_char_t const* name, tb_ipaddr_ref_t addr)
+static tb_bool_t tb_addrinfo_addr_impl_1(tb_char_t const* name, tb_ipaddr_ref_t addr)
{
// done
tb_bool_t ok = tb_false;
@@ -79,7 +79,7 @@ tb_bool_t tb_addrinfo_addr_impl_1(tb_char_t const* name, tb_ipaddr_ref_t addr)
// ok?
return ok;
}
-tb_bool_t tb_addrinfo_addr_impl_2(tb_char_t const* name, tb_ipaddr_ref_t addr)
+static tb_bool_t tb_addrinfo_addr_impl_2(tb_char_t const* name, tb_ipaddr_ref_t addr)
{
// not support ipv6
tb_assert_and_check_return_val(tb_ipaddr_family(addr) != TB_IPADDR_FAMILY_IPV6, tb_false);
@@ -104,7 +104,7 @@ tb_bool_t tb_addrinfo_addr_impl_2(tb_char_t const* name, tb_ipaddr_ref_t addr)
#endif
#ifdef TB_ADDRINFO_NAME_IMPL
-tb_char_t const* tb_addrinfo_name_impl_1(tb_ipaddr_ref_t addr, tb_char_t* name, tb_size_t maxn)
+static tb_char_t const* tb_addrinfo_name_impl_1(tb_ipaddr_ref_t addr, tb_char_t* name, tb_size_t maxn)
{
// load socket address
struct sockaddr_storage saddr;
@@ -114,7 +114,7 @@ tb_char_t const* tb_addrinfo_name_impl_1(tb_ipaddr_ref_t addr, tb_char_t* name,
// get host name from address
return !tb_ws2_32()->getnameinfo((struct sockaddr const*)&saddr, saddrlen, name, (DWORD)maxn, tb_null, 0, NI_NAMEREQD)? name : tb_null;
}
-tb_char_t const* tb_addrinfo_name_impl_2(tb_ipaddr_ref_t addr, tb_char_t* name, tb_size_t maxn)
+static tb_char_t const* tb_addrinfo_name_impl_2(tb_ipaddr_ref_t addr, tb_char_t* name, tb_size_t maxn)
{
// done
struct hostent* hostaddr = tb_null;
diff --git a/core/src/tbox/src/tbox/platform/windows/atomic.h b/core/src/tbox/src/tbox/platform/windows/atomic.h
index 64cb788d1..927f65415 100644
--- a/core/src/tbox/src/tbox/platform/windows/atomic.h
+++ b/core/src/tbox/src/tbox/platform/windows/atomic.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file atomic.h
diff --git a/core/src/tbox/src/tbox/platform/windows/atomic64.h b/core/src/tbox/src/tbox/platform/windows/atomic64.h
index 12c358517..fa260aec9 100644
--- a/core/src/tbox/src/tbox/platform/windows/atomic64.h
+++ b/core/src/tbox/src/tbox/platform/windows/atomic64.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file atomic64.h
diff --git a/core/src/tbox/src/tbox/platform/windows/backtrace.c b/core/src/tbox/src/tbox/platform/windows/backtrace.c
index 3b081d4d6..541ce4c42 100644
--- a/core/src/tbox/src/tbox/platform/windows/backtrace.c
+++ b/core/src/tbox/src/tbox/platform/windows/backtrace.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file backtrace.c
diff --git a/core/src/tbox/src/tbox/platform/windows/barrier.h b/core/src/tbox/src/tbox/platform/windows/barrier.h
index ec7167338..f6e8663f2 100644
--- a/core/src/tbox/src/tbox/platform/windows/barrier.h
+++ b/core/src/tbox/src/tbox/platform/windows/barrier.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file barrier.h
diff --git a/core/src/tbox/src/tbox/platform/windows/context.c b/core/src/tbox/src/tbox/platform/windows/context.c
index 71edebbe5..a8c9c9cd0 100644
--- a/core/src/tbox/src/tbox/platform/windows/context.c
+++ b/core/src/tbox/src/tbox/platform/windows/context.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file context.c
diff --git a/core/src/tbox/src/tbox/platform/windows/directory.c b/core/src/tbox/src/tbox/platform/windows/directory.c
index 3c7e96a0f..9643d760f 100644
--- a/core/src/tbox/src/tbox/platform/windows/directory.c
+++ b/core/src/tbox/src/tbox/platform/windows/directory.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file directory.c
diff --git a/core/src/tbox/src/tbox/platform/windows/dns.c b/core/src/tbox/src/tbox/platform/windows/dns.c
index 76dba97ad..c54878158 100644
--- a/core/src/tbox/src/tbox/platform/windows/dns.c
+++ b/core/src/tbox/src/tbox/platform/windows/dns.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file dns.c
diff --git a/core/src/tbox/src/tbox/platform/windows/dynamic.c b/core/src/tbox/src/tbox/platform/windows/dynamic.c
index e430e5f0d..02c81f7bd 100644
--- a/core/src/tbox/src/tbox/platform/windows/dynamic.c
+++ b/core/src/tbox/src/tbox/platform/windows/dynamic.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file dynamic.c
diff --git a/core/src/tbox/src/tbox/platform/windows/environment.c b/core/src/tbox/src/tbox/platform/windows/environment.c
index 29f3327bf..4993d495c 100644
--- a/core/src/tbox/src/tbox/platform/windows/environment.c
+++ b/core/src/tbox/src/tbox/platform/windows/environment.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file environment.c
diff --git a/core/src/tbox/src/tbox/platform/windows/event.c b/core/src/tbox/src/tbox/platform/windows/event.c
index 4d63968d5..fd8318f59 100644
--- a/core/src/tbox/src/tbox/platform/windows/event.c
+++ b/core/src/tbox/src/tbox/platform/windows/event.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file event.c
diff --git a/core/src/tbox/src/tbox/platform/windows/exception.c b/core/src/tbox/src/tbox/platform/windows/exception.c
index 2a73cf5f0..5ebd81197 100644
--- a/core/src/tbox/src/tbox/platform/windows/exception.c
+++ b/core/src/tbox/src/tbox/platform/windows/exception.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file exception.c
diff --git a/core/src/tbox/src/tbox/platform/windows/exception.h b/core/src/tbox/src/tbox/platform/windows/exception.h
index 397193901..789228ae1 100644
--- a/core/src/tbox/src/tbox/platform/windows/exception.h
+++ b/core/src/tbox/src/tbox/platform/windows/exception.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file exception.h
diff --git a/core/src/tbox/src/tbox/platform/windows/file.c b/core/src/tbox/src/tbox/platform/windows/file.c
index 82e7e6db8..34792aa31 100644
--- a/core/src/tbox/src/tbox/platform/windows/file.c
+++ b/core/src/tbox/src/tbox/platform/windows/file.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2018, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file file.c
diff --git a/core/src/tbox/src/tbox/platform/windows/hostname.c b/core/src/tbox/src/tbox/platform/windows/hostname.c
index b01864acf..ca88a6d3b 100644
--- a/core/src/tbox/src/tbox/platform/windows/hostname.c
+++ b/core/src/tbox/src/tbox/platform/windows/hostname.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file hostname.c
diff --git a/core/src/tbox/src/tbox/platform/windows/ifaddrs.c b/core/src/tbox/src/tbox/platform/windows/ifaddrs.c
index 68a8ca1f0..0001a9446 100644
--- a/core/src/tbox/src/tbox/platform/windows/ifaddrs.c
+++ b/core/src/tbox/src/tbox/platform/windows/ifaddrs.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ifaddrs.c
@@ -37,12 +37,12 @@
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)
+ tb_ifaddrs_interface_ref_t iface = (tb_ifaddrs_interface_ref_t)buff;
+ if (iface)
{
// exit the interface name
- if (interface->name) tb_free(interface->name);
- interface->name = tb_null;
+ if (iface->name) tb_free(iface->name);
+ iface->name = tb_null;
}
}
static tb_void_t tb_ifaddrs_interface_load4(tb_list_ref_t interfaces)
@@ -83,26 +83,26 @@ static tb_void_t tb_ifaddrs_interface_load4(tb_list_ref_t interfaces)
/* 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, adapter->AdapterName);
- if (!interface) interface = &interface_new;
+ tb_ifaddrs_interface_t iface_new = {0};
+ tb_ifaddrs_interface_ref_t iface = tb_ifaddrs_interface_find((tb_iterator_ref_t)interfaces, adapter->AdapterName);
+ if (!iface) iface = &iface_new;
// check
- tb_assert(interface == &interface_new || interface->name);
+ tb_assert(iface == &iface_new || iface->name);
// save flags
- if (adapter->Type == MIB_IF_TYPE_LOOPBACK) interface->flags |= TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK;
+ if (adapter->Type == MIB_IF_TYPE_LOOPBACK) iface->flags |= TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK;
// save hwaddr
- if (adapter->AddressLength == sizeof(interface->hwaddr.u8))
+ if (adapter->AddressLength == sizeof(iface->hwaddr.u8))
{
- interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR;
- tb_memcpy(interface->hwaddr.u8, adapter->Address, sizeof(interface->hwaddr.u8));
+ iface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR;
+ tb_memcpy(iface->hwaddr.u8, adapter->Address, sizeof(iface->hwaddr.u8));
}
// save ipaddrs
PIP_ADDR_STRING ipAddress = &adapter->IpAddressList;
- while (ipAddress && (interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR) != TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR)
+ while (ipAddress && (iface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR) != TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR)
{
// done
tb_ipaddr_t ipaddr;
@@ -111,13 +111,13 @@ static tb_void_t tb_ifaddrs_interface_load4(tb_list_ref_t interfaces)
{
if (ipaddr.family == TB_IPADDR_FAMILY_IPV4)
{
- interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR4;
- interface->ipaddr4 = ipaddr.u.ipv4;
+ iface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR4;
+ iface->ipaddr4 = ipaddr.u.ipv4;
}
else if (ipaddr.family == TB_IPADDR_FAMILY_IPV6)
{
- interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR6;
- interface->ipaddr6 = ipaddr.u.ipv6;
+ iface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR6;
+ iface->ipaddr6 = ipaddr.u.ipv6;
}
}
@@ -126,15 +126,15 @@ static tb_void_t tb_ifaddrs_interface_load4(tb_list_ref_t interfaces)
}
// new interface? save it
- if ( interface == &interface_new
- && interface->flags)
+ if ( iface == &iface_new
+ && iface->flags)
{
// save interface name
- interface->name = tb_strdup(adapter->AdapterName);
- tb_assert(interface->name);
+ iface->name = tb_strdup(adapter->AdapterName);
+ tb_assert(iface->name);
// save interface
- tb_list_insert_tail(interfaces, interface);
+ tb_list_insert_tail(interfaces, iface);
}
// the next adapter
@@ -185,26 +185,26 @@ static tb_void_t tb_ifaddrs_interface_load6(tb_list_ref_t interfaces)
/* 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, address->AdapterName);
- if (!interface) interface = &interface_new;
+ tb_ifaddrs_interface_t iface_new = {0};
+ tb_ifaddrs_interface_ref_t iface = tb_ifaddrs_interface_find((tb_iterator_ref_t)interfaces, address->AdapterName);
+ if (!iface) iface = &iface_new;
// check
- tb_assert(interface == &interface_new || interface->name);
+ tb_assert(iface == &iface_new || iface->name);
// save flags
- if (address->IfType == IF_TYPE_SOFTWARE_LOOPBACK) interface->flags |= TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK;
+ if (address->IfType == IF_TYPE_SOFTWARE_LOOPBACK) iface->flags |= TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK;
// save hwaddr
- if (address->PhysicalAddressLength == sizeof(interface->hwaddr.u8))
+ if (address->PhysicalAddressLength == sizeof(iface->hwaddr.u8))
{
- interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR;
- tb_memcpy(interface->hwaddr.u8, address->PhysicalAddress, sizeof(interface->hwaddr.u8));
+ iface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR;
+ tb_memcpy(iface->hwaddr.u8, address->PhysicalAddress, sizeof(iface->hwaddr.u8));
}
// save ipaddrs
PIP_ADAPTER_UNICAST_ADDRESS ipAddress = address->FirstUnicastAddress;
- while (ipAddress && (interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR) != TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR)
+ while (ipAddress && (iface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR) != TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR)
{
// done
tb_ipaddr_t ipaddr;
@@ -213,13 +213,13 @@ static tb_void_t tb_ifaddrs_interface_load6(tb_list_ref_t interfaces)
{
if (ipaddr.family == TB_IPADDR_FAMILY_IPV4)
{
- interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR4;
- interface->ipaddr4 = ipaddr.u.ipv4;
+ iface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR4;
+ iface->ipaddr4 = ipaddr.u.ipv4;
}
else if (ipaddr.family == TB_IPADDR_FAMILY_IPV6)
{
- interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR6;
- interface->ipaddr6 = ipaddr.u.ipv6;
+ iface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR6;
+ iface->ipaddr6 = ipaddr.u.ipv6;
}
}
@@ -228,15 +228,15 @@ static tb_void_t tb_ifaddrs_interface_load6(tb_list_ref_t interfaces)
}
// new interface? save it
- if ( interface == &interface_new
- && interface->flags)
+ if ( iface == &iface_new
+ && iface->flags)
{
// save interface name
- interface->name = tb_strdup(address->AdapterName);
- tb_assert(interface->name);
+ iface->name = tb_strdup(address->AdapterName);
+ tb_assert(iface->name);
// save interface
- tb_list_insert_tail(interfaces, interface);
+ tb_list_insert_tail(interfaces, iface);
}
// the next address
diff --git a/core/src/tbox/src/tbox/platform/windows/interface/dbghelp.c b/core/src/tbox/src/tbox/platform/windows/interface/dbghelp.c
index ea7410c55..1e8a75ff4 100644
--- a/core/src/tbox/src/tbox/platform/windows/interface/dbghelp.c
+++ b/core/src/tbox/src/tbox/platform/windows/interface/dbghelp.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file dbghelp.c
@@ -40,7 +40,7 @@ static tb_bool_t tb_dbghelp_instance_init(tb_handle_t instance, tb_cpointer_t pr
// the dbghelp module
HANDLE module = GetModuleHandleA("dbghelp.dll");
- if (!module) module = tb_dynamic_init("dbghelp.dll");
+ if (!module) module = (HANDLE)tb_dynamic_init("dbghelp.dll");
tb_check_return_val(module, tb_false);
// init interfaces
diff --git a/core/src/tbox/src/tbox/platform/windows/interface/dbghelp.h b/core/src/tbox/src/tbox/platform/windows/interface/dbghelp.h
index e8081a021..24afb22fb 100644
--- a/core/src/tbox/src/tbox/platform/windows/interface/dbghelp.h
+++ b/core/src/tbox/src/tbox/platform/windows/interface/dbghelp.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file dbghelp.h
diff --git a/core/src/tbox/src/tbox/platform/windows/interface/interface.c b/core/src/tbox/src/tbox/platform/windows/interface/interface.c
index a52199015..210603539 100644
--- a/core/src/tbox/src/tbox/platform/windows/interface/interface.c
+++ b/core/src/tbox/src/tbox/platform/windows/interface/interface.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file interface.c
diff --git a/core/src/tbox/src/tbox/platform/windows/interface/interface.h b/core/src/tbox/src/tbox/platform/windows/interface/interface.h
index 5a0b8a13d..72699fa2b 100644
--- a/core/src/tbox/src/tbox/platform/windows/interface/interface.h
+++ b/core/src/tbox/src/tbox/platform/windows/interface/interface.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file interface.h
diff --git a/core/src/tbox/src/tbox/platform/windows/interface/iphlpapi.c b/core/src/tbox/src/tbox/platform/windows/interface/iphlpapi.c
index a9c790494..763fb66cf 100644
--- a/core/src/tbox/src/tbox/platform/windows/interface/iphlpapi.c
+++ b/core/src/tbox/src/tbox/platform/windows/interface/iphlpapi.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file iphlpapi.c
@@ -40,7 +40,7 @@ static tb_bool_t tb_iphlpapi_instance_init(tb_handle_t instance, tb_cpointer_t p
// the iphlpapi module
HANDLE module = GetModuleHandleA("iphlpapi.dll");
- if (!module) module = tb_dynamic_init("iphlpapi.dll");
+ if (!module) module = (HANDLE)tb_dynamic_init("iphlpapi.dll");
tb_check_return_val(module, tb_false);
// init interfaces
diff --git a/core/src/tbox/src/tbox/platform/windows/interface/iphlpapi.h b/core/src/tbox/src/tbox/platform/windows/interface/iphlpapi.h
index 157e532f7..d3b99f8a8 100644
--- a/core/src/tbox/src/tbox/platform/windows/interface/iphlpapi.h
+++ b/core/src/tbox/src/tbox/platform/windows/interface/iphlpapi.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file iphlpapi.h
diff --git a/core/src/tbox/src/tbox/platform/windows/interface/kernel32.c b/core/src/tbox/src/tbox/platform/windows/interface/kernel32.c
index 26d257814..3f1ddad3c 100644
--- a/core/src/tbox/src/tbox/platform/windows/interface/kernel32.c
+++ b/core/src/tbox/src/tbox/platform/windows/interface/kernel32.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2018, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file kernel32.c
diff --git a/core/src/tbox/src/tbox/platform/windows/interface/kernel32.h b/core/src/tbox/src/tbox/platform/windows/interface/kernel32.h
index 873a67da6..909b39ea3 100644
--- a/core/src/tbox/src/tbox/platform/windows/interface/kernel32.h
+++ b/core/src/tbox/src/tbox/platform/windows/interface/kernel32.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2018, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file kernel32.h
@@ -31,6 +31,13 @@
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
+ * macros
+ */
+#ifndef FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
+# define FILE_SKIP_COMPLETION_PORT_ON_SUCCESS (0x1)
+#endif
+
+/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
__tb_extern_c_enter__
diff --git a/core/src/tbox/src/tbox/platform/windows/interface/mswsock.c b/core/src/tbox/src/tbox/platform/windows/interface/mswsock.c
index becdcacb9..16edbc088 100644
--- a/core/src/tbox/src/tbox/platform/windows/interface/mswsock.c
+++ b/core/src/tbox/src/tbox/platform/windows/interface/mswsock.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file mswsock.c
diff --git a/core/src/tbox/src/tbox/platform/windows/interface/mswsock.h b/core/src/tbox/src/tbox/platform/windows/interface/mswsock.h
index ebeafadf7..fbec6b9d5 100644
--- a/core/src/tbox/src/tbox/platform/windows/interface/mswsock.h
+++ b/core/src/tbox/src/tbox/platform/windows/interface/mswsock.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file mswsock.h
diff --git a/core/src/tbox/src/tbox/platform/windows/interface/ole32.c b/core/src/tbox/src/tbox/platform/windows/interface/ole32.c
index 2ecab8d31..6a48bc05d 100644
--- a/core/src/tbox/src/tbox/platform/windows/interface/ole32.c
+++ b/core/src/tbox/src/tbox/platform/windows/interface/ole32.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ole32.c
@@ -40,7 +40,7 @@ static tb_bool_t tb_ole32_instance_init(tb_handle_t instance, tb_cpointer_t priv
// the ole32 module
HANDLE module = GetModuleHandleA("ole32.dll");
- if (!module) module = tb_dynamic_init("ole32.dll");
+ if (!module) module = (HANDLE)tb_dynamic_init("ole32.dll");
tb_assert_and_check_return_val(module, tb_false);
// init interfaces
diff --git a/core/src/tbox/src/tbox/platform/windows/interface/ole32.h b/core/src/tbox/src/tbox/platform/windows/interface/ole32.h
index ca0f2ab3f..d44389d00 100644
--- a/core/src/tbox/src/tbox/platform/windows/interface/ole32.h
+++ b/core/src/tbox/src/tbox/platform/windows/interface/ole32.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ole32.h
diff --git a/core/src/tbox/src/tbox/platform/windows/interface/prefix.h b/core/src/tbox/src/tbox/platform/windows/interface/prefix.h
index 6786d4d65..48d36b4f6 100644
--- a/core/src/tbox/src/tbox/platform/windows/interface/prefix.h
+++ b/core/src/tbox/src/tbox/platform/windows/interface/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/platform/windows/interface/shell32.c b/core/src/tbox/src/tbox/platform/windows/interface/shell32.c
index 94ba587e2..e0ef67dd7 100644
--- a/core/src/tbox/src/tbox/platform/windows/interface/shell32.c
+++ b/core/src/tbox/src/tbox/platform/windows/interface/shell32.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file shell32.c
@@ -40,7 +40,7 @@ static tb_bool_t tb_shell32_instance_init(tb_handle_t instance, tb_cpointer_t pr
// the shell32 module
HANDLE module = GetModuleHandleA("shell32.dll");
- if (!module) module = tb_dynamic_init("shell32.dll");
+ if (!module) module = (HANDLE)tb_dynamic_init("shell32.dll");
tb_check_return_val(module, tb_false);
// init interfaces
diff --git a/core/src/tbox/src/tbox/platform/windows/interface/shell32.h b/core/src/tbox/src/tbox/platform/windows/interface/shell32.h
index ac0f58d5f..80922c692 100644
--- a/core/src/tbox/src/tbox/platform/windows/interface/shell32.h
+++ b/core/src/tbox/src/tbox/platform/windows/interface/shell32.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file shell32.h
diff --git a/core/src/tbox/src/tbox/platform/windows/interface/user32.c b/core/src/tbox/src/tbox/platform/windows/interface/user32.c
index 1a39cc65b..5f461d81a 100644
--- a/core/src/tbox/src/tbox/platform/windows/interface/user32.c
+++ b/core/src/tbox/src/tbox/platform/windows/interface/user32.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file user32.c
@@ -40,7 +40,7 @@ static tb_bool_t tb_user32_instance_init(tb_handle_t instance, tb_cpointer_t pri
// the user32 module
HANDLE module = GetModuleHandleA("user32.dll");
- if (!module) module = tb_dynamic_init("user32.dll");
+ if (!module) module = (HANDLE)tb_dynamic_init("user32.dll");
tb_assert_and_check_return_val(module, tb_false);
// init interfaces
diff --git a/core/src/tbox/src/tbox/platform/windows/interface/user32.h b/core/src/tbox/src/tbox/platform/windows/interface/user32.h
index bcb9c747c..223c84f06 100644
--- a/core/src/tbox/src/tbox/platform/windows/interface/user32.h
+++ b/core/src/tbox/src/tbox/platform/windows/interface/user32.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file user32.h
diff --git a/core/src/tbox/src/tbox/platform/windows/interface/ws2_32.c b/core/src/tbox/src/tbox/platform/windows/interface/ws2_32.c
index c262e3adb..f7eb8eb48 100644
--- a/core/src/tbox/src/tbox/platform/windows/interface/ws2_32.c
+++ b/core/src/tbox/src/tbox/platform/windows/interface/ws2_32.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2018, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ws2_32.c
@@ -32,7 +32,9 @@
/* //////////////////////////////////////////////////////////////////////////////////////
* pragma
*/
-#pragma comment(lib, "Ws2_32.lib")
+#ifndef TB_COMPILER_IS_MINGW
+# pragma comment(lib, "Ws2_32.lib")
+#endif
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
diff --git a/core/src/tbox/src/tbox/platform/windows/interface/ws2_32.h b/core/src/tbox/src/tbox/platform/windows/interface/ws2_32.h
index 7a2abfae5..de0655889 100644
--- a/core/src/tbox/src/tbox/platform/windows/interface/ws2_32.h
+++ b/core/src/tbox/src/tbox/platform/windows/interface/ws2_32.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2018, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ws2_32.h
diff --git a/core/src/tbox/src/tbox/platform/windows/iocp_object.c b/core/src/tbox/src/tbox/platform/windows/iocp_object.c
new file mode 100644
index 000000000..cfc6f5ff7
--- /dev/null
+++ b/core/src/tbox/src/tbox/platform/windows/iocp_object.c
@@ -0,0 +1,1350 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
+ *
+ * @author ruki
+ * @file iocp_object.c
+ * @ingroup platform
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * trace
+ */
+#define TB_TRACE_MODULE_NAME "iocp_object"
+#define TB_TRACE_MODULE_DEBUG (1)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "iocp_object.h"
+#include "interface/interface.h"
+#include "../thread_local.h"
+#include "../impl/sockdata.h"
+#include "../posix/sockaddr.h"
+#include "../../libc/libc.h"
+#include "../../container/container.h"
+#include "../../algorithm/algorithm.h"
+#ifdef TB_CONFIG_MODULE_HAVE_COROUTINE
+# include "../../coroutine/coroutine.h"
+# include "../../coroutine/impl/impl.h"
+#endif
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * macros
+ */
+
+// the iocp object cache maximum count
+#ifdef __tb_small__
+# define TB_IOCP_OBJECT_CACHE_MAXN (64)
+#else
+# define TB_IOCP_OBJECT_CACHE_MAXN (256)
+#endif
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * private declaration
+ */
+__tb_extern_c_enter__
+
+// bind iocp port for object
+tb_bool_t tb_poller_iocp_bind_object(tb_poller_ref_t poller, tb_iocp_object_ref_t object);
+
+__tb_extern_c_leave__
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * globals
+ */
+
+// the iocp object cache in the local thread (contains killing/killed object)
+static tb_thread_local_t g_iocp_object_cache_local = TB_THREAD_LOCAL_INIT;
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * private implementation
+ */
+static tb_bool_t tb_iocp_object_cache_clean(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value)
+{
+ // the cache
+ tb_list_entry_head_ref_t cache = (tb_list_entry_head_ref_t)value;
+ tb_assert(cache);
+
+ // the object
+ tb_iocp_object_ref_t object = (tb_iocp_object_ref_t)item;
+ tb_assert(object);
+
+ // remove it?
+ if (tb_list_entry_size(cache) > TB_IOCP_OBJECT_CACHE_MAXN && object->state != TB_STATE_KILLING)
+ {
+ // trace
+ tb_trace_d("clean %s object(%p) in cache(%lu)", tb_state_cstr(object->state), object->sock, tb_list_entry_size(cache));
+ return tb_true;
+ }
+ return tb_false;
+}
+static tb_void_t tb_iocp_object_cache_free(tb_cpointer_t priv)
+{
+ tb_list_entry_head_ref_t cache = (tb_list_entry_head_ref_t)priv;
+ if (cache)
+ {
+ // trace
+ tb_trace_d("exit iocp cache(%lu)", tb_list_entry_size(cache));
+
+ // exit all cached iocp objects
+ while (tb_list_entry_size(cache))
+ {
+ // get the next entry from head
+ tb_list_entry_ref_t entry = tb_list_entry_head(cache);
+ tb_assert(entry);
+
+ // remove it from the cache
+ tb_list_entry_remove_head(cache);
+
+ // exit this iocp object
+ tb_iocp_object_ref_t object = (tb_iocp_object_ref_t)tb_list_entry(cache, entry);
+ if (object)
+ {
+ // trace
+ tb_trace_d("exit %s object(%p) in cache", tb_state_cstr(object->state), object->sock);
+
+ // clear object first
+ tb_iocp_object_clear(object);
+
+ // free object
+ tb_free(object);
+ }
+ }
+
+ // exit cache entry
+ tb_list_entry_exit(cache);
+
+ // free cache
+ tb_free(cache);
+ }
+}
+static tb_list_entry_head_ref_t tb_iocp_object_cache()
+{
+ // init local iocp object cache local data
+ if (!tb_thread_local_init(&g_iocp_object_cache_local, tb_iocp_object_cache_free)) return tb_null;
+
+ // init local iocp object cache
+ tb_list_entry_head_ref_t cache = (tb_list_entry_head_ref_t)tb_thread_local_get(&g_iocp_object_cache_local);
+ if (!cache)
+ {
+ // make cache
+ cache = tb_malloc0_type(tb_list_entry_head_t);
+ if (cache)
+ {
+ // init cache entry
+ tb_list_entry_init(cache, tb_iocp_object_t, entry, tb_null);
+
+ // save cache to local thread
+ tb_thread_local_set(&g_iocp_object_cache_local, cache);
+ }
+ }
+ return cache;
+}
+static tb_iocp_object_ref_t tb_iocp_object_cache_alloc()
+{
+ // get cache
+ tb_list_entry_head_ref_t cache = tb_iocp_object_cache();
+ tb_assert_and_check_return_val(cache, tb_null);
+
+ // find a free iocp object
+ tb_iocp_object_ref_t result = tb_null;
+ tb_for_all_if (tb_iocp_object_ref_t, object, tb_list_entry_itor(cache), object)
+ {
+ if (object->state != TB_STATE_KILLING)
+ {
+ result = object;
+ break;
+ }
+ }
+
+ // found?
+ if (result)
+ {
+ // trace
+ tb_trace_d("alloc an new iocp object from cache(%lu)", tb_list_entry_size(cache));
+
+ // check
+ tb_assert(result->state == TB_STATE_OK);
+
+ // remove this object from the cache
+ tb_list_entry_remove(cache, &result->entry);
+
+ // init it
+ tb_memset(result, 0, sizeof(tb_iocp_object_t));
+ }
+ return result;
+}
+static __tb_inline__ tb_sockdata_ref_t tb_iocp_object_sockdata()
+{
+ // we only enable iocp in coroutine
+#if defined(TB_CONFIG_MODULE_HAVE_COROUTINE)
+ return (tb_co_scheduler_self() || tb_lo_scheduler_self_())? tb_sockdata() : tb_null;
+#else
+ return tb_null;
+#endif
+}
+static tb_bool_t tb_iocp_object_cancel(tb_iocp_object_ref_t object)
+{
+ // check
+ tb_assert_and_check_return_val(object && object->state == TB_STATE_WAITING && object->sock, tb_false);
+
+ // get the local socket data
+ tb_sockdata_ref_t sockdata = tb_iocp_object_sockdata();
+ tb_assert_and_check_return_val(sockdata, tb_false);
+
+ // get the iocp object cache
+ tb_list_entry_head_ref_t cache = tb_iocp_object_cache();
+ tb_assert_and_check_return_val(cache, tb_false);
+
+ // trace
+ tb_trace_d("sock(%p): cancel io ..", object->sock);
+
+ // cancel io
+ if (!CancelIo((HANDLE)(tb_size_t)tb_sock2fd(object->sock)))
+ {
+ // trace
+ tb_trace_e("sock(%p): cancel io failed(%d)!", object->sock, GetLastError());
+ return tb_false;
+ }
+
+ // move this object to the cache
+ object->state = TB_STATE_KILLING;
+ tb_list_entry_insert_tail(cache, &object->entry);
+
+ // remove this object from the local socket data
+ tb_sockdata_remove(sockdata, object->sock);
+
+ // trace
+ tb_trace_d("insert to the iocp object cache(%lu)", tb_list_entry_size(cache));
+
+ // ok
+ return tb_true;
+}
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * implementation
+ */
+tb_iocp_object_ref_t tb_iocp_object_get_or_new(tb_socket_ref_t sock)
+{
+ // check
+ tb_assert_and_check_return_val(sock, tb_null);
+
+ // get or new object
+ tb_iocp_object_ref_t object = tb_null;
+ do
+ {
+ // get the local socket data
+ tb_sockdata_ref_t sockdata = tb_iocp_object_sockdata();
+ tb_check_break(sockdata);
+
+ // attempt to get object first if exists
+ object = (tb_iocp_object_ref_t)tb_sockdata_get(sockdata, sock);
+
+ // new an object if not exists
+ if (!object)
+ {
+ // attempt to alloc object from the cache first
+ object = tb_iocp_object_cache_alloc();
+
+ // alloc object from the heap if no cache
+ if (!object) object = tb_malloc0_type(tb_iocp_object_t);
+ tb_assert_and_check_break(object);
+
+ // init object
+ object->sock = sock;
+ tb_iocp_object_clear(object);
+
+ // save object
+ tb_sockdata_insert(sockdata, sock, (tb_cpointer_t)object);
+ }
+
+ } while (0);
+
+ // done
+ return object;
+}
+tb_iocp_object_ref_t tb_iocp_object_get(tb_socket_ref_t sock)
+{
+ tb_sockdata_ref_t sockdata = tb_iocp_object_sockdata();
+ return sockdata? (tb_iocp_object_ref_t)tb_sockdata_get(sockdata, sock) : tb_null;
+}
+tb_void_t tb_iocp_object_remove(tb_socket_ref_t sock)
+{
+ // get the local socket data
+ tb_sockdata_ref_t sockdata = tb_iocp_object_sockdata();
+ tb_check_return(sockdata);
+
+ // get cache
+ tb_list_entry_head_ref_t cache = tb_iocp_object_cache();
+ tb_assert_and_check_return(cache);
+
+ // get iocp object
+ tb_iocp_object_ref_t object = (tb_iocp_object_ref_t)tb_sockdata_get(sockdata, sock);
+ if (object)
+ {
+ // trace
+ tb_trace_d("sock(%p): removing, state: %s", sock, tb_state_cstr(object->state));
+
+ // clean some objects in cache
+ tb_remove_if(tb_list_entry_itor(cache), tb_iocp_object_cache_clean, cache);
+
+ // no waiting io or cancel failed? remove and free this iocp object directly
+ if (object->state != TB_STATE_WAITING || !tb_iocp_object_cancel(object))
+ {
+ // trace
+ tb_trace_d("sock(%p): removed directly, state: %s", sock, tb_state_cstr(object->state));
+
+ // remove this object from the local socket data
+ tb_sockdata_remove(sockdata, sock);
+
+ // clear and free the object data
+ tb_iocp_object_clear(object);
+
+ // insert to iocp object cache
+ if (tb_list_entry_size(cache) < TB_IOCP_OBJECT_CACHE_MAXN)
+ tb_list_entry_insert_head(cache, &object->entry);
+ else tb_free(object);
+ }
+ }
+}
+tb_void_t tb_iocp_object_clear(tb_iocp_object_ref_t object)
+{
+ // check
+ tb_assert(object);
+
+ // free the private buffer for iocp
+ if (object->buffer)
+ {
+ tb_free(object->buffer);
+ object->buffer = tb_null;
+ }
+
+ // trace
+ tb_trace_d("sock(%p): clear %s ..", object->sock, tb_state_cstr(object->state));
+
+ // clear object code and state
+ object->code = TB_IOCP_OBJECT_CODE_NONE;
+ object->state = TB_STATE_OK;
+}
+tb_socket_ref_t tb_iocp_object_accept(tb_iocp_object_ref_t object, tb_ipaddr_ref_t addr)
+{
+ // check
+ tb_assert_and_check_return_val(object, tb_null);
+
+ // always be accept, need not clear object each time
+ tb_assert(object->code == TB_IOCP_OBJECT_CODE_NONE || object->code == TB_IOCP_OBJECT_CODE_ACPT);
+
+ // attempt to get the result if be finished
+ if (object->code == TB_IOCP_OBJECT_CODE_ACPT)
+ {
+ if (object->state == TB_STATE_FINISHED)
+ {
+ // trace
+ tb_trace_d("accept(%p): state: %s, result: %p", object->sock, tb_state_cstr(object->state), object->u.acpt.result);
+
+ // get result
+ object->state = TB_STATE_OK;
+ if (addr) tb_ipaddr_copy(addr, &object->u.acpt.addr);
+ return object->u.acpt.result;
+ }
+ // waiting timeout before?
+ else if (object->state == TB_STATE_WAITING)
+ {
+ // trace
+ tb_trace_d("accept(%p): state: %s, continue ..", object->sock, tb_state_cstr(object->state));
+ return tb_null;
+ }
+ }
+
+ // trace
+ tb_trace_d("accept(%p): state: %s ..", object->sock, tb_state_cstr(object->state));
+
+ // check state
+ tb_assert_and_check_return_val(object->state != TB_STATE_WAITING, tb_null);
+
+ // bind iocp object first
+ if (!tb_poller_iocp_bind_object(tb_null, object)) return tb_null;
+
+ // post a accept event
+ tb_bool_t ok = tb_false;
+ tb_bool_t init_ok = tb_false;
+ tb_bool_t AcceptEx_ok = tb_false;
+ do
+ {
+ // init olap
+ tb_memset(&object->olap, 0, sizeof(OVERLAPPED));
+
+ // make address buffer
+ if (!object->buffer) object->buffer = tb_malloc0(((sizeof(struct sockaddr_storage)) << 1));
+ tb_assert_and_check_break(object->buffer);
+
+ // get bound address family
+ struct sockaddr_storage bound_addr;
+ socklen_t len = sizeof(bound_addr);
+ tb_size_t family = TB_IPADDR_FAMILY_IPV4;
+ if (getsockname((SOCKET)tb_sock2fd(object->sock), (struct sockaddr *)&bound_addr, &len) != -1 && bound_addr.ss_family == AF_INET6)
+ family = TB_IPADDR_FAMILY_IPV6;
+
+ // make accept socket
+ object->u.acpt.result = tb_socket_init(TB_SOCKET_TYPE_TCP, family);
+ tb_assert_and_check_break(object->u.acpt.result);
+ init_ok = tb_true;
+
+ // the client fd
+ SOCKET clientfd = tb_sock2fd(object->u.acpt.result);
+
+ /* do AcceptEx
+ *
+ * @note this socket have been bound to local address in tb_socket_connect()
+ */
+ DWORD real = 0;
+ AcceptEx_ok = tb_mswsock()->AcceptEx( (SOCKET)tb_sock2fd(object->sock)
+ , clientfd
+ , (tb_byte_t*)object->buffer
+ , 0
+ , sizeof(struct sockaddr_storage)
+ , sizeof(struct sockaddr_storage)
+ , &real
+ , (LPOVERLAPPED)&object->olap)? tb_true : tb_false;
+
+ // trace
+ tb_trace_d("accept(%p): AcceptEx: %d, lasterror: %d", object->sock, AcceptEx_ok, tb_ws2_32()->WSAGetLastError());
+ tb_check_break(AcceptEx_ok);
+
+ // update the accept context, otherwise shutdown and getsockname will be failed
+ SOCKET acceptfd = (SOCKET)tb_sock2fd(object->sock);
+ tb_ws2_32()->setsockopt(clientfd, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (tb_char_t*)&acceptfd, sizeof(acceptfd));
+
+ // non-block
+ ULONG nb = 1;
+ tb_ws2_32()->ioctlsocket(clientfd, FIONBIO, &nb);
+
+ /* disable the nagle's algorithm to fix 40ms ack delay in some case (.e.g send-send-40ms-recv)
+ *
+ * 40ms is the tcp ack delay, which indicates that you are likely
+ * encountering a bad interaction between delayed acks and the nagle's algorithm.
+ *
+ * TCP_NODELAY simply disables the nagle's algorithm and is a one-time setting on the socket,
+ * whereas the other two must be set at the appropriate times during the life of the connection
+ * and can therefore be trickier to use.
+ *
+ * so we set TCP_NODELAY to reduce response delay for the accepted socket in the server by default
+ */
+ tb_int_t enable = 1;
+ tb_ws2_32()->setsockopt(clientfd, IPPROTO_TCP, TCP_NODELAY, (tb_char_t*)&enable, sizeof(enable));
+
+ // skip the completion notification on success
+ if (tb_kernel32_has_SetFileCompletionNotificationModes())
+ {
+ if (tb_kernel32()->SetFileCompletionNotificationModes((HANDLE)clientfd, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS))
+ {
+ tb_iocp_object_ref_t client_object = tb_iocp_object_get_or_new(object->u.acpt.result);
+ if (client_object)
+ client_object->skip_cpos = 1;
+ }
+ }
+
+ // get accept socket addresses
+ INT server_size = 0;
+ INT client_size = 0;
+ struct sockaddr_storage* server_addr = tb_null;
+ struct sockaddr_storage* client_addr = tb_null;
+ if (addr && tb_mswsock()->GetAcceptExSockaddrs)
+ {
+ // check
+ tb_assert(object->buffer);
+
+ // get server and client addresses
+ tb_mswsock()->GetAcceptExSockaddrs( (tb_byte_t*)object->buffer
+ , 0
+ , sizeof(struct sockaddr_storage)
+ , sizeof(struct sockaddr_storage)
+ , (LPSOCKADDR*)&server_addr
+ , &server_size
+ , (LPSOCKADDR*)&client_addr
+ , &client_size);
+
+ // exists client address?
+ if (client_addr)
+ {
+ // save address
+ tb_sockaddr_save(addr, client_addr);
+
+ // trace
+ tb_trace_d("accept(%p): client address: %{ipaddr}", object->sock, addr);
+ }
+ }
+
+ // trace
+ tb_trace_d("accept(%p): result: %p, state: finished directly", object->sock, object->u.acpt.result);
+
+ // ok
+ ok = tb_true;
+
+ } while (0);
+
+ // AcceptEx failed?
+ if (!ok)
+ {
+ // pending? continue it
+ if (init_ok && WSA_IO_PENDING == tb_ws2_32()->WSAGetLastError())
+ {
+ object->code = TB_IOCP_OBJECT_CODE_ACPT;
+ object->state = TB_STATE_WAITING;
+ }
+ // failed?
+ else
+ {
+ // free result socket
+ if (object->u.acpt.result) tb_socket_exit(object->u.acpt.result);
+ object->u.acpt.result = tb_null;
+ }
+ }
+
+ // ok?
+ return ok? object->u.acpt.result : tb_null;
+}
+tb_long_t tb_iocp_object_connect(tb_iocp_object_ref_t object, tb_ipaddr_ref_t addr)
+{
+ // check
+ tb_assert_and_check_return_val(object && addr, -1);
+
+ // attempt to get the result if be finished
+ if (object->code == TB_IOCP_OBJECT_CODE_CONN)
+ {
+ if (object->state == TB_STATE_FINISHED)
+ {
+ /* clear the previous object data first
+ *
+ * @note conn.addr and conn.result cannot be cleared
+ */
+ tb_iocp_object_clear(object);
+ if (tb_ipaddr_is_equal(&object->u.conn.addr, addr))
+ {
+ // skip the completion notification on success
+ if (tb_kernel32_has_SetFileCompletionNotificationModes())
+ {
+ if (tb_kernel32()->SetFileCompletionNotificationModes((HANDLE)(SOCKET)tb_sock2fd(object->sock), FILE_SKIP_COMPLETION_PORT_ON_SUCCESS))
+ object->skip_cpos = 1;
+ }
+
+ // trace
+ tb_trace_d("connect(%p): %{ipaddr}, skip: %d, state: %s, result: %ld", object->sock, addr, object->skip_cpos, tb_state_cstr(object->state), object->u.conn.result);
+
+ // ok
+ return object->u.conn.result;
+ }
+ }
+ // waiting timeout before?
+ else if (object->state == TB_STATE_WAITING && tb_ipaddr_is_equal(&object->u.conn.addr, addr))
+ {
+ // trace
+ tb_trace_d("connect(%p, %{ipaddr}): %s, continue ..", object->sock, addr, tb_state_cstr(object->state));
+ return 0;
+ }
+ }
+
+ // trace
+ tb_trace_d("connect(%p, %{ipaddr}): %s ..", object->sock, addr, tb_state_cstr(object->state));
+
+ // check state
+ tb_assert_and_check_return_val(object->state != TB_STATE_WAITING, -1);
+
+ // bind iocp object first
+ if (!tb_poller_iocp_bind_object(tb_null, object)) return -1;
+
+ // post a connection event
+ tb_long_t ok = -1;
+ tb_bool_t init_ok = tb_false;
+ tb_bool_t ConnectEx_ok = tb_false;
+ do
+ {
+ // init olap
+ tb_memset(&object->olap, 0, sizeof(OVERLAPPED));
+
+ // load client address
+ tb_size_t caddr_size = 0;
+ struct sockaddr_storage caddr_data = {0};
+ if (!(caddr_size = tb_sockaddr_load(&caddr_data, addr))) break;
+
+ // load local address
+ tb_size_t laddr_size = 0;
+ struct sockaddr_storage laddr_data = {0};
+ tb_ipaddr_t laddr;
+ if (!tb_ipaddr_set(&laddr, tb_null, 0, (tb_uint8_t)tb_ipaddr_family(addr))) break;
+ if (!(laddr_size = tb_sockaddr_load(&laddr_data, &laddr))) break;
+
+ // bind it first for ConnectEx
+ if (SOCKET_ERROR == tb_ws2_32()->bind((SOCKET)tb_sock2fd(object->sock), (LPSOCKADDR)&laddr_data, (tb_int_t)laddr_size))
+ {
+ // trace
+ tb_trace_e("connect(%p, %{ipaddr}): bind failed, error: %u", object->sock, addr, GetLastError());
+ break;
+ }
+ init_ok = tb_true;
+
+ /* do ConnectEx
+ *
+ * @note this socket have been bound to local address in tb_socket_connect()
+ */
+ DWORD real = 0;
+ ConnectEx_ok = tb_mswsock()->ConnectEx( (SOCKET)tb_sock2fd(object->sock)
+ , (struct sockaddr const*)&caddr_data
+ , (tb_int_t)caddr_size
+ , tb_null
+ , 0
+ , &real
+ , (LPOVERLAPPED)&object->olap)? tb_true : tb_false;
+
+ // trace
+ tb_trace_d("connect(%p): ConnectEx: %d, lasterror: %d", object->sock, ConnectEx_ok, tb_ws2_32()->WSAGetLastError());
+ tb_check_break(ConnectEx_ok);
+
+ // skip the completion notification on success
+ if (tb_kernel32_has_SetFileCompletionNotificationModes())
+ {
+ if (tb_kernel32()->SetFileCompletionNotificationModes((HANDLE)(SOCKET)tb_sock2fd(object->sock), FILE_SKIP_COMPLETION_PORT_ON_SUCCESS))
+ object->skip_cpos = 1;
+ }
+
+ // trace
+ tb_trace_d("connect(%p): %{ipaddr}, skip: %d, state: finished directly", object->sock, addr, object->skip_cpos);
+
+ // ok
+ ok = 1;
+
+ } while (0);
+
+ // ConnectEx failed?
+ if (ok < 0)
+ {
+ // pending? continue to wait it
+ if (init_ok && WSA_IO_PENDING == tb_ws2_32()->WSAGetLastError())
+ {
+ ok = 0;
+ object->code = TB_IOCP_OBJECT_CODE_CONN;
+ object->state = TB_STATE_WAITING;
+ object->u.conn.addr = *addr;
+ object->u.conn.result = -1;
+ }
+ // already connected?
+ else if (tb_ws2_32()->WSAGetLastError() == WSAEISCONN) ok = 1;
+ }
+
+ // failed?
+ if (ok < 0) tb_iocp_object_clear(object);
+ return ok;
+}
+tb_long_t tb_iocp_object_recv(tb_iocp_object_ref_t object, tb_byte_t* data, tb_size_t size)
+{
+ // check
+ tb_assert_and_check_return_val(object && data && size, -1);
+
+ // continue to the previous operation
+ if (object->code == TB_IOCP_OBJECT_CODE_RECV)
+ {
+ // attempt to get the result if be finished
+ if (object->state == TB_STATE_FINISHED)
+ {
+ // trace
+ tb_trace_d("recv(%p): state: %s, result: %ld", object->sock, tb_state_cstr(object->state), object->u.recv.result);
+
+ // clear the previous object data first, but the result cannot be cleared
+ tb_iocp_object_clear(object);
+ return object->u.recv.result;
+ }
+ else if (object->state == TB_STATE_WAITING)
+ {
+ // check
+ tb_assert_and_check_return_val(object->u.recv.data == data, -1);
+
+ // trace
+ tb_trace_d("recv(%p): state: %s, continue ..", object->sock, tb_state_cstr(object->state));
+ return 0;
+ }
+ }
+
+ // trace
+ tb_trace_d("recv(%p, %lu): %s ..", object->sock, size, tb_state_cstr(object->state));
+
+ // check state
+ tb_assert_and_check_return_val(object->state != TB_STATE_WAITING, -1);
+
+ // bind iocp object first
+ if (!tb_poller_iocp_bind_object(tb_null, object)) return -1;
+
+ // attach buffer data
+ object->u.recv.data = data;
+ object->u.recv.size = (tb_iovec_size_t)size;
+
+ // attempt to recv data directly
+ DWORD flag = 0;
+ DWORD real = 0;
+ tb_long_t ok = tb_ws2_32()->WSARecv((SOCKET)tb_sock2fd(object->sock), (WSABUF*)&object->u.recv, 1, &real, &flag, (LPOVERLAPPED)&object->olap, tb_null);
+
+ // finished and skip iocp notification? return it directly
+ if (!ok && object->skip_cpos)
+ {
+ // trace
+ tb_trace_d("recv(%p): WSARecv: %u bytes, skip: %d, state: finished directly", object->sock, real, object->skip_cpos);
+ return (tb_long_t)(real > 0? real : (tb_long_t)-1);
+ }
+
+ // trace
+ tb_trace_d("recv(%p): WSARecv: %ld, skip: %d, lasterror: %d", object->sock, ok, object->skip_cpos, tb_ws2_32()->WSAGetLastError());
+
+ // ok or pending? continue to wait it
+ if (!ok || ((ok == SOCKET_ERROR) && (WSA_IO_PENDING == tb_ws2_32()->WSAGetLastError())))
+ {
+ object->code = TB_IOCP_OBJECT_CODE_RECV;
+ object->state = TB_STATE_WAITING;
+ return 0;
+ }
+
+ // failed
+ tb_iocp_object_clear(object);
+ return -1;
+}
+tb_long_t tb_iocp_object_send(tb_iocp_object_ref_t object, tb_byte_t const* data, tb_size_t size)
+{
+ // check
+ tb_assert_and_check_return_val(object && data, -1);
+
+ // attempt to get the result if be finished
+ if (object->code == TB_IOCP_OBJECT_CODE_SEND)
+ {
+ if (object->state == TB_STATE_FINISHED)
+ {
+ // trace
+ tb_trace_d("send(%p): state: %s, result: %ld", object->sock, tb_state_cstr(object->state), object->u.send.result);
+
+ // clear the previous object data first, but the result cannot be cleared
+ tb_iocp_object_clear(object);
+ return object->u.send.result;
+ }
+ // waiting timeout before?
+ else if (object->state == TB_STATE_WAITING)
+ {
+ // check
+ tb_assert_and_check_return_val(object->u.send.data == data, -1);
+
+ // trace
+ tb_trace_d("send(%p): state: %s, continue ..", object->sock, tb_state_cstr(object->state));
+ return 0;
+ }
+ }
+
+ // trace
+ tb_trace_d("send(%p, %lu): %s ..", object->sock, size, tb_state_cstr(object->state));
+
+ // check state
+ tb_assert_and_check_return_val(object->state != TB_STATE_WAITING, -1);
+
+ // bind iocp object first
+ if (!tb_poller_iocp_bind_object(tb_null, object)) return -1;
+
+ // attempt buffer data
+ object->u.send.data = data;
+ object->u.send.size = (tb_iovec_size_t)size;
+
+ // attempt to send data directly
+ DWORD real = 0;
+ tb_long_t ok = tb_ws2_32()->WSASend((SOCKET)tb_sock2fd(object->sock), (WSABUF*)&object->u.send, 1, &real, 0, (LPOVERLAPPED)&object->olap, tb_null);
+
+ // finished and skip iocp notification? return it directly
+ if (!ok && object->skip_cpos)
+ {
+ // trace
+ tb_trace_d("send(%p): WSASend: %u bytes, skip: %d, state: finished directly", object->sock, real, object->skip_cpos);
+ return (tb_long_t)(real > 0? real : (tb_long_t)-1);
+ }
+
+ // trace
+ tb_trace_d("send(%p): WSASend: %ld, skip: %d, lasterror: %d", object->sock, ok, object->skip_cpos, tb_ws2_32()->WSAGetLastError());
+
+ // ok or pending? continue to wait it
+ if (!ok || ((ok == SOCKET_ERROR) && (WSA_IO_PENDING == tb_ws2_32()->WSAGetLastError())))
+ {
+ object->code = TB_IOCP_OBJECT_CODE_SEND;
+ object->state = TB_STATE_WAITING;
+ return 0;
+ }
+
+ // failed
+ tb_iocp_object_clear(object);
+ return -1;
+}
+tb_long_t tb_iocp_object_urecv(tb_iocp_object_ref_t object, tb_ipaddr_ref_t addr, tb_byte_t* data, tb_size_t size)
+{
+ // check
+ tb_assert_and_check_return_val(object && data && size, -1);
+
+ // continue to the previous operation
+ if (object->code == TB_IOCP_OBJECT_CODE_URECV)
+ {
+ // attempt to get the result if be finished
+ if (object->state == TB_STATE_FINISHED)
+ {
+ // trace
+ tb_trace_d("urecv(%p): state: %s, result: %ld", object->sock, tb_state_cstr(object->state), object->u.urecv.result);
+
+ // clear the previous object data first, but the result cannot be cleared
+ tb_iocp_object_clear(object);
+ if (addr) tb_ipaddr_copy(addr, &object->u.urecv.addr);
+ return object->u.urecv.result;
+ }
+ // waiting timeout before?
+ else if (object->state == TB_STATE_WAITING)
+ {
+ // check
+ tb_assert_and_check_return_val(object->u.urecv.data == data, -1);
+
+ // trace
+ tb_trace_d("urecv(%p): state: %s, continue ..", object->sock, tb_state_cstr(object->state));
+ return 0;
+ }
+ }
+
+ // trace
+ tb_trace_d("urecv(%p, %lu): %s ..", object->sock, size, tb_state_cstr(object->state));
+
+ // check state
+ tb_assert_and_check_return_val(object->state != TB_STATE_WAITING, -1);
+
+ // bind iocp object first
+ if (!tb_poller_iocp_bind_object(tb_null, object)) return -1;
+
+ // attach buffer data
+ object->u.urecv.data = data;
+ object->u.urecv.size = (tb_iovec_size_t)size;
+
+ // make buffer for address, size and flags
+ if (!object->buffer) object->buffer = tb_malloc0(sizeof(struct sockaddr_storage) + sizeof(tb_int_t) + sizeof(DWORD));
+ tb_assert_and_check_return_val(object->buffer, -1);
+
+ // init size
+ tb_int_t* psize = (tb_int_t*)((tb_byte_t*)object->buffer + sizeof(struct sockaddr_storage));
+ *psize = sizeof(struct sockaddr_storage);
+
+ // init flag
+ DWORD* pflag = (DWORD*)((tb_byte_t*)object->buffer + sizeof(struct sockaddr_storage) + sizeof(tb_int_t));
+ *pflag = 0;
+
+ /* post to recv event
+ *
+ * It's not safe to skip completion notifications for UDP:
+ * https://blogs.technet.com/b/winserverperformance/archive/2008/06/26/designing-applications-for-high-performance-part-iii.aspx
+ */
+ tb_long_t ok = tb_ws2_32()->WSARecvFrom((SOCKET)tb_sock2fd(object->sock), (WSABUF*)&object->u.urecv, 1, tb_null, pflag, (struct sockaddr*)object->buffer, psize, (LPOVERLAPPED)&object->olap, tb_null);
+
+ // trace
+ tb_trace_d("urecv(%p): WSARecvFrom: %ld, lasterror: %d", object->sock, ok, tb_ws2_32()->WSAGetLastError());
+
+ // ok or pending? continue it
+ if (!ok || ((ok == SOCKET_ERROR) && (WSA_IO_PENDING == tb_ws2_32()->WSAGetLastError())))
+ {
+ object->code = TB_IOCP_OBJECT_CODE_URECV;
+ object->state = TB_STATE_WAITING;
+ return 0;
+ }
+
+ // failed
+ tb_iocp_object_clear(object);
+ return -1;
+}
+tb_long_t tb_iocp_object_usend(tb_iocp_object_ref_t object, tb_ipaddr_ref_t addr, tb_byte_t const* data, tb_size_t size)
+{
+ // check
+ tb_assert_and_check_return_val(object && addr && data, -1);
+
+ // attempt to get the result if be finished
+ if (object->code == TB_IOCP_OBJECT_CODE_USEND)
+ {
+ if (object->state == TB_STATE_FINISHED)
+ {
+ // trace
+ tb_trace_d("usend(%p, %{ipaddr}): state: %s, result: %ld", object->sock, addr, tb_state_cstr(object->state), object->u.usend.result);
+
+ // clear the previous object data first, but the result cannot be cleared
+ tb_iocp_object_clear(object);
+ return object->u.usend.result;
+ }
+ // waiting timeout before?
+ else if (object->state == TB_STATE_WAITING && tb_ipaddr_is_equal(&object->u.usend.addr, addr))
+ {
+ // check
+ tb_assert_and_check_return_val(object->u.usend.data == data, -1);
+
+ // trace
+ tb_trace_d("usend(%p, %{ipaddr}): state: %s, continue ..", object->sock, addr, tb_state_cstr(object->state));
+ return 0;
+ }
+ }
+
+ // trace
+ tb_trace_d("usend(%p, %{ipaddr}, %lu): %s ..", object->sock, addr, size, tb_state_cstr(object->state));
+
+ // has waiting io?
+ if (object->state == TB_STATE_WAITING)
+ {
+ // get bound iocp port and user private data
+ HANDLE port = object->port;
+ tb_cpointer_t priv = object->priv;
+
+ // cancel the previous io (urecv) first
+ if (!tb_iocp_object_cancel(object)) return -1;
+
+ // create a new iocp object
+ object = tb_iocp_object_get_or_new(object->sock);
+ tb_assert_and_check_return_val(object, -1);
+
+ // restore the previous bound iocp port and user private data
+ object->port = port;
+ object->priv = priv;
+ }
+
+ // check state
+ tb_assert_and_check_return_val(object->state != TB_STATE_WAITING, -1);
+
+ // bind iocp object first
+ if (!tb_poller_iocp_bind_object(tb_null, object)) return -1;
+
+ // attach buffer data and address
+ object->u.usend.addr = *addr;
+ object->u.usend.data = data;
+ object->u.usend.size = (tb_iovec_size_t)size;
+
+ // load address
+ tb_size_t n = 0;
+ struct sockaddr_storage d = {0};
+ if (!(n = tb_sockaddr_load(&d, &object->u.usend.addr))) return tb_false;
+
+ /* attempt to send data directly
+ *
+ * It's not safe to skip completion notifications for UDP:
+ * https://blogs.technet.com/b/winserverperformance/archive/2008/06/26/designing-applications-for-high-performance-part-iii.aspx
+ *
+ * So we attempt to send data firstly without overlapped.
+ */
+ DWORD real = 0;
+ tb_long_t ok = tb_ws2_32()->WSASendTo((SOCKET)tb_sock2fd(object->sock), (WSABUF*)&object->u.usend, 1, &real, 0, (struct sockaddr*)&d, (tb_int_t)n, tb_null, tb_null);
+ if (!ok && real)
+ {
+ // trace
+ tb_trace_d("usend(%p, %{ipaddr}): WSASendTo: %u bytes, state: finished directly", object->sock, addr, real);
+ return (tb_long_t)real;
+ }
+
+ // post a send event
+ ok = tb_ws2_32()->WSASendTo((SOCKET)tb_sock2fd(object->sock), (WSABUF*)&object->u.usend, 1, tb_null, 0, (struct sockaddr*)&d, (tb_int_t)n, (LPOVERLAPPED)&object->olap, tb_null);
+
+ // trace
+ tb_trace_d("usend(%p, %{ipaddr}): WSASendTo: %ld, lasterror: %d", object->sock, addr, ok, tb_ws2_32()->WSAGetLastError());
+
+ // ok or pending? continue it
+ if (!ok || ((ok == SOCKET_ERROR) && (WSA_IO_PENDING == tb_ws2_32()->WSAGetLastError())))
+ {
+ object->code = TB_IOCP_OBJECT_CODE_USEND;
+ object->state = TB_STATE_WAITING;
+ return 0;
+ }
+
+ // failed
+ tb_iocp_object_clear(object);
+ return -1;
+}
+tb_hong_t tb_iocp_object_sendf(tb_iocp_object_ref_t object, tb_file_ref_t file, tb_hize_t offset, tb_hize_t size)
+{
+ // check
+ tb_assert_and_check_return_val(object && file, -1);
+
+ // attempt to get the result if be finished
+ if (object->code == TB_IOCP_OBJECT_CODE_SENDF)
+ {
+ if (object->state == TB_STATE_FINISHED)
+ {
+ // trace
+ tb_trace_d("sendfile(%p): state: %s, result: %ld", object->sock, tb_state_cstr(object->state), object->u.sendf.result);
+
+ // clear the previous object data first, but the result cannot be cleared
+ tb_iocp_object_clear(object);
+ return object->u.sendf.result;
+ }
+ // waiting timeout before?
+ else if (object->state == TB_STATE_WAITING)
+ {
+ // check
+ tb_assert_and_check_return_val(object->u.sendf.file == file, -1);
+ tb_assert_and_check_return_val(object->u.sendf.offset == offset, -1);
+
+ // trace
+ tb_trace_d("sendfile(%p): state: %s, continue ..", object->sock, tb_state_cstr(object->state));
+ return 0;
+ }
+ }
+
+ // trace
+ tb_trace_d("sendfile(%p, %llu at %llu): %s ..", object->sock, size, offset, tb_state_cstr(object->state));
+
+ // check state
+ tb_assert_and_check_return_val(object->state != TB_STATE_WAITING, -1);
+
+ // bind iocp object first
+ if (!tb_poller_iocp_bind_object(tb_null, object)) return -1;
+
+ // do send file
+ object->olap.Offset = (DWORD)offset;
+ object->olap.OffsetHigh = (DWORD)(offset >> 32);
+ BOOL ok = tb_mswsock()->TransmitFile((SOCKET)tb_sock2fd(object->sock), (HANDLE)file, (DWORD)size, (1 << 16), (LPOVERLAPPED)&object->olap, tb_null, 0);
+
+ // trace
+ tb_trace_d("sendfile(%p): TransmitFile: %d, lasterror: %d", object->sock, ok, tb_ws2_32()->WSAGetLastError());
+
+ // ok or pending? continue it
+ if (!ok || ((ok == SOCKET_ERROR) && (WSA_IO_PENDING == tb_ws2_32()->WSAGetLastError())))
+ {
+ object->code = TB_IOCP_OBJECT_CODE_SENDF;
+ object->state = TB_STATE_WAITING;
+ object->u.sendf.file = file;
+ object->u.sendf.offset = offset;
+ object->u.sendf.size = size;
+ return 0;
+ }
+
+ // failed
+ tb_iocp_object_clear(object);
+ return -1;
+}
+tb_long_t tb_iocp_object_recvv(tb_iocp_object_ref_t object, tb_iovec_t const* list, tb_size_t size)
+{
+ // check
+ tb_assert_and_check_return_val(object && list && size, -1);
+
+ // attempt to get the result if be finished
+ if (object->code == TB_IOCP_OBJECT_CODE_RECVV)
+ {
+ if (object->state == TB_STATE_FINISHED)
+ {
+ // trace
+ tb_trace_d("recvv(%p): state: %s, result: %ld", object->sock, tb_state_cstr(object->state), object->u.recvv.result);
+
+ // clear the previous object data first, but the result cannot be cleared
+ tb_iocp_object_clear(object);
+ return object->u.recvv.result;
+ }
+ else if (object->state == TB_STATE_WAITING)
+ {
+ // check
+ tb_assert_and_check_return_val(object->u.recvv.list == list, -1);
+
+ // trace
+ tb_trace_d("recvv(%p): state: %s, continue ..", object->sock, tb_state_cstr(object->state));
+ return 0;
+ }
+ }
+
+ // trace
+ tb_trace_d("recvv(%p, %lu): %s ..", object->sock, size, tb_state_cstr(object->state));
+
+ // check state
+ tb_assert_and_check_return_val(object->state != TB_STATE_WAITING, -1);
+
+ // bind iocp object first
+ if (!tb_poller_iocp_bind_object(tb_null, object)) return -1;
+
+ // attach buffer data
+ object->u.recvv.list = list;
+ object->u.recvv.size = (tb_iovec_size_t)size;
+
+ // attempt to recv data directly
+ DWORD flag = 0;
+ DWORD real = 0;
+ tb_long_t ok = tb_ws2_32()->WSARecv((SOCKET)tb_sock2fd(object->sock), (WSABUF*)&object->u.recvv.list, (DWORD)object->u.recvv.size, &real, &flag, (LPOVERLAPPED)&object->olap, tb_null);
+
+ // finished and skip iocp notification? return it directly
+ if (!ok && object->skip_cpos)
+ {
+ // trace
+ tb_trace_d("recvv(%p): WSARecv: %u bytes, skip: %d, state: finished directly", object->sock, real, object->skip_cpos);
+ return (tb_long_t)(real > 0? real : (tb_long_t)-1);
+ }
+
+ // trace
+ tb_trace_d("recvv(%p): WSARecv: %ld, skip: %d, lasterror: %d", object->sock, ok, object->skip_cpos, tb_ws2_32()->WSAGetLastError());
+
+ // ok or pending? continue to wait it
+ if (!ok || ((ok == SOCKET_ERROR) && (WSA_IO_PENDING == tb_ws2_32()->WSAGetLastError())))
+ {
+ object->code = TB_IOCP_OBJECT_CODE_RECVV;
+ object->state = TB_STATE_WAITING;
+ return 0;
+ }
+
+ // failed
+ tb_iocp_object_clear(object);
+ return -1;
+}
+tb_long_t tb_iocp_object_sendv(tb_iocp_object_ref_t object, tb_iovec_t const* list, tb_size_t size)
+{
+ // check
+ tb_assert_and_check_return_val(object && list && size, -1);
+
+ // attempt to get the result if be finished
+ if (object->code == TB_IOCP_OBJECT_CODE_SENDV)
+ {
+ if (object->state == TB_STATE_FINISHED)
+ {
+ // trace
+ tb_trace_d("sendv(%p): state: %s, result: %ld", object->sock, tb_state_cstr(object->state), object->u.sendv.result);
+
+ // clear the previous object data first, but the result cannot be cleared
+ tb_iocp_object_clear(object);
+ return object->u.sendv.result;
+ }
+ // waiting timeout before?
+ else if (object->state == TB_STATE_WAITING)
+ {
+ // check
+ tb_assert_and_check_return_val(object->u.sendv.list == list, -1);
+
+ // trace
+ tb_trace_d("sendv(%p): state: %s, continue ..", object->sock, tb_state_cstr(object->state));
+ return 0;
+ }
+ }
+
+ // trace
+ tb_trace_d("sendv(%p, %lu): %s ..", object->sock, size, tb_state_cstr(object->state));
+
+ // check state
+ tb_assert_and_check_return_val(object->state != TB_STATE_WAITING, -1);
+
+ // bind iocp object first
+ if (!tb_poller_iocp_bind_object(tb_null, object)) return -1;
+
+ // attach buffer data
+ object->u.sendv.list = list;
+ object->u.sendv.size = (tb_iovec_size_t)size;
+
+ // attempt to send data directly
+ DWORD real = 0;
+ tb_long_t ok = tb_ws2_32()->WSASend((SOCKET)tb_sock2fd(object->sock), (WSABUF*)&object->u.sendv.list, (DWORD)object->u.sendv.size, &real, 0, (LPOVERLAPPED)&object->olap, tb_null);
+
+ // finished and skip iocp notification? return it directly
+ if (!ok && object->skip_cpos)
+ {
+ // trace
+ tb_trace_d("sendv(%p): WSASend: %u bytes, skip: %d, state: finished directly", object->sock, real, object->skip_cpos);
+ return (tb_long_t)(real > 0? real : (tb_long_t)-1);
+ }
+
+ // trace
+ tb_trace_d("sendv(%p): WSASend: %ld, skip: %d, lasterror: %d", object->sock, ok, object->skip_cpos, tb_ws2_32()->WSAGetLastError());
+
+ // ok or pending? continue to wait it
+ if (!ok || ((ok == SOCKET_ERROR) && (WSA_IO_PENDING == tb_ws2_32()->WSAGetLastError())))
+ {
+ object->code = TB_IOCP_OBJECT_CODE_SENDV;
+ object->state = TB_STATE_WAITING;
+ return 0;
+ }
+
+ // failed
+ tb_iocp_object_clear(object);
+ return -1;
+}
+tb_long_t tb_iocp_object_urecvv(tb_iocp_object_ref_t object, tb_ipaddr_ref_t addr, tb_iovec_t const* list, tb_size_t size)
+{
+ // check
+ tb_assert_and_check_return_val(object && list && size, -1);
+
+ // attempt to get the result if be finished
+ if (object->code == TB_IOCP_OBJECT_CODE_URECVV)
+ {
+ if (object->state == TB_STATE_FINISHED)
+ {
+ // trace
+ tb_trace_d("urecvv(%p): state: %s, result: %ld", object->sock, tb_state_cstr(object->state), object->u.urecvv.result);
+
+ // clear the previous object data first, but the result cannot be cleared
+ tb_iocp_object_clear(object);
+ if (addr) tb_ipaddr_copy(addr, &object->u.urecvv.addr);
+ return object->u.urecvv.result;
+ }
+ // waiting timeout before?
+ else if (object->state == TB_STATE_WAITING)
+ {
+ // check
+ tb_assert_and_check_return_val(object->u.urecvv.list == list, -1);
+
+ // trace
+ tb_trace_d("urecvv(%p): state: %s, continue ..", object->sock, tb_state_cstr(object->state));
+ return 0;
+ }
+ }
+
+ // trace
+ tb_trace_d("urecvv(%p, %lu): %s ..", object->sock, size, tb_state_cstr(object->state));
+
+ // check state
+ tb_assert_and_check_return_val(object->state != TB_STATE_WAITING, -1);
+
+ // bind iocp object first
+ if (!tb_poller_iocp_bind_object(tb_null, object)) return -1;
+
+ // attach buffer data
+ object->u.urecvv.list = list;
+ object->u.urecvv.size = (tb_iovec_size_t)size;
+
+ // make buffer for address, size and flags
+ if (!object->buffer) object->buffer = tb_malloc0(sizeof(struct sockaddr_storage) + sizeof(tb_int_t) + sizeof(DWORD));
+ tb_assert_and_check_return_val(object->buffer, tb_false);
+
+ // init size
+ tb_int_t* psize = (tb_int_t*)((tb_byte_t*)object->buffer + sizeof(struct sockaddr_storage));
+ *psize = sizeof(struct sockaddr_storage);
+
+ // init flag
+ DWORD* pflag = (DWORD*)((tb_byte_t*)object->buffer + sizeof(struct sockaddr_storage) + sizeof(tb_int_t));
+ *pflag = 0;
+
+ /* post to recv event
+ *
+ * It's not safe to skip completion notifications for UDP:
+ * https://blogs.technet.com/b/winserverperformance/archive/2008/06/26/designing-applications-for-high-performance-part-iii.aspx
+ */
+ tb_long_t ok = tb_ws2_32()->WSARecvFrom((SOCKET)tb_sock2fd(object->sock), (WSABUF*)&object->u.urecvv.list, (DWORD)object->u.urecvv.size, tb_null, pflag, (struct sockaddr*)object->buffer, psize, (LPOVERLAPPED)&object->olap, tb_null);
+
+ // trace
+ tb_trace_d("urecvv(%p): WSARecvFrom: %ld, lasterror: %d", object->sock, ok, tb_ws2_32()->WSAGetLastError());
+
+ // ok or pending? continue it
+ if (!ok || ((ok == SOCKET_ERROR) && (WSA_IO_PENDING == tb_ws2_32()->WSAGetLastError())))
+ {
+ object->code = TB_IOCP_OBJECT_CODE_URECVV;
+ object->state = TB_STATE_WAITING;
+ return 0;
+ }
+
+ // failed
+ tb_iocp_object_clear(object);
+ return -1;
+}
+tb_long_t tb_iocp_object_usendv(tb_iocp_object_ref_t object, tb_ipaddr_ref_t addr, tb_iovec_t const* list, tb_size_t size)
+{
+ // check
+ tb_assert_and_check_return_val(object && addr && list, -1);
+
+ // attempt to get the result if be finished
+ if (object->code == TB_IOCP_OBJECT_CODE_USENDV)
+ {
+ if (object->state == TB_STATE_FINISHED)
+ {
+ // trace
+ tb_trace_d("usendv(%p, %{ipaddr}): state: %s, result: %ld", object->sock, addr, tb_state_cstr(object->state), object->u.usendv.result);
+
+ // clear the previous object data first, but the result cannot be cleared
+ tb_iocp_object_clear(object);
+ return object->u.usendv.result;
+ }
+ // waiting timeout before?
+ else if (object->state == TB_STATE_WAITING && tb_ipaddr_is_equal(&object->u.usendv.addr, addr))
+ {
+ // check
+ tb_assert_and_check_return_val(object->u.usendv.list == list, -1);
+
+ // trace
+ tb_trace_d("usendv(%p, %{ipaddr}): state: %s, continue ..", object->sock, addr, tb_state_cstr(object->state));
+ return 0;
+ }
+ }
+
+ // trace
+ tb_trace_d("usendv(%p, %{ipaddr}, %lu): %s ..", object->sock, addr, size, tb_state_cstr(object->state));
+
+ // has waiting io?
+ if (object->state == TB_STATE_WAITING)
+ {
+ // get bound iocp port and user private data
+ HANDLE port = object->port;
+ tb_cpointer_t priv = object->priv;
+
+ // cancel the previous io (urecv) first
+ if (!tb_iocp_object_cancel(object)) return -1;
+
+ // create a new iocp object
+ object = tb_iocp_object_get_or_new(object->sock);
+ tb_assert_and_check_return_val(object, -1);
+
+ // restore the previous bound iocp port and user private data
+ object->port = port;
+ object->priv = priv;
+ }
+
+ // check state
+ tb_assert_and_check_return_val(object->state != TB_STATE_WAITING, -1);
+
+ // bind iocp object first
+ if (!tb_poller_iocp_bind_object(tb_null, object)) return -1;
+
+ // attach buffer data and address
+ object->u.usendv.addr = *addr;
+ object->u.usendv.list = list;
+ object->u.usendv.size = (tb_iovec_size_t)size;
+
+ // load address
+ tb_size_t n = 0;
+ struct sockaddr_storage d = {0};
+ if (!(n = tb_sockaddr_load(&d, &object->u.usendv.addr))) return -1;
+
+ /* attempt to send data directly
+ *
+ * It's not safe to skip completion notifications for UDP:
+ * https://blogs.technet.com/b/winserverperformance/archive/2008/06/26/designing-applications-for-high-performance-part-iii.aspx
+ *
+ * So we attempt to send data firstly without overlapped.
+ */
+ DWORD real = 0;
+ tb_long_t ok = tb_ws2_32()->WSASendTo((SOCKET)tb_sock2fd(object->sock), (WSABUF*)object->u.usendv.list, (DWORD)object->u.usendv.size, &real, 0, (struct sockaddr*)&d, (tb_int_t)n, tb_null, tb_null);
+ if (!ok && real)
+ {
+ // trace
+ tb_trace_d("usendv(%p, %{ipaddr}): WSASendTo: %u bytes, state: finished directly", object->sock, addr, real);
+ return (tb_long_t)real;
+ }
+
+ // post a send event
+ ok = tb_ws2_32()->WSASendTo((SOCKET)tb_sock2fd(object->sock), (WSABUF*)&object->u.usendv.list, (DWORD)object->u.usendv.size, tb_null, 0, (struct sockaddr*)&d, (tb_int_t)n, (LPOVERLAPPED)&object->olap, tb_null);
+
+ // trace
+ tb_trace_d("usendv(%p, %{ipaddr}): WSASendTo: %ld, lasterror: %d", object->sock, addr, ok, tb_ws2_32()->WSAGetLastError());
+
+ // ok or pending? continue it
+ if (!ok || ((ok == SOCKET_ERROR) && (WSA_IO_PENDING == tb_ws2_32()->WSAGetLastError())))
+ {
+ object->code = TB_IOCP_OBJECT_CODE_USENDV;
+ object->state = TB_STATE_WAITING;
+ return 0;
+ }
+
+ // failed
+ tb_iocp_object_clear(object);
+ return -1;
+}
diff --git a/core/src/tbox/src/tbox/platform/windows/iocp_object.h b/core/src/tbox/src/tbox/platform/windows/iocp_object.h
new file mode 100644
index 000000000..0576b932c
--- /dev/null
+++ b/core/src/tbox/src/tbox/platform/windows/iocp_object.h
@@ -0,0 +1,466 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
+ *
+ * @author ruki
+ * @file iocp_object.h
+ * @ingroup platform
+ *
+ */
+#ifndef TB_PLATFORM_WINDOWS_IOCP_OBJECT_H
+#define TB_PLATFORM_WINDOWS_IOCP_OBJECT_H
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "prefix.h"
+#include "../../container/list_entry.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_enter__
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * types
+ */
+
+// the iocp object code enum
+typedef enum __tb_iocp_object_code_e
+{
+ TB_IOCP_OBJECT_CODE_NONE = 0
+, TB_IOCP_OBJECT_CODE_ACPT = 1 //!< accept it
+, TB_IOCP_OBJECT_CODE_CONN = 2 //!< connect to the host address
+, TB_IOCP_OBJECT_CODE_RECV = 3 //!< recv data for tcp
+, TB_IOCP_OBJECT_CODE_SEND = 4 //!< send data for tcp
+, TB_IOCP_OBJECT_CODE_URECV = 5 //!< recv data for udp
+, TB_IOCP_OBJECT_CODE_USEND = 6 //!< send data for udp
+, TB_IOCP_OBJECT_CODE_RECVV = 7 //!< recv iovec data for tcp
+, TB_IOCP_OBJECT_CODE_SENDV = 8 //!< send iovec data for tcp
+, TB_IOCP_OBJECT_CODE_URECVV = 9 //!< recv iovec data for udp
+, TB_IOCP_OBJECT_CODE_USENDV = 10 //!< send iovec data for udp
+, TB_IOCP_OBJECT_CODE_SENDF = 11 //!< maybe return TB_STATE_NOT_SUPPORTED
+
+, TB_IOCP_OBJECT_CODE_MAXN = 12
+
+}tb_iocp_object_code_e;
+
+// the accept iocp object type
+typedef struct __tb_iocp_object_acpt_t
+{
+ // the client address
+ tb_ipaddr_t addr;
+
+ // the result socket
+ tb_socket_ref_t result;
+
+}tb_iocp_object_acpt_t;
+
+// the connection iocp object type
+typedef struct __tb_iocp_object_conn_t
+{
+ // the connected address
+ tb_ipaddr_t addr;
+
+ // the result
+ tb_long_t result;
+
+}tb_iocp_object_conn_t;
+
+// the recv iocp object type, base: tb_iovec_t
+typedef struct __tb_iocp_object_recv_t
+{
+ // the data size for (tb_iovec_t*)->size
+ tb_iovec_size_t size;
+
+ // the recv data for (tb_iovec_t*)->data
+ tb_byte_t* data;
+
+ // the result
+ tb_long_t result; //<! at same position for all iorw objects
+
+}tb_iocp_object_recv_t;
+
+// the send iocp object type, base: tb_iovec_t
+typedef struct __tb_iocp_object_send_t
+{
+ // the data size for (tb_iovec_t*)->size
+ tb_iovec_size_t size;
+
+ // the send data for (tb_iovec_t*)->data
+ tb_byte_t const* data;
+
+ // the result
+ tb_long_t result; //<! at same position for all iorw objects
+
+}tb_iocp_object_send_t;
+
+// the urecv iocp object type, base: tb_iovec_t
+typedef struct __tb_iocp_object_urecv_t
+{
+ // the data size for (tb_iovec_t*)->size
+ tb_iovec_size_t size;
+
+ // the recv data for (tb_iovec_t*)->data
+ tb_byte_t* data;
+
+ // the result
+ tb_long_t result; //<! at same position for all iorw objects
+
+ // the addr
+ tb_ipaddr_t addr;
+
+}tb_iocp_object_urecv_t;
+
+// the usend iocp object type, base: tb_iovec_t
+typedef struct __tb_iocp_object_usend_t
+{
+ // the data size for (tb_iovec_t*)->size
+ tb_iovec_size_t size;
+
+ // the send data for (tb_iovec_t*)->data
+ tb_byte_t const* data;
+
+ // the result
+ tb_long_t result; //<! at same position for all iorw objects
+
+ // the peer addr
+ tb_ipaddr_t addr;
+
+}tb_iocp_object_usend_t;
+
+// the recvv iocp object type
+typedef struct __tb_iocp_object_recvv_t
+{
+ // the recv list
+ tb_iovec_t const* list;
+
+ // the list size
+ tb_size_t size;
+
+ // the result
+ tb_long_t result; //<! at same position for all iorw objects
+
+}tb_iocp_object_recvv_t;
+
+// the sendv iocp object type
+typedef struct __tb_iocp_object_sendv_t
+{
+ // the send list
+ tb_iovec_t const* list;
+
+ // the list size
+ tb_size_t size;
+
+ // the result
+ tb_long_t result; //<! at same position for all iorw objects
+
+}tb_iocp_object_sendv_t;
+
+// the urecvv iocp object type
+typedef struct __tb_iocp_object_urecvv_t
+{
+ // the recv list
+ tb_iovec_t const* list;
+
+ // the list size
+ tb_size_t size;
+
+ // the result
+ tb_long_t result; //<! at same position for all iorw objects
+
+ // the peer addr
+ tb_ipaddr_t addr;
+
+}tb_iocp_object_urecvv_t;
+
+// the usendv iocp object type
+typedef struct __tb_iocp_object_usendv_t
+{
+ // the send list
+ tb_iovec_t const* list;
+
+ // the list size
+ tb_size_t size;
+
+ // the result
+ tb_long_t result; //<! at same position for all iorw objects
+
+ // the addr
+ tb_ipaddr_t addr;
+
+}tb_iocp_object_usendv_t;
+
+/* the sendfile iocp object type
+ *
+ * @note hack result struct member offset for hacking the same result offset for the other iocp object
+ *
+ * see poller_iocp.c: tb_poller_iocp_event_spak_iorw()
+ */
+typedef struct __tb_iocp_object_sendf_t
+{
+#if TB_CPU_BIT64
+
+ // the file
+ tb_file_ref_t file;
+
+ // the size
+ tb_hize_t size;
+
+ // the result
+ tb_long_t result; //<! at same position for all iorw objects
+
+ // the offset
+ tb_hize_t offset;
+#else
+
+ // the size
+ tb_hize_t size;
+
+ // the result
+ tb_long_t result; //<! at same position for all iorw objects
+
+ // the file
+ tb_file_ref_t file;
+
+ // the offset
+ tb_hize_t offset;
+#endif
+
+}tb_iocp_object_sendf_t;
+
+// the iocp object type
+typedef __tb_cpu_aligned__ struct __tb_iocp_object_t
+{
+ // the overlapped data
+ OVERLAPPED olap;
+
+ // the bound iocp port
+ HANDLE port;
+
+ // the socket
+ tb_socket_ref_t sock;
+
+ // the user private data
+ tb_cpointer_t priv;
+
+ // the list entry
+ tb_list_entry_t entry;
+
+ /* the private buffer for iocp poller
+ *
+ * acpt: sizeof(struct sockaddr_storage)) * 2
+ * urecv and recvv: sizeof(struct sockaddr_storage)) + sizeof(tb_int_t) + sizeof(DWORD)
+ */
+ tb_pointer_t buffer;
+
+ /* the objects
+ *
+ * tb_iovec_t must be aligned by cpu-bytes for WSABUF
+ */
+ __tb_cpu_aligned__ union
+ {
+ tb_iocp_object_acpt_t acpt;
+ tb_iocp_object_conn_t conn;
+ tb_iocp_object_recv_t recv;
+ tb_iocp_object_send_t send;
+ tb_iocp_object_urecv_t urecv;
+ tb_iocp_object_usend_t usend;
+ tb_iocp_object_recvv_t recvv;
+ tb_iocp_object_sendv_t sendv;
+ tb_iocp_object_urecvv_t urecvv;
+ tb_iocp_object_usendv_t usendv;
+ tb_iocp_object_sendf_t sendf;
+
+ } u;
+
+ // the object code
+ tb_uint8_t code;
+
+ /* the object state
+ *
+ * TB_STATE_OK
+ * TB_STATE_KILLING
+ * TB_STATE_PENDING
+ * TB_STATE_WAITING
+ * TB_STATE_FINISHED
+ */
+ tb_uint8_t state;
+
+ /* skip completion port on success?
+ *
+ * SetFileCompletionNotificationModes(fd, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)
+ */
+ tb_uint8_t skip_cpos;
+
+}tb_iocp_object_t, *tb_iocp_object_ref_t;
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * interfaces
+ */
+
+/* get or new an iocp object from the given socket in local thread
+ *
+ * @note only init object once in every thread
+ *
+ * @param sock the socket
+ *
+ * @return the iocp object
+ */
+tb_iocp_object_ref_t tb_iocp_object_get_or_new(tb_socket_ref_t sock);
+
+/* get iocp object from the given socket in local thread
+ *
+ * @param sock the socket
+ *
+ * @return the iocp object
+ */
+tb_iocp_object_ref_t tb_iocp_object_get(tb_socket_ref_t sock);
+
+/* remove iocp object for the given socket in local thread
+ *
+ * @param sock the socket
+ */
+tb_void_t tb_iocp_object_remove(tb_socket_ref_t sock);
+
+/* clear iocp object state and buffer
+ *
+ * @param object the iocp object
+ */
+tb_void_t tb_iocp_object_clear(tb_iocp_object_ref_t object);
+
+/*! accept socket
+ *
+ * @param object the iocp object
+ * @param addr the client address
+ *
+ * @return the client socket
+ */
+tb_socket_ref_t tb_iocp_object_accept(tb_iocp_object_ref_t object, tb_ipaddr_ref_t addr);
+
+/* connect the given client address
+ *
+ * @param object the iocp object
+ * @param addr the client address
+ *
+ * @return ok: 1, continue: 0; failed: -1
+ */
+tb_long_t tb_iocp_object_connect(tb_iocp_object_ref_t object, tb_ipaddr_ref_t addr);
+
+/* recv the socket data for tcp
+ *
+ * @param object the iocp object
+ * @param data the data
+ * @param size the size
+ *
+ * @return the real size or -1
+ */
+tb_long_t tb_iocp_object_recv(tb_iocp_object_ref_t object, tb_byte_t* data, tb_size_t size);
+
+/* connect the given client address
+ *
+ * @param object the iocp object
+ * @param data the data
+ * @param size the size
+ *
+ * @return the real size or -1
+ */
+tb_long_t tb_iocp_object_send(tb_iocp_object_ref_t object, tb_byte_t const* data, tb_size_t size);
+
+/*! recvv the socket data for tcp
+ *
+ * @param object the iocp object
+ * @param list the iovec list
+ * @param size the iovec size
+ *
+ * @return the real size or -1
+ */
+tb_long_t tb_iocp_object_recvv(tb_iocp_object_ref_t object, tb_iovec_t const* list, tb_size_t size);
+
+/*! sendv the socket data for tcp
+ *
+ * @param object the iocp object
+ * @param list the iovec list
+ * @param size the iovec size
+ *
+ * @return the real size or -1
+ */
+tb_long_t tb_iocp_object_sendv(tb_iocp_object_ref_t object, tb_iovec_t const* list, tb_size_t size);
+
+/* recv the socket data for udp
+ *
+ * @param object the iocp object
+ * @param addr the peer address(output)
+ * @param data the data
+ * @param size the size
+ *
+ * @return the real size or -1
+ */
+tb_long_t tb_iocp_object_urecv(tb_iocp_object_ref_t object, tb_ipaddr_ref_t addr, tb_byte_t* data, tb_size_t size);
+
+/* send the socket data for udp
+ *
+ * @param object the iocp object
+ * @param addr the address
+ * @param data the data
+ * @param size the size
+ *
+ * @return the real size or -1
+ */
+tb_long_t tb_iocp_object_usend(tb_iocp_object_ref_t object, tb_ipaddr_ref_t addr, tb_byte_t const* data, tb_size_t size);
+
+/*! urecvv the socket data for udp
+ *
+ * @param object the iocp object
+ * @param addr the peer address(output)
+ * @param list the iovec list
+ * @param size the iovec size
+ *
+ * @return the real size or -1
+ */
+tb_long_t tb_iocp_object_urecvv(tb_iocp_object_ref_t object, tb_ipaddr_ref_t addr, tb_iovec_t const* list, tb_size_t size);
+
+/*! usendv the socket data for udp
+ *
+ * @param object the iocp object
+ * @param addr the addr
+ * @param list the iovec list
+ * @param size the iovec size
+ *
+ * @return the real size or -1
+ */
+tb_long_t tb_iocp_object_usendv(tb_iocp_object_ref_t object, tb_ipaddr_ref_t addr, tb_iovec_t const* list, tb_size_t size);
+
+/* send file data
+ *
+ * @param object the iocp object
+ * @param file the file
+ * @param offset the offset
+ * @param size the size
+ *
+ * @return the real size or -1
+ */
+tb_hong_t tb_iocp_object_sendf(tb_iocp_object_ref_t object, tb_file_ref_t file, tb_hize_t offset, tb_hize_t size);
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_leave__
+
+#endif
diff --git a/core/src/tbox/src/tbox/platform/windows/memory.c b/core/src/tbox/src/tbox/platform/windows/memory.c
index 0504d3470..9de4c638b 100644
--- a/core/src/tbox/src/tbox/platform/windows/memory.c
+++ b/core/src/tbox/src/tbox/platform/windows/memory.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file memory.c
diff --git a/core/src/tbox/src/tbox/platform/windows/mutex.c b/core/src/tbox/src/tbox/platform/windows/mutex.c
index 323f88538..9cf9366d3 100644
--- a/core/src/tbox/src/tbox/platform/windows/mutex.c
+++ b/core/src/tbox/src/tbox/platform/windows/mutex.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file mutex.c
@@ -41,7 +41,7 @@ tb_mutex_ref_t tb_mutex_init()
}
tb_void_t tb_mutex_exit(tb_mutex_ref_t mutex)
{
- if (mutex) CloseHandle(mutex);
+ if (mutex) CloseHandle((HANDLE)mutex);
}
tb_bool_t tb_mutex_enter(tb_mutex_ref_t mutex)
{
diff --git a/core/src/tbox/src/tbox/platform/windows/ntstatus.h b/core/src/tbox/src/tbox/platform/windows/ntstatus.h
index 580bc939e..5646a30d7 100644
--- a/core/src/tbox/src/tbox/platform/windows/ntstatus.h
+++ b/core/src/tbox/src/tbox/platform/windows/ntstatus.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file ntstatus.h
diff --git a/core/src/tbox/src/tbox/platform/windows/page.c b/core/src/tbox/src/tbox/platform/windows/page.c
index 847ec68f9..d6bf9a8ed 100644
--- a/core/src/tbox/src/tbox/platform/windows/page.c
+++ b/core/src/tbox/src/tbox/platform/windows/page.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file page.c
diff --git a/core/src/tbox/src/tbox/platform/windows/poller_iocp.c b/core/src/tbox/src/tbox/platform/windows/poller_iocp.c
new file mode 100644
index 000000000..2bd8ab9aa
--- /dev/null
+++ b/core/src/tbox/src/tbox/platform/windows/poller_iocp.c
@@ -0,0 +1,695 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
+ *
+ * @author ruki
+ * @file poller_iocp.c
+ *
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "prefix.h"
+#include "iocp_object.h"
+#include "../posix/sockaddr.h"
+#include "../../container/container.h"
+#include "../../algorithm/algorithm.h"
+#include "interface/interface.h"
+#include "ntstatus.h"
+#ifdef TB_CONFIG_MODULE_HAVE_COROUTINE
+# include "../../coroutine/coroutine.h"
+# include "../../coroutine/impl/impl.h"
+#endif
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * types
+ */
+
+// the iocp func type
+typedef struct __tb_iocp_func_t
+{
+ // the GetAcceptExSockaddrs func
+ tb_mswsock_GetAcceptExSockaddrs_t GetAcceptExSockaddrs;
+
+ // the GetQueuedCompletionStatusEx func
+ tb_kernel32_GetQueuedCompletionStatusEx_t GetQueuedCompletionStatusEx;
+
+ // WSAGetLastError
+ tb_ws2_32_WSAGetLastError_t WSAGetLastError;
+
+}tb_iocp_func_t;
+
+// the poller iocp type
+typedef struct __tb_poller_iocp_t
+{
+ // the maxn
+ tb_size_t maxn;
+
+ // the user private data
+ tb_cpointer_t priv;
+
+ // the iocp func
+ tb_iocp_func_t func;
+
+ // the i/o completion port
+ HANDLE port;
+
+ // the events
+ tb_OVERLAPPED_ENTRY_t* events;
+
+ // the events count
+ tb_size_t events_count;
+
+ // the last wait count
+ tb_size_t lastwait_count;
+
+}tb_poller_iocp_t, *tb_poller_iocp_ref_t;
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * private declaration
+ */
+__tb_extern_c_enter__
+
+// bind iocp port for object
+tb_bool_t tb_poller_iocp_bind_object(tb_poller_iocp_ref_t poller, tb_iocp_object_ref_t object);
+
+__tb_extern_c_leave__
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * private implementation
+ */
+static tb_size_t tb_poller_iocp_event_from_code(tb_size_t code)
+{
+ static tb_size_t s_events[] =
+ {
+ TB_POLLER_EVENT_CONN
+ , TB_POLLER_EVENT_ACPT
+ , TB_POLLER_EVENT_CONN
+ , TB_POLLER_EVENT_RECV
+ , TB_POLLER_EVENT_SEND
+ , TB_POLLER_EVENT_RECV
+ , TB_POLLER_EVENT_SEND
+ , TB_POLLER_EVENT_RECV
+ , TB_POLLER_EVENT_SEND
+ , TB_POLLER_EVENT_RECV
+ , TB_POLLER_EVENT_SEND
+ , TB_POLLER_EVENT_SEND
+ };
+ tb_assert_and_check_return_val(code < tb_arrayn(s_events), TB_POLLER_EVENT_NONE);
+ return s_events[code];
+}
+static tb_long_t tb_poller_iocp_event_spak_conn(tb_poller_iocp_ref_t poller, tb_iocp_object_ref_t object, tb_size_t real, tb_size_t error)
+{
+ // have been finished?
+ tb_check_return_val(object->state != TB_STATE_FINISHED, 1);
+
+ // done
+ switch (error)
+ {
+ // ok?
+ case ERROR_SUCCESS:
+ object->u.conn.result = 1;
+ break;
+ // pending?
+ case WAIT_TIMEOUT:
+ case ERROR_IO_PENDING:
+ object->u.conn.result = 0;
+ break;
+ // timeout?
+ case WSAEINTR:
+ case ERROR_SEM_TIMEOUT:
+ case ERROR_OPERATION_ABORTED:
+ object->u.conn.result = 0;
+ break;
+ // failed?
+ case WSAENOTCONN:
+ case WSAECONNREFUSED:
+ case ERROR_CONNECTION_REFUSED:
+ object->u.conn.result = -1;
+ break;
+ // unknown error
+ default:
+ // trace
+ tb_trace_e("connect(%p): %{ipaddr}, unknown error: %u", object->sock, &object->u.conn.addr, error);
+ object->u.conn.result = -1;
+ break;
+ }
+
+ // trace
+ tb_trace_d("connect(%p) %{ipaddr}, return: %ld", object->sock, &object->u.conn.addr, object->u.conn.result);
+
+ // ok
+ return 1;
+}
+static tb_long_t tb_poller_iocp_event_spak_acpt(tb_poller_iocp_ref_t poller, tb_iocp_object_ref_t object, tb_size_t real, tb_size_t error)
+{
+ // done
+ switch (error)
+ {
+ // ok or pending?
+ case ERROR_SUCCESS:
+ case WAIT_TIMEOUT:
+ case ERROR_IO_PENDING:
+ {
+ // update the accept context, otherwise shutdown and getsockname will be failed
+ SOCKET fd = tb_sock2fd(object->u.acpt.result);
+ SOCKET acpt = (SOCKET)tb_sock2fd(object->sock);
+ tb_ws2_32()->setsockopt(fd, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (tb_char_t*)&acpt, sizeof(acpt));
+
+ // non-block
+ ULONG nb = 1;
+ tb_ws2_32()->ioctlsocket(fd, FIONBIO, &nb);
+
+ /* disable the nagle's algorithm to fix 40ms ack delay in some case (.e.g send-send-40ms-recv)
+ *
+ * 40ms is the tcp ack delay, which indicates that you are likely
+ * encountering a bad interaction between delayed acks and the nagle's algorithm.
+ *
+ * TCP_NODELAY simply disables the nagle's algorithm and is a one-time setting on the socket,
+ * whereas the other two must be set at the appropriate times during the life of the connection
+ * and can therefore be trickier to use.
+ *
+ * so we set TCP_NODELAY to reduce response delay for the accepted socket in the server by default
+ */
+ tb_int_t enable = 1;
+ tb_ws2_32()->setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (tb_char_t*)&enable, sizeof(enable));
+
+ // skip the completion notification on success
+ if (tb_kernel32_has_SetFileCompletionNotificationModes())
+ {
+ if (tb_kernel32()->SetFileCompletionNotificationModes((HANDLE)fd, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS))
+ {
+ tb_iocp_object_ref_t client_object = tb_iocp_object_get_or_new(object->u.acpt.result);
+ if (client_object)
+ client_object->skip_cpos = 1;
+ }
+ }
+
+ // get accept socket addresses
+ INT server_size = 0;
+ INT client_size = 0;
+ struct sockaddr_storage* server_addr = tb_null;
+ struct sockaddr_storage* client_addr = tb_null;
+ if (poller->func.GetAcceptExSockaddrs)
+ {
+ // check
+ tb_assert(object->buffer);
+
+ // get server and client addresses
+ poller->func.GetAcceptExSockaddrs( (tb_byte_t*)object->buffer
+ , 0
+ , sizeof(struct sockaddr_storage)
+ , sizeof(struct sockaddr_storage)
+ , (LPSOCKADDR*)&server_addr
+ , &server_size
+ , (LPSOCKADDR*)&client_addr
+ , &client_size);
+
+ // exists client address?
+ if (client_addr)
+ {
+ // save address
+ tb_sockaddr_save(&object->u.acpt.addr, client_addr);
+
+ // trace
+ tb_trace_d("accept(%p): client address: %{ipaddr}", object->sock, &object->u.acpt.addr);
+ }
+ }
+ }
+ break;
+ // canceled? timeout?
+ case WSAEINTR:
+ case ERROR_OPERATION_ABORTED:
+ if (object->u.acpt.result) tb_socket_exit(object->u.acpt.result);
+ object->u.acpt.result = tb_null;
+ break;
+ // unknown error
+ default:
+ // trace
+ tb_trace_e("accept(%p): unknown error: %u", object->sock, error);
+ if (object->u.acpt.result) tb_socket_exit(object->u.acpt.result);
+ object->u.acpt.result = tb_null;
+ break;
+ }
+
+ // ok
+ return 1;
+}
+static tb_long_t tb_poller_iocp_event_spak_iorw(tb_poller_iocp_ref_t poller, tb_iocp_object_ref_t object, tb_size_t real, tb_size_t error)
+{
+ // have been finished?
+ tb_check_return_val(object->state != TB_STATE_FINISHED, 1);
+
+ // ok?
+ if (real)
+ {
+ // trace
+ tb_trace_d("iorw(%p): code: %u, real: %lu", object->sock, object->code, real);
+
+ // save address for urecv or urecvv
+ if (object->code == TB_IOCP_OBJECT_CODE_URECV || object->code == TB_IOCP_OBJECT_CODE_URECVV)
+ {
+ // the address
+ struct sockaddr_storage* addr = (struct sockaddr_storage*)object->buffer;
+ tb_assert_and_check_return_val(addr, -1);
+
+ // save address
+ tb_sockaddr_save(object->code == TB_IOCP_OBJECT_CODE_URECV? &object->u.urecv.addr : &object->u.urecvv.addr, addr);
+ }
+
+ // check struct member offset for hacking the same result offset for the other iocp object
+ tb_assert_static(tb_offsetof(tb_iocp_object_recv_t, result) == tb_offsetof(tb_iocp_object_send_t, result));
+ tb_assert_static(tb_offsetof(tb_iocp_object_recv_t, result) == tb_offsetof(tb_iocp_object_recvv_t, result));
+ tb_assert_static(tb_offsetof(tb_iocp_object_recv_t, result) == tb_offsetof(tb_iocp_object_sendv_t, result));
+ tb_assert_static(tb_offsetof(tb_iocp_object_recv_t, result) == tb_offsetof(tb_iocp_object_urecv_t, result));
+ tb_assert_static(tb_offsetof(tb_iocp_object_recv_t, result) == tb_offsetof(tb_iocp_object_usend_t, result));
+ tb_assert_static(tb_offsetof(tb_iocp_object_recv_t, result) == tb_offsetof(tb_iocp_object_urecvv_t, result));
+ tb_assert_static(tb_offsetof(tb_iocp_object_recv_t, result) == tb_offsetof(tb_iocp_object_usendv_t, result));
+ tb_assert_static(tb_offsetof(tb_iocp_object_recv_t, result) == tb_offsetof(tb_iocp_object_sendf_t, result));
+
+
+ // save the result size, @note: hack the result offset
+ object->u.recv.result = real;
+ return 1;
+ }
+
+ // error?
+ switch (error)
+ {
+ // connection closed?
+ case ERROR_SUCCESS:
+ case WAIT_TIMEOUT:
+ case ERROR_IO_PENDING:
+ object->u.recv.result = -1;
+ break;
+ // canceled? timeout
+ case WSAEINTR:
+ case ERROR_OPERATION_ABORTED:
+ object->u.recv.result = 0;
+ break;
+ // connection reset?
+ case WSAECONNRESET:
+ case ERROR_HANDLE_EOF:
+ case ERROR_NETNAME_DELETED:
+ case ERROR_BAD_COMMAND:
+ object->u.recv.result = -1;
+ break;
+ // unknown error
+ default:
+ // trace
+ tb_trace_e("iorw(%p): code: %u, unknown error: %lu", object->sock, object->code, error);
+ object->u.recv.result = -1;
+ break;
+ }
+
+ // ok
+ return 1;
+}
+static tb_long_t tb_poller_iocp_event_spak(tb_poller_iocp_ref_t poller, tb_poller_event_func_t func, tb_iocp_object_ref_t object, tb_size_t real, tb_size_t error)
+{
+ // trace
+ tb_trace_d("spak[%p]: code %u, state: %s ..", object->sock, object->code, tb_state_cstr(object->state));
+
+ // check
+ tb_assert_and_check_return_val(object->state == TB_STATE_WAITING || object->state == TB_STATE_FINISHED, -1);
+
+ // init spak
+ static tb_long_t (*s_spak[])(tb_poller_iocp_ref_t , tb_iocp_object_ref_t, tb_size_t , tb_size_t ) =
+ {
+ tb_null
+ , tb_poller_iocp_event_spak_acpt
+ , tb_poller_iocp_event_spak_conn
+ , tb_poller_iocp_event_spak_iorw
+ , tb_poller_iocp_event_spak_iorw
+ , tb_poller_iocp_event_spak_iorw
+ , tb_poller_iocp_event_spak_iorw
+ , tb_poller_iocp_event_spak_iorw
+ , tb_poller_iocp_event_spak_iorw
+ , tb_poller_iocp_event_spak_iorw
+ , tb_poller_iocp_event_spak_iorw
+ , tb_poller_iocp_event_spak_iorw
+ };
+ tb_assert_and_check_return_val(object->code < tb_arrayn(s_spak), -1);
+
+ // spark event
+ tb_long_t ok = (s_spak[object->code])? s_spak[object->code](poller, object, real, error) : -1;
+
+ // finish to wait events
+ object->state = TB_STATE_FINISHED;
+
+ // do event handler
+ func((tb_poller_ref_t)poller, object->sock, tb_poller_iocp_event_from_code(object->code), object->priv);
+
+ // ok?
+ return ok;
+}
+static tb_long_t tb_poller_iocp_event_wait_ex(tb_poller_iocp_ref_t poller, tb_poller_event_func_t func, tb_long_t timeout)
+{
+ // clear error first
+ SetLastError(ERROR_SUCCESS);
+
+ // 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, tb_OVERLAPPED_ENTRY_t);
+ tb_assert_and_check_return_val(poller->events, -1);
+ }
+
+ // wait events
+ DWORD events_count = 0;
+ BOOL wait_ok = poller->func.GetQueuedCompletionStatusEx(poller->port, poller->events, (DWORD)poller->events_count, &events_count, (DWORD)(timeout < 0? INFINITE : timeout), FALSE);
+
+ // the last error
+ tb_size_t error = (tb_size_t)GetLastError();
+
+ // timeout?
+ if (!wait_ok && error == WAIT_TIMEOUT) return 0;
+
+ // error?
+ tb_assert_and_check_return_val(wait_ok, -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 = (tb_OVERLAPPED_ENTRY_t*)tb_ralloc(poller->events, poller->events_count * sizeof(tb_OVERLAPPED_ENTRY_t));
+ tb_assert_and_check_return_val(poller->events, -1);
+ }
+ tb_assert(events_count <= poller->events_count);
+
+ // limit
+ events_count = tb_min(events_count, (DWORD)poller->maxn);
+
+ // handle events
+ tb_size_t i = 0;
+ tb_size_t wait = 0;
+ tb_OVERLAPPED_ENTRY_t* e = tb_null;
+ for (i = 0; i < events_count; i++)
+ {
+ // the iocp event
+ e = poller->events + i;
+
+ // get iocp object
+ tb_iocp_object_ref_t object = (tb_iocp_object_ref_t)e->lpOverlapped;
+
+ // iocp port is killed?
+ tb_check_return_val(object, -1);
+
+ // spark notification, is 1?
+ tb_check_continue(!e->lpCompletionKey);
+
+ // this object is killing? ignore it directly
+ if (object->state == TB_STATE_KILLING)
+ {
+ // trace
+ tb_trace_d("wait_ex[%p]: ignore killing object", object->sock);
+ tb_iocp_object_clear(object);
+ continue ;
+ }
+
+ // check socket
+ tb_assert_and_check_return_val(object->sock, -1);
+
+ // get real transferred bytes
+ tb_size_t real = (tb_size_t)e->dwNumberOfBytesTransferred;
+
+ // get last error
+ error = tb_ntstatus_to_winerror((tb_size_t)e->Internal);
+
+ // trace
+ tb_trace_d("wait_ex[%p]: real: %u bytes, lasterror: %lu", object->sock, real, error);
+
+ // spark and update the events
+ if (tb_poller_iocp_event_spak(poller, func, object, real, error) > 0)
+ wait++;
+ }
+
+ // ok
+ return wait;
+}
+static tb_long_t tb_poller_iocp_event_wait(tb_poller_iocp_ref_t poller, tb_poller_event_func_t func, tb_long_t timeout)
+{
+ tb_size_t wait = 0;
+ while (1)
+ {
+ // compute the timeout
+ if (wait) timeout = 0;
+
+ // clear error first
+ SetLastError(ERROR_SUCCESS);
+
+ // wait event
+ DWORD real = 0;
+ tb_pointer_t pkey = tb_null;
+ tb_iocp_object_ref_t object = tb_null;
+ BOOL wait_ok = GetQueuedCompletionStatus(poller->port, (LPDWORD)&real, (PULONG_PTR)&pkey, (LPOVERLAPPED*)&object, (DWORD)(timeout < 0? INFINITE : timeout));
+
+ // the last error
+ tb_size_t error = (tb_size_t)GetLastError();
+
+ // timeout or spark?
+ if ((!wait_ok && (error == WAIT_TIMEOUT || error == ERROR_OPERATION_ABORTED)) || pkey) break;
+
+ // iocp port is killed?
+ tb_check_return_val(object, -1);
+
+ // this object is killing? ignore it directly
+ if (object->state == TB_STATE_KILLING)
+ {
+ // trace
+ tb_trace_d("wait[%p]: ignore killing object", object->sock);
+ tb_iocp_object_clear(object);
+ continue ;
+ }
+
+ // check
+ tb_assert_and_check_return_val(object->sock, -1);
+
+ // trace
+ tb_trace_d("wait[%p]: %s, real: %u bytes, lasterror: %lu", object->sock, wait_ok? "ok" : "failed", real, error);
+
+ // spark and update the events
+ if (tb_poller_iocp_event_spak(poller, func, object, real, error) > 0)
+ wait++;
+ }
+
+ // ok
+ return wait;
+}
+tb_bool_t tb_poller_iocp_bind_object(tb_poller_iocp_ref_t poller, tb_iocp_object_ref_t object)
+{
+ // check
+ tb_assert(object);
+
+ // bind this socket and object to port
+ if (!object->port)
+ {
+ // get the poller of the current coroutin scheduler
+#ifdef TB_CONFIG_MODULE_HAVE_COROUTINE
+ if (!poller)
+ {
+ tb_co_scheduler_io_ref_t co_scheduler_io = tb_co_scheduler_io_need(tb_null);
+ if (co_scheduler_io) poller = (tb_poller_iocp_ref_t)co_scheduler_io->poller;
+ else
+ {
+ tb_lo_scheduler_io_ref_t lo_scheduler_io = tb_lo_scheduler_io_need(tb_null);
+ if (lo_scheduler_io) poller = (tb_poller_iocp_ref_t)lo_scheduler_io->poller;
+ }
+ }
+#endif
+ tb_assert_and_check_return_val(poller, tb_false);
+
+ // bind iocp port
+ HANDLE port = CreateIoCompletionPort((HANDLE)(SOCKET)tb_sock2fd(object->sock), poller->port, tb_null, 0);
+ if (port != poller->port)
+ {
+ // trace
+ tb_trace_e("CreateIoCompletionPort failed: %d, socket: %p", GetLastError(), object->sock);
+ return tb_false;
+ }
+
+ // bind ok
+ object->port = port;
+ }
+
+ // ok
+ return tb_true;
+}
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * implementation
+ */
+tb_poller_ref_t tb_poller_init(tb_cpointer_t priv)
+{
+ // done
+ tb_bool_t ok = tb_false;
+ tb_poller_iocp_ref_t poller = tb_null;
+ do
+ {
+ // check iovec
+ tb_assert_static(sizeof(tb_iovec_t) == sizeof(WSABUF));
+ tb_assert_and_check_break(tb_memberof_eq(tb_iovec_t, data, WSABUF, buf));
+ tb_assert_and_check_break(tb_memberof_eq(tb_iovec_t, size, WSABUF, len));
+
+ // make poller
+ poller = tb_malloc0_type(tb_poller_iocp_t);
+ tb_assert_and_check_break(poller);
+
+ // init maxn
+ poller->maxn = 1 << 16;
+
+ // init user private data
+ poller->priv = priv;
+
+ // init func
+ poller->func.GetAcceptExSockaddrs = tb_mswsock()->GetAcceptExSockaddrs;
+ poller->func.GetQueuedCompletionStatusEx = tb_kernel32()->GetQueuedCompletionStatusEx;
+ poller->func.WSAGetLastError = tb_ws2_32()->WSAGetLastError;
+ tb_assert_and_check_break(poller->func.WSAGetLastError);
+
+ // init port
+ poller->port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, tb_null, 0, 0);
+ tb_assert_and_check_break(poller->port && poller->port != INVALID_HANDLE_VALUE);
+
+ // ok
+ ok = tb_true;
+
+ } while (0);
+
+ // failed?
+ if (!ok)
+ {
+ // exit it
+ if (poller) tb_poller_exit((tb_poller_ref_t)poller);
+ poller = tb_null;
+ }
+
+ // ok?
+ return (tb_poller_ref_t)poller;
+}
+tb_void_t tb_poller_exit(tb_poller_ref_t self)
+{
+ // check
+ tb_poller_iocp_ref_t poller = (tb_poller_iocp_ref_t)self;
+ tb_assert_and_check_return(poller);
+
+ // exit port
+ if (poller->port) CloseHandle(poller->port);
+ poller->port = tb_null;
+
+ // exit events
+ if (poller->events) tb_free(poller->events);
+ poller->events = tb_null;
+ poller->events_count = 0;
+
+ // free it
+ tb_free(poller);
+}
+tb_size_t tb_poller_type(tb_poller_ref_t poller)
+{
+ return TB_POLLER_TYPE_IOCP;
+}
+tb_cpointer_t tb_poller_priv(tb_poller_ref_t self)
+{
+ // check
+ tb_poller_iocp_ref_t poller = (tb_poller_iocp_ref_t)self;
+ tb_assert_and_check_return_val(poller, tb_null);
+
+ // get the user private data
+ return poller->priv;
+}
+tb_void_t tb_poller_kill(tb_poller_ref_t self)
+{
+ // check
+ tb_poller_iocp_ref_t poller = (tb_poller_iocp_ref_t)self;
+ tb_assert_and_check_return(poller);
+
+ // post kill notification to iocp port
+ PostQueuedCompletionStatus(poller->port, 0, tb_null, tb_null);
+}
+tb_void_t tb_poller_spak(tb_poller_ref_t self)
+{
+ // check
+ tb_poller_iocp_ref_t poller = (tb_poller_iocp_ref_t)self;
+ tb_assert_and_check_return(poller);
+
+ // post spark notification to iocp port
+ PostQueuedCompletionStatus(poller->port, 0, (ULONG_PTR)tb_u2p(1), tb_null);
+}
+tb_bool_t tb_poller_support(tb_poller_ref_t self, tb_size_t events)
+{
+ // all supported events
+ static const tb_size_t events_supported = TB_POLLER_EVENT_EALL | TB_POLLER_EVENT_ONESHOT;
+
+ // is supported?
+ return (events_supported & events) == events;
+}
+tb_bool_t tb_poller_insert(tb_poller_ref_t self, tb_socket_ref_t sock, tb_size_t events, tb_cpointer_t priv)
+{
+ // check
+ tb_poller_iocp_ref_t poller = (tb_poller_iocp_ref_t)self;
+ tb_assert_and_check_return_val(poller && sock, tb_false);
+
+ // get iocp object for this socket, @note only init event once in every thread
+ tb_iocp_object_ref_t object = tb_iocp_object_get_or_new(sock);
+ tb_assert_and_check_return_val(object, tb_false);
+
+ // save the user private data
+ object->priv = priv;
+ return tb_true;
+}
+tb_bool_t tb_poller_remove(tb_poller_ref_t self, tb_socket_ref_t sock)
+{
+ return tb_true;
+}
+tb_bool_t tb_poller_modify(tb_poller_ref_t self, tb_socket_ref_t sock, tb_size_t events, tb_cpointer_t priv)
+{
+ return tb_poller_insert(self, sock, 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_iocp_ref_t poller = (tb_poller_iocp_ref_t)self;
+ tb_assert_and_check_return_val(poller && func, -1);
+
+ // trace
+ tb_trace_d("waiting with timeout(%ld) ..", timeout);
+
+ /* we can use GetQueuedCompletionStatusEx() to increase performance, perhaps,
+ * but we may end up lowering perf if you max out only one I/O thread.
+ */
+ tb_long_t wait = -1;
+ if (poller->lastwait_count > 1 && poller->func.GetQueuedCompletionStatusEx)
+ wait = tb_poller_iocp_event_wait_ex(poller, func, timeout);
+ else wait = tb_poller_iocp_event_wait(poller, func, timeout);
+
+ // save the last wait count
+ poller->lastwait_count = wait;
+
+ // wait ok
+ return wait;
+}
+
diff --git a/core/src/tbox/src/tbox/platform/windows/prefix.h b/core/src/tbox/src/tbox/platform/windows/prefix.h
index 5c1372b10..03099d987 100644
--- a/core/src/tbox/src/tbox/platform/windows/prefix.h
+++ b/core/src/tbox/src/tbox/platform/windows/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
@@ -52,15 +52,16 @@ static __tb_inline__ tb_time_t tb_filetime_to_time(FILETIME ft)
return (tb_time_t)((LONGLONG)(ui.QuadPart - 116444736000000000ull) / 10000000ul);
}
-// the path full for wchar
+// get absolute path for wchar
static __tb_inline__ tb_wchar_t const* tb_path_absolute_w(tb_char_t const* path, tb_wchar_t* full, tb_size_t maxn)
{
- // the path full
- tb_char_t full_a[TB_PATH_MAXN] = {0};
- if (!tb_path_absolute(path, full_a, TB_PATH_MAXN)) return tb_null;
+ // get absolute path
+ tb_char_t data[TB_PATH_MAXN] = {0};
+ path = tb_path_absolute(path, data, TB_PATH_MAXN);
+ tb_check_return_val(path, tb_null);
// atow
- return tb_atow(full, full_a, maxn) != -1? full : tb_null;
+ return tb_atow(full, path, maxn) != -1? full : tb_null;
}
#endif
diff --git a/core/src/tbox/src/tbox/platform/windows/print.c b/core/src/tbox/src/tbox/platform/windows/print.c
index 7265a7e5d..883ccc51d 100644
--- a/core/src/tbox/src/tbox/platform/windows/print.c
+++ b/core/src/tbox/src/tbox/platform/windows/print.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file print.c
diff --git a/core/src/tbox/src/tbox/platform/windows/process.c b/core/src/tbox/src/tbox/platform/windows/process.c
index 6d879081c..b4b6bbf4f 100644
--- a/core/src/tbox/src/tbox/platform/windows/process.c
+++ b/core/src/tbox/src/tbox/platform/windows/process.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2018, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file process.c
diff --git a/core/src/tbox/src/tbox/platform/windows/processor.c b/core/src/tbox/src/tbox/platform/windows/processor.c
index 722041cee..5f950be43 100644
--- a/core/src/tbox/src/tbox/platform/windows/processor.c
+++ b/core/src/tbox/src/tbox/platform/windows/processor.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file processor.c
diff --git a/core/src/tbox/src/tbox/platform/windows/sched.c b/core/src/tbox/src/tbox/platform/windows/sched.c
index 32d4ee5b8..469900936 100644
--- a/core/src/tbox/src/tbox/platform/windows/sched.c
+++ b/core/src/tbox/src/tbox/platform/windows/sched.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file sched.c
diff --git a/core/src/tbox/src/tbox/platform/windows/semaphore.c b/core/src/tbox/src/tbox/platform/windows/semaphore.c
index b9294bf3b..8679cc8e9 100644
--- a/core/src/tbox/src/tbox/platform/windows/semaphore.c
+++ b/core/src/tbox/src/tbox/platform/windows/semaphore.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file semaphore.c
diff --git a/core/src/tbox/src/tbox/platform/windows/socket.c b/core/src/tbox/src/tbox/platform/windows/socket.c
index 8e89c81e5..920eb887b 100644
--- a/core/src/tbox/src/tbox/platform/windows/socket.c
+++ b/core/src/tbox/src/tbox/platform/windows/socket.c
@@ -16,11 +16,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file socket.c
- *
*/
/* //////////////////////////////////////////////////////////////////////////////////////
@@ -29,6 +28,7 @@
#include "prefix.h"
#include "../socket.h"
#include "interface/interface.h"
+#include "iocp_object.h"
#include "socket_pool.h"
#include "../posix/sockaddr.h"
#ifdef TB_CONFIG_MODULE_HAVE_COROUTINE
@@ -307,10 +307,7 @@ tb_bool_t tb_socket_ctrl(tb_socket_ref_t sock, tb_size_t ctrl, ...)
// enable the nagle's algorithm
tb_int_t enable = (tb_int_t)tb_va_arg(args, tb_bool_t);
if (!tb_ws2_32()->setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (tb_char_t*)&enable, sizeof(enable)))
- {
- // ok
ok = tb_true;
- }
}
break;
case TB_SOCKET_CTRL_GET_TCP_NODELAY:
@@ -341,10 +338,7 @@ tb_bool_t tb_socket_ctrl(tb_socket_ref_t sock, tb_size_t ctrl, ...)
// set the recv buffer size
tb_int_t real = (tb_int_t)buff_size;
if (!tb_ws2_32()->setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (tb_char_t*)&real, sizeof(real)))
- {
- // ok
ok = tb_true;
- }
}
break;
case TB_SOCKET_CTRL_GET_RECV_BUFF_SIZE:
@@ -375,10 +369,7 @@ tb_bool_t tb_socket_ctrl(tb_socket_ref_t sock, tb_size_t ctrl, ...)
// set the send buffer size
tb_int_t real = (tb_int_t)buff_size;
if (!tb_ws2_32()->setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (tb_char_t*)&real, sizeof(real)))
- {
- // ok
ok = tb_true;
- }
}
break;
case TB_SOCKET_CTRL_GET_SEND_BUFF_SIZE:
@@ -421,6 +412,12 @@ tb_long_t tb_socket_connect(tb_socket_ref_t sock, tb_ipaddr_ref_t addr)
tb_assert_and_check_return_val(sock && addr, -1);
tb_assert_and_check_return_val(!tb_ipaddr_is_empty(addr), -1);
+#if defined(TB_CONFIG_MODULE_HAVE_COROUTINE) && !defined(TB_CONFIG_MICRO_ENABLE)
+ // attempt to use iocp object to connect if exists
+ tb_iocp_object_ref_t object = tb_iocp_object_get_or_new(sock);
+ if (object) return tb_iocp_object_connect(object, addr);
+#endif
+
// load addr
tb_size_t n = 0;
struct sockaddr_storage d = {0};
@@ -439,7 +436,8 @@ tb_long_t tb_socket_connect(tb_socket_ref_t sock, tb_ipaddr_ref_t addr)
if (e == WSAEISCONN) return 1;
// continue?
- if (e == WSAEWOULDBLOCK || e == WSAEINPROGRESS) return 0;
+ if (e == WSAEWOULDBLOCK || e == WSAEINPROGRESS)
+ return 0;
// error
return -1;
@@ -495,6 +493,12 @@ tb_socket_ref_t tb_socket_accept(tb_socket_ref_t sock, tb_ipaddr_ref_t addr)
// check
tb_assert_and_check_return_val(sock, tb_null);
+#if defined(TB_CONFIG_MODULE_HAVE_COROUTINE) && !defined(TB_CONFIG_MICRO_ENABLE)
+ // attempt to use iocp object to accept if exists
+ tb_iocp_object_ref_t object = tb_iocp_object_get_or_new(sock);
+ if (object) return tb_iocp_object_accept(object, addr);
+#endif
+
// done
tb_bool_t ok = tb_false;
tb_socket_ref_t acpt = tb_null;
@@ -515,6 +519,20 @@ tb_socket_ref_t tb_socket_accept(tb_socket_ref_t sock, tb_ipaddr_ref_t addr)
ULONG nb = 1;
if (tb_ws2_32()->ioctlsocket(fd, FIONBIO, &nb) == SOCKET_ERROR) break;
+ /* disable the nagle's algorithm to fix 40ms ack delay in some case (.e.g send-send-40ms-recv)
+ *
+ * 40ms is the tcp ack delay, which indicates that you are likely
+ * encountering a bad interaction between delayed acks and the nagle's algorithm.
+ *
+ * TCP_NODELAY simply disables the nagle's algorithm and is a one-time setting on the socket,
+ * whereas the other two must be set at the appropriate times during the life of the connection
+ * and can therefore be trickier to use.
+ *
+ * so we set TCP_NODELAY to reduce response delay for the accepted socket in the server by default
+ */
+ tb_int_t enable = 1;
+ setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (tb_char_t*)&enable, sizeof(enable));
+
// save address
if (addr) tb_sockaddr_save(addr, &d);
@@ -590,6 +608,9 @@ tb_bool_t tb_socket_exit(tb_socket_ref_t sock)
// check
tb_assert_and_check_return_val(sock, tb_false);
+ // trace
+ tb_trace_d("close: %p", sock);
+
#ifdef TB_CONFIG_MODULE_HAVE_COROUTINE
// attempt to cancel waiting from coroutine first
tb_pointer_t scheduler_io = tb_null;
@@ -600,14 +621,17 @@ tb_bool_t tb_socket_exit(tb_socket_ref_t sock)
if ((scheduler_io = tb_lo_scheduler_io_self()) && tb_lo_scheduler_io_cancel((tb_lo_scheduler_io_ref_t)scheduler_io, sock)) {}
#endif
+#if defined(TB_CONFIG_MODULE_HAVE_COROUTINE) && !defined(TB_CONFIG_MICRO_ENABLE)
+ // remove iocp object for this socket if exists
+ tb_iocp_object_remove(sock);
+#endif
+
// close it
tb_bool_t ok = !tb_ws2_32()->closesocket(tb_sock2fd(sock))? tb_true : tb_false;
-
- // failed?
if (!ok)
{
// trace
- tb_trace_e("clos: %p failed, errno: %d", sock, GetLastError());
+ tb_trace_e("close: %p failed, errno: %d", sock, GetLastError());
}
// ok?
@@ -619,6 +643,12 @@ tb_long_t tb_socket_recv(tb_socket_ref_t sock, tb_byte_t* data, tb_size_t size)
tb_assert_and_check_return_val(sock && data, -1);
tb_check_return_val(size, 0);
+#if defined(TB_CONFIG_MODULE_HAVE_COROUTINE) && !defined(TB_CONFIG_MICRO_ENABLE)
+ // attempt to use iocp object to recv data if exists
+ tb_iocp_object_ref_t object = tb_iocp_object_get_or_new(sock);
+ if (object) return tb_iocp_object_recv(object, data, size);
+#endif
+
// recv
tb_long_t real = tb_ws2_32()->recv(tb_sock2fd(sock), (tb_char_t*)data, (tb_int_t)size, 0);
@@ -640,6 +670,12 @@ tb_long_t tb_socket_send(tb_socket_ref_t sock, tb_byte_t const* data, tb_size_t
tb_assert_and_check_return_val(sock && data, -1);
tb_check_return_val(size, 0);
+#if defined(TB_CONFIG_MODULE_HAVE_COROUTINE) && !defined(TB_CONFIG_MICRO_ENABLE)
+ // attempt to use iocp object to send data if exists
+ tb_iocp_object_ref_t object = tb_iocp_object_get_or_new(sock);
+ if (object) return tb_iocp_object_send(object, data, size);
+#endif
+
// recv
tb_long_t real = tb_ws2_32()->send(tb_sock2fd(sock), (tb_char_t const*)data, (tb_int_t)size, 0);
@@ -660,25 +696,28 @@ tb_hong_t tb_socket_sendf(tb_socket_ref_t sock, tb_file_ref_t file, tb_hize_t of
// check
tb_assert_and_check_return_val(sock && file && size, -1);
- // the transmitfile func
- tb_mswsock_TransmitFile_t pTransmitFile = tb_mswsock()->TransmitFile;
- tb_assert_and_check_return_val(pTransmitFile, -1);
-
- // transmit it
- OVERLAPPED olap = {0}; olap.Offset = (DWORD)offset;
- tb_hong_t real = pTransmitFile((SOCKET)sock - 1, (HANDLE)file, (DWORD)size, (1 << 16), &olap, tb_null, 0);
-
- // ok?
- if (real >= 0) return real;
+#if defined(TB_CONFIG_MODULE_HAVE_COROUTINE) && !defined(TB_CONFIG_MICRO_ENABLE)
+ // attempt to use iocp object to send file data if exists
+ tb_iocp_object_ref_t object = tb_iocp_object_get_or_new(sock);
+ if (object) return tb_iocp_object_sendf(object, file, offset, size);
+#endif
- // errno
- tb_long_t e = tb_ws2_32()->WSAGetLastError();
+ // read data
+ tb_byte_t data[8192];
+ tb_long_t read = tb_file_pread(file, data, sizeof(data), offset);
+ tb_check_return_val(read > 0, read);
- // continue?
- if (e == WSAEWOULDBLOCK || e == WSAEINPROGRESS || e == WSA_IO_PENDING) return 0;
+ // send data
+ tb_size_t writ = 0;
+ while (writ < read)
+ {
+ tb_long_t real = tb_socket_send(sock, data + writ, read - writ);
+ if (real > 0) writ += real;
+ else break;
+ }
- // error
- return -1;
+ // ok?
+ return writ == read? writ : -1;
}
tb_long_t tb_socket_urecv(tb_socket_ref_t sock, tb_ipaddr_ref_t addr, tb_byte_t* data, tb_size_t size)
{
@@ -688,6 +727,12 @@ tb_long_t tb_socket_urecv(tb_socket_ref_t sock, tb_ipaddr_ref_t addr, tb_byte_t*
// no size?
tb_check_return_val(size, 0);
+#if defined(TB_CONFIG_MODULE_HAVE_COROUTINE) && !defined(TB_CONFIG_MICRO_ENABLE)
+ // attempt to use iocp object to urecv data if exists
+ tb_iocp_object_ref_t object = tb_iocp_object_get_or_new(sock);
+ if (object) return tb_iocp_object_urecv(object, addr, data, size);
+#endif
+
// recv
struct sockaddr_storage d = {0};
tb_int_t n = sizeof(d);
@@ -718,6 +763,12 @@ tb_long_t tb_socket_usend(tb_socket_ref_t sock, tb_ipaddr_ref_t addr, tb_byte_t
// no size?
tb_check_return_val(size, 0);
+#if defined(TB_CONFIG_MODULE_HAVE_COROUTINE) && !defined(TB_CONFIG_MICRO_ENABLE)
+ // attempt to use iocp object to usend data if exists
+ tb_iocp_object_ref_t object = tb_iocp_object_get_or_new(sock);
+ if (object) return tb_iocp_object_usend(object, addr, data, size);
+#endif
+
// load addr
tb_size_t n = 0;
struct sockaddr_storage d = {0};
@@ -741,6 +792,12 @@ tb_long_t tb_socket_recvv(tb_socket_ref_t sock, tb_iovec_t const* list, tb_size_
// check
tb_assert_and_check_return_val(sock && list && size, -1);
+#ifdef TB_CONFIG_MODULE_HAVE_COROUTINE
+ // attempt to use iocp object to recv data if exists
+ tb_iocp_object_ref_t object = tb_iocp_object_get_or_new(sock);
+ if (object) return tb_iocp_object_recvv(object, list, size);
+#endif
+
// walk read
tb_size_t i = 0;
tb_size_t read = 0;
@@ -779,6 +836,12 @@ tb_long_t tb_socket_sendv(tb_socket_ref_t sock, tb_iovec_t const* list, tb_size_
// check
tb_assert_and_check_return_val(sock && list && size, -1);
+#ifdef TB_CONFIG_MODULE_HAVE_COROUTINE
+ // attempt to use iocp object to send data if exists
+ tb_iocp_object_ref_t object = tb_iocp_object_get_or_new(sock);
+ if (object) return tb_iocp_object_sendv(object, list, size);
+#endif
+
// walk writ
tb_size_t i = 0;
tb_size_t writ = 0;
@@ -817,6 +880,12 @@ tb_long_t tb_socket_urecvv(tb_socket_ref_t sock, tb_ipaddr_ref_t addr, tb_iovec_
// check
tb_assert_and_check_return_val(sock && list && size, -1);
+#ifdef TB_CONFIG_MODULE_HAVE_COROUTINE
+ // attempt to use iocp object to recv data if exists
+ tb_iocp_object_ref_t object = tb_iocp_object_get_or_new(sock);
+ if (object) return tb_iocp_object_urecvv(object, addr, list, size);
+#endif
+
// done
tb_size_t i = 0;
struct sockaddr_storage d = {0};
@@ -861,6 +930,12 @@ tb_long_t tb_socket_usendv(tb_socket_ref_t sock, tb_ipaddr_ref_t addr, tb_iovec_
tb_assert_and_check_return_val(sock && addr && list && size, -1);
tb_assert_and_check_return_val(!tb_ipaddr_is_empty(addr), -1);
+#ifdef TB_CONFIG_MODULE_HAVE_COROUTINE
+ // attempt to use iocp object to send data if exists
+ tb_iocp_object_ref_t object = tb_iocp_object_get_or_new(sock);
+ if (object) return tb_iocp_object_usendv(object, addr, list, size);
+#endif
+
// load addr
tb_size_t n = 0;
struct sockaddr_storage d = {0};
diff --git a/core/src/tbox/src/tbox/platform/windows/socket_pool.c b/core/src/tbox/src/tbox/platform/windows/socket_pool.c
index d39283039..eae2aaa33 100644
--- a/core/src/tbox/src/tbox/platform/windows/socket_pool.c
+++ b/core/src/tbox/src/tbox/platform/windows/socket_pool.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file socket_pool.c
diff --git a/core/src/tbox/src/tbox/platform/windows/socket_pool.h b/core/src/tbox/src/tbox/platform/windows/socket_pool.h
index 1042b36f7..24ea7c87e 100644
--- a/core/src/tbox/src/tbox/platform/windows/socket_pool.h
+++ b/core/src/tbox/src/tbox/platform/windows/socket_pool.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file socket_pool.h
diff --git a/core/src/tbox/src/tbox/platform/windows/syserror.c b/core/src/tbox/src/tbox/platform/windows/syserror.c
index 7ac744ca5..ec08d21c1 100644
--- a/core/src/tbox/src/tbox/platform/windows/syserror.c
+++ b/core/src/tbox/src/tbox/platform/windows/syserror.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file syserror.c
diff --git a/core/src/tbox/src/tbox/platform/windows/thread.c b/core/src/tbox/src/tbox/platform/windows/thread.c
index d3be03a2a..30491f610 100644
--- a/core/src/tbox/src/tbox/platform/windows/thread.c
+++ b/core/src/tbox/src/tbox/platform/windows/thread.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file thread.c
@@ -86,10 +86,11 @@ tb_long_t tb_thread_wait(tb_thread_ref_t thread, tb_long_t timeout, tb_int_t* re
tb_check_return_val(r >= WAIT_OBJECT_0, -1);
// get the return value
- DWORD code = 0;
- if (retval && GetExitCodeThread((HANDLE)thread, &code))
- *retval = (tb_int_t)code;
- else *retval = 0;
+ if (retval)
+ {
+ DWORD code = 0;
+ *retval = GetExitCodeThread((HANDLE)thread, &code)? (tb_int_t)code : 0;
+ }
// ok
return 1;
diff --git a/core/src/tbox/src/tbox/platform/windows/thread_local.c b/core/src/tbox/src/tbox/platform/windows/thread_local.c
index 13728e057..07f137d45 100644
--- a/core/src/tbox/src/tbox/platform/windows/thread_local.c
+++ b/core/src/tbox/src/tbox/platform/windows/thread_local.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @tlocal thread_local.c
@@ -99,6 +99,10 @@ tb_void_t tb_thread_local_exit(tb_thread_local_ref_t local)
// check
tb_assert(local);
+ // free the previous data first
+ if (local->free && tb_thread_local_has(local))
+ local->free(tb_thread_local_get(local));
+
// exit it
TlsFree(*((DWORD*)local->priv));
}
diff --git a/core/src/tbox/src/tbox/platform/windows/time.c b/core/src/tbox/src/tbox/platform/windows/time.c
index 0ceb4023a..fecd2b103 100644
--- a/core/src/tbox/src/tbox/platform/windows/time.c
+++ b/core/src/tbox/src/tbox/platform/windows/time.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file utils.c
diff --git a/core/src/tbox/src/tbox/platform/windows/uuid.c b/core/src/tbox/src/tbox/platform/windows/uuid.c
index 2e2881d94..e72435979 100644
--- a/core/src/tbox/src/tbox/platform/windows/uuid.c
+++ b/core/src/tbox/src/tbox/platform/windows/uuid.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file uuid.c
diff --git a/core/src/tbox/src/tbox/prefix.h b/core/src/tbox/src/tbox/prefix.h
index 9c9633e09..76ac09ad4 100644
--- a/core/src/tbox/src/tbox/prefix.h
+++ b/core/src/tbox/src/tbox/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/prefix/abort.h b/core/src/tbox/src/tbox/prefix/abort.h
index 639ff71a7..03800b955 100644
--- a/core/src/tbox/src/tbox/prefix/abort.h
+++ b/core/src/tbox/src/tbox/prefix/abort.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file abort.h
diff --git a/core/src/tbox/src/tbox/prefix/arch.h b/core/src/tbox/src/tbox/prefix/arch.h
index 4ebe36bd3..1a8c09d8c 100644
--- a/core/src/tbox/src/tbox/prefix/arch.h
+++ b/core/src/tbox/src/tbox/prefix/arch.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file arch.h
@@ -108,11 +108,15 @@
# define TB_ARCH_ARM_VERSION (4)
# define TB_ARCH_ARM_v4t
# define TB_ARCH_STRING "armv4t"
+# elif defined(__ARM_ARCH_3__)
+# define TB_ARCH_ARM_VERSION (3)
+# define TB_ARCH_ARM_v3
+# define TB_ARCH_STRING "armv3"
# elif defined(__ARM_ARCH)
# define TB_ARCH_ARM_VERSION __ARM_ARCH
# if __ARM_ARCH >= 8
# define TB_ARCH_ARM_v8
-# if defined(__arm64) || defined(__arm64__)
+# if defined(__arm64) || defined(__arm64__)
# define TB_ARCH_ARM64
# define TB_ARCH_STRING "arm64"
# elif (defined(__aarch64__) && __aarch64__)
@@ -160,6 +164,19 @@
|| defined(__mips__)
# define TB_ARCH_MIPS
# define TB_ARCH_STRING "mips"
+#elif defined(TB_COMPILER_IS_TINYC)
+# if defined(TCC_TARGET_I386)
+# define TB_ARCH_x86
+# define TB_ARCH_STRING "i386"
+# elif defined(TCC_TARGET_X86_64)
+# define TB_ARCH_x64
+# define TB_ARCH_STRING "x86_64"
+# elif defined(TCC_TARGET_ARM)
+# define TB_ARCH_ARM
+# define TB_ARCH_STRING "arm"
+# else
+# error unknown arch for tiny c, please define target like -DTCC_TARGET_I386
+# endif
#else
//# define TB_ARCH_SPARC
//# define TB_ARCH_PPC
@@ -187,13 +204,13 @@
#endif
// vfp
-#if defined(__VFP_FP__)
+#if defined(__VFP_FP__) || (defined(TB_COMPILER_IS_TINYC) && defined(TCC_ARM_VFP))
# define TB_ARCH_VFP
# define TB_ARCH_STRING_4 "_vfp"
#endif
// elf
-#if defined(__ELF__)
+#if defined(__ELF__) || (defined(TB_COMPILER_IS_TINYC) && !defined(TCC_ARM_PE))
# define TB_ARCH_ELF
# define TB_ARCH_STRING_5 "_elf"
#endif
diff --git a/core/src/tbox/src/tbox/prefix/arm/prefix.S b/core/src/tbox/src/tbox/prefix/arm/prefix.S
index dc1114f8f..f05c1ee28 100644
--- a/core/src/tbox/src/tbox/prefix/arm/prefix.S
+++ b/core/src/tbox/src/tbox/prefix/arm/prefix.S
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.S
diff --git a/core/src/tbox/src/tbox/prefix/arm64/prefix.S b/core/src/tbox/src/tbox/prefix/arm64/prefix.S
index bcd65c0ae..01c998cca 100644
--- a/core/src/tbox/src/tbox/prefix/arm64/prefix.S
+++ b/core/src/tbox/src/tbox/prefix/arm64/prefix.S
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.S
diff --git a/core/src/tbox/src/tbox/prefix/assembler.h b/core/src/tbox/src/tbox/prefix/assembler.h
index 9e5a86f06..f4a4597bb 100644
--- a/core/src/tbox/src/tbox/prefix/assembler.h
+++ b/core/src/tbox/src/tbox/prefix/assembler.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file assembler.h
diff --git a/core/src/tbox/src/tbox/prefix/assert.h b/core/src/tbox/src/tbox/prefix/assert.h
index f8e1340d8..2c8c4a86a 100644
--- a/core/src/tbox/src/tbox/prefix/assert.h
+++ b/core/src/tbox/src/tbox/prefix/assert.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file assert.h
@@ -54,7 +54,7 @@ __tb_extern_c_enter__
// assert
#ifdef __tb_debug__
-# if defined(TB_COMPILER_IS_GCC)
+# if defined(TB_COMPILER_IS_GCC) || defined(TB_COMPILER_IS_TINYC)
# define tb_assertf(x, fmt, arg...) do { if (!(x)) {tb_trace_a("expr[%s]: " fmt, #x, ##arg); tb_assert_backtrace_dump(); tb_trace_sync(); tb_abort(); } } while(0)
# define tb_assertf_and_check_abort(x, fmt, arg...) tb_assertf(x, fmt, ##arg)
# define tb_assertf_and_check_return(x, fmt, arg...) tb_assertf(x, fmt, ##arg)
@@ -80,7 +80,7 @@ __tb_extern_c_enter__
# define tb_assertf_and_check_continue
# endif
#else
-# if defined(TB_COMPILER_IS_GCC)
+# if defined(TB_COMPILER_IS_GCC) || defined(TB_COMPILER_IS_TINYC)
# define tb_assertf(x, fmt, arg...)
# define tb_assertf_and_check_abort(x, fmt, arg...) tb_check_abort(x)
# define tb_assertf_and_check_return(x, fmt, arg...) tb_check_return(x)
@@ -129,7 +129,7 @@ __tb_extern_c_enter__
// assert and pass code, not abort it
#ifdef __tb_debug__
-# if defined(TB_COMPILER_IS_GCC)
+# if defined(TB_COMPILER_IS_GCC) || defined(TB_COMPILER_IS_TINYC)
# define tb_assertf_pass_return(x, fmt, arg...) do { if (!(x)) {tb_trace_a("expr[%s]: " fmt, #x, ##arg); tb_assert_backtrace_dump(); tb_trace_sync(); return ; } } while(0)
# define tb_assertf_pass_return_val(x, v, fmt, arg...) do { if (!(x)) {tb_trace_a("expr[%s]: " fmt, #x, ##arg); tb_assert_backtrace_dump(); tb_trace_sync(); return (v); } } while(0)
# define tb_assertf_pass_goto(x, b, fmt, arg...) do { if (!(x)) {tb_trace_a("expr[%s]: " fmt, #x, ##arg); tb_assert_backtrace_dump(); tb_trace_sync(); goto b; } } while(0)
@@ -167,7 +167,7 @@ __tb_extern_c_enter__
# define tb_assertf_pass_and_check_continue
# endif
#else
-# if defined(TB_COMPILER_IS_GCC)
+# if defined(TB_COMPILER_IS_GCC) || defined(TB_COMPILER_IS_TINYC)
# define tb_assertf_pass_return(x, fmt, arg...)
# define tb_assertf_pass_return_val(x, v, fmt, arg...)
# define tb_assertf_pass_goto(x, b, fmt, arg...)
@@ -250,11 +250,17 @@ __tb_extern_c_enter__
* @endcode
*/
#if __tb_has_feature__(c_static_assert)
-# define tb_assert_static(x) _Static_assert(x, "")
+# define tb_assert_static(x) _Static_assert(x, "")
+# define tb_assert_static_msg(x, m) _Static_assert(x, m)
+#elif defined(__cpp_static_assert)
+# define tb_assert_static(x) static_assert(x, "")
+# define tb_assert_static_msg(x, m) static_assert(x, m)
#elif defined(TB_COMPILER_IS_GCC) && TB_COMPILER_VERSION_BE(4, 6)
-# define tb_assert_static(x) _Static_assert(x, "")
+# define tb_assert_static(x) _Static_assert(x, "")
+# define tb_assert_static_msg(x, m) _Static_assert(x, m)
#else
-# define tb_assert_static(x) do { typedef int __tb_static_assert__[(x)? 1 : -1]; __tb_volatile__ __tb_static_assert__ __a; tb_used_ptr((tb_cpointer_t)(tb_size_t)__a); } while(0)
+# define tb_assert_static(x) do { typedef int __tb_static_assert__[(x)? 1 : -1]; __tb_volatile__ __tb_static_assert__ __a; tb_used_ptr((tb_cpointer_t)(tb_size_t)__a); } while(0)
+# define tb_assert_static_msg(x, m) tb_assert_static(x)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
diff --git a/core/src/tbox/src/tbox/prefix/cache.h b/core/src/tbox/src/tbox/prefix/cache.h
index 9b8128942..b9a66da91 100644
--- a/core/src/tbox/src/tbox/prefix/cache.h
+++ b/core/src/tbox/src/tbox/prefix/cache.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file cache.h
diff --git a/core/src/tbox/src/tbox/prefix/check.h b/core/src/tbox/src/tbox/prefix/check.h
index 420f10610..8573b2bd6 100644
--- a/core/src/tbox/src/tbox/prefix/check.h
+++ b/core/src/tbox/src/tbox/prefix/check.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file check.h
diff --git a/core/src/tbox/src/tbox/prefix/compiler.h b/core/src/tbox/src/tbox/prefix/compiler.h
index ef1668d73..9f4bc42ac 100644
--- a/core/src/tbox/src/tbox/prefix/compiler.h
+++ b/core/src/tbox/src/tbox/prefix/compiler.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file compiler.h
@@ -88,6 +88,21 @@
# error Unknown Intel C++ Compiler Version
# endif
+// tiny c
+#elif defined(__TINYC__)
+# define TB_COMPILER_IS_TINYC
+# define TB_COMPILER_VERSION_BT(major, minor) (__TINYC__ > ((major) * 100 + (minor)))
+# define TB_COMPILER_VERSION_BE(major, minor) (__TINYC__ >= ((major) * 100 + (minor)))
+# define TB_COMPILER_VERSION_EQ(major, minor) (__TINYC__ == ((major) * 100 + (minor)))
+# define TB_COMPILER_VERSION_LT(major, minor) (__TINYC__ < ((major) * 100 + (minor)))
+# define TB_COMPILER_VERSION_LE(major, minor) (__TINYC__ <= ((major) * 100 + (minor)))
+# define TB_COMPILER_STRING "tiny c"
+# if (__TINYC__ == 926)
+# define TB_COMPILER_VERSION_STRING "tiny c 0.9.26"
+# else
+# error Unknown Tiny C Compiler Version
+# endif
+
// borland c++
#elif defined(__BORLANDC__)
# define TB_COMPILER_IS_BORLAND
@@ -116,6 +131,9 @@
// gnu c/c++
#elif defined(__GNUC__)
# define TB_COMPILER_IS_GCC
+# if defined(__MINGW32__) || defined(__MINGW64__)
+# define TB_COMPILER_IS_MINGW
+# endif
# define TB_COMPILER_VERSION_BT(major, minor) ((__GNUC__ * 100 + __GNUC_MINOR__) > ((major) * 100 + (minor)))
# define TB_COMPILER_VERSION_BE(major, minor) ((__GNUC__ * 100 + __GNUC_MINOR__) >= ((major) * 100 + (minor)))
# define TB_COMPILER_VERSION_EQ(major, minor) ((__GNUC__ * 100 + __GNUC_MINOR__) == ((major) * 100 + (minor)))
diff --git a/core/src/tbox/src/tbox/prefix/config.h b/core/src/tbox/src/tbox/prefix/config.h
index dfc256073..d57aa3c6e 100644
--- a/core/src/tbox/src/tbox/prefix/config.h
+++ b/core/src/tbox/src/tbox/prefix/config.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file config.h
diff --git a/core/src/tbox/src/tbox/prefix/cpu.h b/core/src/tbox/src/tbox/prefix/cpu.h
index 8be64370a..6f9d1c76a 100644
--- a/core/src/tbox/src/tbox/prefix/cpu.h
+++ b/core/src/tbox/src/tbox/prefix/cpu.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file cpu.h
@@ -51,7 +51,8 @@
|| defined(_M_X64) \
|| defined(_M_AMD64) \
|| defined(_M_IA64) \
- || (defined(__WORDSIZE) && (__WORDSIZE == 64))
+ || (defined(__WORDSIZE) && (__WORDSIZE == 64)) \
+ || defined(TCC_TARGET_X86_64)
# define TB_CPU_BITSIZE (64)
# define TB_CPU_BITBYTE (8)
# define TB_CPU_BITALIGN (7)
diff --git a/core/src/tbox/src/tbox/prefix/endian.h b/core/src/tbox/src/tbox/prefix/endian.h
index fa3854f18..3e01a54a4 100644
--- a/core/src/tbox/src/tbox/prefix/endian.h
+++ b/core/src/tbox/src/tbox/prefix/endian.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file endian.h
@@ -38,15 +38,16 @@
#ifdef __BYTE_ORDER__
# if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
# define TB_WORDS_BIGENDIAN
-# error check it
# endif
#endif
+#if defined(MIPSEB) || defined(_MIPSEB) || defined(__MIPSEB__)
+# define TB_WORDS_BIGENDIAN
+#endif
// float endian
#ifdef __FLOAT_WORD_ORDER__
# if __FLOAT_WORD_ORDER__ != __ORDER_LITTLE_ENDIAN__
-# define TB_FLOAT_BIGENDIAN
-# error check it
+# define TB_FLOAT_BIGENDIAN
# endif
#endif
diff --git a/core/src/tbox/src/tbox/prefix/keyword.h b/core/src/tbox/src/tbox/prefix/keyword.h
index c0a84fa1d..94281940b 100644
--- a/core/src/tbox/src/tbox/prefix/keyword.h
+++ b/core/src/tbox/src/tbox/prefix/keyword.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file keyword.h
@@ -43,12 +43,12 @@
# define __tb_register__
#endif
#define __tb_volatile__ volatile
-#define __tb_func__ __FUNCTION__
-#define __tb_file__ __FILE__
-#define __tb_line__ __LINE__
#if defined(TB_COMPILER_IS_MSVC)
+# define __tb_func__ __FUNCTION__
+# define __tb_file__ __FILE__
+# define __tb_line__ __LINE__
# define __tb_asm__ __asm
# define __tb_inline__ __inline
# define __tb_inline_force__ __forceinline
@@ -61,6 +61,9 @@
#elif defined(TB_COMPILER_IS_GCC)
+# define __tb_func__ __FUNCTION__
+# define __tb_file__ __FILE__
+# define __tb_line__ __LINE__
# define __tb_asm__ __asm__
# define __tb_inline__ __inline__
# define __tb_inline_force__ __inline__ __attribute__((always_inline))
@@ -82,6 +85,22 @@
# define __tb_fastcall__ __attribute__((__fastcall__))
# define __tb_thiscall__ __attribute__((__thiscall__))
# endif
+
+#elif defined(TB_COMPILER_IS_TINYC)
+
+# define __tb_func__ __func__
+# define __tb_file__ __FILE__
+# define __tb_line__ __LINE__
+# define __tb_asm__ __asm__
+# define __tb_inline__ __inline__
+# define __tb_inline_force__ __inline__ __attribute__((always_inline))
+# define __tb_packed__ __attribute__((packed, aligned(1)))
+# define __tb_aligned__(a) __attribute__((aligned(a)))
+# define __tb_cdecl__ __attribute__((cdecl))
+# define __tb_stdcall__ __attribute__((stdcall))
+# define __tb_fastcall__ __attribute__((fastcall))
+# define __tb_thiscall__ __attribute__((thiscall))
+
#else
# define __tb_asm__
@@ -252,7 +271,7 @@
* @endcode
*
*/
-#define __tb_typeref__(object) struct __tb_##object##_dummy_t{tb_int_t dummy;}* tb_##object##_ref_t
+#define __tb_typeref__(object) struct __tb_##object##_dummy_t{tb_int_t dummy;} const* tb_##object##_ref_t
// macros
#define __tb_mstring__(x) #x
diff --git a/core/src/tbox/src/tbox/prefix/limits.h b/core/src/tbox/src/tbox/prefix/limits.h
index f8ad9a855..647bc0769 100644
--- a/core/src/tbox/src/tbox/prefix/limits.h
+++ b/core/src/tbox/src/tbox/prefix/limits.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file limits.h
diff --git a/core/src/tbox/src/tbox/prefix/malloc.h b/core/src/tbox/src/tbox/prefix/malloc.h
index 334815267..de4d55e96 100644
--- a/core/src/tbox/src/tbox/prefix/malloc.h
+++ b/core/src/tbox/src/tbox/prefix/malloc.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file malloc.h
diff --git a/core/src/tbox/src/tbox/prefix/mips/prefix.S b/core/src/tbox/src/tbox/prefix/mips/prefix.S
index 9441b0484..a350424b7 100644
--- a/core/src/tbox/src/tbox/prefix/mips/prefix.S
+++ b/core/src/tbox/src/tbox/prefix/mips/prefix.S
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.S
diff --git a/core/src/tbox/src/tbox/prefix/packed.h b/core/src/tbox/src/tbox/prefix/packed.h
index 0c4e35270..fca8e0172 100644
--- a/core/src/tbox/src/tbox/prefix/packed.h
+++ b/core/src/tbox/src/tbox/prefix/packed.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file packed_e.h
diff --git a/core/src/tbox/src/tbox/prefix/prefix.S b/core/src/tbox/src/tbox/prefix/prefix.S
index b499166c3..0f65ccf97 100644
--- a/core/src/tbox/src/tbox/prefix/prefix.S
+++ b/core/src/tbox/src/tbox/prefix/prefix.S
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.S
diff --git a/core/src/tbox/src/tbox/prefix/prefix.h b/core/src/tbox/src/tbox/prefix/prefix.h
index e75fda462..ed92e4804 100644
--- a/core/src/tbox/src/tbox/prefix/prefix.h
+++ b/core/src/tbox/src/tbox/prefix/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/prefix/state.c b/core/src/tbox/src/tbox/prefix/state.c
index 00c6ff5ab..3ed79f927 100644
--- a/core/src/tbox/src/tbox/prefix/state.c
+++ b/core/src/tbox/src/tbox/prefix/state.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file state.c
diff --git a/core/src/tbox/src/tbox/prefix/state.h b/core/src/tbox/src/tbox/prefix/state.h
index 7d3baa8cd..090c1a05a 100644
--- a/core/src/tbox/src/tbox/prefix/state.h
+++ b/core/src/tbox/src/tbox/prefix/state.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file state.h
diff --git a/core/src/tbox/src/tbox/prefix/trace.h b/core/src/tbox/src/tbox/prefix/trace.h
index 7cca2c87d..1a2d41c81 100644
--- a/core/src/tbox/src/tbox/prefix/trace.h
+++ b/core/src/tbox/src/tbox/prefix/trace.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file trace.h
@@ -57,7 +57,7 @@ __tb_extern_c_enter__
#endif
// trace prefix
-#if defined(TB_COMPILER_IS_GCC)
+#if defined(TB_COMPILER_IS_GCC) || defined(TB_COMPILER_IS_TINYC)
# define tb_trace_p(prefix, fmt, arg ...) do { tb_trace_done(prefix, TB_TRACE_MODULE_NAME, fmt __tb_newline__, ## arg); } while (0)
# define tb_tracef_p(prefix, fmt, arg ...) do { tb_trace_done(prefix, TB_TRACE_MODULE_NAME, fmt, ## arg); } while (0)
# ifdef __tb_debug__
@@ -136,7 +136,7 @@ __tb_extern_c_enter__
*
*/
#if TB_TRACE_MODULE_DEBUG && defined(__tb_debug__)
-# if defined(TB_COMPILER_IS_GCC)
+# if defined(TB_COMPILER_IS_GCC) || defined(TB_COMPILER_IS_TINYC)
# define TB_TRACE_DEBUG
# define tb_trace_d(fmt, arg ...) tb_trace_p(__tb_prefix__, fmt, ## arg)
# define tb_tracef_d(fmt, arg ...) tb_tracef_p(__tb_prefix__, fmt, ## arg)
@@ -152,7 +152,7 @@ __tb_extern_c_enter__
# define tb_tracet_d
# endif
#else
-# if defined(TB_COMPILER_IS_GCC) || (defined(TB_COMPILER_IS_MSVC) && TB_COMPILER_VERSION_BE(13, 0))
+# if defined(TB_COMPILER_IS_GCC) || (defined(TB_COMPILER_IS_MSVC) && TB_COMPILER_VERSION_BE(13, 0)) || defined(TB_COMPILER_IS_TINYC)
# define tb_trace_d(fmt, ...)
# define tb_tracef_d(fmt, ...)
# define tb_tracet_d(fmt, ...)
@@ -163,7 +163,7 @@ __tb_extern_c_enter__
# endif
#endif
-#if defined(TB_COMPILER_IS_GCC)
+#if defined(TB_COMPILER_IS_GCC) || defined(TB_COMPILER_IS_TINYC)
# define tb_trace_i(fmt, arg ...) tb_trace_p(__tb_prefix__, fmt, ## arg)
# define tb_trace_e(fmt, arg ...) tb_trace_error_p(__tb_prefix__, fmt, ## arg)
# define tb_trace_a(fmt, arg ...) tb_trace_assert_p(__tb_prefix__, fmt, ## arg)
@@ -205,7 +205,7 @@ __tb_extern_c_enter__
#endif
// trace once
-#if defined(TB_COMPILER_IS_GCC)
+#if defined(TB_COMPILER_IS_GCC) || defined(TB_COMPILER_IS_TINYC)
# define tb_trace1_d(fmt, arg ...) do { static tb_bool_t __trace_once = tb_false; if (!__trace_once) { tb_trace_d(fmt, ## arg); __trace_once = tb_true; } } while (0)
# define tb_trace1_i(fmt, arg ...) do { static tb_bool_t __trace_once = tb_false; if (!__trace_once) { tb_trace_i(fmt, ## arg); __trace_once = tb_true; } } while (0)
# define tb_trace1_e(fmt, arg ...) do { static tb_bool_t __trace_once = tb_false; if (!__trace_once) { tb_trace_e(fmt, ## arg); __trace_once = tb_true; } } while (0)
@@ -219,6 +219,7 @@ __tb_extern_c_enter__
# define tb_trace1_w(fmt, ...) do { static tb_bool_t __trace_once = tb_false; if (!__trace_once) { tb_trace_w(fmt, __VA_ARGS__); __trace_once = tb_true; } } while (0)
#else
# define tb_trace1_i
+# define tb_trace1_w
#endif
// trace more info?
@@ -242,7 +243,7 @@ __tb_extern_c_enter__
# undef tb_trace1_a
# undef tb_trace1_w
# define TB_TRACE_MODULE_DEBUG (0)
-# if defined(TB_COMPILER_IS_GCC)
+# if defined(TB_COMPILER_IS_GCC) || defined(TB_COMPILER_IS_TINYC)
# define tb_trace_d(fmt, arg ...)
# define tb_trace_e(fmt, arg ...)
# define tb_trace_a(fmt, arg ...)
diff --git a/core/src/tbox/src/tbox/prefix/type.h b/core/src/tbox/src/tbox/prefix/type.h
index 5eec3c380..26146e40c 100644
--- a/core/src/tbox/src/tbox/prefix/type.h
+++ b/core/src/tbox/src/tbox/prefix/type.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file type.h
@@ -111,7 +111,7 @@ typedef tb_int32_t tb_wchar_t;
#if defined(TB_COMPILER_IS_MSVC)
typedef __int64 tb_int64_t;
typedef unsigned __int64 tb_uint64_t;
-#elif (TB_CPU_BITSIZE == 64)
+#elif (TB_CPU_BITSIZE == 64) && !defined(TB_COMPILER_IS_MINGW)
typedef signed long tb_int64_t;
typedef unsigned long tb_uint64_t;
#else
diff --git a/core/src/tbox/src/tbox/prefix/utils.h b/core/src/tbox/src/tbox/prefix/utils.h
index 549182a7e..5cd5151cd 100644
--- a/core/src/tbox/src/tbox/prefix/utils.h
+++ b/core/src/tbox/src/tbox/prefix/utils.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file utils.h
diff --git a/core/src/tbox/src/tbox/prefix/version.h b/core/src/tbox/src/tbox/prefix/version.h
index fe989c2d5..8df862343 100644
--- a/core/src/tbox/src/tbox/prefix/version.h
+++ b/core/src/tbox/src/tbox/prefix/version.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file version.h
@@ -45,12 +45,12 @@
#define TB_VERSION_ALTER TB_CONFIG_VERSION_ALTER
/// the build version
-#define TB_VERSION_BUILD TB_CONFIG_VERSION_BUILD
-
-/// the build version string
#ifndef TB_CONFIG_VERSION_BUILD
# define TB_CONFIG_VERSION_BUILD 0
#endif
+#define TB_VERSION_BUILD TB_CONFIG_VERSION_BUILD
+
+/// the build version string
#define TB_VERSION_BUILD_STRING __tb_mstring_ex__(TB_CONFIG_VERSION_BUILD)
/// the version string
diff --git a/core/src/tbox/src/tbox/prefix/x64/prefix.S b/core/src/tbox/src/tbox/prefix/x64/prefix.S
index 22c80181d..bb38f0813 100644
--- a/core/src/tbox/src/tbox/prefix/x64/prefix.S
+++ b/core/src/tbox/src/tbox/prefix/x64/prefix.S
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.S
diff --git a/core/src/tbox/src/tbox/prefix/x86/prefix.S b/core/src/tbox/src/tbox/prefix/x86/prefix.S
index a351181cf..1aca5289f 100644
--- a/core/src/tbox/src/tbox/prefix/x86/prefix.S
+++ b/core/src/tbox/src/tbox/prefix/x86/prefix.S
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.S
diff --git a/core/src/tbox/src/tbox/container/iterator/size.c b/core/src/tbox/src/tbox/regex/impl/impl.h
index b3696e246..f44181a1c 100644
--- a/core/src/tbox/src/tbox/container/iterator/size.c
+++ b/core/src/tbox/src/tbox/regex/impl/impl.h
@@ -16,13 +16,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
- * @file size.c
- * @ingroup container
+ * @file prefix.h
*
*/
+#ifndef TB_REGEX_IMPL_H
+#define TB_REGEX_IMPL_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
@@ -30,10 +31,18 @@
#include "prefix.h"
/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
+ * private implementation
*/
-tb_iterator_ref_t tb_iterator_make_for_size(tb_array_iterator_ref_t iterator, tb_size_t* items, tb_size_t count)
+static tb_void_t tb_regex_match_exit(tb_element_ref_t element, tb_pointer_t buff)
{
- // make iterator for the pointer array
- return tb_iterator_make_for_ptr(iterator, (tb_pointer_t*)items, count);
+ // check
+ tb_regex_match_ref_t match = (tb_regex_match_ref_t)buff;
+ tb_assert_and_check_return(match);
+
+ // exit it
+ if (match->cstr) tb_free(match->cstr);
+ match->cstr = tb_null;
+ match->size = 0;
}
+
+#endif
diff --git a/core/src/tbox/src/tbox/regex/impl/pcre.c b/core/src/tbox/src/tbox/regex/impl/pcre.c
new file mode 100644
index 000000000..a3f12611d
--- /dev/null
+++ b/core/src/tbox/src/tbox/regex/impl/pcre.c
@@ -0,0 +1,358 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
+ *
+ * @author ruki
+ * @file pcre.c
+ *
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "prefix.h"
+#define PCRE_STATIC
+#include <pcre.h>
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * types
+ */
+
+// the regex type
+typedef struct __tb_regex_t
+{
+ // the code
+ pcre* code;
+
+ // the results
+ tb_vector_ref_t results;
+
+ // the mode
+ tb_size_t mode;
+
+ // the ovector data
+ tb_int_t* ovector_data;
+
+ // the ovector maxn
+ tb_size_t ovector_maxn;
+
+ // the buffer data
+ tb_char_t* buffer_data;
+
+ // the buffer maxn
+ tb_size_t buffer_maxn;
+
+}tb_regex_t;
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * implementation
+ */
+tb_regex_ref_t tb_regex_init(tb_char_t const* pattern, tb_size_t mode)
+{
+ // check
+ tb_assert_and_check_return_val(pattern, tb_null);
+
+ // done
+ tb_bool_t ok = tb_false;
+ tb_regex_t* regex = tb_null;
+ do
+ {
+ // make regex
+ regex = (tb_regex_t*)tb_malloc0_type(tb_regex_t);
+ tb_assert_and_check_break(regex);
+
+ // init options
+ tb_int_t options = 0;//PCRE_UTF8;
+ if (mode & TB_REGEX_MODE_CASELESS) options |= PCRE_CASELESS;
+ if (mode & TB_REGEX_MODE_MULTILINE) options |= PCRE_MULTILINE;
+#ifndef __tb_debug__
+ options |= 0;//PCRE_NO_UTF_CHECK;
+#endif
+
+ // init code
+ tb_char_t const* errorstring = tb_null;
+ tb_int_t erroroffset = 0;
+ regex->code = pcre_compile(pattern, options, &errorstring, &erroroffset, tb_null);
+ if (!regex->code)
+ {
+ // trace
+ tb_trace_d("compile failed at offset %ld: %s\n", (tb_long_t)erroroffset, errorstring);
+
+ // end
+ break;
+ }
+
+ // save mode
+ regex->mode = mode;
+
+ // ok
+ ok = tb_true;
+
+ } while (0);
+
+ // failed?
+ if (!ok)
+ {
+ // exit it
+ if (regex) tb_regex_exit((tb_regex_ref_t)regex);
+ regex = tb_null;
+ }
+
+ // ok?
+ return (tb_regex_ref_t)regex;
+}
+tb_void_t tb_regex_exit(tb_regex_ref_t self)
+{
+ // check
+ tb_regex_t* regex = (tb_regex_t*)self;
+ tb_assert_and_check_return(regex);
+
+ // exit buffer data
+ if (regex->buffer_data) tb_free(regex->buffer_data);
+ regex->buffer_data = tb_null;
+ regex->buffer_maxn = 0;
+
+ // exit ovector
+ if (regex->ovector_data) tb_free(regex->ovector_data);
+ regex->ovector_data = tb_null;
+ regex->ovector_maxn = 0;
+
+ // exit results
+ if (regex->results) tb_vector_exit(regex->results);
+ regex->results = tb_null;
+
+ // exit code
+ if (regex->code) pcre_free(regex->code);
+ regex->code = tb_null;
+
+ // exit it
+ tb_free(regex);
+}
+tb_long_t tb_regex_match(tb_regex_ref_t self, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_size_t* plength, tb_vector_ref_t* presults)
+{
+ // check
+ tb_regex_t* regex = (tb_regex_t*)self;
+ tb_assert_and_check_return_val(regex && regex->code && cstr, -1);
+
+ // done
+ tb_long_t ok = -1;
+ do
+ {
+ // clear length first
+ if (plength) *plength = 0;
+
+ // end?
+ tb_check_break(start < size);
+
+ // init options
+#ifdef __tb_debug__
+ tb_uint32_t options = 0;
+#else
+ tb_uint32_t options = 0;//PCRE_NO_UTF_CHECK;
+#endif
+
+ // init ovector
+ if (!regex->ovector_data)
+ {
+ regex->ovector_maxn = 3 * 16;
+ regex->ovector_data = (tb_int_t*)tb_malloc_bytes(sizeof(tb_int_t) * regex->ovector_maxn);
+ }
+ tb_assert_and_check_break(regex->ovector_data);
+
+ // match it
+ tb_long_t count = -1;
+ while (!(count = pcre_exec(regex->code, tb_null, cstr, (tb_int_t)size, (tb_int_t)start, (tb_int_t)options, regex->ovector_data, (tb_int_t)regex->ovector_maxn)))
+ {
+ // grow ovector
+ regex->ovector_maxn <<= 1;
+ regex->ovector_data = (tb_int_t*)tb_ralloc_bytes(regex->ovector_data, sizeof(tb_int_t) * regex->ovector_maxn);
+ tb_assert_and_check_break(regex->ovector_data);
+ }
+ if (count < 0)
+ {
+ // no match?
+ tb_check_break(count != PCRE_ERROR_NOMATCH);
+
+ // trace
+ tb_trace_d("match failed at offset %lu: error: %ld\n", start, count);
+
+ // end
+ break;
+ }
+
+ // check
+ tb_assertf_and_check_break(count, "ovector has not enough space!");
+
+ // get the match offset and length
+ tb_int_t const* ovector = regex->ovector_data;
+ tb_size_t offset = (tb_size_t)ovector[0];
+ tb_size_t length = (tb_size_t)ovector[1] - ovector[0];
+ tb_assert_and_check_break(offset + length <= size);
+
+ // trace
+ tb_trace_d("matched count: %lu, offset: %lu, length: %lu", count, offset, length);
+
+ // save results
+ if (presults)
+ {
+ // init results if not exists
+ tb_vector_ref_t results = *presults;
+ if (!results)
+ {
+ // init it
+ if (!regex->results) regex->results = tb_vector_init(16, tb_element_mem(sizeof(tb_regex_match_t), tb_regex_match_exit, tb_null));
+
+ // save it
+ *presults = results = regex->results;
+ }
+ tb_assert_and_check_break(results);
+
+ // clear it first
+ tb_vector_clear(results);
+
+ // done
+ tb_long_t i = 0;
+ tb_regex_match_t entry;
+ for (i = 0; i < count; i++)
+ {
+ // get substring offset and length
+ tb_size_t substr_offset = ovector[i << 1];
+ tb_size_t substr_length = ovector[(i << 1) + 1] - ovector[i << 1];
+ tb_assert_and_check_break(substr_offset + substr_length <= size);
+
+ // make match entry
+ entry.cstr = tb_strndup(cstr + substr_offset, substr_length);
+ entry.size = substr_length;
+ entry.start = substr_offset;
+ tb_assert_and_check_break(entry.cstr);
+
+ // trace
+ tb_trace_d(" matched: [%lu, %lu]: %s", entry.start, entry.size, entry.cstr);
+
+ // append it
+ tb_vector_insert_tail(results, &entry);
+ }
+ tb_assert_and_check_break(i == count);
+ }
+
+ // save length
+ if (plength) *plength = length;
+
+ // ok
+ ok = offset;
+
+ } while (0);
+
+ // ok?
+ return ok;
+}
+tb_char_t const* tb_regex_replace(tb_regex_ref_t self, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_char_t const* replace_cstr, tb_size_t replace_size, tb_size_t* plength)
+{
+ // check
+ tb_regex_t* regex = (tb_regex_t*)self;
+ tb_assert_and_check_return_val(regex && cstr && replace_cstr, tb_null);
+
+ // done
+ tb_char_t const* result = tb_null;
+ do
+ {
+ // clear length first
+ if (plength) *plength = 0;
+
+ // end?
+ tb_check_break(start < size);
+
+ // init buffer
+ if (!regex->buffer_data)
+ {
+ regex->buffer_maxn = tb_max(size + replace_size + 64, 256);
+ regex->buffer_data = tb_malloc_cstr(regex->buffer_maxn);
+ }
+ tb_assert_and_check_break(regex->buffer_data);
+
+ // copy cstr
+ tb_memcpy(regex->buffer_data, cstr, size);
+ regex->buffer_data[size] = '\0';
+
+ // done
+ tb_size_t count = 0;
+ tb_long_t suboffset = start;
+ tb_size_t sublength = 0;
+ tb_size_t length = 0;
+ tb_vector_ref_t results = tb_null;
+ while ((suboffset = tb_regex_match(self, regex->buffer_data, size, suboffset + sublength, &sublength, &results)) >= 0 && results)
+ {
+ // trace
+ tb_trace_d("replace: match: [%lu, %lu]", suboffset, sublength);
+
+ // calculate substring end
+ tb_size_t subend = suboffset + sublength;
+ tb_assert_and_check_break(subend <= size);
+
+ // update length
+ length = size - sublength + replace_size;
+
+ // grow buffer
+ if (regex->buffer_maxn < length)
+ {
+ regex->buffer_maxn = tb_max(regex->buffer_maxn << 1, length);
+ regex->buffer_data = tb_ralloc_cstr(regex->buffer_data, regex->buffer_maxn + 1);
+ }
+ tb_assert_and_check_break(regex->buffer_data);
+
+ // replace this match
+ if (subend < size) tb_memmov(regex->buffer_data + suboffset + replace_size, regex->buffer_data + subend, size - subend);
+ tb_memcpy(regex->buffer_data + suboffset, replace_cstr, replace_size);
+ regex->buffer_data[length] = '\0';
+
+ // trace
+ tb_trace_d("replace: => %s", regex->buffer_data);
+
+ // update matched count
+ count++;
+
+ // global replace?
+ tb_check_break(regex->mode & TB_REGEX_MODE_GLOBAL);
+
+ // update size
+ size = length;
+ sublength = replace_size;
+ }
+
+ // check
+ tb_check_break(count);
+ tb_assert_and_check_break(length < regex->buffer_maxn);
+
+ // end
+ regex->buffer_data[length] = '\0';
+
+ // trace
+ tb_trace_d(" replace: [%lu]: %s", length, regex->buffer_data);
+
+ // save length
+ if (plength) *plength = length;
+
+ // ok
+ result = (tb_char_t const*)regex->buffer_data;
+
+ } while (0);
+
+ // ok?
+ return result;
+}
diff --git a/core/src/tbox/src/tbox/regex/impl/pcre2.c b/core/src/tbox/src/tbox/regex/impl/pcre2.c
new file mode 100644
index 000000000..5dac2372c
--- /dev/null
+++ b/core/src/tbox/src/tbox/regex/impl/pcre2.c
@@ -0,0 +1,352 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
+ *
+ * @author ruki
+ * @file pcre2.c
+ *
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "prefix.h"
+#define PCRE2_STATIC
+#include <pcre2.h>
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * types
+ */
+
+// the regex type
+typedef struct __tb_regex_t
+{
+ // the code
+ pcre2_code* code;
+
+ // the match data
+ pcre2_match_data* match_data;
+
+ // the results
+ tb_vector_ref_t results;
+
+ // the mode
+ tb_size_t mode;
+
+ // the buffer data
+ PCRE2_UCHAR* buffer_data;
+
+ // the buffer maxn
+ tb_size_t buffer_maxn;
+
+}tb_regex_t;
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * implementation
+ */
+tb_regex_ref_t tb_regex_init(tb_char_t const* pattern, tb_size_t mode)
+{
+ // check
+ tb_assert_and_check_return_val(pattern, tb_null);
+
+ // done
+ tb_bool_t ok = tb_false;
+ tb_regex_t* regex = tb_null;
+ do
+ {
+ // make regex
+ regex = (tb_regex_t*)tb_malloc0_type(tb_regex_t);
+ tb_assert_and_check_break(regex);
+
+ // init options
+ tb_uint32_t options = PCRE2_UTF;
+ if (mode & TB_REGEX_MODE_CASELESS) options |= PCRE2_CASELESS;
+ if (mode & TB_REGEX_MODE_MULTILINE) options |= PCRE2_MULTILINE;
+#ifndef __tb_debug__
+ options |= PCRE2_NO_UTF_CHECK;
+#endif
+
+ // init code
+ tb_int_t errornumber;
+ PCRE2_SIZE erroroffset;
+ regex->code = pcre2_compile((PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED, options, &errornumber, &erroroffset, tb_null);
+ if (!regex->code)
+ {
+#if defined(__tb_debug__) && !defined(TB_CONFIG_OS_WINDOWS) // FIXME: _sprintf undefined link error for vs2015 on windows
+ // get error info
+ PCRE2_UCHAR info[256];
+ pcre2_get_error_message(errornumber, info, sizeof(info));
+
+ // trace
+ tb_trace_d("compile failed at offset %ld: %s\n", (tb_long_t)erroroffset, info);
+#endif
+
+ // end
+ break;
+ }
+
+ // init match data
+ regex->match_data = pcre2_match_data_create_from_pattern(regex->code, tb_null);
+ tb_assert_and_check_break(regex->match_data);
+
+ // save mode
+ regex->mode = mode;
+
+ // ok
+ ok = tb_true;
+
+ } while (0);
+
+ // failed?
+ if (!ok)
+ {
+ // exit it
+ if (regex) tb_regex_exit((tb_regex_ref_t)regex);
+ regex = tb_null;
+ }
+
+ // ok?
+ return (tb_regex_ref_t)regex;
+}
+tb_void_t tb_regex_exit(tb_regex_ref_t self)
+{
+ // check
+ tb_regex_t* regex = (tb_regex_t*)self;
+ tb_assert_and_check_return(regex);
+
+ // exit buffer
+ if (regex->buffer_data) tb_free(regex->buffer_data);
+ regex->buffer_data = tb_null;
+ regex->buffer_maxn = 0;
+
+ // exit results
+ if (regex->results) tb_vector_exit(regex->results);
+ regex->results = tb_null;
+
+ // exit match data
+ if (regex->match_data) pcre2_match_data_free(regex->match_data);
+ regex->match_data = tb_null;
+
+ // exit code
+ if (regex->code) pcre2_code_free(regex->code);
+ regex->code = tb_null;
+
+ // exit it
+ tb_free(regex);
+}
+tb_long_t tb_regex_match(tb_regex_ref_t self, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_size_t* plength, tb_vector_ref_t* presults)
+{
+ // check
+ tb_regex_t* regex = (tb_regex_t*)self;
+ tb_assert_and_check_return_val(regex && regex->code && regex->match_data && cstr, -1);
+
+ // done
+ tb_long_t ok = -1;
+ do
+ {
+ // clear length first
+ if (plength) *plength = 0;
+
+ // end?
+ tb_check_break(start < size);
+
+ // init options
+#ifdef __tb_debug__
+ tb_uint32_t options = 0;
+#else
+ tb_uint32_t options = PCRE2_NO_UTF_CHECK;
+#endif
+
+ // match it
+ tb_long_t count = pcre2_match(regex->code, (PCRE2_SPTR)cstr, (PCRE2_SIZE)size, (PCRE2_SIZE)start, options, regex->match_data, tb_null);
+ if (count < 0)
+ {
+ // no match?
+ tb_check_break(count != PCRE2_ERROR_NOMATCH);
+
+#if defined(__tb_debug__) && !defined(TB_CONFIG_OS_WINDOWS)
+ // get error info
+ PCRE2_UCHAR info[256];
+ pcre2_get_error_message(count, info, sizeof(info));
+
+ // trace
+ tb_trace_d("match failed at offset %lu: error: %ld, %s\n", start, count, info);
+#endif
+
+ // end
+ break;
+ }
+
+ // check
+ tb_assertf_and_check_break(count, "ovector has not enough space!");
+
+ // get output vector
+ PCRE2_SIZE* ovector = pcre2_get_ovector_pointer(regex->match_data);
+ tb_assert_and_check_break(ovector);
+
+ // get the match offset and length
+ tb_size_t offset = (tb_size_t)ovector[0];
+ tb_size_t length = (tb_size_t)ovector[1] - ovector[0];
+ tb_assert_and_check_break(offset + length <= size);
+
+ // trace
+ tb_trace_d("matched count: %lu, offset: %lu, length: %lu", count, offset, length);
+
+ // save results
+ if (presults)
+ {
+ // init results if not exists
+ tb_vector_ref_t results = *presults;
+ if (!results)
+ {
+ // init it
+ if (!regex->results) regex->results = tb_vector_init(16, tb_element_mem(sizeof(tb_regex_match_t), tb_regex_match_exit, tb_null));
+
+ // save it
+ *presults = results = regex->results;
+ }
+ tb_assert_and_check_break(results);
+
+ // clear it first
+ tb_vector_clear(results);
+
+ // done
+ tb_long_t i = 0;
+ tb_regex_match_t entry;
+ for (i = 0; i < count; i++)
+ {
+ // get substring offset and length
+ tb_size_t substr_offset = ovector[i << 1];
+ tb_size_t substr_length = ovector[(i << 1) + 1] - ovector[i << 1];
+ tb_assert_and_check_break(substr_offset + substr_length <= size);
+
+ // make match entry
+ entry.cstr = tb_strndup(cstr + substr_offset, substr_length);
+ entry.size = substr_length;
+ entry.start = substr_offset;
+ tb_assert_and_check_break(entry.cstr);
+
+ // trace
+ tb_trace_d(" matched: [%lu, %lu]: %s", entry.start, entry.size, entry.cstr);
+
+ // append it
+ tb_vector_insert_tail(results, &entry);
+ }
+ tb_assert_and_check_break(i == count);
+ }
+
+ // save length
+ if (plength) *plength = length;
+
+ // ok
+ ok = offset;
+
+ } while (0);
+
+ // ok?
+ return ok;
+}
+tb_char_t const* tb_regex_replace(tb_regex_ref_t self, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_char_t const* replace_cstr, tb_size_t replace_size, tb_size_t* plength)
+{
+ // check
+ tb_regex_t* regex = (tb_regex_t*)self;
+ tb_assert_and_check_return_val(regex && regex->code && cstr && replace_cstr, tb_null);
+
+ // done
+ tb_char_t const* result = tb_null;
+ do
+ {
+ // clear length first
+ if (plength) *plength = 0;
+
+ // end?
+ tb_check_break(start < size);
+
+ // init options
+#ifdef __tb_debug__
+ tb_uint32_t options = 0;
+#else
+ tb_uint32_t options = PCRE2_NO_UTF_CHECK;
+#endif
+ if (regex->mode & TB_REGEX_MODE_GLOBAL) options |= PCRE2_SUBSTITUTE_GLOBAL;
+
+ // init buffer
+ if (!regex->buffer_data)
+ {
+ regex->buffer_maxn = tb_max(size + replace_size + 64, 256);
+ regex->buffer_data = (PCRE2_UCHAR*)tb_malloc_bytes(regex->buffer_maxn);
+ }
+ tb_assert_and_check_break(regex->buffer_data);
+
+ // done
+ tb_long_t ok = -1;
+ PCRE2_SIZE length = 0;
+ while (1)
+ {
+ // replace it
+ length = (PCRE2_SIZE)regex->buffer_maxn;
+ ok = pcre2_substitute(regex->code, (PCRE2_SPTR)cstr, (PCRE2_SIZE)size, (PCRE2_SIZE)start, options, tb_null, tb_null, (PCRE2_SPTR)replace_cstr, (PCRE2_SIZE)replace_size, regex->buffer_data, &length);
+
+ // no space?
+ if (ok == PCRE2_ERROR_NOMEMORY)
+ {
+ // grow buffer
+ regex->buffer_maxn <<= 1;
+ regex->buffer_data = (PCRE2_UCHAR*)tb_ralloc_bytes(regex->buffer_data, regex->buffer_maxn);
+ tb_assert_and_check_break(regex->buffer_data);
+ }
+ // failed
+ else if (ok < 0)
+ {
+#if defined(__tb_debug__) && !defined(TB_CONFIG_OS_WINDOWS)
+ // get error info
+ PCRE2_UCHAR info[256];
+ pcre2_get_error_message(ok, info, sizeof(info));
+
+ // trace
+ tb_trace_d("replace failed at offset %lu: error: %ld, %s\n", start, ok, info);
+#endif
+
+ // end
+ break;
+ }
+ else break;
+ }
+
+ // check
+ tb_check_break(ok > 0);
+ tb_assert_and_check_break(length < regex->buffer_maxn);
+
+ // end
+ regex->buffer_data[length] = '\0';
+
+ // trace
+ tb_trace_d(" replace: [%lu]: %s", length, regex->buffer_data);
+
+ // save length
+ if (plength) *plength = (tb_size_t)length;
+
+ // ok
+ result = (tb_char_t const*)regex->buffer_data;
+
+ } while (0);
+
+ // ok?
+ return result;
+}
diff --git a/core/src/tbox/src/tbox/regex/impl/prefix.h b/core/src/tbox/src/tbox/regex/impl/prefix.h
new file mode 100644
index 000000000..55010ed07
--- /dev/null
+++ b/core/src/tbox/src/tbox/regex/impl/prefix.h
@@ -0,0 +1,38 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
+ *
+ * @author ruki
+ * @file prefix.h
+ *
+ */
+#ifndef TB_REGEX_IMPL_PREFIX_H
+#define TB_REGEX_IMPL_PREFIX_H
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "../prefix.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * types
+ */
+
+
+#endif
diff --git a/core/src/tbox/src/tbox/platform/deprecated/prefix.h b/core/src/tbox/src/tbox/regex/prefix.h
index 722b6448d..7ae5011f7 100644
--- a/core/src/tbox/src/tbox/platform/deprecated/prefix.h
+++ b/core/src/tbox/src/tbox/regex/prefix.h
@@ -16,19 +16,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
+ * @ingroup regex
*
*/
-#ifndef TB_PLATFORM_DEPRECATED_PREFIX_H
-#define TB_PLATFORM_DEPRECATED_PREFIX_H
+#ifndef TB_REGEX_PREFIX_H
+#define TB_REGEX_PREFIX_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
#include "../prefix.h"
+#include "../libc/libc.h"
+#include "../container/container.h"
#endif
diff --git a/core/src/tbox/src/tbox/regex/regex.c b/core/src/tbox/src/tbox/regex/regex.c
new file mode 100644
index 000000000..ced832263
--- /dev/null
+++ b/core/src/tbox/src/tbox/regex/regex.c
@@ -0,0 +1,205 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
+ *
+ * @author ruki
+ * @file regex.c
+ * @ingroup regex
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * trace
+ */
+#define TB_TRACE_MODULE_NAME "regex"
+#define TB_TRACE_MODULE_DEBUG (1)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "regex.h"
+#include "impl/impl.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * implementation
+ */
+#if defined(TB_CONFIG_PACKAGE_HAVE_PCRE2)
+# include "impl/pcre2.c"
+#elif defined(TB_CONFIG_PACKAGE_HAVE_PCRE)
+# include "impl/pcre.c"
+#elif defined(TB_CONFIG_POSIX_HAVE_REGCOMP) \
+ && defined(TB_CONFIG_POSIX_HAVE_REGEXEC)
+# include "../platform/posix/regex.c"
+#else
+tb_regex_ref_t tb_regex_init(tb_char_t const* pattern, tb_size_t mode)
+{
+ tb_assert_noimpl();
+ return tb_null;
+}
+tb_void_t tb_regex_exit(tb_regex_ref_t regex)
+{
+ tb_assert_noimpl();
+}
+tb_long_t tb_regex_match(tb_regex_ref_t regex, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_size_t* plength, tb_vector_ref_t* presults)
+{
+ tb_assert_noimpl();
+ return -1;
+}
+tb_char_t const* tb_regex_replace(tb_regex_ref_t regex, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_char_t const* replace_cstr, tb_size_t replace_size, tb_size_t* plength)
+{
+ tb_assert_noimpl();
+ return tb_null;
+}
+#endif
+tb_long_t tb_regex_match_cstr(tb_regex_ref_t regex, tb_char_t const* cstr, tb_size_t start, tb_size_t* plength, tb_vector_ref_t* presults)
+{
+ // check
+ tb_assert_and_check_return_val(cstr, -1);
+
+ // done
+ return tb_regex_match(regex, cstr, tb_strlen(cstr), start, plength, presults);
+}
+tb_vector_ref_t tb_regex_match_simple(tb_regex_ref_t regex, tb_char_t const* cstr)
+{
+ // check
+ tb_assert_and_check_return_val(cstr, tb_null);
+
+ // done
+ tb_vector_ref_t results = tb_null;
+ return tb_regex_match(regex, cstr, tb_strlen(cstr), 0, tb_null, &results) >= 0? results : tb_null;
+}
+tb_char_t const* tb_regex_replace_cstr(tb_regex_ref_t regex, tb_char_t const* cstr, tb_size_t start, tb_char_t const* replace_cstr, tb_size_t* plength)
+{
+ // check
+ tb_assert_and_check_return_val(cstr && replace_cstr, tb_null);
+
+ // done
+ return tb_regex_replace(regex, cstr, tb_strlen(cstr), start, replace_cstr, tb_strlen(replace_cstr), plength);
+}
+tb_char_t const* tb_regex_replace_simple(tb_regex_ref_t regex, tb_char_t const* cstr, tb_char_t const* replace_cstr)
+{
+ // check
+ tb_assert_and_check_return_val(cstr && replace_cstr, tb_null);
+
+ // done
+ return tb_regex_replace(regex, cstr, tb_strlen(cstr), 0, replace_cstr, tb_strlen(replace_cstr), tb_null);
+}
+tb_long_t tb_regex_match_done(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_size_t* plength, tb_vector_ref_t* presults)
+{
+ // clear results first
+ if (presults) *presults = tb_null;
+
+ // init regex
+ tb_long_t ok = -1;
+ tb_regex_ref_t regex = tb_regex_init(pattern, mode);
+ if (regex)
+ {
+ // init results
+ tb_vector_ref_t results = tb_vector_init(16, tb_element_mem(sizeof(tb_regex_match_t), tb_regex_match_exit, tb_null));
+ if (results)
+ {
+ // match regex
+ ok = tb_regex_match(regex, cstr, size, start, plength, &results);
+
+ // ok?
+ if (ok >= 0)
+ {
+ // save results
+ if (presults)
+ {
+ *presults = results;
+ results = tb_null;
+ }
+ }
+
+ // exit results
+ if (results) tb_vector_exit(results);
+ results = tb_null;
+ }
+
+ // exit regex
+ tb_regex_exit(regex);
+ }
+
+ // ok?
+ return ok;
+}
+tb_long_t tb_regex_match_done_cstr(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr, tb_size_t start, tb_size_t* plength, tb_vector_ref_t* presults)
+{
+ // check
+ tb_assert_and_check_return_val(cstr, -1);
+
+ // done
+ return tb_regex_match_done(pattern, mode, cstr, tb_strlen(cstr), start, plength, presults);
+}
+tb_vector_ref_t tb_regex_match_done_simple(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr)
+{
+ // check
+ tb_assert_and_check_return_val(cstr, tb_null);
+
+ // done
+ tb_vector_ref_t results = tb_null;
+ return tb_regex_match_done(pattern, mode, cstr, tb_strlen(cstr), 0, tb_null, &results) >= 0? results : tb_null;
+}
+tb_char_t const* tb_regex_replace_done(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_char_t const* replace_cstr, tb_size_t replace_size, tb_size_t* plength)
+{
+ // clear length first
+ if (plength) *plength = 0;
+
+ // init regex
+ tb_char_t* result = tb_null;
+ tb_regex_ref_t regex = tb_regex_init(pattern, mode);
+ if (regex)
+ {
+ // replace regex
+ tb_size_t result_size = 0;
+ tb_char_t const* result_cstr = tb_regex_replace(regex, cstr, size, start, replace_cstr, replace_size, &result_size);
+ if (result_cstr && result_size)
+ {
+ // save result
+ result = tb_strndup(result_cstr, result_size);
+ if (result)
+ {
+ // save length
+ if (plength) *plength = result_size;
+ }
+ }
+
+ // exit regex
+ tb_regex_exit(regex);
+ }
+
+ // ok?
+ return result;
+}
+tb_char_t const* tb_regex_replace_done_cstr(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr, tb_size_t start, tb_char_t const* replace_cstr, tb_size_t* plength)
+{
+ // check
+ tb_assert_and_check_return_val(cstr && replace_cstr, tb_null);
+
+ // done
+ return tb_regex_replace_done(pattern, mode, cstr, tb_strlen(cstr), start, replace_cstr, tb_strlen(replace_cstr), tb_null);
+}
+tb_char_t const* tb_regex_replace_done_simple(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr, tb_char_t const* replace_cstr)
+{
+ // check
+ tb_assert_and_check_return_val(cstr && replace_cstr, tb_null);
+
+ // done
+ return tb_regex_replace_done(pattern, mode, cstr, tb_strlen(cstr), 0, replace_cstr, tb_strlen(replace_cstr), tb_null);
+}
diff --git a/core/src/tbox/src/tbox/regex/regex.h b/core/src/tbox/src/tbox/regex/regex.h
new file mode 100644
index 000000000..8ee6b4300
--- /dev/null
+++ b/core/src/tbox/src/tbox/regex/regex.h
@@ -0,0 +1,422 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
+ *
+ * @author ruki
+ * @file regex.h
+ * @defgroup regex
+ */
+#ifndef TB_REGEX_H
+#define TB_REGEX_H
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "prefix.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_enter__
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * types
+ */
+
+/// the regex ref type
+typedef __tb_typeref__(regex);
+
+/// the regex match type
+typedef struct _tb_regex_match_t
+{
+ /// the c-string data
+ tb_char_t const* cstr;
+
+ /// the c-string size
+ tb_size_t size;
+
+ /// the matched start position
+ tb_size_t start;
+
+}tb_regex_match_t, *tb_regex_match_ref_t;
+
+/// the regex mode enum
+typedef enum __tb_regex_mode_e
+{
+ TB_REGEX_MODE_NONE = 0 //!< the default mode
+, TB_REGEX_MODE_CASELESS = 1 //!< do caseless matching
+, TB_REGEX_MODE_MULTILINE = 2 //!< ^ and $ match newlines within data
+, TB_REGEX_MODE_GLOBAL = 4 //!< global replace all
+
+}tb_regex_mode_e;
+
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * interfaces
+ */
+
+/*! init regex
+ *
+ * @param pattern the regex pattern
+ * @param mode the regex mode, uses the default mode if be zero
+ *
+ * @return the regex
+ */
+tb_regex_ref_t tb_regex_init(tb_char_t const* pattern, tb_size_t mode);
+
+/*! exit regex
+ *
+ * @param regex the regex
+ */
+tb_void_t tb_regex_exit(tb_regex_ref_t regex);
+
+/*! match the given c-string and size by regex
+ *
+ * @param regex the regex
+ * @param cstr the c-string data
+ * @param size the c-string size
+ * @param start the start position
+ * @param plength the matched length pointer, do not get it if be null
+ * @param presults the results pointer, only match it if be null
+ *
+ * @return the matched position, not match: -1
+ */
+tb_long_t tb_regex_match(tb_regex_ref_t regex, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_size_t* plength, tb_vector_ref_t* presults);
+
+/*! match the given c-string by regex
+ *
+ * @code
+
+ // init regex
+ tb_regex_ref_t regex = tb_regex_init("\\w+", 0);
+ if (regex)
+ {
+ // match single
+ //
+ // results: "hello"
+ //
+ tb_vector_ref_t results = tb_null;
+ if (tb_regex_match_cstr(regex, "hello world", 0, tb_null, &results) >= 0 && results)
+ {
+ // show results
+ tb_for_all_if (tb_regex_match_ref_t, entry, results, entry)
+ {
+ // trace
+ tb_trace_i("cstr: %s, size: %lu, start: %lu", entry->cstr, entry->size, entry->start);
+ }
+ }
+
+ // match global
+ //
+ // results: "hello"
+ // results: "world"
+ //
+ tb_long_t start = 0;
+ tb_size_t length = 0;
+ tb_vector_ref_t results = tb_null;
+ while ((start = tb_regex_match_cstr(regex, "hello world", start + length, &length, &results)) >= 0 && results)
+ {
+ // show results
+ tb_for_all_if (tb_regex_match_ref_t, entry, results, entry)
+ {
+ // trace
+ tb_trace_i("cstr: %s, size: %lu, start: %lu", entry->cstr, entry->size, entry->start);
+ }
+ }
+
+ // exit regex
+ tb_regex_exit(regex);
+ }
+ * @endcode
+ *
+ * @param regex the regex
+ * @param cstr the c-string
+ * @param start the start position
+ * @param plength the matched length pointer, do not get it if be null
+ * @param presults the results pointer, only match it if be null
+ *
+ * @return the matched position, not match: -1
+ */
+tb_long_t tb_regex_match_cstr(tb_regex_ref_t regex, tb_char_t const* cstr, tb_size_t start, tb_size_t* plength, tb_vector_ref_t* presults);
+
+/*! simply match the given c-string by regex
+ *
+ * @note only supports single match
+ *
+ * @code
+
+ // init regex
+ tb_regex_ref_t regex = tb_regex_init("\\w+", 0);
+ if (regex)
+ {
+ // match single
+ //
+ // results: "hello"
+ //
+ tb_vector_ref_t results = tb_regex_match_simple(regex, "hello world");
+ if (results)
+ {
+ // show results
+ tb_for_all_if (tb_regex_match_ref_t, entry, results, entry)
+ {
+ // trace
+ tb_trace_i("cstr: %s, size: %lu, start: %lu", entry->cstr, entry->size, entry->start);
+ }
+ }
+
+ // exit regex
+ tb_regex_exit(regex);
+ }
+ * @endcode
+ *
+ * @param regex the regex
+ * @param cstr the c-string
+ *
+ * @return the matched results
+ */
+tb_vector_ref_t tb_regex_match_simple(tb_regex_ref_t regex, tb_char_t const* cstr);
+
+/*! replace the given c-string and size by regex
+ *
+ * @param regex the regex
+ * @param cstr the c-string data
+ * @param size the c-string size
+ * @param start the start position
+ * @param replace_cstr the replacement c-string data
+ * @param replace_size the replacement c-string size
+ * @param plength the result c-string length pointer, do not get it if be null
+ *
+ * @return the result c-string
+ */
+tb_char_t const* tb_regex_replace(tb_regex_ref_t regex, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_char_t const* replace_cstr, tb_size_t replace_size, tb_size_t* plength);
+
+/*! replace the given c-string by regex
+ *
+ * @param regex the regex
+ * @param cstr the c-string data
+ * @param start the start position
+ * @param replace_cstr the replacement c-string data
+ * @param plength the result c-string length pointer, do not get it if be null
+ *
+ * @return the result c-string
+ */
+tb_char_t const* tb_regex_replace_cstr(tb_regex_ref_t regex, tb_char_t const* cstr, tb_size_t start, tb_char_t const* replace_cstr, tb_size_t* plength);
+
+/*! simply replace the given c-string by regex
+ *
+ * @code
+
+ // init regex
+ tb_regex_ref_t regex = tb_regex_init("\\w+", 0);
+ if (regex)
+ {
+ // match single
+ //
+ // results: "hi world"
+ //
+ tb_char_t const* results = tb_regex_replace_simple(regex, "hello world", "hi");
+ if (results)
+ {
+ // trace
+ tb_trace_i("results: %s", results);
+ }
+
+ // exit regex
+ tb_regex_exit(regex);
+ }
+ * @endcode
+ *
+ * @param regex the regex
+ * @param cstr the c-string data
+ * @param replace_cstr the replacement c-string data
+ *
+ * @return the result c-string
+ */
+tb_char_t const* tb_regex_replace_simple(tb_regex_ref_t regex, tb_char_t const* cstr, tb_char_t const* replace_cstr);
+
+/*! match the given c-string and size by the given regex pattern
+ *
+ * @param pattern the regex pattern
+ * @param mode the regex mode, uses the default mode if be zero
+ * @param cstr the c-string data
+ * @param size the c-string size
+ * @param start the start position
+ * @param plength the matched length pointer, do not get it if be null
+ * @param presults the results pointer, only match it if be null
+ * @note we need exit it manually
+ *
+ * @return the matched position, not match: -1
+ */
+tb_long_t tb_regex_match_done(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_size_t* plength, tb_vector_ref_t* presults);
+
+/*! match the given c-string by the given regex pattern
+ *
+ * @code
+
+ // match single
+ //
+ // results: "hello"
+ //
+ tb_vector_ref_t results = tb_null;
+ if (tb_regex_match_done_cstr("\\w+", 0, "hello world", 0, tb_null, &results) >= 0 && results)
+ {
+ // show results
+ tb_for_all_if (tb_regex_match_ref_t, entry, results, entry)
+ {
+ // trace
+ tb_trace_i("cstr: %s, size: %lu, start: %lu", entry->cstr, entry->size, entry->start);
+ }
+
+ // exit results
+ tb_vector_exit(results);
+ }
+
+ // match global
+ //
+ // results: "hello"
+ // results: "world"
+ //
+ tb_long_t start = 0;
+ tb_size_t length = 0;
+ tb_vector_ref_t results = tb_null;
+ while ((start = tb_regex_match_done_cstr("\\w+", 0, "hello world", start + length, &length, &results)) >= 0 && results)
+ {
+ // show results
+ tb_for_all_if (tb_regex_match_ref_t, entry, results, entry)
+ {
+ // trace
+ tb_trace_i("cstr: %s, size: %lu, start: %lu", entry->cstr, entry->size, entry->start);
+ }
+
+ // exit results
+ tb_vector_exit(results);
+ }
+
+ * @endcode
+ *
+ * @param pattern the regex pattern
+ * @param mode the regex mode, uses the default mode if be zero
+ * @param cstr the c-string data
+ * @param start the start position
+ * @param plength the matched length pointer, do not get it if be null
+ * @param presults the results pointer, only match it if be null
+ * @note we need exit it manually
+ *
+ * @return the matched position, not match: -1
+ */
+tb_long_t tb_regex_match_done_cstr(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr, tb_size_t start, tb_size_t* plength, tb_vector_ref_t* presults);
+
+/*! simply match the given c-string by the given regex pattern
+ *
+ * @note only supports single match
+ *
+ * @code
+
+ // match single
+ //
+ // results: "hello"
+ //
+ tb_vector_ref_t results = tb_regex_match_done_simple("\\w+", 0, "hello world");
+ if (results)
+ {
+ // show results
+ tb_for_all_if (tb_regex_match_ref_t, entry, results, entry)
+ {
+ // trace
+ tb_trace_i("cstr: %s, size: %lu, start: %lu", entry->cstr, entry->size, entry->start);
+ }
+
+ // exit results
+ tb_vector_exit(results);
+ }
+
+ * @endcode
+ *
+ * @param pattern the regex pattern
+ * @param mode the regex mode, uses the default mode if be zero
+ * @param cstr the c-string data
+ *
+ * @return the matched results, we need exit it manually
+ */
+tb_vector_ref_t tb_regex_match_done_simple(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr);
+
+/*! replace the given c-string and size by the given regex pattern
+ *
+ * @param pattern the regex pattern
+ * @param mode the regex mode, uses the default mode if be zero
+ * @param cstr the c-string data
+ * @param size the c-string size
+ * @param start the start position
+ * @param replace_cstr the replacement c-string data
+ * @param replace_size the replacement c-string size
+ * @param plength the result c-string length pointer, do not get it if be null
+ *
+ * @return the result c-string
+ */
+tb_char_t const* tb_regex_replace_done(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_char_t const* replace_cstr, tb_size_t replace_size, tb_size_t* plength);
+
+/*! replace the given c-string by the given regex pattern
+ *
+ * @param pattern the regex pattern
+ * @param mode the regex mode, uses the default mode if be zero
+ * @param cstr the c-string data
+ * @param start the start position
+ * @param replace_cstr the replacement c-string data
+ * @param plength the result c-string length pointer, do not get it if be null
+ *
+ * @return the result c-string
+ */
+tb_char_t const* tb_regex_replace_done_cstr(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr, tb_size_t start, tb_char_t const* replace_cstr, tb_size_t* plength);
+
+/*! simply replace the given c-string by the given regex pattern
+ *
+ * @code
+
+ // replace single
+ //
+ // results: "hi world"
+ //
+ tb_char_t const* results = tb_regex_replace_done_simple("\\w+", 0, "hello world", "hi");
+ if (results)
+ {
+ // trace
+ tb_trace_i("results: %s", results);
+
+ // exit results
+ tb_free(results);
+ }
+
+ * @endcode
+ *
+ * @param pattern the regex pattern
+ * @param mode the regex mode, uses the default mode if be zero
+ * @param cstr the c-string data
+ * @param replace_cstr the replacement c-string data
+ *
+ * @return the result c-string, @note we need free it manually
+ */
+tb_char_t const* tb_regex_replace_done_simple(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr, tb_char_t const* replace_cstr);
+
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_leave__
+
+#endif
diff --git a/core/src/tbox/src/tbox/stream/deprecated/async_stream.c b/core/src/tbox/src/tbox/stream/deprecated/async_stream.c
deleted file mode 100644
index 3905b5f0d..000000000
--- a/core/src/tbox/src/tbox/stream/deprecated/async_stream.c
+++ /dev/null
@@ -1,1341 +0,0 @@
-/*!The Treasure Box Library
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
- *
- * @author ruki
- * @file async_stream.c
- * @ingroup stream
- *
- */
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * trace
- */
-#define TB_TRACE_MODULE_NAME "async_stream"
-#define TB_TRACE_MODULE_DEBUG (1)
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
- */
-#include "async_stream.h"
-#include "impl/async_stream/prefix.h"
-#include "../../network/network.h"
-#include "../../platform/platform.h"
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
- */
-static tb_bool_t tb_async_stream_cache_sync_func(tb_async_stream_ref_t stream, tb_size_t state, tb_byte_t const* data, tb_size_t real, tb_size_t size, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl && impl->sync && impl->wcache_and.sync.func, tb_false);
-
- // move cache
- if (real) tb_buffer_memmov(&impl->wcache_data, real);
-
- // not finished? continue it
- if (state == TB_STATE_OK && real < size) return tb_true;
-
- // not finished? continue it
- tb_bool_t ok = tb_false;
- if (state == TB_STATE_OK && real < size) ok = tb_true;
- // ok? sync it
- else if (state == TB_STATE_OK && real == size)
- {
- // check
- tb_assert_and_check_return_val(!tb_buffer_size(&impl->wcache_data), tb_false);
-
- // post sync
- ok = impl->sync(stream, impl->wcache_and.sync.bclosing, impl->wcache_and.sync.func, priv);
-
- // failed? done func
- if (!ok) ok = impl->wcache_and.sync.func(stream, TB_STATE_UNKNOWN_ERROR, impl->wcache_and.sync.bclosing, priv);
- }
- // failed?
- else
- {
- // failed? done func
- ok = impl->wcache_and.sync.func(stream, state != TB_STATE_OK? state : TB_STATE_UNKNOWN_ERROR, impl->wcache_and.sync.bclosing, priv);
- }
-
- // ok?
- return ok;
-}
-static tb_bool_t tb_async_stream_cache_writ_func(tb_async_stream_ref_t stream, tb_size_t state, tb_byte_t const* data, tb_size_t real, tb_size_t size, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl && impl->wcache_and.writ.func, tb_false);
-
- // done
- tb_bool_t bwrit = tb_true;
- do
- {
- // check
- tb_check_break(state == TB_STATE_OK);
-
- // finished?
- if (real == size)
- {
- // trace
- tb_trace_d("cache: writ: %lu: ok", impl->wcache_and.writ.size);
-
- // clear cache
- tb_buffer_clear(&impl->wcache_data);
-
- // done func
- impl->wcache_and.writ.func(stream, TB_STATE_OK, impl->wcache_and.writ.data, impl->wcache_and.writ.size, impl->wcache_and.writ.size, priv);
-
- // break
- bwrit = tb_false;
- }
-
- } while (0);
-
- // failed?
- if (state != TB_STATE_OK)
- {
- // trace
- tb_trace_d("cache: writ: %lu: failed: %s", impl->wcache_and.writ.size, tb_state_cstr(state));
-
- // done func
- impl->wcache_and.writ.func(stream, state, impl->wcache_and.writ.data, 0, impl->wcache_and.writ.size, priv);
-
- // break
- bwrit = tb_false;
- }
-
- // continue writing?
- return bwrit;
-}
-static tb_bool_t tb_async_stream_cache_writ_done(tb_async_stream_ref_t stream, tb_size_t delay, tb_byte_t const* data, tb_size_t size, tb_async_stream_writ_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl && impl->writ && data && size && func, tb_false);
-
- // using cache?
- tb_bool_t ok = tb_false;
- if (impl->wcache_maxn)
- {
- // writ data to cache
- if (data && size) tb_buffer_memncat(&impl->wcache_data, data, size);
-
- // the writ data and size
- tb_byte_t const* writ_data = tb_buffer_data(&impl->wcache_data);
- tb_size_t writ_size = tb_buffer_size(&impl->wcache_data);
-
- // no full? writ ok
- if (writ_size < impl->wcache_maxn)
- {
- // trace
- tb_trace_d("cache: writ: %lu: ok", size);
-
- // done func
- func(stream, TB_STATE_OK, data, size, size, priv);
- ok = tb_true;
- }
- else
- {
- // trace
- tb_trace_d("cache: writ: %lu: ..", size);
-
- // writ it
- impl->wcache_and.writ.func = func;
- impl->wcache_and.writ.data = data;
- impl->wcache_and.writ.size = size;
- ok = impl->writ(stream, delay, writ_data, writ_size, tb_async_stream_cache_writ_func, priv);
- }
- }
- // writ it
- else ok = impl->writ(stream, delay, data, size, func, priv);
-
- // ok?
- return ok;
-}
-static tb_bool_t tb_async_stream_cache_read_done(tb_async_stream_ref_t stream, tb_size_t delay, tb_size_t size, tb_async_stream_read_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl && impl->read && func, tb_false);
-
- // have writed cache? need sync it first
- tb_assert_and_check_return_val(!impl->wcache_maxn || !tb_buffer_size(&impl->wcache_data), tb_false);
-
- // using cache?
- tb_byte_t* data = tb_null;
- if (impl->rcache_maxn)
- {
- // grow data
- if (impl->rcache_maxn > tb_buffer_maxn(&impl->rcache_data))
- tb_buffer_resize(&impl->rcache_data, impl->rcache_maxn);
-
- // the cache data
- data = tb_buffer_data(&impl->rcache_data);
- tb_assert_and_check_return_val(data, tb_false);
-
- // the maxn
- tb_size_t maxn = tb_buffer_maxn(&impl->rcache_data);
-
- // adjust the size
- if (!size || size > maxn) size = maxn;
- }
-
- // read it
- return impl->read(stream, delay, data, size, func, priv);
-}
-static tb_bool_t tb_async_stream_open_read_func(tb_async_stream_ref_t stream, tb_size_t state, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_async_stream_open_read_t* open_read = (tb_async_stream_open_read_t*)priv;
- tb_assert_and_check_return_val(impl && impl->read && open_read && open_read->func, tb_false);
-
- // done
- tb_bool_t ok = tb_true;
- do
- {
- // ok?
- tb_check_break(state == TB_STATE_OK);
-
- // reset state
- state = TB_STATE_UNKNOWN_ERROR;
-
- // killed?
- if (tb_async_stream_is_killed(stream))
- {
- state = TB_STATE_KILLED;
- break;
- }
-
- // read it
- if (!tb_async_stream_cache_read_done(stream, 0, open_read->size, open_read->func, open_read->priv)) break;
-
- // ok
- state = TB_STATE_OK;
-
- } while (0);
-
- // failed?
- if (state != TB_STATE_OK)
- {
- // done func
- ok = open_read->func(stream, state, tb_null, 0, open_read->size, open_read->priv);
- }
-
- // ok?
- return ok;
-}
-static tb_bool_t tb_async_stream_open_writ_func(tb_async_stream_ref_t stream, tb_size_t state, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_async_stream_open_writ_t* owrit = (tb_async_stream_open_writ_t*)priv;
- tb_assert_and_check_return_val(impl && impl->writ && owrit && owrit->func, tb_false);
-
- // done
- tb_bool_t ok = tb_true;
- do
- {
- // ok?
- tb_check_break(state == TB_STATE_OK);
-
- // reset state
- state = TB_STATE_UNKNOWN_ERROR;
-
- // killed?
- if (tb_async_stream_is_killed(stream))
- {
- state = TB_STATE_KILLED;
- break;
- }
-
- // check
- tb_assert_and_check_break(owrit->data && owrit->size);
-
- // writ it
- if (!tb_async_stream_cache_writ_done(stream, 0, owrit->data, owrit->size, owrit->func, owrit->priv)) break;
-
- // ok
- state = TB_STATE_OK;
-
- } while (0);
-
- // failed?
- if (state != TB_STATE_OK)
- {
- // done func
- ok = owrit->func(stream, state, owrit->data, 0, owrit->size, owrit->priv);
- }
-
- // ok?
- return ok;
-}
-static tb_bool_t tb_async_stream_open_seek_func(tb_async_stream_ref_t stream, tb_size_t state, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_async_stream_open_seek_t* open_seek = (tb_async_stream_open_seek_t*)priv;
- tb_assert_and_check_return_val(impl && impl->seek && open_seek && open_seek->func, tb_false);
-
- // done
- tb_bool_t ok = tb_true;
- do
- {
- // ok?
- tb_check_break(state == TB_STATE_OK);
-
- // reset state
- state = TB_STATE_UNKNOWN_ERROR;
-
- // killed?
- if (tb_async_stream_is_killed(stream))
- {
- state = TB_STATE_KILLED;
- break;
- }
-
- // offset be not modified?
- if (tb_async_stream_offset(stream) == open_seek->offset)
- {
- // done func
- ok = open_seek->func(stream, TB_STATE_OK, open_seek->offset, open_seek->priv);
- }
- else
- {
- // seek it
- if (!impl->seek(stream, open_seek->offset, open_seek->func, open_seek->priv)) break;
- }
-
- // ok
- state = TB_STATE_OK;
-
- } while (0);
-
- // failed?
- if (state != TB_STATE_OK)
- {
- // done func
- ok = open_seek->func(stream, state, 0, open_seek->priv);
- }
-
- // ok?
- return ok;
-}
-static tb_bool_t tb_async_stream_sync_read_func(tb_async_stream_ref_t stream, tb_size_t state, tb_bool_t bclosing, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_async_stream_sync_read_t* sync_read = (tb_async_stream_sync_read_t*)priv;
- tb_assert_and_check_return_val(impl && impl->read && sync_read && sync_read->func, tb_false);
-
- // done
- tb_bool_t ok = tb_true;
- do
- {
- // ok?
- tb_check_break(state == TB_STATE_OK);
-
- // reset state
- state = TB_STATE_UNKNOWN_ERROR;
-
- // killed?
- if (tb_async_stream_is_killed(stream))
- {
- state = TB_STATE_KILLED;
- break;
- }
-
- // read it
- if (!tb_async_stream_cache_read_done(stream, 0, sync_read->size, sync_read->func, sync_read->priv)) break;
-
- // ok
- state = TB_STATE_OK;
-
- } while (0);
-
- // failed?
- if (state != TB_STATE_OK)
- {
- // done func
- ok = sync_read->func(stream, state, tb_null, 0, sync_read->size, sync_read->priv);
- }
-
- // ok?
- return ok;
-}
-static tb_bool_t tb_async_stream_sync_seek_func(tb_async_stream_ref_t stream, tb_size_t state, tb_bool_t bclosing, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_async_stream_sync_seek_t* sync_seek = (tb_async_stream_sync_seek_t*)priv;
- tb_assert_and_check_return_val(impl && impl->seek && sync_seek && sync_seek->func, tb_false);
-
- // done
- tb_bool_t ok = tb_true;
- do
- {
- // ok?
- tb_check_break(state == TB_STATE_OK);
-
- // reset state
- state = TB_STATE_UNKNOWN_ERROR;
-
- // killed?
- if (tb_async_stream_is_killed(stream))
- {
- state = TB_STATE_KILLED;
- break;
- }
-
- // offset be not modified?
- if (tb_async_stream_offset(stream) == sync_seek->offset)
- {
- // done func
- ok = sync_seek->func(stream, TB_STATE_OK, sync_seek->offset, sync_seek->priv);
- }
- else
- {
- // seek it
- if (!impl->seek(stream, sync_seek->offset, sync_seek->func, sync_seek->priv)) break;
- }
-
- // ok
- state = TB_STATE_OK;
-
- } while (0);
-
- // failed?
- if (state != TB_STATE_OK)
- {
- // done func
- ok = sync_seek->func(stream, state, 0, sync_seek->priv);
- }
-
- // ok?
- return ok;
-}
-/* //////////////////////////////////////////////////////////////////////////////////////
- * interfaces
- */
-tb_async_stream_ref_t tb_async_stream_init( tb_aicp_ref_t aicp
- , tb_size_t type
- , tb_size_t type_size
- , tb_size_t rcache
- , tb_size_t wcache
- , tb_bool_t (*open_try)(tb_async_stream_ref_t stream)
- , tb_bool_t (*clos_try)(tb_async_stream_ref_t stream)
- , tb_bool_t (*open)(tb_async_stream_ref_t stream, tb_async_stream_open_func_t func, tb_cpointer_t priv)
- , tb_bool_t (*clos)(tb_async_stream_ref_t stream, tb_async_stream_clos_func_t func, tb_cpointer_t priv)
- , tb_bool_t (*exit)(tb_async_stream_ref_t stream)
- , tb_void_t (*kill)(tb_async_stream_ref_t stream)
- , tb_bool_t (*ctrl)(tb_async_stream_ref_t stream, tb_size_t ctrl, tb_va_list_t args)
- , tb_bool_t (*read)(tb_async_stream_ref_t stream, tb_size_t delay, tb_byte_t* data, tb_size_t size, tb_async_stream_read_func_t func, tb_cpointer_t priv)
- , tb_bool_t (*writ)(tb_async_stream_ref_t stream, tb_size_t delay, tb_byte_t const* data, tb_size_t size, tb_async_stream_writ_func_t func, tb_cpointer_t priv)
- , tb_bool_t (*seek)(tb_async_stream_ref_t stream, tb_hize_t offset, tb_async_stream_seek_func_t func, tb_cpointer_t priv)
- , tb_bool_t (*sync)(tb_async_stream_ref_t stream, tb_bool_t bclosing, tb_async_stream_sync_func_t func, tb_cpointer_t priv)
- , tb_bool_t (*task)(tb_async_stream_ref_t stream, tb_size_t delay, tb_async_stream_task_func_t func, tb_cpointer_t priv))
-{
- // check
- tb_assert_and_check_return_val(type_size, tb_null);
- tb_assert_and_check_return_val(open && clos && ctrl && kill, tb_null);
- tb_assert_and_check_return_val(read || writ, tb_null);
-
- // done
- tb_bool_t ok = tb_false;
- tb_async_stream_impl_t* impl = tb_null;
- tb_async_stream_ref_t stream = tb_null;
- do
- {
- // make impl
- impl = (tb_async_stream_impl_t*)tb_align8_malloc0(sizeof(tb_async_stream_impl_t) + type_size);
- tb_assert_and_check_break(impl);
-
- // init stream
- stream = (tb_async_stream_ref_t)&impl[1];
-
- // init type
- impl->type = (tb_uint8_t)type;
-
- // init timeout, 10s
- impl->timeout = TB_STREAM_DEFAULT_TIMEOUT;
-
- // init internal state
- impl->istate = TB_STATE_CLOSED;
-
- // init aicp
- impl->aicp = aicp? aicp : tb_aicp();
- tb_assert_and_check_break(impl->aicp);
-
- // init url
- if (!tb_url_init(&impl->url)) break;
-
- // init rcache
- if (!tb_buffer_init(&impl->rcache_data)) break;
- impl->rcache_maxn = rcache;
-
- // init wcache
- if (!tb_buffer_init(&impl->wcache_data)) break;
- impl->wcache_maxn = wcache;
-
- // init func
- impl->open_try = open_try;
- impl->clos_try = clos_try;
- impl->open = open;
- impl->clos = clos;
- impl->exit = exit;
- impl->kill = kill;
- impl->ctrl = ctrl;
- impl->read = read;
- impl->writ = writ;
- impl->seek = seek;
- impl->sync = sync;
- impl->task = task;
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // failed?
- if (!ok)
- {
- // exit it
- if (stream) tb_async_stream_exit(stream);
- stream = tb_null;
- }
-
- // ok?
- return stream;
-}
-tb_async_stream_ref_t tb_async_stream_init_from_url(tb_aicp_ref_t aicp, tb_char_t const* url)
-{
- // check
- tb_assert_and_check_return_val(url, tb_null);
-
- // the init
- static tb_async_stream_ref_t (*s_init[])(tb_aicp_ref_t) =
- {
- tb_null
- , tb_async_stream_init_file
- , tb_async_stream_init_sock
- , tb_async_stream_init_http
- , tb_async_stream_init_data
- };
-
- // probe protocol
- tb_size_t protocol = tb_url_protocol_probe(url);
- tb_assert_static((tb_size_t)TB_URL_PROTOCOL_FILE == (tb_size_t)TB_STREAM_TYPE_FILE);
- tb_assert_static((tb_size_t)TB_URL_PROTOCOL_HTTP == (tb_size_t)TB_STREAM_TYPE_HTTP);
- tb_assert_static((tb_size_t)TB_URL_PROTOCOL_SOCK == (tb_size_t)TB_STREAM_TYPE_SOCK);
- tb_assert_static((tb_size_t)TB_URL_PROTOCOL_DATA == (tb_size_t)TB_STREAM_TYPE_DATA);
-
- // protocol => type
- tb_size_t type = protocol;
- if (!type || type > TB_STREAM_TYPE_DATA)
- {
- tb_trace_e("unknown stream for url: %s", url);
- return tb_null;
- }
- tb_assert_and_check_return_val(type && type < tb_arrayn(s_init) && s_init[type], tb_null);
-
- // done
- tb_bool_t ok = tb_false;
- tb_async_stream_ref_t stream = tb_null;
- do
- {
- // init stream
- stream = s_init[type](aicp);
- tb_assert_and_check_break(stream);
-
- // init url
- if (!tb_async_stream_ctrl(stream, TB_STREAM_CTRL_SET_URL, url)) break;
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // failed?
- if (!ok)
- {
- // exit stream
- if (stream) tb_async_stream_exit(stream);
- stream = tb_null;
- }
-
- // ok?
- return stream;
-}
-tb_bool_t tb_async_stream_exit(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl, tb_false);
-
- // trace
- tb_trace_d("exit: %s: ..", tb_url_cstr(&impl->url));
-
- // kill it first
- tb_async_stream_kill(stream);
-
- // try closing it
- tb_size_t tryn = 30;
- tb_bool_t ok = tb_false;
- while (!(ok = tb_async_stream_clos_try(stream)) && tryn--)
- {
- // wait some time
- tb_msleep(200);
- }
-
- // close failed?
- if (!ok)
- {
- // trace
- tb_trace_e("exit: %s: failed!", tb_url_cstr(&impl->url));
- return tb_false;
- }
-
- // exit it
- if (impl->exit && !impl->exit(stream)) return tb_false;
-
- // exit url
- tb_url_exit(&impl->url);
-
- // exit rcache
- tb_buffer_exit(&impl->rcache_data);
-
- // exit wcache
- tb_buffer_exit(&impl->wcache_data);
-
- // free it
- tb_align8_free(impl);
-
- // trace
- tb_trace_d("exit: ok");
-
- // ok
- return tb_true;
-}
-tb_url_ref_t tb_async_stream_url(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl, tb_null);
-
- // get the url
- return &impl->url;
-}
-tb_size_t tb_async_stream_type(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl, TB_STREAM_TYPE_NONE);
-
- // the type
- return impl->type;
-}
-tb_hong_t tb_async_stream_size(tb_async_stream_ref_t stream)
-{
- // check
- tb_assert_and_check_return_val(stream, 0);
-
- // get the size
- tb_hong_t size = -1;
- return tb_async_stream_ctrl((tb_async_stream_ref_t)stream, TB_STREAM_CTRL_GET_SIZE, &size)? size : -1;
-}
-tb_hize_t tb_async_stream_left(tb_async_stream_ref_t stream)
-{
- // check
- tb_assert_and_check_return_val(stream, 0);
-
- // the size
- tb_hong_t size = tb_async_stream_size(stream);
- tb_check_return_val(size >= 0, -1);
-
- // the offset
- tb_hize_t offset = tb_async_stream_offset(stream);
- tb_assert_and_check_return_val(offset <= size, 0);
-
- // the left
- return size - offset;
-}
-tb_bool_t tb_async_stream_beof(tb_async_stream_ref_t stream)
-{
- // check
- tb_assert_and_check_return_val(stream, tb_true);
-
- // size
- tb_hong_t size = tb_async_stream_size(stream);
- tb_hize_t offt = tb_async_stream_offset(stream);
-
- // eof?
- return (size > 0 && offt >= size)? tb_true : tb_false;
-}
-tb_hize_t tb_async_stream_offset(tb_async_stream_ref_t stream)
-{
- // check
- tb_assert_and_check_return_val(stream, 0);
-
- // get the offset
- tb_hize_t offset = 0;
- return tb_async_stream_ctrl((tb_async_stream_ref_t)stream, TB_STREAM_CTRL_GET_OFFSET, &offset)? offset : 0;
-}
-tb_bool_t tb_async_stream_is_opened(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl, tb_false);
-
- // the state
- tb_size_t state = tb_atomic_get(&impl->istate);
-
- // is opened?
- return (TB_STATE_OPENED == state || TB_STATE_KILLING == state)? tb_true : tb_false;
-}
-tb_bool_t tb_async_stream_is_closed(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl, tb_false);
-
- // the state
- tb_size_t state = tb_atomic_get(&impl->istate);
-
- // is closed?
- return (TB_STATE_CLOSED == state || TB_STATE_KILLED == state)? tb_true : tb_false;
-}
-tb_bool_t tb_async_stream_is_killed(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl, tb_false);
-
- // the state
- tb_size_t state = tb_atomic_get(&impl->istate);
-
- // is killed?
- return (TB_STATE_KILLED == state || TB_STATE_KILLING == state)? tb_true : tb_false;
-}
-tb_long_t tb_async_stream_timeout(tb_async_stream_ref_t stream)
-{
- // check
- tb_assert_and_check_return_val(stream, -1);
-
- // get the timeout
- tb_long_t timeout = -1;
- return tb_async_stream_ctrl(stream, TB_STREAM_CTRL_GET_TIMEOUT, &timeout)? timeout : -1;
-}
-tb_bool_t tb_async_stream_ctrl(tb_async_stream_ref_t stream, tb_size_t ctrl, ...)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl && impl->ctrl, tb_false);
-
- // init args
- tb_va_list_t args;
- tb_va_start(args, ctrl);
-
- // ctrl it
- tb_bool_t ok = tb_async_stream_ctrl_with_args(stream, ctrl, args);
-
- // exit args
- tb_va_end(args);
-
- // ok?
- return ok;
-}
-tb_bool_t tb_async_stream_ctrl_with_args(tb_async_stream_ref_t stream, tb_size_t ctrl, tb_va_list_t args)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl && impl->ctrl, tb_false);
-
- // save args
- tb_va_list_t args_saved;
- tb_va_copy(args_saved, args);
-
- // ctrl
- tb_bool_t ok = tb_false;
- switch (ctrl)
- {
- case TB_STREAM_CTRL_SET_URL:
- {
- // check
- tb_assert_and_check_return_val(tb_async_stream_is_closed(stream), tb_false);
-
- // set url
- tb_char_t const* url = (tb_char_t const*)tb_va_arg(args, tb_char_t const*);
- if (url && tb_url_cstr_set(&impl->url, url)) ok = tb_true;
- }
- break;
- case TB_STREAM_CTRL_GET_URL:
- {
- // get url
- tb_char_t const** purl = (tb_char_t const**)tb_va_arg(args, tb_char_t const**);
- if (purl)
- {
- tb_char_t const* url = tb_url_cstr(&impl->url);
- if (url)
- {
- *purl = url;
- ok = tb_true;
- }
- }
- }
- break;
- case TB_STREAM_CTRL_SET_HOST:
- {
- // check
- tb_assert_and_check_return_val(tb_async_stream_is_closed(stream), tb_false);
-
- // set host
- tb_char_t const* host = (tb_char_t const*)tb_va_arg(args, tb_char_t const*);
- if (host)
- {
- tb_url_host_set(&impl->url, host);
- ok = tb_true;
- }
- }
- break;
- case TB_STREAM_CTRL_GET_HOST:
- {
- // get host
- tb_char_t const** phost = (tb_char_t const**)tb_va_arg(args, tb_char_t const**);
- if (phost)
- {
- tb_char_t const* host = tb_url_host(&impl->url);
- if (host)
- {
- *phost = host;
- ok = tb_true;
- }
- }
- }
- break;
- case TB_STREAM_CTRL_SET_PORT:
- {
- // check
- tb_assert_and_check_return_val(tb_async_stream_is_closed(stream), tb_false);
-
- // set port
- tb_size_t port = (tb_size_t)tb_va_arg(args, tb_size_t);
- if (port)
- {
- tb_url_port_set(&impl->url, (tb_uint16_t)port);
- ok = tb_true;
- }
- }
- break;
- case TB_STREAM_CTRL_GET_PORT:
- {
- // get port
- tb_size_t* pport = (tb_size_t*)tb_va_arg(args, tb_size_t*);
- if (pport)
- {
- *pport = tb_url_port(&impl->url);
- ok = tb_true;
- }
- }
- break;
- case TB_STREAM_CTRL_SET_PATH:
- {
- // check
- tb_assert_and_check_return_val(tb_async_stream_is_closed(stream), tb_false);
-
- // set path
- tb_char_t const* path = (tb_char_t const*)tb_va_arg(args, tb_char_t const*);
- if (path)
- {
- tb_url_path_set(&impl->url, path);
- ok = tb_true;
- }
- }
- break;
- case TB_STREAM_CTRL_GET_PATH:
- {
- // get path
- tb_char_t const** ppath = (tb_char_t const**)tb_va_arg(args, tb_char_t const**);
- if (ppath)
- {
- tb_char_t const* path = tb_url_path(&impl->url);
- if (path)
- {
- *ppath = path;
- ok = tb_true;
- }
- }
- }
- break;
- case TB_STREAM_CTRL_SET_SSL:
- {
- // check
- tb_assert_and_check_return_val(tb_async_stream_is_closed(stream), tb_false);
-
- // set ssl
- tb_bool_t bssl = (tb_bool_t)tb_va_arg(args, tb_bool_t);
- tb_url_ssl_set(&impl->url, bssl);
- ok = tb_true;
- }
- break;
- case TB_STREAM_CTRL_GET_SSL:
- {
- // get ssl
- tb_bool_t* pssl = (tb_bool_t*)tb_va_arg(args, tb_bool_t*);
- if (pssl)
- {
- *pssl = tb_url_ssl(&impl->url);
- ok = tb_true;
- }
- }
- break;
- case TB_STREAM_CTRL_SET_TIMEOUT:
- {
- // check
- tb_assert_and_check_return_val(tb_async_stream_is_closed(stream), tb_false);
-
- // set timeout
- tb_long_t timeout = (tb_long_t)tb_va_arg(args, tb_long_t);
- impl->timeout = timeout? timeout : TB_STREAM_DEFAULT_TIMEOUT;
- ok = tb_true;
- }
- break;
- case TB_STREAM_CTRL_GET_TIMEOUT:
- {
- // get timeout
- tb_long_t* ptimeout = (tb_long_t*)tb_va_arg(args, tb_long_t*);
- if (ptimeout)
- {
- *ptimeout = impl->timeout;
- ok = tb_true;
- }
- }
- break;
- default:
- break;
- }
-
- // restore args
- tb_va_copy(args, args_saved);
-
- // ctrl stream
- ok = (impl->ctrl(stream, ctrl, args) || ok)? tb_true : tb_false;
-
- // ok?
- return ok;
-}
-tb_void_t tb_async_stream_kill(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return(impl);
-
- // trace
- tb_trace_d("kill: %s: state: %s: ..", tb_url_cstr(&impl->url), tb_state_cstr(tb_atomic_get(&impl->istate)));
-
- // opened? kill it
- if (TB_STATE_OPENED == tb_atomic_fetch_and_pset(&impl->istate, TB_STATE_OPENED, TB_STATE_KILLING))
- {
- // kill it
- if (impl->kill) impl->kill(stream);
-
- // trace
- tb_trace_d("kill: %s: ok", tb_url_cstr(&impl->url));
- }
- // opening? kill it
- else if (TB_STATE_OPENING == tb_atomic_fetch_and_pset(&impl->istate, TB_STATE_OPENING, TB_STATE_KILLING))
- {
- // kill it
- if (impl->kill) impl->kill(stream);
-
- // trace
- tb_trace_d("kill: %s: ok", tb_url_cstr(&impl->url));
- }
- else
- {
- // closed? killed
- tb_atomic_pset(&impl->istate, TB_STATE_CLOSED, TB_STATE_KILLED);
- }
-}
-tb_bool_t tb_async_stream_open_try(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl, tb_false);
-
- // not supported?
- if (!impl->open_try) return tb_async_stream_is_opened(stream);
-
- // trace
- tb_trace_d("open: try: %s: ..", tb_url_cstr(&impl->url));
-
- // set opening
- tb_size_t state = tb_atomic_fetch_and_pset(&impl->istate, TB_STATE_CLOSED, TB_STATE_OPENING);
-
- // opened?
- tb_check_return_val(state != TB_STATE_OPENED, tb_true);
-
- // must be closed
- tb_assert_and_check_return_val(state == TB_STATE_CLOSED, tb_false);
-
- // try opening it
- tb_bool_t ok = impl->open_try(stream);
-
- // trace
- tb_trace_d("open: try: %s: %s", tb_url_cstr(&impl->url), ok? "ok" : "no");
-
- // ok?
- return ok;
-}
-tb_bool_t tb_async_stream_open_(tb_async_stream_ref_t stream, tb_async_stream_open_func_t func, tb_cpointer_t priv __tb_debug_decl__)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl && impl->open && func, tb_false);
-
- // trace
- tb_trace_d("open: %s: ..", tb_url_cstr(&impl->url));
-
- // try opening ok? done func directly
- if (tb_async_stream_open_try(stream))
- {
- // done func
- func(stream, TB_STATE_OK, priv);
- return tb_true;
- }
-
- // set opening
- tb_size_t state = tb_atomic_fetch_and_pset(&impl->istate, TB_STATE_CLOSED, TB_STATE_OPENING);
-
- // must be closed
- tb_assert_and_check_return_val(state == TB_STATE_CLOSED, tb_false);
-
- // open it
- return impl->open(stream, func, priv);
-}
-tb_bool_t tb_async_stream_clos_try(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl, tb_false);
-
- // not supported?
- if (!impl->clos_try) return tb_async_stream_is_closed(stream);
-
- // trace
- tb_trace_d("clos: try: %s: ..", tb_url_cstr(&impl->url));
-
- // done
- tb_bool_t ok = tb_false;
- do
- {
- // closed?
- if (TB_STATE_CLOSED == tb_atomic_get(&impl->istate))
- {
- ok = tb_true;
- break;
- }
-
- // try closing it
- ok = impl->clos_try(stream);
-
- } while (0);
-
- // trace
- tb_trace_d("clos: try: %s: %s", tb_url_cstr(&impl->url), ok? "ok" : "no");
-
- // ok?
- return ok;
-}
-tb_bool_t tb_async_stream_clos_(tb_async_stream_ref_t stream, tb_async_stream_clos_func_t func, tb_cpointer_t priv __tb_debug_decl__)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl && impl->clos && func, tb_false);
-
- // trace
- tb_trace_d("clos: %s: ..", tb_url_cstr(&impl->url));
-
- // try closing ok? done func directly
- if (tb_async_stream_clos_try(stream))
- {
- // done func
- func(stream, TB_STATE_OK, priv);
- return tb_true;
- }
-
- // save debug info
-#ifdef __tb_debug__
- impl->func = func_;
- impl->file = file_;
- impl->line = line_;
-#endif
-
- // clos it
- return impl->clos(stream, func, priv);
-}
-tb_bool_t tb_async_stream_read_(tb_async_stream_ref_t stream, tb_size_t size, tb_async_stream_read_func_t func, tb_cpointer_t priv __tb_debug_decl__)
-{
- // read it
- return tb_async_stream_read_after_(stream, 0, size, func, priv __tb_debug_args__);
-}
-tb_bool_t tb_async_stream_writ_(tb_async_stream_ref_t stream, tb_byte_t const* data, tb_size_t size, tb_async_stream_writ_func_t func, tb_cpointer_t priv __tb_debug_decl__)
-{
- // writ it
- return tb_async_stream_writ_after_(stream, 0, data, size, func, priv __tb_debug_args__);
-}
-tb_bool_t tb_async_stream_seek_(tb_async_stream_ref_t stream, tb_hize_t offset, tb_async_stream_seek_func_t func, tb_cpointer_t priv __tb_debug_decl__)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl && impl->seek && func, tb_false);
-
- // check state
- tb_assert_and_check_return_val(TB_STATE_OPENED == tb_atomic_get(&impl->istate), tb_false);
-
- // save debug info
-#ifdef __tb_debug__
- impl->func = func_;
- impl->file = file_;
- impl->line = line_;
-#endif
-
- // have writed cache? sync it first
- if (impl->wcache_maxn && tb_buffer_size(&impl->wcache_data))
- {
- // init sync and seek
- impl->sync_and.seek.func = func;
- impl->sync_and.seek.priv = priv;
- impl->sync_and.seek.offset = offset;
- return tb_async_stream_sync_(stream, tb_false, tb_async_stream_sync_seek_func, &impl->sync_and.seek __tb_debug_args__);
- }
-
- // offset be not modified?
- if (tb_async_stream_offset(stream) == offset)
- {
- func(stream, TB_STATE_OK, offset, priv);
- return tb_true;
- }
-
- // seek it
- return impl->seek(stream, offset, func, priv);
-}
-tb_bool_t tb_async_stream_sync_(tb_async_stream_ref_t stream, tb_bool_t bclosing, tb_async_stream_sync_func_t func, tb_cpointer_t priv __tb_debug_decl__)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl && impl->sync && func, tb_false);
-
- // check state
- tb_assert_and_check_return_val(TB_STATE_OPENED == tb_atomic_get(&impl->istate), tb_false);
-
- // save debug info
-#ifdef __tb_debug__
- impl->func = func_;
- impl->file = file_;
- impl->line = line_;
-#endif
-
- // using cache?
- tb_bool_t ok = tb_false;
- if (impl->wcache_maxn)
- {
- // sync the cache data
- tb_byte_t* data = tb_buffer_data(&impl->wcache_data);
- tb_size_t size = tb_buffer_size(&impl->wcache_data);
- if (data && size)
- {
- // writ the cache data
- impl->wcache_and.sync.func = func;
- impl->wcache_and.sync.bclosing = bclosing;
- ok = impl->writ(stream, 0, data, size, tb_async_stream_cache_sync_func, priv);
- }
- // sync it
- else ok = impl->sync(stream, bclosing, func, priv);
- }
- // sync it
- else ok = impl->sync(stream, bclosing, func, priv);
-
- // ok?
- return ok;
-}
-tb_bool_t tb_async_stream_task_(tb_async_stream_ref_t stream, tb_size_t delay, tb_async_stream_task_func_t func, tb_cpointer_t priv __tb_debug_decl__)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl && impl->task && func, tb_false);
-
- // check state
- tb_assert_and_check_return_val(TB_STATE_OPENED == tb_atomic_get(&impl->istate), tb_false);
-
- // save debug info
-#ifdef __tb_debug__
- impl->func = func_;
- impl->file = file_;
- impl->line = line_;
-#endif
-
- // task it
- return impl->task(stream, delay, func, priv);
-}
-tb_bool_t tb_async_stream_open_read_(tb_async_stream_ref_t stream, tb_size_t size, tb_async_stream_read_func_t func, tb_cpointer_t priv __tb_debug_decl__)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl && impl->open && impl->read && func, tb_false);
-
- // no opened? open it first
- if (TB_STATE_CLOSED == tb_atomic_get(&impl->istate))
- {
- // init open and read
- impl->open_and.read.func = func;
- impl->open_and.read.priv = priv;
- impl->open_and.read.size = size;
- return tb_async_stream_open_(stream, tb_async_stream_open_read_func, &impl->open_and.read __tb_debug_args__);
- }
-
- // read it
- return tb_async_stream_read_(stream, size, func, priv __tb_debug_args__);
-}
-tb_bool_t tb_async_stream_open_writ_(tb_async_stream_ref_t stream, tb_byte_t const* data, tb_size_t size, tb_async_stream_writ_func_t func, tb_cpointer_t priv __tb_debug_decl__)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl && impl->open && impl->writ && data && size && func, tb_false);
-
- // no opened? open it first
- if (TB_STATE_CLOSED == tb_atomic_get(&impl->istate))
- {
- // init open and writ
- impl->open_and.writ.func = func;
- impl->open_and.writ.priv = priv;
- impl->open_and.writ.data = data;
- impl->open_and.writ.size = size;
- return tb_async_stream_open_(stream, tb_async_stream_open_writ_func, &impl->open_and.writ __tb_debug_args__);
- }
-
- // writ it
- return tb_async_stream_writ_(stream, data, size, func, priv __tb_debug_args__);
-}
-tb_bool_t tb_async_stream_open_seek_(tb_async_stream_ref_t stream, tb_hize_t offset, tb_async_stream_seek_func_t func, tb_cpointer_t priv __tb_debug_decl__)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl && impl->open && impl->seek && func, tb_false);
-
- // no opened? open it first
- if (TB_STATE_CLOSED == tb_atomic_get(&impl->istate))
- {
- // init open and seek
- impl->open_and.seek.func = func;
- impl->open_and.seek.priv = priv;
- impl->open_and.seek.offset = offset;
- return tb_async_stream_open_(stream, tb_async_stream_open_seek_func, &impl->open_and.seek __tb_debug_args__);
- }
-
- // seek it
- return tb_async_stream_seek_(stream, offset, func, priv __tb_debug_args__);
-}
-tb_bool_t tb_async_stream_read_after_(tb_async_stream_ref_t stream, tb_size_t delay, tb_size_t size, tb_async_stream_read_func_t func, tb_cpointer_t priv __tb_debug_decl__)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl && impl->read && func, tb_false);
-
- // check state
- tb_assert_and_check_return_val(TB_STATE_OPENED == tb_atomic_get(&impl->istate), tb_false);
-
- // save debug info
-#ifdef __tb_debug__
- impl->func = func_;
- impl->file = file_;
- impl->line = line_;
-#endif
-
- // have writed cache? sync it first
- if (impl->wcache_maxn && tb_buffer_size(&impl->wcache_data))
- {
- // init sync and read
- impl->sync_and.read.func = func;
- impl->sync_and.read.priv = priv;
- impl->sync_and.read.size = size;
- return tb_async_stream_sync_(stream, tb_false, tb_async_stream_sync_read_func, &impl->sync_and.read __tb_debug_args__);
- }
-
- // read it
- return tb_async_stream_cache_read_done(stream, delay, size, func, priv);
-}
-tb_bool_t tb_async_stream_writ_after_(tb_async_stream_ref_t stream, tb_size_t delay, tb_byte_t const* data, tb_size_t size, tb_async_stream_writ_func_t func, tb_cpointer_t priv __tb_debug_decl__)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl && impl->writ && data && size && func, tb_false);
-
- // check state
- tb_assert_and_check_return_val(TB_STATE_OPENED == tb_atomic_get(&impl->istate), tb_false);
-
- // save debug info
-#ifdef __tb_debug__
- impl->func = func_;
- impl->file = file_;
- impl->line = line_;
-#endif
-
- // writ it
- return tb_async_stream_cache_writ_done(stream, delay, data, size, func, priv);
-}
-tb_aicp_ref_t tb_async_stream_aicp(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl, tb_null);
-
- // the aicp
- return impl->aicp;
-}
-#ifdef __tb_debug__
-tb_char_t const* tb_async_stream_func(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl, tb_null);
-
- // the func
- return impl->func;
-}
-tb_char_t const* tb_async_stream_file(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl, tb_null);
-
- // the file
- return impl->file;
-}
-tb_size_t tb_async_stream_line(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl, 0);
-
- // the line
- return impl->line;
-}
-#endif
diff --git a/core/src/tbox/src/tbox/stream/deprecated/async_stream.h b/core/src/tbox/src/tbox/stream/deprecated/async_stream.h
deleted file mode 100644
index e6b2b3309..000000000
--- a/core/src/tbox/src/tbox/stream/deprecated/async_stream.h
+++ /dev/null
@@ -1,726 +0,0 @@
-/*!The Treasure Box Library
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
- *
- * @author ruki
- * @file async_stream.h
- * @ingroup stream
- *
- */
-#ifndef TB_STREAM_ASYNC_STREAM_H
-#define TB_STREAM_ASYNC_STREAM_H
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
- */
-#include "prefix.h"
-#include "../../asio/deprecated/asio.h"
-#include "../../libc/libc.h"
-#include "../../network/url.h"
-#include "../../memory/memory.h"
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * extern
- */
-__tb_extern_c_enter__
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * macros
- */
-
-/// open
-#define tb_async_stream_open(stream, func, priv) tb_async_stream_open_(stream, func, priv __tb_debug_vals__)
-
-/// clos
-#define tb_async_stream_clos(stream, func, priv) tb_async_stream_clos_(stream, func, priv __tb_debug_vals__)
-
-/// read
-#define tb_async_stream_read(stream, size, func, priv) tb_async_stream_read_(stream, size, func, priv __tb_debug_vals__)
-
-/// writ
-#define tb_async_stream_writ(stream, data, size, func, priv) tb_async_stream_writ_(stream, data, size, func, priv __tb_debug_vals__)
-
-/// seek
-#define tb_async_stream_seek(stream, offset, func, priv) tb_async_stream_seek_(stream, offset, func, priv __tb_debug_vals__)
-
-/// sync
-#define tb_async_stream_sync(stream, bclosing, func, priv) tb_async_stream_sync_(stream, bclosing, func, priv __tb_debug_vals__)
-
-/// task
-#define tb_async_stream_task(stream, delay, func, priv) tb_async_stream_task_(stream, delay, func, priv __tb_debug_vals__)
-
-/// open and read
-#define tb_async_stream_open_read(stream, size, func, priv) tb_async_stream_open_read_(stream, size, func, priv __tb_debug_vals__)
-
-/// open and writ
-#define tb_async_stream_open_writ(stream, data, size, func, priv) tb_async_stream_open_writ_(stream, data, size, func, priv __tb_debug_vals__)
-
-/// open and seek
-#define tb_async_stream_open_seek(stream, offset, func, priv) tb_async_stream_open_seek_(stream, offset, func, priv __tb_debug_vals__)
-
-/// read after delay
-#define tb_async_stream_read_after(stream, delay, size, func, priv) tb_async_stream_read_after_(stream, delay, size, func, priv __tb_debug_vals__)
-
-/// writ after delay
-#define tb_async_stream_writ_after(stream, delay, data, size, func, priv) tb_async_stream_writ_after_(stream, delay, data, size, func, priv __tb_debug_vals__)
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * types
- */
-
-/*! the stream open func type
- *
- * @param stream the stream
- * @param state the state
- * @param priv the func private data
- *
- * @return tb_true: ok, tb_false: error, but not break aicp
- */
-typedef tb_bool_t (*tb_async_stream_open_func_t)(tb_async_stream_ref_t stream, tb_size_t state, tb_cpointer_t priv);
-
-/*! the stream clos func type
- *
- * @param stream the stream
- * @param state the state
- * @param priv the func private data
- */
-typedef tb_void_t (*tb_async_stream_clos_func_t)(tb_async_stream_ref_t stream, tb_size_t state, tb_cpointer_t priv);
-
-/*! the stream read func type
- *
- * @param stream the stream
- * @param state the state
- * @param data the readed data
- * @param real the real size, maybe zero
- * @param size the need size
- * @param priv the func private data
- *
- * @return tb_true: ok and continue it if need, tb_false: break it, but not break aicp
- */
-typedef tb_bool_t (*tb_async_stream_read_func_t)(tb_async_stream_ref_t stream, tb_size_t state, tb_byte_t const* data, tb_size_t real, tb_size_t size, tb_cpointer_t priv);
-
-/*! the stream writ func type
- *
- * @param stream the stream
- * @param state the state
- * @param data the writed data
- * @param real the real size, maybe zero
- * @param size the need size
- * @param priv the func private data
- *
- * @return tb_true: ok and continue it if need, tb_false: break it, but not break aicp
- */
-typedef tb_bool_t (*tb_async_stream_writ_func_t)(tb_async_stream_ref_t stream, tb_size_t state, tb_byte_t const* data, tb_size_t real, tb_size_t size, tb_cpointer_t priv);
-
-/*! the stream seek func type
- *
- * @param stream the stream
- * @param state the state
- * @param offset the real offset
- * @param priv the func private data
- *
- * @return tb_true: ok, tb_false: error, but not break aicp
- */
-typedef tb_bool_t (*tb_async_stream_seek_func_t)(tb_async_stream_ref_t stream, tb_size_t state, tb_hize_t offset, tb_cpointer_t priv);
-
-/*! the stream sync func type
- *
- * @param stream the stream
- * @param state the state
- * @param bclosing is closing?
- * @param priv the func private data
- *
- * @return tb_true: ok, tb_false: error, but not break aicp
- */
-typedef tb_bool_t (*tb_async_stream_sync_func_t)(tb_async_stream_ref_t stream, tb_size_t state, tb_bool_t bclosing, tb_cpointer_t priv);
-
-/*! the stream task func type
- *
- * @param stream the stream
- * @param state the state
- * @param priv the func private data
- *
- * @return tb_true: ok, tb_false: error, but not break aicp
- */
-typedef tb_bool_t (*tb_async_stream_task_func_t)(tb_async_stream_ref_t stream, tb_size_t state, tb_cpointer_t priv);
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * interfaces
- */
-
-/*! init async stream
- *
- * @param aicp the aicp
- * @param type the stream type
- * @param type_size the stream type size
- * @param rcache the read cache size
- * @param wcache the writ cache size
- * @param open the stream impl func: open
- * @param clos the stream impl func: clos
- * @param exit the stream impl func: exit, optional
- * @param ctrl the stream impl func: ctrl
- * @param wait the stream impl func: wait
- * @param read the stream impl func: read
- * @param writ the stream impl func: writ
- * @param seek the stream impl func: seek, optional
- * @param sync the stream impl func: sync, optional
- * @param kill the stream impl func: kill, optional
- *
- * @return the stream
- *
- * @code
- // the custom xxxx async stream type
- typedef struct __tb_async_stream_xxxx_impl_t
- {
- // the xxxx data
- tb_handle_t xxxx;
-
- }tb_async_stream_xxxx_impl_t;
-
- static tb_bool_t tb_async_stream_xxxx_impl_open(tb_async_stream_ref_t stream, tb_async_stream_open_func_t func, tb_cpointer_t priv)
- {
- // check
- tb_async_stream_xxxx_impl_t* impl = (tb_async_stream_xxxx_impl_t*)stream;
- tb_assert_and_check_return_val(impl, tb_false);
-
- // ok
- return tb_true;
- }
- static tb_bool_t tb_async_stream_xxxx_impl_clos(tb_async_stream_ref_t stream, tb_async_stream_clos_func_t, tb_cpointer_t priv)
- {
- // check
- tb_async_stream_xxxx_impl_t* impl = (tb_async_stream_xxxx_impl_t*)stream;
- tb_assert_and_check_return_val(impl, tb_false);
-
- // ok
- return tb_true;
- }
-
- // define other xxxx async stream func
- // ...
-
- // init async stream
- tb_async_stream_ref_t stream = tb_async_stream_init( tb_aicp()
- , TB_STREAM_TYPE_XXXX
- , sizeof(tb_async_stream_xxxx_impl_t)
- , 0
- , 0
- , tb_async_stream_xxxx_impl_open_try
- , tb_async_stream_xxxx_impl_clos_try
- , tb_async_stream_xxxx_impl_open
- , tb_async_stream_xxxx_impl_clos
- , tb_async_stream_xxxx_impl_exit
- , tb_async_stream_xxxx_impl_kill
- , tb_async_stream_xxxx_impl_ctrl
- , tb_async_stream_xxxx_impl_read
- , tb_async_stream_xxxx_impl_writ
- , tb_async_stream_xxxx_impl_seek
- , tb_async_stream_xxxx_impl_sync
- , tb_async_stream_xxxx_impl_task
- );
-
- // using async stream
- // ...
-
- * @endcode
- */
-tb_async_stream_ref_t tb_async_stream_init( tb_aicp_ref_t aicp
- , tb_size_t type
- , tb_size_t type_size
- , tb_size_t rcache
- , tb_size_t wcache
- , tb_bool_t (*open_try)(tb_async_stream_ref_t stream)
- , tb_bool_t (*clos_try)(tb_async_stream_ref_t stream)
- , tb_bool_t (*open)(tb_async_stream_ref_t stream, tb_async_stream_open_func_t func, tb_cpointer_t priv)
- , tb_bool_t (*clos)(tb_async_stream_ref_t stream, tb_async_stream_clos_func_t func, tb_cpointer_t priv)
- , tb_bool_t (*exit)(tb_async_stream_ref_t stream)
- , tb_void_t (*kill)(tb_async_stream_ref_t stream)
- , tb_bool_t (*ctrl)(tb_async_stream_ref_t stream, tb_size_t ctrl, tb_va_list_t args)
- , tb_bool_t (*read)(tb_async_stream_ref_t stream, tb_size_t delay, tb_byte_t* data, tb_size_t size, tb_async_stream_read_func_t func, tb_cpointer_t priv)
- , tb_bool_t (*writ)(tb_async_stream_ref_t stream, tb_size_t delay, tb_byte_t const* data, tb_size_t size, tb_async_stream_writ_func_t func, tb_cpointer_t priv)
- , tb_bool_t (*seek)(tb_async_stream_ref_t stream, tb_hize_t offset, tb_async_stream_seek_func_t func, tb_cpointer_t priv)
- , tb_bool_t (*sync)(tb_async_stream_ref_t stream, tb_bool_t bclosing, tb_async_stream_sync_func_t func, tb_cpointer_t priv)
- , tb_bool_t (*task)(tb_async_stream_ref_t stream, tb_size_t delay, tb_async_stream_task_func_t func, tb_cpointer_t priv));
-
-/*! init data stream
- *
- * @param aicp the aicp, using the default aicp if be null
- *
- * @return the stream
- */
-tb_async_stream_ref_t tb_async_stream_init_data(tb_aicp_ref_t aicp);
-
-/*! init file stream
- *
- * @param aicp the aicp, using the default aicp if be null
- *
- * @return the stream
- */
-tb_async_stream_ref_t tb_async_stream_init_file(tb_aicp_ref_t aicp);
-
-/*! init sock stream
- *
- * @param aicp the aicp, using the default aicp if be null
- *
- * @return the stream
- */
-tb_async_stream_ref_t tb_async_stream_init_sock(tb_aicp_ref_t aicp);
-
-/*! init http stream
- *
- * @param aicp the aicp, using the default aicp if be null
- *
- * @return the stream
- */
-tb_async_stream_ref_t tb_async_stream_init_http(tb_aicp_ref_t aicp);
-
-/*! init filter stream
- *
- * @param aicp the aicp, using the default aicp if be null
- *
- * @return the stream
- */
-tb_async_stream_ref_t tb_async_stream_init_filter(tb_aicp_ref_t aicp);
-
-/*! exit stream
- *
- * @param stream the stream
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_stream_exit(tb_async_stream_ref_t stream);
-
-/*! init stream from url
- *
- * @param aicp the aicp, using the default aicp if be null
- * @param url the url
- * <pre>
- * data://base64
- * file://path or unix path: e.g. /root/xxxx/file
- * sock://host:port?tcp=
- * sock://host:port?udp=
- * socks://host:port
- * http://host:port/path?arg0=&arg1=...
- * https://host:port/path?arg0=&arg1=...
- * </pre>
- *
- * @return the stream
- */
-tb_async_stream_ref_t tb_async_stream_init_from_url(tb_aicp_ref_t aicp, tb_char_t const* url);
-
-/*! init stream from data
- *
- * @param aicp the aicp, using the default aicp if be null
- * @param data the data
- * @param size the size
- *
- * @return the stream
- */
-tb_async_stream_ref_t tb_async_stream_init_from_data(tb_aicp_ref_t aicp, tb_byte_t const* data, tb_size_t size);
-
-/*! init stream from file
- *
- * @param aicp the aicp, using the default aicp if be null
- * @param path the file path
- * @param mode the file mode, using the default ro mode if zero
- *
- * @return the stream
- */
-tb_async_stream_ref_t tb_async_stream_init_from_file(tb_aicp_ref_t aicp, tb_char_t const* path, tb_size_t mode);
-
-/*! init stream from sock
- *
- * @param aicp the aicp, using the default aicp if be null
- * @param host the host
- * @param port the port
- * @param type the socket type, tcp or udp
- * @param bssl enable ssl?
- *
- * @return the stream
- */
-tb_async_stream_ref_t tb_async_stream_init_from_sock(tb_aicp_ref_t aicp, tb_char_t const* host, tb_uint16_t port, tb_size_t type, tb_bool_t bssl);
-
-/*! init stream from http or https
- *
- * @param aicp the aicp, using the default aicp if be null
- * @param host the host
- * @param port the port
- * @param path the path
- * @param bssl enable ssl?
- *
- * @return the stream
- */
-tb_async_stream_ref_t tb_async_stream_init_from_http(tb_aicp_ref_t aicp, tb_char_t const* host, tb_uint16_t port, tb_char_t const* path, tb_bool_t bssl);
-
-/*! init filter stream from null
- *
- * @param stream the stream
- *
- * @return the stream
- */
-tb_async_stream_ref_t tb_async_stream_init_filter_from_null(tb_async_stream_ref_t stream);
-
-/*! init filter stream from zip
- *
- * @param stream the stream
- * @param algo the zip algorithm
- * @param action the zip action
- *
- * @return the stream
- */
-tb_async_stream_ref_t tb_async_stream_init_filter_from_zip(tb_async_stream_ref_t stream, tb_size_t algo, tb_size_t action);
-
-/*! init filter stream from cache
- *
- * @param stream the stream
- * @param size the initial cache size, using the default size if be zero
- *
- * @return the stream
- */
-tb_async_stream_ref_t tb_async_stream_init_filter_from_cache(tb_async_stream_ref_t stream, tb_size_t size);
-
-/*! init filter stream from charset
- *
- * @param stream the stream
- * @param fr the from charset
- * @param to the to charset
- *
- * @return the stream
- */
-tb_async_stream_ref_t tb_async_stream_init_filter_from_charset(tb_async_stream_ref_t stream, tb_size_t fr, tb_size_t to);
-
-/*! init filter stream from chunked
- *
- * @param stream the stream
- * @param dechunked decode the chunked data?
- *
- * @return the stream
- */
-tb_async_stream_ref_t tb_async_stream_init_filter_from_chunked(tb_async_stream_ref_t stream, tb_bool_t dechunked);
-
-/*! the stream url
- *
- * @param stream the stream
- *
- * @return the stream url
- */
-tb_url_ref_t tb_async_stream_url(tb_async_stream_ref_t stream);
-
-/*! the stream type
- *
- * @param stream the stream
- *
- * @return the stream type
- */
-tb_size_t tb_async_stream_type(tb_async_stream_ref_t stream);
-
-/*! the stream size and not seeking it
- *
- * @param stream the stream
- *
- * @return the stream size, no size: -1, empty or error: 0
- */
-tb_hong_t tb_async_stream_size(tb_async_stream_ref_t stream);
-
-/*! the stream left size and not seeking it
- *
- * @param stream the stream
- *
- * @return the stream left size, no size: infinity, empty or end: 0
- */
-tb_hize_t tb_async_stream_left(tb_async_stream_ref_t stream);
-
-/*! the stream is end?
- *
- * @param stream the stream
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_stream_beof(tb_async_stream_ref_t stream);
-
-/*! the stream offset
- *
- * the offset is read + writ and using seek for modifying it if size != -1, .e.g: data, file, ..
- * the offset is calculated from the last read/writ and not seeking it if size == -1, .e.g: sock, filter, ..
- *
- * @param stream the stream
- *
- * @return the stream offset
- */
-tb_hize_t tb_async_stream_offset(tb_async_stream_ref_t stream);
-
-/*! is opened?
- *
- * @param stream the stream
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_stream_is_opened(tb_async_stream_ref_t stream);
-
-/*! is closed?
- *
- * @param stream the stream
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_stream_is_closed(tb_async_stream_ref_t stream);
-
-/*! is killed?
- *
- * @param stream the stream
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_stream_is_killed(tb_async_stream_ref_t stream);
-
-/*! the stream timeout
- *
- * @param stream the stream
- *
- * @return the stream timeout
- */
-tb_long_t tb_async_stream_timeout(tb_async_stream_ref_t stream);
-
-/*! ctrl stream
- *
- * @param stream the stream
- * @param ctrl the ctrl code
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_stream_ctrl(tb_async_stream_ref_t stream, tb_size_t ctrl, ...);
-
-/*! ctrl stream with arguments
- *
- * @param stream the stream
- * @param ctrl the ctrl code
- * @param args the ctrl args
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_stream_ctrl_with_args(tb_async_stream_ref_t stream, tb_size_t ctrl, tb_va_list_t args);
-
-/*! kill stream
- *
- * @param stream the stream
- */
-tb_void_t tb_async_stream_kill(tb_async_stream_ref_t stream);
-
-/*! try opening the stream for stream: file, filter, ...
- *
- * @param stream the stream
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_stream_open_try(tb_async_stream_ref_t stream);
-
-/*! open the stream
- *
- * @param stream the stream
- * @param func the func
- * @param priv the func data
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_stream_open_(tb_async_stream_ref_t stream, tb_async_stream_open_func_t func, tb_cpointer_t priv __tb_debug_decl__);
-
-/*! try closing the stream for stream: file, filter, or closed stream...
- *
- * @param stream the stream
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_stream_clos_try(tb_async_stream_ref_t stream);
-
-/*! close the stream
- *
- * @param stream the stream
- * @param func the func
- * @param priv the func data
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_stream_clos_(tb_async_stream_ref_t stream, tb_async_stream_clos_func_t func, tb_cpointer_t priv __tb_debug_decl__);
-
-/*! read the stream
- *
- * @param stream the stream
- * @param size the read size, using the default size if be zero
- * @param func the func
- * @param priv the func data
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_stream_read_(tb_async_stream_ref_t stream, tb_size_t size, tb_async_stream_read_func_t func, tb_cpointer_t priv __tb_debug_decl__);
-
-/*! writ the stream
- *
- * @param stream the stream
- * @param data the data
- * @param size the size
- * @param func the func
- * @param priv the func data
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_stream_writ_(tb_async_stream_ref_t stream, tb_byte_t const* data, tb_size_t size, tb_async_stream_writ_func_t func, tb_cpointer_t priv __tb_debug_decl__);
-
-/*! seek the stream
- *
- * @param stream the stream
- * @param offset the offset
- * @param func the func
- * @param priv the func data
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_stream_seek_(tb_async_stream_ref_t stream, tb_hize_t offset, tb_async_stream_seek_func_t func, tb_cpointer_t priv __tb_debug_decl__);
-
-/*! sync the stream
- *
- * @param stream the stream
- * @param bclosing sync the tail data for closing
- * @param func the func
- * @param priv the func data
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_stream_sync_(tb_async_stream_ref_t stream, tb_bool_t bclosing, tb_async_stream_sync_func_t func, tb_cpointer_t priv __tb_debug_decl__);
-
-/*! task the stream
- *
- * @param stream the stream
- * @param delay the delay time, ms
- * @param func the func
- * @param priv the func data
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_stream_task_(tb_async_stream_ref_t stream, tb_size_t delay, tb_async_stream_task_func_t func, tb_cpointer_t priv __tb_debug_decl__);
-
-/*! open and read the stream, open it first if not opened
- *
- * @param stream the stream
- * @param size the read size, using the default size if be zero
- * @param func the func
- * @param priv the func data
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_stream_read_(tb_async_stream_ref_t stream, tb_size_t size, tb_async_stream_read_func_t func, tb_cpointer_t priv __tb_debug_decl__);
-
-/*! open and read the stream, open it first if not opened
- *
- * @param stream the stream
- * @param size the size, using the default size be zero
- * @param func the func
- * @param priv the func data
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_stream_open_read_(tb_async_stream_ref_t stream, tb_size_t size, tb_async_stream_read_func_t func, tb_cpointer_t priv __tb_debug_decl__);
-
-/*! open and writ the stream, open it first if not opened
- *
- * @param stream the stream
- * @param data the data
- * @param size the size
- * @param func the func
- * @param priv the func data
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_stream_open_writ_(tb_async_stream_ref_t stream, tb_byte_t const* data, tb_size_t size, tb_async_stream_writ_func_t func, tb_cpointer_t priv __tb_debug_decl__);
-
-/*! open and seek the stream, open it first if not opened
- *
- * @param stream the stream
- * @param offset the offset
- * @param func the func
- * @param priv the func data
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_stream_open_seek_(tb_async_stream_ref_t stream, tb_hize_t offset, tb_async_stream_seek_func_t func, tb_cpointer_t priv __tb_debug_decl__);
-
-/*! read the stream after the delay time
- *
- * @param stream the stream
- * @param delay the delay time, ms
- * @param size the read size, using the default size if be zero
- * @param func the func
- * @param priv the func data
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_stream_read_after_(tb_async_stream_ref_t stream, tb_size_t delay, tb_size_t size, tb_async_stream_read_func_t func, tb_cpointer_t priv __tb_debug_decl__);
-
-/*! writ the stream after the delay time
- *
- * @param stream the stream
- * @param delay the delay time, ms
- * @param data the data
- * @param size the size
- * @param func the func
- * @param priv the func data
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_stream_writ_after_(tb_async_stream_ref_t stream, tb_size_t delay, tb_byte_t const* data, tb_size_t size, tb_async_stream_writ_func_t func, tb_cpointer_t priv __tb_debug_decl__);
-
-/*! the stream aicp
- *
- * @param stream the stream
- *
- * @return the stream aicp
- */
-tb_aicp_ref_t tb_async_stream_aicp(tb_async_stream_ref_t stream);
-
-#ifdef __tb_debug__
-/*! the stream func name from post for debug
- *
- * @param stream the stream
- *
- * @return the stream func name
- */
-tb_char_t const* tb_async_stream_func(tb_async_stream_ref_t stream);
-
-/*! the stream file name from post for debug
- *
- * @param stream the stream
- *
- * @return the stream file name
- */
-tb_char_t const* tb_async_stream_file(tb_async_stream_ref_t stream);
-
-/*! the stream line number from post for debug
- *
- * @param stream the stream
- *
- * @return the stream line number
- */
-tb_size_t tb_async_stream_line(tb_async_stream_ref_t stream);
-#endif
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * extern
- */
-__tb_extern_c_leave__
-
-#endif
diff --git a/core/src/tbox/src/tbox/stream/deprecated/async_transfer.c b/core/src/tbox/src/tbox/stream/deprecated/async_transfer.c
deleted file mode 100644
index c72213dd9..000000000
--- a/core/src/tbox/src/tbox/stream/deprecated/async_transfer.c
+++ /dev/null
@@ -1,1284 +0,0 @@
-/*!The Treasure Box Library
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
- *
- * @author ruki
- * @file async_transfer.c
- * @ingroup stream
- *
- */
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * trace
- */
-#define TB_TRACE_MODULE_NAME "async_transfer"
-#define TB_TRACE_MODULE_DEBUG (1)
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
- */
-#include "../stream.h"
-#include "async_transfer.h"
-#include "../../network/network.h"
-#include "../../platform/platform.h"
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * types
- */
-
-// the async impl open type
-typedef struct __tb_async_transfer_open_t_t
-{
- // the func
- tb_async_transfer_open_func_t func;
-
- // the priv
- tb_cpointer_t priv;
-
-}tb_async_transfer_open_t_t;
-
-// the async impl ctrl type
-typedef struct __tb_async_transfer_ctrl_t_t
-{
- // the func
- tb_async_transfer_ctrl_func_t func;
-
- // the priv
- tb_cpointer_t priv;
-
-}tb_async_transfer_ctrl_t_t;
-
-// the async impl clos type
-typedef struct __tb_async_transfer_clos_t_t
-{
- // the func
- tb_async_transfer_clos_func_t func;
-
- // the priv
- tb_cpointer_t priv;
-
-}tb_async_transfer_clos_t_t;
-
-// the async impl done type
-typedef struct __tb_async_transfer_done_t_t
-{
- // the func
- tb_async_transfer_done_func_t func;
-
- // the priv
- tb_cpointer_t priv;
-
- // the base_time time
- tb_hong_t base_time;
-
- // the base_time time for 1s
- tb_hong_t base_time1s;
-
- // the saved_size size
- tb_hize_t saved_size;
-
- // the saved_size size for 1s
- tb_size_t saved_size1s;
-
- // the closed size
- tb_hong_t closed_size;
-
- // the closed state
- tb_size_t closed_state;
-
- // the closed offset
- tb_hize_t closed_offset;
-
- // the current rate
- tb_size_t current_rate;
-
-}tb_async_transfer_done_t_t;
-
-// the async impl close opening type
-typedef struct __tb_async_transfer_clos_opening_t_t
-{
- // the func
- tb_async_transfer_open_func_t func;
-
- // the priv
- tb_cpointer_t priv;
-
- // the open state
- tb_size_t state;
-
-}tb_async_transfer_clos_opening_t_t;
-
-// the async impl type
-typedef struct __tb_async_transfer_impl_t
-{
- // the aicp
- tb_aicp_ref_t aicp;
-
- // the istream
- tb_async_stream_ref_t istream;
-
- // the ostream
- tb_async_stream_ref_t ostream;
-
- // the istream is owner?
- tb_uint8_t iowner : 1;
-
- // the ostream is owner?
- tb_uint8_t oowner : 1;
-
- // auto closing it?
- tb_uint8_t autoclosing : 1;
-
- /* state
- *
- * TB_STATE_CLOSED
- * TB_STATE_OPENED
- * TB_STATE_OPENING
- * TB_STATE_KILLING
- */
- tb_atomic_t state;
-
- /* pause state
- *
- * TB_STATE_OK
- * TB_STATE_PAUSED
- * TB_STATE_PAUSING
- */
- tb_atomic_t state_pause;
-
- // the limited rate
- tb_atomic_t limited_rate;
-
- // the ctrl
- tb_async_transfer_ctrl_t_t ctrl;
-
- // the open
- tb_async_transfer_open_t_t open;
-
- // the clos
- tb_async_transfer_clos_t_t clos;
-
- // the done
- tb_async_transfer_done_t_t done;
-
- // the clos opening
- tb_async_transfer_clos_opening_t_t clos_opening;
-
-}tb_async_transfer_impl_t;
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
- */
-static tb_void_t tb_async_transfer_clos_func(tb_async_transfer_impl_t* impl, tb_size_t state)
-{
- // check
- tb_assert_and_check_return(impl && impl->clos.func);
-
- // trace
- tb_trace_d("closed");
-
- // closed
- tb_atomic_set(&impl->state, TB_STATE_CLOSED);
-
- // clear pause state
- tb_atomic_set(&impl->state_pause, TB_STATE_OK);
-
- // done func
- impl->clos.func(state, impl->clos.priv);
-}
-static tb_void_t tb_async_transfer_clos_opening_func(tb_size_t state, tb_cpointer_t priv)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)priv;
- tb_assert_and_check_return(impl && impl->clos_opening.func);
-
- // trace
- tb_trace_d("clos: opening");
-
- // done
- impl->clos_opening.func(impl->clos_opening.state, 0, 0, impl->clos_opening.priv);
-}
-static tb_bool_t tb_async_transfer_open_func(tb_async_transfer_impl_t* impl, tb_size_t state, tb_hize_t offset, tb_hong_t size, tb_async_transfer_open_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_assert_and_check_return_val(impl, tb_false);
-
- // ok?
- tb_bool_t ok = tb_true;
- if (state == TB_STATE_OK)
- {
- // opened
- tb_atomic_set(&impl->state, TB_STATE_OPENED);
-
- // done func
- if (func) ok = func(state, offset, size, priv);
- }
- // failed?
- else
- {
- // init func and state
- impl->clos_opening.func = func;
- impl->clos_opening.priv = priv;
- impl->clos_opening.state = state;
-
- // close it
- ok = tb_async_transfer_clos((tb_async_transfer_ref_t)impl, tb_async_transfer_clos_opening_func, impl);
- }
-
- // ok?
- return ok;
-}
-static tb_void_t tb_async_transfer_done_clos_func(tb_size_t state, tb_cpointer_t priv);
-static tb_bool_t tb_async_transfer_done_func(tb_async_transfer_impl_t* impl, tb_size_t state)
-{
- // check
- tb_assert_and_check_return_val(impl && impl->istream && impl->done.func, tb_false);
-
- // open failed? closed?
- if (TB_STATE_CLOSED == tb_atomic_get(&impl->state))
- {
- // done func
- return impl->done.func(state, 0, 0, 0, 0, impl->done.priv);
- }
-
- // trace
- tb_trace_d("done: %llu bytes, rate: %lu bytes/s, state: %s", tb_async_stream_offset(impl->istream), impl->done.current_rate, tb_state_cstr(state));
-
- // auto closing it?
- if (impl->autoclosing)
- {
- // killed or failed or closed? close it
- if ((state != TB_STATE_OK && state != TB_STATE_PAUSED) || (TB_STATE_KILLING == tb_atomic_get(&impl->state)))
- {
- // save the closed state
- impl->done.closed_state = (TB_STATE_KILLING == tb_atomic_get(&impl->state))? TB_STATE_KILLED : state;
- impl->done.closed_size = tb_async_stream_size(impl->istream);
- impl->done.closed_offset = tb_async_stream_offset(impl->istream);
- return tb_async_transfer_clos((tb_async_transfer_ref_t)impl, tb_async_transfer_done_clos_func, impl);
- }
- }
-
- // done
- return impl->done.func(state, tb_async_stream_offset(impl->istream), tb_async_stream_size(impl->istream), impl->done.saved_size, impl->done.current_rate, impl->done.priv);
-}
-static tb_void_t tb_async_transfer_done_clos_func(tb_size_t state, tb_cpointer_t priv)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)priv;
- tb_assert_and_check_return(impl && impl->done.func);
-
- // trace
- tb_trace_d("done: closed");
-
- // done
- impl->done.func(impl->done.closed_state, impl->done.closed_offset, impl->done.closed_size, impl->done.saved_size, impl->done.current_rate, impl->done.priv);
-}
-static tb_bool_t tb_async_transfer_open_done_func(tb_size_t state, tb_hize_t offset, tb_hong_t size, tb_cpointer_t priv)
-{
- // the impl
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)priv;
- tb_assert_and_check_return_val(impl && impl->done.func, tb_false);
-
- // trace
- tb_trace_d("open_done: offset: %llu, size: %lld, state: %s", offset, size, tb_state_cstr(state));
-
- // done
- tb_bool_t ok = tb_true;
- do
- {
- // ok?
- tb_check_break(state == TB_STATE_OK);
-
- // reset state
- state = TB_STATE_UNKNOWN_ERROR;
-
- // killed?
- if (TB_STATE_KILLING == tb_atomic_get(&impl->state))
- {
- state = TB_STATE_KILLED;
- break;
- }
-
- // done it
- if (!tb_async_transfer_done((tb_async_transfer_ref_t)impl, impl->done.func, impl->done.priv)) break;
-
- // ok
- state = TB_STATE_OK;
-
- } while (0);
-
- // failed?
- if (state != TB_STATE_OK)
- {
- // done func for closing it
- ok = tb_async_transfer_done_func(impl, state);
- }
-
- // ok?
- return ok;
-}
-static tb_bool_t tb_async_transfer_istream_read_func(tb_async_stream_ref_t stream, tb_size_t state, tb_byte_t const* data, tb_size_t real, tb_size_t size, tb_cpointer_t priv);
-static tb_bool_t tb_async_transfer_ostream_writ_func(tb_async_stream_ref_t stream, tb_size_t state, tb_byte_t const* data, tb_size_t real, tb_size_t size, tb_cpointer_t priv)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)priv;
- tb_assert_and_check_return_val(stream && impl && impl->aicp && impl->istream, tb_false);
-
- // trace
- tb_trace_d("writ: real: %lu, size: %lu, state: %s", real, size, tb_state_cstr(state));
-
- // the time
- tb_hong_t time = tb_aicp_time(impl->aicp);
-
- // done
- tb_bool_t bwrit = tb_false;
- do
- {
- // ok?
- tb_check_break(state == TB_STATE_OK);
-
- // reset state
- state = TB_STATE_UNKNOWN_ERROR;
-
- // done func at first once
- if (!impl->done.saved_size && !tb_async_transfer_done_func(impl, TB_STATE_OK)) break;
-
- // update saved size
- impl->done.saved_size += real;
-
- // < 1s?
- tb_size_t delay = 0;
- tb_size_t limited_rate = tb_atomic_get(&impl->limited_rate);
- if (time < impl->done.base_time1s + 1000)
- {
- // save size for 1s
- impl->done.saved_size1s += real;
-
- // save current rate if < 1s from base_time
- if (time < impl->done.base_time + 1000) impl->done.current_rate = impl->done.saved_size1s;
-
- // compute the delay for limit rate
- if (limited_rate) delay = impl->done.saved_size1s >= limited_rate? (tb_size_t)(impl->done.base_time1s + 1000 - time) : 0;
- }
- else
- {
- // save current rate
- impl->done.current_rate = impl->done.saved_size1s;
-
- // update base_time1s
- impl->done.base_time1s = time;
-
- // reset size
- impl->done.saved_size1s = 0;
-
- // reset delay
- delay = 0;
-
- // done func
- if (!tb_async_transfer_done_func(impl, TB_STATE_OK)) break;
- }
-
- // killed?
- if (TB_STATE_KILLING == tb_atomic_get(&impl->state))
- {
- state = TB_STATE_KILLED;
- break;
- }
-
- // not finished? continue to writ
- tb_size_t state_pause = TB_STATE_OK;
- if (real < size) bwrit = tb_true;
- // pausing or paused?
- else if ( (TB_STATE_PAUSED == (state_pause = tb_atomic_fetch_and_pset(&impl->state_pause, TB_STATE_PAUSING, TB_STATE_PAUSED)))
- || (state_pause == TB_STATE_PAUSING))
- {
- // done func
- if (!tb_async_transfer_done_func(impl, TB_STATE_PAUSED)) break;
- }
- // continue?
- else
- {
- // trace
- tb_trace_d("delay: %lu ms", delay);
-
- // continue to read it
- if (!tb_async_stream_read_after(impl->istream, delay, limited_rate, tb_async_transfer_istream_read_func, (tb_pointer_t)impl)) break;
- }
-
- // ok
- state = TB_STATE_OK;
-
- } while (0);
-
- // failed?
- if (state != TB_STATE_OK)
- {
- // compute the total rate
- impl->done.current_rate = (impl->done.saved_size && (time > impl->done.base_time))? (tb_size_t)((impl->done.saved_size * 1000) / (time - impl->done.base_time)) : (tb_size_t)impl->done.saved_size;
-
- // done func
- tb_async_transfer_done_func(impl, state);
-
- // break;
- bwrit = tb_false;
- }
-
- // continue to writ or break it
- return bwrit;
-}
-static tb_bool_t tb_async_transfer_ostream_sync_func(tb_async_stream_ref_t stream, tb_size_t state, tb_bool_t bclosing, tb_cpointer_t priv)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)priv;
- tb_assert_and_check_return_val(stream && impl && impl->aicp && impl->istream, tb_false);
-
- // trace
- tb_trace_d("sync: state: %s", tb_state_cstr(state));
-
- // the time
- tb_hong_t time = tb_aicp_time(impl->aicp);
-
- // compute the total rate
- impl->done.current_rate = (impl->done.saved_size && (time > impl->done.base_time))? (tb_size_t)((impl->done.saved_size * 1000) / (time - impl->done.base_time)) : (tb_size_t)impl->done.saved_size;
-
- // done func
- return tb_async_transfer_done_func(impl, state == TB_STATE_OK? TB_STATE_CLOSED : state);
-}
-static tb_bool_t tb_async_transfer_istream_read_func(tb_async_stream_ref_t stream, tb_size_t state, tb_byte_t const* data, tb_size_t real, tb_size_t size, tb_cpointer_t priv)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)priv;
- tb_assert_and_check_return_val(stream && impl && impl->aicp && impl->ostream, tb_false);
-
- // trace
- tb_trace_d("read: size: %lu, state: %s", real, tb_state_cstr(state));
-
- // done
- tb_bool_t bread = tb_false;
- do
- {
- // ok?
- tb_check_break(state == TB_STATE_OK);
-
- // reset state
- state = TB_STATE_UNKNOWN_ERROR;
-
- // killed?
- if (TB_STATE_KILLING == tb_atomic_get(&impl->state))
- {
- state = TB_STATE_KILLED;
- break;
- }
-
- // check
- tb_assert_and_check_break(data);
-
- // no data? continue it
- if (!real)
- {
- bread = tb_true;
- state = TB_STATE_OK;
- break;
- }
-
- // writ it
- if (!tb_async_stream_writ(impl->ostream, data, real, tb_async_transfer_ostream_writ_func, impl)) break;
-
- // ok
- state = TB_STATE_OK;
-
- } while (0);
-
- // closed or failed?
- if (state != TB_STATE_OK)
- {
- // sync it if closed
- tb_bool_t bend = tb_true;
- if (state == TB_STATE_CLOSED)
- bend = tb_async_stream_sync(impl->ostream, tb_true, tb_async_transfer_ostream_sync_func, impl)? tb_false : tb_true;
-
- // end?
- if (bend)
- {
- // the time
- tb_hong_t time = tb_aicp_time(impl->aicp);
-
- // compute the total rate
- impl->done.current_rate = (impl->done.saved_size && (time > impl->done.base_time))? (tb_size_t)((impl->done.saved_size * 1000) / (time - impl->done.base_time)) : (tb_size_t)impl->done.saved_size;
-
- // done func
- tb_async_transfer_done_func(impl, state);
- }
-
- // break
- bread = tb_false;
- }
-
- // continue to read or break it
- return bread;
-}
-static tb_bool_t tb_async_transfer_ostream_open_func(tb_async_stream_ref_t stream, tb_size_t state, tb_cpointer_t priv)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)priv;
- tb_assert_and_check_return_val(stream && impl && impl->open.func, tb_false);
-
- // trace
- tb_trace_d("open: ostream: %s, state: %s", tb_url_cstr(tb_async_stream_url(stream)), tb_state_cstr(state));
-
- // done
- tb_bool_t ok = tb_true;
- do
- {
- // ok?
- tb_check_break(state == TB_STATE_OK);
-
- // reset state
- state = TB_STATE_UNKNOWN_ERROR;
-
- // check
- tb_assert_and_check_break(impl->istream);
-
- // killed?
- if (TB_STATE_KILLING == tb_atomic_get(&impl->state))
- {
- state = TB_STATE_KILLED;
- break;
- }
-
- // done func
- ok = tb_async_transfer_open_func(impl, TB_STATE_OK, tb_async_stream_offset(impl->istream), tb_async_stream_size(impl->istream), impl->open.func, impl->open.priv);
-
- // ok
- state = TB_STATE_OK;
-
- } while (0);
-
- // failed?
- if (state != TB_STATE_OK)
- {
- // done func
- ok = tb_async_transfer_open_func(impl, state, 0, 0, impl->open.func, impl->open.priv);
- }
-
- // ok
- return ok;
-}
-static tb_bool_t tb_async_transfer_istream_open_func(tb_async_stream_ref_t stream, tb_size_t state, tb_hize_t offset, tb_cpointer_t priv)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)priv;
- tb_assert_and_check_return_val(stream && impl && impl->open.func, tb_false);
-
- // trace
- tb_trace_d("open: istream: %s, offset: %llu, state: %s", tb_url_cstr(tb_async_stream_url(stream)), offset, tb_state_cstr(state));
-
- // done
- tb_bool_t ok = tb_true;
- do
- {
- // ok?
- tb_check_break(state == TB_STATE_OK);
-
- // reset state
- state = TB_STATE_UNKNOWN_ERROR;
-
- // killed?
- if (TB_STATE_KILLING == tb_atomic_get(&impl->state))
- {
- state = TB_STATE_KILLED;
- break;
- }
-
- // open it
- if (!tb_async_stream_open(impl->ostream, tb_async_transfer_ostream_open_func, impl)) break;
-
- // ok
- state = TB_STATE_OK;
-
- } while (0);
-
- // failed?
- if (state != TB_STATE_OK)
- {
- // done func
- ok = tb_async_transfer_open_func(impl, state, 0, 0, impl->open.func, impl->open.priv);
- }
-
- // ok?
- return ok;
-}
-static tb_void_t tb_async_transfer_ostream_clos_func(tb_async_stream_ref_t stream, tb_size_t state, tb_cpointer_t priv)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)priv;
- tb_assert_and_check_return(stream && impl);
-
- // trace
- tb_trace_d("clos: ostream: %s, state: %s", tb_url_cstr(tb_async_stream_url(stream)), tb_state_cstr(state));
-
- // done func
- tb_async_transfer_clos_func(impl, state);
-}
-static tb_void_t tb_async_transfer_istream_clos_func(tb_async_stream_ref_t stream, tb_size_t state, tb_cpointer_t priv)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)priv;
- tb_assert_and_check_return(stream && impl);
-
- // trace
- tb_trace_d("clos: istream: %s, state: %s", tb_url_cstr(tb_async_stream_url(stream)), tb_state_cstr(state));
-
- // done
- do
- {
- // ok?
- tb_check_break(state == TB_STATE_OK);
-
- // reset state
- state = TB_STATE_UNKNOWN_ERROR;
-
- // clos it
- if (!tb_async_stream_clos(impl->ostream, tb_async_transfer_ostream_clos_func, impl)) break;
-
- // ok
- state = TB_STATE_OK;
-
- } while (0);
-
- // failed?
- if (state != TB_STATE_OK)
- {
- // trace
- tb_trace_e("clos: failed: %s", tb_state_cstr(state));
-
- // done func
- tb_async_transfer_clos_func(impl, state);
- }
-}
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * interfaces
- */
-tb_async_transfer_ref_t tb_async_transfer_init(tb_aicp_ref_t aicp, tb_bool_t autoclosing)
-{
- // using the default aicp
- if (!aicp) aicp = tb_aicp();
- tb_assert_and_check_return_val(aicp, tb_null);
-
- // make impl
- tb_async_transfer_impl_t* impl = tb_malloc0_type(tb_async_transfer_impl_t);
- tb_assert_and_check_return_val(impl, tb_null);
-
- // init state
- impl->state = TB_STATE_CLOSED;
- impl->state_pause = TB_STATE_OK;
- impl->autoclosing = autoclosing? 1 : 0;
-
- // init aicp
- impl->aicp = aicp;
-
- // ok?
- return (tb_async_transfer_ref_t)impl;
-}
-tb_bool_t tb_async_transfer_init_istream(tb_async_transfer_ref_t transfer, tb_async_stream_ref_t stream)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)transfer;
- tb_assert_and_check_return_val(impl, tb_false);
-
- // muse be closed
- tb_assert_and_check_return_val(TB_STATE_CLOSED == tb_atomic_get(&impl->state), tb_false);
-
- // exit the previous stream first
- if (impl->istream && impl->istream != stream)
- {
- if (impl->iowner) tb_async_stream_exit(impl->istream);
- impl->istream = tb_null;
- }
-
- // init stream
- impl->istream = stream;
- impl->iowner = 0;
-
- // ok
- return tb_true;
-}
-tb_bool_t tb_async_transfer_init_istream_from_url(tb_async_transfer_ref_t transfer, tb_char_t const* url)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)transfer;
- tb_assert_and_check_return_val(impl && impl->aicp && url, tb_false);
-
- // muse be closed
- tb_assert_and_check_return_val(TB_STATE_CLOSED == tb_atomic_get(&impl->state), tb_false);
-
- // check stream type
- if (impl->istream)
- {
- // probe protocol
- tb_size_t protocol = tb_url_protocol_probe(url);
- tb_assert_static((tb_size_t)TB_URL_PROTOCOL_FILE == (tb_size_t)TB_STREAM_TYPE_FILE);
- tb_assert_static((tb_size_t)TB_URL_PROTOCOL_HTTP == (tb_size_t)TB_STREAM_TYPE_HTTP);
- tb_assert_static((tb_size_t)TB_URL_PROTOCOL_SOCK == (tb_size_t)TB_STREAM_TYPE_SOCK);
- tb_assert_static((tb_size_t)TB_URL_PROTOCOL_DATA == (tb_size_t)TB_STREAM_TYPE_DATA);
-
- // protocol => type
- tb_size_t type = protocol;
- if (!type || type > TB_STREAM_TYPE_DATA)
- {
- tb_trace_e("unknown stream for url: %s", url);
- return tb_false;
- }
-
- // exit the previous stream first if be different stream type
- if (tb_async_stream_type(impl->istream) != type)
- {
- if (impl->iowner) tb_async_stream_exit(impl->istream);
- impl->istream = tb_null;
- }
- }
-
- // using the previous stream?
- if (impl->istream)
- {
- // ctrl stream
- if (!tb_async_stream_ctrl(impl->istream, TB_STREAM_CTRL_SET_URL, url)) return tb_false;
- }
- else
- {
- // init stream
- impl->istream = tb_async_stream_init_from_url(impl->aicp, url);
- tb_assert_and_check_return_val(impl->istream, tb_false);
-
- // init owner
- impl->iowner = 1;
- }
-
- // ok
- return tb_true;
-}
-tb_bool_t tb_async_transfer_init_istream_from_data(tb_async_transfer_ref_t transfer, tb_byte_t const* data, tb_size_t size)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)transfer;
- tb_assert_and_check_return_val(impl && impl->aicp && data && size, tb_false);
-
- // muse be closed
- tb_assert_and_check_return_val(TB_STATE_CLOSED == tb_atomic_get(&impl->state), tb_false);
-
- // exit the previous stream first if be not data stream
- if (impl->istream && tb_async_stream_type(impl->istream) != TB_STREAM_TYPE_DATA)
- {
- if (impl->iowner) tb_async_stream_exit(impl->istream);
- impl->istream = tb_null;
- }
-
- // using the previous stream?
- if (impl->istream)
- {
- // ctrl stream
- if (!tb_async_stream_ctrl(impl->istream, TB_STREAM_CTRL_DATA_SET_DATA, data, size)) return tb_false;
- }
- else
- {
- // init stream
- impl->istream = tb_async_stream_init_from_data(impl->aicp, (tb_byte_t*)data, size);
- tb_assert_and_check_return_val(impl->istream, tb_false);
-
- // init owner
- impl->iowner = 1;
- }
-
- // ok
- return tb_true;
-}
-tb_bool_t tb_async_transfer_init_ostream(tb_async_transfer_ref_t transfer, tb_async_stream_ref_t stream)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)transfer;
- tb_assert_and_check_return_val(impl, tb_false);
-
- // muse be closed
- tb_assert_and_check_return_val(TB_STATE_CLOSED == tb_atomic_get(&impl->state), tb_false);
-
- // exit the previous stream first
- if (impl->ostream && impl->ostream != stream)
- {
- if (impl->oowner) tb_async_stream_exit(impl->ostream);
- impl->ostream = tb_null;
- }
-
- // init stream
- impl->ostream = stream;
- impl->oowner = 0;
-
- // ok
- return tb_true;
-}
-tb_bool_t tb_async_transfer_init_ostream_from_url(tb_async_transfer_ref_t transfer, tb_char_t const* url)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)transfer;
- tb_assert_and_check_return_val(impl && impl->aicp && url, tb_false);
-
- // muse be closed
- tb_assert_and_check_return_val(TB_STATE_CLOSED == tb_atomic_get(&impl->state), tb_false);
-
- // check stream type
- if (impl->ostream)
- {
- // probe protocol
- tb_size_t protocol = tb_url_protocol_probe(url);
- tb_assert_static((tb_size_t)TB_URL_PROTOCOL_FILE == (tb_size_t)TB_STREAM_TYPE_FILE);
- tb_assert_static((tb_size_t)TB_URL_PROTOCOL_HTTP == (tb_size_t)TB_STREAM_TYPE_HTTP);
- tb_assert_static((tb_size_t)TB_URL_PROTOCOL_SOCK == (tb_size_t)TB_STREAM_TYPE_SOCK);
- tb_assert_static((tb_size_t)TB_URL_PROTOCOL_DATA == (tb_size_t)TB_STREAM_TYPE_DATA);
-
- // protocol => type
- tb_size_t type = protocol;
- if (!type || type > TB_STREAM_TYPE_DATA)
- {
- tb_trace_e("unknown stream for url: %s", url);
- return tb_false;
- }
-
- // exit the previous stream first if be different stream type
- if (tb_async_stream_type(impl->ostream) != type)
- {
- if (impl->oowner) tb_async_stream_exit(impl->ostream);
- impl->ostream = tb_null;
- }
- }
-
- // using the previous stream?
- if (impl->ostream)
- {
- // ctrl stream
- if (!tb_async_stream_ctrl(impl->ostream, TB_STREAM_CTRL_SET_URL, url)) return tb_false;
- }
- else
- {
- // init stream
- impl->ostream = tb_async_stream_init_from_url(impl->aicp, url);
- tb_assert_and_check_return_val(impl->ostream, tb_false);
-
- // ctrl stream for file
- if (tb_async_stream_type(impl->ostream) == TB_STREAM_TYPE_FILE)
- {
- // ctrl mode
- if (!tb_async_stream_ctrl(impl->ostream, TB_STREAM_CTRL_FILE_SET_MODE, TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC)) return tb_false;
- }
-
- // init owner
- impl->oowner = 1;
- }
-
- // ok
- return tb_true;
-}
-tb_bool_t tb_async_transfer_init_ostream_from_data(tb_async_transfer_ref_t transfer, tb_byte_t* data, tb_size_t size)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)transfer;
- tb_assert_and_check_return_val(impl && impl->aicp && data && size, tb_false);
-
- // muse be closed
- tb_assert_and_check_return_val(TB_STATE_CLOSED == tb_atomic_get(&impl->state), tb_false);
-
- // exit the previous stream first if be not data stream
- if (impl->ostream && tb_async_stream_type(impl->ostream) != TB_STREAM_TYPE_DATA)
- {
- if (impl->oowner) tb_async_stream_exit(impl->ostream);
- impl->ostream = tb_null;
- }
-
- // using the previous stream?
- if (impl->ostream)
- {
- // ctrl stream
- if (!tb_async_stream_ctrl(impl->ostream, TB_STREAM_CTRL_DATA_SET_DATA, data, size)) return tb_false;
- }
- else
- {
- // init stream
- impl->ostream = tb_async_stream_init_from_data(impl->aicp, data, size);
- tb_assert_and_check_return_val(impl->ostream, tb_false);
-
- // init owner
- impl->oowner = 1;
- }
-
- // ok
- return tb_true;
-}
-tb_bool_t tb_async_transfer_ctrl_istream(tb_async_transfer_ref_t transfer, tb_size_t ctrl, ...)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)transfer;
- tb_assert_and_check_return_val(impl && impl->istream, tb_false);
-
- // init args
- tb_va_list_t args;
- tb_va_start(args, ctrl);
-
- // ctrl it
- tb_bool_t ok = tb_async_stream_ctrl_with_args(impl->istream, ctrl, args);
-
- // exit args
- tb_va_end(args);
-
- // ok?
- return ok;
-}
-tb_bool_t tb_async_transfer_ctrl_ostream(tb_async_transfer_ref_t transfer, tb_size_t ctrl, ...)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)transfer;
- tb_assert_and_check_return_val(impl && impl->ostream, tb_false);
-
- // init args
- tb_va_list_t args;
- tb_va_start(args, ctrl);
-
- // ctrl it
- tb_bool_t ok = tb_async_stream_ctrl_with_args(impl->ostream, ctrl, args);
-
- // exit args
- tb_va_end(args);
-
- // ok?
- return ok;
-}
-tb_bool_t tb_async_transfer_open(tb_async_transfer_ref_t transfer, tb_hize_t offset, tb_async_transfer_open_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)transfer;
- tb_assert_and_check_return_val(impl && impl->aicp && func, tb_false);
-
- // done
- tb_bool_t ok = tb_false;
- do
- {
- // set opening
- tb_size_t state = tb_atomic_fetch_and_pset(&impl->state, TB_STATE_CLOSED, TB_STATE_OPENING);
-
- // opened? done func directly
- if (state == TB_STATE_OPENED)
- {
- // check
- tb_assert_and_check_break(impl->istream && impl->ostream);
-
- // done func
- func(TB_STATE_OK, tb_async_stream_offset(impl->istream), tb_async_stream_size(impl->istream), priv);
-
- // ok
- ok = tb_true;
- break;
- }
-
- // must be closed
- tb_assert_and_check_break(state == TB_STATE_CLOSED);
-
- // clear pause state
- tb_atomic_set(&impl->state_pause, TB_STATE_OK);
-
- // init func
- impl->open.func = func;
- impl->open.priv = priv;
-
- // check
- tb_assert_and_check_break(impl->istream);
- tb_assert_and_check_break(impl->ostream);
-
- // init some rate info
- impl->done.base_time = tb_aicp_time(impl->aicp);
- impl->done.base_time1s = impl->done.base_time;
- impl->done.saved_size = 0;
- impl->done.saved_size1s = 0;
- impl->done.current_rate = 0;
-
- // ctrl stream
- if (impl->ctrl.func && !impl->ctrl.func(impl->istream, impl->ostream, impl->ctrl.priv)) break;
-
- // open and seek istream
- if (!tb_async_stream_open_seek(impl->istream, offset, tb_async_transfer_istream_open_func, impl)) break;
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // failed? restore state
- if (!ok) tb_atomic_set(&impl->state, TB_STATE_CLOSED);
-
- // ok?
- return ok;
-}
-tb_bool_t tb_async_transfer_clos(tb_async_transfer_ref_t transfer, tb_async_transfer_clos_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)transfer;
- tb_assert_and_check_return_val(impl && func, tb_false);
-
- // try closing ok?
- if (tb_async_transfer_clos_try(transfer))
- {
- // done func directly
- func(TB_STATE_OK, priv);
- return tb_true;
- }
-
- // init func
- impl->clos.func = func;
- impl->clos.priv = priv;
-
- // clos istream
- if (impl->istream) return tb_async_stream_clos(impl->istream, tb_async_transfer_istream_clos_func, impl);
- // clos ostream
- else if (impl->ostream) return tb_async_stream_clos(impl->ostream, tb_async_transfer_ostream_clos_func, impl);
- // done func directly
- else tb_async_transfer_clos_func(impl, TB_STATE_OK);
-
- // ok
- return tb_true;
-}
-tb_bool_t tb_async_transfer_clos_try(tb_async_transfer_ref_t transfer)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)transfer;
- tb_assert_and_check_return_val(impl, tb_false);
-
- // trace
- tb_trace_d("clos: try: ..");
-
- // done
- tb_bool_t ok = tb_false;
- do
- {
- // closed?
- if (TB_STATE_CLOSED == tb_atomic_get(&impl->state))
- {
- ok = tb_true;
- break;
- }
-
- // try closing istream
- if (impl->istream && !tb_async_stream_clos_try(impl->istream)) break;
-
- // try closing ostream
- if (impl->ostream && !tb_async_stream_clos_try(impl->ostream)) break;
-
- // closed
- tb_atomic_set(&impl->state, TB_STATE_CLOSED);
-
- // clear pause state
- tb_atomic_set(&impl->state_pause, TB_STATE_OK);
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // trace
- tb_trace_d("clos: try: %s", ok? "ok" : "no");
-
- // ok?
- return ok;
-}
-tb_bool_t tb_async_transfer_ctrl(tb_async_transfer_ref_t transfer, tb_async_transfer_ctrl_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)transfer;
- tb_assert_and_check_return_val(impl && func, tb_false);
-
- // check state
- tb_assert_and_check_return_val(TB_STATE_CLOSED == tb_atomic_get(&impl->state), tb_false);
-
- // init func
- impl->ctrl.func = func;
- impl->ctrl.priv = priv;
-
- // ok
- return tb_true;
-}
-tb_bool_t tb_async_transfer_done(tb_async_transfer_ref_t transfer, tb_async_transfer_done_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)transfer;
- tb_assert_and_check_return_val(impl && func, tb_false);
-
- // check state
- tb_assert_and_check_return_val(TB_STATE_OPENED == tb_atomic_get(&impl->state), tb_false);
-
- // check stream
- tb_assert_and_check_return_val(impl->istream && impl->ostream, tb_false);
-
- // init func
- impl->done.func = func;
- impl->done.priv = priv;
-
- // read it
- return tb_async_stream_read(impl->istream, (tb_size_t)tb_atomic_get(&impl->limited_rate), tb_async_transfer_istream_read_func, impl);
-}
-tb_bool_t tb_async_transfer_open_done(tb_async_transfer_ref_t transfer, tb_hize_t offset, tb_async_transfer_done_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)transfer;
- tb_assert_and_check_return_val(impl && func, tb_false);
-
- // no opened? open it first
- if (TB_STATE_CLOSED == tb_atomic_get(&impl->state))
- {
- impl->done.func = func;
- impl->done.priv = priv;
- return tb_async_transfer_open(transfer, offset, tb_async_transfer_open_done_func, impl);
- }
-
- // done it
- return tb_async_transfer_done(transfer, func, priv);
-}
-tb_void_t tb_async_transfer_kill(tb_async_transfer_ref_t transfer)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)transfer;
- tb_assert_and_check_return(impl);
-
- // kill it
- tb_size_t state = tb_atomic_fetch_and_set(&impl->state, TB_STATE_KILLING);
- tb_check_return(state != TB_STATE_KILLING);
-
- // trace
- tb_trace_d("kill: ..");
-
- // kill istream
- if (impl->istream) tb_async_stream_kill(impl->istream);
-
- // kill ostream
- if (impl->ostream) tb_async_stream_kill(impl->ostream);
-}
-tb_bool_t tb_async_transfer_exit(tb_async_transfer_ref_t transfer)
-{
- // chec:w
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)transfer;
- tb_assert_and_check_return_val(impl, tb_false);
-
- // trace
- tb_trace_d("exit: ..");
-
- // kill it first
- tb_async_transfer_kill(transfer);
-
- // try closing it
- tb_size_t tryn = 30;
- tb_bool_t ok = tb_false;
- while (!(ok = tb_async_transfer_clos_try(transfer)) && tryn--)
- {
- // wait some time
- tb_msleep(200);
- }
-
- // close failed?
- if (!ok)
- {
- // trace
- tb_trace_e("exit: failed!");
- return tb_false;
- }
-
- // exit istream
- if (impl->istream && impl->iowner) tb_async_stream_exit(impl->istream);
- impl->istream = tb_null;
-
- // exit ostream
- if (impl->ostream && impl->oowner) tb_async_stream_exit(impl->ostream);
- impl->ostream = tb_null;
-
- // exit impl
- tb_free(impl);
-
- // trace
- tb_trace_d("exit: ok");
-
- // ok
- return tb_true;
-}
-tb_void_t tb_async_transfer_pause(tb_async_transfer_ref_t transfer)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)transfer;
- tb_assert_and_check_return(impl);
-
- // pause it
- tb_atomic_pset(&impl->state_pause, TB_STATE_OK, TB_STATE_PAUSING);
-}
-tb_bool_t tb_async_transfer_resume(tb_async_transfer_ref_t transfer)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)transfer;
- tb_assert_and_check_return_val(impl && impl->aicp, tb_false);
-
- // done
- tb_bool_t ok = tb_false;
- tb_size_t state_pause = TB_STATE_OK;
- do
- {
- // must be opened?
- tb_check_break(TB_STATE_OPENED == tb_atomic_get(&impl->state));
-
- // resume it
- tb_size_t state_pause = tb_atomic_fetch_and_set(&impl->state_pause, TB_STATE_OK);
-
- // pausing or ok? return ok directly
- tb_check_return_val(state_pause == TB_STATE_PAUSED, tb_true);
-
- // check
- tb_assert_and_check_break(impl->istream);
- tb_assert_and_check_break(impl->ostream);
-
- // init some rate info
- impl->done.base_time = tb_aicp_time(impl->aicp);
- impl->done.base_time1s = impl->done.base_time;
- impl->done.saved_size1s = 0;
- impl->done.current_rate = 0;
-
- // read it
- if (!tb_async_stream_read(impl->istream, (tb_size_t)tb_atomic_get(&impl->limited_rate), tb_async_transfer_istream_read_func, impl)) break;
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // failed? restore state
- if (!ok && state_pause != TB_STATE_OK) tb_atomic_pset(&impl->state_pause, TB_STATE_OK, state_pause);
-
- // ok?
- return ok;
-}
-tb_void_t tb_async_transfer_limitrate(tb_async_transfer_ref_t transfer, tb_size_t rate)
-{
- // check
- tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)transfer;
- tb_assert_and_check_return(impl);
-
- // set the limited rate
- tb_atomic_set(&impl->limited_rate, rate);
-}
-
diff --git a/core/src/tbox/src/tbox/stream/deprecated/async_transfer.h b/core/src/tbox/src/tbox/stream/deprecated/async_transfer.h
deleted file mode 100644
index 3024d3762..000000000
--- a/core/src/tbox/src/tbox/stream/deprecated/async_transfer.h
+++ /dev/null
@@ -1,323 +0,0 @@
-/*!The Treasure Box Library
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
- *
- * @author ruki
- * @file async_transfer.h
- * @ingroup stream
- *
- */
-#ifndef TB_STREAM_ASYNC_TRANSFER_H
-#define TB_STREAM_ASYNC_TRANSFER_H
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
- */
-#include "prefix.h"
-#include "async_stream.h"
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * extern
- */
-__tb_extern_c_enter__
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * types
- */
-
-/*! the async transfer open func type
- *
- * @param state the stream state
- * @param offset the istream offset
- * @param size the istream size, no size: -1
- * @param priv the func private data
- *
- * @return tb_true: ok, tb_false: break it
- */
-typedef tb_bool_t (*tb_async_transfer_open_func_t)(tb_size_t state, tb_hize_t offset, tb_hong_t size, tb_cpointer_t priv);
-
-/*! the async transfer clos func type
- *
- * @param state the stream state
- * @param priv the func private data
- */
-typedef tb_void_t (*tb_async_transfer_clos_func_t)(tb_size_t state, tb_cpointer_t priv);
-
-/*! the async transfer ctrl func type
- *
- * @param istream the istream
- * @param ostream the ostream
- * @param priv the func private data
- *
- * @return tb_true: ok, tb_false: break it
- */
-typedef tb_bool_t (*tb_async_transfer_ctrl_func_t)(tb_async_stream_ref_t istream, tb_async_stream_ref_t ostream, tb_cpointer_t priv);
-
-/*! the async transfer done func type
- *
- * @param state the stream state
- * @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_async_transfer_done_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 async transfer ref type
-typedef __tb_typeref__(async_transfer);
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * interfaces
- */
-
-/*! init async transfer
- *
- * @param aicp the aicp, using the default aicp if be null
- * @param autoclosing auto closing it after finishing transfer
- *
- * @return the async transfer
- */
-tb_async_transfer_ref_t tb_async_transfer_init(tb_aicp_ref_t aicp, tb_bool_t autoclosing);
-
-/*! init istream
- *
- * @param transfer the async transfer
- * @param stream the stream
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_transfer_init_istream(tb_async_transfer_ref_t transfer, tb_async_stream_ref_t stream);
-
-/*! init istream from url
- *
- * @param transfer the async transfer
- * @param url the url
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_transfer_init_istream_from_url(tb_async_transfer_ref_t transfer, tb_char_t const* url);
-
-/*! init istream from data
- *
- * @param transfer the async transfer
- * @param data the data
- * @param size the size
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_transfer_init_istream_from_data(tb_async_transfer_ref_t transfer, tb_byte_t const* data, tb_size_t size);
-
-/*! init ostream
- *
- * @param transfer the async transfer
- * @param stream the stream
- *
- * @return the async transfer
- */
-tb_bool_t tb_async_transfer_init_ostream(tb_async_transfer_ref_t transfer, tb_async_stream_ref_t stream);
-
-/*! init ostream from url
- *
- * @param transfer the async transfer
- * @param url the url
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_transfer_init_ostream_from_url(tb_async_transfer_ref_t transfer, tb_char_t const* url);
-
-/*! init ostream from data
- *
- * @param transfer the async transfer
- * @param data the data
- * @param size the size
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_transfer_init_ostream_from_data(tb_async_transfer_ref_t transfer, tb_byte_t* data, tb_size_t size);
-
-/*! ctrl istream
- *
- * @note must call it before opening
- *
- * @param transfer the async transfer
- * @param ctrl the ctrl code, using the stream ctrl code
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_transfer_ctrl_istream(tb_async_transfer_ref_t transfer, tb_size_t ctrl, ...);
-
-/*! ctrl ostream
- *
- * @note must call it before opening
- *
- * @param transfer the async transfer
- * @param ctrl the ctrl code, using the stream ctrl code
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_transfer_ctrl_ostream(tb_async_transfer_ref_t transfer, tb_size_t ctrl, ...);
-
-/*! ctrl transfer
- *
- * @param transfer the async transfer
- * @param offset the start offset
- * @param func the ctrl func
- * @param priv the func private data
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_transfer_ctrl(tb_async_transfer_ref_t transfer, tb_async_transfer_ctrl_func_t func, tb_cpointer_t priv);
-
-/*! open transfer
- *
- * @param transfer the async transfer
- * @param offset the start offset
- * @param func the open func
- * @param priv the func private data
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_transfer_open(tb_async_transfer_ref_t transfer, tb_hize_t offset, tb_async_transfer_open_func_t func, tb_cpointer_t priv);
-
-/*! clos transfer
- *
- * @param transfer the async transfer
- * @param func the clos func
- * @param priv the func private data
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_transfer_clos(tb_async_transfer_ref_t transfer, tb_async_transfer_clos_func_t func, tb_cpointer_t priv);
-
-/*! try closing transfer
- *
- * @param transfer the async transfer
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_transfer_clos_try(tb_async_transfer_ref_t transfer);
-
-/*! done transfer and will close it automaticly
- *
- * @param transfer the async transfer
- * @param func the save func
- * @param priv the func private data
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_transfer_done(tb_async_transfer_ref_t transfer, tb_async_transfer_done_func_t func, tb_cpointer_t priv);
-
-/*! open and done transfer and will close it automaticly
- *
- * @code
- *
- static tb_bool_t tb_demo_transfer_done_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 = (offset * 100) / size;
- else if (state == TB_STATE_OK) percent = 100;
-
- // trace
- tb_trace_i("done: %llu bytes, rate: %lu bytes/s, percent: %lu%%, state: %s", save, rate, percent, tb_state_cstr(state));
-
- // ok
- return tb_true;
- }
-
- // init transfer
- tb_async_transfer_ref_t transfer = tb_async_transfer_init(tb_null);
- if (transfer)
- {
- // init stream
- tb_async_transfer_init_istream_from_url(transfer, url);
- tb_async_transfer_init_ostream_from_data(transfer, data, size);
-
- // ctrl stream
-// tb_async_transfer_ctrl_istream(transfer, TB_STREAM_CTRL_SET_TIMEOUT, 10000);
-
- // limit rate
-// tb_async_transfer_limitrate(transfer, 256000);
-
- // open and done transfer
- tb_async_transfer_open_done(transfer, 0, tb_demo_transfer_done_func, tb_null);
-
- // exit transfer
- tb_async_transfer_exit(transfer);
- }
- *
- * @endcode
- *
- * @param transfer the async transfer
- * @param offset the start offset
- * @param func the save func
- * @param priv the func private data
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_transfer_open_done(tb_async_transfer_ref_t transfer, tb_hize_t offset, tb_async_transfer_done_func_t func, tb_cpointer_t priv);
-
-/*! kill transfer
- *
- * @param transfer the async transfer
- */
-tb_void_t tb_async_transfer_kill(tb_async_transfer_ref_t transfer);
-
-/*! exit transfer
- *
- * @note will wait transfer closed and cannot be called in the callback func
- *
- * @param transfer the async transfer
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_transfer_exit(tb_async_transfer_ref_t transfer);
-
-/*! pause transfer
- *
- * the save func state will return TB_STATE_PAUSED
- *
- * @param transfer the async transfer
- */
-tb_void_t tb_async_transfer_pause(tb_async_transfer_ref_t transfer);
-
-/*! resume transfer
- *
- * @param transfer the async transfer
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_transfer_resume(tb_async_transfer_ref_t transfer);
-
-/*! limit transfer rate
- *
- * @param transfer the async transfer
- * @param rate the trasfer rate and no limit if 0, bytes/s
- */
-tb_void_t tb_async_transfer_limitrate(tb_async_transfer_ref_t transfer, tb_size_t rate);
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * extern
- */
-__tb_extern_c_leave__
-
-#endif
diff --git a/core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/data.c b/core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/data.c
deleted file mode 100644
index 660dce87c..000000000
--- a/core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/data.c
+++ /dev/null
@@ -1,710 +0,0 @@
-/*!The Treasure Box Library
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
- *
- * @author ruki
- * @data data.c
- *
- */
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * trace
- */
-#define TB_TRACE_MODULE_NAME "async_stream_data"
-#define TB_TRACE_MODULE_DEBUG (0)
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
- */
-#include "prefix.h"
-#include "../../../../utils/utils.h"
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * types
- */
-
-// the data read type
-typedef struct __tb_async_stream_data_impl_read_t
-{
- // the func
- tb_async_stream_read_func_t func;
-
- // the size
- tb_size_t size;
-
- // the priv
- tb_cpointer_t priv;
-
-}tb_async_stream_data_impl_read_t;
-
-// the data writ type
-typedef struct __tb_async_stream_data_impl_writ_t
-{
- // the func
- tb_async_stream_writ_func_t func;
-
- // the data
- tb_byte_t const* data;
-
- // the size
- tb_size_t size;
-
- // the priv
- tb_cpointer_t priv;
-
-}tb_async_stream_data_impl_writ_t;
-
-// the data task type
-typedef struct __tb_async_stream_data_impl_task_t
-{
- // the func
- tb_async_stream_task_func_t func;
-
- // the priv
- tb_cpointer_t priv;
-
-}tb_async_stream_data_impl_task_t;
-
-// the data clos type
-typedef struct __tb_async_stream_data_impl_clos_t
-{
- // the func
- tb_async_stream_clos_func_t func;
-
- // the priv
- tb_cpointer_t priv;
-
-}tb_async_stream_data_impl_clos_t;
-
-// the data stream type
-typedef struct __tb_async_stream_data_impl_t
-{
- // the aico for task
- tb_aico_ref_t aico;
-
- // the data
- tb_byte_t* data;
-
- // the head
- tb_byte_t* head;
-
- // the size
- tb_size_t size;
-
- // the data is referenced?
- tb_bool_t bref;
-
- // the offset
- tb_atomic64_t offset;
-
- // the func
- union
- {
- tb_async_stream_data_impl_read_t read;
- tb_async_stream_data_impl_writ_t writ;
- tb_async_stream_data_impl_task_t task;
- tb_async_stream_data_impl_clos_t clos;
-
- } func;
-
-}tb_async_stream_data_impl_t;
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
- */
-static __tb_inline__ tb_async_stream_data_impl_t* tb_async_stream_data_impl_cast(tb_async_stream_ref_t stream)
-{
- // check
- tb_assert_and_check_return_val(stream && tb_async_stream_type(stream) == TB_STREAM_TYPE_DATA, tb_null);
-
- // ok?
- return (tb_async_stream_data_impl_t*)stream;
-}
-static tb_void_t tb_async_stream_data_impl_clos_clear(tb_async_stream_data_impl_t* impl)
-{
- // check
- tb_assert_and_check_return(impl);
-
- // clear head
- impl->head = tb_null;
-
- // clear offset
- tb_atomic64_set0(&impl->offset);
-
- // clear base
- tb_async_stream_clear((tb_async_stream_ref_t)impl);
-}
-static tb_bool_t tb_async_stream_data_impl_clos_func(tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_CLOS, tb_false);
-
- // the impl
- tb_async_stream_data_impl_t* impl = tb_async_stream_data_impl_cast((tb_async_stream_ref_t)aice->priv);
- tb_assert_and_check_return_val(impl && impl->func.clos.func, tb_false);
-
- // trace
- tb_trace_d("clos: notify: ..");
-
- // clear it
- tb_async_stream_data_impl_clos_clear(impl);
-
- /* done clos func
- *
- * note: cannot use this stream after closing, the stream may be exited in the closing func
- */
- impl->func.clos.func((tb_async_stream_ref_t)impl, TB_STATE_OK, impl->func.clos.priv);
-
- // trace
- tb_trace_d("clos: notify: ok");
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_async_stream_data_impl_clos_try(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_data_impl_t* impl = tb_async_stream_data_impl_cast(stream);
- tb_assert_and_check_return_val(impl, tb_false);
-
- // no aico or closed?
- if (!impl->aico || tb_aico_clos_try(impl->aico))
- {
- // clear it
- tb_async_stream_data_impl_clos_clear(impl);
-
- // ok
- return tb_true;
- }
-
- // failed
- return tb_false;
-}
-static tb_bool_t tb_async_stream_data_impl_clos(tb_async_stream_ref_t stream, tb_async_stream_clos_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_data_impl_t* impl = tb_async_stream_data_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->aico && func, tb_false);
-
- // trace
- tb_trace_d("clos: ..");
-
- // init func
- impl->func.clos.func = func;
- impl->func.clos.priv = priv;
-
- // clos it
- tb_aico_clos(impl->aico, tb_async_stream_data_impl_clos_func, impl);
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_async_stream_data_impl_open_try(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_data_impl_t* impl = tb_async_stream_data_impl_cast(stream);
- tb_assert_and_check_return_val(impl, tb_false);
-
- // done
- tb_bool_t ok = tb_false;
- do
- {
- // check
- tb_assert_and_check_break(impl->data && impl->size);
-
- // the aicp
- tb_aicp_ref_t aicp = tb_async_stream_aicp(stream);
- tb_assert_and_check_break(aicp);
-
- // init aico
- if (!impl->aico) impl->aico = tb_aico_init(aicp);
- tb_assert_and_check_break(impl->aico);
-
- // open aico
- if (!tb_aico_open_task(impl->aico, tb_false)) break;
-
- // killed?
- tb_check_break(!tb_async_stream_is_killed(stream));
-
- // init head
- impl->head = impl->data;
-
- // init offset
- tb_atomic64_set0(&impl->offset);
-
- // open done
- tb_async_stream_open_done(stream);
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // failed? clear it
- if (!ok) tb_async_stream_data_impl_clos_clear(impl);
-
- // ok?
- return ok;
-}
-static tb_bool_t tb_async_stream_data_impl_open(tb_async_stream_ref_t stream, tb_async_stream_open_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_data_impl_t* impl = tb_async_stream_data_impl_cast(stream);
- tb_assert_and_check_return_val(impl && func, tb_false);
-
- // try opening it
- tb_size_t state = tb_async_stream_data_impl_open_try(stream)? TB_STATE_OK : TB_STATE_UNKNOWN_ERROR;
-
- // killed?
- if (state != TB_STATE_OK && tb_async_stream_is_killed(stream))
- state = TB_STATE_KILLED;
-
- // done func
- return tb_async_stream_open_func(stream, state, func, priv);
-}
-static tb_bool_t tb_async_stream_data_impl_read_func(tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(aice && aice->aico && aice->code == TB_AICE_CODE_RUNTASK, tb_false);
-
- // the stream
- tb_async_stream_data_impl_t* impl = (tb_async_stream_data_impl_t*)aice->priv;
- tb_assert_and_check_return_val(impl && impl->func.read.func, tb_false);
-
- // done state
- tb_size_t state = TB_STATE_UNKNOWN_ERROR;
- switch (aice->state)
- {
- // ok
- case TB_STATE_OK:
- {
- // check
- tb_assert_and_check_break(impl->data && impl->head);
-
- // the left
- tb_size_t left = impl->data + impl->size - impl->head;
-
- // the real
- tb_size_t real = impl->func.read.size;
- if (!real || real > left) real = left;
-
- // no data? closed
- if (!real)
- {
- state = TB_STATE_CLOSED;
- break;
- }
-
- // save data
- tb_byte_t* data = impl->head;
-
- // save head
- impl->head += real;
-
- // save offset
- tb_atomic64_set(&impl->offset, impl->head - impl->data);
-
- // ok
- state = TB_STATE_OK;
-
- // done func
- if (impl->func.read.func((tb_async_stream_ref_t)impl, state, data, real, impl->func.read.size, impl->func.read.priv))
- {
- // continue to post read
- tb_aico_task_run(aice->aico, 0, tb_async_stream_data_impl_read_func, (tb_async_stream_ref_t)impl);
- }
- }
- break;
- // killed
- case TB_STATE_KILLED:
- state = TB_STATE_KILLED;
- break;
- default:
- tb_trace_d("read: unknown state: %s", tb_state_cstr(aice->state));
- break;
- }
-
- // done func
- if (state != TB_STATE_OK) impl->func.read.func((tb_async_stream_ref_t)impl, state, tb_null, 0, impl->func.read.size, impl->func.read.priv);
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_async_stream_data_impl_read(tb_async_stream_ref_t stream, tb_size_t delay, tb_byte_t* data, tb_size_t size, tb_async_stream_read_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_data_impl_t* impl = tb_async_stream_data_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->aico && func, tb_false);
-
- // save func and priv
- impl->func.read.priv = priv;
- impl->func.read.func = func;
- impl->func.read.size = size;
-
- // post read
- return tb_aico_task_run(impl->aico, delay, tb_async_stream_data_impl_read_func, stream);
-}
-static tb_bool_t tb_async_stream_data_impl_writ_func(tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(aice && aice->aico && aice->code == TB_AICE_CODE_RUNTASK, tb_false);
-
- // the stream
- tb_async_stream_data_impl_t* impl = (tb_async_stream_data_impl_t*)aice->priv;
- tb_assert_and_check_return_val(impl && impl->func.writ.func, tb_false);
-
- // done state
- tb_size_t state = TB_STATE_UNKNOWN_ERROR;
- switch (aice->state)
- {
- // ok
- case TB_STATE_OK:
- {
- // check
- tb_assert_and_check_break(impl->data && impl->head);
- tb_assert_and_check_break(impl->func.writ.data && impl->func.writ.size);
-
- // the left
- tb_size_t left = impl->data + impl->size - impl->head;
-
- // the real
- tb_size_t real = impl->func.writ.size;
- if (real > left) real = left;
-
- // no data? closed
- if (!real)
- {
- state = TB_STATE_CLOSED;
- break;
- }
-
- // save data
- tb_memcpy(impl->head, impl->func.writ.data, real);
-
- // save head
- impl->head += real;
-
- // save offset
- tb_atomic64_set(&impl->offset, impl->head - impl->data);
-
- // ok
- state = TB_STATE_OK;
-
- // done func
- if (impl->func.writ.func((tb_async_stream_ref_t)impl, state, impl->func.writ.data, real, impl->func.writ.size, impl->func.writ.priv))
- {
- // not finished?
- if (real < impl->func.writ.size)
- {
- // update data and size
- impl->func.writ.data += real;
- impl->func.writ.size -= real;
-
- // continue to post writ
- tb_aico_task_run(aice->aico, 0, tb_async_stream_data_impl_writ_func, (tb_async_stream_ref_t)impl);
- }
- }
- }
- break;
- // killed
- case TB_STATE_KILLED:
- state = TB_STATE_KILLED;
- break;
- default:
- tb_trace_d("read: unknown state: %s", tb_state_cstr(aice->state));
- break;
- }
-
- // done func
- if (state != TB_STATE_OK) impl->func.writ.func((tb_async_stream_ref_t)impl, state, impl->func.writ.data, 0, impl->func.writ.size, impl->func.writ.priv);
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_async_stream_data_impl_writ(tb_async_stream_ref_t stream, tb_size_t delay, tb_byte_t const* data, tb_size_t size, tb_async_stream_writ_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_data_impl_t* impl = tb_async_stream_data_impl_cast(stream);
- tb_assert_and_check_return_val(impl && data && size && func, tb_false);
-
- // save func and priv
- impl->func.writ.priv = priv;
- impl->func.writ.func = func;
- impl->func.writ.data = data;
- impl->func.writ.size = size;
-
- // post writ
- return tb_aico_task_run(impl->aico, delay, tb_async_stream_data_impl_writ_func, stream);
-}
-static tb_bool_t tb_async_stream_data_impl_seek(tb_async_stream_ref_t stream, tb_hize_t offset, tb_async_stream_seek_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_data_impl_t* impl = tb_async_stream_data_impl_cast(stream);
- tb_assert_and_check_return_val(impl && func, tb_false);
-
- // done
- tb_size_t state = TB_STATE_UNKNOWN_ERROR;
- do
- {
- // check
- tb_assert_and_check_break(impl->data && offset <= impl->size);
-
- // seek
- impl->head = impl->data + offset;
-
- // save offset
- tb_atomic64_set(&impl->offset, offset);
-
- // ok
- state = TB_STATE_OK;
-
- } while (0);
-
- // done func
- func(stream, state, offset, priv);
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_async_stream_data_impl_task_func(tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(aice && aice->aico && aice->code == TB_AICE_CODE_RUNTASK, tb_false);
-
- // the stream
- tb_async_stream_data_impl_t* impl = (tb_async_stream_data_impl_t*)aice->priv;
- tb_assert_and_check_return_val(impl && impl->func.task.func, tb_false);
-
- // done func
- tb_bool_t ok = impl->func.task.func((tb_async_stream_ref_t)impl, aice->state == TB_STATE_OK? TB_STATE_OK : TB_STATE_UNKNOWN_ERROR, impl->func.task.priv);
-
- // ok and continue?
- if (ok && aice->state == TB_STATE_OK)
- {
- // post task
- tb_aico_task_run(aice->aico, aice->u.runtask.delay, tb_async_stream_data_impl_task_func, impl);
- }
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_async_stream_data_impl_task(tb_async_stream_ref_t stream, tb_size_t delay, tb_async_stream_task_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_data_impl_t* impl = tb_async_stream_data_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->aico && func, tb_false);
-
- // save func and priv
- impl->func.task.priv = priv;
- impl->func.task.func = func;
-
- // post task
- return tb_aico_task_run(impl->aico, delay, tb_async_stream_data_impl_task_func, stream);
-}
-static tb_void_t tb_async_stream_data_impl_kill(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_data_impl_t* impl = tb_async_stream_data_impl_cast(stream);
- tb_assert_and_check_return(impl);
-
- // kill the task aico
- if (impl->aico) tb_aico_kill(impl->aico);
-}
-static tb_bool_t tb_async_stream_data_impl_exit(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_data_impl_t* impl = tb_async_stream_data_impl_cast(stream);
- tb_assert_and_check_return_val(impl, tb_false);
-
- // exit the task aico
- if (impl->aico) tb_aico_exit(impl->aico);
- impl->aico = tb_null;
-
- // clear head
- impl->head = tb_null;
-
- // clear offset
- tb_atomic64_set0(&impl->offset);
-
- // exit data
- if (impl->data && !impl->bref) tb_free(impl->data);
- impl->data = tb_null;
- impl->size = 0;
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_async_stream_data_impl_ctrl(tb_async_stream_ref_t stream, tb_size_t ctrl, tb_va_list_t args)
-{
- // check
- tb_async_stream_data_impl_t* impl = tb_async_stream_data_impl_cast(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, tb_false);
-
- // get size
- *psize = impl->size;
- return tb_true;
- }
- case TB_STREAM_CTRL_GET_OFFSET:
- {
- // check
- tb_assert_and_check_return_val(impl->data && impl->size, tb_false);
- tb_assert_and_check_return_val(tb_async_stream_is_opened(stream), tb_false);
-
- // the poffset
- tb_hize_t* poffset = (tb_hize_t*)tb_va_arg(args, tb_hize_t*);
- tb_assert_and_check_return_val(poffset, tb_false);
-
- // get offset
- *poffset = tb_atomic64_get(&impl->offset);
- return tb_true;
- }
- case TB_STREAM_CTRL_DATA_SET_DATA:
- {
- // exit data first if exists
- if (impl->data && !impl->bref) tb_free(impl->data);
-
- // save data
- impl->data = (tb_byte_t*)tb_va_arg(args, tb_byte_t*);
- impl->size = (tb_size_t)tb_va_arg(args, tb_size_t);
- impl->head = tb_null;
- impl->bref = tb_true;
-
- // clear offset
- tb_atomic64_set0(&impl->offset);
-
- // check
- tb_assert_and_check_return_val(impl->data && impl->size, tb_false);
- return tb_true;
- }
- case TB_STREAM_CTRL_SET_URL:
- {
- // check
- tb_assert_and_check_return_val(tb_async_stream_is_closed(stream), tb_false);
-
- // set 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);
-
- // the url size
- tb_size_t url_size = tb_strlen(url);
- tb_assert_and_check_return_val(url_size > 7, tb_false);
-
- // the base64 data and size
- tb_char_t const* base64_data = url + 7;
- tb_size_t base64_size = url_size - 7;
-
- // make data
- tb_size_t maxn = base64_size;
- tb_byte_t* data = tb_malloc_bytes(maxn);
- tb_assert_and_check_return_val(data, tb_false);
-
- // decode base64 data
- tb_size_t size = tb_base64_decode(base64_data, base64_size, data, maxn);
- tb_assert_and_check_return_val(size, tb_false);
-
- // exit data first if exists
- if (impl->data && !impl->bref) tb_free(impl->data);
-
- // save data
- impl->data = data;
- impl->size = size;
- impl->bref = tb_false;
- impl->head = tb_null;
-
- // clear offset
- tb_atomic64_set0(&impl->offset);
-
- // ok
- return tb_true;
- }
- break;
- default:
- break;
- }
- return tb_false;
-}
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * interfaces
- */
-tb_async_stream_ref_t tb_async_stream_init_data(tb_aicp_ref_t aicp)
-{
- return tb_async_stream_init( aicp
- , TB_STREAM_TYPE_DATA
- , sizeof(tb_async_stream_data_impl_t)
- , 0
- , 0
- , tb_async_stream_data_impl_open_try
- , tb_async_stream_data_impl_clos_try
- , tb_async_stream_data_impl_open
- , tb_async_stream_data_impl_clos
- , tb_async_stream_data_impl_exit
- , tb_async_stream_data_impl_kill
- , tb_async_stream_data_impl_ctrl
- , tb_async_stream_data_impl_read
- , tb_async_stream_data_impl_writ
- , tb_async_stream_data_impl_seek
- , tb_null
- , tb_async_stream_data_impl_task);
-}
-tb_async_stream_ref_t tb_async_stream_init_from_data(tb_aicp_ref_t aicp, tb_byte_t const* data, tb_size_t size)
-{
- // check
- tb_assert_and_check_return_val(data && size, tb_null);
-
- // done
- tb_bool_t ok = tb_false;
- tb_async_stream_ref_t stream = tb_null;
- do
- {
- // init stream
- stream = tb_async_stream_init_data(aicp);
- tb_assert_and_check_break(stream);
-
- // set data
- if (!tb_async_stream_ctrl(stream, TB_STREAM_CTRL_DATA_SET_DATA, data, size)) break;
-
- // check
- tb_assert_static(!(tb_offsetof(tb_async_stream_data_impl_t, offset) & (sizeof(tb_atomic64_t) - 1)));
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // failed?
- if (!ok)
- {
- // exit it
- if (stream) tb_async_stream_exit(stream);
- stream = tb_null;
- }
-
- // ok?
- return stream;
-}
diff --git a/core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/file.c b/core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/file.c
deleted file mode 100644
index d580678db..000000000
--- a/core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/file.c
+++ /dev/null
@@ -1,648 +0,0 @@
-/*!The Treasure Box Library
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
- *
- * @author ruki
- * @file file.c
- *
- */
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * trace
- */
-#define TB_TRACE_MODULE_NAME "async_stream_file"
-#define TB_TRACE_MODULE_DEBUG (1)
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
- */
-#include "prefix.h"
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * macros
- */
-
-// the file cache maxn
-#define TB_ASYNC_STREAM_FILE_CACHE_MAXN TB_FILE_DIRECT_CSIZE
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * types
- */
-
-// the file stream type
-typedef struct __tb_async_stream_file_impl_t
-{
- // the aico
- tb_aico_ref_t aico;
-
- // the file mode
- tb_size_t mode;
-
- // the file offset
- tb_atomic64_t offset;
-
- // is stream file?
- tb_bool_t bstream;
-
- // is closing
- tb_bool_t bclosing;
-
- // the func
- union
- {
- tb_async_stream_read_func_t read;
- tb_async_stream_writ_func_t writ;
- tb_async_stream_sync_func_t sync;
- tb_async_stream_task_func_t task;
- tb_async_stream_clos_func_t clos;
-
- } func;
-
- // the priv
- tb_cpointer_t priv;
-
-}tb_async_stream_file_impl_t;
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
- */
-static __tb_inline__ tb_async_stream_file_impl_t* tb_async_stream_file_impl_cast(tb_async_stream_ref_t stream)
-{
- // check
- tb_assert_and_check_return_val(stream && tb_async_stream_type(stream) == TB_STREAM_TYPE_FILE, tb_null);
-
- // ok?
- return (tb_async_stream_file_impl_t*)stream;
-}
-static tb_void_t tb_async_stream_file_impl_clos_clear(tb_async_stream_file_impl_t* impl)
-{
- // check
- tb_assert_and_check_return(impl);
-
- // clear the offset
- tb_atomic64_set0(&impl->offset);
-
- // clear base
- tb_async_stream_clear((tb_async_stream_ref_t)impl);
-}
-static tb_bool_t tb_async_stream_file_impl_clos_func(tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_CLOS, tb_false);
-
- // the impl
- tb_async_stream_file_impl_t* impl = tb_async_stream_file_impl_cast((tb_async_stream_ref_t)aice->priv);
- tb_assert_and_check_return_val(impl && impl->func.clos, tb_false);
-
- // trace
- tb_trace_d("clos: notify: ..");
-
- // clear it
- tb_async_stream_file_impl_clos_clear(impl);
-
- /* done clos func
- *
- * note: cannot use this stream after closing, the stream may be exited in the closing func
- */
- impl->func.clos((tb_async_stream_ref_t)impl, TB_STATE_OK, impl->priv);
-
- // trace
- tb_trace_d("clos: notify: ok");
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_async_stream_file_impl_clos_try(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_file_impl_t* impl = tb_async_stream_file_impl_cast(stream);
- tb_assert_and_check_return_val(impl, tb_false);
-
- // no aico or closed?
- if (!impl->aico || tb_aico_clos_try(impl->aico))
- {
- // clear it
- tb_async_stream_file_impl_clos_clear(impl);
-
- // ok
- return tb_true;
- }
-
- // failed
- return tb_false;
-}
-static tb_bool_t tb_async_stream_file_impl_open_try(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_file_impl_t* impl = tb_async_stream_file_impl_cast(stream);
- tb_assert_and_check_return_val(impl, tb_false);
-
- // done
- tb_bool_t ok = tb_false;
- do
- {
- // the aicp
- tb_aicp_ref_t aicp = tb_async_stream_aicp(stream);
- tb_assert_and_check_break(aicp);
-
- // init aico
- if (!impl->aico) impl->aico = tb_aico_init(tb_async_stream_aicp(stream));
- tb_assert_and_check_break(impl->aico);
-
- // the url
- tb_char_t const* url = tb_url_cstr(tb_async_stream_url(stream));
- tb_assert_and_check_break(url);
-
- // open aico
- if (!tb_aico_open_file_from_path(impl->aico, url, impl->mode)) break;
-
- // killed?
- tb_check_break(!tb_async_stream_is_killed(stream));
-
- // init offset
- tb_atomic64_set0(&impl->offset);
-
- // open done
- tb_async_stream_open_done(stream);
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // failed? clear it
- if (!ok) tb_async_stream_file_impl_clos_clear(impl);
-
- // ok?
- return ok;
-}
-static tb_bool_t tb_async_stream_file_impl_open(tb_async_stream_ref_t stream, tb_async_stream_open_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_file_impl_t* impl = tb_async_stream_file_impl_cast(stream);
- tb_assert_and_check_return_val(impl && func, tb_false);
-
- // done
- tb_size_t state = TB_STATE_UNKNOWN_ERROR;
- do
- {
- // try opening it
- if (!tb_async_stream_file_impl_open_try(stream))
- {
- // killed?
- if (tb_async_stream_is_killed(stream))
- {
- // save state
- state = TB_STATE_KILLED;
- break;
- }
-
- // the url
- tb_char_t const* url = tb_url_cstr(tb_async_stream_url(stream));
- tb_assert_and_check_break(url);
-
- // trace
- tb_trace_e("open %s: failed", url);
-
- // save state
- state = tb_syserror_state();
- break;
- }
-
- // ok
- state = TB_STATE_OK;
-
- } while (0);
-
- // open done
- return tb_async_stream_open_func(stream, state, func, priv);
-}
-static tb_bool_t tb_async_stream_file_impl_clos(tb_async_stream_ref_t stream, tb_async_stream_clos_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_file_impl_t* impl = tb_async_stream_file_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->aico && func, tb_false);
-
- // trace
- tb_trace_d("clos: ..");
-
- // init clos
- impl->func.clos = func;
- impl->priv = priv;
-
- /* clos aico
- *
- * note: cannot use this stream after exiting, the stream may be exited after calling clos func
- */
- tb_aico_clos(impl->aico, tb_async_stream_file_impl_clos_func, impl);
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_async_stream_file_impl_read_func(tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(aice && aice->aico && aice->code == TB_AICE_CODE_READ, tb_false);
-
- // the stream
- tb_async_stream_file_impl_t* impl = (tb_async_stream_file_impl_t*)aice->priv;
- tb_assert_and_check_return_val(impl && impl->func.read, tb_false);
-
- // done state
- tb_size_t state = TB_STATE_UNKNOWN_ERROR;
- switch (aice->state)
- {
- // ok
- case TB_STATE_OK:
- tb_atomic64_fetch_and_add(&impl->offset, aice->u.read.real);
- state = TB_STATE_OK;
- break;
- // closed
- case TB_STATE_CLOSED:
- state = TB_STATE_CLOSED;
- break;
- // killed
- case TB_STATE_KILLED:
- state = TB_STATE_KILLED;
- break;
- default:
- tb_trace_d("read: unknown state: %s", tb_state_cstr(aice->state));
- break;
- }
-
- // done func
- if (impl->func.read((tb_async_stream_ref_t)impl, state, aice->u.read.data, aice->u.read.real, aice->u.read.size, impl->priv))
- {
- // continue?
- if (aice->state == TB_STATE_OK)
- {
- // continue to post read
- tb_aico_read(aice->aico, (tb_hize_t)tb_atomic64_get(&impl->offset), aice->u.read.data, aice->u.read.size, tb_async_stream_file_impl_read_func, (tb_async_stream_ref_t)impl);
- }
- }
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_async_stream_file_impl_read(tb_async_stream_ref_t stream, tb_size_t delay, tb_byte_t* data, tb_size_t size, tb_async_stream_read_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_file_impl_t* impl = tb_async_stream_file_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->aico && data && size && func, tb_false);
-
- // save func and priv
- impl->priv = priv;
- impl->func.read = func;
-
- // post read
- return tb_aico_read_after(impl->aico, delay, (tb_hize_t)tb_atomic64_get(&impl->offset), data, size, tb_async_stream_file_impl_read_func, stream);
-}
-static tb_bool_t tb_async_stream_file_impl_writ_func(tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(aice && aice->aico && aice->code == TB_AICE_CODE_WRIT, tb_false);
-
- // the stream
- tb_async_stream_file_impl_t* impl = (tb_async_stream_file_impl_t*)aice->priv;
- tb_assert_and_check_return_val(impl && impl->func.writ, tb_false);
-
- // done state
- tb_size_t state = TB_STATE_UNKNOWN_ERROR;
- switch (aice->state)
- {
- // ok
- case TB_STATE_OK:
- tb_assert_and_check_break(aice->u.writ.data && aice->u.writ.real <= aice->u.writ.size);
- tb_atomic64_fetch_and_add(&impl->offset, aice->u.writ.real);
- state = TB_STATE_OK;
- break;
- // closed
- case TB_STATE_CLOSED:
- state = TB_STATE_CLOSED;
- break;
- // killed
- case TB_STATE_KILLED:
- state = TB_STATE_KILLED;
- break;
- default:
- tb_trace_d("writ: unknown state: %s", tb_state_cstr(aice->state));
- break;
- }
-
- // done func
- if (impl->func.writ((tb_async_stream_ref_t)impl, state, aice->u.writ.data, aice->u.writ.real, aice->u.writ.size, impl->priv))
- {
- // continue?
- if (aice->state == TB_STATE_OK && aice->u.writ.real < aice->u.writ.size)
- {
- // continue to post writ
- tb_aico_writ(aice->aico, (tb_hize_t)tb_atomic64_get(&impl->offset), aice->u.writ.data + aice->u.writ.real, aice->u.writ.size - aice->u.writ.real, tb_async_stream_file_impl_writ_func, (tb_async_stream_ref_t)impl);
- }
- }
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_async_stream_file_impl_writ(tb_async_stream_ref_t stream, tb_size_t delay, tb_byte_t const* data, tb_size_t size, tb_async_stream_writ_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_file_impl_t* impl = tb_async_stream_file_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->aico && data && size && func, tb_false);
-
- // save func and priv
- impl->priv = priv;
- impl->func.writ = func;
-
- // post writ
- return tb_aico_writ_after(impl->aico, delay, (tb_hize_t)tb_atomic64_get(&impl->offset), data, size, tb_async_stream_file_impl_writ_func, stream);
-}
-static tb_bool_t tb_async_stream_file_impl_seek(tb_async_stream_ref_t stream, tb_hize_t offset, tb_async_stream_seek_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_file_impl_t* impl = tb_async_stream_file_impl_cast(stream);
- tb_assert_and_check_return_val(impl && func, tb_false);
-
- // done
- tb_size_t state = TB_STATE_UNKNOWN_ERROR;
- do
- {
- // check
- tb_assert_and_check_break(impl->aico);
-
- // is stream file?
- tb_check_break_state(!impl->bstream, state, TB_STATE_NOT_SUPPORTED);
-
- // update offset
- tb_atomic64_set(&impl->offset, offset);
-
- // ok
- state = TB_STATE_OK;
-
- } while (0);
-
- // done func
- func(stream, state, offset, priv);
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_async_stream_file_impl_sync_func(tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(aice && aice->aico && aice->code == TB_AICE_CODE_FSYNC, tb_false);
-
- // the stream
- tb_async_stream_file_impl_t* impl = (tb_async_stream_file_impl_t*)aice->priv;
- tb_assert_and_check_return_val(impl && impl->func.sync, tb_false);
-
- // done func
- impl->func.sync((tb_async_stream_ref_t)impl, aice->state == TB_STATE_OK? TB_STATE_OK : TB_STATE_UNKNOWN_ERROR, impl->bclosing, impl->priv);
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_async_stream_file_impl_sync(tb_async_stream_ref_t stream, tb_bool_t bclosing, tb_async_stream_sync_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_file_impl_t* impl = tb_async_stream_file_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->aico && func, tb_false);
-
- // save func and priv
- impl->priv = priv;
- impl->func.sync = func;
- impl->bclosing = bclosing;
-
- // post sync
- return tb_aico_fsync(impl->aico, tb_async_stream_file_impl_sync_func, stream);
-}
-static tb_bool_t tb_async_stream_file_impl_task_func(tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(aice && aice->aico && aice->code == TB_AICE_CODE_RUNTASK, tb_false);
-
- // the stream
- tb_async_stream_file_impl_t* impl = (tb_async_stream_file_impl_t*)aice->priv;
- tb_assert_and_check_return_val(impl && impl->func.task, tb_false);
-
- // done func
- tb_bool_t ok = impl->func.task((tb_async_stream_ref_t)impl, aice->state, impl->priv);
-
- // ok and continue?
- if (ok && aice->state == TB_STATE_OK)
- {
- // post task
- tb_aico_task_run(aice->aico, aice->u.runtask.delay, tb_async_stream_file_impl_task_func, impl);
- }
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_async_stream_file_impl_task(tb_async_stream_ref_t stream, tb_size_t delay, tb_async_stream_task_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_file_impl_t* impl = tb_async_stream_file_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->aico && func, tb_false);
-
- // save func and priv
- impl->priv = priv;
- impl->func.task = func;
-
- // post task
- return tb_aico_task_run(impl->aico, delay, tb_async_stream_file_impl_task_func, stream);
-}
-static tb_void_t tb_async_stream_file_impl_kill(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_file_impl_t* impl = tb_async_stream_file_impl_cast(stream);
- tb_assert_and_check_return(impl);
-
- // trace
- tb_trace_d("kill: %s: ..", tb_url_cstr(tb_async_stream_url(stream)));
-
- // kill it
- if (impl->aico) tb_aico_kill(impl->aico);
-}
-static tb_bool_t tb_async_stream_file_impl_exit(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_file_impl_t* impl = tb_async_stream_file_impl_cast(stream);
- tb_assert_and_check_return_val(impl, tb_false);
-
- // exit aico
- if (impl->aico) tb_aico_exit(impl->aico);
- impl->aico = tb_null;
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_async_stream_file_impl_ctrl(tb_async_stream_ref_t stream, tb_size_t ctrl, tb_va_list_t args)
-{
- // check
- tb_async_stream_file_impl_t* impl = tb_async_stream_file_impl_cast(stream);
- tb_assert_and_check_return_val(impl, tb_false);
-
- // ctrl
- switch (ctrl)
- {
- case TB_STREAM_CTRL_GET_SIZE:
- {
- // check
- tb_assert_and_check_return_val(tb_async_stream_is_opened(stream) && impl->aico, tb_false);
-
- // the file
- tb_file_ref_t file = tb_aico_file(impl->aico);
- tb_assert_and_check_return_val(file, tb_false);
-
- // the psize
- tb_hong_t* psize = (tb_hong_t*)tb_va_arg(args, tb_hong_t*);
- tb_assert_and_check_return_val(psize, tb_false);
-
- // get size
- if (!impl->bstream) *psize = tb_file_size(file);
- else *psize = -1;
-
- // ok
- return tb_true;
- }
- case TB_STREAM_CTRL_GET_OFFSET:
- {
- // check
- tb_assert_and_check_return_val(tb_async_stream_is_opened(stream), tb_false);
-
- // the poffset
- tb_hize_t* poffset = (tb_hize_t*)tb_va_arg(args, tb_hize_t*);
- tb_assert_and_check_return_val(poffset, tb_false);
-
- // get offset
- *poffset = (tb_hize_t)tb_atomic64_get(&impl->offset);
-
- // ok
- return tb_true;
- }
- case TB_STREAM_CTRL_FILE_SET_MODE:
- {
- // check
- tb_assert_and_check_return_val(tb_async_stream_is_closed(stream), tb_false);
-
- // set mode
- impl->mode = (tb_size_t)tb_va_arg(args, tb_size_t);
- return tb_true;
- }
- case TB_STREAM_CTRL_FILE_GET_MODE:
- {
- // the pmode
- tb_size_t* pmode = (tb_size_t*)tb_va_arg(args, tb_size_t*);
- tb_assert_and_check_return_val(pmode, tb_false);
-
- // get mode
- *pmode = impl->mode;
-
- // ok
- return tb_true;
- }
- case TB_STREAM_CTRL_FILE_IS_STREAM:
- {
- // is stream
- impl->bstream = (tb_bool_t)tb_va_arg(args, tb_bool_t);
-
- // ok
- return tb_true;
- }
- default:
- break;
- }
- return tb_false;
-}
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * interfaces
- */
-tb_async_stream_ref_t tb_async_stream_init_file(tb_aicp_ref_t aicp)
-{
- // init stream
- tb_async_stream_ref_t stream = tb_async_stream_init( aicp
- , TB_STREAM_TYPE_FILE
- , sizeof(tb_async_stream_file_impl_t)
- , TB_ASYNC_STREAM_FILE_CACHE_MAXN
- , TB_ASYNC_STREAM_FILE_CACHE_MAXN
- , tb_async_stream_file_impl_open_try
- , tb_async_stream_file_impl_clos_try
- , tb_async_stream_file_impl_open
- , tb_async_stream_file_impl_clos
- , tb_async_stream_file_impl_exit
- , tb_async_stream_file_impl_kill
- , tb_async_stream_file_impl_ctrl
- , tb_async_stream_file_impl_read
- , tb_async_stream_file_impl_writ
- , tb_async_stream_file_impl_seek
- , tb_async_stream_file_impl_sync
- , tb_async_stream_file_impl_task);
- tb_assert_and_check_return_val(stream, tb_null);
-
- // init the stream impl
- tb_async_stream_file_impl_t* impl = tb_async_stream_file_impl_cast(stream);
- if (impl)
- {
- // init mode
- impl->mode = TB_FILE_MODE_RO;
- impl->bstream = tb_false;
- }
-
- // ok?
- return stream;
-}
-tb_async_stream_ref_t tb_async_stream_init_from_file(tb_aicp_ref_t aicp, tb_char_t const* path, tb_size_t mode)
-{
- // check
- tb_assert_and_check_return_val(path, tb_null);
-
- // done
- tb_bool_t ok = tb_false;
- tb_async_stream_ref_t stream = tb_null;
- do
- {
- // init stream
- stream = tb_async_stream_init_file(aicp);
- tb_assert_and_check_break(stream);
-
- // set path
- if (!tb_async_stream_ctrl(stream, TB_STREAM_CTRL_SET_URL, path)) break;
-
- // set mode
- if (stream) if (!tb_async_stream_ctrl(stream, TB_STREAM_CTRL_FILE_SET_MODE, mode)) break;
-
- // check
- tb_assert_static(!(tb_offsetof(tb_async_stream_file_impl_t, offset) & (sizeof(tb_atomic64_t) - 1)));
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // failed?
- if (!ok)
- {
- // exit it
- if (stream) tb_async_stream_exit(stream);
- stream = tb_null;
- }
-
- // ok
- return stream;
-}
diff --git a/core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/filter.c b/core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/filter.c
deleted file mode 100644
index d6a26e8a0..000000000
--- a/core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/filter.c
+++ /dev/null
@@ -1,916 +0,0 @@
-/*!The Treasure Box Library
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
- *
- * @author ruki
- * @file filter.c
- *
- */
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * trace
- */
-#define TB_TRACE_MODULE_NAME "async_stream_filter"
-#define TB_TRACE_MODULE_DEBUG (1)
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
- */
-#include "prefix.h"
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * types
- */
-
-// the filter stream type
-typedef struct __tb_async_stream_filter_impl_t
-{
- // the filter
- tb_filter_ref_t filter;
-
- // the filter is referenced? need not exit it
- tb_uint32_t bref : 1;
-
- // is reading now?
- tb_uint32_t bread : 1;
-
- // the stream
- tb_async_stream_ref_t stream;
-
- // the read size
- tb_size_t size;
-
- // the offset
- tb_atomic64_t offset;
-
- // is closing for sync
- tb_bool_t bclosing;
-
- // the func
- union
- {
- tb_async_stream_open_func_t open;
- tb_async_stream_read_func_t read;
- tb_async_stream_writ_func_t writ;
- tb_async_stream_sync_func_t sync;
- tb_async_stream_task_func_t task;
- tb_async_stream_clos_func_t clos;
-
- } func;
-
- // the priv
- tb_cpointer_t priv;
-
-}tb_async_stream_filter_impl_t;
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
- */
-static __tb_inline__ tb_async_stream_filter_impl_t* tb_async_stream_filter_impl_cast(tb_async_stream_ref_t stream)
-{
- // check
- tb_assert_and_check_return_val(stream && tb_async_stream_type(stream) == TB_STREAM_TYPE_FLTR, tb_null);
-
- // ok?
- return (tb_async_stream_filter_impl_t*)stream;
-}
-static tb_void_t tb_async_stream_filter_impl_clos_clear(tb_async_stream_filter_impl_t* impl)
-{
- // check
- tb_assert_and_check_return(impl);
-
- // clos the filter
- if (impl->filter) tb_filter_clos(impl->filter);
-
- // clear the mode
- impl->bread = 0;
-
- // clear the offset
- tb_atomic64_set0(&impl->offset);
-
- // clear base
- tb_async_stream_clear((tb_async_stream_ref_t)impl);
-}
-static tb_void_t tb_async_stream_filter_impl_clos_func(tb_async_stream_ref_t stream, tb_size_t state, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_filter_impl_t* impl = tb_async_stream_filter_impl_cast((tb_async_stream_ref_t)priv);
- tb_assert_and_check_return(impl && impl->func.clos);
-
- // trace
- tb_trace_d("clos: notify: ..");
-
- // clear it
- tb_async_stream_filter_impl_clos_clear(impl);
-
- /* done clos func
- *
- * note: cannot use this stream after closing, the stream may be exited in the closing func
- */
- impl->func.clos((tb_async_stream_ref_t)impl, TB_STATE_OK, impl->priv);
-
- // trace
- tb_trace_d("clos: notify: ok");
-}
-static tb_bool_t tb_async_stream_filter_impl_clos_try(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_filter_impl_t* impl = tb_async_stream_filter_impl_cast(stream);
- tb_assert_and_check_return_val(impl, tb_false);
-
- // try closing ok?
- if (!impl->stream || tb_async_stream_clos_try(impl->stream))
- {
- // clear it
- tb_async_stream_filter_impl_clos_clear(impl);
-
- // ok
- return tb_true;
- }
-
- // failed
- return tb_false;
-}
-static tb_bool_t tb_async_stream_filter_impl_clos(tb_async_stream_ref_t stream, tb_async_stream_clos_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_filter_impl_t* impl = tb_async_stream_filter_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->stream && func, tb_false);
-
- // trace
- tb_trace_d("clos: ..");
-
- // init clos
- impl->func.clos = func;
- impl->priv = priv;
-
- // close it
- return tb_async_stream_clos(impl->stream, tb_async_stream_filter_impl_clos_func, impl);
-}
-static tb_bool_t tb_async_stream_filter_impl_open_func(tb_async_stream_ref_t stream, tb_size_t state, tb_cpointer_t priv)
-{
- // check
- tb_assert_and_check_return_val(stream, tb_false);
-
- // the stream
- tb_async_stream_filter_impl_t* impl = (tb_async_stream_filter_impl_t*)priv;
- tb_assert_and_check_return_val(impl && impl->func.open, tb_false);
-
- // trace
- tb_trace_d("open: %s, state: %s", tb_url_cstr(tb_async_stream_url(stream)), tb_state_cstr(state));
-
- // open done
- return tb_async_stream_open_func((tb_async_stream_ref_t)impl, state, impl->func.open, impl->priv);
-}
-static tb_bool_t tb_async_stream_filter_impl_open_try(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_filter_impl_t* impl = tb_async_stream_filter_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->stream, tb_false);
-
- // done
- tb_bool_t ok = tb_false;
- do
- {
- // clear the mode
- impl->bread = 0;
-
- // clear the offset
- tb_atomic64_set0(&impl->offset);
-
- // open filter first
- if (impl->filter && !tb_filter_open(impl->filter)) break;
-
- // try opening stream
- if (!tb_async_stream_open_try(impl->stream)) break;
-
- // open done
- tb_async_stream_open_done(stream);
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // failed? clear it
- if (!ok) tb_async_stream_filter_impl_clos_clear(impl);
-
- // ok?
- return ok;
-}
-static tb_bool_t tb_async_stream_filter_impl_open(tb_async_stream_ref_t stream, tb_async_stream_open_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_filter_impl_t* impl = tb_async_stream_filter_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->stream && func, tb_false);
-
- // clear the mode
- impl->bread = 0;
-
- // clear the offset
- tb_atomic64_set0(&impl->offset);
-
- // open filter first
- if (impl->filter && !tb_filter_open(impl->filter))
- {
- // open done
- return tb_async_stream_open_func(stream, TB_STATE_FAILED, func, priv);
- }
-
- // init func and priv
- impl->priv = priv;
- impl->func.open = func;
-
- // post open
- return tb_async_stream_open(impl->stream, tb_async_stream_filter_impl_open_func, stream);
-}
-static tb_bool_t tb_async_stream_filter_impl_sync_read_func(tb_async_stream_ref_t stream, tb_size_t state, tb_cpointer_t priv)
-{
- // check
- tb_assert_and_check_return_val(stream, tb_false);
-
- // the stream
- tb_async_stream_filter_impl_t* impl = (tb_async_stream_filter_impl_t*)priv;
- tb_assert_and_check_return_val(impl && impl->func.read, tb_false);
-
- // trace
- tb_trace_d("sync_read: %s, state: %s", tb_url_cstr(tb_async_stream_url(stream)), tb_state_cstr(state));
-
- // killed or failed?
- if (state != TB_STATE_OK && state != TB_STATE_CLOSED)
- {
- // done func
- impl->func.read((tb_async_stream_ref_t)impl, state, tb_null, 0, impl->size, impl->priv);
-
- // break it
- return tb_false;
- }
-
- // spak the filter
- tb_byte_t const* data = tb_null;
- tb_long_t spak = tb_filter_spak(impl->filter, tb_null, 0, &data, impl->size, -1);
-
- // has output data?
- tb_bool_t ok = tb_false;
- if (spak > 0 && data)
- {
- // save offset
- tb_atomic64_fetch_and_add(&impl->offset, spak);
-
- // done data
- ok = impl->func.read((tb_async_stream_ref_t)impl, TB_STATE_OK, data, spak, impl->size, impl->priv);
- }
- // closed?
- else
- {
- // done closed
- impl->func.read((tb_async_stream_ref_t)impl, TB_STATE_CLOSED, tb_null, 0, impl->size, impl->priv);
-
- // break it
- // ok = tb_false;
- }
-
- // ok?
- return ok;
-}
-static tb_bool_t tb_async_stream_filter_impl_read_func(tb_async_stream_ref_t stream, tb_size_t state, tb_byte_t const* data, tb_size_t real, tb_size_t size, tb_cpointer_t priv)
-{
- // check
- tb_assert_and_check_return_val(stream, tb_false);
-
- // the stream
- tb_async_stream_filter_impl_t* impl = (tb_async_stream_filter_impl_t*)priv;
- tb_assert_and_check_return_val(impl && impl->func.read, tb_false);
-
- // trace
- tb_trace_d("read: %s, state: %s", tb_url_cstr(tb_async_stream_url(stream)), tb_state_cstr(state));
-
- // done filter
- tb_bool_t ok = tb_false;
- if (impl->filter)
- {
- // done filter
- switch (state)
- {
- case TB_STATE_OK:
- {
- // spak the filter
- tb_long_t spak = tb_filter_spak(impl->filter, data, real, &data, size, 0);
-
- // has output data?
- if (spak > 0 && data)
- {
- // save offset
- tb_atomic64_fetch_and_add(&impl->offset, spak);
-
- // done data
- ok = impl->func.read((tb_async_stream_ref_t)impl, TB_STATE_OK, data, spak, size, impl->priv);
- }
- // no data? continue it
- else if (!spak) ok = tb_true;
- // closed?
- else
- {
- // done closed
- impl->func.read((tb_async_stream_ref_t)impl, TB_STATE_CLOSED, tb_null, 0, size, impl->priv);
-
- // break it
- // ok = tb_false;
- }
-
- // eof and continue?
- if (tb_filter_beof(impl->filter) && ok)
- {
- // done sync for reading
- ok = tb_async_stream_task(impl->stream, 0, tb_async_stream_filter_impl_sync_read_func, impl);
-
- // error? done error
- if (!ok) impl->func.read((tb_async_stream_ref_t)impl, TB_STATE_UNKNOWN_ERROR, tb_null, 0, size, impl->priv);
-
- // need not read data, break it
- ok = tb_false;
- }
- }
- break;
- case TB_STATE_CLOSED:
- {
- // done sync for reading
- ok = tb_async_stream_task(impl->stream, 0, tb_async_stream_filter_impl_sync_read_func, impl);
-
- // error? done error
- if (!ok) impl->func.read((tb_async_stream_ref_t)impl, TB_STATE_UNKNOWN_ERROR, tb_null, 0, size, impl->priv);
- }
- break;
- default:
- {
- // done closed or failed
- impl->func.read((tb_async_stream_ref_t)impl, state, tb_null, 0, size, impl->priv);
-
- // break it
- // ok = tb_false;
- }
- break;
- }
- }
- // done func
- else ok = impl->func.read((tb_async_stream_ref_t)impl, state, data, real, size, impl->priv);
-
- // ok?
- return ok;
-}
-static tb_bool_t tb_async_stream_filter_impl_read(tb_async_stream_ref_t stream, tb_size_t delay, tb_byte_t* data, tb_size_t size, tb_async_stream_read_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_filter_impl_t* impl = tb_async_stream_filter_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->stream && func, tb_false);
-
- // clear the offset if be writ mode now
- if (!impl->bread) tb_atomic64_set0(&impl->offset);
-
- // set read mode
- impl->bread = 1;
-
- // save func and priv
- impl->priv = priv;
- impl->func.read = func;
- impl->size = size;
-
- // filter eof? flush the left data
- if (impl->filter && tb_filter_beof(impl->filter))
- return tb_async_stream_task(impl->stream, 0, tb_async_stream_filter_impl_sync_read_func, impl);
-
- // post read
- return tb_async_stream_read_after(impl->stream, delay, size, tb_async_stream_filter_impl_read_func, stream);
-}
-static tb_bool_t tb_async_stream_filter_impl_writ_func(tb_async_stream_ref_t stream, tb_size_t state, tb_byte_t const* data, tb_size_t real, tb_size_t size, tb_cpointer_t priv)
-{
- // check
- tb_assert_and_check_return_val(stream, tb_false);
-
- // the stream
- tb_async_stream_filter_impl_t* impl = (tb_async_stream_filter_impl_t*)priv;
- tb_assert_and_check_return_val(impl && impl->func.writ, tb_false);
-
- // trace
- tb_trace_d("writ: %s, state: %s", tb_url_cstr(tb_async_stream_url(stream)), tb_state_cstr(state));
-
- // save offset
- if (real) tb_atomic64_fetch_and_add(&impl->offset, real);
-
- // done func
- return impl->func.writ((tb_async_stream_ref_t)impl, state, data, real, size, impl->priv);
-}
-static tb_bool_t tb_async_stream_filter_impl_writ(tb_async_stream_ref_t stream, tb_size_t delay, tb_byte_t const* data, tb_size_t size, tb_async_stream_writ_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_filter_impl_t* impl = tb_async_stream_filter_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->stream && data && size && func, tb_false);
-
- // clear the offset if be read mode now
- if (impl->bread) tb_atomic64_set0(&impl->offset);
-
- // set writ mode
- impl->bread = 0;
-
- // save func and priv
- impl->priv = priv;
- impl->func.writ = func;
-
- // done filter
- tb_bool_t ok = tb_true;
- if (impl->filter)
- {
- // spak the filter
- tb_long_t real = tb_filter_spak(impl->filter, data, size, &data, size, 0);
-
- // has data?
- if (real > 0 && data)
- {
- // post writ
- ok = tb_async_stream_writ_after(impl->stream, delay, data, real, tb_async_stream_filter_impl_writ_func, stream);
- }
- // no data or end? continue to writ or sync
- else
- {
- // done func, no data and finished
- ok = func((tb_async_stream_ref_t)impl, TB_STATE_OK, tb_null, 0, 0, impl->priv);
- }
- }
- // post writ
- else ok = tb_async_stream_writ_after(impl->stream, delay, data, size, tb_async_stream_filter_impl_writ_func, stream);
-
- // ok?
- return ok;
-}
-static tb_bool_t tb_async_stream_filter_impl_sync_func(tb_async_stream_ref_t stream, tb_size_t state, tb_bool_t bclosing, tb_cpointer_t priv)
-{
- // check
- tb_assert_and_check_return_val(stream, tb_false);
-
- // the stream
- tb_async_stream_filter_impl_t* impl = (tb_async_stream_filter_impl_t*)priv;
- tb_assert_and_check_return_val(impl && impl->func.sync, tb_false);
-
- // trace
- tb_trace_d("sync: %s, state: %s", tb_url_cstr(tb_async_stream_url(stream)), tb_state_cstr(state));
-
- // done func
- return impl->func.sync((tb_async_stream_ref_t)impl, state, bclosing, impl->priv);
-}
-static tb_bool_t tb_async_stream_filter_impl_writ_sync_func(tb_async_stream_ref_t stream, tb_size_t state, tb_byte_t const* data, tb_size_t real, tb_size_t size, tb_cpointer_t priv)
-{
- // check
- tb_assert_and_check_return_val(stream && data && size, tb_false);
-
- // the stream
- tb_async_stream_filter_impl_t* impl = (tb_async_stream_filter_impl_t*)priv;
- tb_assert_and_check_return_val(impl && impl->func.sync, tb_false);
-
- // trace
- tb_trace_d("writ_sync: %s, state: %s", tb_url_cstr(tb_async_stream_url(stream)), tb_state_cstr(state));
-
- // save offset
- if (real) tb_atomic64_fetch_and_add(&impl->offset, real);
-
- // not finished? continue it
- tb_bool_t ok = tb_false;
- if (state == TB_STATE_OK && real < size) ok = tb_true;
- // ok? sync it
- else if (state == TB_STATE_OK && real == size)
- {
- // post sync
- ok = tb_async_stream_sync(impl->stream, impl->bclosing, tb_async_stream_filter_impl_sync_func, impl);
-
- // failed? done func
- if (!ok) ok = impl->func.sync((tb_async_stream_ref_t)impl, TB_STATE_UNKNOWN_ERROR, impl->bclosing, impl->priv);
- }
- // failed?
- else
- {
- // failed? done func
- ok = impl->func.sync((tb_async_stream_ref_t)impl, state != TB_STATE_OK? state : TB_STATE_UNKNOWN_ERROR, impl->bclosing, impl->priv);
- }
-
- // ok?
- return ok;
-}
-static tb_bool_t tb_async_stream_filter_impl_sync(tb_async_stream_ref_t stream, tb_bool_t bclosing, tb_async_stream_sync_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_filter_impl_t* impl = tb_async_stream_filter_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->stream && func, tb_false);
-
- // clear the offset if be read mode now
- if (impl->bread) tb_atomic64_set0(&impl->offset);
-
- // set writ mode
- impl->bread = 0;
-
- // save func and priv
- impl->priv = priv;
- impl->func.sync = func;
- impl->bclosing = bclosing;
-
- // done filter
- tb_bool_t ok = tb_true;
- if (impl->filter)
- {
- // trace
- tb_trace_d("sync: spak: %s", tb_url_cstr(tb_async_stream_url(stream)));
-
- // spak the filter
- tb_byte_t const* data = tb_null;
- tb_long_t real = tb_filter_spak(impl->filter, tb_null, 0, &data, 0, bclosing? -1 : 1);
-
- // has data? post writ and sync
- if (real > 0 && data)
- ok = tb_async_stream_writ(impl->stream, data, real, tb_async_stream_filter_impl_writ_sync_func, stream);
- }
- // post sync
- else ok = tb_async_stream_sync(impl->stream, bclosing, tb_async_stream_filter_impl_sync_func, stream);
-
- // ok?
- return ok;
-}
-static tb_bool_t tb_async_stream_filter_impl_task_func(tb_async_stream_ref_t stream, tb_size_t state, tb_cpointer_t priv)
-{
- // check
- tb_assert_and_check_return_val(stream, tb_false);
-
- // the stream
- tb_async_stream_filter_impl_t* impl = (tb_async_stream_filter_impl_t*)priv;
- tb_assert_and_check_return_val(impl && impl->func.task, tb_false);
-
- // done func
- return impl->func.task((tb_async_stream_ref_t)impl, state, impl->priv);
-}
-static tb_bool_t tb_async_stream_filter_impl_task(tb_async_stream_ref_t stream, tb_size_t delay, tb_async_stream_task_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_filter_impl_t* impl = tb_async_stream_filter_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->stream && func, tb_false);
-
- // save func and priv
- impl->priv = priv;
- impl->func.task = func;
-
- // post task
- return tb_async_stream_task(impl->stream, delay, tb_async_stream_filter_impl_task_func, stream);
-}
-static tb_void_t tb_async_stream_filter_impl_kill(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_filter_impl_t* impl = tb_async_stream_filter_impl_cast(stream);
- tb_assert_and_check_return(impl);
-
- // kill stream
- if (impl->stream) tb_async_stream_kill(impl->stream);
-}
-static tb_bool_t tb_async_stream_filter_impl_exit(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_filter_impl_t* impl = tb_async_stream_filter_impl_cast(stream);
- tb_assert_and_check_return_val(impl, tb_false);
-
- // exit it
- if (!impl->bref && impl->filter) tb_filter_exit(impl->filter);
- impl->filter = tb_null;
- impl->bref = 0;
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_async_stream_filter_impl_ctrl(tb_async_stream_ref_t stream, tb_size_t ctrl, tb_va_list_t args)
-{
- // check
- tb_async_stream_filter_impl_t* impl = tb_async_stream_filter_impl_cast(stream);
- tb_assert_and_check_return_val(impl, tb_false);
-
- // ctrl
- switch (ctrl)
- {
- case TB_STREAM_CTRL_GET_OFFSET:
- {
- // check
- tb_assert_and_check_break(tb_async_stream_is_opened(stream));
-
- // the poffset
- tb_hize_t* poffset = (tb_hize_t*)tb_va_arg(args, tb_hize_t*);
- tb_assert_and_check_break(poffset);
-
- // get offset
- *poffset = (tb_hize_t)tb_atomic64_get(&impl->offset);
-
- // ok
- return tb_true;
- }
- case TB_STREAM_CTRL_FLTR_SET_STREAM:
- {
- // check
- tb_assert_and_check_break(tb_async_stream_is_closed(stream));
-
- // set pstream
- impl->stream = (tb_async_stream_ref_t)tb_va_arg(args, tb_async_stream_ref_t);
-
- // ok
- return tb_true;
- }
- case TB_STREAM_CTRL_FLTR_GET_STREAM:
- {
- // the pstream
- tb_async_stream_ref_t* pstream = (tb_async_stream_ref_t*)tb_va_arg(args, tb_async_stream_ref_t*);
- tb_assert_and_check_break(pstream);
-
- // get stream
- *pstream = impl->stream;
-
- // ok
- return tb_true;
- }
- case TB_STREAM_CTRL_FLTR_SET_FILTER:
- {
- // check
- tb_assert_and_check_break(tb_async_stream_is_closed(stream));
-
- // exit filter first if exists
- if (!impl->bref && impl->filter) tb_filter_exit(impl->filter);
-
- // set filter
- tb_filter_ref_t filter = (tb_filter_ref_t)tb_va_arg(args, tb_filter_ref_t);
- impl->filter = filter;
- impl->bref = filter? 1 : 0;
-
- // ok
- return tb_true;
- }
- case TB_STREAM_CTRL_FLTR_GET_FILTER:
- {
- // the pfilter
- tb_filter_ref_t* pfilter = (tb_filter_ref_t*)tb_va_arg(args, tb_filter_ref_t*);
- tb_assert_and_check_break(pfilter);
-
- // get filter
- *pfilter = impl->filter;
-
- // ok
- return tb_true;
- }
- default:
- break;
- }
-
- // failed
- return tb_false;
-}
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * interfaces
- */
-tb_async_stream_ref_t tb_async_stream_init_filter(tb_aicp_ref_t aicp)
-{
- return tb_async_stream_init( aicp
- , TB_STREAM_TYPE_FLTR
- , sizeof(tb_async_stream_filter_impl_t)
- , 0
- , 0
- , tb_async_stream_filter_impl_open_try
- , tb_async_stream_filter_impl_clos_try
- , tb_async_stream_filter_impl_open
- , tb_async_stream_filter_impl_clos
- , tb_async_stream_filter_impl_exit
- , tb_async_stream_filter_impl_kill
- , tb_async_stream_filter_impl_ctrl
- , tb_async_stream_filter_impl_read
- , tb_async_stream_filter_impl_writ
- , tb_null
- , tb_async_stream_filter_impl_sync
- , tb_async_stream_filter_impl_task);
-}
-tb_async_stream_ref_t tb_async_stream_init_filter_from_null(tb_async_stream_ref_t stream)
-{
- // check
- tb_assert_and_check_return_val(stream, tb_null);
-
- // the aicp
- tb_aicp_ref_t aicp = tb_async_stream_aicp(stream);
- tb_assert_and_check_return_val(aicp, tb_null);
-
- // done
- tb_bool_t ok = tb_false;
- tb_async_stream_ref_t impl = tb_null;
- do
- {
- // init stream
- impl = tb_async_stream_init_filter(aicp);
- tb_assert_and_check_break(impl);
-
- // set stream
- if (!tb_async_stream_ctrl(impl, TB_STREAM_CTRL_FLTR_SET_STREAM, stream)) break;
-
- // check
- tb_assert_static(!(tb_offsetof(tb_async_stream_filter_impl_t, offset) & (sizeof(tb_atomic64_t) - 1)));
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // failed?
- if (!ok)
- {
- // exit it
- if (impl) tb_async_stream_exit((tb_async_stream_ref_t)impl);
- impl = tb_null;
- }
-
- // ok?
- return impl;
-}
-#ifdef TB_CONFIG_MODULE_HAVE_ZIP
-tb_async_stream_ref_t tb_async_stream_init_filter_from_zip(tb_async_stream_ref_t stream, tb_size_t algo, tb_size_t action)
-{
- // check
- tb_assert_and_check_return_val(stream, tb_null);
-
- // the aicp
- tb_aicp_ref_t aicp = tb_async_stream_aicp(stream);
- tb_assert_and_check_return_val(aicp, tb_null);
-
- // done
- tb_bool_t ok = tb_false;
- tb_async_stream_ref_t impl = tb_null;
- do
- {
- // init stream
- impl = tb_async_stream_init_filter(aicp);
- tb_assert_and_check_break(impl);
-
- // set stream
- if (!tb_async_stream_ctrl(impl, TB_STREAM_CTRL_FLTR_SET_STREAM, stream)) break;
-
- // set filter
- ((tb_async_stream_filter_impl_t*)impl)->bref = 0;
- ((tb_async_stream_filter_impl_t*)impl)->filter = tb_filter_init_from_zip(algo, action);
- tb_assert_and_check_break(((tb_async_stream_filter_impl_t*)impl)->filter);
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // failed?
- if (!ok)
- {
- // exit it
- if (impl) tb_async_stream_exit(impl);
- impl = tb_null;
- }
-
- // ok?
- return impl;
-}
-#endif
-tb_async_stream_ref_t tb_async_stream_init_filter_from_cache(tb_async_stream_ref_t stream, tb_size_t size)
-{
- // check
- tb_assert_and_check_return_val(stream, tb_null);
-
- // the aicp
- tb_aicp_ref_t aicp = tb_async_stream_aicp(stream);
- tb_assert_and_check_return_val(aicp, tb_null);
-
- // done
- tb_bool_t ok = tb_false;
- tb_async_stream_ref_t impl = tb_null;
- do
- {
- // init stream
- impl = tb_async_stream_init_filter(aicp);
- tb_assert_and_check_break(impl);
-
- // set stream
- if (!tb_async_stream_ctrl(impl, TB_STREAM_CTRL_FLTR_SET_STREAM, stream)) break;
-
- // set filter
- ((tb_async_stream_filter_impl_t*)impl)->bref = 0;
- ((tb_async_stream_filter_impl_t*)impl)->filter = tb_filter_init_from_cache(size);
- tb_assert_and_check_break(((tb_async_stream_filter_impl_t*)impl)->filter);
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // failed?
- if (!ok)
- {
- // exit it
- if (impl) tb_async_stream_exit(impl);
- impl = tb_null;
- }
-
- // ok?
- return impl;
-}
-#ifdef TB_CONFIG_MODULE_HAVE_CHARSET
-tb_async_stream_ref_t tb_async_stream_init_filter_from_charset(tb_async_stream_ref_t stream, tb_size_t fr, tb_size_t to)
-{
- // check
- tb_assert_and_check_return_val(stream, tb_null);
-
- // the aicp
- tb_aicp_ref_t aicp = tb_async_stream_aicp(stream);
- tb_assert_and_check_return_val(aicp, tb_null);
-
- // done
- tb_bool_t ok = tb_false;
- tb_async_stream_ref_t impl = tb_null;
- do
- {
- // init stream
- impl = tb_async_stream_init_filter(aicp);
- tb_assert_and_check_break(impl);
-
- // set stream
- if (!tb_async_stream_ctrl(impl, TB_STREAM_CTRL_FLTR_SET_STREAM, stream)) break;
-
- // set filter
- ((tb_async_stream_filter_impl_t*)impl)->bref = 0;
- ((tb_async_stream_filter_impl_t*)impl)->filter = tb_filter_init_from_charset(fr, to);
- tb_assert_and_check_break(((tb_async_stream_filter_impl_t*)impl)->filter);
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // failed?
- if (!ok)
- {
- // exit it
- if (impl) tb_async_stream_exit(impl);
- impl = tb_null;
- }
-
- // ok?
- return impl;
-}
-#endif
-tb_async_stream_ref_t tb_async_stream_init_filter_from_chunked(tb_async_stream_ref_t stream, tb_bool_t dechunked)
-{
- // check
- tb_assert_and_check_return_val(stream, tb_null);
-
- // the aicp
- tb_aicp_ref_t aicp = tb_async_stream_aicp(stream);
- tb_assert_and_check_return_val(aicp, tb_null);
-
- // done
- tb_bool_t ok = tb_false;
- tb_async_stream_ref_t impl = tb_null;
- do
- {
- // init stream
- impl = tb_async_stream_init_filter(aicp);
- tb_assert_and_check_break(impl);
-
- // set stream
- if (!tb_async_stream_ctrl(impl, TB_STREAM_CTRL_FLTR_SET_STREAM, stream)) break;
-
- // set filter
- ((tb_async_stream_filter_impl_t*)impl)->bref = 0;
- ((tb_async_stream_filter_impl_t*)impl)->filter = tb_filter_init_from_chunked(dechunked);
- tb_assert_and_check_break(((tb_async_stream_filter_impl_t*)impl)->filter);
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // failed?
- if (!ok)
- {
- // exit it
- if (impl) tb_async_stream_exit(impl);
- impl = tb_null;
- }
-
- // ok?
- return impl;
-}
diff --git a/core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/http.c b/core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/http.c
deleted file mode 100644
index c4b0506cc..000000000
--- a/core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/http.c
+++ /dev/null
@@ -1,849 +0,0 @@
-/*!The Treasure Box Library
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
- *
- * @author ruki
- * @file http.c
- *
- */
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * trace
- */
-#define TB_TRACE_MODULE_NAME "async_stream_http"
-#define TB_TRACE_MODULE_DEBUG (1)
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
- */
-#include "prefix.h"
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * types
- */
-
-// the http stream type
-typedef struct __tb_async_stream_http_impl_t
-{
- // the http
- tb_aicp_http_ref_t http;
-
- // the size
- tb_atomic64_t size;
-
- // the offset
- tb_atomic64_t offset;
-
- // the func
- union
- {
- tb_async_stream_open_func_t open;
- tb_async_stream_read_func_t read;
- tb_async_stream_seek_func_t seek;
- tb_async_stream_sync_func_t sync;
- tb_async_stream_task_func_t task;
- tb_async_stream_clos_func_t clos;
-
- } func;
-
- // the priv
- tb_cpointer_t priv;
-
-}tb_async_stream_http_impl_t;
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
- */
-static __tb_inline__ tb_async_stream_http_impl_t* tb_async_stream_http_impl_cast(tb_async_stream_ref_t stream)
-{
- // check
- tb_assert_and_check_return_val(stream && tb_async_stream_type(stream) == TB_STREAM_TYPE_HTTP, tb_null);
-
- // ok?
- return (tb_async_stream_http_impl_t*)stream;
-}
-static tb_void_t tb_async_stream_http_impl_clos_clear(tb_async_stream_http_impl_t* impl)
-{
- // check
- tb_assert_and_check_return(impl);
-
- // clear size
- tb_atomic64_set(&impl->size, -1);
-
- // clear offset
- tb_atomic64_set0(&impl->offset);
-
- // clear base
- tb_async_stream_clear((tb_async_stream_ref_t)impl);
-}
-static tb_void_t tb_async_stream_http_impl_clos_func(tb_aicp_http_ref_t http, tb_size_t state, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_http_impl_t* impl = tb_async_stream_http_impl_cast((tb_async_stream_ref_t)priv);
- tb_assert_and_check_return(impl && impl->func.clos);
-
- // trace
- tb_trace_d("clos: notify: ..");
-
- // clear it
- tb_async_stream_http_impl_clos_clear(impl);
-
- /* done clos func
- *
- * note: cannot use this stream after closing, the stream may be exited in the closing func
- */
- impl->func.clos((tb_async_stream_ref_t)impl, TB_STATE_OK, impl->priv);
-
- // trace
- tb_trace_d("clos: notify: ok");
-}
-static tb_bool_t tb_async_stream_http_impl_clos_try(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_http_impl_t* impl = tb_async_stream_http_impl_cast(stream);
- tb_assert_and_check_return_val(impl, tb_false);
-
- // try closing ok?
- if (!impl->http || tb_aicp_http_clos_try(impl->http))
- {
- // clear it
- tb_async_stream_http_impl_clos_clear(impl);
-
- // ok
- return tb_true;
- }
-
- // failed
- return tb_false;
-}
-static tb_bool_t tb_async_stream_http_impl_clos(tb_async_stream_ref_t stream, tb_async_stream_clos_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_http_impl_t* impl = tb_async_stream_http_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->http && func, tb_false);
-
- // trace
- tb_trace_d("clos: %s: ..", tb_url_cstr(tb_async_stream_url(stream)));
-
- // init func
- impl->func.clos = func;
- impl->priv = priv;
-
- // close it
- return tb_aicp_http_clos(impl->http, tb_async_stream_http_impl_clos_func, impl);
-}
-static tb_bool_t tb_async_stream_http_impl_open_func(tb_aicp_http_ref_t http, tb_size_t state, tb_http_status_t const* status, tb_cpointer_t priv)
-{
- // check
- tb_assert_and_check_return_val(http && status, tb_false);
-
- // the stream
- tb_async_stream_http_impl_t* impl = (tb_async_stream_http_impl_t*)priv;
- tb_assert_and_check_return_val(impl && impl->func.open, tb_false);
-
- // save size
- tb_hong_t size = (!status->bgzip && !status->bdeflate && !status->bchunked)? status->document_size : -1;
- if (size >= 0) tb_atomic64_set(&impl->size, size);
-
- // open done
- return tb_async_stream_open_func((tb_async_stream_ref_t)impl, state, impl->func.open, impl->priv);
-}
-static tb_bool_t tb_async_stream_http_impl_open(tb_async_stream_ref_t stream, tb_async_stream_open_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_http_impl_t* impl = tb_async_stream_http_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->http && func, tb_false);
-
- // save func and priv
- impl->priv = priv;
- impl->func.open = func;
-
- // init size and offset
- tb_atomic64_set(&impl->size, -1);
- tb_atomic64_set0(&impl->offset);
-
- // post open
- return tb_aicp_http_open(impl->http, tb_async_stream_http_impl_open_func, stream);
-}
-static tb_bool_t tb_async_stream_http_impl_read_func(tb_aicp_http_ref_t http, tb_size_t state, tb_byte_t const* data, tb_size_t real, tb_size_t size, tb_cpointer_t priv)
-{
- // check
- tb_assert_and_check_return_val(http, tb_false);
-
- // the stream
- tb_async_stream_http_impl_t* impl = (tb_async_stream_http_impl_t*)priv;
- tb_assert_and_check_return_val(impl && impl->func.read, tb_false);
-
- // ok?
- tb_bool_t bend = tb_false;
- if (state == TB_STATE_OK)
- {
- // save offset
- tb_hize_t offset = tb_atomic64_add_and_fetch(&impl->offset, real);
-
- // end?
- tb_hong_t hsize = tb_atomic64_get(&impl->size);
- if (hsize >= 0 && offset == hsize) bend = tb_true;
- }
-
- // done func
- tb_bool_t ok = impl->func.read((tb_async_stream_ref_t)impl, state, data, real, size, impl->priv);
-
- // end? closed
- if (ok && bend) ok = impl->func.read((tb_async_stream_ref_t)impl, TB_STATE_CLOSED, data, 0, size, impl->priv);
-
- // ok?
- return ok;
-}
-static tb_bool_t tb_async_stream_http_impl_read(tb_async_stream_ref_t stream, tb_size_t delay, tb_byte_t* data, tb_size_t size, tb_async_stream_read_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_http_impl_t* impl = tb_async_stream_http_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->http && func, tb_false);
-
- // end? closed
- tb_hong_t hsize = tb_atomic64_get(&impl->size);
- if (hsize >= 0)
- {
- tb_hize_t offset = tb_atomic64_get(&impl->offset);
- if (offset == hsize)
- {
- func(stream, TB_STATE_CLOSED, tb_null, 0, size, priv);
- return tb_true;
- }
- }
-
- // save func and priv
- impl->priv = priv;
- impl->func.read = func;
-
- // post read
- return tb_aicp_http_read_after(impl->http, delay, size, tb_async_stream_http_impl_read_func, stream);
-}
-static tb_bool_t tb_async_stream_http_impl_seek_func(tb_aicp_http_ref_t http, tb_size_t state, tb_hize_t offset, tb_cpointer_t priv)
-{
- // check
- tb_assert_and_check_return_val(http, tb_false);
-
- // the stream
- tb_async_stream_http_impl_t* impl = (tb_async_stream_http_impl_t*)priv;
- tb_assert_and_check_return_val(impl && impl->func.seek, tb_false);
-
- // save offset
- if (state == TB_STATE_OK) tb_atomic64_set(&impl->offset, offset);
-
- // done func
- return impl->func.seek((tb_async_stream_ref_t)impl, state, offset, impl->priv);
-}
-static tb_bool_t tb_async_stream_http_impl_seek(tb_async_stream_ref_t stream, tb_hize_t offset, tb_async_stream_seek_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_http_impl_t* impl = tb_async_stream_http_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->http && func, tb_false);
-
- // save func and priv
- impl->priv = priv;
- impl->func.seek = func;
-
- // post seek
- return tb_aicp_http_seek(impl->http, offset, tb_async_stream_http_impl_seek_func, stream);
-}
-static tb_bool_t tb_async_stream_http_impl_task_func(tb_aicp_http_ref_t http, tb_size_t state, tb_cpointer_t priv)
-{
- // check
- tb_assert_and_check_return_val(http, tb_false);
-
- // the stream
- tb_async_stream_http_impl_t* impl = (tb_async_stream_http_impl_t*)priv;
- tb_assert_and_check_return_val(impl && impl->func.task, tb_false);
-
- // done func
- return impl->func.task((tb_async_stream_ref_t)impl, state, impl->priv);
-}
-static tb_bool_t tb_async_stream_http_impl_task(tb_async_stream_ref_t stream, tb_size_t delay, tb_async_stream_task_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_http_impl_t* impl = tb_async_stream_http_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->http && func, tb_false);
-
- // save func and priv
- impl->priv = priv;
- impl->func.task = func;
-
- // post task
- return tb_aicp_http_task(impl->http, delay, tb_async_stream_http_impl_task_func, stream);
-}
-static tb_void_t tb_async_stream_http_impl_kill(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_http_impl_t* impl = tb_async_stream_http_impl_cast(stream);
- tb_assert_and_check_return(impl);
-
- // trace
- tb_trace_d("kill: %s: ..", tb_url_cstr(tb_async_stream_url(stream)));
-
- // kill it
- if (impl->http) tb_aicp_http_kill(impl->http);
-}
-static tb_bool_t tb_async_stream_http_impl_exit(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_http_impl_t* impl = tb_async_stream_http_impl_cast(stream);
- tb_assert_and_check_return_val(impl, tb_false);
-
- // exit it
- if (impl->http) tb_aicp_http_exit(impl->http);
- impl->http = tb_null;
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_async_stream_http_impl_ctrl(tb_async_stream_ref_t stream, tb_size_t ctrl, tb_va_list_t args)
-{
- // check
- tb_async_stream_http_impl_t* impl = tb_async_stream_http_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->http, tb_false);
-
- // done
- switch (ctrl)
- {
- case TB_STREAM_CTRL_GET_SIZE:
- {
- // check
- tb_assert_and_check_return_val(tb_async_stream_is_opened(stream) && impl->http, tb_false);
-
- // get size
- tb_hong_t* psize = (tb_hong_t*)tb_va_arg(args, tb_hong_t*);
- tb_assert_and_check_return_val(psize, tb_false);
- *psize = (tb_hong_t)tb_atomic64_get(&impl->size);
- return tb_true;
- }
- case TB_STREAM_CTRL_GET_OFFSET:
- {
- // check
- tb_assert_and_check_return_val(tb_async_stream_is_opened(stream) && impl->http, tb_false);
-
- // get offset
- tb_hize_t* poffset = (tb_hize_t*)tb_va_arg(args, tb_hize_t*);
- tb_assert_and_check_return_val(poffset, tb_false);
- *poffset = (tb_hize_t)tb_atomic64_get(&impl->offset);
- return tb_true;
- }
- case TB_STREAM_CTRL_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
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_SET_URL, url);
- }
- break;
- case TB_STREAM_CTRL_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
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_GET_URL, purl);
- }
- break;
- case TB_STREAM_CTRL_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
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_SET_HOST, host);
- }
- break;
- case TB_STREAM_CTRL_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
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_GET_HOST, phost);
- }
- break;
- case TB_STREAM_CTRL_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
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_SET_PORT, port);
- }
- break;
- case TB_STREAM_CTRL_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
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_GET_PORT, pport);
- }
- break;
- case TB_STREAM_CTRL_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
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_SET_PATH, path);
- }
- break;
- case TB_STREAM_CTRL_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
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_GET_PATH, ppath);
- }
- break;
- case TB_STREAM_CTRL_HTTP_SET_METHOD:
- {
- // method
- tb_size_t method = (tb_size_t)tb_va_arg(args, tb_size_t);
-
- // set method
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_SET_METHOD, method);
- }
- break;
- case TB_STREAM_CTRL_HTTP_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
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_GET_METHOD, pmethod);
- }
- break;
- case TB_STREAM_CTRL_HTTP_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);
-
- // set head
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_SET_HEAD, key, val);
- }
- break;
- case TB_STREAM_CTRL_HTTP_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);
-
- // get head
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_GET_HEAD, key, pval);
- }
- break;
- case TB_STREAM_CTRL_HTTP_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
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_SET_HEAD_FUNC, head_func);
- }
- break;
- case TB_STREAM_CTRL_HTTP_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
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_GET_HEAD_FUNC, phead_func);
- }
- break;
- case TB_STREAM_CTRL_HTTP_SET_HEAD_PRIV:
- {
- // head_priv
- tb_pointer_t head_priv = (tb_pointer_t)tb_va_arg(args, tb_pointer_t);
-
- // set head_priv
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_SET_HEAD_PRIV, head_priv);
- }
- break;
- case TB_STREAM_CTRL_HTTP_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
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_GET_HEAD_PRIV, phead_priv);
- }
- break;
- case TB_STREAM_CTRL_HTTP_SET_RANGE:
- {
- tb_hize_t bof = (tb_hize_t)tb_va_arg(args, tb_hize_t);
- tb_hize_t eof = (tb_hize_t)tb_va_arg(args, tb_hize_t);
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_SET_RANGE, bof, eof);
- }
- break;
- case TB_STREAM_CTRL_HTTP_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
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_GET_RANGE, pbof, peof);
- }
- break;
- case TB_STREAM_CTRL_SET_SSL:
- {
- // bssl
- tb_bool_t bssl = (tb_bool_t)tb_va_arg(args, tb_bool_t);
-
- // set ssl
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_SET_SSL, bssl);
- }
- break;
- case TB_STREAM_CTRL_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
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_GET_SSL, pssl);
- }
- break;
- case TB_STREAM_CTRL_SET_TIMEOUT:
- {
- // timeout
- tb_size_t timeout = (tb_size_t)tb_va_arg(args, tb_size_t);
- tb_assert_and_check_return_val(timeout, tb_false);
-
- // set timeout
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_SET_TIMEOUT, timeout);
- }
- break;
- case TB_STREAM_CTRL_GET_TIMEOUT:
- {
- // ptimeout
- tb_size_t* ptimeout = (tb_size_t*)tb_va_arg(args, tb_size_t*);
- tb_assert_and_check_return_val(ptimeout, tb_false);
-
- // get timeout
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_GET_TIMEOUT, ptimeout);
- }
- break;
- case TB_STREAM_CTRL_HTTP_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);
-
- // set url
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_SET_POST_URL, url);
- }
- break;
- case TB_STREAM_CTRL_HTTP_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
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_GET_POST_URL, purl);
- }
- break;
- case TB_STREAM_CTRL_HTTP_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);
-
- // set post data
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_SET_POST_DATA, data, size);
- }
- break;
- case TB_STREAM_CTRL_HTTP_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
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_GET_POST_DATA, pdata, psize);
- }
- break;
- case TB_STREAM_CTRL_HTTP_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
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_SET_POST_FUNC, func);
- }
- break;
- case TB_STREAM_CTRL_HTTP_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
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_GET_POST_FUNC, pfunc);
- }
- break;
- case TB_STREAM_CTRL_HTTP_SET_POST_PRIV:
- {
- // post priv
- tb_cpointer_t priv = (tb_pointer_t)tb_va_arg(args, tb_pointer_t);
-
- // set post priv
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_SET_POST_PRIV, priv);
- }
- break;
- case TB_STREAM_CTRL_HTTP_GET_POST_PRIV:
- {
- // ppost priv
- tb_pointer_t* ppriv = (tb_pointer_t*)tb_va_arg(args, tb_pointer_t*);
- tb_assert_and_check_return_val(ppriv, tb_false);
-
- // get post priv
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_GET_POST_PRIV, ppriv);
- }
- break;
- case TB_STREAM_CTRL_HTTP_SET_POST_LRATE:
- {
- // post lrate
- tb_size_t lrate = (tb_size_t)tb_va_arg(args, tb_size_t);
-
- // set post lrate
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_SET_POST_LRATE, lrate);
- }
- break;
- case TB_STREAM_CTRL_HTTP_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
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_GET_POST_LRATE, plrate);
- }
- break;
- case TB_STREAM_CTRL_HTTP_SET_AUTO_UNZIP:
- {
- // bunzip
- tb_bool_t bunzip = (tb_bool_t)tb_va_arg(args, tb_bool_t);
-
- // set bunzip
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_SET_AUTO_UNZIP, bunzip);
- }
- break;
- case TB_STREAM_CTRL_HTTP_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
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_GET_AUTO_UNZIP, pbunzip);
- }
- break;
- case TB_STREAM_CTRL_HTTP_SET_REDIRECT:
- {
- // redirect
- tb_size_t redirect = (tb_size_t)tb_va_arg(args, tb_size_t);
-
- // set redirect
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_SET_REDIRECT, redirect);
- }
- break;
- case TB_STREAM_CTRL_HTTP_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
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_GET_REDIRECT, predirect);
- }
- break;
- case TB_STREAM_CTRL_HTTP_SET_VERSION:
- {
- // version
- tb_size_t version = (tb_size_t)tb_va_arg(args, tb_size_t);
-
- // set version
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_SET_VERSION, version);
- }
- break;
- case TB_STREAM_CTRL_HTTP_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
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_GET_VERSION, pversion);
- }
- break;
- case TB_STREAM_CTRL_HTTP_SET_COOKIES:
- {
- // cookies
- tb_cookies_ref_t cookies = (tb_cookies_ref_t)tb_va_arg(args, tb_cookies_ref_t);
-
- // set cookies
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_SET_COOKIES, cookies);
- }
- break;
- case TB_STREAM_CTRL_HTTP_GET_COOKIES:
- {
- // pcookies
- 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 version
- return tb_aicp_http_ctrl(impl->http, TB_HTTP_OPTION_GET_COOKIES, pcookies);
- }
- break;
- default:
- break;
- }
- return tb_false;
-}
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * interfaces
- */
-tb_async_stream_ref_t tb_async_stream_init_http(tb_aicp_ref_t aicp)
-{
- // done
- tb_bool_t ok = tb_false;
- tb_async_stream_ref_t stream = tb_null;
- do
- {
- // init stream
- stream = tb_async_stream_init( aicp
- , TB_STREAM_TYPE_HTTP
- , sizeof(tb_async_stream_http_impl_t)
- , 0
- , 0
- , tb_null
- , tb_async_stream_http_impl_clos_try
- , tb_async_stream_http_impl_open
- , tb_async_stream_http_impl_clos
- , tb_async_stream_http_impl_exit
- , tb_async_stream_http_impl_kill
- , tb_async_stream_http_impl_ctrl
- , tb_async_stream_http_impl_read
- , tb_null
- , tb_async_stream_http_impl_seek
- , tb_null
- , tb_async_stream_http_impl_task);
- tb_assert_and_check_break(stream);
-
- // init the stream impl
- tb_async_stream_http_impl_t* impl = tb_async_stream_http_impl_cast(stream);
- tb_assert_and_check_break(impl);
-
- // init http
- impl->http = tb_aicp_http_init(tb_async_stream_aicp(stream));
- tb_assert_and_check_break(impl->http);
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // failed?
- if (!ok)
- {
- // exit it
- if (stream) tb_async_stream_exit(stream);
- stream = tb_null;
- }
-
- // ok?
- return stream;
-}
-tb_async_stream_ref_t tb_async_stream_init_from_http(tb_aicp_ref_t aicp, tb_char_t const* host, tb_uint16_t port, tb_char_t const* path, tb_bool_t bssl)
-{
- // check
- tb_assert_and_check_return_val(host && port && path, tb_null);
-
- // done
- tb_bool_t ok = tb_false;
- tb_async_stream_ref_t stream = tb_null;
- do
- {
- // init stream
- stream = tb_async_stream_init_http(aicp);
- tb_assert_and_check_break(stream);
-
- // ctrl
- if (!tb_async_stream_ctrl(stream, TB_STREAM_CTRL_SET_HOST, host)) break;
- if (!tb_async_stream_ctrl(stream, TB_STREAM_CTRL_SET_PORT, port)) break;
- if (!tb_async_stream_ctrl(stream, TB_STREAM_CTRL_SET_PATH, path)) break;
- if (!tb_async_stream_ctrl(stream, TB_STREAM_CTRL_SET_SSL, bssl)) break;
-
- // check
- tb_assert_static(!(tb_offsetof(tb_async_stream_http_impl_t, size) & (sizeof(tb_atomic64_t) - 1)));
- tb_assert_static(!(tb_offsetof(tb_async_stream_http_impl_t, offset) & (sizeof(tb_atomic64_t) - 1)));
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // failed?
- if (!ok)
- {
- // exit it
- if (stream) tb_async_stream_exit(stream);
- stream = tb_null;
- }
-
- // ok?
- return stream;
-}
-
diff --git a/core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/prefix.c b/core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/prefix.c
deleted file mode 100644
index 3a4d3aa4a..000000000
--- a/core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/prefix.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*!The Treasure Box Library
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
- *
- * @author ruki
- * @file prefix.c
- *
- */
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * trace
- */
-#define TB_TRACE_MODULE_NAME "async_stream"
-#define TB_TRACE_MODULE_DEBUG (1)
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
- */
-#include "prefix.h"
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
- */
-static tb_void_t tb_async_stream_clos_opening(tb_async_stream_ref_t stream, tb_size_t state, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return(impl);
-
- // trace
- tb_trace_d("clos: opening: %s, state: %s", tb_url_cstr(&impl->url), tb_state_cstr(impl->clos_opening.state));
-
- // closed
- tb_atomic_set(&impl->istate, TB_STATE_CLOSED);
-
- // done func
- if (impl->clos_opening.func) impl->clos_opening.func(stream, impl->clos_opening.state, impl->clos_opening.priv);
-}
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * private interfaces
- */
-tb_void_t tb_async_stream_clear(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return(impl);
-
- // clear rcache
- tb_buffer_clear(&impl->rcache_data);
-
- // clear wcache
- tb_buffer_clear(&impl->wcache_data);
-
- // clear istate
- tb_atomic_set(&impl->istate, TB_STATE_CLOSED);
-}
-tb_void_t tb_async_stream_open_done(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return(impl);
-
- // opened or closed?
- tb_atomic_set(&impl->istate, TB_STATE_OPENED);
-}
-tb_bool_t tb_async_stream_open_func(tb_async_stream_ref_t stream, tb_size_t state, tb_async_stream_open_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
- tb_assert_and_check_return_val(impl, tb_false);
-
- // ok?
- tb_bool_t ok = tb_true;
- if (state == TB_STATE_OK)
- {
- // opened
- tb_atomic_set(&impl->istate, TB_STATE_OPENED);
-
- // done func
- if (func) ok = func(stream, state, priv);
- }
- // failed?
- else
- {
- // try closing ok?
- if (impl->clos_try && impl->clos_try(stream))
- {
- // closed
- tb_atomic_set(&impl->istate, TB_STATE_CLOSED);
-
- // done func
- if (func) func(stream, state, priv);
- }
- else
- {
- // check
- tb_assert_and_check_return_val(impl->clos, tb_false);
-
- // init func and state
- impl->clos_opening.func = func;
- impl->clos_opening.priv = priv;
- impl->clos_opening.state = state;
-
- // close it
- ok = impl->clos(stream, tb_async_stream_clos_opening, tb_null);
- }
- }
-
- // ok?
- return ok;
-}
-
diff --git a/core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/prefix.h b/core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/prefix.h
deleted file mode 100644
index cda25b51a..000000000
--- a/core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/prefix.h
+++ /dev/null
@@ -1,390 +0,0 @@
-/*!The Treasure Box Library
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
- *
- * @author ruki
- * @file prefix.h
- *
- */
-#ifndef TB_STREAM_IMPL_ASYNC_STREAM_PREFIX_H
-#define TB_STREAM_IMPL_ASYNC_STREAM_PREFIX_H
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
- */
-#include "../prefix.h"
-#include "../../async_stream.h"
-#include "../../../filter.h"
-#include "../../../../asio/deprecated/asio.h"
-#include "../../../../platform/platform.h"
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * macros
- */
-
-// the async stream impl
-#define tb_async_stream_impl(stream) ((stream)? &(((tb_async_stream_impl_t*)(stream))[-1]) : tb_null)
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * types
- */
-
-// the stream open and read type
-typedef struct __tb_async_stream_open_read_t
-{
- // the func
- tb_async_stream_read_func_t func;
-
- // the priv
- tb_cpointer_t priv;
-
- // the size
- tb_size_t size;
-
-}tb_async_stream_open_read_t;
-
-// the stream open and writ type
-typedef struct __tb_async_stream_open_writ_t
-{
- // the func
- tb_async_stream_writ_func_t func;
-
- // the priv
- tb_cpointer_t priv;
-
- // the data
- tb_byte_t const* data;
-
- // the size
- tb_size_t size;
-
-}tb_async_stream_open_writ_t;
-
-// the stream open and seek type
-typedef struct __tb_async_stream_open_seek_t
-{
- // the func
- tb_async_stream_seek_func_t func;
-
- // the priv
- tb_cpointer_t priv;
-
- // the offset
- tb_hize_t offset;
-
-}tb_async_stream_open_seek_t;
-
-// the stream close opening type
-typedef struct __tb_async_stream_clos_opening_t
-{
- // the func
- tb_async_stream_open_func_t func;
-
- // the priv
- tb_cpointer_t priv;
-
- // the open state
- tb_size_t state;
-
-}tb_async_stream_clos_opening_t;
-
-// the stream cache and writ type
-typedef struct __tb_async_stream_cache_writ_t
-{
- // the func
- tb_async_stream_writ_func_t func;
-
- // the data
- tb_byte_t const* data;
-
- // the size
- tb_size_t size;
-
-}tb_async_stream_cache_writ_t;
-
-// the stream cache and sync type
-typedef struct __tb_async_stream_cache_sync_t
-{
- // the func
- tb_async_stream_sync_func_t func;
-
- // is closing
- tb_bool_t bclosing;
-
-}tb_async_stream_cache_sync_t;
-
-// the stream sync and read type
-typedef struct __tb_async_stream_sync_read_t
-{
- // the func
- tb_async_stream_read_func_t func;
-
- // the priv
- tb_cpointer_t priv;
-
- // the size
- tb_size_t size;
-
-}tb_async_stream_sync_read_t;
-
-// the stream sync and seek type
-typedef struct __tb_async_stream_sync_seek_t
-{
- // the func
- tb_async_stream_seek_func_t func;
-
- // the priv
- tb_cpointer_t priv;
-
- // the offset
- tb_hize_t offset;
-
-}tb_async_stream_sync_seek_t;
-
-// the asio stream type
-typedef __tb_aligned__(8) struct __tb_async_stream_impl_t
-{
- // the stream type
- tb_uint8_t type;
-
- // the url
- tb_url_t url;
-
- /* internal state
- *
- * <pre>
- * TB_STATE_CLOSED
- * TB_STATE_OPENED
- * TB_STATE_KILLED
- * TB_STATE_OPENING
- * TB_STATE_KILLING
- * </pre>
- */
- tb_atomic_t istate;
-
- // the timeout
- tb_long_t timeout;
-
- // the aicp
- tb_aicp_ref_t aicp;
-
-#ifdef __tb_debug__
- // the func
- tb_char_t const* func;
-
- // the file
- tb_char_t const* file;
-
- // the line
- tb_size_t line;
-#endif
-
- // the open and read, writ, seek, ...
- union
- {
- tb_async_stream_open_read_t read;
- tb_async_stream_open_writ_t writ;
- tb_async_stream_open_seek_t seek;
-
- } open_and;
-
- // the sync and read, writ, seek, ...
- union
- {
- tb_async_stream_sync_read_t read;
- tb_async_stream_sync_seek_t seek;
-
- } sync_and;
-
- // the wcache and writ, sync, ...
- union
- {
- tb_async_stream_cache_writ_t writ;
- tb_async_stream_cache_sync_t sync;
-
- } wcache_and;
-
- // the close opening
- tb_async_stream_clos_opening_t clos_opening;
-
- // the read cache data
- tb_buffer_t rcache_data;
-
- // the read cache maxn
- tb_size_t rcache_maxn;
-
- // the writ cache data
- tb_buffer_t wcache_data;
-
- // the writ cache maxn
- tb_size_t wcache_maxn;
-
- /* try opening stream, optional
- *
- * @param stream the stream
- *
- * @return tb_true or tb_false
- */
- tb_bool_t (*open_try)(tb_async_stream_ref_t stream);
-
- /* try closing stream, optional
- *
- * @param stream the stream
- *
- * @return tb_true or tb_false
- */
- tb_bool_t (*clos_try)(tb_async_stream_ref_t stream);
-
- /* open stream
- *
- * @param stream the stream
- * @param func the open func
- * @param priv the func private data
- *
- * @return tb_true or tb_false
- */
- tb_bool_t (*open)(tb_async_stream_ref_t stream, tb_async_stream_open_func_t func, tb_cpointer_t priv);
-
- /* clos stream
- *
- * @param stream the stream
- * @param func the open func
- * @param priv the func private data
- *
- * @return tb_true or tb_false
- */
- tb_bool_t (*clos)(tb_async_stream_ref_t stream, tb_async_stream_clos_func_t func, tb_cpointer_t priv);
-
- /* read stream
- *
- * @param stream the stream
- * @param delay read it after the delay time, ms
- * @param data the read data
- * @param size the read size
- * @param func the read func
- * @param priv the func private data
- *
- * @return tb_true or tb_false
- */
- tb_bool_t (*read)(tb_async_stream_ref_t stream, tb_size_t delay, tb_byte_t* data, tb_size_t size, tb_async_stream_read_func_t func, tb_cpointer_t priv);
-
- /* writ stream
- *
- * @param stream the stream
- * @param delay writ it after the delay time, ms
- * @param data the writ data
- * @param size the writ size
- * @param func the writ func
- * @param priv the func private data
- *
- * @return tb_true or tb_false
- */
- tb_bool_t (*writ)(tb_async_stream_ref_t stream, tb_size_t delay, tb_byte_t const* data, tb_size_t size, tb_async_stream_writ_func_t func, tb_cpointer_t priv);
-
- /* seek stream, optional
- *
- * @param stream the stream
- * @param offset the seek offset
- * @param func the writ func
- * @param priv the func private data
- *
- * @return tb_true or tb_false
- */
- tb_bool_t (*seek)(tb_async_stream_ref_t stream, tb_hize_t offset, tb_async_stream_seek_func_t func, tb_cpointer_t priv);
-
- /* sync stream, optional
- *
- * @param stream the stream
- * @param bclosing the stream will be closed?
- * @param func the writ func
- * @param priv the func private data
- *
- * @return tb_true or tb_false
- */
- tb_bool_t (*sync)(tb_async_stream_ref_t stream, tb_bool_t bclosing, tb_async_stream_sync_func_t func, tb_cpointer_t priv);
-
- /* post stream task
- *
- * @param stream the stream
- * @param delay done it after the delay time, ms
- * @param func the writ func
- * @param priv the func private data
- *
- * @return tb_true or tb_false
- */
- tb_bool_t (*task)(tb_async_stream_ref_t stream, tb_size_t delay, tb_async_stream_task_func_t func, tb_cpointer_t priv);
-
- /* ctrl stream
- *
- * @param stream the stream
- * @param ctrl the ctrl code
- * @param args the ctrl arguments
- *
- * @return tb_true or tb_false
- */
- tb_bool_t (*ctrl)(tb_async_stream_ref_t stream, tb_size_t ctrl, tb_va_list_t args);
-
- /* exit stream, optional
- *
- * @param stream the stream
- *
- * @return tb_true or tb_false
- */
- tb_bool_t (*exit)(tb_async_stream_ref_t stream);
-
- /* kill stream
- *
- * @param stream the stream
- *
- * @return tb_true or tb_false
- */
- tb_void_t (*kill)(tb_async_stream_ref_t stream);
-
-}__tb_aligned__(8) tb_async_stream_impl_t;
-
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * private interfaces
- */
-
-/* clear the stream after closing stream
- *
- * @param stream the stream
- */
-tb_void_t tb_async_stream_clear(tb_async_stream_ref_t stream);
-
-/* done the opening stream
- *
- * @param stream the stream
- */
-tb_void_t tb_async_stream_open_done(tb_async_stream_ref_t stream);
-
-/* done the open func after opening stream
- *
- * @param stream the stream
- * @param state the state
- * @param func the open func
- * @param priv the func private data
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_async_stream_open_func(tb_async_stream_ref_t stream, tb_size_t state, tb_async_stream_open_func_t func, tb_cpointer_t priv);
-
-
-#endif
diff --git a/core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/sock.c b/core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/sock.c
deleted file mode 100644
index a3fd9f808..000000000
--- a/core/src/tbox/src/tbox/stream/deprecated/impl/async_stream/sock.c
+++ /dev/null
@@ -1,1231 +0,0 @@
-/*!The Treasure Box Library
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
- *
- * @author ruki
- * @file sock.c
- *
- */
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * trace
- */
-#define TB_TRACE_MODULE_NAME "async_stream_sock"
-#define TB_TRACE_MODULE_DEBUG (1)
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
- */
-#include "prefix.h"
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * macros
- */
-
-// the sock cache maxn
-#ifdef __tb_small__
-# define TB_STREAM_SOCK_CACHE_MAXN (8192)
-#else
-# define TB_STREAM_SOCK_CACHE_MAXN (8192 << 1)
-#endif
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * types
- */
-
-// the sock stream type
-typedef struct __tb_async_stream_sock_impl_t
-{
- // the aico
- tb_aico_ref_t aico;
-
- // the aicp dns
- tb_aicp_dns_ref_t hdns;
-
-#ifdef TB_SSL_ENABLE
- // the aicp ssl
- tb_aicp_ssl_ref_t hssl;
-#endif
-
- // the sock type
- tb_uint32_t type : 31;
-
- // keep alive after being closed?
- tb_uint32_t balived : 1;
-
- // is reading now?
- tb_uint32_t bread : 1;
-
- // the offset
- tb_atomic64_t offset;
-
- // the func
- union
- {
- tb_async_stream_open_func_t open;
- tb_async_stream_read_func_t read;
- tb_async_stream_writ_func_t writ;
- tb_async_stream_task_func_t task;
- tb_async_stream_clos_func_t clos;
-
- } func;
-
- // the priv
- tb_cpointer_t priv;
-
-}tb_async_stream_sock_impl_t;
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
- */
-static __tb_inline__ tb_async_stream_sock_impl_t* tb_async_stream_sock_impl_cast(tb_async_stream_ref_t stream)
-{
- // check
- tb_assert_and_check_return_val(stream && tb_async_stream_type(stream) == TB_STREAM_TYPE_SOCK, tb_null);
-
- // ok?
- return (tb_async_stream_sock_impl_t*)stream;
-}
-static tb_void_t tb_async_stream_sock_impl_clos_clear(tb_async_stream_sock_impl_t* impl)
-{
- // check
- tb_assert_and_check_return(impl);
-
- // clear the mode
- impl->bread = 0;
-
- // clear the offset
- tb_atomic64_set0(&impl->offset);
-
- // clear base
- tb_async_stream_clear((tb_async_stream_ref_t)impl);
-}
-static tb_void_t tb_async_stream_sock_impl_clos_func(tb_aico_ref_t aico, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_sock_impl_t* impl = tb_async_stream_sock_impl_cast((tb_async_stream_ref_t)priv);
- tb_assert_and_check_return(impl && impl->func.clos);
-
- // trace
- tb_trace_d("clos[%p]: notify: %s: ..", aico, tb_url_cstr(tb_async_stream_url((tb_async_stream_ref_t)impl)));
-
- // clear it
- tb_async_stream_sock_impl_clos_clear(impl);
-
- /* done clos func
- *
- * note: cannot use this stream after closing, the stream may be exited in the closing func
- */
- impl->func.clos((tb_async_stream_ref_t)impl, TB_STATE_OK, impl->priv);
-
- // trace
- tb_trace_d("clos[%p]: notify: ok", aico);
-}
-static tb_bool_t tb_async_stream_sock_impl_clos_aico_func(tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_CLOS, tb_false);
-
- // the impl
- tb_async_stream_sock_impl_t* impl = tb_async_stream_sock_impl_cast((tb_async_stream_ref_t)aice->priv);
- tb_assert_and_check_return_val(impl, tb_false);
-
- // trace
- tb_trace_d("clos[%p]: aico: notify: %s: ..", aice->aico, tb_url_cstr(tb_async_stream_url((tb_async_stream_ref_t)impl)));
-
- // clear aico
-#ifdef TB_SSL_ENABLE
- if (impl->hssl) tb_aicp_ssl_set_aico(impl->hssl, tb_null);
-#endif
-
- // done func directly
- tb_async_stream_sock_impl_clos_func(tb_null, impl);
-
- // trace
- tb_trace_d("clos[%p]: aico: notify: ok", aice->aico);
-
- // ok
- return tb_true;
-}
-#ifdef TB_SSL_ENABLE
-static tb_void_t tb_async_stream_sock_impl_clos_ssl_func(tb_aicp_ssl_ref_t ssl, tb_size_t state, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_sock_impl_t* impl = tb_async_stream_sock_impl_cast((tb_async_stream_ref_t)priv);
- tb_assert_and_check_return(impl && impl->aico && impl->func.clos);
-
- // trace
- tb_trace_d("clos[%p]: ssl: notify: %s: ..", impl->aico, tb_url_cstr(tb_async_stream_url((tb_async_stream_ref_t)impl)));
-
- // close it if be not alived
- if (!impl->balived)
- {
- // clos aico
- tb_aico_clos(impl->aico, tb_async_stream_sock_impl_clos_aico_func, impl);
- }
- // done func directly
- else tb_async_stream_sock_impl_clos_func(tb_null, impl);
-
- // trace
- tb_trace_d("clos: ssl: notify: ok");
-}
-#endif
-static tb_bool_t tb_async_stream_sock_impl_clos_try(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_sock_impl_t* impl = tb_async_stream_sock_impl_cast(stream);
- tb_assert_and_check_return_val(impl, tb_false);
-
- // trace
- tb_trace_d("clos[%p]: try: %s: ..", impl->aico, tb_url_cstr(tb_async_stream_url(stream)));
-
- // try closing ssl first
-#ifdef TB_SSL_ENABLE
- if (!impl->hssl || tb_aicp_ssl_clos_try(impl->hssl))
-#endif
- {
- // alived or no aico or closed?
- if (impl->balived || !impl->aico || tb_aico_clos_try(impl->aico))
- {
- // clear it
- tb_async_stream_sock_impl_clos_clear(impl);
-
- // trace
- tb_trace_d("clos[%p]: try: %s: ok", impl->aico, tb_url_cstr(tb_async_stream_url(stream)));
-
- // ok
- return tb_true;
- }
- }
-
- // trace
- tb_trace_d("clos[%p]: try: %s: no", impl->aico, tb_url_cstr(tb_async_stream_url(stream)));
-
- // failed
- return tb_false;
-}
-static tb_bool_t tb_async_stream_sock_impl_clos(tb_async_stream_ref_t stream, tb_async_stream_clos_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_sock_impl_t* impl = tb_async_stream_sock_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->aico && func, tb_false);
-
- // trace
-#ifdef TB_SSL_ENABLE
- tb_trace_d("clos[%p]: %s: balived: %d, hssl: %p, hdns: %p: ..", impl->aico, tb_url_cstr(tb_async_stream_url(stream)), impl->balived, impl->hssl, impl->hdns);
-#else
- tb_trace_d("clos[%p]: %s: balived: %d, hdns: %p: ..", impl->aico, tb_url_cstr(tb_async_stream_url(stream)), impl->balived, impl->hdns);
-#endif
-
- // init clos
- impl->func.clos = func;
- impl->priv = priv;
-
- // clos ssl first
-#ifdef TB_SSL_ENABLE
- if (impl->hssl) tb_aicp_ssl_clos(impl->hssl, tb_async_stream_sock_impl_clos_ssl_func, impl);
- else
-#endif
- if (!impl->balived)
- {
- // clos aico
- tb_aico_clos(impl->aico, tb_async_stream_sock_impl_clos_aico_func, impl);
- }
- // done func directly
- else tb_async_stream_sock_impl_clos_func(tb_null, impl);
-
- // ok
- return tb_true;
-}
-#ifdef TB_SSL_ENABLE
-static tb_bool_t tb_async_stream_sock_impl_open_ssl_func(tb_aicp_ssl_ref_t ssl, tb_size_t state, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_sock_impl_t* impl = tb_async_stream_sock_impl_cast((tb_async_stream_ref_t)priv);
- tb_assert_and_check_return_val(ssl && impl->func.open, tb_false);
-
- // trace
- tb_trace_d("open[%p]: ssl: %s", impl->aico, tb_state_cstr(state));
-
- // open done
- tb_async_stream_open_func((tb_async_stream_ref_t)impl, state, impl->func.open, impl->priv);
-
- // ok
- return tb_true;
-}
-static tb_size_t tb_async_stream_sock_impl_open_ssl(tb_async_stream_sock_impl_t* impl)
-{
- // check
- tb_assert_and_check_return_val(impl && impl->aico, TB_STATE_SOCK_SSL_UNKNOWN_ERROR);
-
- // init ssl
- if (!impl->hssl) impl->hssl = tb_aicp_ssl_init(tb_async_stream_aicp((tb_async_stream_ref_t)impl), tb_false);
- tb_assert_and_check_return_val(impl->hssl, TB_STATE_SOCK_SSL_UNKNOWN_ERROR);
-
- // killed?
- if (tb_async_stream_is_killed((tb_async_stream_ref_t)impl)) return TB_STATE_KILLED;
-
- // init ssl aico
- tb_aicp_ssl_set_aico(impl->hssl, impl->aico);
-
- // init ssl timeout
- tb_aicp_ssl_set_timeout(impl->hssl, tb_async_stream_timeout((tb_async_stream_ref_t)impl));
-
- // open ssl
- if (!tb_aicp_ssl_open(impl->hssl, tb_async_stream_sock_impl_open_ssl_func, impl)) return TB_STATE_SOCK_SSL_UNKNOWN_ERROR;
-
- // ok
- return TB_STATE_OK;
-}
-#endif
-static tb_bool_t tb_async_stream_sock_impl_conn_func(tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(aice && aice->aico && aice->code == TB_AICE_CODE_CONN, tb_false);
-
- // the stream
- tb_async_stream_sock_impl_t* impl = tb_async_stream_sock_impl_cast((tb_async_stream_ref_t)aice->priv);
- tb_assert_and_check_return_val(impl && impl->func.open, tb_false);
-
- // trace
- tb_trace_d("open[%p]: conn: %s", impl->aico, tb_state_cstr(aice->state));
-
- // done
- tb_size_t state = TB_STATE_SOCK_UNKNOWN_ERROR;
- switch (aice->state)
- {
- // ok
- case TB_STATE_OK:
- {
-#ifdef TB_SSL_ENABLE
- // ssl?
- if (tb_url_ssl(tb_async_stream_url((tb_async_stream_ref_t)impl)))
- {
- // open ssl
- state = tb_async_stream_sock_impl_open_ssl(impl);
- tb_check_break(state == TB_STATE_OK);
- }
- else
-#endif
- {
- // open done
- tb_async_stream_open_func((tb_async_stream_ref_t)impl, TB_STATE_OK, impl->func.open, impl->priv);
- }
-
- // ok
- state = TB_STATE_OK;
- }
- break;
- // timeout
- case TB_STATE_TIMEOUT:
- state = TB_STATE_SOCK_CONNECT_TIMEOUT;
- break;
- // killed
- case TB_STATE_KILLED:
- state = TB_STATE_KILLED;
- break;
- // failed
- default:
- state = TB_STATE_SOCK_CONNECT_FAILED;
- break;
- }
-
- // failed?
- if (state != TB_STATE_OK)
- {
- // open done
- tb_async_stream_open_func((tb_async_stream_ref_t)impl, state, impl->func.open, impl->priv);
- }
-
- // ok
- return tb_true;
-}
-static tb_void_t tb_async_stream_sock_impl_dns_func(tb_aicp_dns_ref_t dns, tb_char_t const* host, tb_ipaddr_ref_t addr, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_sock_impl_t* impl = tb_async_stream_sock_impl_cast((tb_async_stream_ref_t)priv);
- tb_assert_and_check_return(dns && impl && impl->func.open);
-
- // done
- tb_size_t state = TB_STATE_SOCK_UNKNOWN_ERROR;
- do
- {
- // addr ok?
- if (addr)
- {
- // trace
- tb_trace_d("open[%p]: host: %s, addr: %{ipaddr}", impl->aico, host, addr);
-
- // init aico
- if (!impl->aico) impl->aico = tb_aico_init(tb_async_stream_aicp((tb_async_stream_ref_t)impl));
- tb_assert_and_check_break(impl->aico);
-
- // open aico
- if (!tb_aico_open_sock_from_type(impl->aico, impl->type, tb_ipaddr_family(addr)))
- {
- // trace
- tb_trace_e("open sock failed!");
-
- // save state
- state = TB_STATE_SOCK_OPEN_FAILED;
- break;
- }
-
- // init timeout
- tb_long_t timeout = tb_async_stream_timeout((tb_async_stream_ref_t)impl);
- tb_aico_timeout_set(impl->aico, TB_AICO_TIMEOUT_CONN, timeout);
- tb_aico_timeout_set(impl->aico, TB_AICO_TIMEOUT_RECV, timeout);
- tb_aico_timeout_set(impl->aico, TB_AICO_TIMEOUT_SEND, timeout);
-
- // the url
- tb_url_ref_t url = tb_async_stream_url((tb_async_stream_ref_t)impl);
- tb_assert_and_check_break(url);
-
- // get address from the url
- tb_ipaddr_ref_t url_addr = tb_url_addr(url);
- tb_assert_and_check_break(url_addr);
-
- // update the ip address
- tb_ipaddr_ip_set(url_addr, addr);
-
- // the sock type: tcp or udp? for url: sock://ip:port/?udp=
- tb_char_t const* args = tb_url_args(url);
- if (args && !tb_strnicmp(args, "udp=", 4)) impl->type = TB_SOCKET_TYPE_UDP;
- else if (args && !tb_strnicmp(args, "tcp=", 4)) impl->type = TB_SOCKET_TYPE_TCP;
- tb_assert_and_check_break(impl->type == TB_SOCKET_TYPE_TCP || impl->type == TB_SOCKET_TYPE_UDP);
-
- // killed?
- if (tb_async_stream_is_killed((tb_async_stream_ref_t)impl))
- {
- // save state
- state = TB_STATE_KILLED;
- break;
- }
-
- // tcp?
- if (impl->type == TB_SOCKET_TYPE_TCP)
- {
- // done conn
- if (!tb_aico_conn(impl->aico, url_addr, tb_async_stream_sock_impl_conn_func, impl)) break;
- }
- // udp?
- else
- {
- // ssl? not supported
- if (tb_url_ssl(url))
- {
- // trace
- tb_trace_w("udp ssl is not supported!");
- }
-
- // open done
- tb_async_stream_open_func((tb_async_stream_ref_t)impl, TB_STATE_OK, impl->func.open, impl->priv);
- }
-
- // ok
- state = TB_STATE_OK;
- }
- // timeout or failed?
- else
- {
- // trace
- tb_trace_d("open[%p]: addr: %s failed", impl->aico, host);
-
- // dns failed
- state = TB_STATE_SOCK_DNS_FAILED;
- }
-
- } while (0);
-
- // failed?
- if (state != TB_STATE_OK)
- {
- // open done
- tb_async_stream_open_func((tb_async_stream_ref_t)impl, state, impl->func.open, impl->priv);
- }
-}
-static tb_bool_t tb_async_stream_sock_impl_open(tb_async_stream_ref_t stream, tb_async_stream_open_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_sock_impl_t* impl = tb_async_stream_sock_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->type && func, tb_false);
-
- // done
- tb_size_t state = TB_STATE_SOCK_UNKNOWN_ERROR;
- do
- {
- // clear the mode
- impl->bread = 0;
-
- // clear the offset
- tb_atomic64_set0(&impl->offset);
-
- // init func and priv
- impl->priv = priv;
- impl->func.open = func;
-
- // the url
- tb_url_ref_t url = tb_async_stream_url(stream);
- tb_assert_and_check_break(url);
-
-#ifndef TB_SSL_ENABLE
- // ssl? not supported
- if (tb_url_ssl(url))
- {
- // trace
- tb_trace_w("ssl is not supported now! please enable it from config if you need it.");
-
- // save state
- state = TB_STATE_SOCK_SSL_NOT_SUPPORTED;
- break;
- }
-#endif
-
- // keep alive and have been opened? reopen it directly
- if (impl->balived && impl->hdns && impl->aico)
- {
-#ifdef TB_SSL_ENABLE
- // ssl?
- if (tb_url_ssl(url))
- {
- // open ssl
- state = tb_async_stream_sock_impl_open_ssl(impl);
- tb_assert_and_check_break(state != TB_STATE_SOCK_SSL_UNKNOWN_ERROR);
- }
- else
-#endif
- // open done
- tb_async_stream_open_func(stream, TB_STATE_OK, func, priv);
-
- // ok
- state = TB_STATE_OK;
- break;
- }
-
- // get the host from url
- tb_char_t const* host = tb_url_host(url);
- tb_assert_and_check_break(host);
-
- // init dns
- if (!impl->hdns) impl->hdns = tb_aicp_dns_init(tb_async_stream_aicp(stream));
- tb_assert_and_check_break(impl->hdns);
-
- // killed?
- if (tb_async_stream_is_killed(stream))
- {
- // save state
- state = TB_STATE_KILLED;
- break;
- }
-
- // done addr
- if (!tb_aicp_dns_done(impl->hdns, host, tb_async_stream_timeout(stream), tb_async_stream_sock_impl_dns_func, stream))
- {
- // save state
- state = TB_STATE_SOCK_DNS_FAILED;
- break;
- }
-
- // ok
- state = TB_STATE_OK;
-
- } while (0);
-
- // failed?
- if (state != TB_STATE_OK)
- {
- // open done
- tb_async_stream_open_func(stream, state, func, priv);
- }
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_async_stream_sock_impl_read_func(tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(aice && aice->aico && aice->code == TB_AICE_CODE_RECV, tb_false);
-
- // the stream
- tb_async_stream_sock_impl_t* impl = (tb_async_stream_sock_impl_t*)aice->priv;
- tb_assert_and_check_return_val(impl && impl->func.read, tb_false);
-
- // trace
- tb_trace_d("recv[%p]: real: %lu, size: %lu, state: %s", aice->aico, aice->u.recv.real, aice->u.recv.size, tb_state_cstr(aice->state));
-
- // done state
- tb_size_t state = TB_STATE_SOCK_UNKNOWN_ERROR;
- switch (aice->state)
- {
- // ok
- case TB_STATE_OK:
- tb_atomic64_fetch_and_add(&impl->offset, aice->u.recv.real);
- state = TB_STATE_OK;
- break;
- // closed
- case TB_STATE_CLOSED:
- state = TB_STATE_CLOSED;
- break;
- // killed
- case TB_STATE_KILLED:
- state = TB_STATE_KILLED;
- break;
- // timeout?
- case TB_STATE_TIMEOUT:
- state = TB_STATE_SOCK_RECV_TIMEOUT;
- break;
- default:
- tb_trace_e("recv: unknown state: %s", tb_state_cstr(aice->state));
- break;
- }
-
- // done func
- if (impl->func.read((tb_async_stream_ref_t)impl, state, aice->u.recv.data, aice->u.recv.real, aice->u.recv.size, impl->priv))
- {
- // continue?
- if (aice->state == TB_STATE_OK)
- {
- // continue to post read
- if (!tb_aico_recv(aice->aico, aice->u.recv.data, aice->u.recv.size, tb_async_stream_sock_impl_read_func, (tb_async_stream_ref_t)impl))
- impl->func.read((tb_async_stream_ref_t)impl, TB_STATE_SOCK_RECV_FAILED, aice->u.recv.data, 0, aice->u.recv.size, impl->priv);
- }
- }
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_async_stream_sock_impl_read_udp_func(tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(aice && aice->aico && aice->code == TB_AICE_CODE_URECV, tb_false);
-
- // the stream
- tb_async_stream_sock_impl_t* impl = (tb_async_stream_sock_impl_t*)aice->priv;
- tb_assert_and_check_return_val(impl && impl->func.read, tb_false);
-
- // trace
- tb_trace_d("urecv[%p]: real: %lu, size: %lu, state: %s", aice->aico, aice->u.urecv.real, aice->u.urecv.size, tb_state_cstr(aice->state));
-
- // done state
- tb_size_t state = TB_STATE_SOCK_UNKNOWN_ERROR;
- switch (aice->state)
- {
- // ok
- case TB_STATE_OK:
- tb_atomic64_fetch_and_add(&impl->offset, aice->u.urecv.real);
- state = TB_STATE_OK;
- break;
- // closed
- case TB_STATE_CLOSED:
- state = TB_STATE_CLOSED;
- break;
- // killed
- case TB_STATE_KILLED:
- state = TB_STATE_KILLED;
- break;
- // timeout?
- case TB_STATE_TIMEOUT:
- state = TB_STATE_SOCK_RECV_TIMEOUT;
- break;
- default:
- tb_trace_e("read: unknown state: %s", tb_state_cstr(aice->state));
- break;
- }
-
- // done func
- if (impl->func.read((tb_async_stream_ref_t)impl, state, aice->u.urecv.data, aice->u.urecv.real, aice->u.urecv.size, impl->priv))
- {
- // continue?
- if (aice->state == TB_STATE_OK)
- {
- // continue to post read
- if (!tb_aico_urecv(aice->aico, aice->u.urecv.data, aice->u.urecv.size, tb_async_stream_sock_impl_read_udp_func, (tb_async_stream_ref_t)impl))
- impl->func.read((tb_async_stream_ref_t)impl, TB_STATE_SOCK_RECV_FAILED, aice->u.urecv.data, 0, aice->u.urecv.size, impl->priv);
- }
- }
-
- // ok
- return tb_true;
-}
-#ifdef TB_SSL_ENABLE
-static tb_bool_t tb_async_stream_sock_impl_read_ssl_func(tb_aicp_ssl_ref_t ssl, tb_size_t state, tb_byte_t* data, tb_size_t real, tb_size_t size, tb_cpointer_t priv)
-{
- // check
- tb_assert_and_check_return_val(ssl, tb_false);
-
- // the stream
- tb_async_stream_sock_impl_t* impl = (tb_async_stream_sock_impl_t*)priv;
- tb_assert_and_check_return_val(impl && impl->func.read, tb_false);
-
- // trace
- tb_trace_d("srecv[%p]: real: %lu, size: %lu, state: %s", impl->aico, real, size, tb_state_cstr(state));
-
- // save offset
- if (state == TB_STATE_OK) tb_atomic64_fetch_and_add(&impl->offset, real);
-
- // done func
- if (impl->func.read((tb_async_stream_ref_t)impl, state, data, real, size, impl->priv))
- {
- // ok? continue it
- if (state == TB_STATE_OK)
- {
- // continue to post read
- if (!tb_aicp_ssl_read(impl->hssl, data, size, tb_async_stream_sock_impl_read_ssl_func, (tb_async_stream_ref_t)impl))
- impl->func.read((tb_async_stream_ref_t)impl, TB_STATE_SOCK_SSL_READ_FAILED, data, 0, size, impl->priv);
- }
- }
-
- // ok
- return tb_true;
-}
-#endif
-static tb_bool_t tb_async_stream_sock_impl_read(tb_async_stream_ref_t stream, tb_size_t delay, tb_byte_t* data, tb_size_t size, tb_async_stream_read_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_sock_impl_t* impl = tb_async_stream_sock_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->aico && data && size && func, tb_false);
-
- // clear the offset if be writ mode now
- if (!impl->bread) tb_atomic64_set0(&impl->offset);
-
- // set read mode
- impl->bread = 1;
-
- // save func and priv
- impl->priv = priv;
- impl->func.read = func;
-
- // done
- tb_bool_t ok = tb_false;
- switch (impl->type)
- {
- case TB_SOCKET_TYPE_TCP:
- {
-#ifdef TB_SSL_ENABLE
- // ssl?
- if (tb_url_ssl(tb_async_stream_url((tb_async_stream_ref_t)impl)))
- {
- // check
- tb_assert_and_check_break(impl->hssl);
-
- // post ssl read
- ok = tb_aicp_ssl_read_after(impl->hssl, delay, data, size, tb_async_stream_sock_impl_read_ssl_func, stream);
- }
- // post tcp read
- else
-#endif
- {
- ok = tb_aico_recv_after(impl->aico, delay, data, size, tb_async_stream_sock_impl_read_func, stream);
- }
- }
- break;
- case TB_SOCKET_TYPE_UDP:
- {
- // post udp read
- ok = tb_aico_urecv_after(impl->aico, delay, data, size, tb_async_stream_sock_impl_read_udp_func, stream);
- }
- break;
- default:
- tb_trace_e("unknown socket type: %lu", impl->type);
- break;
- }
-
- // ok?
- return ok;
-}
-static tb_bool_t tb_async_stream_sock_impl_writ_func(tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(aice && aice->aico && aice->code == TB_AICE_CODE_SEND, tb_false);
-
- // the stream
- tb_async_stream_sock_impl_t* impl = (tb_async_stream_sock_impl_t*)aice->priv;
- tb_assert_and_check_return_val(impl && impl->func.writ, tb_false);
-
- // trace
- tb_trace_d("send[%p]: real: %lu, size: %lu, state: %s", aice->aico, aice->u.send.real, aice->u.send.size, tb_state_cstr(aice->state));
-
- // done state
- tb_size_t state = TB_STATE_SOCK_UNKNOWN_ERROR;
- switch (aice->state)
- {
- // ok
- case TB_STATE_OK:
- tb_assert_and_check_break(aice->u.send.data && aice->u.send.real <= aice->u.send.size);
- tb_atomic64_fetch_and_add(&impl->offset, aice->u.send.real);
- state = TB_STATE_OK;
- break;
- // closed
- case TB_STATE_CLOSED:
- state = TB_STATE_CLOSED;
- break;
- // killed
- case TB_STATE_KILLED:
- state = TB_STATE_KILLED;
- break;
- // timeout?
- case TB_STATE_TIMEOUT:
- state = TB_STATE_SOCK_SEND_TIMEOUT;
- break;
- default:
- tb_trace_e("writ: unknown state: %s", tb_state_cstr(aice->state));
- break;
- }
-
- // done func
- if (impl->func.writ((tb_async_stream_ref_t)impl, state, aice->u.send.data, aice->u.send.real, aice->u.send.size, impl->priv))
- {
- // continue?
- if (aice->state == TB_STATE_OK && aice->u.send.real < aice->u.send.size)
- {
- // continue to post writ
- if (!tb_aico_send(aice->aico, aice->u.send.data + aice->u.send.real, aice->u.send.size - aice->u.send.real, tb_async_stream_sock_impl_writ_func, (tb_async_stream_ref_t)impl))
- impl->func.writ((tb_async_stream_ref_t)impl, TB_STATE_SOCK_SEND_FAILED, aice->u.usend.data, 0, aice->u.usend.size, impl->priv);
- }
- }
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_async_stream_sock_impl_writ_udp_func(tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(aice && aice->aico && aice->code == TB_AICE_CODE_USEND, tb_false);
-
- // the stream
- tb_async_stream_sock_impl_t* impl = (tb_async_stream_sock_impl_t*)aice->priv;
- tb_assert_and_check_return_val(impl && impl->func.writ, tb_false);
-
- // trace
- tb_trace_d("usend[%p]: real: %lu, size: %lu, state: %s", aice->aico, aice->u.usend.real, aice->u.usend.size, tb_state_cstr(aice->state));
-
- // done state
- tb_size_t state = TB_STATE_SOCK_UNKNOWN_ERROR;
- switch (aice->state)
- {
- case TB_STATE_OK:
- {
- // check
- tb_assert_and_check_break(aice->u.usend.data && aice->u.usend.real <= aice->u.usend.size);
-
- // update offset
- tb_atomic64_fetch_and_add(&impl->offset, aice->u.usend.real);
-
- // ok
- state = TB_STATE_OK;
- }
- break;
- // closed
- case TB_STATE_CLOSED:
- state = TB_STATE_CLOSED;
- break;
- // killed
- case TB_STATE_KILLED:
- state = TB_STATE_KILLED;
- break;
- // timeout?
- case TB_STATE_TIMEOUT:
- state = TB_STATE_SOCK_SEND_TIMEOUT;
- break;
- default:
- {
- // trace
- tb_trace_e("writ: unknown state: %s", tb_state_cstr(aice->state));
- }
- break;
- }
-
- // done func
- if (impl->func.writ((tb_async_stream_ref_t)impl, state, aice->u.usend.data, aice->u.usend.real, aice->u.usend.size, impl->priv))
- {
- // continue?
- if (aice->state == TB_STATE_OK && aice->u.usend.real < aice->u.usend.size)
- {
- // continue to post writ
- if (!tb_aico_usend(aice->aico, &aice->u.usend.addr, aice->u.usend.data + aice->u.usend.real, aice->u.usend.size - aice->u.usend.real, tb_async_stream_sock_impl_writ_udp_func, (tb_async_stream_ref_t)impl))
- impl->func.writ((tb_async_stream_ref_t)impl, TB_STATE_SOCK_SEND_FAILED, aice->u.usend.data, 0, aice->u.usend.size, impl->priv);
- }
- }
-
- // ok
- return tb_true;
-}
-#ifdef TB_SSL_ENABLE
-static tb_bool_t tb_async_stream_sock_impl_writ_ssl_func(tb_aicp_ssl_ref_t ssl, tb_size_t state, tb_byte_t const* data, tb_size_t real, tb_size_t size, tb_cpointer_t priv)
-{
- // check
- tb_assert_and_check_return_val(ssl, tb_false);
-
- // the stream
- tb_async_stream_sock_impl_t* impl = (tb_async_stream_sock_impl_t*)priv;
- tb_assert_and_check_return_val(impl && impl->func.writ, tb_false);
-
- // trace
- tb_trace_d("ssend[%p]: real: %lu, size: %lu, state: %s", impl->aico, real, size, tb_state_cstr(state));
-
- // save offset
- if (state == TB_STATE_OK) tb_atomic64_fetch_and_add(&impl->offset, real);
-
- // done func
- if (impl->func.writ((tb_async_stream_ref_t)impl, state, data, real, size, impl->priv))
- {
- // ok? continue it
- if (state == TB_STATE_OK && real < size)
- {
- // continue to post writ
- if (!tb_aicp_ssl_writ(impl->hssl, data, size, tb_async_stream_sock_impl_writ_ssl_func, (tb_async_stream_ref_t)impl))
- impl->func.writ((tb_async_stream_ref_t)impl, TB_STATE_SOCK_SSL_WRIT_FAILED, data, 0, size, impl->priv);
- }
- }
-
- // ok
- return tb_true;
-}
-#endif
-static tb_bool_t tb_async_stream_sock_impl_writ(tb_async_stream_ref_t stream, tb_size_t delay, tb_byte_t const* data, tb_size_t size, tb_async_stream_writ_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_sock_impl_t* impl = tb_async_stream_sock_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->aico && data && size && func, tb_false);
-
- // clear the offset if be read mode now
- if (impl->bread) tb_atomic64_set0(&impl->offset);
-
- // set writ mode
- impl->bread = 0;
-
- // save func and priv
- impl->priv = priv;
- impl->func.writ = func;
-
- // done
- tb_bool_t ok = tb_false;
- switch (impl->type)
- {
- case TB_SOCKET_TYPE_TCP:
- {
-#ifdef TB_SSL_ENABLE
- // ssl?
- if (tb_url_ssl(tb_async_stream_url((tb_async_stream_ref_t)impl)))
- {
- // check
- tb_assert_and_check_break(impl->hssl);
-
- // post ssl writ
- ok = tb_aicp_ssl_writ_after(impl->hssl, delay, data, size, tb_async_stream_sock_impl_writ_ssl_func, stream);
- }
- // post tcp writ
- else
-#endif
- {
- ok = tb_aico_send_after(impl->aico, delay, data, size, tb_async_stream_sock_impl_writ_func, stream);
- }
- }
- break;
- case TB_SOCKET_TYPE_UDP:
- {
- // post udp writ
- ok = tb_aico_usend_after(impl->aico, delay, tb_url_addr(tb_async_stream_url((tb_async_stream_ref_t)impl)), data, size, tb_async_stream_sock_impl_writ_udp_func, stream);
- }
- break;
- default:
- tb_trace_e("unknown socket type: %lu", impl->type);
- break;
- }
-
- // ok?
- return ok;
-}
-static tb_bool_t tb_async_stream_sock_impl_seek(tb_async_stream_ref_t stream, tb_hize_t offset, tb_async_stream_seek_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_sock_impl_t* impl = tb_async_stream_sock_impl_cast(stream);
- tb_assert_and_check_return_val(impl && func, tb_false);
-
- // done func
- func(stream, TB_STATE_NOT_SUPPORTED, 0, priv);
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_async_stream_sock_impl_sync(tb_async_stream_ref_t stream, tb_bool_t bclosing, tb_async_stream_sync_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_sock_impl_t* impl = tb_async_stream_sock_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->aico && func, tb_false);
-
- // done func
- func(stream, TB_STATE_OK, bclosing, priv);
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_async_stream_sock_impl_task_func(tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(aice && aice->aico && aice->code == TB_AICE_CODE_RUNTASK, tb_false);
-
- // the stream
- tb_async_stream_sock_impl_t* impl = (tb_async_stream_sock_impl_t*)aice->priv;
- tb_assert_and_check_return_val(impl && impl->func.task, tb_false);
-
- // done func
- tb_bool_t ok = impl->func.task((tb_async_stream_ref_t)impl, aice->state, impl->priv);
-
- // ok and continue?
- if (ok && aice->state == TB_STATE_OK)
- {
- // post task
- tb_aico_task_run(aice->aico, aice->u.runtask.delay, tb_async_stream_sock_impl_task_func, impl);
- }
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_async_stream_sock_impl_task(tb_async_stream_ref_t stream, tb_size_t delay, tb_async_stream_task_func_t func, tb_cpointer_t priv)
-{
- // check
- tb_async_stream_sock_impl_t* impl = tb_async_stream_sock_impl_cast(stream);
- tb_assert_and_check_return_val(impl && impl->aico && func, tb_false);
-
- // init func
- impl->func.task = func;
- impl->priv = priv;
-
- // post task
- return tb_aico_task_run(impl->aico, delay, tb_async_stream_sock_impl_task_func, stream);
-}
-static tb_void_t tb_async_stream_sock_impl_kill(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_sock_impl_t* impl = tb_async_stream_sock_impl_cast(stream);
- tb_assert_and_check_return(impl);
-
- // trace
-#ifdef TB_SSL_ENABLE
- tb_trace_d("kill[%p]: %s: balived: %d, hssl: %p, hdns: %p: ..", impl->aico, tb_url_cstr(tb_async_stream_url(stream)), impl->balived, impl->hssl, impl->hdns);
-#else
- tb_trace_d("kill[%p]: %s: balived: %d, hdns: %p: ..", impl->aico, tb_url_cstr(tb_async_stream_url(stream)), impl->balived, impl->hdns);
-#endif
-
- // exit ssl
-#ifdef TB_SSL_ENABLE
- if (impl->hssl) tb_aicp_ssl_kill(impl->hssl);
-#endif
- // kill addr
- if (impl->hdns) tb_aicp_dns_kill(impl->hdns);
-
- // kill aico
- if (impl->aico) tb_aico_kill(impl->aico);
-}
-static tb_bool_t tb_async_stream_sock_impl_exit_aico_func(tb_aice_ref_t aice)
-{
- // check
- tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_CLOS, tb_false);
-
- // the wait
- tb_atomic_t* wait = (tb_atomic_t*)aice->priv;
- tb_assert_and_check_return_val(wait, tb_false);
-
- // wait ok
- tb_atomic_set(wait, 1);
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_async_stream_sock_impl_exit(tb_async_stream_ref_t stream)
-{
- // check
- tb_async_stream_sock_impl_t* impl = tb_async_stream_sock_impl_cast(stream);
- tb_assert_and_check_return_val(impl, tb_false);
-
- // exit ssl
-#ifdef TB_SSL_ENABLE
- if (impl->hssl) tb_aicp_ssl_exit(impl->hssl);
- impl->hssl = tb_null;
-#endif
-
- // alived? wait closing it
- if (impl->balived && impl->aico)
- {
- // post to clos
- tb_atomic_t wait = 0;
- if (!tb_aico_clos(impl->aico, tb_async_stream_sock_impl_exit_aico_func, (tb_cpointer_t)&wait)) return tb_false;
-
- // wait closing?
- tb_size_t tryn = 15;
- while (!tb_atomic_get(&wait) && tryn--)
- {
- // trace
- tb_trace_d("exit[%p]: %s: wait: ..", impl->aico, tb_url_cstr(tb_async_stream_url(stream)));
-
- // wait some time
- tb_msleep(200);
- }
-
- // check
- tb_assert(tb_atomic_get(&wait));
- tb_check_return_val(tb_atomic_get(&wait), tb_false);
- }
-
- // exit aico
- if (impl->aico) tb_aico_exit(impl->aico);
- impl->aico = tb_null;
-
- // exit hdns
- if (impl->hdns) tb_aicp_dns_exit(impl->hdns);
- impl->hdns = tb_null;
-
- // ok
- return tb_true;
-}
-static tb_bool_t tb_async_stream_sock_impl_ctrl(tb_async_stream_ref_t stream, tb_size_t ctrl, tb_va_list_t args)
-{
- // check
- tb_async_stream_sock_impl_t* impl = tb_async_stream_sock_impl_cast(stream);
- tb_assert_and_check_return_val(impl, tb_false);
-
- // ctrl
- switch (ctrl)
- {
- case TB_STREAM_CTRL_GET_OFFSET:
- {
- // check
- tb_assert_and_check_return_val(tb_async_stream_is_opened(stream), tb_false);
-
- // get offset
- tb_hize_t* poffset = (tb_hize_t*)tb_va_arg(args, tb_hize_t*);
- tb_assert_and_check_return_val(poffset, tb_false);
- *poffset = (tb_hize_t)tb_atomic64_get(&impl->offset);
- return tb_true;
- }
- case TB_STREAM_CTRL_SOCK_SET_TYPE:
- {
- // check
- tb_assert_and_check_return_val(tb_async_stream_is_closed(stream), tb_false);
- tb_assert_and_check_return_val(!impl->balived, tb_false);
-
- // the type
- tb_size_t type = (tb_size_t)tb_va_arg(args, tb_size_t);
- tb_assert_and_check_return_val(type == TB_SOCKET_TYPE_TCP || type == TB_SOCKET_TYPE_UDP, tb_false);
-
- // set type
- impl->type = type;
-
- // ok
- return tb_true;
- }
- case TB_STREAM_CTRL_SOCK_GET_TYPE:
- {
- tb_size_t* ptype = (tb_size_t*)tb_va_arg(args, tb_size_t*);
- tb_assert_and_check_return_val(ptype, tb_false);
- *ptype = impl->type;
- return tb_true;
- }
- case TB_STREAM_CTRL_SOCK_KEEP_ALIVE:
- {
- // keep alive?
- tb_bool_t balived = (tb_bool_t)tb_va_arg(args, tb_bool_t);
- impl->balived = balived? 1 : 0;
- return tb_true;
- }
- default:
- break;
- }
- return tb_false;
-}
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * interfaces
- */
-tb_async_stream_ref_t tb_async_stream_init_sock(tb_aicp_ref_t aicp)
-{
- // init stream
- tb_async_stream_ref_t stream = tb_async_stream_init( aicp
- , TB_STREAM_TYPE_SOCK
- , sizeof(tb_async_stream_sock_impl_t)
- , TB_STREAM_SOCK_CACHE_MAXN
- , TB_STREAM_SOCK_CACHE_MAXN
- , tb_null
- , tb_async_stream_sock_impl_clos_try
- , tb_async_stream_sock_impl_open
- , tb_async_stream_sock_impl_clos
- , tb_async_stream_sock_impl_exit
- , tb_async_stream_sock_impl_kill
- , tb_async_stream_sock_impl_ctrl
- , tb_async_stream_sock_impl_read
- , tb_async_stream_sock_impl_writ
- , tb_async_stream_sock_impl_seek
- , tb_async_stream_sock_impl_sync
- , tb_async_stream_sock_impl_task);
- tb_assert_and_check_return_val(stream, tb_null);
-
- // init the stream impl
- tb_async_stream_sock_impl_t* impl = tb_async_stream_sock_impl_cast(stream);
- if (impl)
- {
- // init type
- impl->type = TB_SOCKET_TYPE_TCP;
- }
-
- // ok?
- return stream;
-}
-tb_async_stream_ref_t tb_async_stream_init_from_sock(tb_aicp_ref_t aicp, tb_char_t const* host, tb_uint16_t port, tb_size_t type, tb_bool_t bssl)
-{
- // check
- tb_assert_and_check_return_val(host && port, tb_null);
-
- // ssl is not supported now.
- tb_assert_and_check_return_val(!bssl, tb_null);
-
- // done
- tb_bool_t ok = tb_false;
- tb_async_stream_ref_t stream = tb_null;
- do
- {
- // init stream
- stream = tb_async_stream_init_sock(aicp);
- tb_assert_and_check_return_val(stream, tb_null);
-
- // ctrl stream
- if (!tb_async_stream_ctrl(stream, TB_STREAM_CTRL_SET_HOST, host)) break;
- if (!tb_async_stream_ctrl(stream, TB_STREAM_CTRL_SET_PORT, port)) break;
- if (!tb_async_stream_ctrl(stream, TB_STREAM_CTRL_SET_SSL, bssl)) break;
- if (!tb_async_stream_ctrl(stream, TB_STREAM_CTRL_SOCK_SET_TYPE, type)) break;
-
- // check
- tb_assert_static(!(tb_offsetof(tb_async_stream_sock_impl_t, offset) & (sizeof(tb_atomic64_t) - 1)));
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // failed?
- if (!ok)
- {
- // exit it
- if (stream) tb_async_stream_exit(stream);
- stream = tb_null;
- }
-
- // ok?
- return stream;
-}
diff --git a/core/src/tbox/src/tbox/stream/deprecated/transfer_pool.c b/core/src/tbox/src/tbox/stream/deprecated/transfer_pool.c
deleted file mode 100644
index 26da7fce5..000000000
--- a/core/src/tbox/src/tbox/stream/deprecated/transfer_pool.c
+++ /dev/null
@@ -1,575 +0,0 @@
-/*!The Treasure Box Library
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
- *
- * @author ruki
- * @file transfer_pool.c
- * @ingroup stream
- *
- */
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * trace
- */
-#define TB_TRACE_MODULE_NAME "transfer_pool"
-#define TB_TRACE_MODULE_DEBUG (1)
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
- */
-#include "transfer_pool.h"
-#include "../stream.h"
-#include "../../network/network.h"
-#include "../../platform/platform.h"
-#include "../../container/container.h"
-#include "../../algorithm/algorithm.h"
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * types
- */
-
-// the task pool type
-typedef struct __tb_transfer_pool_impl_t
-{
- // the aicp
- tb_aicp_ref_t aicp;
-
- // the task maxn
- tb_size_t maxn;
-
- // the lock
- tb_spinlock_t lock;
-
- // the task pool
- tb_fixed_pool_ref_t pool;
-
- // the idle task list
- tb_list_entry_head_t idle;
-
- // the work task list
- tb_list_entry_head_t work;
-
- /* the state
- *
- * TB_STATE_OK
- * TB_STATE_KILLING
- */
- tb_atomic_t state;
-
-}tb_transfer_pool_impl_t;
-
-// the task task type
-typedef struct __tb_transfer_task_t
-{
- // the transfer
- tb_async_transfer_ref_t transfer;
-
- // the pool
- tb_transfer_pool_impl_t* pool;
-
- // the func
- tb_async_transfer_done_func_t func;
-
- // the priv
- tb_cpointer_t priv;
-
- // the entry
- tb_list_entry_t entry;
-
-}tb_transfer_task_t;
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * implementation
- */
-static tb_void_t tb_transfer_task_exit(tb_transfer_pool_impl_t* impl, tb_transfer_task_t* task)
-{
- // check
- tb_assert_and_check_return(impl && impl->pool && task);
-
- // trace
- tb_trace_d("task[%p]: exit", task);
-
- // append task to the idle list
- tb_list_entry_insert_tail(&impl->idle, &task->entry);
-}
-static tb_transfer_task_t* tb_transfer_task_init(tb_transfer_pool_impl_t* impl, tb_async_transfer_done_func_t done, tb_async_transfer_ctrl_func_t ctrl, tb_cpointer_t priv)
-{
- // check
- tb_assert_and_check_return_val(impl, tb_null);
-
- // done
- tb_bool_t ok = tb_false;
- tb_transfer_task_t* task = tb_null;
- do
- {
- // init task pool
- if (!impl->pool) impl->pool = tb_fixed_pool_init(tb_null, (impl->maxn >> 4) + 16, sizeof(tb_transfer_task_t), tb_null, tb_null, tb_null);
- tb_assert_and_check_break(impl->pool);
-
- // init task from the idle list first
- if (tb_list_entry_size(&impl->idle))
- {
- // get the head entry
- tb_list_entry_ref_t entry = tb_list_entry_head(&impl->idle);
- tb_assert_and_check_break(entry);
-
- // the task
- task = (tb_transfer_task_t*)tb_list_entry(&impl->idle, entry);
- tb_assert_and_check_break(task);
-
- // remove the last task
- tb_list_entry_remove(&impl->idle, entry);
-
- // check
- tb_assert_and_check_break(task->transfer);
- }
- // init task from the task pool
- else
- {
- // make task
- task = (tb_transfer_task_t*)tb_fixed_pool_malloc0(impl->pool);
- tb_assert_and_check_break(task);
-
- // init transfer
- task->transfer = tb_async_transfer_init(impl->aicp, tb_true);
- tb_assert_and_check_break(task->transfer);
- }
-
- // init ctrl
- if (ctrl && !tb_async_transfer_ctrl(task->transfer, ctrl, priv)) break;
-
- // init task
- task->func = done;
- task->priv = priv;
- task->pool = impl;
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // failed?
- if (!ok)
- {
- // exit it
- if (task) tb_transfer_task_exit(impl, task);
- task = tb_null;
- }
-
- // ok?
- return task;
-}
-static tb_bool_t tb_transfer_task_done(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 task
- tb_transfer_task_t* task = (tb_transfer_task_t*)priv;
- tb_assert_and_check_return_val(task && task->transfer, tb_false);
-
- // the pool
- tb_transfer_pool_impl_t* impl = (tb_transfer_pool_impl_t*)task->pool;
- tb_assert_and_check_return_val(impl, tb_false);
-
- // trace
- tb_trace_d("task[%p]: done: %llu bytes, rate: %lu bytes/s, state: %s", task, save, rate, tb_state_cstr(state));
-
- // done func
- tb_bool_t ok = task->func? task->func(state, offset, size, save, rate, task->priv) : tb_true;
-
- // failed, killed or closed?
- if (state != TB_STATE_OK && state != TB_STATE_PAUSED)
- {
- // enter
- tb_spinlock_enter(&impl->lock);
-
- // remove task from the work list
- tb_list_entry_remove(&impl->work, &task->entry);
-
- // exit task
- tb_transfer_task_exit(impl, task);
- task = tb_null;
-
- // leave
- tb_spinlock_leave(&impl->lock);
- }
-
- // ok?
- return ok;
-}
-static tb_bool_t tb_transfer_pool_work_kill(tb_iterator_ref_t iterator, tb_pointer_t item, tb_cpointer_t priv)
-{
- // the task
- tb_transfer_task_t* task = (tb_transfer_task_t*)item;
- tb_check_return_val(task, tb_false);
-
- // check
- tb_assert_and_check_return_val(task->transfer, tb_false);
-
- // kill it
- tb_async_transfer_kill(task->transfer);
-
- // ok
- return tb_true;
-}
-#ifdef __tb_debug__
-static tb_bool_t tb_transfer_pool_work_wait(tb_iterator_ref_t iterator, tb_pointer_t item, tb_cpointer_t priv)
-{
- // check
- tb_transfer_task_t* task = (tb_transfer_task_t*)item;
- tb_assert_and_check_return_val(task, tb_false);
-
- // trace
- tb_trace_d("wait: task: %p: ..", task);
-
- // ok
- return tb_true;
-}
-#endif
-static tb_bool_t tb_transfer_pool_walk_exit(tb_pointer_t item, tb_cpointer_t priv)
-{
- // check
- tb_transfer_task_t* task = (tb_transfer_task_t*)item;
- tb_assert_and_check_return_val(task, tb_false);
-
- // exit transfer
- if (task->transfer) tb_async_transfer_exit(task->transfer);
- task->transfer = tb_null;
-
- // ok
- return tb_true;
-}
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * instance implementation
- */
-static tb_handle_t tb_transfer_pool_instance_init(tb_cpointer_t* ppriv)
-{
- // init it
- return (tb_handle_t)tb_transfer_pool_init(tb_null);
-}
-static tb_void_t tb_transfer_pool_instance_exit(tb_handle_t pool, tb_cpointer_t priv)
-{
- tb_transfer_pool_exit((tb_transfer_pool_ref_t)pool);
-}
-static tb_void_t tb_transfer_pool_instance_kill(tb_handle_t pool, tb_cpointer_t priv)
-{
- tb_transfer_pool_kill((tb_transfer_pool_ref_t)pool);
-}
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * interfaces
- */
-tb_transfer_pool_ref_t tb_transfer_pool()
-{
- return (tb_transfer_pool_ref_t)tb_singleton_instance(TB_SINGLETON_TYPE_TRANSFER_POOL, tb_transfer_pool_instance_init, tb_transfer_pool_instance_exit, tb_transfer_pool_instance_kill, tb_null);
-}
-tb_transfer_pool_ref_t tb_transfer_pool_init(tb_aicp_ref_t aicp)
-{
- // done
- tb_bool_t ok = tb_false;
- tb_transfer_pool_impl_t* impl = tb_null;
- do
- {
- // using the default aicp if be null
- if (!aicp) aicp = tb_aicp();
- tb_assert_and_check_break(aicp);
-
- // make impl
- impl = tb_malloc0_type(tb_transfer_pool_impl_t);
- tb_assert_and_check_break(impl);
-
- // init lock
- if (!tb_spinlock_init(&impl->lock)) break;
-
- // init pool
- impl->aicp = aicp;
- impl->maxn = tb_aicp_maxn(aicp);
- impl->state = TB_STATE_OK;
- tb_assert_and_check_break(impl->maxn);
-
- // init idle task list
- tb_list_entry_init(&impl->idle, tb_transfer_task_t, entry, tb_null);
-
- // init work task list
- tb_list_entry_init(&impl->work, tb_transfer_task_t, entry, tb_null);
-
- // register lock profiler
-#ifdef TB_LOCK_PROFILER_ENABLE
- tb_lock_profiler_register(tb_lock_profiler(), (tb_pointer_t)&impl->lock, TB_TRACE_MODULE_NAME);
-#endif
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // failed?
- if (!ok)
- {
- // exit it
- if (impl) tb_transfer_pool_exit((tb_transfer_pool_ref_t)impl);
- impl = tb_null;
- }
-
- // ok?
- return (tb_transfer_pool_ref_t)impl;
-}
-tb_void_t tb_transfer_pool_kill(tb_transfer_pool_ref_t pool)
-{
- // check
- tb_transfer_pool_impl_t* impl = (tb_transfer_pool_impl_t*)pool;
- tb_assert_and_check_return(impl);
-
- // trace
- tb_trace_d("kill: ..");
-
- // kill it
- if (TB_STATE_OK == tb_atomic_fetch_and_set(&impl->state, TB_STATE_KILLING))
- tb_transfer_pool_kill_all(pool);
-}
-tb_void_t tb_transfer_pool_kill_all(tb_transfer_pool_ref_t pool)
-{
- // check
- tb_transfer_pool_impl_t* impl = (tb_transfer_pool_impl_t*)pool;
- tb_assert_and_check_return(impl);
-
- // check
- tb_check_return(TB_STATE_OK == tb_atomic_get(&impl->state));
-
- // enter
- tb_spinlock_enter(&impl->lock);
-
- // trace
- tb_trace_d("kill_all: %lu, ..", tb_list_entry_size(&impl->work));
-
- // kill it
- tb_walk_all(tb_list_entry_itor(&impl->work), tb_transfer_pool_work_kill, tb_null);
-
- // leave
- tb_spinlock_leave(&impl->lock);
-}
-tb_long_t tb_transfer_pool_wait_all(tb_transfer_pool_ref_t pool, tb_long_t timeout)
-{
- // check
- tb_transfer_pool_impl_t* impl = (tb_transfer_pool_impl_t*)pool;
- tb_assert_and_check_return_val(impl, -1);
-
- // wait it
- tb_size_t size = 0;
- tb_hong_t time = tb_cache_time_spak();
- while ((timeout < 0 || tb_cache_time_spak() < time + timeout))
- {
- // enter
- tb_spinlock_enter(&impl->lock);
-
- // the size
- tb_size_t size = tb_list_entry_size(&impl->work);
-
- // trace
- tb_trace_d("wait: %lu: ..", size);
-
- // trace work
-#ifdef __tb_debug__
- if (size) tb_walk_all(tb_list_entry_itor(&impl->work), tb_transfer_pool_work_wait, tb_null);
-#endif
-
- // leave
- tb_spinlock_leave(&impl->lock);
-
- // ok?
- tb_check_break(size);
-
- // wait some time
- tb_msleep(200);
- }
-
- // ok?
- return !size? 1 : 0;
-}
-tb_bool_t tb_transfer_pool_exit(tb_transfer_pool_ref_t pool)
-{
- // check
- tb_transfer_pool_impl_t* impl = (tb_transfer_pool_impl_t*)pool;
- tb_assert_and_check_return_val(impl, tb_false);
-
- // trace
- tb_trace_d("exit: ..");
-
- // kill it first
- tb_transfer_pool_kill(pool);
-
- // wait all
- if (tb_transfer_pool_wait_all(pool, 5000) <= 0)
- {
- // trace
- tb_trace_e("exit: wait failed!");
- return tb_false;
- }
-
- // enter
- tb_spinlock_enter(&impl->lock);
-
- // check
- tb_assert(!tb_list_entry_size(&impl->work));
-
- // exit the work list
- tb_list_entry_exit(&impl->work);
-
- // exit the idle list
- tb_list_entry_exit(&impl->idle);
-
- // exit pool
- if (impl->pool)
- {
- // exit all task
- tb_fixed_pool_walk(impl->pool, tb_transfer_pool_walk_exit, tb_null);
-
- // exit it
- tb_fixed_pool_exit(impl->pool);
- impl->pool = tb_null;
- }
-
- // leave
- tb_spinlock_leave(&impl->lock);
-
- // exit lock
- tb_spinlock_exit(&impl->lock);
-
- // exit it
- tb_free(pool);
-
- // trace
- tb_trace_d("exit: ok");
-
- // ok
- return tb_true;
-}
-tb_size_t tb_transfer_pool_maxn(tb_transfer_pool_ref_t pool)
-{
- // check
- tb_transfer_pool_impl_t* impl = (tb_transfer_pool_impl_t*)pool;
- tb_assert_and_check_return_val(impl, 0);
-
- // the maxn
- return impl->maxn;
-}
-tb_size_t tb_transfer_pool_size(tb_transfer_pool_ref_t pool)
-{
- // check
- tb_transfer_pool_impl_t* impl = (tb_transfer_pool_impl_t*)pool;
- tb_assert_and_check_return_val(impl, 0);
-
- // enter
- tb_spinlock_enter(&impl->lock);
-
- // the size
- tb_size_t size = tb_list_entry_size(&impl->work);
-
- // leave
- tb_spinlock_leave(&impl->lock);
-
- // ok?
- return size;
-}
-tb_bool_t tb_transfer_pool_done(tb_transfer_pool_ref_t pool, tb_char_t const* iurl, tb_char_t const* ourl, tb_hize_t offset, tb_size_t rate, tb_async_transfer_done_func_t done, tb_async_transfer_ctrl_func_t ctrl, tb_cpointer_t priv)
-{
- // check
- tb_transfer_pool_impl_t* impl = (tb_transfer_pool_impl_t*)pool;
- tb_assert_and_check_return_val(impl && impl->aicp && iurl && ourl, tb_false);
-
- // enter
- tb_spinlock_enter(&impl->lock);
-
- // done
- tb_bool_t ok = tb_false;
- tb_transfer_task_t* task = tb_null;
- do
- {
- // check
- tb_check_break(TB_STATE_OK == tb_atomic_get(&impl->state));
-
- // too many tasks?
- if (tb_list_entry_size(&impl->work) >= impl->maxn)
- {
- // trace
- tb_trace_e("too many tasks, done task: %s => %s failed!", iurl, ourl);
- break;
- }
-
- // init task
- task = tb_transfer_task_init(impl, done, ctrl, priv);
- tb_assert_and_check_break(task && task->transfer);
-
- // init transfer stream
- if (!tb_async_transfer_init_istream_from_url(task->transfer, iurl)) break;
- if (!tb_async_transfer_init_ostream_from_url(task->transfer, ourl)) break;
-
- // init transfer rate
- tb_async_transfer_limitrate(task->transfer, rate);
-
- // check
- tb_assert_and_check_break(impl->pool);
-
- // append to the work list
- tb_list_entry_insert_tail(&impl->work, &task->entry);
-
- // ok
- ok = tb_true;
-
- } while (0);
-
- // trace
- tb_trace_d("done: task: %p, %s => %s, work: %lu, idle: %lu, state: %s", task, iurl, ourl, tb_list_entry_size(&impl->work), tb_list_entry_size(&impl->idle), ok? "ok" : "no");
-
- // failed?
- if (!ok)
- {
- // exit it
- if (task) tb_transfer_task_exit(impl, task);
- task = tb_null;
- }
-
- // leave
- tb_spinlock_leave(&impl->lock);
-
- // ok? done it
- if (ok && task && task->transfer)
- {
- // done
- if (!tb_async_transfer_open_done(task->transfer, 0, tb_transfer_task_done, task))
- {
- // enter
- tb_spinlock_enter(&impl->lock);
-
- // remove task from the work list
- tb_list_entry_remove(&impl->work, &task->entry);
-
- // exit task
- tb_transfer_task_exit(impl, task);
-
- // leave
- tb_spinlock_leave(&impl->lock);
-
- // failed
- ok = tb_false;
- }
- }
-
- // ok?
- return ok;
-}
diff --git a/core/src/tbox/src/tbox/stream/deprecated/transfer_pool.h b/core/src/tbox/src/tbox/stream/deprecated/transfer_pool.h
deleted file mode 100644
index fbdda8c5a..000000000
--- a/core/src/tbox/src/tbox/stream/deprecated/transfer_pool.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*!The Treasure Box Library
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
- *
- * @author ruki
- * @file transfer_pool.h
- * @ingroup stream
- *
- */
-#ifndef TB_STREAM_TRANSFER_POOL_H
-#define TB_STREAM_TRANSFER_POOL_H
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * includes
- */
-#include "prefix.h"
-#include "../transfer.h"
-#include "async_stream.h"
-#include "async_transfer.h"
-#include "../../asio/deprecated/asio.h"
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * extern
- */
-__tb_extern_c_enter__
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * types
- */
-
-/// the transfer pool ref type
-typedef __tb_typeref__(transfer_pool);
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * interfaces
- */
-
-/*! the transfer pool instance
- *
- * @return the transfer pool instance
- */
-tb_transfer_pool_ref_t tb_transfer_pool(tb_noarg_t);
-
-/*! init transfer pool
- *
- * @param aicp the aicp, using the default aicp if be null
- *
- * @return the transfer pool
- */
-tb_transfer_pool_ref_t tb_transfer_pool_init(tb_aicp_ref_t aicp);
-
-/*! exit transfer pool
- *
- * @param pool the transfer pool
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_transfer_pool_exit(tb_transfer_pool_ref_t pool);
-
-/*! kill transfer pool
- *
- * @param pool the transfer pool
- */
-tb_void_t tb_transfer_pool_kill(tb_transfer_pool_ref_t pool);
-
-/*! kill all working tasks
- *
- * @param pool the transfer pool handle
- */
-tb_void_t tb_transfer_pool_kill_all(tb_transfer_pool_ref_t pool);
-
-/*! wait all working tasks
- *
- * @param pool the transfer pool handle
- * @param timeout the timeout
- *
- * @return ok: 1, timeout: 0, error: -1
- */
-tb_long_t tb_transfer_pool_wait_all(tb_transfer_pool_ref_t pool, tb_long_t timeout);
-
-/*! the transfer pool size
- *
- * @param pool the transfer pool
- */
-tb_size_t tb_transfer_pool_size(tb_transfer_pool_ref_t pool);
-
-/*! the transfer pool maxn
- *
- * @param pool the transfer pool
- */
-tb_size_t tb_transfer_pool_maxn(tb_transfer_pool_ref_t pool);
-
-/*! done transfer from iurl to ourl
- *
- * @param pool the transfer pool
- * @param iurl the input url
- * @param ourl the output url
- * @param offset the offset
- * @param rate the limited rate, not limit if be zero
- * @param done the done func
- * @param ctrl the ctrl func
- * @param priv the func private data
- *
- * @return tb_true or tb_false
- */
-tb_bool_t tb_transfer_pool_done(tb_transfer_pool_ref_t pool, tb_char_t const* iurl, tb_char_t const* ourl, tb_hize_t offset, tb_size_t rate, tb_async_transfer_done_func_t done, tb_async_transfer_ctrl_func_t ctrl, tb_cpointer_t priv);
-
-/* //////////////////////////////////////////////////////////////////////////////////////
- * extern
- */
-__tb_extern_c_leave__
-
-#endif
diff --git a/core/src/tbox/src/tbox/stream/filter.c b/core/src/tbox/src/tbox/stream/filter.c
index 7657e7a40..e3f29d753 100644
--- a/core/src/tbox/src/tbox/stream/filter.c
+++ b/core/src/tbox/src/tbox/stream/filter.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file filter.c
diff --git a/core/src/tbox/src/tbox/stream/filter.h b/core/src/tbox/src/tbox/stream/filter.h
index d2c3a77ef..39b49cc14 100644
--- a/core/src/tbox/src/tbox/stream/filter.h
+++ b/core/src/tbox/src/tbox/stream/filter.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file filter.h
diff --git a/core/src/tbox/src/tbox/stream/impl/filter.h b/core/src/tbox/src/tbox/stream/impl/filter.h
index 10af4fb2e..454e0bc62 100644
--- a/core/src/tbox/src/tbox/stream/impl/filter.h
+++ b/core/src/tbox/src/tbox/stream/impl/filter.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file filter.h
diff --git a/core/src/tbox/src/tbox/stream/impl/filter/cache.c b/core/src/tbox/src/tbox/stream/impl/filter/cache.c
index ca85a2a56..10b4be923 100644
--- a/core/src/tbox/src/tbox/stream/impl/filter/cache.c
+++ b/core/src/tbox/src/tbox/stream/impl/filter/cache.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file cache.c
diff --git a/core/src/tbox/src/tbox/stream/impl/filter/charset.c b/core/src/tbox/src/tbox/stream/impl/filter/charset.c
index 6b5fab253..dcd144ec9 100644
--- a/core/src/tbox/src/tbox/stream/impl/filter/charset.c
+++ b/core/src/tbox/src/tbox/stream/impl/filter/charset.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file charset.c
diff --git a/core/src/tbox/src/tbox/stream/impl/filter/chunked.c b/core/src/tbox/src/tbox/stream/impl/filter/chunked.c
index 05f325666..f18761bd2 100644
--- a/core/src/tbox/src/tbox/stream/impl/filter/chunked.c
+++ b/core/src/tbox/src/tbox/stream/impl/filter/chunked.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file chunked.c
diff --git a/core/src/tbox/src/tbox/stream/impl/filter/prefix.h b/core/src/tbox/src/tbox/stream/impl/filter/prefix.h
index 81d8a85c6..e4e648e43 100644
--- a/core/src/tbox/src/tbox/stream/impl/filter/prefix.h
+++ b/core/src/tbox/src/tbox/stream/impl/filter/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/stream/impl/filter/zip.c b/core/src/tbox/src/tbox/stream/impl/filter/zip.c
index 041257109..7077463e5 100644
--- a/core/src/tbox/src/tbox/stream/impl/filter/zip.c
+++ b/core/src/tbox/src/tbox/stream/impl/filter/zip.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file zip.c
diff --git a/core/src/tbox/src/tbox/stream/impl/prefix.h b/core/src/tbox/src/tbox/stream/impl/prefix.h
index 0b67bc9b0..a5c292d3c 100644
--- a/core/src/tbox/src/tbox/stream/impl/prefix.h
+++ b/core/src/tbox/src/tbox/stream/impl/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/stream/impl/stream.h b/core/src/tbox/src/tbox/stream/impl/stream.h
index 4cd96b63d..a101ba0b3 100644
--- a/core/src/tbox/src/tbox/stream/impl/stream.h
+++ b/core/src/tbox/src/tbox/stream/impl/stream.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file stream.h
diff --git a/core/src/tbox/src/tbox/stream/impl/stream/data.c b/core/src/tbox/src/tbox/stream/impl/stream/data.c
index 1c835e51b..00e1e8ae5 100644
--- a/core/src/tbox/src/tbox/stream/impl/stream/data.c
+++ b/core/src/tbox/src/tbox/stream/impl/stream/data.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file data.c
diff --git a/core/src/tbox/src/tbox/stream/impl/stream/file.c b/core/src/tbox/src/tbox/stream/impl/stream/file.c
index 513733dd1..cfbeeab0e 100644
--- a/core/src/tbox/src/tbox/stream/impl/stream/file.c
+++ b/core/src/tbox/src/tbox/stream/impl/stream/file.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file file.c
diff --git a/core/src/tbox/src/tbox/stream/impl/stream/filter.c b/core/src/tbox/src/tbox/stream/impl/stream/filter.c
index c042bd565..8a228bffc 100644
--- a/core/src/tbox/src/tbox/stream/impl/stream/filter.c
+++ b/core/src/tbox/src/tbox/stream/impl/stream/filter.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file filter.c
diff --git a/core/src/tbox/src/tbox/stream/impl/stream/http.c b/core/src/tbox/src/tbox/stream/impl/stream/http.c
index 44a1357d0..b7b73f6c8 100644
--- a/core/src/tbox/src/tbox/stream/impl/stream/http.c
+++ b/core/src/tbox/src/tbox/stream/impl/stream/http.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* \http http.c
diff --git a/core/src/tbox/src/tbox/stream/impl/stream/prefix.h b/core/src/tbox/src/tbox/stream/impl/stream/prefix.h
index f1485c1f0..9697acdc0 100644
--- a/core/src/tbox/src/tbox/stream/impl/stream/prefix.h
+++ b/core/src/tbox/src/tbox/stream/impl/stream/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/stream/impl/stream/sock.c b/core/src/tbox/src/tbox/stream/impl/stream/sock.c
index f3773e7c0..b4d19be03 100644
--- a/core/src/tbox/src/tbox/stream/impl/stream/sock.c
+++ b/core/src/tbox/src/tbox/stream/impl/stream/sock.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* \sock sock.c
@@ -61,13 +61,16 @@ typedef struct __tb_stream_sock_t
#endif
// the sock type
- tb_uint32_t type : 23;
+ tb_uint32_t type : 22;
// the try number
- tb_uint32_t tryn : 8;
+ tb_uint32_t tryn : 8;
// keep alive after being closed?
- tb_uint32_t balived : 1;
+ tb_uint32_t keep_alive : 1;
+
+ // is owner of socket
+ tb_uint32_t owner : 1;
// the wait event
tb_long_t wait;
@@ -103,9 +106,6 @@ static tb_bool_t tb_stream_sock_open(tb_stream_ref_t stream)
stream_sock->read = 0;
stream_sock->writ = 0;
- // opened?
- tb_check_return_val(!stream_sock->sock, tb_true);
-
// the url
tb_url_ref_t url = tb_stream_url(stream);
tb_assert_and_check_return_val(url, tb_false);
@@ -135,10 +135,9 @@ static tb_bool_t tb_stream_sock_open(tb_stream_ref_t stream)
if (tb_ipaddr_ip_is_empty(addr))
{
// look ip
- tb_ipaddr_t ip_addr;
+ tb_ipaddr_t ip_addr = {0};
if (!tb_addrinfo_addr(tb_url_host(url), &ip_addr))
{
- // failed
tb_stream_state_set(stream, TB_STATE_SOCK_DNS_FAILED);
return tb_false;
}
@@ -152,8 +151,15 @@ static tb_bool_t tb_stream_sock_open(tb_stream_ref_t stream)
if (args && !tb_strnicmp(args, "udp=", 4)) stream_sock->type = TB_SOCKET_TYPE_UDP;
else if (args && !tb_strnicmp(args, "tcp=", 4)) stream_sock->type = TB_SOCKET_TYPE_TCP;
+ // exit sock first if not keep-alive
+ if (!stream_sock->keep_alive && stream_sock->sock)
+ {
+ if (stream_sock->sock && !tb_socket_exit(stream_sock->sock)) return tb_false;
+ stream_sock->sock = tb_null;
+ }
+
// make sock
- stream_sock->sock = tb_socket_init(stream_sock->type, tb_ipaddr_family(addr));
+ if (!stream_sock->sock) stream_sock->sock = tb_socket_init(stream_sock->type, tb_ipaddr_family(addr));
// open sock failed?
if (!stream_sock->sock)
@@ -173,7 +179,7 @@ static tb_bool_t tb_stream_sock_open(tb_stream_ref_t stream)
case TB_SOCKET_TYPE_TCP:
{
// trace
- tb_trace_d("connect: %s[%{ipaddr}]: ..", tb_url_host(url), addr);
+ tb_trace_d("sock(%p): connect: %s[%{ipaddr}]: ..", stream_sock->sock, tb_url_host(url), addr);
// connect it
tb_long_t real = -1;
@@ -194,7 +200,7 @@ static tb_bool_t tb_stream_sock_open(tb_stream_ref_t stream)
else tb_stream_state_set(stream, !real? TB_STATE_SOCK_CONNECT_TIMEOUT : TB_STATE_SOCK_CONNECT_FAILED);
// trace
- tb_trace_d("connect: %s", ok? "ok" : "no");
+ tb_trace_d("sock(%p): connect: %s", stream_sock->sock, ok? "ok" : "failed");
// ok?
if (ok)
@@ -226,9 +232,9 @@ static tb_bool_t tb_stream_sock_open(tb_stream_ref_t stream)
} while (0);
// trace
- tb_trace_d("ssl: %s", ok? "ok" : "no");
+ tb_trace_d("sock(%p): ssl: %s", stream_sock->sock, ok? "ok" : "no");
- // failed? save state
+ // ssl failed? save state
if (!ok) tb_stream_state_set(stream, stream_sock->hssl? tb_ssl_state(stream_sock->hssl) : TB_STATE_SOCK_SSL_FAILED);
#endif
}
@@ -262,6 +268,129 @@ static tb_bool_t tb_stream_sock_open(tb_stream_ref_t stream)
break;
}
+ // open failed? close ssl and socket
+ if (!ok)
+ {
+#ifdef TB_SSL_ENABLE
+ // exit ssl
+ if (stream_sock->hssl) tb_ssl_exit(stream_sock->hssl);
+ stream_sock->hssl = tb_null;
+#endif
+
+ // exit sock
+ if (stream_sock->sock) tb_socket_exit(stream_sock->sock);
+ stream_sock->sock = tb_null;
+ }
+
+ // ok?
+ return ok;
+}
+static tb_bool_t tb_stream_sock_open_ref(tb_stream_ref_t stream)
+{
+ // check
+ tb_stream_sock_t* stream_sock = tb_stream_sock_cast(stream);
+ tb_assert_and_check_return_val(stream_sock && stream_sock->type, tb_false);
+
+ // clear
+ stream_sock->wait = 0;
+ stream_sock->tryn = 0;
+ stream_sock->read = 0;
+ stream_sock->writ = 0;
+
+ // the url
+ tb_url_ref_t url = tb_stream_url(stream);
+ tb_assert_and_check_return_val(url, tb_false);
+
+#ifndef TB_SSL_ENABLE
+ // ssl? not supported
+ if (tb_url_ssl(url))
+ {
+ // trace
+ tb_trace_w("ssl is not supported now! please enable it from config if you need it.");
+
+ // save state
+ tb_stream_state_set(stream, TB_STATE_SOCK_SSL_NOT_SUPPORTED);
+ return tb_false;
+ }
+#endif
+
+ // done
+ tb_bool_t ok = tb_false;
+ switch (stream_sock->type)
+ {
+ case TB_SOCKET_TYPE_TCP:
+ {
+ // ssl? init it
+ if (tb_url_ssl(url))
+ {
+#ifdef TB_SSL_ENABLE
+ do
+ {
+ // init ssl
+ if (!stream_sock->hssl) stream_sock->hssl = tb_ssl_init(tb_false);
+ tb_assert_and_check_break(stream_sock->hssl);
+
+ // init bio
+ tb_ssl_set_bio_sock(stream_sock->hssl, stream_sock->sock);
+
+ // init timeout
+ tb_ssl_set_timeout(stream_sock->hssl, tb_stream_timeout(stream));
+
+ // open ssl
+ if (!tb_ssl_open(stream_sock->hssl)) break;
+
+ // ok
+ ok = tb_true;
+
+ } while (0);
+
+ // trace
+ tb_trace_d("sock(%p): ssl: %s", stream_sock->sock, ok? "ok" : "no");
+
+ // ssl failed? save state
+ if (!ok) tb_stream_state_set(stream, stream_sock->hssl? tb_ssl_state(stream_sock->hssl) : TB_STATE_SOCK_SSL_FAILED);
+#endif
+ }
+ else ok = tb_true;
+ }
+ break;
+ case TB_SOCKET_TYPE_UDP:
+ {
+ // ssl? not supported
+ if (tb_url_ssl(url))
+ {
+ // trace
+ tb_trace_w("udp ssl is not supported!");
+
+ // save state
+ tb_stream_state_set(stream, TB_STATE_SOCK_SSL_NOT_SUPPORTED);
+ }
+ else
+ {
+ // ok
+ ok = tb_true;
+ tb_stream_state_set(stream, TB_STATE_OK);
+ }
+ }
+ break;
+ default:
+ {
+ // trace
+ tb_trace_e("unknown socket type: %lu", stream_sock->type);
+ }
+ break;
+ }
+
+ // open failed? close ssl and socket
+ if (!ok)
+ {
+#ifdef TB_SSL_ENABLE
+ // exit ssl
+ if (stream_sock->hssl) tb_ssl_exit(stream_sock->hssl);
+ stream_sock->hssl = tb_null;
+#endif
+ }
+
// ok?
return ok;
}
@@ -278,11 +407,14 @@ static tb_bool_t tb_stream_sock_clos(tb_stream_ref_t stream)
#endif
// keep alive? not close it
- tb_check_return_val(!stream_sock->balived, tb_true);
+ tb_check_return_val(!stream_sock->keep_alive, tb_true);
- // exit sock
- if (stream_sock->sock && !tb_socket_exit(stream_sock->sock)) return tb_false;
- stream_sock->sock = tb_null;
+ // exit socket
+ if (stream_sock->owner)
+ {
+ if (stream_sock->sock && !tb_socket_exit(stream_sock->sock)) return tb_false;
+ stream_sock->sock = tb_null;
+ }
// clear
stream_sock->wait = 0;
@@ -306,7 +438,7 @@ static tb_void_t tb_stream_sock_exit(tb_stream_ref_t stream)
#endif
// exit sock
- if (stream_sock->sock) tb_socket_exit(stream_sock->sock);
+ if (stream_sock->sock && stream_sock->owner) tb_socket_exit(stream_sock->sock);
stream_sock->sock = tb_null;
// clear
@@ -358,7 +490,7 @@ static tb_long_t tb_stream_sock_read(tb_stream_ref_t stream, tb_byte_t* data, tb
real = tb_ssl_read(stream_sock->hssl, data, size);
// trace
- tb_trace_d("read: %ld <? %lu", real, size);
+ tb_trace_d("sock(%p): read: %ld <? %lu", stream_sock->sock, real, size);
// failed or closed?
tb_check_return_val(real >= 0, -1);
@@ -370,7 +502,7 @@ static tb_long_t tb_stream_sock_read(tb_stream_ref_t stream, tb_byte_t* data, tb
real = tb_socket_recv(stream_sock->sock, data, size);
// trace
- tb_trace_d("read: %ld <? %lu", real, size);
+ tb_trace_d("sock(%p): read: %ld <? %lu", stream_sock->sock, real, size);
// failed or closed?
tb_check_return_val(real >= 0, -1);
@@ -389,7 +521,7 @@ static tb_long_t tb_stream_sock_read(tb_stream_ref_t stream, tb_byte_t* data, tb
real = tb_socket_urecv(stream_sock->sock, tb_null, data, size);
// trace
- tb_trace_d("read: %ld <? %lu", real, size);
+ tb_trace_d("sock(%p): read: %ld <? %lu", stream_sock->sock, real, size);
// failed or closed?
tb_check_return_val(real >= 0, -1);
@@ -445,7 +577,7 @@ static tb_long_t tb_stream_sock_writ(tb_stream_ref_t stream, tb_byte_t const* da
real = tb_ssl_writ(stream_sock->hssl, data, size);
// trace
- tb_trace_d("writ: %ld <? %lu", real, size);
+ tb_trace_d("sock(%p): writ: %ld <? %lu", stream_sock->sock, real, size);
// failed or closed?
tb_check_return_val(real >= 0, -1);
@@ -457,7 +589,7 @@ static tb_long_t tb_stream_sock_writ(tb_stream_ref_t stream, tb_byte_t const* da
real = tb_socket_send(stream_sock->sock, data, size);
// trace
- tb_trace_d("writ: %ld <? %lu", real, size);
+ tb_trace_d("sock(%p): writ: %ld <? %lu", stream_sock->sock, real, size);
// failed or closed?
tb_check_return_val(real >= 0, -1);
@@ -480,7 +612,7 @@ static tb_long_t tb_stream_sock_writ(tb_stream_ref_t stream, tb_byte_t const* da
real = tb_socket_usend(stream_sock->sock, addr, data, size);
// trace
- tb_trace_d("writ: %ld <? %lu", real, size);
+ tb_trace_d("sock(%p): writ: %ld <? %lu", stream_sock->sock, real, size);
// failed or closed?
tb_check_return_val(real >= 0, -1);
@@ -534,7 +666,7 @@ static tb_long_t tb_stream_sock_wait(tb_stream_ref_t stream, tb_size_t wait, tb_
}
// trace
- tb_trace_d("wait: %ld", stream_sock->wait);
+ tb_trace_d("sock(%p): wait: %ld", stream_sock->sock, stream_sock->wait);
// ok?
return stream_sock->wait;
@@ -550,7 +682,7 @@ static tb_bool_t tb_stream_sock_ctrl(tb_stream_ref_t stream, tb_size_t ctrl, tb_
{
// check
tb_assert_and_check_return_val(tb_stream_is_closed(stream), tb_false);
- tb_assert_and_check_return_val(!stream_sock->balived, tb_false);
+ tb_assert_and_check_return_val(!stream_sock->keep_alive, tb_false);
// the type
tb_size_t type = (tb_size_t)tb_va_arg(args, tb_size_t);
@@ -572,8 +704,8 @@ static tb_bool_t tb_stream_sock_ctrl(tb_stream_ref_t stream, tb_size_t ctrl, tb_
case TB_STREAM_CTRL_SOCK_KEEP_ALIVE:
{
// keep alive?
- tb_bool_t balived = (tb_bool_t)tb_va_arg(args, tb_bool_t);
- stream_sock->balived = balived? 1 : 0;
+ tb_bool_t keep_alive = (tb_bool_t)tb_va_arg(args, tb_bool_t);
+ stream_sock->keep_alive = keep_alive? 1 : 0;
return tb_true;
}
default:
@@ -628,11 +760,76 @@ tb_stream_ref_t tb_stream_init_from_sock(tb_char_t const* host, tb_uint16_t port
stream = tb_stream_init_sock();
tb_assert_and_check_break(stream);
- // ctrl
+ // ctrl stream
if (!tb_stream_ctrl(stream, TB_STREAM_CTRL_SET_HOST, host)) break;
if (!tb_stream_ctrl(stream, TB_STREAM_CTRL_SET_PORT, port)) break;
if (!tb_stream_ctrl(stream, TB_STREAM_CTRL_SET_SSL, bssl)) break;
if (!tb_stream_ctrl(stream, TB_STREAM_CTRL_SOCK_SET_TYPE, type)) break;
+
+ // init the sock stream
+ tb_stream_sock_t* stream_sock = tb_stream_sock_cast(stream);
+ tb_assert_and_check_break(stream_sock);
+
+ // mark as owner of socket
+ stream_sock->owner = 1;
+
+ // ok
+ ok = tb_true;
+
+ } while (0);
+
+ // failed?
+ if (!ok)
+ {
+ // exit it
+ if (stream) tb_stream_exit(stream);
+ stream = tb_null;
+ }
+
+ // ok?
+ return stream;
+}
+tb_stream_ref_t tb_stream_init_from_sock_ref(tb_socket_ref_t sock, tb_size_t type, tb_bool_t bssl)
+{
+ // check
+ tb_assert_and_check_return_val(sock, tb_null);
+
+ // done
+ tb_bool_t ok = tb_false;
+ tb_stream_ref_t stream = tb_null;
+ do
+ {
+ // init stream
+ stream = tb_stream_init( TB_STREAM_TYPE_SOCK
+ , sizeof(tb_stream_sock_t)
+ , TB_STREAM_SOCK_CACHE_MAXN
+ , tb_stream_sock_open_ref
+ , tb_stream_sock_clos
+ , tb_stream_sock_exit
+ , tb_stream_sock_ctrl
+ , tb_stream_sock_wait
+ , tb_stream_sock_read
+ , tb_stream_sock_writ
+ , tb_null
+ , tb_null
+ , tb_stream_sock_kill);
+ tb_assert_and_check_break(stream);
+
+ // ctrl stream
+ if (!tb_stream_ctrl(stream, TB_STREAM_CTRL_SET_HOST, "fd")) break;
+ if (!tb_stream_ctrl(stream, TB_STREAM_CTRL_SET_PORT, (tb_uint16_t)tb_sock2fd(sock))) break;
+ if (!tb_stream_ctrl(stream, TB_STREAM_CTRL_SET_SSL, bssl)) break;
+ if (!tb_stream_ctrl(stream, TB_STREAM_CTRL_SOCK_SET_TYPE, type)) break;
+
+ // init the sock stream
+ tb_stream_sock_t* stream_sock = tb_stream_sock_cast(stream);
+ tb_assert_and_check_break(stream_sock);
+
+ // only be reference of socket
+ stream_sock->owner = 0;
+
+ // save socket
+ stream_sock->sock = sock;
// ok
ok = tb_true;
diff --git a/core/src/tbox/src/tbox/stream/prefix.h b/core/src/tbox/src/tbox/stream/prefix.h
index 317c74c7b..98f561706 100644
--- a/core/src/tbox/src/tbox/stream/prefix.h
+++ b/core/src/tbox/src/tbox/stream/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/stream/static_stream.c b/core/src/tbox/src/tbox/stream/static_stream.c
index ecc241935..5d75af38a 100644
--- a/core/src/tbox/src/tbox/stream/static_stream.c
+++ b/core/src/tbox/src/tbox/stream/static_stream.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file static_stream.c
diff --git a/core/src/tbox/src/tbox/stream/static_stream.h b/core/src/tbox/src/tbox/stream/static_stream.h
index e9c373849..5a57a94fc 100644
--- a/core/src/tbox/src/tbox/stream/static_stream.h
+++ b/core/src/tbox/src/tbox/stream/static_stream.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file static_stream.h
diff --git a/core/src/tbox/src/tbox/stream/stream.c b/core/src/tbox/src/tbox/stream/stream.c
index 81c0418a3..8615be79a 100644
--- a/core/src/tbox/src/tbox/stream/stream.c
+++ b/core/src/tbox/src/tbox/stream/stream.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file stream.c
@@ -74,7 +74,7 @@ tb_stream_ref_t tb_stream_init( tb_size_t type
stream = (tb_stream_t*)tb_malloc0(sizeof(tb_stream_t) + type_size);
tb_assert_and_check_break(stream);
- // init stream referenced
+ // init stream reference
stream_ref = (tb_stream_ref_t)&stream[1];
// init type
diff --git a/core/src/tbox/src/tbox/stream/stream.h b/core/src/tbox/src/tbox/stream/stream.h
index d5a12debd..50bd0463b 100644
--- a/core/src/tbox/src/tbox/stream/stream.h
+++ b/core/src/tbox/src/tbox/stream/stream.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file stream.h
@@ -33,9 +33,6 @@
#include "filter.h"
#include "transfer.h"
#include "static_stream.h"
-#ifdef TB_CONFIG_API_HAVE_DEPRECATED
-# include "deprecated/deprecated.h"
-#endif
/*!architecture
*
@@ -347,6 +344,16 @@ tb_stream_ref_t tb_stream_init_from_file(tb_char_t const* path, tb_size_
*/
tb_stream_ref_t tb_stream_init_from_sock(tb_char_t const* host, tb_uint16_t port, tb_size_t type, tb_bool_t bssl);
+/*! init stream from sock reference
+ *
+ * @param sock the socket
+ * @param type the socket type, tcp or udp
+ * @param bssl enable ssl?
+ *
+ * @return the stream
+ */
+tb_stream_ref_t tb_stream_init_from_sock_ref(tb_socket_ref_t sock, tb_size_t type, tb_bool_t bssl);
+
/*! init stream from http or https
*
* @param host the host
diff --git a/core/src/tbox/src/tbox/stream/transfer.c b/core/src/tbox/src/tbox/stream/transfer.c
index c3a8c47bc..0be9343fd 100644
--- a/core/src/tbox/src/tbox/stream/transfer.c
+++ b/core/src/tbox/src/tbox/stream/transfer.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file transfer.c
@@ -51,7 +51,7 @@ tb_hong_t tb_transfer(tb_stream_ref_t istream, tb_stream_ref_t ostream, tb_size_
// open it first if ostream have been not opened
if (tb_stream_is_closed(ostream) && !tb_stream_open(ostream)) return -1;
-
+
// done func
if (func) func(TB_STATE_OK, tb_stream_offset(istream), tb_stream_size(istream), 0, 0, priv);
@@ -124,10 +124,7 @@ tb_hong_t tb_transfer(tb_stream_ref_t istream, tb_stream_ref_t ostream, tb_size_
{
// 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);
+ tb_check_break(wait > 0);
// has writ?
tb_assert_and_check_break(wait & TB_STREAM_WAIT_READ);
diff --git a/core/src/tbox/src/tbox/stream/transfer.h b/core/src/tbox/src/tbox/stream/transfer.h
index d09fdca10..2f91df680 100644
--- a/core/src/tbox/src/tbox/stream/transfer.h
+++ b/core/src/tbox/src/tbox/stream/transfer.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file transfer.h
diff --git a/core/src/tbox/src/tbox/string/prefix.h b/core/src/tbox/src/tbox/string/prefix.h
index 197597569..b576f87b4 100644
--- a/core/src/tbox/src/tbox/string/prefix.h
+++ b/core/src/tbox/src/tbox/string/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/string/static_string.c b/core/src/tbox/src/tbox/string/static_string.c
index 0b61df8d5..aaa598202 100644
--- a/core/src/tbox/src/tbox/string/static_string.c
+++ b/core/src/tbox/src/tbox/string/static_string.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file static_string.c
@@ -34,11 +34,11 @@
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
-// the maximum grow size of value string
+// the format string data size
#ifdef __tb_small__
-# define TB_STATIC_STRING_FMTD_SIZE (4096)
+# define TB_STATIC_STRING_FMTD_SIZE (512)
#else
-# define TB_STATIC_STRING_FMTD_SIZE (8192)
+# define TB_STATIC_STRING_FMTD_SIZE (1024)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
diff --git a/core/src/tbox/src/tbox/string/static_string.h b/core/src/tbox/src/tbox/string/static_string.h
index 607118614..85675964e 100644
--- a/core/src/tbox/src/tbox/string/static_string.h
+++ b/core/src/tbox/src/tbox/string/static_string.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file static_string.h
diff --git a/core/src/tbox/src/tbox/string/string.c b/core/src/tbox/src/tbox/string/string.c
index e0e322cfe..c323563c5 100644
--- a/core/src/tbox/src/tbox/string/string.c
+++ b/core/src/tbox/src/tbox/string/string.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file string.c
@@ -34,11 +34,11 @@
/* //////////////////////////////////////////////////////////////////////////////////////
* macros
*/
-// the maximum grow size of value string
+// the format string data size
#ifdef __tb_small__
-# define TB_SCOPED_STRING_FMTD_SIZE (4096)
+# define TB_SCOPED_STRING_FMTD_SIZE (512)
#else
-# define TB_SCOPED_STRING_FMTD_SIZE (8192)
+# define TB_SCOPED_STRING_FMTD_SIZE (1024)
#endif
/* //////////////////////////////////////////////////////////////////////////////////////
diff --git a/core/src/tbox/src/tbox/string/string.h b/core/src/tbox/src/tbox/string/string.h
index f535b1856..4d7bc533a 100644
--- a/core/src/tbox/src/tbox/string/string.h
+++ b/core/src/tbox/src/tbox/string/string.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file string.h
diff --git a/core/src/tbox/src/tbox/tbox.c b/core/src/tbox/src/tbox/tbox.c
index 51a139aac..f555ce43c 100644
--- a/core/src/tbox/src/tbox/tbox.c
+++ b/core/src/tbox/src/tbox/tbox.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file tbox.c
@@ -30,6 +30,7 @@
#include "libc/impl/impl.h"
#include "libm/impl/impl.h"
#include "math/impl/impl.h"
+#include "object/impl/impl.h"
#include "memory/impl/impl.h"
#include "network/impl/impl.h"
#include "platform/impl/impl.h"
diff --git a/core/src/tbox/src/tbox/tbox.config.h.in b/core/src/tbox/src/tbox/tbox.config.h.in
new file mode 100644
index 000000000..8c2607887
--- /dev/null
+++ b/core/src/tbox/src/tbox/tbox.config.h.in
@@ -0,0 +1,172 @@
+#ifndef TB_CONFIG_H
+#define TB_CONFIG_H
+
+// version
+#define TB_CONFIG_VERSION "${VERSION}"
+#define TB_CONFIG_VERSION_MAJOR ${VERSION_MAJOR}
+#define TB_CONFIG_VERSION_MINOR ${VERSION_MINOR}
+#define TB_CONFIG_VERSION_ALTER ${VERSION_ALTER}
+#define TB_CONFIG_VERSION_BUILD ${VERSION_BUILD}
+
+// defines
+#define TB_CONFIG_OS_${OS} 1
+${define _GNU_SOURCE}
+${define _REENTRANT}
+${define TB_CONFIG_SMALL}
+${define TB_CONFIG_MICRO_ENABLE}
+${define TB_CONFIG_TYPE_HAVE_WCHAR}
+${define TB_CONFIG_TYPE_HAVE_FLOAT}
+
+// modules
+${define TB_CONFIG_MODULE_HAVE_XML}
+${define TB_CONFIG_MODULE_HAVE_ZIP}
+${define TB_CONFIG_MODULE_HAVE_HASH}
+${define TB_CONFIG_MODULE_HAVE_REGEX}
+${define TB_CONFIG_MODULE_HAVE_OBJECT}
+${define TB_CONFIG_MODULE_HAVE_CHARSET}
+${define TB_CONFIG_MODULE_HAVE_DATABASE}
+${define TB_CONFIG_MODULE_HAVE_COROUTINE}
+
+// packages
+${define TB_CONFIG_PACKAGE_HAVE_ZLIB}
+${define TB_CONFIG_PACKAGE_HAVE_MYSQL}
+${define TB_CONFIG_PACKAGE_HAVE_SQLITE3}
+${define TB_CONFIG_PACKAGE_HAVE_OPENSSL}
+${define TB_CONFIG_PACKAGE_HAVE_POLARSSL}
+${define TB_CONFIG_PACKAGE_HAVE_MBEDTLS}
+${define TB_CONFIG_PACKAGE_HAVE_PCRE2}
+${define TB_CONFIG_PACKAGE_HAVE_PCRE}
+
+// libc functions
+${define TB_CONFIG_LIBC_HAVE_MEMCPY}
+${define TB_CONFIG_LIBC_HAVE_MEMSET}
+${define TB_CONFIG_LIBC_HAVE_MEMMOVE}
+${define TB_CONFIG_LIBC_HAVE_MEMCMP}
+${define TB_CONFIG_LIBC_HAVE_MEMMEM}
+${define TB_CONFIG_LIBC_HAVE_STRCAT}
+${define TB_CONFIG_LIBC_HAVE_STRNCAT}
+${define TB_CONFIG_LIBC_HAVE_STRCPY}
+${define TB_CONFIG_LIBC_HAVE_STRNCPY}
+${define TB_CONFIG_LIBC_HAVE_STRLCPY}
+${define TB_CONFIG_LIBC_HAVE_STRLEN}
+${define TB_CONFIG_LIBC_HAVE_STRNLEN}
+${define TB_CONFIG_LIBC_HAVE_STRSTR}
+${define TB_CONFIG_LIBC_HAVE_STRCASESTR}
+${define TB_CONFIG_LIBC_HAVE_STRCMP}
+${define TB_CONFIG_LIBC_HAVE_STRCASECMP}
+${define TB_CONFIG_LIBC_HAVE_STRNCMP}
+${define TB_CONFIG_LIBC_HAVE_STRNCASECMP}
+
+${define TB_CONFIG_LIBC_HAVE_WCSCAT}
+${define TB_CONFIG_LIBC_HAVE_WCSNCAT}
+${define TB_CONFIG_LIBC_HAVE_WCSCPY}
+${define TB_CONFIG_LIBC_HAVE_WCSNCPY}
+${define TB_CONFIG_LIBC_HAVE_WCSLCPY}
+${define TB_CONFIG_LIBC_HAVE_WCSLEN}
+${define TB_CONFIG_LIBC_HAVE_WCSNLEN}
+${define TB_CONFIG_LIBC_HAVE_WCSSTR}
+${define TB_CONFIG_LIBC_HAVE_WCSCASESTR}
+${define TB_CONFIG_LIBC_HAVE_WCSCMP}
+${define TB_CONFIG_LIBC_HAVE_WCSCASECMP}
+${define TB_CONFIG_LIBC_HAVE_WCSNCMP}
+${define TB_CONFIG_LIBC_HAVE_WCSNCASECMP}
+${define TB_CONFIG_LIBC_HAVE_WCSTOMBS}
+${define TB_CONFIG_LIBC_HAVE_MBSTOWCS}
+
+${define TB_CONFIG_LIBC_HAVE_GMTIME}
+${define TB_CONFIG_LIBC_HAVE_MKTIME}
+${define TB_CONFIG_LIBC_HAVE_LOCALTIME}
+${define TB_CONFIG_LIBC_HAVE_GETTIMEOFDAY}
+${define TB_CONFIG_LIBC_HAVE_SIGNAL}
+${define TB_CONFIG_LIBC_HAVE_SETJMP}
+${define TB_CONFIG_LIBC_HAVE_SIGSETJMP}
+${define TB_CONFIG_LIBC_HAVE_KILL}
+${define TB_CONFIG_LIBC_HAVE_BACKTRACE}
+${define TB_CONFIG_LIBC_HAVE_SETLOCALE}
+${define TB_CONFIG_LIBC_HAVE_FPUTS}
+${define TB_CONFIG_LIBC_HAVE_SRANDOM}
+${define TB_CONFIG_LIBC_HAVE_RANDOM}
+
+// libm functions
+${define TB_CONFIG_LIBM_HAVE_SINCOS}
+${define TB_CONFIG_LIBM_HAVE_SINCOSF}
+${define TB_CONFIG_LIBM_HAVE_LOG2}
+${define TB_CONFIG_LIBM_HAVE_LOG2F}
+${define TB_CONFIG_LIBM_HAVE_SQRT}
+${define TB_CONFIG_LIBM_HAVE_SQRTF}
+${define TB_CONFIG_LIBM_HAVE_ACOS}
+${define TB_CONFIG_LIBM_HAVE_ACOSF}
+${define TB_CONFIG_LIBM_HAVE_ASIN}
+${define TB_CONFIG_LIBM_HAVE_ASINF}
+${define TB_CONFIG_LIBM_HAVE_POW}
+${define TB_CONFIG_LIBM_HAVE_POWF}
+${define TB_CONFIG_LIBM_HAVE_FMOD}
+${define TB_CONFIG_LIBM_HAVE_FMODF}
+${define TB_CONFIG_LIBM_HAVE_TAN}
+${define TB_CONFIG_LIBM_HAVE_TANF}
+${define TB_CONFIG_LIBM_HAVE_ATAN}
+${define TB_CONFIG_LIBM_HAVE_ATANF}
+${define TB_CONFIG_LIBM_HAVE_ATAN2}
+${define TB_CONFIG_LIBM_HAVE_ATAN2F}
+${define TB_CONFIG_LIBM_HAVE_COS}
+${define TB_CONFIG_LIBM_HAVE_COSF}
+${define TB_CONFIG_LIBM_HAVE_SIN}
+${define TB_CONFIG_LIBM_HAVE_SINF}
+${define TB_CONFIG_LIBM_HAVE_EXP}
+${define TB_CONFIG_LIBM_HAVE_EXPF}
+
+// posix functions
+${define TB_CONFIG_POSIX_HAVE_POLL}
+${define TB_CONFIG_POSIX_HAVE_SELECT}
+${define TB_CONFIG_POSIX_HAVE_PTHREAD_MUTEX_INIT}
+${define TB_CONFIG_POSIX_HAVE_PTHREAD_CREATE}
+${define TB_CONFIG_POSIX_HAVE_PTHREAD_SETSPECIFIC}
+${define TB_CONFIG_POSIX_HAVE_PTHREAD_GETSPECIFIC}
+${define TB_CONFIG_POSIX_HAVE_PTHREAD_KEY_CREATE}
+${define TB_CONFIG_POSIX_HAVE_PTHREAD_KEY_DELETE}
+${define TB_CONFIG_POSIX_HAVE_SOCKET}
+${define TB_CONFIG_POSIX_HAVE_POLL}
+${define TB_CONFIG_POSIX_HAVE_OPENDIR}
+${define TB_CONFIG_POSIX_HAVE_DLOPEN}
+${define TB_CONFIG_POSIX_HAVE_OPEN}
+${define TB_CONFIG_POSIX_HAVE_STAT64}
+${define TB_CONFIG_POSIX_HAVE_GETHOSTNAME}
+${define TB_CONFIG_POSIX_HAVE_GETIFADDRS}
+${define TB_CONFIG_POSIX_HAVE_SEM_INIT}
+${define TB_CONFIG_POSIX_HAVE_GETPAGESIZE}
+${define TB_CONFIG_POSIX_HAVE_SYSCONF}
+${define TB_CONFIG_POSIX_HAVE_SCHED_YIELD}
+${define TB_CONFIG_POSIX_HAVE_REGCOMP}
+${define TB_CONFIG_POSIX_HAVE_REGEXEC}
+${define TB_CONFIG_POSIX_HAVE_READV}
+${define TB_CONFIG_POSIX_HAVE_WRITEV}
+${define TB_CONFIG_POSIX_HAVE_PREADV}
+${define TB_CONFIG_POSIX_HAVE_PWRITEV}
+${define TB_CONFIG_POSIX_HAVE_PREAD64}
+${define TB_CONFIG_POSIX_HAVE_PWRITE64}
+${define TB_CONFIG_POSIX_HAVE_FDATASYNC}
+${define TB_CONFIG_POSIX_HAVE_COPYFILE}
+${define TB_CONFIG_POSIX_HAVE_SENDFILE}
+${define TB_CONFIG_POSIX_HAVE_EPOLL_CREATE}
+${define TB_CONFIG_POSIX_HAVE_EPOLL_WAIT}
+${define TB_CONFIG_POSIX_HAVE_POSIX_SPAWNP}
+${define TB_CONFIG_POSIX_HAVE_EXECVP}
+${define TB_CONFIG_POSIX_HAVE_EXECVPE}
+${define TB_CONFIG_POSIX_HAVE_FORK}
+${define TB_CONFIG_POSIX_HAVE_VFORK}
+${define TB_CONFIG_POSIX_HAVE_WAITPID}
+${define TB_CONFIG_POSIX_HAVE_GETDTABLESIZE}
+${define TB_CONFIG_POSIX_HAVE_GETRLIMIT}
+${define TB_CONFIG_POSIX_HAVE_GETADDRINFO}
+${define TB_CONFIG_POSIX_HAVE_GETNAMEINFO}
+${define TB_CONFIG_POSIX_HAVE_GETHOSTBYNAME}
+${define TB_CONFIG_POSIX_HAVE_GETHOSTBYADDR}
+
+// systemv functions
+${define TB_CONFIG_SYSTEMV_HAVE_SEMGET}
+${define TB_CONFIG_SYSTEMV_HAVE_SEMTIMEDOP}
+
+// valgrind functions
+${define TB_CONFIG_SYSTEMV_HAVE_VALGRIND_STACK_REGISTER}
+
+#endif
diff --git a/core/src/tbox/src/tbox/tbox.h b/core/src/tbox/src/tbox/tbox.h
index 69c63073a..1fec6b044 100644
--- a/core/src/tbox/src/tbox/tbox.h
+++ b/core/src/tbox/src/tbox/tbox.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file tbox.h
@@ -30,19 +30,24 @@
*/
#include "prefix.h"
#include "zip/zip.h"
+#include "xml/xml.h"
#include "libm/libm.h"
#include "libc/libc.h"
#include "math/math.h"
#include "hash/hash.h"
#include "utils/utils.h"
+#include "regex/regex.h"
+#include "object/object.h"
#include "memory/memory.h"
#include "stream/stream.h"
#include "string/string.h"
#include "network/network.h"
#include "charset/charset.h"
#include "platform/platform.h"
+#include "database/database.h"
#include "algorithm/algorithm.h"
#include "container/container.h"
+#include "coroutine/coroutine.h"
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
diff --git a/core/src/tbox/src/tbox/utils/base32.c b/core/src/tbox/src/tbox/utils/base32.c
index 7b146fe89..a581dc887 100644
--- a/core/src/tbox/src/tbox/utils/base32.c
+++ b/core/src/tbox/src/tbox/utils/base32.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file base32.c
diff --git a/core/src/tbox/src/tbox/utils/base32.h b/core/src/tbox/src/tbox/utils/base32.h
index 79af4126e..c4989e381 100644
--- a/core/src/tbox/src/tbox/utils/base32.h
+++ b/core/src/tbox/src/tbox/utils/base32.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file base32.h
diff --git a/core/src/tbox/src/tbox/utils/base64.c b/core/src/tbox/src/tbox/utils/base64.c
index cb3354a0b..6ed5425d5 100644
--- a/core/src/tbox/src/tbox/utils/base64.c
+++ b/core/src/tbox/src/tbox/utils/base64.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file base64.c
diff --git a/core/src/tbox/src/tbox/utils/base64.h b/core/src/tbox/src/tbox/utils/base64.h
index 13b270b37..609e5b795 100644
--- a/core/src/tbox/src/tbox/utils/base64.h
+++ b/core/src/tbox/src/tbox/utils/base64.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file base.h
diff --git a/core/src/tbox/src/tbox/utils/bits.c b/core/src/tbox/src/tbox/utils/bits.c
index dc67fee9b..6643290d0 100644
--- a/core/src/tbox/src/tbox/utils/bits.c
+++ b/core/src/tbox/src/tbox/utils/bits.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file bits.c
diff --git a/core/src/tbox/src/tbox/utils/bits.h b/core/src/tbox/src/tbox/utils/bits.h
index 933a3c4c9..a2abefd0d 100644
--- a/core/src/tbox/src/tbox/utils/bits.h
+++ b/core/src/tbox/src/tbox/utils/bits.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file bits.h
diff --git a/core/src/tbox/src/tbox/utils/dump.c b/core/src/tbox/src/tbox/utils/dump.c
index 9929e800a..52fc63b95 100644
--- a/core/src/tbox/src/tbox/utils/dump.c
+++ b/core/src/tbox/src/tbox/utils/dump.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file dump.c
diff --git a/core/src/tbox/src/tbox/utils/dump.h b/core/src/tbox/src/tbox/utils/dump.h
index 37f2e83b9..ac80c1485 100644
--- a/core/src/tbox/src/tbox/utils/dump.h
+++ b/core/src/tbox/src/tbox/utils/dump.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file dump.h
diff --git a/core/src/tbox/src/tbox/utils/impl/bits_arm.h b/core/src/tbox/src/tbox/utils/impl/bits_arm.h
index b02261aa6..90f45a3de 100644
--- a/core/src/tbox/src/tbox/utils/impl/bits_arm.h
+++ b/core/src/tbox/src/tbox/utils/impl/bits_arm.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file bits_arm.h
diff --git a/core/src/tbox/src/tbox/utils/impl/bits_gcc.h b/core/src/tbox/src/tbox/utils/impl/bits_gcc.h
index b78b955d5..0564ba0a6 100644
--- a/core/src/tbox/src/tbox/utils/impl/bits_gcc.h
+++ b/core/src/tbox/src/tbox/utils/impl/bits_gcc.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file bits_gcc.h
diff --git a/core/src/tbox/src/tbox/utils/impl/bits_sh4.h b/core/src/tbox/src/tbox/utils/impl/bits_sh4.h
index 3aaeff504..6f2014ee8 100644
--- a/core/src/tbox/src/tbox/utils/impl/bits_sh4.h
+++ b/core/src/tbox/src/tbox/utils/impl/bits_sh4.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file bits_sh4.h
diff --git a/core/src/tbox/src/tbox/utils/impl/bits_x86.h b/core/src/tbox/src/tbox/utils/impl/bits_x86.h
index 353e44876..f36f93150 100644
--- a/core/src/tbox/src/tbox/utils/impl/bits_x86.h
+++ b/core/src/tbox/src/tbox/utils/impl/bits_x86.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file bits_x86.h
diff --git a/core/src/tbox/src/tbox/utils/impl/impl.h b/core/src/tbox/src/tbox/utils/impl/impl.h
index 4c884bfee..cf11864a9 100644
--- a/core/src/tbox/src/tbox/utils/impl/impl.h
+++ b/core/src/tbox/src/tbox/utils/impl/impl.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file impl.h
diff --git a/core/src/tbox/src/tbox/utils/impl/prefix.h b/core/src/tbox/src/tbox/utils/impl/prefix.h
index 5130498bc..d538313e0 100644
--- a/core/src/tbox/src/tbox/utils/impl/prefix.h
+++ b/core/src/tbox/src/tbox/utils/impl/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/utils/lock_profiler.c b/core/src/tbox/src/tbox/utils/lock_profiler.c
index abcee8fcf..c348d5dfe 100644
--- a/core/src/tbox/src/tbox/utils/lock_profiler.c
+++ b/core/src/tbox/src/tbox/utils/lock_profiler.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file lock_profiler.c
diff --git a/core/src/tbox/src/tbox/utils/lock_profiler.h b/core/src/tbox/src/tbox/utils/lock_profiler.h
index 7023100ac..d13227c76 100644
--- a/core/src/tbox/src/tbox/utils/lock_profiler.h
+++ b/core/src/tbox/src/tbox/utils/lock_profiler.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file lock_profiler.h
diff --git a/core/src/tbox/src/tbox/utils/option.c b/core/src/tbox/src/tbox/utils/option.c
index 8b17fd6b2..4dc1250ee 100644
--- a/core/src/tbox/src/tbox/utils/option.c
+++ b/core/src/tbox/src/tbox/utils/option.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file option.c
@@ -75,8 +75,8 @@ static __tb_inline__ tb_bool_t tb_option_is_integer(tb_char_t const* data)
// init
tb_char_t const* p = data;
- // skip '-'
- if (*p == '-') p++;
+ // skip '-' & '+'
+ if (*p == '-' || *p == '+') p++;
// walk
for (; *p && tb_isdigit(*p); p++);
diff --git a/core/src/tbox/src/tbox/utils/option.h b/core/src/tbox/src/tbox/utils/option.h
index 0981d37cc..e8b3228ea 100644
--- a/core/src/tbox/src/tbox/utils/option.h
+++ b/core/src/tbox/src/tbox/utils/option.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file option.h
diff --git a/core/src/tbox/src/tbox/utils/prefix.h b/core/src/tbox/src/tbox/utils/prefix.h
index 12e600f2d..8b6bfd657 100644
--- a/core/src/tbox/src/tbox/utils/prefix.h
+++ b/core/src/tbox/src/tbox/utils/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/utils/singleton.c b/core/src/tbox/src/tbox/utils/singleton.c
index 22e0032b7..e5067e4cd 100644
--- a/core/src/tbox/src/tbox/utils/singleton.c
+++ b/core/src/tbox/src/tbox/utils/singleton.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file singleton.c
diff --git a/core/src/tbox/src/tbox/utils/singleton.h b/core/src/tbox/src/tbox/utils/singleton.h
index 32f8c601b..6c76f357d 100644
--- a/core/src/tbox/src/tbox/utils/singleton.h
+++ b/core/src/tbox/src/tbox/utils/singleton.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file singleton.h
diff --git a/core/src/tbox/src/tbox/utils/trace.c b/core/src/tbox/src/tbox/utils/trace.c
index e24a655f0..0d41d6513 100644
--- a/core/src/tbox/src/tbox/utils/trace.c
+++ b/core/src/tbox/src/tbox/utils/trace.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file trace.c
@@ -128,13 +128,13 @@ tb_bool_t tb_trace_mode_set(tb_size_t mode)
return tb_true;
}
#ifndef TB_CONFIG_MICRO_ENABLE
-tb_handle_t tb_trace_file()
+tb_file_ref_t tb_trace_file()
{
// enter
tb_spinlock_enter_without_profiler(&g_lock);
// the file
- tb_handle_t file = g_file;
+ tb_file_ref_t file = g_file;
// leave
tb_spinlock_leave(&g_lock);
diff --git a/core/src/tbox/src/tbox/utils/trace.h b/core/src/tbox/src/tbox/utils/trace.h
index 437682722..8ca8e9155 100644
--- a/core/src/tbox/src/tbox/utils/trace.h
+++ b/core/src/tbox/src/tbox/utils/trace.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file trace.h
@@ -82,7 +82,7 @@ tb_bool_t tb_trace_mode_set(tb_size_t mode);
*
* @return the trace file handle
*/
-tb_handle_t tb_trace_file(tb_noarg_t);
+tb_file_ref_t tb_trace_file(tb_noarg_t);
/*! set the trace file
*
diff --git a/core/src/tbox/src/tbox/utils/url.c b/core/src/tbox/src/tbox/utils/url.c
index 7a65bfc37..54e6aaa01 100644
--- a/core/src/tbox/src/tbox/utils/url.c
+++ b/core/src/tbox/src/tbox/utils/url.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file url.c
diff --git a/core/src/tbox/src/tbox/utils/url.h b/core/src/tbox/src/tbox/utils/url.h
index 6226f8553..bdcb7c311 100644
--- a/core/src/tbox/src/tbox/utils/url.h
+++ b/core/src/tbox/src/tbox/utils/url.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file url.h
diff --git a/core/src/tbox/src/tbox/utils/used.c b/core/src/tbox/src/tbox/utils/used.c
index 04d565a55..034f6cc97 100644
--- a/core/src/tbox/src/tbox/utils/used.c
+++ b/core/src/tbox/src/tbox/utils/used.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file used.c
diff --git a/core/src/tbox/src/tbox/utils/used.h b/core/src/tbox/src/tbox/utils/used.h
index 1e18456ff..998164965 100644
--- a/core/src/tbox/src/tbox/utils/used.h
+++ b/core/src/tbox/src/tbox/utils/used.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file used.h
diff --git a/core/src/tbox/src/tbox/utils/utils.h b/core/src/tbox/src/tbox/utils/utils.h
index 0f44ba622..c9d531d54 100644
--- a/core/src/tbox/src/tbox/utils/utils.h
+++ b/core/src/tbox/src/tbox/utils/utils.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file utils.h
diff --git a/core/src/tbox/src/tbox/xmake.lua b/core/src/tbox/src/tbox/xmake.lua
index b21eb34af..d358a1991 100644
--- a/core/src/tbox/src/tbox/xmake.lua
+++ b/core/src/tbox/src/tbox/xmake.lua
@@ -8,7 +8,8 @@ target("tbox")
add_defines("__tb_prefix__=\"tbox\"")
-- set the auto-generated config.h
- set_config_header("$(buildir)/$(plat)/$(arch)/$(mode)/tbox.config.h", {prefix = "TB_CONFIG", version = "1.6.2", buildversion = "%Y%m%d%H%M"})
+ set_configdir("$(buildir)/$(plat)/$(arch)/$(mode)")
+ add_configfiles("tbox.config.h.in")
-- add include directories
add_includedirs("..")
@@ -26,10 +27,10 @@ target("tbox")
add_headerfiles("$(buildir)/$(plat)/$(arch)/$(mode)/tbox.config.h", {prefixdir = "tbox"})
-- add packages
- add_options("zlib", "mysql", "sqlite3", "openssl", "polarssl", "mbedtls", "pcre2", "pcre")
+ add_packages("mbedtls", "polarssl", "openssl", "pcre2", "pcre", "zlib", "mysql", "sqlite3")
-- add options
- add_options("info", "float", "wchar", "exception", "deprecated")
+ add_options("info", "float", "wchar", "exception")
-- add modules
add_options("xml", "zip", "hash", "regex", "coroutine", "object", "charset", "database")
@@ -43,7 +44,7 @@ target("tbox")
add_files("prefix/**.c")
add_files("memory/**.c")
add_files("string/**.c")
- add_files("stream/**.c|**/charset.c|**/zip.c|deprecated/**.c")
+ add_files("stream/**.c|**/charset.c|**/zip.c")
add_files("network/**.c|impl/ssl/*.c")
add_files("algorithm/**.c")
add_files("container/**.c|element/obj.c")
@@ -72,17 +73,6 @@ target("tbox")
end
end
- -- add the source files for the asio module
- if has_config("deprecated") then
- add_files("asio/deprecated/*.c|ssl.c")
- add_files("stream/deprecated/**async_**.c")
- add_files("stream/deprecated/transfer_pool.c")
- add_files("platform/deprecated/aicp.c")
- add_files("platform/deprecated/aioo.c")
- add_files("platform/deprecated/aiop.c")
- if has_config("openssl", "polarssl", "mbedtls") then add_files("asio/deprecated/ssl.c") end
- end
-
-- add the source files for the coroutine module
if has_config("coroutine") then
add_files("platform/context.c")
@@ -132,17 +122,18 @@ target("tbox")
-- add the source files for the database module
if has_config("database") then
add_files("database/*.c")
- if has_config("mysql") then add_files("database/impl/mysql.c") end
- if has_config("sqlite3") then add_files("database/impl/sqlite3.c") end
+ if has_package("mysql") then add_files("database/impl/mysql.c") end
+ if has_package("sqlite3") then add_files("database/impl/sqlite3.c") end
end
-- add the source files for the ssl package
- if has_config("mbedtls") then add_files("network/impl/ssl/mbedtls.c")
- elseif has_config("polarssl") then add_files("network/impl/ssl/polarssl.c")
- elseif has_config("openssl") then add_files("network/impl/ssl/openssl.c") end
+ if has_package("mbedtls") then add_files("network/impl/ssl/mbedtls.c")
+ elseif has_package("polarssl") then add_files("network/impl/ssl/polarssl.c")
+ elseif has_package("openssl") then add_files("network/impl/ssl/openssl.c") end
-- add the source for the windows
if is_os("windows") then
+ add_files("platform/windows/iocp_object.c")
add_files("platform/windows/socket_pool.c")
add_files("platform/windows/interface/*.c")
end
diff --git a/core/src/tbox/src/tbox/xml/node.c b/core/src/tbox/src/tbox/xml/node.c
new file mode 100644
index 000000000..89471f2b6
--- /dev/null
+++ b/core/src/tbox/src/tbox/xml/node.c
@@ -0,0 +1,466 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
+ *
+ * @author ruki
+ * @file node.c
+ * @ingroup xml
+ *
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * trace
+ */
+#define TB_TRACE_MODULE_NAME "xml"
+#define TB_TRACE_MODULE_DEBUG (1)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "node.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * implementation
+ */
+tb_xml_node_ref_t tb_xml_node_init_element(tb_char_t const* name)
+{
+ // check
+ tb_assert_and_check_return_val(name, tb_null);
+
+ // make node
+ tb_xml_node_ref_t node = (tb_xml_node_ref_t)tb_malloc0_type(tb_xml_element_t);
+ tb_assert_and_check_return_val(node, tb_null);
+
+ // init
+ node->type = TB_XML_NODE_TYPE_ELEMENT;
+ tb_string_init(&node->name);
+ tb_string_init(&node->data);
+ tb_string_cstrcpy(&node->name, name);
+
+ // ok
+ return node;
+}
+tb_xml_node_ref_t tb_xml_node_init_text(tb_char_t const* data)
+{
+ // make node
+ tb_xml_node_ref_t node = (tb_xml_node_ref_t)tb_malloc0_type(tb_xml_text_t);
+ tb_assert_and_check_return_val(node, tb_null);
+
+ // init
+ node->type = TB_XML_NODE_TYPE_TEXT;
+ tb_string_init(&node->name);
+ tb_string_init(&node->data);
+ tb_string_cstrcpy(&node->name, "#text");
+ if (data) tb_string_cstrcpy(&node->data, data);
+
+ // ok
+ return node;
+}
+tb_xml_node_ref_t tb_xml_node_init_cdata(tb_char_t const* cdata)
+{
+ // make node
+ tb_xml_node_ref_t node = (tb_xml_node_ref_t)tb_malloc0_type(tb_xml_cdata_t);
+ tb_assert_and_check_return_val(node, tb_null);
+
+ // init
+ node->type = TB_XML_NODE_TYPE_CDATA;
+ tb_string_init(&node->name);
+ tb_string_init(&node->data);
+ tb_string_cstrcpy(&node->name, "#cdata");
+ if (cdata) tb_string_cstrcpy(&node->data, cdata);
+
+ // ok
+ return node;
+}
+tb_xml_node_ref_t tb_xml_node_init_comment(tb_char_t const* comment)
+{
+ // make node
+ tb_xml_node_ref_t node = (tb_xml_node_ref_t)tb_malloc0_type(tb_xml_comment_t);
+ tb_assert_and_check_return_val(node, tb_null);
+
+ // init
+ node->type = TB_XML_NODE_TYPE_COMMENT;
+ tb_string_init(&node->name);
+ tb_string_init(&node->data);
+ tb_string_cstrcpy(&node->name, "#comment");
+ if (comment) tb_string_cstrcpy(&node->data, comment);
+
+ // ok
+ return node;
+}
+tb_xml_node_ref_t tb_xml_node_init_attribute(tb_char_t const* name, tb_char_t const* data)
+{
+ // make node
+ tb_xml_node_ref_t node = (tb_xml_node_ref_t)tb_malloc0_type(tb_xml_attribute_t);
+ tb_assert_and_check_return_val(node, tb_null);
+
+ // init
+ node->type = TB_XML_NODE_TYPE_ATTRIBUTE;
+ tb_string_init(&node->name);
+ tb_string_init(&node->data);
+ if (name) tb_string_cstrcpy(&node->name, name);
+ if (data) tb_string_cstrcpy(&node->data, data);
+
+ // ok
+ return node;
+}
+tb_xml_node_ref_t tb_xml_node_init_document(tb_char_t const* version, tb_char_t const* charset)
+{
+ // make node
+ tb_xml_node_ref_t node = (tb_xml_node_ref_t)tb_malloc0_type(tb_xml_document_t);
+ tb_assert_and_check_return_val(node, tb_null);
+
+ // init
+ node->type = TB_XML_NODE_TYPE_DOCUMENT;
+ tb_string_init(&node->name);
+ tb_string_init(&node->data);
+ tb_string_init(&((tb_xml_document_t*)node)->version);
+ tb_string_init(&((tb_xml_document_t*)node)->charset);
+ tb_string_cstrcpy(&node->name, "#document");
+ tb_string_cstrcpy(&((tb_xml_document_t*)node)->version, version? version : "2.0");
+ tb_string_cstrcpy(&((tb_xml_document_t*)node)->charset, charset? charset : "utf-8");
+
+ // ok
+ return node;
+}
+tb_xml_node_ref_t tb_xml_node_init_document_type(tb_char_t const* type)
+{
+ // make node
+ tb_xml_node_ref_t node = (tb_xml_node_ref_t)tb_malloc0_type(tb_xml_document_type_t);
+ tb_assert_and_check_return_val(node, tb_null);
+
+ // init
+ node->type = TB_XML_NODE_TYPE_DOCUMENT_TYPE;
+ tb_string_init(&node->name);
+ tb_string_init(&node->data);
+ tb_string_init(&((tb_xml_document_type_t*)node)->type);
+ tb_string_cstrcpy(&node->name, "#doctype");
+ tb_string_cstrcpy(&((tb_xml_document_type_t*)node)->type, type? type : "");
+
+ // ok
+ return node;
+}
+tb_void_t tb_xml_node_exit(tb_xml_node_ref_t node)
+{
+ if (node)
+ {
+ // free name & data
+ tb_string_exit(&node->name);
+ tb_string_exit(&node->data);
+
+ // free version & charset for document
+ if (node->type == TB_XML_NODE_TYPE_DOCUMENT)
+ {
+ tb_string_exit(&((tb_xml_document_t*)node)->version);
+ tb_string_exit(&((tb_xml_document_t*)node)->charset);
+ }
+
+ // free type
+ if (node->type == TB_XML_NODE_TYPE_DOCUMENT_TYPE)
+ tb_string_exit(&((tb_xml_document_type_t*)node)->type);
+
+ // free childs
+ if (node->chead)
+ {
+ tb_xml_node_ref_t save = tb_null;
+ tb_xml_node_ref_t next = node->chead;
+ while (next)
+ {
+ // save
+ save = next->next;
+
+ // exit
+ tb_xml_node_exit(next);
+
+ // next
+ next = save;
+ }
+ }
+
+ // free attributes
+ if (node->ahead)
+ {
+ tb_xml_node_ref_t save = tb_null;
+ tb_xml_node_ref_t next = node->ahead;
+ while (next)
+ {
+ // save
+ save = next->next;
+
+ // exit
+ tb_xml_node_exit(next);
+
+ // next
+ next = save;
+ }
+ }
+
+ // free it
+ tb_free(node);
+ }
+}
+tb_xml_node_ref_t tb_xml_node_chead(tb_xml_node_ref_t node)
+{
+ // check
+ tb_assert_and_check_return_val(node, tb_null);
+
+ // get it
+ return node->chead;
+}
+tb_size_t tb_xml_node_csize(tb_xml_node_ref_t node)
+{
+ // check
+ tb_assert_and_check_return_val(node, 0);
+
+ // get it
+ return node->csize;
+}
+tb_xml_node_ref_t tb_xml_node_ahead(tb_xml_node_ref_t node)
+{
+ // check
+ tb_assert_and_check_return_val(node, tb_null);
+
+ // get it
+ return node->ahead;
+}
+tb_size_t tb_xml_node_asize(tb_xml_node_ref_t node)
+{
+ // check
+ tb_assert_and_check_return_val(node, 0);
+
+ // get it
+ return node->asize;
+}
+tb_void_t tb_xml_node_insert_next(tb_xml_node_ref_t node, tb_xml_node_ref_t next)
+{
+ // check
+ tb_assert_and_check_return(node && next);
+
+ // init
+ next->parent = node->parent;
+ next->next = node->next;
+
+ // next
+ node->next = next;
+}
+tb_void_t tb_xml_node_remove_next(tb_xml_node_ref_t node)
+{
+ // check
+ tb_assert_and_check_return(node);
+
+ // next
+ tb_xml_node_ref_t next = node->next;
+
+ // save
+ tb_xml_node_ref_t save = next? next->next : tb_null;
+
+ // exit
+ if (next) tb_xml_node_exit(next);
+
+ // next
+ node->next = save;
+}
+tb_void_t tb_xml_node_append_chead(tb_xml_node_ref_t node, tb_xml_node_ref_t child)
+{
+ // check
+ tb_assert_and_check_return(node && child);
+
+ // init
+ child->parent = node;
+
+ // append
+ if (node->chead)
+ {
+ child->next = node->chead;
+ node->chead = child;
+ node->csize++;
+ }
+ else
+ {
+ tb_assert(!node->ctail);
+ node->ctail = node->chead = child;
+ node->csize = 1;
+ }
+}
+tb_void_t tb_xml_node_append_ctail(tb_xml_node_ref_t node, tb_xml_node_ref_t child)
+{
+ // check
+ tb_assert_and_check_return(node && child);
+
+ // init
+ child->parent = node;
+ child->next = tb_null;
+
+ // append
+ if (node->ctail)
+ {
+ node->ctail->next = child;
+ node->ctail = child;
+ node->csize++;
+ }
+ else
+ {
+ tb_assert(!node->chead);
+ node->ctail = node->chead = child;
+ node->csize = 1;
+ }
+}
+tb_void_t tb_xml_node_remove_chead(tb_xml_node_ref_t node)
+{
+ // check
+ tb_assert_and_check_return(node);
+
+ // null?
+ tb_check_return(node->chead);
+
+ // remove
+ if (node->chead != node->ctail)
+ {
+ // save
+ tb_xml_node_ref_t save = node->chead;
+
+ // remove
+ node->chead = save->next;
+
+ // exit
+ tb_xml_node_exit(save);
+
+ // size--
+ node->csize--;
+ }
+ else
+ {
+ // save
+ tb_xml_node_ref_t save = node->chead;
+
+ // remove
+ node->chead = tb_null;
+ node->ctail = tb_null;
+
+ // exit
+ tb_xml_node_exit(save);
+
+ // size--
+ node->csize--;
+ }
+}
+tb_void_t tb_xml_node_remove_ctail(tb_xml_node_ref_t node)
+{
+ tb_trace_noimpl();
+}
+tb_void_t tb_xml_node_append_ahead(tb_xml_node_ref_t node, tb_xml_node_ref_t attribute)
+{
+ // check
+ tb_assert_and_check_return(node && attribute);
+
+ // init
+ attribute->parent = node;
+
+ // append
+ if (node->ahead)
+ {
+ attribute->next = node->ahead;
+ node->ahead = attribute;
+ node->asize++;
+ }
+ else
+ {
+ tb_assert(!node->atail);
+ node->atail = node->ahead = attribute;
+ node->asize = 1;
+ }
+}
+tb_void_t tb_xml_node_append_atail(tb_xml_node_ref_t node, tb_xml_node_ref_t attribute)
+{
+ // check
+ tb_assert_and_check_return(node && attribute);
+
+ // init
+ attribute->parent = node;
+ attribute->next = tb_null;
+
+ // append
+ if (node->atail)
+ {
+ node->atail->next = attribute;
+ node->atail = attribute;
+ node->asize++;
+ }
+ else
+ {
+ tb_assert(!node->ahead);
+ node->atail = node->ahead = attribute;
+ node->asize = 1;
+ }
+}
+tb_xml_node_ref_t tb_xml_node_goto(tb_xml_node_ref_t node, tb_char_t const* path)
+{
+ // check
+ tb_assert_and_check_return_val(node && path, tb_null);
+
+ // trace
+ tb_trace_d("root: %s goto: %s", tb_string_cstr(&node->name), path);
+
+ // skip '/'
+ tb_char_t const* p = path; while (*p && *p == '/') p++;
+
+ // is self?
+ if (!*p) return node;
+
+ // size
+ tb_size_t n = tb_strlen(p);
+
+ // walk the child nodes
+ tb_xml_node_ref_t head = node->chead;
+ for (node = head; node; node = node->next)
+ {
+ if (node->type == TB_XML_NODE_TYPE_ELEMENT)
+ {
+ // size
+ tb_size_t m = tb_string_size(&node->name);
+
+ // trace
+ tb_trace_d("%s", tb_string_cstr(&node->name));
+
+ // has it?
+ if (!tb_string_cstrncmp(&node->name, p, m))
+ {
+ // is it?
+ if (m == n) return node;
+ else if (m < n)
+ {
+ // skip this node
+ tb_char_t const* q = p + m;
+
+ // is root?
+ if (*q == '/')
+ {
+ // goto the child node
+ tb_xml_node_ref_t c = tb_xml_node_goto(node, q);
+ if (c) return c;
+ }
+ }
+ }
+ }
+ }
+
+ // no
+ return tb_null;
+}
+
diff --git a/core/src/tbox/src/tbox/xml/node.h b/core/src/tbox/src/tbox/xml/node.h
new file mode 100644
index 000000000..c44cea6b6
--- /dev/null
+++ b/core/src/tbox/src/tbox/xml/node.h
@@ -0,0 +1,333 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
+ *
+ * @author ruki
+ * @file node.h
+ * @ingroup xml
+ *
+ */
+#ifndef TB_XML_NODE_H
+#define TB_XML_NODE_H
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "prefix.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_enter__
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * types
+ */
+
+/*! the xml node type
+ *
+ * @note see http://www.w3.org/TR/REC-DOM-Level-1/
+ *
+ */
+typedef enum __tb_xml_node_type_t
+{
+ TB_XML_NODE_TYPE_NONE = 0
+, TB_XML_NODE_TYPE_ELEMENT = 1
+, TB_XML_NODE_TYPE_ATTRIBUTE = 2
+, TB_XML_NODE_TYPE_TEXT = 3
+, TB_XML_NODE_TYPE_CDATA = 4
+, TB_XML_NODE_TYPE_ENTITY_REFERENCE = 5
+, TB_XML_NODE_TYPE_ENTITY = 6
+, TB_XML_NODE_TYPE_PROCESSING_INSTRUCTION = 7
+, TB_XML_NODE_TYPE_COMMENT = 8
+, TB_XML_NODE_TYPE_DOCUMENT = 9
+, TB_XML_NODE_TYPE_DOCUMENT_TYPE = 10
+, TB_XML_NODE_TYPE_DOCUMENT_FRAGMENT = 11
+, TB_XML_NODE_TYPE_NOTATION = 12
+
+}tb_xml_node_type_t;
+
+/// the xml node
+typedef struct __tb_xml_node_t
+{
+ /// the node type
+ tb_size_t type;
+
+ /// the node name
+ tb_string_t name;
+
+ /// the node data
+ tb_string_t data;
+
+ /// the next
+ struct __tb_xml_node_t* next;
+
+ /// the childs head
+ struct __tb_xml_node_t* chead;
+
+ /// the childs tail
+ struct __tb_xml_node_t* ctail;
+
+ /// the childs size
+ tb_size_t csize;
+
+ /// the attributes head
+ struct __tb_xml_node_t* ahead;
+
+ /// the attributes tail
+ struct __tb_xml_node_t* atail;
+
+ /// the attributes size
+ tb_size_t asize;
+
+ /// the parent
+ struct __tb_xml_node_t* parent;
+
+}tb_xml_node_t;
+
+/// the xml element type
+typedef struct __tb_xml_element_t
+{
+ /// the node base
+ tb_xml_node_t base;
+
+}tb_xml_element_t;
+
+/// the xml text type
+typedef struct __tb_xml_text_t
+{
+ /// the node base
+ tb_xml_node_t base;
+
+}tb_xml_text_t;
+
+/// the xml cdata type
+typedef struct __tb_xml_cdata_t
+{
+ /// the node base
+ tb_xml_node_t base;
+
+}tb_xml_cdata_t;
+
+/// the xml comment type
+typedef struct __tb_xml_comment_t
+{
+ /// the node base
+ tb_xml_node_t base;
+
+}tb_xml_comment_t;
+
+/*! the xml attribute type
+ *
+ * <pre>
+ * inherit node,
+ * but since they are not actually child nodes of the element they describe,
+ * the DOM does not consider them part of the document tree.
+ * </pre>
+ */
+typedef struct __tb_xml_attribute_t
+{
+ /// the node base
+ tb_xml_node_t base;
+
+}tb_xml_attribute_t;
+
+/// the xml document type
+typedef struct __tb_xml_document_t
+{
+ /// the node base
+ tb_xml_node_t base;
+
+ /// the version
+ tb_string_t version;
+
+ /// the charset
+ tb_string_t charset;
+
+}tb_xml_document_t;
+
+/// the xml document type type
+typedef struct __tb_xml_document_type_t
+{
+ /// the node base
+ tb_xml_node_t base;
+
+ /// the type
+ tb_string_t type;
+
+}tb_xml_document_type_t;
+
+/// the xml node ref type
+typedef tb_xml_node_t* tb_xml_node_ref_t;
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * interfaces
+ */
+
+/*! init element node
+ *
+ * @param name the element name
+ * @return the element node
+ */
+tb_xml_node_ref_t tb_xml_node_init_element(tb_char_t const* name);
+
+/*! init text node
+ *
+ * @param data the element text
+ * @return the element node
+ */
+tb_xml_node_ref_t tb_xml_node_init_text(tb_char_t const* data);
+
+/*! init cdata node
+ *
+ * @param cdata the element cdata
+ * @return the element node
+ */
+tb_xml_node_ref_t tb_xml_node_init_cdata(tb_char_t const* cdata);
+
+/*! init comment node
+ *
+ * @param comment the element comment
+ * @return the element node
+ */
+tb_xml_node_ref_t tb_xml_node_init_comment(tb_char_t const* comment);
+
+/*! init attribute node
+ *
+ * @param name the attribute name
+ * @param data the attribute data
+ * @return the element node
+ */
+tb_xml_node_ref_t tb_xml_node_init_attribute(tb_char_t const* name, tb_char_t const* data);
+
+/*! init document node
+ *
+ * @param version the xml version
+ * @param encoding the xml encoding
+ * @return the element node
+ */
+tb_xml_node_ref_t tb_xml_node_init_document(tb_char_t const* version, tb_char_t const* encoding);
+
+/*! init document type node
+ *
+ * @param type the document type
+ * @return the element node
+ */
+tb_xml_node_ref_t tb_xml_node_init_document_type(tb_char_t const* type);
+
+/*! exit the xml node
+ *
+ * @param node the element node
+ */
+tb_void_t tb_xml_node_exit(tb_xml_node_ref_t node);
+
+/*! goto node by the gived path
+ *
+ * @param node the root node
+ * @return the goto node
+ */
+tb_xml_node_ref_t tb_xml_node_goto(tb_xml_node_ref_t node, tb_char_t const* path);
+
+/*! the xml childs head node
+ *
+ * @param node the xml node
+ * @return the xml childs head node
+ */
+tb_xml_node_ref_t tb_xml_node_chead(tb_xml_node_ref_t node);
+
+/*! the xml childs count
+ *
+ * @param node the xml node
+ * @return the xml childs count
+ */
+tb_size_t tb_xml_node_csize(tb_xml_node_ref_t node);
+
+/*! the xml attributes head node
+ *
+ * @param node the xml node
+ * @return the xml attributes head node
+ */
+tb_xml_node_ref_t tb_xml_node_ahead(tb_xml_node_ref_t node);
+
+/*! the xml attributes count
+ *
+ * @param node the xml node
+ * @return the xml attributes count
+ */
+tb_size_t tb_xml_node_asize(tb_xml_node_ref_t node);
+
+/*! insert to the next node
+ *
+ * @param node the xml node
+ * @param next the xml next node
+ */
+tb_void_t tb_xml_node_insert_next(tb_xml_node_ref_t node, tb_xml_node_ref_t next);
+
+/*! remove the next node
+ *
+ * @param node the xml node
+ */
+tb_void_t tb_xml_node_remove_next(tb_xml_node_ref_t node);
+
+/*! append the node to the childs head
+ *
+ * @param node the xml node
+ * @param child the xml child node
+ */
+tb_void_t tb_xml_node_append_chead(tb_xml_node_ref_t node, tb_xml_node_ref_t child);
+
+/*! append the node to the childs tail
+ *
+ * @param node the xml node
+ * @param child the xml child node
+ */
+tb_void_t tb_xml_node_append_ctail(tb_xml_node_ref_t node, tb_xml_node_ref_t child);
+
+/*! remove the node from the childs head
+ *
+ * @param node the xml node
+ */
+tb_void_t tb_xml_node_remove_chead(tb_xml_node_ref_t node);
+
+/*! remove the node from the childs tail
+ *
+ * @param node the xml node
+ */
+tb_void_t tb_xml_node_remove_ctail(tb_xml_node_ref_t node);
+
+/*! append the node to the attributes head
+ *
+ * @param node the xml node
+ * @param attribute the xml attribute node
+ */
+tb_void_t tb_xml_node_append_ahead(tb_xml_node_ref_t node, tb_xml_node_ref_t attribute);
+
+/*! append the node to the attributes tail
+ *
+ * @param node the xml node
+ * @param attribute the xml attribute node
+ */
+tb_void_t tb_xml_node_append_atail(tb_xml_node_ref_t node, tb_xml_node_ref_t attribute);
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_leave__
+
+#endif
diff --git a/core/src/tbox/src/tbox/xml/prefix.h b/core/src/tbox/src/tbox/xml/prefix.h
new file mode 100644
index 000000000..85349e26e
--- /dev/null
+++ b/core/src/tbox/src/tbox/xml/prefix.h
@@ -0,0 +1,41 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
+ *
+ * @author ruki
+ * @file prefix.h
+ *
+ */
+#ifndef TB_XML_PREFIX_H
+#define TB_XML_PREFIX_H
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "../prefix.h"
+#include "../libc/libc.h"
+#include "../utils/utils.h"
+#include "../stream/stream.h"
+#include "../string/string.h"
+#include "../memory/memory.h"
+#include "../platform/platform.h"
+#include "../container/container.h"
+
+
+#endif
diff --git a/core/src/tbox/src/tbox/xml/reader.c b/core/src/tbox/src/tbox/xml/reader.c
new file mode 100644
index 000000000..5c316c1a4
--- /dev/null
+++ b/core/src/tbox/src/tbox/xml/reader.c
@@ -0,0 +1,928 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
+ *
+ * @author ruki
+ * @file reader.c
+ * @ingroup xml
+ *
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * trace
+ */
+#define TB_TRACE_MODULE_NAME "xml"
+#define TB_TRACE_MODULE_DEBUG (0)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "reader.h"
+#include "../charset/charset.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * macros
+ */
+
+#ifdef __tb_small__
+# define TB_XML_READER_ATTRIBUTES_MAXN (64)
+#else
+# define TB_XML_READER_ATTRIBUTES_MAXN (128)
+#endif
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * types
+ */
+
+// the xml reader impl type
+typedef struct __tb_xml_reader_impl_t
+{
+ // the event
+ tb_size_t event;
+
+ // the level
+ tb_size_t level;
+
+ // is bowner of the input stream?
+ tb_bool_t bowner;
+
+ // the input stream
+ tb_stream_ref_t istream;
+
+ // the filter stream
+ tb_stream_ref_t fstream;
+
+ // the reader stream
+ tb_stream_ref_t rstream;
+
+ // the version
+ tb_string_t version;
+
+ // the charset
+ tb_string_t charset;
+
+ // the element
+ tb_string_t element;
+
+ // the element name
+ tb_string_t element_name;
+
+ // the text
+ tb_string_t text;
+
+ // the attribute name
+ tb_string_t attribute_name;
+
+ // the attribute data
+ tb_string_t attribute_data;
+
+ // the attributes
+ tb_xml_attribute_t attributes[TB_XML_READER_ATTRIBUTES_MAXN];
+
+}tb_xml_reader_impl_t;
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * parser implementation
+ */
+static tb_char_t const* tb_xml_reader_element_parse(tb_xml_reader_impl_t* reader)
+{
+ // clear element
+ tb_string_clear(&reader->element);
+
+ // parse element
+ tb_char_t ch = '\0';
+ tb_size_t in = 0;
+ while (tb_stream_bread_s8(reader->rstream, (tb_sint8_t*)&ch))
+ {
+ // append element
+ if (!in && ch == '<') in = 1;
+ else if (in)
+ {
+ if (ch != '>') tb_string_chrcat(&reader->element, ch);
+ else return tb_string_cstr(&reader->element);
+ }
+ }
+
+ // failed
+ tb_assertf(0, "invalid element: %s from %s", tb_string_cstr(&reader->element), tb_url_cstr(tb_stream_url(reader->istream)));
+ return tb_null;
+}
+static tb_char_t const* tb_xml_reader_text_parse(tb_xml_reader_impl_t* reader)
+{
+ // clear text
+ tb_string_clear(&reader->text);
+
+ // parse text
+ tb_char_t* pc = tb_null;
+ while (tb_stream_need(reader->rstream, (tb_byte_t**)&pc, 1) && pc)
+ {
+ // is end? </ ..>
+ if (pc[0] == '<') return tb_string_cstr(&reader->text);
+ else
+ {
+ tb_string_chrcat(&reader->text, *pc);
+ if (!tb_stream_skip(reader->rstream, 1)) return tb_null;
+ }
+ }
+ return tb_null;
+}
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * implementation
+ */
+tb_xml_reader_ref_t tb_xml_reader_init()
+{
+ // init reader
+ tb_xml_reader_impl_t* reader = tb_malloc0_type(tb_xml_reader_impl_t);
+ tb_assert_and_check_return_val(reader, tb_null);
+
+ // init string
+ tb_string_init(&reader->text);
+ tb_string_init(&reader->version);
+ tb_string_init(&reader->charset);
+ tb_string_init(&reader->element);
+ tb_string_init(&reader->element_name);
+ tb_string_init(&reader->attribute_name);
+ tb_string_init(&reader->attribute_data);
+ tb_string_cstrcpy(&reader->version, "2.0");
+ tb_string_cstrcpy(&reader->charset, "utf-8");
+
+ // init attributes
+ tb_size_t i = 0;
+ for (i = 0; i < TB_XML_READER_ATTRIBUTES_MAXN; i++)
+ {
+ tb_xml_node_ref_t node = (tb_xml_node_ref_t)(reader->attributes + i);
+ tb_string_init(&node->name);
+ tb_string_init(&node->data);
+ }
+
+ // ok
+ return (tb_xml_reader_ref_t)reader;
+}
+tb_void_t tb_xml_reader_exit(tb_xml_reader_ref_t reader)
+{
+ // check
+ tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader;
+ tb_assert_and_check_return(impl);
+
+ // clos it first
+ tb_xml_reader_clos(reader);
+
+ // exit the filter stream
+ if (impl->fstream) tb_stream_exit(impl->fstream);
+
+ // exit text
+ tb_string_exit(&impl->text);
+
+ // exit version
+ tb_string_exit(&impl->version);
+
+ // exit charset
+ tb_string_exit(&impl->charset);
+
+ // exit element
+ tb_string_exit(&impl->element);
+
+ // exit element name
+ tb_string_exit(&impl->element_name);
+
+ // exit attribute name
+ tb_string_exit(&impl->attribute_name);
+
+ // exit attribute data
+ tb_string_exit(&impl->attribute_data);
+
+ // exit attributes
+ tb_long_t i = 0;
+ for (i = 0; i < TB_XML_READER_ATTRIBUTES_MAXN; i++)
+ {
+ tb_xml_node_ref_t node = (tb_xml_node_ref_t)(impl->attributes + i);
+ tb_string_exit(&node->name);
+ tb_string_exit(&node->data);
+ }
+
+ // free it
+ tb_free(impl);
+}
+tb_bool_t tb_xml_reader_open(tb_xml_reader_ref_t reader, tb_stream_ref_t stream, tb_bool_t bowner)
+{
+ // check
+ tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader;
+ tb_assert_and_check_return_val(impl && stream, tb_false);
+
+ // done
+ tb_bool_t ok = tb_false;
+ do
+ {
+ // check
+ tb_assert_and_check_break(!impl->rstream && !impl->istream);
+
+ // init level
+ impl->level = 0;
+
+ // init owner
+ impl->bowner = bowner;
+
+ // init the input stream
+ impl->istream = stream;
+
+ // init the reader stream
+ impl->rstream = stream;
+
+ // open the reader stream if be not opened
+ if (!tb_stream_is_opened(impl->rstream) && !tb_stream_open(impl->rstream)) break;
+
+ // clear text
+ tb_string_clear(&impl->text);
+
+ // clear element
+ tb_string_clear(&impl->element);
+
+ // clear name
+ tb_string_clear(&impl->element_name);
+
+ // clear attribute name
+ tb_string_clear(&impl->attribute_name);
+
+ // clear attribute data
+ tb_string_clear(&impl->attribute_data);
+
+ // clear attributes
+ tb_long_t i = 0;
+ for (i = 0; i < TB_XML_READER_ATTRIBUTES_MAXN; i++)
+ {
+ tb_xml_node_ref_t node = (tb_xml_node_ref_t)(impl->attributes + i);
+ tb_string_clear(&node->name);
+ tb_string_clear(&node->data);
+ }
+
+ // ok
+ ok = tb_true;
+
+ } while (0);
+
+ // failed? close it
+ if (!ok) tb_xml_reader_clos(reader);
+
+ // ok?
+ return ok;
+}
+tb_void_t tb_xml_reader_clos(tb_xml_reader_ref_t reader)
+{
+ // check
+ tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader;
+ tb_assert_and_check_return(impl);
+
+ // clos the reader stream
+ if (impl->rstream) tb_stream_clos(impl->rstream);
+ impl->rstream = tb_null;
+
+ // exit the input stream
+ if (impl->istream && impl->bowner) tb_stream_exit(impl->istream);
+ impl->istream = tb_null;
+
+ // clear level
+ impl->level = 0;
+
+ // clear owner
+ impl->bowner = tb_false;
+
+ // clear text
+ tb_string_clear(&impl->text);
+
+ // clear element
+ tb_string_clear(&impl->element);
+
+ // clear name
+ tb_string_clear(&impl->element_name);
+
+ // clear attribute name
+ tb_string_clear(&impl->attribute_name);
+
+ // clear attribute data
+ tb_string_clear(&impl->attribute_data);
+
+ // clear attributes
+ tb_long_t i = 0;
+ for (i = 0; i < TB_XML_READER_ATTRIBUTES_MAXN; i++)
+ {
+ tb_xml_node_ref_t node = (tb_xml_node_ref_t)(impl->attributes + i);
+ tb_string_clear(&node->name);
+ tb_string_clear(&node->data);
+ }
+}
+tb_stream_ref_t tb_xml_reader_stream(tb_xml_reader_ref_t reader)
+{
+ // check
+ tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader;
+ tb_assert_and_check_return_val(impl, tb_null);
+
+ return impl->rstream;
+}
+tb_size_t tb_xml_reader_level(tb_xml_reader_ref_t reader)
+{
+ // check
+ tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader;
+ tb_assert_and_check_return_val(impl, 0);
+
+ return impl->level;
+}
+tb_size_t tb_xml_reader_next(tb_xml_reader_ref_t reader)
+{
+ // check
+ tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader;
+ tb_assert_and_check_return_val(impl && impl->rstream, TB_XML_READER_EVENT_NONE);
+
+ // reset event
+ impl->event = TB_XML_READER_EVENT_NONE;
+
+ // next
+ while (!impl->event)
+ {
+ // peek character
+ tb_char_t* pc = tb_null;
+ if (!tb_stream_need(impl->rstream, (tb_byte_t**)&pc, 1) || !pc) break;
+
+ // is element?
+ if (*pc == '<')
+ {
+ // parse element: <...>
+ tb_char_t const* element = tb_xml_reader_element_parse(impl);
+ tb_assert_and_check_break(element);
+
+ // is document begin: <?xml version="..." charset=".." ?>
+ tb_size_t size = tb_string_size(&impl->element);
+ if (size > 4 && !tb_strnicmp(element, "?xml", 4))
+ {
+ // update event
+ impl->event = TB_XML_READER_EVENT_DOCUMENT;
+
+ // update version & charset
+ tb_xml_node_ref_t attr = (tb_xml_node_ref_t)tb_xml_reader_attributes(reader);
+ for (; attr; attr = attr->next)
+ {
+ if (!tb_string_cstricmp(&attr->name, "version")) tb_string_strcpy(&impl->version, &attr->data);
+ if (!tb_string_cstricmp(&attr->name, "encoding")) tb_string_strcpy(&impl->charset, &attr->data);
+ }
+
+ // transform stream => utf-8
+ if (tb_string_cstricmp(&impl->charset, "utf-8") && tb_string_cstricmp(&impl->charset, "utf8"))
+ {
+ // charset
+ tb_size_t charset = TB_CHARSET_TYPE_UTF8;
+ if (!tb_string_cstricmp(&impl->charset, "gb2312") || !tb_string_cstricmp(&impl->charset, "gbk"))
+ charset = TB_CHARSET_TYPE_GB2312;
+ else tb_trace_e("the charset: %s is not supported", tb_string_cstr(&impl->charset));
+
+ // init transform stream
+ if (charset != TB_CHARSET_TYPE_UTF8)
+ {
+#ifdef TB_CONFIG_MODULE_HAVE_CHARSET
+ // init the filter stream
+ if (!impl->fstream) impl->fstream = tb_stream_init_filter_from_charset(impl->istream, charset, TB_CHARSET_TYPE_UTF8);
+ else
+ {
+ // ctrl stream
+ if (!tb_stream_ctrl(impl->fstream, TB_STREAM_CTRL_FLTR_SET_STREAM, impl->istream)) break;
+
+ // the filter
+ tb_filter_ref_t filter = tb_null;
+ if (!tb_stream_ctrl(impl->fstream, TB_STREAM_CTRL_FLTR_GET_FILTER, &filter)) break;
+ tb_assert_and_check_break(filter);
+
+ // ctrl filter
+ if (!tb_filter_ctrl(filter, TB_FILTER_CTRL_CHARSET_SET_FTYPE, charset)) break;
+ }
+
+ // open the filter stream
+ if (impl->fstream && tb_stream_open(impl->fstream))
+ impl->rstream = impl->fstream;
+ tb_string_cstrcpy(&impl->charset, "utf-8");
+#else
+ // trace
+ tb_trace_e("unicode type is not supported, please enable charset module config if you want to use it!");
+#endif
+ }
+ }
+ }
+ // is document type: <!DOCTYPE ... >
+ else if (size > 8 && !tb_strnicmp(element, "!DOCTYPE", 8))
+ {
+ // update event
+ impl->event = TB_XML_READER_EVENT_DOCUMENT_TYPE;
+ }
+ // is element end: </name>
+ else if (size > 1 && element[0] == '/')
+ {
+ // check
+ tb_check_break(impl->level);
+
+ // update event
+ impl->event = TB_XML_READER_EVENT_ELEMENT_END;
+
+ // leave
+ impl->level--;
+ }
+ // is comment: <!-- text -->
+ else if (size >= 3 && !tb_strncmp(element, "!--", 3))
+ {
+ // no comment end?
+ if (element[size - 2] != '-' || element[size - 1] != '-')
+ {
+ // patch '>'
+ tb_string_chrcat(&impl->element, '>');
+
+ // seek to comment end
+ tb_char_t ch = '\0';
+ tb_int_t n = 0;
+ while (tb_stream_bread_s8(impl->rstream, (tb_sint8_t*)&ch))
+ {
+ // -->
+ if (n == 2 && ch == '>') break;
+ else
+ {
+ // append it
+ tb_string_chrcat(&impl->element, ch);
+
+ if (ch == '-') n++;
+ else n = 0;
+ }
+ }
+
+ // update event
+ if (ch != '\0') impl->event = TB_XML_READER_EVENT_COMMENT;
+ }
+ else impl->event = TB_XML_READER_EVENT_COMMENT;
+ }
+ // is cdata: <![CDATA[ text ]]>
+ else if (size >= 8 && !tb_strnicmp(element, "![CDATA[", 8))
+ {
+ if (element[size - 2] != ']' || element[size - 1] != ']')
+ {
+ // patch '>'
+ tb_string_chrcat(&impl->element, '>');
+
+ // seek to cdata end
+ tb_char_t ch = '\0';
+ tb_int_t n = 0;
+ while (tb_stream_bread_s8(impl->rstream, (tb_sint8_t*)&ch))
+ {
+ // ]]>
+ if (n == 2 && ch == '>') break;
+ else
+ {
+ // append it
+ tb_string_chrcat(&impl->element, ch);
+
+ if (ch == ']') n++;
+ else n = 0;
+ }
+ }
+
+ // update event
+ if (ch != '\0') impl->event = TB_XML_READER_EVENT_CDATA;
+ }
+ else impl->event = TB_XML_READER_EVENT_CDATA;
+ }
+ // is empty element: <name/>
+ else if (size > 1 && element[size - 1] == '/')
+ {
+ // update event
+ impl->event = TB_XML_READER_EVENT_ELEMENT_EMPTY;
+ }
+ // is element begin: <name>
+ else
+ {
+ // update event
+ impl->event = TB_XML_READER_EVENT_ELEMENT_BEG;
+
+ // enter
+ impl->level++;
+ }
+
+ // trace
+ tb_trace_d("<%s>", element);
+ }
+ // is text: <> text </>
+ else if (*pc)
+ {
+ // parse text: <> ... <>
+ tb_char_t const* text = tb_xml_reader_text_parse(impl);
+ if (text && tb_string_cstrcmp(&impl->text, "\r\n") && tb_string_cstrcmp(&impl->text, "\n"))
+ impl->event = TB_XML_READER_EVENT_TEXT;
+
+ // trace
+ tb_trace_d("%s", text);
+ }
+ else
+ {
+ // skip the invalid character
+ if (!tb_stream_skip(impl->rstream, 1)) break;
+ }
+ }
+
+ // ok?
+ return impl->event;
+}
+tb_bool_t tb_xml_reader_goto(tb_xml_reader_ref_t reader, tb_char_t const* path)
+{
+ // check
+ tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader;
+ tb_assert_and_check_return_val(impl && impl->rstream && path, tb_false);
+
+ // trace
+ tb_trace_d("goto: %s", path);
+
+ // init level
+ impl->level = 0;
+
+ // seek to the stream head
+ if (!tb_stream_seek(impl->rstream, 0)) return tb_false;
+
+ // init
+ tb_static_string_t s;
+ tb_char_t data[8192];
+ if (!tb_static_string_init(&s, data, 8192)) return tb_false;
+
+ // save the current offset
+ tb_hize_t save = tb_stream_offset(impl->rstream);
+
+ // done
+ tb_bool_t ok = tb_false;
+ tb_bool_t leave = tb_false;
+ tb_size_t event = TB_XML_READER_EVENT_NONE;
+ while (!leave && !ok && (event = tb_xml_reader_next(reader)))
+ {
+ switch (event)
+ {
+ case TB_XML_READER_EVENT_ELEMENT_EMPTY:
+ {
+ // name
+ tb_char_t const* name = tb_xml_reader_element(reader);
+ tb_assert_and_check_break_state(name, leave, tb_true);
+
+ // append
+ tb_size_t n = tb_static_string_size(&s);
+ tb_static_string_chrcat(&s, '/');
+ tb_static_string_cstrcat(&s, name);
+
+ // ok?
+ if (!tb_static_string_cstricmp(&s, path)) ok = tb_true;
+
+ // trace
+ tb_trace_d("path: %s", tb_static_string_cstr(&s));
+
+ // remove
+ tb_static_string_strip(&s, n);
+
+ // restore
+ if (ok) if (!(ok = tb_stream_seek(impl->rstream, save))) leave = tb_true;
+ }
+ break;
+ case TB_XML_READER_EVENT_ELEMENT_BEG:
+ {
+ // name
+ tb_char_t const* name = tb_xml_reader_element(reader);
+ tb_assert_and_check_break_state(name, leave, tb_true);
+
+ // append
+ tb_static_string_chrcat(&s, '/');
+ tb_static_string_cstrcat(&s, name);
+
+ // ok?
+ if (!tb_static_string_cstricmp(&s, path)) ok = tb_true;
+
+ // trace
+ tb_trace_d("path: %s", tb_static_string_cstr(&s));
+
+ // restore
+ if (ok) if (!(ok = tb_stream_seek(impl->rstream, save))) leave = tb_true;
+ }
+ break;
+ case TB_XML_READER_EVENT_ELEMENT_END:
+ {
+ // remove
+ tb_long_t p = tb_static_string_strrchr(&s, 0, '/');
+ if (p >= 0) tb_static_string_strip(&s, p);
+
+ // ok?
+ if (!tb_static_string_cstricmp(&s, path)) ok = tb_true;
+
+ // trace
+ tb_trace_d("path: %s", tb_static_string_cstr(&s));
+
+ // restore
+ if (ok) if (!(ok = tb_stream_seek(impl->rstream, save))) leave = tb_true;
+ }
+ break;
+ default:
+ break;
+ }
+
+ // save
+ save = tb_stream_offset(impl->rstream);
+ }
+
+ // exit string
+ tb_static_string_exit(&s);
+
+ // clear level
+ impl->level = 0;
+
+ // failed? restore to the stream head
+ if (!ok) tb_stream_seek(impl->rstream, 0);
+
+ // ok?
+ return ok;
+}
+tb_xml_node_ref_t tb_xml_reader_load(tb_xml_reader_ref_t reader)
+{
+ // check
+ tb_assert_and_check_return_val(reader, tb_null);
+
+ // done
+ tb_bool_t ok = tb_true;
+ tb_xml_node_ref_t node = tb_null;
+ tb_size_t event = TB_XML_READER_EVENT_NONE;
+ while (ok && (event = tb_xml_reader_next(reader)))
+ {
+ // init document node
+ if (!node)
+ {
+ node = tb_xml_node_init_document(tb_xml_reader_version(reader), tb_xml_reader_charset(reader));
+ tb_assert_and_check_break_state(node && !node->parent, ok, tb_false);
+ }
+
+ switch (event)
+ {
+ case TB_XML_READER_EVENT_DOCUMENT:
+ break;
+ case TB_XML_READER_EVENT_DOCUMENT_TYPE:
+ {
+ // init
+ tb_xml_node_ref_t doctype = tb_xml_node_init_document_type(tb_xml_reader_doctype(reader));
+ tb_assert_and_check_break_state(doctype, ok, tb_false);
+
+ // append
+ tb_xml_node_append_ctail(node, doctype);
+ tb_assert_and_check_break_state(doctype->parent, ok, tb_false);
+ }
+ break;
+ case TB_XML_READER_EVENT_ELEMENT_EMPTY:
+ {
+ // init
+ tb_xml_node_ref_t element = tb_xml_node_init_element(tb_xml_reader_element(reader));
+ tb_assert_and_check_break_state(element, ok, tb_false);
+
+ // attributes
+ tb_xml_node_ref_t attr = tb_xml_reader_attributes(reader);
+ for (; attr; attr = attr->next)
+ tb_xml_node_append_atail(element, tb_xml_node_init_attribute(tb_string_cstr(&attr->name), tb_string_cstr(&attr->data)));
+
+ // append
+ tb_xml_node_append_ctail(node, element);
+ tb_assert_and_check_break_state(element->parent, ok, tb_false);
+ }
+ break;
+ case TB_XML_READER_EVENT_ELEMENT_BEG:
+ {
+ // init
+ tb_xml_node_ref_t element = tb_xml_node_init_element(tb_xml_reader_element(reader));
+ tb_assert_and_check_break_state(element, ok, tb_false);
+
+ // attributes
+ tb_xml_node_ref_t attr = tb_xml_reader_attributes(reader);
+ for (; attr; attr = attr->next)
+ tb_xml_node_append_atail(element, tb_xml_node_init_attribute(tb_string_cstr(&attr->name), tb_string_cstr(&attr->data)));
+
+ // append
+ tb_xml_node_append_ctail(node, element);
+ tb_assert_and_check_break_state(element->parent, ok, tb_false);
+
+ // enter
+ node = element;
+ }
+ break;
+ case TB_XML_READER_EVENT_ELEMENT_END:
+ {
+ // check
+ tb_assert_and_check_break_state(node, ok, tb_false);
+
+ // the parent node
+ node = node->parent;
+ }
+ break;
+ case TB_XML_READER_EVENT_TEXT:
+ {
+ // init
+ tb_xml_node_ref_t text = tb_xml_node_init_text(tb_xml_reader_text(reader));
+ tb_assert_and_check_break_state(text, ok, tb_false);
+
+ // append
+ tb_xml_node_append_ctail(node, text);
+ tb_assert_and_check_break_state(text->parent, ok, tb_false);
+ }
+ break;
+ case TB_XML_READER_EVENT_CDATA:
+ {
+ // init
+ tb_xml_node_ref_t cdata = tb_xml_node_init_cdata(tb_xml_reader_cdata(reader));
+ tb_assert_and_check_break_state(cdata, ok, tb_false);
+
+ // append
+ tb_xml_node_append_ctail(node, cdata);
+ tb_assert_and_check_break_state(cdata->parent, ok, tb_false);
+
+ }
+ break;
+ case TB_XML_READER_EVENT_COMMENT:
+ {
+ // init
+ tb_xml_node_ref_t comment = tb_xml_node_init_comment(tb_xml_reader_comment(reader));
+ tb_assert_and_check_break_state(comment, ok, tb_false);
+
+ // append
+ tb_xml_node_append_ctail(node, comment);
+ tb_assert_and_check_break_state(comment->parent, ok, tb_false);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ // failed?
+ if (!ok)
+ {
+ // exit it
+ if (node) tb_xml_node_exit(node);
+ node = tb_null;
+ }
+
+ // ok
+ return node;
+}
+tb_char_t const* tb_xml_reader_version(tb_xml_reader_ref_t reader)
+{
+ // check
+ tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader;
+ tb_assert_and_check_return_val(impl, tb_null);
+
+ // text
+ return tb_string_cstr(&impl->version);
+}
+tb_char_t const* tb_xml_reader_charset(tb_xml_reader_ref_t reader)
+{
+ // check
+ tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader;
+ tb_assert_and_check_return_val(impl, tb_null);
+
+ // text
+ return tb_string_cstr(&impl->charset);
+}
+tb_char_t const* tb_xml_reader_comment(tb_xml_reader_ref_t reader)
+{
+ // check
+ tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader;
+ tb_assert_and_check_return_val(impl && impl->event == TB_XML_READER_EVENT_COMMENT, tb_null);
+
+ // init
+ tb_char_t const* p = tb_string_cstr(&impl->element);
+ tb_size_t n = tb_string_size(&impl->element);
+ tb_assert_and_check_return_val(p && n >= 6, tb_null);
+
+ // comment
+ tb_string_cstrncpy(&impl->text, p + 3, n - 5);
+ return tb_string_cstr(&impl->text);
+}
+tb_char_t const* tb_xml_reader_cdata(tb_xml_reader_ref_t reader)
+{
+ // check
+ tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader;
+ tb_assert_and_check_return_val(impl && impl->event == TB_XML_READER_EVENT_CDATA, tb_null);
+
+ // init
+ tb_char_t const* p = tb_string_cstr(&impl->element);
+ tb_size_t n = tb_string_size(&impl->element);
+ tb_assert_and_check_return_val(p && n >= 11, tb_null);
+
+ // comment
+ tb_string_cstrncpy(&impl->text, p + 8, n - 10);
+ return tb_string_cstr(&impl->text);
+}
+tb_char_t const* tb_xml_reader_text(tb_xml_reader_ref_t reader)
+{
+ // check
+ tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader;
+ tb_assert_and_check_return_val(impl && impl->event == TB_XML_READER_EVENT_TEXT, tb_null);
+
+ // text
+ return tb_string_cstr(&impl->text);
+}
+tb_char_t const* tb_xml_reader_element(tb_xml_reader_ref_t reader)
+{
+ // check
+ tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader;
+ tb_assert_and_check_return_val(impl && ( impl->event == TB_XML_READER_EVENT_ELEMENT_BEG
+ || impl->event == TB_XML_READER_EVENT_ELEMENT_END
+ || impl->event == TB_XML_READER_EVENT_ELEMENT_EMPTY), tb_null);
+
+ // init
+ tb_char_t const* p = tb_null;
+ tb_char_t const* b = tb_string_cstr(&impl->element);
+ tb_char_t const* e = b + tb_string_size(&impl->element);
+ tb_assert_and_check_return_val(b, tb_null);
+
+ // </name> or <name ... />
+ if (b < e && *b == '/') b++;
+ for (p = b; p < e && *p && !tb_isspace(*p) && *p != '/'; p++) ;
+
+ // ok?
+ return p > b? tb_string_cstrncpy(&impl->element_name, b, p - b) : tb_null;
+}
+tb_char_t const* tb_xml_reader_doctype(tb_xml_reader_ref_t reader)
+{
+ // check
+ tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader;
+ tb_assert_and_check_return_val(impl && impl->event == TB_XML_READER_EVENT_DOCUMENT_TYPE, tb_null);
+
+ // doctype
+ tb_char_t const* p = tb_string_cstr(&impl->element);
+ tb_assert_and_check_return_val(p, tb_null);
+
+ // skip !DOCTYPE
+ return (p + 9);
+}
+tb_xml_node_ref_t tb_xml_reader_attributes(tb_xml_reader_ref_t reader)
+{
+ // check
+ tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader;
+ tb_assert_and_check_return_val(impl && ( impl->event == TB_XML_READER_EVENT_DOCUMENT
+ || impl->event == TB_XML_READER_EVENT_ELEMENT_BEG
+ || impl->event == TB_XML_READER_EVENT_ELEMENT_END
+ || impl->event == TB_XML_READER_EVENT_ELEMENT_EMPTY), tb_null);
+
+ // init
+ tb_char_t const* p = tb_string_cstr(&impl->element);
+ tb_char_t const* e = p + tb_string_size(&impl->element);
+
+ // skip name
+ while (p < e && *p && !tb_isspace(*p)) p++;
+ while (p < e && *p && tb_isspace(*p)) p++;
+
+ // parse attributes
+ tb_size_t n = 0;
+ while (p < e)
+ {
+ // parse name
+ tb_string_clear(&impl->attribute_name);
+ for (; p < e && *p != '='; p++) if (!tb_isspace(*p)) tb_string_chrcat(&impl->attribute_name, *p);
+ if (*p != '=') break;
+
+ // parse data
+ tb_string_clear(&impl->attribute_data);
+ for (p++; p < e && (*p != '\'' && *p != '\"'); p++) ;
+ if (*p != '\'' && *p != '\"') break;
+ for (p++; p < e && (*p != '\'' && *p != '\"'); p++) tb_string_chrcat(&impl->attribute_data, *p);
+ if (*p != '\'' && *p != '\"') break;
+ p++;
+
+ // append node
+ if (tb_string_cstr(&impl->attribute_name) && tb_string_cstr(&impl->attribute_data))
+ {
+ // node
+ tb_xml_node_ref_t prev = n > 0? (tb_xml_node_ref_t)&impl->attributes[n - 1] : tb_null;
+ tb_xml_node_ref_t node = (tb_xml_node_ref_t)&impl->attributes[n];
+
+ // init node
+ tb_string_strcpy(&node->name, &impl->attribute_name);
+ tb_string_strcpy(&node->data, &impl->attribute_data);
+
+ // append node
+ if (prev) prev->next = node;
+ node->next = tb_null;
+
+ // next
+ n++;
+ }
+ }
+
+ // ok?
+ return n? (tb_xml_node_ref_t)&impl->attributes[0] : tb_null;
+}
diff --git a/core/src/tbox/src/tbox/xml/reader.h b/core/src/tbox/src/tbox/xml/reader.h
new file mode 100644
index 000000000..527923001
--- /dev/null
+++ b/core/src/tbox/src/tbox/xml/reader.h
@@ -0,0 +1,298 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
+ *
+ * @author ruki
+ * @file reader.h
+ * @ingroup xml
+ *
+ */
+#ifndef TB_XML_READER_H
+#define TB_XML_READER_H
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "prefix.h"
+#include "node.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_enter__
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * types
+ */
+
+/// the xml reader event type for iterator
+typedef enum __tb_xml_reader_event_t
+{
+ TB_XML_READER_EVENT_NONE = 0
+, TB_XML_READER_EVENT_DOCUMENT_TYPE = 1
+, TB_XML_READER_EVENT_DOCUMENT = 2
+, TB_XML_READER_EVENT_ELEMENT_BEG = 3
+, TB_XML_READER_EVENT_ELEMENT_END = 4
+, TB_XML_READER_EVENT_ELEMENT_EMPTY = 5
+, TB_XML_READER_EVENT_COMMENT = 6
+, TB_XML_READER_EVENT_TEXT = 7
+, TB_XML_READER_EVENT_CDATA = 8
+
+}tb_xml_reader_event_t;
+
+/// the xml reader ref type
+typedef __tb_typeref__(xml_reader);
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * interfaces
+ */
+
+/*! init the xml reader
+ *
+ * @return the reader
+ */
+tb_xml_reader_ref_t tb_xml_reader_init(tb_noarg_t);
+
+/*! exit the xml reader
+ *
+ * @param reader the xml reader
+ */
+tb_void_t tb_xml_reader_exit(tb_xml_reader_ref_t reader);
+
+/*! open the xml reader
+ *
+ * @param reader the xml reader
+ * @param stream the stream, will open it if be not opened
+ * @param bowner the xml reader is owner of the stream?
+ *
+ * @return tb_true or tb_false
+ */
+tb_bool_t tb_xml_reader_open(tb_xml_reader_ref_t reader, tb_stream_ref_t stream, tb_bool_t bowner);
+
+/*! clos the xml reader
+ *
+ * @param reader the xml reader
+ */
+tb_void_t tb_xml_reader_clos(tb_xml_reader_ref_t reader);
+
+/*! the next iterator for the xml reader
+ *
+ * @param reader the xml reader
+ * @return the iterator event
+ *
+ * @code
+ *
+ // 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("<?xml version = \"%s\" encoding = \"%s\" ?>\n"
+ , tb_xml_reader_version(reader), tb_xml_reader_charset(reader));
+ }
+ break;
+ case TB_XML_READER_EVENT_DOCUMENT_TYPE:
+ {
+ tb_printf("<!DOCTYPE>\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("<![CDATA[%s]]>", 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("<!--%s-->", tb_xml_reader_comment(reader));
+ tb_printf("\n");
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ // exit reader
+ tb_xml_reader_exit(reader);
+ }
+
+ * @endcode
+ */
+tb_size_t tb_xml_reader_next(tb_xml_reader_ref_t reader);
+
+/*! the xml stream
+ *
+ * @param reader the xml reader
+ * @return the xml stream
+ */
+tb_stream_ref_t tb_xml_reader_stream(tb_xml_reader_ref_t reader);
+
+/*! the xml level
+ *
+ * @param reader the xml reader
+ * @return the xml level for tab spaces
+ */
+tb_size_t tb_xml_reader_level(tb_xml_reader_ref_t reader);
+
+/*! seek to the given node for xml, .e.g /root/node/item
+ *
+ * @param reader the reader handle
+ * @param path the xml path
+ * @return tb_true or tb_false
+ *
+ * @note the stream will be reseted
+ */
+tb_bool_t tb_xml_reader_goto(tb_xml_reader_ref_t reader, tb_char_t const* path);
+
+/*! load the xml
+ *
+ * @param reader the xml reader
+ * @return the xml root node
+ */
+tb_xml_node_ref_t tb_xml_reader_load(tb_xml_reader_ref_t reader);
+
+/*! the xml version
+ *
+ * @param reader the xml reader
+ * @return the xml version
+ */
+tb_char_t const* tb_xml_reader_version(tb_xml_reader_ref_t reader);
+
+/*! the xml charset
+ *
+ * @param reader the xml reader
+ * @return the xml charset
+ */
+tb_char_t const* tb_xml_reader_charset(tb_xml_reader_ref_t reader);
+
+/*! the current xml element name
+ *
+ * @param reader the xml reader
+ * @return the current xml element name
+ */
+tb_char_t const* tb_xml_reader_element(tb_xml_reader_ref_t reader);
+
+/*! the current xml node text
+ *
+ * @param reader the xml reader
+ * @return the current xml node text
+ */
+tb_char_t const* tb_xml_reader_text(tb_xml_reader_ref_t reader);
+
+/*! the current xml node cdata
+ *
+ * @param reader the xml reader
+ * @return the current xml node cdata
+ */
+tb_char_t const* tb_xml_reader_cdata(tb_xml_reader_ref_t reader);
+
+/*! the current xml node comment
+ *
+ * @param reader the xml reader
+ * @return the current xml node comment
+ */
+tb_char_t const* tb_xml_reader_comment(tb_xml_reader_ref_t reader);
+
+/*! the xml document type
+ *
+ * @param reader the xml reader
+ * @return the xml document type
+ */
+tb_char_t const* tb_xml_reader_doctype(tb_xml_reader_ref_t reader);
+
+/*! the current xml node attributes
+ *
+ * @param reader the xml reader
+ * @return the current xml node attributes
+ */
+tb_xml_node_ref_t tb_xml_reader_attributes(tb_xml_reader_ref_t reader);
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_leave__
+
+#endif
diff --git a/core/src/tbox/src/tbox/xml/writer.c b/core/src/tbox/src/tbox/xml/writer.c
new file mode 100644
index 000000000..72e3902a9
--- /dev/null
+++ b/core/src/tbox/src/tbox/xml/writer.c
@@ -0,0 +1,497 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
+ *
+ * @author ruki
+ * @file writer.c
+ * @ingroup xml
+ *
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * trace
+ */
+#define TB_TRACE_MODULE_NAME "xml"
+#define TB_TRACE_MODULE_DEBUG (0)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "writer.h"
+#include "../charset/charset.h"
+#include "../algorithm/algorithm.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * macros
+ */
+#ifdef __tb_small__
+# define TB_XML_WRITER_ELEMENTS_GROW (32)
+#else
+# define TB_XML_WRITER_ELEMENTS_GROW (64)
+#endif
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * types
+ */
+
+// the xml writer impl type
+typedef struct __tb_xml_writer_impl_t
+{
+ // stream
+ tb_stream_ref_t stream;
+
+ // is format?
+ tb_bool_t bformat;
+
+ // is owner of the stream?
+ tb_bool_t bowner;
+
+ // the elements stack
+ tb_stack_ref_t elements;
+
+ // the attributes hash
+ tb_hash_map_ref_t attributes;
+
+}tb_xml_writer_impl_t;
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * implementation
+ */
+tb_xml_writer_ref_t tb_xml_writer_init()
+{
+ // done
+ tb_bool_t ok = tb_false;
+ tb_xml_writer_impl_t* writer = tb_null;
+ do
+ {
+ // make writer
+ writer = tb_malloc0_type(tb_xml_writer_impl_t);
+ tb_assert_and_check_break(writer);
+
+ // init elements
+ writer->elements = tb_stack_init(TB_XML_WRITER_ELEMENTS_GROW, tb_element_str(tb_false));
+ tb_assert_and_check_break(writer->elements);
+
+ // init attributes
+ writer->attributes = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_str(tb_false), tb_element_str(tb_false));
+ tb_assert_and_check_break(writer->attributes);
+
+ // ok
+ ok = tb_true;
+
+ } while (0);
+
+ // failed?
+ if (!ok)
+ {
+ // exit it
+ if (writer) tb_xml_writer_exit((tb_xml_writer_ref_t)writer);
+ writer = tb_null;
+ }
+
+ // ok?
+ return (tb_xml_writer_ref_t)writer;
+}
+tb_void_t tb_xml_writer_exit(tb_xml_writer_ref_t writer)
+{
+ // check
+ tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer;
+ tb_assert_and_check_return(impl);
+
+ // clos it first
+ tb_xml_writer_clos(writer);
+
+ // exit attributes
+ if (impl->attributes) tb_hash_map_exit(impl->attributes);
+ impl->attributes = tb_null;
+
+ // exit elements
+ if (impl->elements) tb_stack_exit(impl->elements);
+ impl->elements = tb_null;
+
+ // free it
+ tb_free(impl);
+}
+tb_bool_t tb_xml_writer_open(tb_xml_writer_ref_t writer, tb_bool_t bformat, tb_stream_ref_t stream, tb_bool_t bowner)
+{
+ // check
+ tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer;
+ tb_assert_and_check_return_val(impl && stream, tb_false);
+
+ // done
+ tb_bool_t ok = tb_false;
+ do
+ {
+ // check
+ tb_assert_and_check_break(!impl->stream);
+
+ // init format
+ impl->bformat = bformat;
+
+ // init owner
+ impl->bowner = bowner;
+
+ // init stream
+ impl->stream = stream;
+
+ // ctrl stream
+ if (tb_stream_type(stream) == TB_STREAM_TYPE_FILE)
+ {
+ // ctrl mode
+ if (!tb_stream_ctrl(stream, TB_STREAM_CTRL_FILE_SET_MODE, TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC)) break;
+ }
+
+ // open the reader stream if be not opened
+ if (!tb_stream_is_opened(impl->stream) && !tb_stream_open(impl->stream)) break;
+
+ // ok
+ ok = tb_true;
+
+ } while (0);
+
+ // failed? close it
+ if (!ok) tb_xml_writer_clos(writer);
+
+ // ok?
+ return ok;
+}
+tb_void_t tb_xml_writer_clos(tb_xml_writer_ref_t writer)
+{
+ // check
+ tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer;
+ tb_assert_and_check_return(impl);
+
+ // clos stream
+ if (impl->stream) tb_stream_clos(impl->stream);
+
+ // exit stream
+ if (impl->stream && impl->bowner) tb_stream_exit(impl->stream);
+ impl->stream = tb_null;
+
+ // clear owner
+ impl->bowner = tb_false;
+
+ // clear format
+ impl->bformat = tb_false;
+
+ // clear attributes
+ if (impl->attributes) tb_hash_map_clear(impl->attributes);
+
+ // clear elements
+ if (impl->elements) tb_stack_clear(impl->elements);
+}
+tb_void_t tb_xml_writer_save(tb_xml_writer_ref_t writer, tb_xml_node_ref_t node)
+{
+ // check
+ tb_assert_and_check_return(writer && node);
+
+ // done
+ switch (node->type)
+ {
+ case TB_XML_NODE_TYPE_DOCUMENT:
+ {
+ // document
+ tb_xml_document_t* document = (tb_xml_document_t*)node;
+ tb_xml_writer_document(writer, tb_string_cstr(&document->version), tb_string_cstr(&document->charset));
+
+ // childs
+ tb_xml_node_ref_t next = node->chead;
+ while (next)
+ {
+ // save
+ tb_xml_writer_save(writer, next);
+
+ // next
+ next = next->next;
+ }
+ }
+ break;
+ case TB_XML_NODE_TYPE_DOCUMENT_TYPE:
+ {
+ // document type
+ tb_xml_document_type_t* doctype = (tb_xml_document_type_t*)node;
+ tb_xml_writer_document_type(writer, tb_string_cstr(&doctype->type));
+ }
+ break;
+ case TB_XML_NODE_TYPE_ELEMENT:
+ {
+ // attributes
+ tb_xml_node_ref_t attr = node->ahead;
+ while (attr)
+ {
+ // save
+ tb_xml_writer_attributes_cstr(writer, tb_string_cstr(&attr->name), tb_string_cstr(&attr->data));
+
+ // next
+ attr = attr->next;
+ }
+
+ // childs
+ tb_xml_node_ref_t next = node->chead;
+ if (next)
+ {
+ // enter
+ tb_xml_writer_element_enter(writer, tb_string_cstr(&node->name));
+
+ // init
+ while (next)
+ {
+ // save
+ tb_xml_writer_save(writer, next);
+
+ // next
+ next = next->next;
+ }
+
+ // leave
+ tb_xml_writer_element_leave(writer);
+ }
+ else tb_xml_writer_element_empty(writer, tb_string_cstr(&node->name));
+ }
+ break;
+ case TB_XML_NODE_TYPE_COMMENT:
+ tb_xml_writer_comment(writer, tb_string_cstr(&node->data));
+ break;
+ case TB_XML_NODE_TYPE_CDATA:
+ tb_xml_writer_cdata(writer, tb_string_cstr(&node->data));
+ break;
+ case TB_XML_NODE_TYPE_TEXT:
+ tb_xml_writer_text(writer, tb_string_cstr(&node->data));
+ break;
+ default:
+ break;
+ }
+}
+tb_void_t tb_xml_writer_document(tb_xml_writer_ref_t writer, tb_char_t const* version, tb_char_t const* charset)
+{
+ // check
+ tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer;
+ tb_assert_and_check_return(impl && impl->stream);
+
+ tb_stream_printf(impl->stream, "<?xml version=\"%s\" encoding=\"%s\"?>", version? version : "2.0", charset? charset : "utf-8");
+ if (impl->bformat) tb_stream_printf(impl->stream, "\n");
+}
+tb_void_t tb_xml_writer_document_type(tb_xml_writer_ref_t writer, tb_char_t const* type)
+{
+ // check
+ tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer;
+ tb_assert_and_check_return(impl && impl->stream);
+
+ tb_stream_printf(impl->stream, "<!DOCTYPE %s>", type? type : "");
+ if (impl->bformat) tb_stream_printf(impl->stream, "\n");
+}
+tb_void_t tb_xml_writer_cdata(tb_xml_writer_ref_t writer, tb_char_t const* data)
+{
+ // check
+ tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer;
+ tb_assert_and_check_return(impl && impl->stream && data);
+
+ // writ tabs
+ if (impl->bformat)
+ {
+ tb_size_t t = tb_stack_size(impl->elements);
+ while (t--) tb_stream_printf(impl->stream, "\t");
+ }
+
+ tb_stream_printf(impl->stream, "<![CDATA[%s]]>", data);
+ if (impl->bformat) tb_stream_printf(impl->stream, "\n");
+}
+tb_void_t tb_xml_writer_text(tb_xml_writer_ref_t writer, tb_char_t const* text)
+{
+ // check
+ tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer;
+ tb_assert_and_check_return(impl && impl->stream && text);
+
+ // writ tabs
+ if (impl->bformat)
+ {
+ tb_size_t t = tb_stack_size(impl->elements);
+ while (t--) tb_stream_printf(impl->stream, "\t");
+ }
+
+ tb_stream_printf(impl->stream, "%s", text);
+ if (impl->bformat) tb_stream_printf(impl->stream, "\n");
+}
+tb_void_t tb_xml_writer_comment(tb_xml_writer_ref_t writer, tb_char_t const* comment)
+{
+ // check
+ tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer;
+ tb_assert_and_check_return(impl && impl->stream && comment);
+
+ // writ tabs
+ if (impl->bformat)
+ {
+ tb_size_t t = tb_stack_size(impl->elements);
+ while (t--) tb_stream_printf(impl->stream, "\t");
+ }
+
+ tb_stream_printf(impl->stream, "<!--%s-->", comment);
+ if (impl->bformat) tb_stream_printf(impl->stream, "\n");
+}
+tb_void_t tb_xml_writer_element_empty(tb_xml_writer_ref_t writer, tb_char_t const* name)
+{
+ // check
+ tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer;
+ tb_assert_and_check_return(impl && impl->stream && impl->attributes && name);
+
+ // writ tabs
+ if (impl->bformat)
+ {
+ tb_size_t t = tb_stack_size(impl->elements);
+ while (t--) tb_stream_printf(impl->stream, "\t");
+ }
+
+ // writ name
+ tb_stream_printf(impl->stream, "<%s", name);
+
+ // writ attributes
+ if (tb_hash_map_size(impl->attributes))
+ {
+ tb_for_all (tb_hash_map_item_ref_t, item, impl->attributes)
+ {
+ if (item && item->name && item->data)
+ tb_stream_printf(impl->stream, " %s=\"%s\"", item->name, item->data);
+ }
+ tb_hash_map_clear(impl->attributes);
+ }
+
+ // writ end
+ tb_stream_printf(impl->stream, "/>");
+ if (impl->bformat) tb_stream_printf(impl->stream, "\n");
+}
+tb_void_t tb_xml_writer_element_enter(tb_xml_writer_ref_t writer, tb_char_t const* name)
+{
+ // check
+ tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer;
+ tb_assert_and_check_return(impl && impl->stream && impl->elements && impl->attributes && name);
+
+ // writ tabs
+ if (impl->bformat)
+ {
+ tb_size_t t = tb_stack_size(impl->elements);
+ while (t--) tb_stream_printf(impl->stream, "\t");
+ }
+
+ // writ name
+ tb_stream_printf(impl->stream, "<%s", name);
+
+ // writ attributes
+ if (tb_hash_map_size(impl->attributes))
+ {
+ tb_for_all (tb_hash_map_item_ref_t, item, impl->attributes)
+ {
+ if (item && item->name && item->data)
+ tb_stream_printf(impl->stream, " %s=\"%s\"", item->name, item->data);
+ }
+ tb_hash_map_clear(impl->attributes);
+ }
+
+ // writ end
+ tb_stream_printf(impl->stream, ">");
+ if (impl->bformat) tb_stream_printf(impl->stream, "\n");
+
+ // put name
+ tb_stack_put(impl->elements, name);
+}
+tb_void_t tb_xml_writer_element_leave(tb_xml_writer_ref_t writer)
+{
+ // check
+ tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer;
+ tb_assert_and_check_return(impl && impl->stream && impl->elements && impl->attributes);
+
+ // writ tabs
+ if (impl->bformat)
+ {
+ tb_size_t t = tb_stack_size(impl->elements);
+ if (t) t--;
+ while (t--) tb_stream_printf(impl->stream, "\t");
+ }
+
+ // writ name
+ tb_char_t const* name = (tb_char_t const*)tb_stack_top(impl->elements);
+ tb_assert_and_check_return(name);
+
+ tb_stream_printf(impl->stream, "</%s>", name);
+ if (impl->bformat) tb_stream_printf(impl->stream, "\n");
+
+ // pop name
+ tb_stack_pop(impl->elements);
+}
+tb_void_t tb_xml_writer_attributes_long(tb_xml_writer_ref_t writer, tb_char_t const* name, tb_long_t value)
+{
+ // check
+ tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer;
+ tb_assert_and_check_return(impl && impl->attributes && name);
+
+ tb_char_t data[64] = {0};
+ tb_snprintf(data, 64, "%ld", value);
+ tb_hash_map_insert(impl->attributes, name, data);
+}
+tb_void_t tb_xml_writer_attributes_bool(tb_xml_writer_ref_t writer, tb_char_t const* name, tb_bool_t value)
+{
+ // check
+ tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer;
+ tb_assert_and_check_return(impl && impl->attributes && name);
+
+ tb_char_t data[64] = {0};
+ tb_snprintf(data, 64, "%s", value? "true" : "false");
+ tb_hash_map_insert(impl->attributes, name, data);
+}
+tb_void_t tb_xml_writer_attributes_cstr(tb_xml_writer_ref_t writer, tb_char_t const* name, tb_char_t const* value)
+{
+ // check
+ tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer;
+ tb_assert_and_check_return(impl && impl->attributes && name && value);
+
+ tb_hash_map_insert(impl->attributes, name, value);
+}
+tb_void_t tb_xml_writer_attributes_format(tb_xml_writer_ref_t writer, tb_char_t const* name, tb_char_t const* format, ...)
+{
+ // check
+ tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer;
+ tb_assert_and_check_return(impl && impl->attributes && name && format);
+
+ tb_size_t size = 0;
+ tb_char_t data[8192] = {0};
+ tb_vsnprintf_format(data, 8192, format, &size);
+ tb_hash_map_insert(impl->attributes, name, data);
+}
+#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
+tb_void_t tb_xml_writer_attributes_float(tb_xml_writer_ref_t writer, tb_char_t const* name, tb_float_t value)
+{
+ // check
+ tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer;
+ tb_assert_and_check_return(impl && impl->attributes && name);
+
+ tb_char_t data[64] = {0};
+ tb_snprintf(data, 64, "%f", value);
+ tb_hash_map_insert(impl->attributes, name, data);
+}
+tb_void_t tb_xml_writer_attributes_double(tb_xml_writer_ref_t writer, tb_char_t const* name, tb_double_t value)
+{
+ // check
+ tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer;
+ tb_assert_and_check_return(impl && impl->attributes && name);
+
+ tb_char_t data[64] = {0};
+ tb_snprintf(data, 64, "%lf", value);
+ tb_hash_map_insert(impl->attributes, name, data);
+}
+#endif
+
diff --git a/core/src/tbox/src/tbox/xml/writer.h b/core/src/tbox/src/tbox/xml/writer.h
new file mode 100644
index 000000000..02915e5fe
--- /dev/null
+++ b/core/src/tbox/src/tbox/xml/writer.h
@@ -0,0 +1,198 @@
+/*!The Treasure Box Library
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
+ *
+ * @author ruki
+ * @file writer.h
+ * @ingroup xml
+ *
+ */
+#ifndef TB_XML_WRITER_H
+#define TB_XML_WRITER_H
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "prefix.h"
+#include "node.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_enter__
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * types
+ */
+
+/// the xml writer ref type
+typedef __tb_typeref__(xml_writer);
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * interfaces
+ */
+
+/*! init the xml writer
+ *
+ * @return the writer
+ */
+tb_xml_writer_ref_t tb_xml_writer_init(tb_noarg_t);
+
+/*! exit the xml writer
+ *
+ * @param writer the xml writer
+ */
+tb_void_t tb_xml_writer_exit(tb_xml_writer_ref_t writer);
+
+/*! open the xml writer
+ *
+ * @param writer the xml writer
+ * @param bformat is format xml?
+ * @param stream the stream, will open it if be not opened
+ * @param bowner the xml writer is owner of the stream?
+ *
+ * @return tb_true or tb_false
+ */
+tb_bool_t tb_xml_writer_open(tb_xml_writer_ref_t writer, tb_bool_t bformat, tb_stream_ref_t stream, tb_bool_t bowner);
+
+/*! clos the xml writer
+ *
+ * @param writer the xml writer
+ */
+tb_void_t tb_xml_writer_clos(tb_xml_writer_ref_t writer);
+
+/*! save the xml document or node
+ *
+ * @param writer the xml writer
+ * @param node the xml node
+ */
+tb_void_t tb_xml_writer_save(tb_xml_writer_ref_t writer, tb_xml_node_ref_t node);
+
+/*! writ the xml document node: <?xml version = \"...\" encoding = \"...\" ?>
+ *
+ * @param writer the xml writer
+ * @param version the xml version
+ * @param encoding the xml encoding
+ */
+tb_void_t tb_xml_writer_document(tb_xml_writer_ref_t writer, tb_char_t const* version, tb_char_t const* encoding);
+
+/*! writ the xml document type: <!DOCTYPE type>
+ *
+ * @param writer the xml writer
+ * @param type the xml document type
+ */
+tb_void_t tb_xml_writer_document_type(tb_xml_writer_ref_t writer, tb_char_t const* type);
+
+/*! writ the xml cdata: <![CDATA[...]]>
+ *
+ * @param writer the xml writer
+ * @param data the xml cdata
+ */
+tb_void_t tb_xml_writer_cdata(tb_xml_writer_ref_t writer, tb_char_t const* data);
+
+/*! writ the xml text
+ *
+ * @param writer the xml writer
+ * @param text the xml text
+ */
+tb_void_t tb_xml_writer_text(tb_xml_writer_ref_t writer, tb_char_t const* text);
+
+/*! writ the xml comment: <!-- ... -->
+ *
+ * @param writer the xml writer
+ * @param comment the xml comment
+ */
+tb_void_t tb_xml_writer_comment(tb_xml_writer_ref_t writer, tb_char_t const* comment);
+
+/*! writ the empty xml element: <name/>
+ *
+ * @param writer the xml writer
+ * @param name the xml element name
+ */
+tb_void_t tb_xml_writer_element_empty(tb_xml_writer_ref_t writer, tb_char_t const* name);
+
+/*! writ the xml element head: <name> ...
+ *
+ * @param writer the xml writer
+ * @param name the xml element name
+ */
+tb_void_t tb_xml_writer_element_enter(tb_xml_writer_ref_t writer, tb_char_t const* name);
+
+/*! writ the xml element tail: ... </name>
+ *
+ * @param writer the xml writer
+ */
+tb_void_t tb_xml_writer_element_leave(tb_xml_writer_ref_t writer);
+
+/*! writ the xml attribute for long value
+ *
+ * @param writer the xml writer
+ * @param name the xml attribute name
+ * @param value the xml attribute value
+ */
+tb_void_t tb_xml_writer_attributes_long(tb_xml_writer_ref_t writer, tb_char_t const* name, tb_long_t value);
+
+/*! writ the xml attribute for boolean value
+ *
+ * @param writer the xml writer
+ * @param name the xml attribute name
+ * @param value the xml attribute value
+ */
+tb_void_t tb_xml_writer_attributes_bool(tb_xml_writer_ref_t writer, tb_char_t const* name, tb_bool_t value);
+
+/*! writ the xml attribute for cstr value
+ *
+ * @param writer the xml writer
+ * @param name the xml attribute name
+ * @param value the xml attribute value
+ */
+tb_void_t tb_xml_writer_attributes_cstr(tb_xml_writer_ref_t writer, tb_char_t const* name, tb_char_t const* value);
+
+/*! writ the xml attribute for format value
+ *
+ * @param writer the xml writer
+ * @param name the xml attribute name
+ * @param format the xml attribute format
+ */
+tb_void_t tb_xml_writer_attributes_format(tb_xml_writer_ref_t writer, tb_char_t const* name, tb_char_t const* format, ...);
+
+#ifdef TB_CONFIG_TYPE_HAVE_FLOAT
+/*! writ the xml attribute for float value
+ *
+ * @param writer the xml writer
+ * @param name the xml attribute name
+ * @param value the xml attribute value
+ */
+tb_void_t tb_xml_writer_attributes_float(tb_xml_writer_ref_t writer, tb_char_t const* name, tb_float_t value);
+
+/*! writ the xml attribute for double value
+ *
+ * @param writer the xml writer
+ * @param name the xml attribute name
+ * @param value the xml attribute value
+ */
+tb_void_t tb_xml_writer_attributes_double(tb_xml_writer_ref_t writer, tb_char_t const* name, tb_double_t value);
+#endif
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * extern
+ */
+__tb_extern_c_leave__
+
+#endif
diff --git a/core/src/tbox/src/tbox/stream/deprecated/impl/prefix.h b/core/src/tbox/src/tbox/xml/xml.h
index 34f051bfc..da520a31d 100644
--- a/core/src/tbox/src/tbox/stream/deprecated/impl/prefix.h
+++ b/core/src/tbox/src/tbox/xml/xml.h
@@ -16,18 +16,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
- * @file prefix.h
+ * @file xml.h
+ * @defgroup xml
*
*/
-#ifndef TB_STREAM_DEPRECATED_IMPL_PREFIX_H
-#define TB_STREAM_DEPRECATED_IMPL_PREFIX_H
+#ifndef TB_XML_H
+#define TB_XML_H
/* //////////////////////////////////////////////////////////////////////////////////////
* includes
*/
-#include "../prefix.h"
+#include "prefix.h"
+#include "node.h"
+#include "reader.h"
+#include "writer.h"
#endif
diff --git a/core/src/tbox/src/tbox/zip/gzip.c b/core/src/tbox/src/tbox/zip/gzip.c
index 370d9087b..1b2fa5c45 100644
--- a/core/src/tbox/src/tbox/zip/gzip.c
+++ b/core/src/tbox/src/tbox/zip/gzip.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file gzip.c
diff --git a/core/src/tbox/src/tbox/zip/gzip.h b/core/src/tbox/src/tbox/zip/gzip.h
index bf0189270..4d6db4f9a 100644
--- a/core/src/tbox/src/tbox/zip/gzip.h
+++ b/core/src/tbox/src/tbox/zip/gzip.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file gzip.h
diff --git a/core/src/tbox/src/tbox/zip/prefix.h b/core/src/tbox/src/tbox/zip/prefix.h
index 447e6219c..bf00b0ae3 100644
--- a/core/src/tbox/src/tbox/zip/prefix.h
+++ b/core/src/tbox/src/tbox/zip/prefix.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file prefix.h
diff --git a/core/src/tbox/src/tbox/zip/zip.c b/core/src/tbox/src/tbox/zip/zip.c
index 0db2a2afa..bf048aab1 100644
--- a/core/src/tbox/src/tbox/zip/zip.c
+++ b/core/src/tbox/src/tbox/zip/zip.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file zip.c
diff --git a/core/src/tbox/src/tbox/zip/zip.h b/core/src/tbox/src/tbox/zip/zip.h
index 84e4ffbf1..2af6439ff 100644
--- a/core/src/tbox/src/tbox/zip/zip.h
+++ b/core/src/tbox/src/tbox/zip/zip.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file zip.h
diff --git a/core/src/tbox/src/tbox/zip/zlib.c b/core/src/tbox/src/tbox/zip/zlib.c
index 271b7a0e6..d40704b8d 100644
--- a/core/src/tbox/src/tbox/zip/zlib.c
+++ b/core/src/tbox/src/tbox/zip/zlib.c
@@ -17,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file zlib.c
diff --git a/core/src/tbox/src/tbox/zip/zlib.h b/core/src/tbox/src/tbox/zip/zlib.h
index cea8ca64d..2f65e159e 100644
--- a/core/src/tbox/src/tbox/zip/zlib.h
+++ b/core/src/tbox/src/tbox/zip/zlib.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file zlib.h
diff --git a/core/src/tbox/src/tbox/zip/zlibraw.c b/core/src/tbox/src/tbox/zip/zlibraw.c
index 5f436edca..b2478db43 100644
--- a/core/src/tbox/src/tbox/zip/zlibraw.c
+++ b/core/src/tbox/src/tbox/zip/zlibraw.c
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file zlibraw.c
diff --git a/core/src/tbox/src/tbox/zip/zlibraw.h b/core/src/tbox/src/tbox/zip/zlibraw.h
index bbee7d132..9758400a9 100644
--- a/core/src/tbox/src/tbox/zip/zlibraw.h
+++ b/core/src/tbox/src/tbox/zip/zlibraw.h
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- * Copyright (C) 2009 - 2017, TBOOX Open Source Group.
+ * Copyright (C) 2009 - 2019, TBOOX Open Source Group.
*
* @author ruki
* @file zlibraw.h
diff --git a/core/src/tbox/src/xmake.lua b/core/src/tbox/src/xmake.lua
index 93957f5d9..a2af0d215 100644
--- a/core/src/tbox/src/xmake.lua
+++ b/core/src/tbox/src/xmake.lua
@@ -1,9 +1,12 @@
+includes("check_cfuncs.lua")
+
-- option: demo
option("demo")
- set_default(false)
+ set_default(true)
set_showmenu(true)
set_category("option")
set_description("Enable or disable the demo module")
+option_end()
-- option: micro
option("micro")
@@ -11,7 +14,8 @@ option("micro")
set_showmenu(true)
set_category("option")
set_description("Compile micro core library for the embed system.")
- add_defines_h("$(prefix)_MICRO_ENABLE")
+ set_configvar("TB_CONFIG_MICRO_ENABLE", 1)
+option_end()
-- option: small
option("small")
@@ -19,11 +23,13 @@ option("small")
set_showmenu(true)
set_category("option")
set_description("Enable the small compile mode and disable all modules.")
+option_end()
-- option: wchar
option("wchar")
add_ctypes("wchar_t")
- add_defines_h("$(prefix)_TYPE_HAVE_WCHAR")
+ set_configvar("TB_CONFIG_TYPE_HAVE_WCHAR", 1)
+option_end()
-- option: float
option("float")
@@ -32,12 +38,13 @@ option("float")
set_category("option")
set_description("Enable or disable the float type")
add_deps("micro")
- add_defines_h("$(prefix)_TYPE_HAVE_FLOAT")
+ set_configvar("TB_CONFIG_TYPE_HAVE_FLOAT", 1)
after_check(function (option)
if option:dep("micro"):enabled() then
option:enable(false)
end
end)
+option_end()
-- option: info
option("info")
@@ -46,13 +53,14 @@ option("info")
set_category("option")
set_description("Enable or disable to get some info, .e.g version ..")
add_deps("small", "micro")
- add_defines_h("$(prefix)_INFO_HAVE_VERSION")
- add_defines_h("$(prefix)_INFO_TRACE_MORE")
+ set_configvar("TB_CONFIG_INFO_HAVE_VERSION", 1)
+ set_configvar("TB_CONFIG_INFO_TRACE_MORE", 1)
after_check(function (option)
if option:dep("small"):enabled() or option:dep("micro"):enabled() then
option:enable(false)
end
end)
+option_end()
-- option: exception
option("exception")
@@ -60,7 +68,8 @@ option("exception")
set_showmenu(true)
set_category("option")
set_description("Enable or disable the exception.")
- add_defines_h("$(prefix)_EXCEPTION_ENABLE")
+ set_configvar("TB_CONFIG_EXCEPTION_ENABLE", 1)
+option_end()
-- option: deprecated
option("deprecated")
@@ -68,7 +77,8 @@ option("deprecated")
set_showmenu(true)
set_category("option")
set_description("Enable or disable the deprecated interfaces.")
- add_defines_h("$(prefix)_API_HAVE_DEPRECATED")
+ set_configvar("TB_CONFIG_API_HAVE_DEPRECATED", 1)
+option_end()
-- add modules
for _, name in ipairs({"xml", "zip", "hash", "regex", "object", "charset", "database", "coroutine"}) do
@@ -78,144 +88,185 @@ for _, name in ipairs({"xml", "zip", "hash", "regex", "object", "charset", "data
set_category("module")
set_description(format("The %s module", name))
add_deps("small", "micro")
- add_defines_h(format("$(prefix)_MODULE_HAVE_%s", name:upper()))
+ set_configvar("TB_CONFIG_MODULE_HAVE_" .. name:upper(), 1)
after_check(function (option)
- if (name ~= "hash" and name ~= "charset") and (option:dep("small"):enabled() or option:dep("micro"):enabled()) then
- option:enable(false)
+ if name ~= "hash" and name ~= "charset" then
+ if option:dep("small"):enabled() or option:dep("micro"):enabled() then
+ option:enable(false)
+ end
end
end)
+ option_end()
end
--- the base package
-option("base")
- set_default(true)
- if is_os("windows") then add_links("ws2_32")
- elseif is_os("android") then add_links("m", "c")
- else add_links("pthread", "dl", "m", "c") end
-
--- add packages
+-- define options for package
for _, name in ipairs({"zlib", "mysql", "sqlite3", "openssl", "polarssl", "mbedtls", "pcre2", "pcre"}) do
option(name)
- set_showmenu(true)
- set_category("package")
- set_description(format("The %s package", name))
add_deps("small", "micro")
- add_defines_h(format("$(prefix)_PACKAGE_HAVE_%s", name:upper()))
+ set_default(true)
+ set_showmenu(true)
+ set_description("Enable the " .. name .. " package.")
before_check(function (option)
- import("lib.detect.find_package")
- if not option:dep("small"):enabled() and not option:dep("micro"):enabled() then
- option:add(find_package(name, {packagedirs = path.join(os.projectdir(), "pkg")}))
+ if option:dep("small"):enabled() or option:dep("micro"):enabled() then
+ option:enable(false)
end
end)
+ option_end()
+end
+
+-- add requires
+local groups = {nil, nil, nil, "ssl", "ssl", "ssl", "pcre", "pcre"}
+for idx, require_name in ipairs({"zlib", "sqlite3", "mysql", "mbedtls 2.13.*", "openssl 1.1.*", "polarssl", "pcre2", "pcre"}) do
+ local name = require_name:split('%s')[1]
+ if has_config(name) then
+ add_requires(require_name, {optional = true, group = groups[idx], on_load = function (package)
+ package:set("configvar", {["TB_CONFIG_PACKAGE_HAVE_" .. name:upper()] = 1})
+ end})
+ end
+end
+
+-- get function name
+--
+-- sigsetjmp
+-- sigsetjmp((void*)0, 0)
+-- sigsetjmp{sigsetjmp((void*)0, 0);}
+-- sigsetjmp{int a = 0; sigsetjmp((void*)a, a);}
+--
+function get_function_name(func)
+ local name, code = string.match(func, "(.+){(.+)}")
+ if code == nil then
+ local pos = func:find("%(")
+ if pos then
+ name = func:sub(1, pos - 1)
+ else
+ name = func
+ end
+ end
+ return name:trim()
+end
+
+-- check c functions in the given module
+function check_module_cfuncs(module, includes, ...)
+ for _, func in ipairs({...}) do
+ local funcname = get_function_name(func)
+ configvar_check_cfuncs(("TB_CONFIG_%s_HAVE_%s"):format(module:upper(), funcname:upper()), func, {name = module .. "_" .. funcname, includes = includes})
+ end
end
-- check interfaces
function check_interfaces()
- -- add the interfaces for libc
- add_cfuncs("libc", nil, {"string.h", "stdlib.h"}, "memcpy",
- "memset",
- "memmove",
- "memcmp",
- "memmem",
- "strcat",
- "strncat",
- "strcpy",
- "strncpy",
- "strlcpy",
- "strlen",
- "strnlen",
- "strstr",
- "strcasestr",
- "strcmp",
- "strcasecmp",
- "strncmp",
- "strncasecmp")
- add_cfuncs("libc", nil, {"wchar.h", "stdlib.h"}, "wcscat",
- "wcsncat",
- "wcscpy",
- "wcsncpy",
- "wcslcpy",
- "wcslen",
- "wcsnlen",
- "wcsstr",
- "wcscasestr",
- "wcscmp",
- "wcscasecmp",
- "wcsncmp",
- "wcsncasecmp",
- "wcstombs",
- "mbstowcs")
- add_cfuncs("libc", nil, "time.h", "gmtime", "mktime", "localtime")
- add_cfuncs("libc", nil, "sys/time.h", "gettimeofday")
- add_cfuncs("libc", nil, {"signal.h", "setjmp.h"}, "signal", "setjmp", "sigsetjmp{sigjmp_buf buf; sigsetjmp(buf, 0);}", "kill")
- add_cfuncs("libc", nil, "execinfo.h", "backtrace")
- add_cfuncs("libc", nil, "locale.h", "setlocale")
- add_cfuncs("libc", nil, "stdio.h", "fputs")
- add_cfuncs("libc", nil, "stdlib.h", "srandom", "random")
+ -- check the interfaces for libc
+ check_module_cfuncs("libc", {"string.h", "stdlib.h"},
+ "memcpy",
+ "memset",
+ "memmove",
+ "memcmp",
+ "memmem",
+ "strcat",
+ "strncat",
+ "strcpy",
+ "strncpy",
+ "strlcpy",
+ "strlen",
+ "strnlen",
+ "strstr",
+ "strcasestr",
+ "strcmp",
+ "strcasecmp",
+ "strncmp",
+ "strncasecmp")
+ check_module_cfuncs("libc", {"wchar.h", "stdlib.h"},
+ "wcscat",
+ "wcsncat",
+ "wcscpy",
+ "wcsncpy",
+ "wcslcpy",
+ "wcslen",
+ "wcsnlen",
+ "wcsstr",
+ "wcscasestr",
+ "wcscmp",
+ "wcscasecmp",
+ "wcsncmp",
+ "wcsncasecmp",
+ "wcstombs",
+ "mbstowcs")
+ check_module_cfuncs("libc", "time.h", "gmtime", "mktime", "localtime")
+ check_module_cfuncs("libc", "sys/time.h", "gettimeofday")
+ check_module_cfuncs("libc", {"signal.h", "setjmp.h"}, "signal", "setjmp", "sigsetjmp{sigjmp_buf buf; sigsetjmp(buf, 0);}", "kill")
+ check_module_cfuncs("libc", "execinfo.h", "backtrace")
+ check_module_cfuncs("libc", "locale.h", "setlocale")
+ check_module_cfuncs("libc", "stdio.h", "fputs")
+ check_module_cfuncs("libc", "stdlib.h", "srandom", "random")
-- add the interfaces for libm
- add_cfuncs("libm", nil, "math.h", "sincos",
- "sincosf",
- "log2",
- "log2f",
- "sqrt",
- "sqrtf",
- "acos",
- "acosf",
- "asin",
- "asinf",
- "pow",
- "powf",
- "fmod",
- "fmodf",
- "tan",
- "tanf",
- "atan",
- "atanf",
- "atan2",
- "atan2f",
- "cos",
- "cosf",
- "sin",
- "sinf",
- "exp",
- "expf")
+ check_module_cfuncs("libm", "math.h",
+ "sincos",
+ "sincosf",
+ "log2",
+ "log2f",
+ "sqrt",
+ "sqrtf",
+ "acos",
+ "acosf",
+ "asin",
+ "asinf",
+ "pow",
+ "powf",
+ "fmod",
+ "fmodf",
+ "tan",
+ "tanf",
+ "atan",
+ "atanf",
+ "atan2",
+ "atan2f",
+ "cos",
+ "cosf",
+ "sin",
+ "sinf",
+ "exp",
+ "expf")
-- add the interfaces for posix
- add_cfuncs("posix", nil, {"sys/poll.h", "sys/socket.h"}, "poll")
- add_cfuncs("posix", nil, {"sys/select.h"}, "select")
- add_cfuncs("posix", nil, "pthread.h", "pthread_mutex_init",
- "pthread_create",
- "pthread_setspecific",
- "pthread_getspecific",
- "pthread_key_create",
- "pthread_key_delete")
- add_cfuncs("posix", nil, {"sys/socket.h", "fcntl.h"}, "socket")
- add_cfuncs("posix", nil, "dirent.h", "opendir")
- add_cfuncs("posix", nil, "dlfcn.h", "dlopen")
- add_cfuncs("posix", nil, {"sys/stat.h", "fcntl.h"}, "open", "stat64")
- add_cfuncs("posix", nil, "unistd.h", "gethostname")
- add_cfuncs("posix", nil, "ifaddrs.h", "getifaddrs")
- add_cfuncs("posix", nil, "semaphore.h", "sem_init")
- add_cfuncs("posix", nil, "unistd.h", "getpagesize", "sysconf")
- add_cfuncs("posix", nil, "sched.h", "sched_yield")
- add_cfuncs("posix", nil, "regex.h", "regcomp", "regexec")
- add_cfuncs("posix", nil, "sys/uio.h", "readv", "writev", "preadv", "pwritev")
- add_cfuncs("posix", nil, "unistd.h", "pread64", "pwrite64")
- add_cfuncs("posix", nil, "unistd.h", "fdatasync")
- add_cfuncs("posix", nil, "copyfile.h", "copyfile")
- add_cfuncs("posix", nil, "sys/sendfile.h", "sendfile")
- add_cfuncs("posix", nil, "sys/epoll.h", "epoll_create", "epoll_wait")
- add_cfuncs("posix", nil, "spawn.h", "posix_spawnp")
- add_cfuncs("posix", nil, "unistd.h", "execvp", "execvpe", "fork", "vfork")
- add_cfuncs("posix", nil, "sys/wait.h", "waitpid")
- add_cfuncs("posix", nil, "unistd.h", "getdtablesize")
- add_cfuncs("posix", nil, "sys/resource.h", "getrlimit")
- add_cfuncs("posix", nil, "netdb.h", "getaddrinfo", "getnameinfo", "gethostbyname", "gethostbyaddr")
+ check_module_cfuncs("posix", {"sys/poll.h", "sys/socket.h"}, "poll")
+ check_module_cfuncs("posix", {"sys/select.h"}, "select")
+ check_module_cfuncs("posix", "pthread.h",
+ "pthread_mutex_init",
+ "pthread_create",
+ "pthread_setspecific",
+ "pthread_getspecific",
+ "pthread_key_create",
+ "pthread_key_delete")
+ check_module_cfuncs("posix", {"sys/socket.h", "fcntl.h"}, "socket")
+ check_module_cfuncs("posix", "dirent.h", "opendir")
+ check_module_cfuncs("posix", "dlfcn.h", "dlopen")
+ check_module_cfuncs("posix", {"sys/stat.h", "fcntl.h"}, "open", "stat64")
+ check_module_cfuncs("posix", "unistd.h", "gethostname")
+ check_module_cfuncs("posix", "ifaddrs.h", "getifaddrs")
+ check_module_cfuncs("posix", "semaphore.h", "sem_init")
+ check_module_cfuncs("posix", "unistd.h", "getpagesize", "sysconf")
+ check_module_cfuncs("posix", "sched.h", "sched_yield")
+ check_module_cfuncs("posix", "regex.h", "regcomp", "regexec")
+ check_module_cfuncs("posix", "sys/uio.h", "readv", "writev", "preadv", "pwritev")
+ check_module_cfuncs("posix", "unistd.h", "pread64", "pwrite64")
+ check_module_cfuncs("posix", "unistd.h", "fdatasync")
+ check_module_cfuncs("posix", "copyfile.h", "copyfile")
+ check_module_cfuncs("posix", "sys/sendfile.h", "sendfile")
+ check_module_cfuncs("posix", "sys/epoll.h", "epoll_create", "epoll_wait")
+ check_module_cfuncs("posix", "spawn.h", "posix_spawnp")
+ check_module_cfuncs("posix", "unistd.h", "execvp", "execvpe", "fork", "vfork")
+ check_module_cfuncs("posix", "sys/wait.h", "waitpid")
+ check_module_cfuncs("posix", "unistd.h", "getdtablesize")
+ check_module_cfuncs("posix", "sys/resource.h", "getrlimit")
+ check_module_cfuncs("posix", "netdb.h", "getaddrinfo", "getnameinfo", "gethostbyname", "gethostbyaddr")
-- add the interfaces for systemv
- add_cfuncs("systemv", nil, {"sys/sem.h", "sys/ipc.h"}, "semget", "semtimedop")
+ check_module_cfuncs("systemv", {"sys/sem.h", "sys/ipc.h"}, "semget", "semtimedop")
+
+ -- add the interfaces for valgrind
+ check_module_cfuncs("valgrind", "valgrind/valgrind.h", "VALGRIND_STACK_REGISTER(0, 0)")
end
-- include project directories
diff --git a/core/src/tbox/xmake.lua b/core/src/tbox/xmake.lua
index 91730628c..a261cb80a 100644
--- a/core/src/tbox/xmake.lua
+++ b/core/src/tbox/xmake.lua
@@ -1,3 +1,6 @@
+-- set project version
+set_version("1.6.3", {build = "%Y%m%d%H%M"})
+
-- set warning all as error
set_warnings("all", "error")
@@ -5,19 +8,15 @@ set_warnings("all", "error")
set_languages("c99", "cxx11")
-- add defines to config.h
-add_defines_h("$(prefix)_OS_$(os:upper)")
-add_defines_h("_GNU_SOURCE=1", "_REENTRANT")
+set_configvar("_GNU_SOURCE", 1)
+set_configvar("_REENTRANT", 1)
-- disable some compiler errors
add_cxflags("-Wno-error=deprecated-declarations", "-fno-strict-aliasing")
add_mxflags("-Wno-error=deprecated-declarations", "-fno-strict-aliasing")
--- set the object files directory
-set_objectdir("$(buildir)/$(mode)/$(arch)/.objs")
-set_targetdir("$(buildir)/$(mode)/$(arch)")
-
--- the debug or check or coverage mode
-if is_mode("debug", "check", "coverage") then
+-- the debug, coverage, valgrind or sanitize-address/thread mode
+if is_mode("debug", "coverage", "valgrind", "asan", "tsan") then
-- enable the debug symbols
set_symbols("debug")
@@ -26,15 +25,29 @@ if is_mode("debug", "check", "coverage") then
set_optimize("none")
-- add defines for debug
- if not is_mode("coverage") then
+ if is_mode("debug") then
add_defines("__tb_debug__")
end
- -- attempt to enable some checkers for pc
- if is_mode("check") and is_arch("i386", "x86_64") then
+ -- add defines for valgrind
+ if is_mode("valgrind") then
+ add_defines("__tb_valgrind__")
+ end
+
+ -- attempt to enable sanitize-address
+ if is_mode("asan") then
add_cxflags("-fsanitize=address", "-ftrapv")
add_mxflags("-fsanitize=address", "-ftrapv")
add_ldflags("-fsanitize=address")
+ add_defines("__tb_sanitize_address__")
+ end
+
+ -- attempt to enable sanitize-thread
+ if is_mode("tsan") then
+ add_cxflags("-fsanitize=thread")
+ add_mxflags("-fsanitize=thread")
+ add_ldflags("-fsanitize=thread")
+ add_defines("__tb_sanitize_thread__")
end
-- enable coverage
@@ -45,7 +58,7 @@ if is_mode("debug", "check", "coverage") then
end
end
--- the release or profile mode
+-- the release, profile mode
if is_mode("release", "profile") then
-- the release mode
@@ -57,10 +70,6 @@ if is_mode("release", "profile") then
-- strip all symbols
set_strip("all")
- -- fomit the frame pointer
- add_cxflags("-fomit-frame-pointer")
- add_mxflags("-fomit-frame-pointer")
-
-- the profile mode
else
@@ -70,18 +79,19 @@ if is_mode("release", "profile") then
-- enable gprof
add_cxflags("-pg")
add_ldflags("-pg")
-
end
-- small or micro?
if has_config("small", "micro") then
-
- -- enable smallest optimization
set_optimize("smallest")
else
- -- enable fastest optimization
set_optimize("fastest")
end
+
+ -- disable stack protector for micro mode
+ if has_config("micro") then
+ add_cxflags("-fno-stack-protector")
+ end
end
-- small or micro?
@@ -91,7 +101,7 @@ if has_config("small", "micro") then
add_defines("__tb_small__")
-- add defines to config.h
- add_defines_h("$(prefix)_SMALL")
+ set_configvar("TB_CONFIG_SMALL", 1)
end
-- for the windows platform (msvc)
@@ -118,6 +128,14 @@ if is_plat("windows") then
-- no msvcrt.lib
add_ldflags("-nodefaultlib:msvcrt.lib")
+ add_syslinks("ws2_32")
+
+elseif is_plat("android") then
+ add_syslinks("m", "c")
+elseif is_plat("mingw") then
+ add_syslinks("ws2_32", "pthread", "m")
+else
+ add_syslinks("pthread", "dl", "m", "c")
end
-- include project sources
diff --git a/core/src/xmake/process/open.c b/core/src/xmake/process/open.c
index a7acf8b38..443f44b89 100644
--- a/core/src/xmake/process/open.c
+++ b/core/src/xmake/process/open.c
@@ -71,8 +71,8 @@ tb_int_t xm_process_open(lua_State* lua)
}
// init process
- tb_process_ref_t process = tb_process_init_cmd(command, &attr);
- if (process) lua_pushlightuserdata(lua, process);
+ tb_process_ref_t process = (tb_process_ref_t)tb_process_init_cmd(command, &attr);
+ if (process) lua_pushlightuserdata(lua, (tb_pointer_t)process);
else lua_pushnil(lua);
// ok
diff --git a/core/src/xmake/process/openv.c b/core/src/xmake/process/openv.c
index 2bdda04bc..cf78ad21b 100644
--- a/core/src/xmake/process/openv.c
+++ b/core/src/xmake/process/openv.c
@@ -113,8 +113,8 @@ tb_int_t xm_process_openv(lua_State* lua)
}
// init process
- tb_process_ref_t process = tb_process_init(shellname, argv, &attr);
- if (process) lua_pushlightuserdata(lua, process);
+ tb_process_ref_t process = (tb_process_ref_t)tb_process_init(shellname, argv, &attr);
+ if (process) lua_pushlightuserdata(lua, (tb_pointer_t)process);
else lua_pushnil(lua);
// exit argv
diff --git a/core/src/xmake/process/waitlist.c b/core/src/xmake/process/waitlist.c
index d089a7b68..53e3d16bf 100644
--- a/core/src/xmake/process/waitlist.c
+++ b/core/src/xmake/process/waitlist.c
@@ -128,7 +128,7 @@ tb_int_t xm_process_waitlist(lua_State* lua)
{
// save one process info
lua_newtable(lua);
- lua_pushlightuserdata(lua, infolist[i].process);
+ lua_pushlightuserdata(lua, (tb_pointer_t)infolist[i].process);
lua_rawseti(lua, -2, 1);
lua_pushinteger(lua, infolist[i].index + 1);
lua_rawseti(lua, -2, 2);
diff --git a/core/src/xmake/string/convert.c b/core/src/xmake/string/convert.c
index 4fb03692a..90a0bd6d3 100644
--- a/core/src/xmake/string/convert.c
+++ b/core/src/xmake/string/convert.c
@@ -74,7 +74,7 @@ static xm_charset_entry_ref_t xm_string_charset_find_by_name(tb_char_t const* na
{
// make iterator
tb_array_iterator_t array_iterator;
- tb_iterator_ref_t iterator = tb_iterator_make_for_mem(&array_iterator, g_charsets, tb_arrayn(g_charsets), sizeof(xm_charset_entry_t));
+ tb_iterator_ref_t iterator = tb_array_iterator_init_mem(&array_iterator, g_charsets, tb_arrayn(g_charsets), sizeof(xm_charset_entry_t));
tb_assert_and_check_return_val(iterator, tb_null);
// find it by the binary search
diff --git a/core/src/xmake/xmake.config.h.in b/core/src/xmake/xmake.config.h.in
new file mode 100644
index 000000000..d4c1f675a
--- /dev/null
+++ b/core/src/xmake/xmake.config.h.in
@@ -0,0 +1,11 @@
+#ifndef XM_CONFIG_H
+#define XM_CONFIG_H
+
+// version
+#define XM_CONFIG_VERSION "${VERSION}"
+#define XM_CONFIG_VERSION_MAJOR ${VERSION_MAJOR}
+#define XM_CONFIG_VERSION_MINOR ${VERSION_MINOR}
+#define XM_CONFIG_VERSION_ALTER ${VERSION_ALTER}
+#define XM_CONFIG_VERSION_BUILD ${VERSION_BUILD}
+
+#endif
diff --git a/core/src/xmake/xmake.lua b/core/src/xmake/xmake.lua
index dfbfe09bd..e5ce4d926 100644
--- a/core/src/xmake/xmake.lua
+++ b/core/src/xmake/xmake.lua
@@ -11,16 +11,12 @@ target("xmake")
add_defines("__tb_prefix__=\"xmake\"")
-- set the auto-generated config.h
- set_config_header("$(projectdir)/xmake.config.h", {prefix = "XM_CONFIG"})
-
- -- set the object files directory
- set_objectdir("$(buildir)/.objs")
+ set_configdir("$(buildir)/$(plat)/$(arch)/$(mode)")
+ add_configfiles("xmake.config.h.in")
-- add includes directory
add_includedirs("$(projectdir)", "$(buildir)/luajit")
-
- -- add packages
- add_packages("tbox")
+ add_includedirs("$(buildir)/$(plat)/$(arch)/$(mode)")
-- add the common source files
add_files("**.c|winos/*.c")
diff --git a/core/xmake.lua b/core/xmake.lua
index 0740de872..227d6d20c 100644
--- a/core/xmake.lua
+++ b/core/xmake.lua
@@ -5,7 +5,7 @@ set_project("xmake")
set_version("2.2.3", {build = "%Y%m%d%H%M"})
-- set xmake min version
-set_xmakever("2.2.2")
+set_xmakever("2.2.3")
-- set warning all as error
set_warnings("all", "error")