diff options
| author | ruki <[email protected]> | 2019-02-08 23:45:06 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2019-02-08 16:30:39 +0800 |
| commit | 9342904338fe355892decb82b8b9fc4d3273d9be (patch) | |
| tree | 5390b307c01374ea5722594dd1a0e682b45a8e4c | |
| parent | 04f4888bf721d9d78b0feb56c392122966a36a4e (diff) | |
update tbox
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") |
