### Coroutine Yield Example in C Source: https://github.com/tboox/tbox/wiki/Stackfull-Coroutines Demonstrates how to use the 'yield' feature of the Tbox coroutine library. It initializes the Tbox environment, sets up a scheduler, and starts multiple coroutines that yield execution. The example shows starting coroutines with default and specified stack sizes, and running the scheduler loop. ```c static tb_void_t switchfunc(tb_cpointer_t priv) { tb_size_t count = (tb_size_t)priv; while (count--) { // trace tb_trace_i("[coroutine: %p]: %lu", tb_coroutine_self(), count); // yield tb_coroutine_yield(); } } 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_co_scheduler_ref_t scheduler = tb_co_scheduler_init(); if (scheduler) { // start coroutine with the default stack size tb_coroutine_start(scheduler, switchfunc, (tb_cpointer_t)10, 0); // start coroutine with stack size (8192) tb_coroutine_start(scheduler, switchfunc, (tb_cpointer_t)10, 8192); // run scheduler loop tb_co_scheduler_loop(scheduler, tb_true); // exit scheduler tb_co_scheduler_exit(scheduler); } // exit tbox tb_exit(); } ``` -------------------------------- ### Tbox Server Accept Example in C Source: https://github.com/tboox/tbox/wiki/使用aicp实现事件回调模式 This C code demonstrates setting up a TCP server using the Tbox library. It initializes the library, creates an acceptor (aico) for the global acceptor pool, opens a TCP socket, binds it to port 9090, starts listening, and registers a callback function to handle incoming connection requests. The server then waits for user input before exiting. ```c /* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t main(tb_int_t argc, tb_char_t** argv) { // check tb_assert_and_check_return_val(argv[1], 0); // done tb_aico_ref_t aico = tb_null; do { // 初始化tbox库 if (!tb_init(tb_null, tb_null, 0)) break; /* 初始化一个用于监听的aico对象 * * 注:这里为了简化代码,直接使用了全局的tb_aicp()对象, * 全局的aicp对象,用起来更加方便,内部回去自己开一个线程运行loop来驱动 * 一般用于客户端应用。 * * 如果想要更高的并发性能,启用更多的线程去驱动loop,需要手动调用tb_aicp_init,指定需要的并发量,来创建。 * 并且需要手动运行tb_aicp_loop */ aico = tb_aico_init(tb_aicp()); tb_assert_and_check_break(aico); // 打开这个aico对象,并为其创建一个tcp socket if (!tb_aico_open_sock_from_type(aico, TB_SOCKET_TYPE_TCP)) break; // 绑定监听端口 if (!tb_socket_bind(tb_aico_sock(aico), tb_null, 9090)) break; // 设置监听 if (!tb_socket_listen(tb_aico_sock(aico), 20)) break; /* 投递accept事件,仅需一次投递 * * 注: * 只有accept事件是一次投递,长期有效,只要有事件过来,就回去调用对应的回调函数 * 不需要重复投递,这样设计也是为了尽可能的接受更多地并发连接 */ if (!tb_aico_acpt(aico, tb_demo_sock_acpt_func, argv[1])) break; // 等待 getchar(); } while (0); // exit tbox tb_exit(); return 0; } ``` -------------------------------- ### Tbox C Example: Initialization, Tracing, Vector, and Stream Source: https://github.com/tboox/tbox/wiki/Home This C code example demonstrates fundamental tbox library functionalities. It covers initialization and exit, basic tracing messages, creating and manipulating a string vector, and reading data from an HTTP stream. It showcases the integration of different tbox modules. ```c #include "tbox/tbox.h" int main(int argc, char** argv) { // init tbox if (!tb_init(tb_null, tb_null)) return 0; // trace tb_trace_i("hello tbox"); // init vector tb_vector_ref_t vector = tb_vector_init(0, tb_element_str(tb_true)); if (vector) { // insert item tb_vector_insert_tail(vector, "hello"); tb_vector_insert_tail(vector, "tbox"); // dump all items tb_for_all (tb_char_t const*, cstr, vector) { // trace tb_trace_i("%s", cstr); } // exit vector tb_vector_exit(vector); } // init stream tb_stream_ref_t stream = tb_stream_init_from_url("http://www.xxx.com/file.txt"); if (stream) { // open stream if (tb_stream_open(stream)) { // read line tb_long_t size = 0; tb_char_t line[TB_STREAM_BLOCK_MAXN]; while ((size = tb_stream_bread_line(stream, line, sizeof(line))) >= 0) { // trace tb_trace_i("line: %s", line); } } // exit stream tb_stream_exit(stream); } // wait tb_getchar(); // exit tbox tb_exit(); return 0; } ``` -------------------------------- ### Tbox Stackless Coroutine Scheduling Example Source: https://github.com/tboox/tbox/wiki/Stackless-Coroutines Demonstrates initializing a tbox scheduler, starting multiple stackless coroutines, and running the scheduler loop. It includes a `switchtask` function that decrements a counter within each coroutine before yielding. The `test` function orchestrates the entire process, from initialization to cleanup. ```c static tb_void_t switchtask(tb_lo_coroutine_ref_t coroutine, tb_cpointer_t priv) { // check tb_size_t* count = (tb_size_t*)priv; // enter coroutine tb_lo_coroutine_enter(coroutine) { // loop while ((*count)--) { // trace tb_trace_i("[coroutine: %p]: %lu", tb_lo_coroutine_self(), *count); // yield tb_lo_coroutine_yield(); } } } static tb_void_t test() { // init scheduler tb_lo_scheduler_ref_t scheduler = tb_lo_scheduler_init(); if (scheduler) { // start coroutines tb_size_t counts[] = {10, 10}; 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, tb_true); // exit scheduler tb_lo_scheduler_exit(scheduler); } } ``` -------------------------------- ### Basic tbox Usage Example Source: https://github.com/tboox/tbox/blob/master/README.md Demonstrates the basic initialization, usage of the vector container, and exit procedures in tbox. It initializes tbox, creates a vector, inserts string elements, iterates through them, and then cleans up. ```c #include "tbox/tbox.h" int main(int argc, char** argv) { if (!tb_init(tb_null, tb_null)) return 0; tb_vector_ref_t vector = tb_vector_init(0, tb_element_str(tb_true)); if (vector) { tb_vector_insert_tail(vector, "hello"); tb_vector_insert_tail(vector, "tbox"); tb_for_all (tb_char_t const*, cstr, vector) { tb_trace_i("%s", cstr); } tb_vector_exit(vector); } tb_exit(); return 0; } ``` -------------------------------- ### Basic Tbox C example with initialization and output Source: https://github.com/tboox/tbox/wiki/v1.5.x编译 A simple C program demonstrating how to initialize the Tbox library, perform basic operations like printing output and assertions, and properly exit the library environment. It highlights the necessity of tb_init() and tb_exit(). ```c #include "tbox/tbox.h" int main(int argv, char** argv) { // Initialize the entire tbox library environment, this is required, but only needs to be executed at the beginning of the program if (!tb_init(tb_null, tb_null)) return 0; // Print output, you need to add newline characters yourself tb_printf("hello world!\n"); // Only print output in debug tb_trace_d("hello world"); // Print output in debug/release tb_trace_i("hello world"); // Assertion detection in debug tb_assert(1 == 1); tb_assert_abort(1 != 2); // Wait indefinitely getchar(); // Exit the entire tbox environment, this step will release all resources occupied by tbox. If it is a debug version, it will also output memory leak detection information to the terminal, etc. tb_exit(); return 0; } ``` -------------------------------- ### Install Compiled Files for Tbox Project Source: https://github.com/tboox/tbox/wiki/编译参数说明 The 'make install' or 'make i' command installs all compiled files, including object files, into the 'tbox/bin' directory. 'make prefix' or 'make p' installs only libraries and header files to the directory specified by PREFIX. ```bash # Install all files to tbox/bin directory make install # Shorthand for install make i # Install only libraries and header files to the directory specified by PREFIX make prefix # Shorthand for prefix installation make p ``` -------------------------------- ### C XML SAX Parsing Example Source: https://context7.com/tboox/tbox/llms.txt Demonstrates how to initialize and use the Tbox XML reader for SAX-style parsing of an XML file. It iterates through parsing events such as document start, element start/end, text content, and CDATA sections. Requires the tbox library. ```c #include "tbox/tbox.h" int main(int argc, char** argv) { if (!tb_init(tb_null, tb_null)) return 0; // Initialize XML reader tb_xml_reader_ref_t reader = tb_xml_reader_init(); if (reader) { // Open XML from file URL if (tb_xml_reader_open(reader, tb_stream_init_from_url("file://document.xml"), tb_true)) { // Optional: Navigate to specific element using XPath-like syntax // tb_xml_reader_goto(reader, "root.items.item"); // Parse XML events tb_size_t event = TB_XML_READER_EVENT_NONE; while ((event = tb_xml_reader_next(reader))) { switch (event) { case TB_XML_READER_EVENT_DOCUMENT: tb_printf("\n", tb_xml_reader_version(reader), tb_xml_reader_charset(reader)); break; case TB_XML_READER_EVENT_ELEMENT_BEG: { tb_size_t level = tb_xml_reader_level(reader); for (tb_size_t i = 1; i < level; i++) tb_printf(" "); tb_printf("<%s", tb_xml_reader_element(reader)); // Print attributes tb_xml_node_ref_t attr = tb_xml_reader_attributes(reader); 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 level = tb_xml_reader_level(reader); for (tb_size_t i = 0; i < level; i++) tb_printf(" "); tb_printf("\n", tb_xml_reader_element(reader)); } break; case TB_XML_READER_EVENT_ELEMENT_EMPTY: { tb_size_t level = tb_xml_reader_level(reader); for (tb_size_t i = 0; i < level; i++) tb_printf(" "); tb_printf("<%s/>\n", tb_xml_reader_element(reader)); } break; case TB_XML_READER_EVENT_TEXT: { tb_size_t level = tb_xml_reader_level(reader); for (tb_size_t i = 0; i < level; i++) tb_printf(" "); tb_printf("%%s\n", tb_xml_reader_text(reader)); } break; case TB_XML_READER_EVENT_CDATA: tb_printf("\n", tb_xml_reader_cdata(reader)); break; case TB_XML_READER_EVENT_COMMENT: tb_printf("\n", tb_xml_reader_comment(reader)); break; } } } tb_xml_reader_exit(reader); } tb_exit(); return 0; } ``` -------------------------------- ### Start HTTP Server Listening with Tbox Source: https://github.com/tboox/tbox/wiki/利用asio开发的轻量级高性能http服务器 Configures the Tbox demo HTTP server to start listening for incoming connections. It uses the previously initialized network socket and sets up an asynchronous acceptor for handling new client requests. This function is typically called after the server is initialized. ```c static tb_void_t tb_demo_httpd_done(tb_demo_httpd_t* httpd) { // check tb_assert_and_check_return(httpd && httpd->aicp && httpd->aico); // done listen if (!tb_aico_acpt(httpd->aico, tb_demo_httpd_acpt, httpd)) return ; // wait some time getchar(); } ``` -------------------------------- ### Main Function for Tbox HTTP Server Source: https://github.com/tboox/tbox/wiki/利用asio开发的轻量级高性能http服务器 The main entry point for the Tbox demo HTTP server application. It initializes the Tbox library, starts the HTTP server using configuration from command-line arguments, and then proceeds to shut down the server and Tbox resources. It handles basic argument parsing for the server root directory. ```c tb_int_t main(tb_int_t argc, tb_char_t** argv) { // init tbox if (!tb_init(tb_null, tb_null, 0)) return 0; // init httpd tb_demo_httpd_t* httpd = tb_demo_httpd_init(argv[1]); if (httpd) { // done httpd tb_demo_httpd_done(httpd); // exit httpd tb_demo_httpd_exit(httpd); } // exit tbox tb_exit(); return 0; } ``` -------------------------------- ### Hash Map Operations in TBOX Source: https://context7.com/tboox/tbox/llms.txt Details the operations for the TBOX hash map, a key-value storage. This example shows how to initialize a hash map with string keys and long integer values, insert pairs, retrieve values, check for key existence, get the size, remove entries, and iterate through all key-value pairs. ```c #include "tbox/tbox.h" int main(int argc, char** argv) { if (!tb_init(tb_null, tb_null)) return 0; // Create hash map: string keys -> integer values tb_hash_map_ref_t map = tb_hash_map_init(8, tb_element_str(tb_true), tb_element_long()); if (map) { // Insert key-value pairs tb_hash_map_insert(map, "hello", (tb_pointer_t)5); tb_hash_map_insert(map, "world", (tb_pointer_t)5); tb_hash_map_insert(map, "tbox", (tb_pointer_t)4); // Retrieve values tb_size_t len = (tb_size_t)tb_hash_map_get(map, "hello"); tb_assert(len == 5); // Check if key exists if (tb_hash_map_get(map, "tbox")) { tb_trace_i("Key 'tbox' found"); } // Get map size tb_size_t size = tb_hash_map_size(map); tb_trace_i("Map size: %lu", size); // Remove key tb_hash_map_remove(map, "hello"); // Iterate through all entries tb_for_all (tb_hash_map_item_ref_t, item, map) { tb_trace_i("Key: %s, Value: %lu", (tb_char_t const*)item->name, (tb_size_t)item->data); } tb_hash_map_exit(map); } tb_exit(); return 0; } ``` -------------------------------- ### JSON Configuration Example for PolarSSL Package Source: https://github.com/tboox/tbox/wiki/实现json解析工具jcat This JSON snippet defines the configuration for the PolarSSL package, including format details, package information, and compiler settings for various platforms and architectures. It demonstrates the use of macro paths (e.g., $.compiler.default.debug) to reference other configuration sections, reducing redundancy. ```json { "format": { "name": "The TBOOX Package Format" , "version": "v1.0.1" , "website": "http://www.tboox.org" } , "package": { "name": "The PolarSSL Library" , "website": "http://www.polarssl.org" } , "compiler": { "default": { "debug": { "libs": "polarssl" , "libpath": "" , "incpath": "" , "libflags": "" , "incflags": "" } , "release": "$.compiler.default.debug" } , "linux" : { "x64": "$.compiler.default" } , "mac" : { "x86": "$.compiler.default" , "x64": "$.compiler.default" } , "msvc" : { "x86": "$.compiler.default" } , "mingw" : { "x86": "$.compiler.default" } , "cygwin" : { "x86": "$.compiler.default" } , "ios" : { "armv7": "$.compiler.default" , "armv7s": "$.compiler.default" , "arm64": "$.compiler.default" } , "android" : { "armv5te": "$.compiler.default" , "armv6": "$.compiler.default" } } } ``` -------------------------------- ### Configure Tbox build flags for external libraries (MySQL on macOS) Source: https://github.com/tboox/tbox/wiki/v1.5.x编译 Example of how to configure xmake build flags to help it detect and link external libraries, specifically MySQL on macOS. It shows how to specify include paths (-I) and library paths (-L) for the compiler and linker. ```bash xmake f -p macosx -c --ldflags="-L/opt//local/lib/mysql5/mysql" --cxflags="-I/opt/local/include/mysql5/mysql" ``` -------------------------------- ### Process HTTP Request Completion Source: https://github.com/tboox/tbox/wiki/利用asio开发的轻量级高性能http服务器 Handles the completion of an HTTP request, determining the appropriate action based on the method and path. It supports GET requests by initializing and sending files, and returns 'Not Implemented' for other methods. Errors are handled by sending appropriate HTTP status codes. ```c static tb_bool_t tb_demo_httpd_session_reqt_done(tb_demo_httpd_session_t* session) { // check tb_assert_and_check_return_val(session && session->aico, tb_false); // done tb_bool_t ok = tb_false; do { // check tb_check_break(session->code == TB_HTTP_CODE_OK); tb_assert_and_check_break(session->httpd); // get? if (session->method == TB_HTTP_METHOD_GET) { // check path tb_check_break_state(tb_string_size(&session->path), session->code, TB_HTTP_CODE_BAD_REQUEST); // the path tb_char_t const* path = tb_string_cstr(&session->path); tb_check_break_state(!session->file && path, session->code, TB_HTTP_CODE_INTERNAL_SERVER_ERROR); // the full path tb_char_t full[TB_PATH_MAXN] = {0}; tb_long_t size = tb_snprintf(full, sizeof(full) - 1, "%s%s%s", session->httpd->root, path[0] != '/'? "/" : "", path); tb_assert_abort(size > 0); // end full[size] = '\0'; // trace tb_trace_d("reqt_done[%p]: full path: %s", session->aico, full); // init file session->file = tb_file_init(full, TB_FILE_MODE_RO | TB_FILE_MODE_BINARY | TB_FILE_MODE_ASIO); tb_check_break_state(session->file, session->code, TB_HTTP_CODE_NOT_FOUND); // send the file if (!tb_demo_httpd_session_resp_send_done(session)) return tb_false; // ok ok = tb_true; } else { // not implemented session->code = TB_HTTP_CODE_NOT_IMPLEMENTED; break; } } while (0); // error? if (!ok) { // save code if (session->code == TB_HTTP_CODE_OK) session->code = TB_HTTP_CODE_INTERNAL_SERVER_ERROR; // send the error info if (!tb_demo_httpd_session_resp_send_done(session)) return tb_false; } // ok return tb_true; } ``` -------------------------------- ### TBOX C Iterator Examples: List Traversal and Filtering Source: https://github.com/tboox/tbox/wiki/迭代器的使用 Demonstrates common iterator usage patterns with TBOX's C container library. It covers initializing a list, inserting elements, and iterating forward, conditionally, in reverse, and partially using macros like `tb_for_all`, `tb_for_all_if`, `tb_rfor_all`, `tb_rfor_all_if`, and `tb_for`. It highlights how these macros abstract manual iterator management. ```c // Initialize a doubly linked list, element type tb_long_t, auto-grows at 256 elements tb_list_ref_t list = tb_list_init(256, tb_element_long()); if (list) { // Insert some elements tb_list_insert_tail(list, (tb_cpointer_t)1); tb_list_insert_tail(list, (tb_cpointer_t)2); tb_list_insert_tail(list, (tb_cpointer_t)3); tb_list_insert_tail(list, (tb_cpointer_t)4); tb_list_insert_tail(list, (tb_cpointer_t)5); // Iterate and print all elements tb_for_all (tb_long_t, item, list) { tb_trace_i("item: %ld", item); } // Iterate and print elements greater than 3 tb_for_all_if (tb_long_t, item2, list, item2 > 3) { tb_trace_i("item: %ld", item2); } // Reverse iterate and print all elements (Note: single linked list does not support reverse iteration) tb_rfor_all (tb_long_t, item3, list) { tb_trace_i("item: %ld", item3); } // Reverse iterate and print elements greater than 3 tb_rfor_all_if (tb_long_t, item4, list, item4 > 3) { tb_trace_i("item: %ld", item4); } // Partial iteration using head and tail iterators tb_for (tb_long_t, item5, tb_iterator_head(list), tb_iterator_tail(list), list) { tb_trace_i("item: %ld", item5); } // Exit the list tb_list_exit(list); } ``` -------------------------------- ### Initialize Hash Map with Custom Comparison and Free Functions (C) Source: https://github.com/tboox/tbox/wiki/hash_map的使用 Demonstrates initializing a hash map with custom comparison and member release functions. This example configures a long integer element type to use a reverse comparison function and a pointer type to use a custom free function, allowing for specialized data handling. Dependencies include TBOX and custom function definitions. ```c // Initialize long integer comparison function tb_element_t element = tb_element_long(); // Replace comparison function, ptr has a convenient way to pass, but can also be passed like this element.comp = tb_hash_map_item_long_comp; // Initialize hash_map tb_hash_map_ref_t hash_map = tb_hash_map_init(0, element, tb_element_ptr(tb_hash_map_item_ptr_free, "private data")); ``` -------------------------------- ### C: Coroutine Channel Communication with Tbox Source: https://context7.com/tboox/tbox/llms.txt This C code snippet demonstrates how to use Tbox's coroutine channels for inter-coroutine communication. It initializes a buffered channel, starts multiple sender and receiver coroutines that communicate via this channel, and then runs the scheduler until all coroutines complete. The channel handles blocking automatically when full or empty. ```c #include "tbox/tbox.h" static tb_void_t sender_coroutine(tb_cpointer_t priv) { tb_co_channel_ref_t channel = (tb_co_channel_ref_t)priv; for (tb_size_t i = 0; i < 10; i++) { tb_trace_i("[Sender %p]: Sending %lu", tb_coroutine_self(), i); // Send data through channel (blocks if full) tb_co_channel_send(channel, (tb_cpointer_t)i); tb_trace_i("[Sender %p]: Sent %lu", tb_coroutine_self(), i); } } static tb_void_t receiver_coroutine(tb_cpointer_t priv) { tb_co_channel_ref_t channel = (tb_co_channel_ref_t)priv; for (tb_size_t i = 0; i < 10; i++) { tb_trace_i("[Receiver %p]: Waiting for data", tb_coroutine_self()); // Receive data from channel (blocks if empty) tb_size_t data = (tb_size_t)tb_co_channel_recv(channel); tb_trace_i("[Receiver %p]: Received %lu", tb_coroutine_self(), data); } } int main(int argc, char** argv) { if (!tb_init(tb_null, tb_null)) return 0; // Initialize coroutine scheduler tb_co_scheduler_ref_t scheduler = tb_co_scheduler_init(); if (scheduler) { // Create channel with buffer size 5 // Parameters: buffer_size, item_func, item_size tb_co_channel_ref_t channel = tb_co_channel_init(5, tb_null, 0); if (channel) { // Start multiple sender coroutines tb_coroutine_start(scheduler, sender_coroutine, channel, 0); tb_coroutine_start(scheduler, sender_coroutine, channel, 0); // Start multiple receiver coroutines tb_coroutine_start(scheduler, receiver_coroutine, channel, 0); tb_coroutine_start(scheduler, receiver_coroutine, channel, 0); // Run scheduler until all coroutines complete tb_hong_t start_time = tb_mclock(); tb_co_scheduler_loop(scheduler, tb_true); tb_hong_t duration = tb_mclock() - start_time; tb_trace_i("All coroutines completed in %lld ms", duration); // Cleanup tb_co_channel_exit(channel); } tb_co_scheduler_exit(scheduler); } tb_exit(); return 0; } ``` -------------------------------- ### Initialize HTTP Server with Tbox Source: https://github.com/tboox/tbox/wiki/利用asio开发的轻量级高性能http服务器 Initializes the Tbox demo HTTP server, setting up the root directory, port, and network sockets. It requires a root path as input and returns a pointer to the initialized server structure or null on failure. Dependencies include Tbox's memory allocation and networking functions. ```c static tb_demo_httpd_t* tb_demo_httpd_init(tb_char_t const* root) { // done tb_bool_t ok = tb_false; tb_demo_httpd_t* httpd = tb_null; do { // make httpd httpd = tb_malloc0_type(tb_demo_httpd_t); tb_assert_and_check_break(httpd); // init root if (root) tb_strlcpy(httpd->root, root, sizeof(httpd->root)); else tb_directory_curt(httpd->root, sizeof(httpd->root)); httpd->root[sizeof(httpd->root) - 1] = '\0'; tb_assert_and_check_break(tb_file_info(httpd->root, tb_null)); // init port httpd->port = TB_DEMO_HTTPD_PORT; // trace tb_trace_d("init: %s: %u", httpd->root, httpd->port); // init aicp httpd->aicp = tb_aicp(); tb_assert_and_check_break(httpd->aicp); // init aico httpd->aico = tb_aico_init(httpd->aicp); tb_assert_and_check_break(httpd->aico); // open aico if (!tb_aico_open_sock_from_type(httpd->aico, TB_SOCKET_TYPE_TCP)) break; // bind port if (!tb_socket_bind(tb_aico_sock(httpd->aico), tb_null, httpd->port)) break; // listen sock if (!tb_socket_listen(tb_aico_sock(httpd->aico), TB_DEMO_HTTPD_SESSION_MAXN >> 2)) break; // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit httpd if (httpd) tb_demo_httpd_exit(httpd); httpd = tb_null; } // ok? return httpd; } ``` -------------------------------- ### Coroutine Suspend and Resume Example in C Source: https://github.com/tboox/tbox/wiki/Stackfull-Coroutines Demonstrates the suspend and resume capabilities of the Tbox coroutine library. This allows a coroutine to pause its execution and be resumed later, optionally passing data between them. The example shows one coroutine resuming another and passing string data. ```c static tb_void_t resumefunc(tb_cpointer_t priv) { // get coroutine of suspendfunc() tb_coroutine_ref_t coroutine = (tb_coroutine_ref_t)priv; // resume the given coroutine to pass "hello suspend!" tb_char_t const*retval = tb_coroutine_resume(coroutine, "hello suspend!"); // retval is "hello resume!" } static tb_void_t suspendfunc(tb_cpointer_t priv) { // start coroutine of resumefunc() tb_coroutine_start(tb_null, resumefunc, tb_coroutine_self(), 0); // suspend current coroutine and pass "hello resume!" to resumefunc() tb_char_t const* retval = tb_coroutine_suspend("hello resume!"); // retval is "hello suspend!" } ``` -------------------------------- ### Spider Initialization from Arguments Source: https://github.com/tboox/tbox/wiki/利用传输池和线程池实现一个简单的横向爬虫 Initializes the spider structure using command-line arguments. It parses options for home directory, user agent, timeout, and rate limiting. It utilizes the `tb_option` library for argument parsing and includes basic assertion checks. ```c static tb_bool_t tb_demo_spider_init(tb_demo_spider_t* spider, tb_int_t argc, tb_char_t** argv) { // check tb_assert_and_check_return_val(spider && argc && argv, tb_false); // done tb_bool_t ok = tb_false; do { // init option spider->option = tb_option_init("spider", "the spider demo", g_options); tb_assert_and_check_break(spider->option); // done option if (!tb_option_done(spider->option, argc - 1, &argv[1])) break; // init home spider->home = tb_option_item_cstr(spider->option, "home"); tb_assert_and_check_break(spider->home); tb_trace_d("home: %s", spider->home); // init root tb_char_t const* root = tb_option_item_cstr(spider->option, "directory"); // init user agent spider->user_agent = tb_option_item_cstr(spider->option, "agent"); // init timeout if (tb_option_find(spider->option, "timeout")) spider->timeout = tb_option_item_sint32(spider->option, "timeout"); // init limited rate if (tb_option_find(spider->option, "rate")) ``` -------------------------------- ### Build tbox using configure and make Source: https://github.com/tboox/tbox/blob/master/README.md Builds the tbox project using the traditional configure and make commands. This method is an alternative to xmake. ```console $ ./configure $ make ``` -------------------------------- ### C: Post a Timer Task After a Delay Source: https://github.com/tboox/tbox/wiki/高精度定时器的使用 Posts a timer task to the global timer that starts its 1000ms interval execution after a 10-second delay. The task is set to repeat. `tb_demo_timer_task_func` is the callback, and `tb_null` is the user data. ```c // Post a timer task to the global timer after a 10s delay, with a 1000ms interval, repeating execution. tb_timer_task_post_after(tb_timer(), 10000, 1000, tb_true, tb_demo_timer_task_func, tb_null); ``` -------------------------------- ### C HTTP Client: Make Request with Custom Headers and Cookies Source: https://context7.com/tboox/tbox/llms.txt This C code snippet demonstrates how to initialize an HTTP client using the TBOX library, set custom headers like 'User-Agent', enable cookie support, and configure a callback for response headers. It also shows how to set a URL, establish a connection, and read response data. ```c #include "tbox/tbox.h" static tb_bool_t http_header_callback(tb_char_t const* line, tb_cpointer_t priv) { tb_trace_i("Response header: %s", line); return tb_true; } int main(int argc, char** argv) { if (!tb_init(tb_null, tb_null)) return 0; tb_http_ref_t http = tb_null; do { // Initialize HTTP client http = tb_http_init(); if (!http) break; // Set cookie support if (!tb_http_ctrl(http, TB_HTTP_OPTION_SET_COOKIES, tb_cookies())) break; // Set header callback for debugging if (!tb_http_ctrl(http, TB_HTTP_OPTION_SET_HEAD_FUNC, http_header_callback)) break; // Set target URL if (!tb_http_ctrl(http, TB_HTTP_OPTION_SET_URL, "http://www.example.com/api/data")) break; // Set custom headers if (!tb_http_ctrl(http, TB_HTTP_OPTION_SET_HEAD, "User-Agent", "TBOX-HTTP-Client/1.0")) break; // Set timeout (in milliseconds) if (!tb_http_ctrl(http, TB_HTTP_OPTION_SET_TIMEOUT, 10000)) break; // Open HTTP connection tb_hong_t start_time = tb_mclock(); if (!tb_http_open(http)) { tb_trace_e("Failed to open HTTP connection"); break; } tb_hong_t connect_time = tb_mclock() - start_time; tb_trace_i("Connected in %lld ms", connect_time); // Get response status tb_http_status_ref_t status = tb_http_status(http); tb_trace_i("Content-Length: %llu bytes", status->content_size); // Read response data tb_byte_t buffer[8192]; tb_hize_t total_read = 0; tb_size_t timeout = 30000; while (1) { tb_long_t real = tb_http_read(http, buffer, sizeof(buffer)); if (real > 0) { total_read += real; tb_trace_i("Read %ld bytes (total: %llu)", real, total_read); // Process data (e.g., write to file, parse JSON, etc.) // fwrite(buffer, 1, real, output_file); } else if (real == 0) { // Wait for more data tb_long_t wait = tb_http_wait(http, TB_SOCKET_EVENT_RECV, timeout); if (wait < 0) break; // Error if (wait == 0) break; // Timeout // Continue reading } else { break; // Error } // Check if complete if (status->content_size && total_read >= status->content_size) break; } tb_trace_i("Successfully downloaded %llu bytes", total_read); } while (0); if (http) tb_http_exit(http); tb_exit(); return 0; } ``` -------------------------------- ### Get Stream State (C) Source: https://github.com/tboox/tbox/wiki/流的读写 Retrieves the current state of a stream. This is useful for diagnosing read or open failures. The function returns a `tb_size_t` representing the state code. An auxiliary function `tb_state_cstr` can convert this code into a human-readable string. ```c tb_size_t state = tb_stream_state(stream); // 将状态码转成字符串 tb_char_t const* state_cstr = tb_state_cstr(state); ``` -------------------------------- ### Initialize and Query MySQL Database Source: https://github.com/tboox/tbox/wiki/数据库的使用 This C code snippet demonstrates how to initialize a MySQL database connection, open the connection, execute a SQL query, load the results, iterate through them, and finally close the connection. It handles potential errors during each step and shows how to access column names and values. ```c /* Initialize a mysql database * * localhost: Hostname, can also be an IP address * type: Database type, currently supports: mysql and sqlite3 * username: Database username * password: Database user password * database: The database name to access. If not set, it automatically connects to the default database. * * If specifying a port in reverse, you can pass it explicitly: * "sql://localhost:3306/?type=mysql&username=xxxx&password=xxxx&database=xxxx" * * The database access URL for sqlite3 is: * "sql:///home/file.sqlitedb?type=sqlite3" * * Or directly pass the file path: * "/home/file.sqlite3" * "file:///home/file.sqlitedb" * "C://home/file.sqlite3" */ tb_database_sql_ref_t database = tb_database_sql_init("sql://localhost/?type=mysql&username=xxxx&password=xxxx&database=test"); if (database) { // Open the database if (tb_database_sql_open(database)) { // Execute SQL statement for querying if (tb_database_sql_done(database, "select * from test")) { /* Load the result set * * If executing non-select statements like insert, update, etc., this returns tb_null, indicating no result set. * * This result set fully adopts the iterator pattern for fast iteration. * * The parameter tb_true indicates to load all results into memory at once. If successful, * you can get the actual result set row count via tb_iterator_size(result). * * If loading all at once fails or tb_false is passed, it means data can only be fetched row by row using fetch. * This consumes less memory but doesn't allow pre-fetching the actual row count. In this case, tb_iterator_size(result) * returns a very large value. */ tb_iterator_ref_t result = tb_database_sql_result_load(database, tb_true); if (result) { // If loaded all at once successfully, return the actual result row count tb_trace_i("row: size: %lu", tb_iterator_size(result)); // Iterate through all rows tb_for_all_if (tb_iterator_ref_t, row, result, row) { // Display the number of columns in the row tb_trace_i("[row: %lu, col: size: %lu]: ", row_itor, tb_iterator_size(row)); // Iterate through all values in this row tb_for_all_if (tb_database_sql_value_t*, value, row, value) { /* tb_database_sql_value_name(value): Get the column name corresponding to the value * tb_database_sql_value_text(value): Get the text data of the value, if it's of text type * tb_database_sql_value_type(value): Get the type of the value * * ... */ tb_tracet_i("[%s:%s] ", tb_database_sql_value_name(value), tb_database_sql_value_text(value)); } } // Free the result set data tb_database_sql_result_exit(database, result); } } else { // Execution failed, display the failure status and reason tb_trace_e("done %s failed, error: %s", sql, tb_state_cstr(tb_database_sql_state(database))); } } else { // Open failed, display the failure status and reason tb_trace_e("open failed: %s", tb_state_cstr(tb_database_sql_state(database))); } // Exit the database tb_database_sql_exit(database); } ``` -------------------------------- ### Tbox Custom Stream Usage: Sending End (C) Source: https://github.com/tboox/tbox/wiki/自定义流的实现和使用 Example code showing how to use a custom Tbox stream on the sending end. This code continuously pushes data into the stream using `tb_stream_ctrl` with the `TB_STREAM_CTRL_REAL_PUSH` command. This simulates a data source feeding the stream. ```c // 将数据不停的送入stream中 while (1) { // fill data tb_byte_t data[8192]; tb_memset(data, 0xff, sizeof(data)); // push data tb_stream_ctrl(stream, TB_STREAM_CTRL_REAL_PUSH, data, sizeof(data)); } ``` -------------------------------- ### Build tbox for Host Platform using xmake Source: https://github.com/tboox/tbox/blob/master/README.md Builds the tbox project for the current host operating system using the xmake build system. This is the default build command. ```console # build for the host platform $ cd ./tbox $ xmake ``` -------------------------------- ### Initialize and Query SQL Database with Tbox Source: https://github.com/tboox/tbox/wiki/Access-sql-database This C code snippet demonstrates how to initialize a database connection (MySQL or SQLite3) using a provided URL, open the connection, execute a SELECT statement, load and iterate through the results, and finally close the connection. It includes error handling and tracing for each step. ```c /* init a mysql database * * mysql database url: * * - "sql://localhost:3306/?type=mysql&username=xxxx&password=xxxx&database=xxxx" * * sqlite3 database url: * * - "sql:///home/file.sqlitedb?type=sqlite3" * - "/home/file.sqlite3" * - "file:///home/file.sqlitedb" * - "C://home/file.sqlite3" */ tb_database_sql_ref_t database = tb_database_sql_init("sql://localhost/?type=mysql&username=xxxx&password=xxxx&database=test"); if (database) { // open database if (tb_database_sql_open(database)) { // execute sql statement if (tb_database_sql_done(database, "select * from test")) { // load all results only for the select statement tb_iterator_ref_t result = tb_database_sql_result_load(database, tb_true); if (result) { // trace tb_trace_i("row: size: %lu", tb_iterator_size(result)); // walk all rows tb_for_all_if (tb_iterator_ref_t, row, result, row) { // trace tb_trace_i("[row: %lu, col: size: %lu]: ", row_itor, tb_iterator_size(row)); // walk all values tb_for_all_if (tb_database_sql_value_t*, value, row, value) { // trace tb_tracet_i("[%s:%s] ", tb_database_sql_value_name(value), tb_database_sql_value_text(value)); } } tb_database_sql_result_exit(database, result); } } else tb_trace_e("done %s failed, error: %s", sql, tb_state_cstr(tb_database_sql_state(database))); } else tb_trace_e("open failed: %s", tb_state_cstr(tb_database_sql_state(database))); // exit database tb_database_sql_exit(database); } ``` -------------------------------- ### jcat Command-Line Usage for JSON Filtering Source: https://github.com/tboox/tbox/wiki/实现json解析工具jcat This example demonstrates how to use the jcat command-line tool to filter a JSON file. It specifies a filter path '.compiler.mac.x64.debug' to extract specific configuration details from the manifest.json file. The output is a JSON object containing the matched configuration. ```bash ./tool/jcat/jcat --filter=.compiler.mac.x64.debug ./pkg/polarssl.pkg/manifest.json ```