static tb_void_t tb_sort_str_test_perf_bubble(tb_size_t n) { __tb_volatile__ tb_size_t i = 0; // init data tb_char_t** data = (tb_char_t**)tb_nalloc0(n, sizeof(tb_char_t*)); tb_assert_and_check_return(data); // init iterator tb_array_iterator_t array_iterator; tb_iterator_ref_t iterator = tb_iterator_make_for_str(&array_iterator, data, n); // make tb_random_clear(tb_null); tb_char_t s[256] = {0}; for (i = 0; i < n; i++) { tb_long_t r = tb_snprintf(s, 256, "%x", tb_random_range(tb_null, 0, TB_MAXU32)); s[r] = '\0'; data[i] = tb_strdup(s); } // sort tb_hong_t time = tb_mclock(); tb_bubble_sort_all(iterator, tb_null); time = tb_mclock() - time; // time tb_trace_i("tb_bubble_sort_str_all: %lld ms", time); // check for (i = 1; i < n; i++) tb_assert_and_check_break(tb_strcmp(data[i - 1], data[i]) <= 0); // free data for (i = 0; i < n; i++) tb_free(data[i]); tb_free(data); }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t tb_demo_stream_null_main(tb_int_t argc, tb_char_t** argv) { // init istream tb_stream_ref_t istream = tb_stream_init_from_url(argv[1]); // init ostream tb_stream_ref_t ostream = tb_stream_init_from_file(argv[2], TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_BINARY | TB_FILE_MODE_TRUNC); // filter istream or ostream? tb_stream_ref_t iostream = istream; // tb_stream_ref_t iostream = ostream; // init fstream tb_stream_ref_t fstream = tb_stream_init_filter_from_null(iostream); // done if (istream && ostream && fstream) { // save it tb_hong_t save = 0; if (iostream == istream) save = tb_transfer_done(fstream, ostream, 0, tb_null, tb_null); else save = tb_transfer_done(istream, fstream, 0, tb_null, tb_null); // trace tb_trace_i("save: %lld bytes, size: %lld bytes", save, tb_stream_size(istream)); } // exit fstream tb_stream_exit(fstream); // exit istream tb_stream_exit(istream); // exit ostream tb_stream_exit(ostream); return 0; }
static tb_size_t tb_vector_remove_last_test() { // init tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_long()); tb_assert_and_check_return_val(vector, 0); __tb_volatile__ tb_size_t i = 0; __tb_volatile__ tb_size_t n = 10000; tb_vector_ninsert_head(vector, (tb_pointer_t)0xf, n); tb_hong_t t = tb_mclock(); for (i = 0; i < n; i++) tb_vector_remove_last(vector); t = tb_mclock() - t; // time tb_trace_i("tb_vector_remove_last(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_vector_size(vector), tb_vector_maxn(vector)); // check tb_assert(!tb_vector_size(vector)); // exit tb_vector_exit(vector); return n / ((tb_uint32_t)(t) + 1); }
tb_void_t tb_dump_data_from_stream(tb_stream_ref_t stream) { // check tb_assert_and_check_return(stream); // init tb_size_t offset = 0; // dump head tb_trace_i(""); // done tb_char_t info[8192]; while (!tb_stream_beof(stream)) { // read line tb_size_t i = 0; tb_size_t n = 147; tb_long_t read = 0; tb_byte_t line[0x20]; while (read < 0x20) { // read data tb_long_t real = tb_stream_read(stream, line + read, 0x20 - read); // has data? if (real > 0) read += real; // no data? else if (!real) { // wait tb_long_t e = tb_stream_wait(stream, TB_AIOE_CODE_RECV, tb_stream_timeout(stream)); tb_assert_and_check_break(e >= 0); // timeout? tb_check_break(e); // has read? tb_assert_and_check_break(e & TB_AIOE_CODE_RECV); } else break; } // full line? tb_char_t* p = info; tb_char_t* e = info + sizeof(info); if (read == 0x20) { // dump offset if (p < e) p += tb_snprintf(p, e - p, "%08X ", offset); // dump data for (i = 0; i < 0x20; i++) { if (!(i & 3) && p < e) p += tb_snprintf(p, e - p, " "); if (p < e) p += tb_snprintf(p, e - p, " %02X", line[i]); } // dump spaces if (p < e) p += tb_snprintf(p, e - p, " "); // dump characters for (i = 0; i < 0x20; i++) { if (p < e) p += tb_snprintf(p, e - p, "%c", tb_isgraph(line[i])? line[i] : '.'); } // dump it if (p < e) { // end *p = '\0'; // trace tb_trace_i("%s", info); } // update offset offset += 0x20; } // has left? else if (read) { // init padding tb_size_t padding = n - 0x20; // dump offset if (p < e) p += tb_snprintf(p, e - p, "%08X ", offset); if (padding >= 9) padding -= 9; // dump data for (i = 0; i < read; i++) { if (!(i & 3)) { if (p < e) p += tb_snprintf(p, e - p, " "); if (padding) padding--; } if (p < e) p += tb_snprintf(p, e - p, " %02X", line[i]); if (padding >= 3) padding -= 3; } // dump spaces while (padding--) if (p < e) p += tb_snprintf(p, e - p, " "); // dump characters for (i = 0; i < read; i++) { if (p < e) p += tb_snprintf(p, e - p, "%c", tb_isgraph(line[i])? line[i] : '.'); } // dump it if (p < e) { // end *p = '\0'; // trace tb_trace_i("%s", info); } // update offset offset += read; } // end else break; } }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_void_t tb_demo_thread_local_free(tb_cpointer_t priv) { tb_trace_i("thread[%lx]: free: %p", tb_thread_self(), priv); }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t tb_demo_network_dns_main(tb_int_t argc, tb_char_t** argv) { // test the invalid host #if TB_DNS_TEST_INVALID_HOST // add not dns host tb_dns_server_add("127.0.0.1"); // add not ipv4 host tb_dns_server_add("localhost"); #endif // test the more host #if TB_DNS_TEST_MORE_HOST tb_dns_server_add("2001:470:20::2"); tb_dns_server_add("fec0:0:0:ffff::1%1"); tb_dns_server_add("205.252.144.228"); tb_dns_server_add("208.151.69.65"); tb_dns_server_add("202.181.202.140"); tb_dns_server_add("202.181.224.2"); tb_dns_server_add("202.175.3.8"); tb_dns_server_add("202.175.3.3"); tb_dns_server_add("168.95.192.1"); tb_dns_server_add("168.95.1.1"); tb_dns_server_add("208.67.222.222"); tb_dns_server_add("205.171.2.65"); tb_dns_server_add("193.0.14.129"); tb_dns_server_add("202.12.27.33"); tb_dns_server_add("202.216.228.18"); tb_dns_server_add("209.166.160.132"); tb_dns_server_add("208.96.10.221"); tb_dns_server_add("61.144.56.101"); tb_dns_server_add("202.101.98.55"); tb_dns_server_add("202.96.128.166"); tb_dns_server_add("202.96.209.134"); tb_dns_server_add("221.12.65.228"); #endif // sort tb_dns_server_sort(); // dump #ifdef __tb_debug__ tb_dns_server_dump(); #endif #if TB_DNS_TEST_HOST_SOME tb_hong_t time = tb_mclock(); tb_dns_test_done("www.tboox.org"); tb_dns_test_done("www.tboox.net"); tb_dns_test_done("www.baidu.com"); tb_dns_test_done("www.google.com"); tb_dns_test_done("www.google.com.hk"); tb_dns_test_done("www.csdn.net"); tb_dns_test_done("www.qq.com"); tb_dns_test_done("www.youku.com"); tb_dns_test_done("www.ibm.com"); tb_dns_test_done("www.sina.com.cn"); tb_dns_test_done("www.hao123.com"); tb_dns_test_done("www.sohu.com"); tb_dns_test_done("www.weibo.com"); tb_dns_test_done("www.126.com"); tb_dns_test_done("www.163.com"); tb_dns_test_done("www.taobao.com"); tb_dns_test_done("www.microsoft.com"); tb_dns_test_done("www.qiyi.com"); tb_dns_test_done("www.xunlei.com"); tb_dns_test_done("www.360buy.com"); tb_dns_test_done("www.tudou.com"); tb_dns_test_done("www.pps.tv"); tb_dns_test_done("www.yahoo.com"); tb_dns_test_done("www.zol.com.cn"); tb_dns_test_done("www.download.com"); tb_dns_test_done("www.webkit.org"); tb_dns_test_done("www.douban.com"); tb_dns_test_done("www.github.com"); tb_dns_test_done("www.videolan.org"); tb_dns_test_done("www.net.cn"); tb_dns_test_done("www.yahoo.com"); tb_dns_test_done("www.sina.com.cn"); tb_dns_test_done("www.hao123.com"); tb_dns_test_done("www.sohu.com"); tb_dns_test_done("www.weibo.com"); tb_dns_test_done("www.126.com"); tb_dns_test_done("www.163.com"); tb_dns_test_done("www.taobao.com"); tb_dns_test_done("www.microsoft.com"); tb_dns_test_done("www.qiyi.com"); tb_dns_test_done("www.xunlei.com"); tb_dns_test_done("www.360buy.com"); tb_dns_test_done("www.tudou.com"); tb_dns_test_done("www.pps.tv"); tb_dns_test_done("www.yahoo.com"); tb_dns_test_done("www.zol.com.cn"); tb_dns_test_done("www.download.com"); tb_dns_test_done("www.webkit.org"); tb_dns_test_done("www.huaxiazi.com"); tb_dns_test_done("www.facebook.com"); tb_dns_test_done("www.youtube.com"); tb_dns_test_done("www.bing.com"); tb_dns_test_done("www.baidu.com"); tb_dns_test_done("www.tianya.com"); tb_dns_test_done("www.adobe.com"); tb_dns_test_done("web2.qq.com"); tb_dns_test_done("www.bluehost.com"); tb_dns_test_done("www.pediy.com"); tb_dns_test_done("www.wordpress.com"); tb_dns_test_done("www.gitorious.org"); tb_dns_test_done("t.qq.com"); tb_dns_test_done("www.wordpress.com"); tb_dns_test_done("www.mop.com"); tb_dns_test_done("www.56.com"); tb_dns_test_done("www.joy.com.cn"); tb_dns_test_done("www.xxxxx.com"); tb_dns_test_done("www.wordpress.com"); tb_dns_test_done("developer.android.com"); tb_dns_test_done("developer.apple.com"); tb_dns_test_done("www.arm.com"); tb_dns_test_done("www.nginx.com"); tb_dns_test_done("www.ted.com"); tb_dns_test_done("www.tboox.org"); tb_dns_test_done("www.tboox.net"); tb_dns_test_done("www.baidu.com"); tb_dns_test_done("www.google.com"); tb_dns_test_done("www.google.com.hk"); tb_dns_test_done("www.csdn.net"); tb_dns_test_done("www.qq.com"); tb_dns_test_done("www.youku.com"); tb_dns_test_done("www.ibm.com"); tb_dns_test_done("www.sina.com.cn"); tb_dns_test_done("www.hao123.com"); tb_dns_test_done("www.sohu.com"); tb_dns_test_done("www.weibo.com"); tb_dns_test_done("www.126.com"); tb_dns_test_done("www.163.com"); tb_dns_test_done("www.taobao.com"); tb_dns_test_done("www.microsoft.com"); tb_dns_test_done("www.qiyi.com"); tb_dns_test_done("www.xunlei.com"); tb_dns_test_done("www.360buy.com"); tb_dns_test_done("www.tudou.com"); tb_dns_test_done("www.pps.tv"); tb_dns_test_done("www.yahoo.com"); tb_dns_test_done("www.zol.com.cn"); tb_dns_test_done("www.download.com"); tb_dns_test_done("www.webkit.org"); tb_dns_test_done("www.douban.com"); tb_dns_test_done("www.github.com"); tb_dns_test_done("www.videolan.org"); tb_dns_test_done("www.net.cn"); tb_dns_test_done("www.yahoo.com"); tb_dns_test_done("www.sina.com.cn"); tb_dns_test_done("www.hao123.com"); tb_dns_test_done("www.sohu.com"); tb_dns_test_done("www.weibo.com"); tb_dns_test_done("www.126.com"); tb_dns_test_done("www.163.com"); tb_dns_test_done("www.taobao.com"); tb_dns_test_done("www.microsoft.com"); tb_dns_test_done("www.qiyi.com"); tb_dns_test_done("www.xunlei.com"); tb_dns_test_done("www.360buy.com"); tb_dns_test_done("www.tudou.com"); tb_dns_test_done("www.pps.tv"); tb_dns_test_done("www.yahoo.com"); tb_dns_test_done("www.zol.com.cn"); tb_dns_test_done("www.download.com"); tb_dns_test_done("www.webkit.org"); tb_dns_test_done("www.huaxiazi.com"); tb_dns_test_done("www.facebook.com"); tb_dns_test_done("www.youtube.com"); tb_dns_test_done("www.bing.com"); tb_dns_test_done("www.baidu.com"); tb_dns_test_done("www.tianya.com"); tb_dns_test_done("www.adobe.com"); tb_dns_test_done("web2.qq.com"); tb_dns_test_done("www.bluehost.com"); tb_dns_test_done("www.pediy.com"); tb_dns_test_done("www.wordpress.com"); tb_dns_test_done("www.gitorious.org"); tb_dns_test_done("t.qq.com"); tb_dns_test_done("www.wordpress.com"); tb_dns_test_done("www.mop.com"); tb_dns_test_done("www.56.com"); tb_dns_test_done("www.joy.com.cn"); tb_dns_test_done("www.xxxxx.com"); tb_dns_test_done("www.wordpress.com"); tb_dns_test_done("developer.android.com"); tb_dns_test_done("developer.apple.com"); tb_dns_test_done("www.arm.com"); tb_dns_test_done("www.nginx.com"); tb_dns_test_done("www.ted.com"); tb_dns_test_done("www.mcu-memory.com"); tb_dns_test_done("mail.126.com"); tb_dns_test_done("mail.163.com"); tb_dns_test_done("mail.google.com"); tb_dns_test_done("mail.qq.com"); tb_dns_test_done("mail.sina.com"); tb_dns_test_done("mail.sohu.com"); tb_dns_test_done("mail.qq.com"); tb_dns_test_done("www.renren.com"); tb_dns_test_done("www.cepark.com"); tb_dns_test_done("www.ifttt.com"); tb_dns_test_done("www.china-pub.com"); tb_dns_test_done("www.amazon.com"); tb_dns_test_done("www.amazon.cn"); tb_dns_test_done("www.2688.com"); tb_dns_test_done("www.mtime.com"); tb_dns_test_done("hi.baidu.com"); tb_dns_test_done("repo.or.cz"); tb_dns_test_done("www.ifeng.com"); tb_dns_test_done("www.sourceforge.com"); tb_dns_test_done("www.wikipedia.org"); tb_dns_test_done("baike.baidu.com"); tb_dns_test_done("www.ted.com"); tb_dns_test_done("www.ted.com"); tb_dns_test_done("www.ted.com"); time = tb_mclock() - time; tb_trace_i("[demo]: done %lld ms", time); #else tb_dns_test_done(argv[1]); #endif return 0; }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t tb_demo_container_bloom_filter_main(tb_int_t argc, tb_char_t** argv) { tb_trace_i("==========================================================="); tb_demo_test_uint8_h(0); tb_demo_test_uint8_h(1); tb_demo_test_uint8_h(2); tb_demo_test_uint8_h(3); tb_demo_test_uint8_h(4); tb_demo_test_uint8_h(5); tb_demo_test_uint8_h(6); tb_demo_test_uint8_h(7); tb_demo_test_uint8_h(8); tb_demo_test_uint8_h(9); tb_demo_test_uint8_h(10); tb_demo_test_uint8_h(11); tb_demo_test_uint8_h(12); tb_demo_test_uint8_h(13); tb_demo_test_uint8_h(14); tb_demo_test_uint8_h(15); tb_trace_i("==========================================================="); tb_demo_test_uint16_h(0); tb_demo_test_uint16_h(1); tb_demo_test_uint16_h(2); tb_demo_test_uint16_h(3); tb_demo_test_uint16_h(4); tb_demo_test_uint16_h(5); tb_demo_test_uint16_h(6); tb_demo_test_uint16_h(7); tb_demo_test_uint16_h(8); tb_demo_test_uint16_h(9); tb_demo_test_uint16_h(10); tb_demo_test_uint16_h(11); tb_demo_test_uint16_h(12); tb_demo_test_uint16_h(13); tb_demo_test_uint16_h(14); tb_demo_test_uint16_h(15); tb_trace_i("==========================================================="); tb_demo_test_uint32_h(0); tb_demo_test_uint32_h(1); tb_demo_test_uint32_h(2); tb_demo_test_uint32_h(3); tb_demo_test_uint32_h(4); tb_demo_test_uint32_h(5); tb_demo_test_uint32_h(6); tb_demo_test_uint32_h(7); tb_demo_test_uint32_h(8); tb_demo_test_uint32_h(9); tb_demo_test_uint32_h(10); tb_demo_test_uint32_h(11); tb_demo_test_uint32_h(12); tb_demo_test_uint32_h(13); tb_demo_test_uint32_h(14); tb_demo_test_uint32_h(15); tb_trace_i("==========================================================="); tb_demo_test_long_h(0); tb_demo_test_long_h(1); tb_demo_test_long_h(2); tb_demo_test_long_h(3); tb_demo_test_long_h(4); tb_demo_test_long_h(5); tb_demo_test_long_h(6); tb_demo_test_long_h(7); tb_demo_test_long_h(8); tb_demo_test_long_h(9); tb_demo_test_long_h(10); tb_demo_test_long_h(11); tb_demo_test_long_h(12); tb_demo_test_long_h(13); tb_demo_test_long_h(14); tb_demo_test_long_h(15); tb_trace_i("==========================================================="); tb_demo_test_cstr_h(0); tb_demo_test_cstr_h(1); tb_demo_test_cstr_h(2); tb_demo_test_cstr_h(3); tb_demo_test_cstr_h(4); tb_demo_test_cstr_h(5); tb_demo_test_cstr_h(6); tb_demo_test_cstr_h(7); tb_demo_test_cstr_h(8); tb_demo_test_cstr_h(9); tb_demo_test_cstr_h(10); tb_demo_test_cstr_h(11); tb_demo_test_cstr_h(12); // tb_demo_test_cstr_h(13); // tb_demo_test_cstr_h(14); // tb_demo_test_cstr_h(15); tb_trace_i("==========================================================="); tb_demo_test_long_p(); tb_demo_test_cstr_p(); return 0; }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t tb_demo_platform_semaphore_main(tb_int_t argc, tb_char_t** argv) { // init loop tb_demo_loop_t loop[10]; tb_size_t i = 0; tb_size_t n = tb_arrayn(loop); for (i = 0; i < n; i++) { // init semaphore loop[i].semaphore = tb_semaphore_init(0); tb_assert_and_check_break(loop[i].semaphore); // post semaphore tb_semaphore_post(loop[i].semaphore, 1); // init index loop[i].index = i; // init stoped loop[i].bstoped = 0; // init loop loop[i].loop = tb_thread_init(tb_null, tb_demo_loop, loop + i, 0); tb_assert_and_check_break(loop[i].loop); } // check tb_assert_and_check_return_val(i == n, 0); // wait some time tb_msleep(100); // post tb_char_t line[256]; tb_bool_t stop = tb_false; while (!stop) { // get line tb_char_t const* p = tb_demo_gets(line, sizeof(line)); tb_assert_and_check_break(p); // trace tb_trace_i("post: %s", p); // done while (*p && !stop) { tb_char_t ch = *p++; switch (ch) { case 'q': stop = tb_true; break; default: { if (ch >= '0' && ch <= '9') { // the index tb_size_t index = ch - '0'; tb_assert_and_check_break(index < n && index == loop[index].index); // post semaphore if (loop[index].semaphore) tb_semaphore_post(loop[index].semaphore, 1); } } break; } } } // post loop for (i = 0; i < n; i++) { // quit thread tb_atomic_set(&loop[i].bstoped, 1); // post semaphore if (loop[i].semaphore) tb_semaphore_post(loop[i].semaphore, 1); } // exit loop for (i = 0; i < n; i++) { // exit loop if (loop[i].loop) { // wait it if (!tb_thread_wait(loop[i].loop, 5000)) { // trace tb_trace_e("wait loop[%lu]: timeout", i); } // exit it tb_thread_exit(loop[i].loop); } // exit semaphore if (loop[i].semaphore) tb_semaphore_exit(loop[i].semaphore); } // exit tb_trace_i("exit"); return 0; }
static tb_void_t tb_pool_data_dump_data(tb_byte_t const* data, tb_size_t size) { // check tb_assert_and_check_return(data && size); // dump head tb_trace_i(""); // walk tb_size_t i = 0; tb_size_t n = 147; tb_byte_t const* p = data; tb_byte_t const* e = data + size; tb_char_t info[8192]; while (p < e) { // full line? tb_char_t* q = info; tb_char_t* d = info + sizeof(info); if (p + 0x20 <= e) { // dump offset if (q < d) q += tb_snprintf(q, d - q, "%08X ", p - data); // dump data for (i = 0; i < 0x20; i++) { if (!(i & 3) && q < d) q += tb_snprintf(q, d - q, " "); if (q < d) q += tb_snprintf(q, d - q, " %02X", p[i]); } // dump spaces if (q < d) q += tb_snprintf(q, d - q, " "); // dump characters for (i = 0; i < 0x20; i++) { if (q < d) q += tb_snprintf(q, d - q, "%c", tb_isgraph(p[i])? p[i] : '.'); } // dump it if (q < d) { // end *q = '\0'; // trace tb_trace_i("%s", info); } // update p p += 0x20; } // has left? else if (p < e) { // init padding tb_size_t padding = n - 0x20; // dump offset if (q < d) q += tb_snprintf(q, d - q, "%08X ", p - data); if (padding >= 9) padding -= 9; // dump data tb_size_t left = e - p; for (i = 0; i < left; i++) { if (!(i & 3)) { if (q < d) q += tb_snprintf(q, d - q, " "); if (padding) padding--; } if (q < d) q += tb_snprintf(q, d - q, " %02X", p[i]); if (padding >= 3) padding -= 3; } // dump spaces while (padding--) if (q < d) q += tb_snprintf(q, d - q, " "); // dump characters for (i = 0; i < left; i++) { if (q < d) q += tb_snprintf(q, d - q, "%c", tb_isgraph(p[i])? p[i] : '.'); } // dump it if (q < d) { // end *q = '\0'; // trace tb_trace_i("%s", info); } // update p p += left; } // end else break; } }
static tb_void_t gb_demo_utils_mesh_tetrahedron() { // trace tb_trace_i("=========================================================================="); // init mesh gb_mesh_ref_t mesh = gb_mesh_init(tb_element_str(tb_true), tb_element_str(tb_true), tb_element_str(tb_true)); if (mesh) { // init listener gb_mesh_listener_set(mesh, gb_demo_utils_mesh_listener, mesh); gb_mesh_listener_event_add(mesh, GB_MESH_EVENT_FACE_MERGE | GB_MESH_EVENT_FACE_SPLIT | GB_MESH_EVENT_EDGE_MERGE | GB_MESH_EVENT_EDGE_SPLIT); // make a clockwise self-loop edge gb_mesh_edge_ref_t edge0 = gb_mesh_edge_make_loop(mesh, tb_false); if (edge0) { /* make a tetrahedron * * e1 * v0 --------------> v1----------------- * | . rface | | * e0 | . | e2 lface | * | face1 e5 . | | e4 * v3 <-------------- v2 | * | e3 | * | | face0 * <----------------------------------- * */ gb_mesh_edge_ref_t edge1 = gb_mesh_edge_insert(mesh, edge0, edge0); gb_mesh_edge_ref_t edge2 = gb_mesh_edge_insert(mesh, edge1, edge0); gb_mesh_edge_ref_t edge3 = gb_mesh_edge_insert(mesh, edge2, edge0); // save face name gb_mesh_face_data_set(mesh, gb_mesh_edge_lface(edge0), "lface"); gb_mesh_face_data_set(mesh, gb_mesh_edge_rface(edge0), "rface"); gb_mesh_edge_ref_t edge4 = gb_mesh_edge_connect(mesh, edge1, edge0); gb_mesh_edge_ref_t edge5 = gb_mesh_edge_connect(mesh, gb_mesh_edge_sym(edge3), gb_mesh_edge_sym(edge0)); // save face name gb_mesh_face_data_set(mesh, gb_mesh_edge_lface(edge4), "face0"); gb_mesh_face_data_set(mesh, gb_mesh_edge_lface(edge5), "face1"); // save edge name gb_mesh_edge_data_set(mesh, edge0, "e0"); gb_mesh_edge_data_set(mesh, edge1, "e1"); gb_mesh_edge_data_set(mesh, edge2, "e2"); gb_mesh_edge_data_set(mesh, edge3, "e3"); gb_mesh_edge_data_set(mesh, edge4, "e4"); gb_mesh_edge_data_set(mesh, edge5, "e5"); // save vertex name gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge0), "v0"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge1), "v1"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge2), "v2"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge3), "v3"); #ifdef __gb_debug__ // trace tb_trace_i(""); tb_trace_i("tetrahedron: make"); // check mesh gb_mesh_check(mesh); // dump mesh gb_mesh_dump(mesh); #endif // delete two gb_mesh_edge_delete(mesh, edge4); gb_mesh_edge_delete(mesh, edge5); #ifdef __gb_debug__ // trace tb_trace_i(""); tb_trace_i("tetrahedron: kill"); // check mesh gb_mesh_check(mesh); // dump mesh gb_mesh_dump(mesh); #endif // remove all gb_mesh_edge_remove(mesh, edge2); gb_mesh_edge_remove(mesh, edge3); gb_mesh_edge_remove(mesh, edge0); gb_mesh_edge_remove(mesh, edge1); // check tb_assert_abort(gb_mesh_is_empty(mesh)); } // exit mesh gb_mesh_exit(mesh); } }
static tb_void_t gb_demo_utils_mesh_split() { // trace tb_trace_i("=========================================================================="); // init mesh gb_mesh_ref_t mesh = gb_mesh_init(tb_element_str(tb_true), tb_element_str(tb_true), tb_element_str(tb_true)); if (mesh) { // init listener gb_mesh_listener_set(mesh, gb_demo_utils_mesh_listener, mesh); gb_mesh_listener_event_add(mesh, GB_MESH_EVENT_FACE_MERGE | GB_MESH_EVENT_FACE_SPLIT | GB_MESH_EVENT_EDGE_MERGE | GB_MESH_EVENT_EDGE_SPLIT); // make a clockwise self-loop edge gb_mesh_edge_ref_t edge0 = gb_mesh_edge_make_loop(mesh, tb_false); if (edge0) { /* make a quadrangle * * e1 * v0 --------------> v1 * | | * e0 | rface | e2 lface * | | * v3 <-------------- v2 * e3 * */ gb_mesh_edge_ref_t edge1 = gb_mesh_edge_insert(mesh, edge0, edge0); gb_mesh_edge_ref_t edge2 = gb_mesh_edge_insert(mesh, edge1, edge0); gb_mesh_edge_ref_t edge3 = gb_mesh_edge_insert(mesh, edge2, edge0); // save face name gb_mesh_face_data_set(mesh, gb_mesh_edge_lface(edge0), "lface"); gb_mesh_face_data_set(mesh, gb_mesh_edge_rface(edge0), "rface"); // save edge name gb_mesh_edge_data_set(mesh, edge0, "e0"); gb_mesh_edge_data_set(mesh, edge1, "e1"); gb_mesh_edge_data_set(mesh, edge2, "e2"); gb_mesh_edge_data_set(mesh, edge3, "e3"); // save vertex name gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge0), "v0"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge1), "v1"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge2), "v2"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge3), "v3"); #ifdef __gb_debug__ // trace tb_trace_i(""); tb_trace_i("split: make"); // check mesh gb_mesh_check(mesh); // dump mesh gb_mesh_dump(mesh); #endif /* split a quadrangle * * e1 e4 * v0 ------ v4 -----> v1 * | | * e0 | rface | e2 lface * | | * v3 <----- v5 <---- v2 * e5 e3 * */ gb_mesh_edge_ref_t edge4 = gb_mesh_edge_split(mesh, edge1); gb_mesh_edge_ref_t edge5 = gb_mesh_edge_split(mesh, edge3); // save edge name gb_mesh_edge_data_set(mesh, edge4, "e4"); gb_mesh_edge_data_set(mesh, edge5, "e5"); // save vertex name gb_mesh_vertex_data_set(mesh, gb_mesh_edge_org(edge4), "v4"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_org(edge5), "v5"); #ifdef __gb_debug__ // trace tb_trace_i(""); tb_trace_i("split: done"); // check mesh gb_mesh_check(mesh); // dump mesh gb_mesh_dump(mesh); #endif } // exit mesh gb_mesh_exit(mesh); } }
static tb_void_t gb_demo_utils_mesh_quadrangle() { // trace tb_trace_i("=========================================================================="); // init mesh gb_mesh_ref_t mesh = gb_mesh_init(tb_element_str(tb_true), tb_element_str(tb_true), tb_element_str(tb_true)); if (mesh) { // init listener gb_mesh_listener_set(mesh, gb_demo_utils_mesh_listener, mesh); gb_mesh_listener_event_add(mesh, GB_MESH_EVENT_FACE_MERGE | GB_MESH_EVENT_FACE_SPLIT | GB_MESH_EVENT_EDGE_MERGE | GB_MESH_EVENT_EDGE_SPLIT); // make a counter-clockwise self-loop edge gb_mesh_edge_ref_t edge0 = gb_mesh_edge_make_loop(mesh, tb_true); if (edge0) { /* make a quadrangle * * e0 * v0 <-------------- v3 * | | * e1 | lface | e3 rface * | | * v1 --------------> v2 * e2 * */ gb_mesh_edge_ref_t edge1 = gb_mesh_edge_insert(mesh, edge0, edge0); gb_mesh_edge_ref_t edge2 = gb_mesh_edge_insert(mesh, edge1, edge0); gb_mesh_edge_ref_t edge3 = gb_mesh_edge_insert(mesh, edge2, edge0); // save face name gb_mesh_face_data_set(mesh, gb_mesh_edge_lface(edge0), "lface"); gb_mesh_face_data_set(mesh, gb_mesh_edge_rface(edge0), "rface"); // save edge name gb_mesh_edge_data_set(mesh, edge0, "e0"); gb_mesh_edge_data_set(mesh, edge1, "e1"); gb_mesh_edge_data_set(mesh, edge2, "e2"); gb_mesh_edge_data_set(mesh, edge3, "e3"); // save vertex name gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge0), "v0"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge1), "v1"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge2), "v2"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge3), "v3"); #ifdef __gb_debug__ // trace tb_trace_i(""); tb_trace_i("quadrangle: make"); // check mesh gb_mesh_check(mesh); // dump mesh gb_mesh_dump(mesh); #endif /* remove one * * v3 * e1 . | * . | e3 rface * . lface | * v1 --------------> v2 * e2 */ gb_mesh_edge_remove(mesh, edge0); #ifdef __gb_debug__ // trace tb_trace_i(""); tb_trace_i("quadrangle: kill"); // check mesh gb_mesh_check(mesh); // dump mesh gb_mesh_dump(mesh); #endif // remove all gb_mesh_edge_remove(mesh, edge2); gb_mesh_edge_remove(mesh, edge3); gb_mesh_edge_remove(mesh, edge1); // check tb_assert_abort(gb_mesh_is_empty(mesh)); } // exit mesh gb_mesh_exit(mesh); } }
static tb_void_t gb_demo_utils_mesh_radiation() { // trace tb_trace_i("=========================================================================="); // init mesh gb_mesh_ref_t mesh = gb_mesh_init(tb_element_str(tb_true), tb_element_str(tb_true), tb_element_str(tb_true)); if (mesh) { // init listener gb_mesh_listener_set(mesh, gb_demo_utils_mesh_listener, mesh); gb_mesh_listener_event_add(mesh, GB_MESH_EVENT_FACE_MERGE | GB_MESH_EVENT_FACE_SPLIT | GB_MESH_EVENT_EDGE_MERGE | GB_MESH_EVENT_EDGE_SPLIT); // make a edge gb_mesh_edge_ref_t edge1 = gb_mesh_edge_make(mesh); if (edge1) { // the face gb_mesh_face_ref_t face = gb_mesh_edge_lface(edge1); tb_assert_abort(face == gb_mesh_edge_rface(edge1)); // save face name gb_mesh_face_data_set(mesh, face, "face"); /* make a radiation * * v4 * / \ * | * | * | e4 * | * | * | * <---------------- v0 ----------------> * v1 e1 | e3 v3 * | * | * | e2 * | * | * \ / * v2 */ gb_mesh_edge_ref_t edge2 = gb_mesh_edge_append(mesh, gb_mesh_edge_sym(edge1)); gb_mesh_edge_ref_t edge3 = gb_mesh_edge_append(mesh, gb_mesh_edge_sym(edge1)); gb_mesh_edge_ref_t edge4 = gb_mesh_edge_append(mesh, gb_mesh_edge_sym(edge1)); // save edge name gb_mesh_edge_data_set(mesh, edge1, "e1"); gb_mesh_edge_data_set(mesh, edge2, "e2"); gb_mesh_edge_data_set(mesh, edge3, "e3"); gb_mesh_edge_data_set(mesh, edge4, "e4"); // save vertex name gb_mesh_vertex_data_set(mesh, gb_mesh_edge_org(edge1), "v0"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge1), "v1"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge2), "v2"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge3), "v3"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge4), "v4"); #ifdef __gb_debug__ // trace tb_trace_i(""); tb_trace_i("radiation: make"); // check mesh gb_mesh_check(mesh); // dump mesh gb_mesh_dump(mesh); #endif /* remove one * * v4 * / \ * | * | * | e4 * | * | * | * v0 ----------------> * | e3 v3 * | * | * | e2 * | * | * \ / * v2 */ gb_mesh_edge_remove(mesh, edge1); #ifdef __gb_debug__ // trace tb_trace_i(""); tb_trace_i("radiation: kill"); // check mesh gb_mesh_check(mesh); // dump mesh gb_mesh_dump(mesh); #endif // remove all gb_mesh_edge_remove(mesh, edge2); gb_mesh_edge_remove(mesh, edge3); gb_mesh_edge_remove(mesh, edge4); // check tb_assert_abort(gb_mesh_is_empty(mesh)); } // exit mesh gb_mesh_exit(mesh); } }
static tb_void_t gb_demo_utils_mesh_splice() { // trace tb_trace_i("=========================================================================="); // init mesh gb_mesh_ref_t mesh = gb_mesh_init(tb_element_str(tb_true), tb_element_str(tb_true), tb_element_str(tb_true)); if (mesh) { // init listener gb_mesh_listener_set(mesh, gb_demo_utils_mesh_listener, mesh); gb_mesh_listener_event_add(mesh, GB_MESH_EVENT_FACE_MERGE | GB_MESH_EVENT_FACE_SPLIT | GB_MESH_EVENT_EDGE_MERGE | GB_MESH_EVENT_EDGE_SPLIT); /* make a edge * * lface * * O -----> D * * lface */ gb_mesh_edge_ref_t edge = gb_mesh_edge_make(mesh); if (edge) { // save face name gb_mesh_face_data_set(mesh, gb_mesh_edge_lface(edge), "lface"); // save vertex name gb_mesh_vertex_data_set(mesh, gb_mesh_edge_org(edge), "org"); gb_mesh_vertex_data_set(mesh, gb_mesh_edge_dst(edge), "dst"); #ifdef __gb_debug__ // trace tb_trace_i(""); tb_trace_i("splice: make"); // check mesh gb_mesh_check(mesh); // dump mesh gb_mesh_dump(mesh); #endif /* splice * * ------- * | | * | rface | * | | * O/D <--- * * lface * */ gb_mesh_edge_splice(mesh, edge, gb_mesh_edge_sym(edge)); #ifdef __gb_debug__ // trace tb_trace_i(""); tb_trace_i("splice: done"); // check mesh gb_mesh_check(mesh); // dump mesh gb_mesh_dump(mesh); #endif /* splice * * lface * * O -----> D * * lface * */ gb_mesh_edge_splice(mesh, edge, gb_mesh_edge_sym(edge)); #ifdef __gb_debug__ // trace tb_trace_i(""); tb_trace_i("splice: done"); // check mesh gb_mesh_check(mesh); // dump mesh gb_mesh_dump(mesh); #endif } // exit mesh gb_mesh_exit(mesh); } }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t tb_demo_stream_async_transfer_main(tb_int_t argc, tb_char_t** argv) { // done tb_async_transfer_ref_t transfer = tb_null; do { // init transfer transfer = tb_async_transfer_init(tb_null, tb_true); tb_assert_and_check_break(transfer); // init transfer stream if (!tb_async_transfer_init_istream_from_url(transfer, argv[1])) break; if (!tb_async_transfer_init_ostream_from_url(transfer, argv[2])) break; // limit rate tb_async_transfer_limitrate(transfer, argv[3]? tb_atoi(argv[3]) : 0); // trace tb_trace_i("done: .."); // open and done transfer if (!tb_async_transfer_open_done(transfer, 0, tb_demo_transfer_done_func, tb_null)) break; // wait getchar(); // trace tb_trace_i("pause: .."); // pause transfer tb_async_transfer_pause(transfer); // wait getchar(); // trace tb_trace_i("resume: .."); // resume transfer if (!tb_async_transfer_resume(transfer)) break; // wait getchar(); // trace tb_trace_i("done: .."); // open and done transfer if (!tb_async_transfer_open_done(transfer, 0, tb_demo_transfer_done_func, tb_null)) break; // wait getchar(); } while (0); // trace tb_trace_i("exit: .."); // exit transfer if (transfer) tb_async_transfer_exit(transfer); transfer = tb_null; return 0; }
static pid_t it_pid(tb_char_t const* name) { // check tb_assert_and_check_return_val(name, 0); // is pid? tb_size_t pid = tb_atoi(name); if (pid) return pid; // init struct kinfo_proc* p = tb_null; struct kinfo_proc* q = tb_null; tb_int_t mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0}; tb_size_t miblen = 4; tb_size_t size = 0; tb_long_t ok = sysctl(mib, miblen, tb_null, &size, tb_null, 0); // walk do { // grow size += size / 10; q = tb_ralloc(p, size); // no memory? if (!q) { if (p) tb_free(p); return 0; } // list p = q; ok = sysctl(mib, miblen, p, &size, tb_null, 0); } while (ok == -1 && errno == ENOMEM); // ok? if (ok == 0) { if (!(size % sizeof(struct kinfo_proc))) { tb_size_t i = 0; tb_size_t n = size / sizeof(struct kinfo_proc); // try accurate name for (i = 0; i < n; i++) { if (!tb_stricmp(p[i].kp_proc.p_comm, name)) { tb_trace_i("name: %s, pid: %u", p[i].kp_proc.p_comm, p[i].kp_proc.p_pid); pid = p[i].kp_proc.p_pid; break; } } // try other name if (!pid) { for (i = 0; i < n; i++) { if (!tb_strnicmp(p[i].kp_proc.p_comm, name, tb_strlen(name))) { tb_trace_i("name: %s, pid: %u", p[i].kp_proc.p_comm, p[i].kp_proc.p_pid); pid = p[i].kp_proc.p_pid; break; } } } } } // free if (p) tb_free(p); // ok return pid; }
tb_void_t tb_pool_data_dump(tb_cpointer_t data, tb_bool_t verbose, tb_char_t const* prefix) { // done tb_pool_data_head_t* data_head = tb_null; do { // no data? tb_assert_and_check_break(data); // the data head data_head = &(((tb_pool_data_head_t*)data)[-1]); // dump the head info tb_size_t data_limit = 256; if (data_head->debug.magic == TB_POOL_DATA_MAGIC) { // the data size tb_size_t data_size = (tb_size_t)data_head->size; // format the backtrace prefix tb_char_t backtrace_prefix[256] = {0}; tb_snprintf(backtrace_prefix, sizeof(backtrace_prefix), "%s ", prefix? prefix : ""); // dump backtrace tb_size_t nframe = 0; while (nframe < tb_arrayn(data_head->debug.backtrace) && data_head->debug.backtrace[nframe]) nframe++; tb_trace_i("%sdata: from: %s(): %u, %s", prefix? prefix : "", data_head->debug.func, data_head->debug.line, data_head->debug.file); tb_backtrace_dump(backtrace_prefix, data_head->debug.backtrace, nframe); // dump the data info tb_trace_i("%sdata: %p, size: %lu, patch: %x", prefix? prefix : "", data, data_size, ((tb_byte_t const*)data)[data_size]); // dump the first 256-bytes data if (data_size && verbose) { // the dump size tb_size_t dump_size = tb_min(data_size, data_limit); // dump it tb_trace_i("%sdata: first %lu-bytes:", prefix? prefix : "", dump_size); tb_pool_data_dump_data((tb_byte_t const*)data, dump_size); // dump the last 256-bytes data if (data_size > dump_size) { // the last data tb_byte_t const* data_last = tb_max((tb_byte_t const*)data + data_size - data_limit, (tb_byte_t const*)data + dump_size); // update the dump size dump_size = (tb_byte_t const*)data + data_size - data_last; // dump it tb_trace_i("%sdata: last %lu-bytes:", prefix? prefix : "", dump_size); tb_pool_data_dump_data(data_last, dump_size); } } } // for the public fixed_pool else if (data_head->debug.magic == TB_POOL_DATA_EMPTY_MAGIC) { // format the backtrace prefix tb_char_t backtrace_prefix[256] = {0}; tb_snprintf(backtrace_prefix, sizeof(backtrace_prefix), "%s ", prefix? prefix : ""); // dump backtrace tb_size_t nframe = 0; while (nframe < tb_arrayn(data_head->debug.backtrace) && data_head->debug.backtrace[nframe]) nframe++; tb_trace_i("%sdata: from: %s(): %u, %s", prefix? prefix : "", data_head->debug.func, data_head->debug.line, data_head->debug.file); tb_backtrace_dump(backtrace_prefix, data_head->debug.backtrace, nframe); // dump the data info tb_trace_i("%sdata: %p, size: fixed", prefix? prefix : "", data); } else { // dump the data head tb_trace_i("%sdata: invalid head:", prefix? prefix : ""); tb_pool_data_dump_data((tb_byte_t const*)data_head, sizeof(tb_pool_data_head_t)); // dump the first 256-bytes data tb_trace_i("%sdata: first %lu-bytes:", prefix? prefix : "", data_limit); tb_pool_data_dump_data((tb_byte_t const*)data, data_limit); } } while (0); }
tb_void_t tb_demo_small_allocator_perf() { // done tb_allocator_ref_t small_allocator = tb_null; tb_allocator_ref_t large_allocator = tb_null; do { // init small allocator small_allocator = tb_small_allocator_init(tb_null); tb_assert_and_check_break(small_allocator); // init large allocator large_allocator = tb_large_allocator_init(tb_null, 0); tb_assert_and_check_break(large_allocator); // make data list tb_size_t maxn = 100000; tb_pointer_t* list = (tb_pointer_t*)tb_allocator_large_nalloc0(large_allocator, maxn, sizeof(tb_pointer_t), tb_null); tb_assert_and_check_break(list); // done __tb_volatile__ tb_size_t indx = 0; __tb_volatile__ tb_hong_t time = tb_mclock(); __tb_volatile__ tb_size_t rand = 0xbeaf; for (indx = 0; indx < maxn; indx++) { // make data list[indx] = tb_allocator_malloc0(small_allocator, (rand & 3071) + 1); tb_assert_and_check_break(list[indx]); // make rand rand = (rand * 10807 + 1) & 0xffffffff; // re-make data if (!(indx & 31)) { list[indx] = tb_allocator_ralloc(small_allocator, list[indx], (rand & 3071) + 1); tb_assert_and_check_break(list[indx]); } // free data __tb_volatile__ tb_size_t size = rand & 15; if (size > 5 && indx) { size -= 5; while (size--) { // the free index tb_size_t free_indx = rand % indx; // free it if (list[free_indx]) tb_allocator_free(small_allocator, list[free_indx]); list[free_indx] = tb_null; } } } time = tb_mclock() - time; #ifdef __tb_debug__ // dump small_allocator tb_allocator_dump(small_allocator); #endif // trace tb_trace_i("time: %lld ms", time); // clear small_allocator tb_allocator_clear(small_allocator); // exit list tb_allocator_large_free(large_allocator, list); } while (0); // exit small allocator if (small_allocator) tb_allocator_exit(small_allocator); small_allocator = tb_null; // exit large allocator if (large_allocator) tb_allocator_exit(large_allocator); large_allocator = tb_null; }
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; }
tb_void_t tb_hash_map_dump(tb_hash_map_ref_t hash_map) { // check tb_hash_map_impl_t* impl = (tb_hash_map_impl_t*)hash_map; tb_assert_and_check_return(impl && impl->hash_list); // the step tb_size_t step = impl->element_name.size + impl->element_data.size; tb_assert_and_check_return(step); // trace tb_trace_i(""); tb_trace_i("hash_map: size: %lu", tb_hash_map_size(hash_map)); // done tb_size_t i = 0; tb_char_t name[4096]; tb_char_t data[4096]; for (i = 0; i < impl->hash_size; i++) { // the list tb_hash_map_item_list_t* list = impl->hash_list[i]; if (list) { // trace tb_trace_i("buck[%u]: size: %u, maxn: %u", i, list->size, list->maxn); // done tb_size_t j = 0; for (j = 0; j < list->size; j++) { // the item tb_byte_t const* item = ((tb_byte_t*)&list[1]) + j * step; // the item name tb_pointer_t element_name = impl->element_name.data(&impl->element_name, item); // the item data tb_pointer_t element_data = impl->element_data.data(&impl->element_data, item + impl->element_name.size); // trace if (impl->element_name.cstr && impl->element_data.cstr) { tb_trace_i(" %s => %s", impl->element_name.cstr(&impl->element_name, element_name, name, sizeof(name)), impl->element_data.cstr(&impl->element_data, element_data, data, sizeof(data))); } else if (impl->element_name.cstr) { tb_trace_i(" %s => %p", impl->element_name.cstr(&impl->element_name, element_name, name, sizeof(name)), element_data); } else if (impl->element_data.cstr) { tb_trace_i(" %x => %p", element_name, impl->element_data.cstr(&impl->element_data, element_data, data, sizeof(data))); } else { tb_trace_i(" %p => %p", element_name, element_data); } } } } }
static tb_void_t tb_demo_task_time_exit(tb_thread_pool_worker_ref_t worker, tb_cpointer_t priv) { // trace tb_trace_i("exit: %u ms", tb_p2u32(priv)); }
static tb_bool_t tb_demo_sock_acpt_func(tb_aice_ref_t aice) { // check tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_ACPT, tb_false); // the file path tb_char_t const* path = (tb_char_t const*)aice->priv; tb_assert_and_check_return_val(path, tb_false); // the aicp tb_aicp_ref_t aicp = tb_aico_aicp(aice->aico); tb_assert_and_check_return_val(aicp, tb_false); // acpt ok? if (aice->state == TB_STATE_OK) { // trace tb_trace_i("acpt[%p]: %p", aice->aico, aice->u.acpt.aico); // done tb_bool_t ok = tb_false; tb_demo_context_t* context = tb_null; do { // make context context = tb_malloc0_type(tb_demo_context_t); tb_assert_and_check_break(context); #ifdef TB_DEMO_MODE_SENDF // init file context->file = tb_file_init(path, TB_FILE_MODE_RO | TB_FILE_MODE_ASIO); tb_assert_and_check_break(context->file); // init sock aico context->aico[0] = aice->u.acpt.aico; tb_assert_and_check_break(context->aico[0]); // post sendf from file if (!tb_aico_sendf(context->aico[0], context->file, 0ULL, tb_file_size(context->file), tb_demo_sock_sendf_func, context)) break; #else // init data context->data = tb_malloc_bytes(TB_DEMO_FILE_READ_MAXN); tb_assert_and_check_break(context->file && context->data); // init sock aico context->aico[0] = aice->u.acpt.aico; tb_assert_and_check_break(context->aico[0]); // init file aico context->aico[1] = tb_aico_init(aicp); tb_assert_and_check_break(context->aico[1]); // open file aico if (!tb_aico_open_file_from_path(context->aico[1], path, TB_FILE_MODE_RO)) break; // post read from file if (!tb_aico_read(context->aico[1], context->size, context->data, TB_DEMO_FILE_READ_MAXN, tb_demo_file_read_func, context)) break; #endif // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit context if (context) tb_demo_context_exit(context); } } // failed? else { // exit loop tb_trace_i("acpt[%p]: state: %s", aice->aico, tb_state_cstr(aice->state)); // clos aico if (aice->aico) tb_aico_clos(aice->aico, tb_demo_aico_clos, tb_null); } // ok return tb_true; }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_void_t tb_demo_coroutine_pull(tb_cpointer_t priv) { // done tb_socket_ref_t sock = tb_null; do { // init socket sock = tb_socket_init(TB_SOCKET_TYPE_TCP, TB_IPADDR_FAMILY_IPV4); tb_assert_and_check_break(sock); // init address tb_ipaddr_t addr; tb_ipaddr_set(&addr, "127.0.0.1", TB_DEMO_PORT, TB_IPADDR_FAMILY_IPV4); // trace tb_trace_d("[%p]: connecting %{ipaddr} ..", sock, &addr); // connect socket tb_long_t ok; while (!(ok = tb_socket_connect(sock, &addr))) { // wait it if (tb_socket_wait(sock, TB_SOCKET_EVENT_CONN, TB_DEMO_TIMEOUT) <= 0) break; } // connect ok? tb_check_break(ok > 0); // trace tb_trace_d("[%p]: recving ..", sock); // recv data tb_byte_t data[8192]; tb_hize_t recv = 0; tb_long_t wait = 0; tb_hong_t time = tb_mclock(); while (1) { // read it tb_long_t real = tb_socket_recv(sock, data, sizeof(data)); // trace tb_trace_d("[%p]: recv: %ld, total: %lu", sock, real, recv + (real > 0? real : 0)); // 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, TB_DEMO_TIMEOUT); tb_assert_and_check_break(wait >= 0); } // failed or end? else break; } // trace tb_trace_i("[%p]: recv %llu bytes %lld ms", sock, recv, tb_mclock() - time); } while (0); // exit socket if (sock) tb_socket_exit(sock); sock = tb_null; }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t tb_demo_asio_aicpd_main(tb_int_t argc, tb_char_t** argv) { // check tb_assert_and_check_return_val(argv[1], 0); // init tb_aicp_ref_t aicp = tb_null; tb_aico_ref_t aico = tb_null; // tb_aico_ref_t task = tb_null; tb_thread_ref_t loop[16] = {tb_null}; do { // init aicp aicp = tb_aicp_init(16); tb_assert_and_check_break(aicp); // init sock aico aico = tb_aico_init(aicp); tb_assert_and_check_break(aico); // init addr tb_ipaddr_t addr; tb_ipaddr_set(&addr, tb_null, 9090, TB_IPADDR_FAMILY_IPV4); // open sock aico if (!tb_aico_open_sock_from_type(aico, TB_SOCKET_TYPE_TCP, tb_ipaddr_family(&addr))) break; // bind port if (!tb_socket_bind(tb_aico_sock(aico), &addr)) break; // listen sock if (!tb_socket_listen(tb_aico_sock(aico), 20)) break; #if 0 // init task aico task = tb_aico_init(aicp); tb_assert_and_check_break(task); // open task aico if (!tb_aico_open_task(task, tb_false)) break; // run task if (!tb_aico_task_run(task, 0, tb_demo_task_func, tb_null)) break; if (!tb_aico_task_run(aico, 0, tb_demo_task_func, tb_null)) break; #endif // post acpt if (!tb_aico_acpt(aico, tb_demo_sock_acpt_func, argv[1])) break; // done loop loop[0] = tb_thread_init(tb_null, tb_demo_loop, aicp, 0); loop[1] = tb_thread_init(tb_null, tb_demo_loop, aicp, 0); loop[2] = tb_thread_init(tb_null, tb_demo_loop, aicp, 0); loop[3] = tb_thread_init(tb_null, tb_demo_loop, aicp, 0); // wait exit getchar(); } while (0); // trace tb_trace_i("end"); #if 1 if (aicp) { // kill all tb_aicp_kill_all(aicp); // wait all tb_aicp_wait_all(aicp, -1); // kill aicp tb_aicp_kill(aicp); } // wait exit { // exit loop tb_thread_ref_t* l = loop; for (; *l; l++) { tb_thread_wait(*l, -1, tb_null); tb_thread_exit(*l); } } #endif // exit aicp if (aicp) tb_aicp_exit(aicp); return 0; }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t main(tb_int_t argc, tb_char_t** argv) { // init tbox #if 0 if (!tb_init(tb_null, (tb_byte_t*)malloc(300 * 1024 * 1024), 300 * 1024 * 1024)) return 0; #else if (!tb_init(tb_null, tb_null, 0)) return 0; #endif // init tb_int_t ok = 0; tb_char_t const* name = tb_null; // find the main func from the .demo file if (!name) { // init file tb_file_ref_t file = tb_file_init(".demo", TB_FILE_MODE_RO); if (file) { // read line tb_char_t line[8192] = {0}; if (tb_file_read(file, (tb_byte_t*)line, sizeof(line) - 1)) { tb_size_t i = 0; tb_size_t n = tb_arrayn(g_demo); for (i = 0; i < n; i++) { // find it? if (g_demo[i].name && !tb_strnicmp(g_demo[i].name, line, tb_strlen(g_demo[i].name))) { // save name name = g_demo[i].name; // done main ok = g_demo[i].main(argc, argv); break; } } } // exit file tb_file_exit(file); } } // find the main func from the first argument if (!name && argc > 1 && argv[1]) { tb_size_t i = 0; tb_size_t n = tb_arrayn(g_demo); for (i = 0; i < n; i++) { // find it? if (g_demo[i].name && !tb_stricmp(g_demo[i].name, argv[1])) { // save name name = g_demo[i].name; // done main ok = g_demo[i].main(argc - 1, argv + 1); break; } } } // no this demo? help it if (!name) { tb_trace_i("======================================================================"); tb_trace_i("help: echo \"name\" > ./.demo"); tb_trace_i("help: ./demo.b args ..."); tb_trace_i("help: or"); tb_trace_i("help: ./demo.b name args ..."); tb_trace_i("help: "); tb_trace_i("help: example: echo \"stream\" > ./.demo"); tb_trace_i("help: example: ./demo.b --help"); tb_trace_i("help: example: ./demo.b http://www.xxxxx.com /tmp/a"); tb_trace_i("help: example: or"); tb_trace_i("help: example: ./demo.b stream http://www.xxxxx.com /tmp/a"); tb_trace_i("help: "); // walk name tb_size_t i = 0; tb_size_t n = tb_arrayn(g_demo); for (i = 0; i < n; i++) tb_trace_i("help: name: %s", g_demo[i].name); } // exit tbox tb_exit(); // ok? return ok; }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t gb_demo_core_path_main(tb_int_t argc, tb_char_t** argv) { // make path gb_path_ref_t path = gb_path_init(); if (path) { // init path gb_path_move2i_to(path, 100, 100); gb_path_line2i_to(path, 200, 200); gb_path_quad2i_to(path, 300, 300, 400, 400); gb_path_cubic2i_to(path, 500, 500, 600, 600, 700, 700); gb_path_clos(path); // make copy gb_path_ref_t copy = gb_path_init(); if (copy) { // copy path gb_path_copy(copy, path); #ifdef __gb_debug__ // dump copy gb_path_dump(copy); #endif // exit copy gb_path_exit(copy); } #ifdef __gb_debug__ // dump path gb_path_dump(path); #endif #if 1 // reverse dump tb_rfor_all_if (gb_path_item_ref_t, item, path, item) { switch (item->code) { case GB_PATH_CODE_MOVE: tb_trace_i("move_to: %{point}", &item->points[0]); break; case GB_PATH_CODE_LINE: tb_trace_i("line_to: %{point}", &item->points[1]); break; case GB_PATH_CODE_QUAD: tb_trace_i("quad_to: %{point}, %{point}", &item->points[1], &item->points[2]); break; case GB_PATH_CODE_CUBIC: tb_trace_i("cubic_to: %{point}, %{point}, %{point}", &item->points[1], &item->points[2], &item->points[3]); break; case GB_PATH_CODE_CLOS: tb_trace_i("closed"); break; default: break; } } #endif // exit path gb_path_exit(path); } return 0; }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t tb_demo_asio_aiopd_main(tb_int_t argc, tb_char_t** argv) { // check tb_assert_and_check_return_val(argv[1], 0); // done tb_socket_ref_t sock = tb_null; tb_aiop_ref_t aiop = tb_null; do { // init sock sock = tb_socket_init(TB_SOCKET_TYPE_TCP); tb_assert_and_check_break(sock); // init aiop aiop = tb_aiop_init(16); tb_assert_and_check_break(aiop); // bind if (!tb_socket_bind(sock, tb_null, 9090)) break; // listen sock if (!tb_socket_listen(sock, 20)) break; // addo sock if (!tb_aiop_addo(aiop, sock, TB_AIOE_CODE_ACPT, tb_null)) break; // accept tb_aioe_t list[16]; while (1) { // wait tb_long_t objn = tb_aiop_wait(aiop, list, 16, -1); tb_assert_and_check_break(objn >= 0); // walk list tb_size_t i = 0; for (i = 0; i < objn; i++) { // the aioo tb_aioo_ref_t aioo = list[i].aioo; // check tb_assert_and_check_break(aioo && tb_aioo_sock(aioo)); // acpt? if (list[i].code & TB_AIOE_CODE_ACPT) { // done acpt tb_bool_t ok = tb_false; tb_demo_context_t* context = tb_null; do { // make context context = tb_malloc0_type(tb_demo_context_t); tb_assert_and_check_break(context); // init sock context->sock = tb_socket_accept(tb_aioo_sock(aioo), tb_null, tb_null); tb_assert_and_check_break(context->sock); // init file context->file = tb_file_init(argv[1], TB_FILE_MODE_RO); tb_assert_and_check_break(context->file); // init data context->data = tb_malloc_bytes(TB_DEMO_FILE_READ_MAXN); tb_assert_and_check_break(context->data); // addo sock context->aioo = tb_aiop_addo(aiop, context->sock, TB_AIOE_CODE_SEND, context); tb_assert_and_check_break(context->aioo); // trace tb_trace_i("acpt[%p]: ok", context->sock); // init left context->left = tb_file_size(context->file); // done read tb_long_t real = tb_file_read(context->file, context->data, tb_min((tb_size_t)context->left, TB_DEMO_FILE_READ_MAXN)); tb_assert_and_check_break(real > 0); // save size context->left -= real; // trace // tb_trace_i("read[%p]: real: %ld", context->file, real); // done send context->send = real; real = tb_socket_send(context->sock, context->data + context->real, context->send - context->real); if (real >= 0) { // save real context->real += real; // trace // tb_trace_i("send[%p]: real: %ld", context->sock, real); } else { // trace tb_trace_i("send[%p]: closed", context->sock); break; } // ok ok = tb_true; } while (0); // failed or closed? if (!ok) { // exit context tb_demo_context_exit(aiop, context); break; } } // writ? else if (list[i].code & TB_AIOE_CODE_SEND) { // the context tb_demo_context_t* context = (tb_demo_context_t*)list[i].priv; tb_assert_and_check_break(context); // continue to send it if not finished if (context->real < context->send) { // done send tb_long_t real = tb_socket_send(tb_aioo_sock(aioo), context->data + context->real, context->send - context->real); if (real > 0) { // save real context->real += real; // trace // tb_trace_i("send[%p]: real: %ld", tb_aioo_sock(aioo), real); } else { // trace tb_trace_i("send[%p]: closed", tb_aioo_sock(aioo)); // exit context tb_demo_context_exit(aiop, context); break; } } // finished? read file else if (context->left) { // init context->real = 0; context->send = 0; // done read tb_size_t tryn = 1; tb_long_t real = 0; while (!(real = tb_file_read(context->file, context->data, tb_min((tb_size_t)context->left, TB_DEMO_FILE_READ_MAXN))) && tryn--); if (real > 0) { // save left context->left -= real; // trace // tb_trace_i("read[%p]: real: %ld", context->file, real); // done send context->send = real; real = tb_socket_send(tb_aioo_sock(aioo), context->data, context->send); if (real >= 0) { // save real context->real += real; // trace // tb_trace_i("send[%p]: real: %ld", tb_aioo_sock(aioo), real); } else { // trace tb_trace_i("send[%p]: closed", tb_aioo_sock(aioo)); // exit context tb_demo_context_exit(aiop, context); break; } } else { // trace tb_trace_i("read[%p]: closed", tb_aioo_sock(aioo)); // exit context tb_demo_context_exit(aiop, context); break; } } else { // trace tb_trace_i("read[%p]: closed", tb_aioo_sock(aioo)); // exit context tb_demo_context_exit(aiop, context); break; } } // error? else { tb_trace_i("aioe[%p]: unknown code: %lu", tb_aioo_sock(aioo), list[i].code); break; } } } } while (0); // trace tb_trace_i("end"); // exit socket if (sock) tb_socket_exit(sock); // exit aiop if (aiop) tb_aiop_exit(aiop); // end return 0; }
static tb_bool_t it_inject(pid_t pid, tb_char_t const* path) { // check tb_assert_and_check_return_val(pid && path, tb_false); // trace tb_trace_d("inject: pid: %lu, path: %s: ..", (tb_size_t)pid, path); #ifdef TB_ARCH_ARM64 // uses libsubstrate first? if (tb_file_info("/usr/lib/libsubstrate.dylib", tb_null)) { // init library tb_bool_t ok = tb_false; tb_handle_t library = tb_dynamic_init("/usr/lib/libsubstrate.dylib"); if (library) { // trace tb_trace_d("library: %p", library); // the func it_MSHookProcess_t pMSHookProcess = tb_dynamic_func(library, "MSHookProcess"); if (pMSHookProcess) { // trace tb_trace_d("MSHookProcess: %p", pMSHookProcess); // hook process ok = pMSHookProcess(pid, path)? tb_true : tb_false; } // exit library tb_dynamic_exit(library); // trace tb_trace_i("%s", ok? "ok" : "no"); // ok? return ok; } } #endif // pid => task task_t task = 0; if (task_for_pid(mach_task_self(), (tb_int_t)pid, &task)) { tb_trace_i("task_for_pid: %lu failed, errno: %d", (tb_size_t)pid, errno); return tb_false; } // trace tb_trace_d("task: %u", task); // stuff cpu_type_t cputype; it_addr_bundle_t addrs; if (!it_stuff(task, &cputype, &addrs)) return tb_false; // trace tb_trace_d("dlopen: %p", addrs.dlopen); tb_trace_d("syscall: %p", addrs.syscall); // alloc stack mach_vm_address_t stack_address = 0; if (mach_vm_allocate(task, &stack_address, it_stack_size, VM_FLAGS_ANYWHERE)) return tb_false; // write path mach_vm_address_t stack_end = stack_address + it_stack_size - 0x100; if (mach_vm_write(task, stack_address, (vm_offset_t)it_address_cast(path), strlen(path) + 1)) return tb_false; /* the first one is the return address * * syscall(SYS_bsdthread_create, 0xdeadbeef, 0xdeadbeef, 128 * 1024, 0, 0) */ tb_uint32_t args_32[] = {0, 360, 0xdeadbeef, 0xdeadbeef, 128 * 1024, 0, 0}; tb_uint64_t args_64[] = {0, 360, 0xdeadbeef, 0xdeadbeef, 128 * 1024, 0, 0}; // init thread state union { it_arm_thread_state_t arm; it_arm_thread_state64_t arm64; it_x86_thread_state32_t x86; it_x86_thread_state64_t x64; natural_t nat; }state; thread_state_flavor_t state_flavor; mach_msg_type_number_t state_count; memset(&state, 0, sizeof(state)); // init thread state for the cpu type switch (cputype) { case CPU_TYPE_ARM: { tb_trace_i("cputype: arm"); memcpy(&state.arm.r[0], args_32 + 1, 4 * sizeof(tb_uint32_t)); if (mach_vm_write(task, stack_end, (vm_offset_t)it_address_cast(args_32 + 5), 2 * sizeof(tb_uint32_t))) return tb_false; state.arm.sp = (tb_uint32_t) stack_end; state.arm.pc = (tb_uint32_t) addrs.syscall; state.arm.lr = (tb_uint32_t) args_32[0]; state_flavor = ARM_THREAD_STATE; state_count = sizeof(state.arm) / sizeof(state.nat); // trace tb_trace_d("init: pc: %x", state.arm.pc); tb_trace_d("init: lr: %x", state.arm.lr); tb_trace_d("init: sp: %x", state.arm.sp); } break; case CPU_TYPE_ARM64: { tb_trace_i("cputype: arm64"); memcpy(&state.arm64.x[0], args_64 + 1, 6 * sizeof(tb_uint64_t)); state.arm64.sp = (tb_uint64_t) stack_end; // state.arm64.fp = (tb_uint64_t) stack_end; state.arm64.pc = (tb_uint64_t) addrs.syscall; state.arm64.lr = (tb_uint64_t) args_64[0]; state_flavor = ARM_THREAD_STATE64; state_count = sizeof(state.arm64) / sizeof(state.nat); // trace tb_trace_d("init: pc: %llx", state.arm64.pc); tb_trace_d("init: lr: %llx", state.arm64.lr); tb_trace_d("init: sp: %llx", state.arm64.sp); } break; case CPU_TYPE_X86: { tb_trace_i("cputype: x86"); if (mach_vm_write(task, stack_end, (vm_offset_t)it_address_cast(args_32), 7 * 4)) return tb_false; state.x86.esp = state.x86.ebp = (tb_uint32_t) stack_end; state.x86.eip = (tb_uint32_t)addrs.syscall; state_flavor = x86_THREAD_STATE32; state_count = sizeof(state.x86) / sizeof(state.nat); } break; case CPU_TYPE_X86_64: { tb_trace_i("cputype: x64"); state.x64.rdi = args_64[1]; state.x64.rsi = args_64[2]; state.x64.rdx = args_64[3]; state.x64.rcx = args_64[4]; state.x64.r8 = args_64[5]; state.x64.r9 = args_64[6]; state.x64.rsp = state.x64.rbp = stack_end; state.x64.rip = addrs.syscall; state_flavor = x86_THREAD_STATE64; state_count = sizeof(state.x64) / sizeof(state.nat); } break; default: tb_trace_i("cputype: unknown: %lx", (tb_size_t)cputype); return tb_false; } // init a remote thread thread_act_t thread = 0; if (thread_create(task, &thread)) return tb_false; // trace tb_trace_d("init: thread: %x", thread); // alloc port mach_port_t exc = 0; mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &exc); if (mach_port_insert_right(mach_task_self(), exc, exc, MACH_MSG_TYPE_MAKE_SEND)) return tb_false; // swap port exception_mask_t em[2]; exception_handler_t eh[2]; exception_behavior_t eb[2]; thread_state_flavor_t ef[2]; mach_msg_type_number_t em_count = 2; if (task_swap_exception_ports(task, EXC_MASK_BAD_ACCESS, exc, EXCEPTION_STATE_IDENTITY, state_flavor, em, &em_count, eh, eb, ef)) return tb_false; tb_assert_and_check_return_val(em_count <= 1, tb_false); // resume thread, done: syscall(SYS_bsdthread_create, 0xdeadbeef, 0xdeadbeef, 128 * 1024, 0, 0) if (thread_set_state(thread, state_flavor, &state.nat, state_count)) return tb_false; if (thread_resume(thread)) return tb_false; // we expect three exceptions: one from thread when it returns, one from the new thread when it calls the fake handler, and one from the new thread when it returns from dlopen. tb_bool_t started_dlopen = tb_false; while (1) { // recv msg it_exception_message_t msg; if (mach_msg_overwrite(tb_null, MACH_RCV_MSG, 0, sizeof(msg), exc, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL, (tb_pointer_t) &msg, sizeof(msg))) return tb_false; // trace tb_trace_d("recv: msg: from thread: %x", msg.thread.name); // check tb_assert_and_check_return_val((msg.Head.msgh_bits & MACH_MSGH_BITS_COMPLEX), tb_false); tb_assert_and_check_return_val((msg.msgh_body.msgh_descriptor_count != 0), tb_false); tb_assert_and_check_return_val((msg.Head.msgh_size >= offsetof(it_exception_message_t, old_state)), tb_false); tb_assert_and_check_return_val((msg.old_stateCnt == state_count), tb_false); tb_assert_and_check_return_val((msg.Head.msgh_size >= offsetof(it_exception_message_t, old_state) + msg.old_stateCnt * sizeof(natural_t)), tb_false); // the msg state memcpy(&state, msg.old_state, sizeof(state)); // dump // tb_dump_data((tb_byte_t const*)&state, sizeof(state)); // done if (msg.thread.name == thread) { tb_trace_d("terminate"); if (thread_terminate(thread)) return tb_false; } else { // init cond tb_bool_t cond = tb_false; switch(cputype) { case CPU_TYPE_ARM: { // trace tb_trace_d("recv: pc: %x", state.arm.pc); tb_trace_d("recv: lr: %x", state.arm.lr); tb_trace_d("recv: sp: %x", state.arm.sp); // cond cond = ((state.arm.pc & ~1) == 0xdeadbeee)? tb_true : tb_false; } break; case CPU_TYPE_ARM64: { // trace tb_trace_d("recv: pc: %llx", state.arm64.pc); tb_trace_d("recv: lr: %llx", state.arm64.lr); tb_trace_d("recv: sp: %llx", state.arm64.sp); // cond cond = ((state.arm64.pc & ~1) == 0xdeadbeee)? tb_true : tb_false; } break; case CPU_TYPE_X86: cond = (state.x86.eip == 0xdeadbeef)? tb_true : tb_false; break; case CPU_TYPE_X86_64: cond = (state.x64.rip == 0xdeadbeef)? tb_true : tb_false; break; } tb_trace_d("cond: %d, started_dlopen: %d", cond, started_dlopen); if (!cond) { // let the normal crash mechanism handle it task_set_exception_ports(task, em[0], eh[0], eb[0], ef[0]); tb_assert_and_check_return_val(0, tb_false); } else if (started_dlopen) { tb_trace_d("terminate"); if (thread_terminate(msg.thread.name)) return tb_false; break; } else { // done: dlopen(path, RTLD_LAZY) switch(cputype) { case CPU_TYPE_ARM: { state.arm.r[0] = (tb_uint32_t) stack_address; state.arm.r[1] = RTLD_LAZY; state.arm.pc = (tb_uint32_t) addrs.dlopen; state.arm.lr = 0xdeadbeef; } break; case CPU_TYPE_ARM64: { state.arm64.x[0] = (tb_uint64_t) stack_address; state.arm64.x[1] = RTLD_LAZY; state.arm64.pc = (tb_uint64_t) addrs.dlopen; state.arm64.lr = 0xdeadbeef; } break; case CPU_TYPE_X86: { tb_uint32_t stack_stuff[3] = {0xdeadbeef, (tb_uint32_t)stack_address, RTLD_LAZY}; if (mach_vm_write(task, (mach_vm_address_t)state.x86.esp, (vm_offset_t)it_address_cast(&stack_stuff), sizeof(stack_stuff))) return tb_false; } state.x86.eip = (tb_uint32_t) addrs.dlopen; break; case CPU_TYPE_X86_64: { tb_uint64_t stack_stuff = 0xdeadbeef; if (mach_vm_write(task, (mach_vm_address_t)state.x64.rsp, (vm_offset_t)it_address_cast(&stack_stuff), sizeof(stack_stuff))) return tb_false; state.x64.rip = addrs.dlopen; state.x64.rdi = stack_address; state.x64.rsi = RTLD_LAZY; } break; } it_exception_reply_t reply; memcpy(&reply.Head, &msg.Head, sizeof(mach_msg_header_t)); reply.Head.msgh_bits &= ~MACH_MSGH_BITS_COMPLEX; reply.Head.msgh_size = offsetof(it_exception_reply_t, new_state) + state_count * sizeof(natural_t); reply.Head.msgh_id += 100; memcpy(&reply.NDR, &msg.NDR, sizeof(NDR_record_t)); reply.RetCode = 0; reply.flavor = state_flavor; reply.new_stateCnt = state_count; memcpy(&reply.new_state, &state, sizeof(state)); if (thread_set_state(msg.thread.name, state_flavor, &state.nat, state_count)) return tb_false; if (mach_msg(&reply.Head, MACH_SEND_MSG, reply.Head.msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL)) return tb_false; started_dlopen = tb_true; } } } // exit if (stack_address) vm_deallocate(task, stack_address, it_stack_size); if (thread) { thread_terminate(thread); mach_port_deallocate(mach_task_self(), thread); } if (task) mach_port_deallocate(mach_task_self(), task); if (exc) mach_port_deallocate(mach_task_self(), exc); // ok tb_trace_i("ok"); return tb_true; }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t tb_demo_utils_option_main(tb_int_t argc, tb_char_t** argv) { // init option tb_option_ref_t option = tb_option_init("option", "the option command test demo", g_options); if (option) { // done option if (tb_option_done(option, argc - 1, &argv[1])) { // done dump tb_option_dump(option); // done help if (tb_option_find(option, "help")) tb_option_help(option); // done version else if (tb_option_find(option, "version")) { tb_version_t const* version = tb_version(); if (version) tb_trace_i("version: tbox-v%u.%u.%u.%llu", version->major, version->minor, version->alter, version->build); } else { // done integer if (tb_option_find(option, "i")) tb_trace_i("integer: %lld", tb_option_item_sint64(option, "i")); // done string if (tb_option_find(option, "s")) tb_trace_i("string: %s", tb_option_item_cstr(option, "s")); #ifdef TB_CONFIG_TYPE_HAVE_FLOAT // done float if (tb_option_find(option, "f")) tb_trace_i("float: %f", tb_option_item_float(option, "f")); #endif // done boolean if (tb_option_find(option, "b")) tb_trace_i("boolean: %s", tb_option_item_bool(option, "b")? "y" : "n"); // done demo if (tb_option_find(option, "demo")) tb_trace_i("demo: %s", tb_option_item_cstr(option, "demo")); // done file0 if (tb_option_find(option, "file0")) tb_trace_i("file0: %s", tb_option_item_cstr(option, "file0")); // done file1 if (tb_option_find(option, "file1")) tb_trace_i("file1: %s", tb_option_item_cstr(option, "file1")); // done more tb_size_t more = 0; while (1) { tb_char_t name[64] = {0}; tb_snprintf(name, 63, "more%lu", more++); if (tb_option_find(option, name)) tb_trace_i("%s: %s", name, tb_option_item_cstr(option, name)); else break; } } } else tb_option_help(option); // exit option tb_option_exit(option); } return 0; }
static tb_void_t tb_test_heap_min_func() { // init heap tb_heap_ref_t heap = tb_heap_init(16, tb_element_uint32()); tb_assert_and_check_return(heap); // clear rand tb_random_clear(tb_null); // make heap tb_size_t i = 0; for (i = 0; i < 100; i++) { // the value tb_uint32_t val = tb_random_range(tb_null, 0, 50); // trace // tb_trace_i("heap_min: put: %u", val); // put it tb_heap_put(heap, tb_u2p(val)); } // clear rand tb_random_clear(tb_null); // remove some values for (i = 0; i < 100; i++) { // the value tb_uint32_t val = tb_random_range(tb_null, 0, 50); // remove it? if (!(i & 3)) { tb_size_t itor = tb_find_all(heap, tb_u2p(val)); if (itor != tb_iterator_tail(heap)) tb_heap_remove(heap, itor); } } // append heap for (i = 0; i < 30; i++) { // the value tb_uint32_t val = tb_random_range(tb_null, 0, 50); // put it tb_heap_put(heap, tb_u2p(val)); } // trace tb_trace_i(""); // dump heap while (tb_heap_size(heap)) { // put it tb_uint32_t val = (tb_uint32_t)(tb_size_t)tb_heap_top(heap); // trace tb_trace_i("heap_min: pop: %u", val); // pop it tb_heap_pop(heap); } // exit heap tb_heap_exit(heap); }