tb_bool_t vm86_parser_get_offset_value(tb_char_t const** pp, tb_char_t const* e, tb_uint32_t* value, tb_hash_map_ref_t proc_labels, vm86_data_ref_t data) { // check tb_assert(pp && e && value && proc_labels); // done tb_bool_t ok = tb_false; tb_char_t const* p = *pp; do { // attempt to get segment name tb_char_t segment[16] = {0}; tb_bool_t has_segment = vm86_parser_get_segment_name(&p, e, segment, sizeof(segment)); // skip "short ..." if (p + 6 < e && !tb_strnicmp(p, "short ", 6)) p += 6; // skip the space while (p < e && tb_isspace(*p)) p++; // get instruction name tb_char_t name[256] = {0}; if (!vm86_parser_get_variable_name(&p, e, name, sizeof(name))) break; // is .data segment? if (has_segment && !tb_stricmp(segment, "ds")) *value = vm86_data_get(data, name, tb_null); // is .code segment? else if (has_segment && !tb_stricmp(segment, "cs")) *value = (tb_uint32_t)tb_hash_map_get(proc_labels, name); else { // get value if (tb_hash_map_find(proc_labels, name) != tb_iterator_tail(proc_labels)) *value = (tb_uint32_t)tb_hash_map_get(proc_labels, name); else if (vm86_data_is(data, name)) *value = vm86_data_get(data, name, tb_null); else break; } // check tb_assert(*value < TB_MAXU32); // trace tb_trace_d("offset: %s: %x", name, *value); // ok ok = tb_true; } while (0); // update the code pointer if ok if (ok) *pp = p; // ok? return ok; }
/* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_size_t tb_database_sqlite3_probe(tb_url_ref_t url) { // check tb_assert_and_check_return_val(url, 0); // done tb_size_t score = 0; tb_stream_ref_t stream = tb_null; do { // the url arguments tb_char_t const* args = tb_url_args(url); if (args) { // find the database type tb_char_t const* ptype = tb_stristr(args, "type="); if (ptype && !tb_strnicmp(ptype + 5, "sqlite3", 7)) { // ok score = 100; break; } } // has host or port? no sqlite3 if (tb_url_host(url) || tb_url_port(url)) break; // the database path tb_char_t const* path = tb_url_cstr((tb_url_ref_t)url); tb_assert_and_check_break(path); // is file? if (tb_url_protocol(url) == TB_URL_PROTOCOL_FILE) score += 20; // init stream stream = tb_stream_init_from_url(path); tb_assert_and_check_break(stream); // open stream if (!tb_stream_open(stream)) break; // read head tb_char_t head[16] = {0}; if (!tb_stream_bread(stream, (tb_byte_t*)head, 15)) break; // is sqlite3? if (!tb_stricmp(head, "SQLite format 3")) score = 100; } while (0); // exit stream if (stream) tb_stream_exit(stream); stream = tb_null; // trace tb_trace_d("probe: %s, score: %lu", tb_url_cstr((tb_url_ref_t)url), score); // ok? return score; }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_object_ref_t tb_object_json_reader_func_null(tb_object_json_reader_t* reader, tb_char_t type) { // check tb_assert_and_check_return_val(reader && reader->stream, tb_null); // init data tb_static_string_t data; tb_char_t buff[256]; if (!tb_static_string_init(&data, buff, 256)) return tb_null; // done tb_object_ref_t null = tb_null; do { // append character tb_static_string_chrcat(&data, type); // walk tb_bool_t failed = tb_false; while (!failed && tb_stream_left(reader->stream)) { // need one character tb_byte_t* p = tb_null; if (!tb_stream_need(reader->stream, &p, 1) && p) { failed = tb_true; break; } // the character tb_char_t ch = *p; // append character if (tb_isalpha(ch)) tb_static_string_chrcat(&data, ch); else break; // skip it tb_stream_skip(reader->stream, 1); } // failed? tb_check_break(!failed); // check tb_assert_and_check_break(tb_static_string_size(&data)); // trace tb_trace_d("null: %s", tb_static_string_cstr(&data)); // null? if (!tb_stricmp(tb_static_string_cstr(&data), "null")) null = tb_object_null_init(); } while (0); // exit data tb_static_string_exit(&data); // ok? return null; }
/* ////////////////////////////////////////////////////////////////////////////////////// * finder */ static tb_long_t tb_charset_comp_by_name(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t name) { // check tb_assert(item); // comp return tb_stricmp(((tb_charset_ref_t)item)->name, (tb_char_t const*)name); }
static tb_bool_t tb_ifaddrs_interface_pred(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t name) { // check tb_assert(item); // is equal? return !tb_stricmp(((tb_ifaddrs_interface_ref_t)item)->name, (tb_char_t const*)name); }
/* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_long_t vm86_parser_comp_register(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t name) { // check tb_assert(item); // hacking for register return tb_stricmp(*((tb_char_t const**)item), (tb_char_t const*)name); }
static tb_long_t tb_iterator_istr_comp(tb_iterator_ref_t iterator, tb_cpointer_t litem, tb_cpointer_t ritem) { // check tb_assert(litem && ritem); // compare it return tb_stricmp((tb_char_t const*)litem, (tb_char_t const*)ritem); }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t main(tb_int_t argc, tb_char_t** argv) { // init tbox #if 0 if (!tb_init(tb_null, tb_default_allocator((tb_byte_t*)malloc(300 * 1024 * 1024), 300 * 1024 * 1024))) return -1; #elif 0 if (!tb_init(tb_null, tb_static_allocator((tb_byte_t*)malloc(300 * 1024 * 1024), 300 * 1024 * 1024))) return -1; #elif (defined(__tb_valgrind__) && defined(TB_CONFIG_VALGRIND_HAVE_VALGRIND_STACK_REGISTER)) \ || defined(__tb_sanitize_address__) || defined(__tb_sanitize_thread__) if (!tb_init(tb_null, tb_native_allocator())) return -1; #else if (!tb_init(tb_null, tb_null)) return -1; #endif // find the main func from the first argument tb_int_t ok = 0; tb_char_t const* name = tb_null; if (argc > 1 && argv[1]) { tb_size_t i = 0; tb_size_t n = tb_arrayn(g_demo); for (i = 0; i < n; i++) { // find it? if (g_demo[i].name && !tb_stricmp(g_demo[i].name, argv[1])) { // save name name = g_demo[i].name; // done main ok = g_demo[i].main(argc - 1, argv + 1); break; } } } // no this demo? help it if (!name) { tb_trace_i("======================================================================"); tb_trace_i("Usages: xmake r demo [testname] arguments ..."); tb_trace_i(""); tb_trace_i(".e.g"); tb_trace_i(" xmake r demo stream http://www.xxxxx.com /tmp/a"); tb_trace_i(""); // walk name tb_size_t i = 0; tb_size_t n = tb_arrayn(g_demo); for (i = 0; i < n; i++) tb_trace_i("testname: %s", g_demo[i].name); } // exit tbox tb_exit(); // ok? return ok; }
static tb_object_ref_t tb_object_xplist_reader_func_boolean(tb_object_xplist_reader_t* reader, tb_size_t event) { // check tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_return_val(name, tb_null); tb_trace_d("boolean: %s", name); // the boolean value tb_bool_t val = tb_false; if (!tb_stricmp(name, "true")) val = tb_true; else if (!tb_stricmp(name, "false")) val = tb_false; else return tb_null; // ok? return (tb_object_ref_t)tb_object_boolean_init(val); }
static tb_void_t tb_test_stricmp(tb_char_t const* s1, tb_char_t const* s2) { __tb_volatile__ tb_long_t n = 1000000; __tb_volatile__ tb_long_t r = 0; tb_hong_t t = tb_mclock(); while (n--) { r = tb_stricmp(s1, s2); } t = tb_mclock() - t; tb_printf("%lld ms, tb_test_stricmp(%s, %s) = %ld\n", t, s1, s2, r); }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t main(tb_int_t argc, tb_char_t** argv) { // init tbox #if 1 if (!tb_init(tb_null, tb_static_allocator((tb_byte_t*)malloc(1024 * 1024), 1024 * 1024))) return 0; #else if (!tb_init(tb_null, tb_native_allocator())) return 0; #endif // find the main func from the first argument tb_int_t ok = 0; tb_char_t const* name = tb_null; if (argc > 1 && argv[1]) { tb_size_t i = 0; tb_size_t n = tb_arrayn(g_demo); for (i = 0; i < n; i++) { // find it? if (g_demo[i].name && !tb_stricmp(g_demo[i].name, argv[1])) { // save name name = g_demo[i].name; // done main ok = g_demo[i].main(argc - 1, argv + 1); break; } } } // no this demo? help it if (!name) { tb_trace_i("======================================================================"); tb_trace_i("Usages: xmake r demo [testname] arguments ..."); tb_trace_i(""); tb_trace_i(".e.g"); tb_trace_i(" xmake r demo stream http://www.xxxxx.com /tmp/a"); tb_trace_i(""); // walk name tb_size_t i = 0; tb_size_t n = tb_arrayn(g_demo); for (i = 0; i < n; i++) tb_trace_i("testname: %s", g_demo[i].name); } // exit tbox tb_exit(); // ok? return ok; }
static tb_object_ref_t tb_object_xplist_reader_func_string(tb_object_xplist_reader_t* reader, tb_size_t event) { // check tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); // empty? if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) return tb_object_string_init_from_cstr(tb_null); // done tb_bool_t leave = tb_false; tb_object_ref_t string = tb_null; while (!leave && (event = tb_xml_reader_next(reader->reader))) { switch (event) { case TB_XML_READER_EVENT_ELEMENT_END: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, leave, tb_true); // is end? if (!tb_stricmp(name, "string")) { // empty? if (!string) string = tb_object_string_init_from_cstr(tb_null); // leave it leave = tb_true; } } break; case TB_XML_READER_EVENT_TEXT: { // text tb_char_t const* text = tb_xml_reader_text(reader->reader); tb_assert_and_check_break_state(text, leave, tb_true); tb_trace_d("string: %s", text); // string string = tb_object_string_init_from_cstr(text); tb_assert_and_check_break_state(string, leave, tb_true); } break; default: break; } } // ok? return string; }
static tb_object_ref_t tb_object_xplist_reader_done(tb_stream_ref_t stream) { // init reader tb_object_xplist_reader_t reader = {0}; reader.reader = tb_xml_reader_init(); tb_assert_and_check_return_val(reader.reader, tb_null); // open reader tb_object_ref_t object = tb_null; if (tb_xml_reader_open(reader.reader, stream, tb_false)) { // done tb_bool_t leave = tb_false; tb_size_t event = TB_XML_READER_EVENT_NONE; while (!leave && !object && (event = tb_xml_reader_next(reader.reader))) { switch (event) { case TB_XML_READER_EVENT_ELEMENT_EMPTY: case TB_XML_READER_EVENT_ELEMENT_BEG: { // name tb_char_t const* name = tb_xml_reader_element(reader.reader); tb_assert_and_check_break_state(name, leave, tb_true); // <plist/> ? if (tb_stricmp(name, "plist")) { // func tb_object_xplist_reader_func_t func = tb_object_xplist_reader_func(name); tb_assert_and_check_break_state(func, leave, tb_true); // read object = func(&reader, event); } } break; default: break; } } } // exit reader tb_xml_reader_exit(reader.reader); // ok? return object; }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_object_ref_t tb_object_xplist_reader_func_date(tb_object_xplist_reader_t* reader, tb_size_t event) { // check tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); // empty? if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) return tb_object_date_init_from_time(0); // done tb_bool_t leave = tb_false; tb_object_ref_t date = tb_null; while (!leave && (event = tb_xml_reader_next(reader->reader))) { switch (event) { case TB_XML_READER_EVENT_ELEMENT_END: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, leave, tb_true); // is end? if (!tb_stricmp(name, "date")) { // empty? if (!date) date = tb_object_date_init_from_time(0); // leave it leave = tb_true; } } break; case TB_XML_READER_EVENT_TEXT: { // text tb_char_t const* text = tb_xml_reader_text(reader->reader); tb_assert_and_check_break_state(text, leave, tb_true); tb_trace_d("date: %s", text); // done date: %04ld-%02ld-%02ld %02ld:%02ld:%02ld tb_tm_t tm = {0}; tb_char_t const* p = text; tb_char_t const* e = text + tb_strlen(text); // init year while (p < e && *p && !tb_isdigit(*p)) p++; tb_assert_and_check_break_state(p < e, leave, tb_true); tm.year = tb_atoi(p); // init month while (p < e && *p && tb_isdigit(*p)) p++; while (p < e && *p && !tb_isdigit(*p)) p++; tb_assert_and_check_break_state(p < e, leave, tb_true); tm.month = tb_atoi(p); // init day while (p < e && *p && tb_isdigit(*p)) p++; while (p < e && *p && !tb_isdigit(*p)) p++; tb_assert_and_check_break_state(p < e, leave, tb_true); tm.mday = tb_atoi(p); // init hour while (p < e && *p && tb_isdigit(*p)) p++; while (p < e && *p && !tb_isdigit(*p)) p++; tb_assert_and_check_break_state(p < e, leave, tb_true); tm.hour = tb_atoi(p); // init minute while (p < e && *p && tb_isdigit(*p)) p++; while (p < e && *p && !tb_isdigit(*p)) p++; tb_assert_and_check_break_state(p < e, leave, tb_true); tm.minute = tb_atoi(p); // init second while (p < e && *p && tb_isdigit(*p)) p++; while (p < e && *p && !tb_isdigit(*p)) p++; tb_assert_and_check_break_state(p < e, leave, tb_true); tm.second = tb_atoi(p); // time tb_time_t time = tb_mktime(&tm); tb_assert_and_check_break_state(time >= 0, leave, tb_true); // date date = tb_object_date_init_from_time(time); } break; default: break; } } // ok? return date; }
static tb_object_ref_t tb_object_xplist_reader_func_dictionary(tb_object_xplist_reader_t* reader, tb_size_t event) { // check tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); // empty? if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) return tb_object_dictionary_init(TB_OBJECT_DICTIONARY_SIZE_MICRO, tb_false); // init key name tb_static_string_t kname; tb_char_t kdata[8192]; if (!tb_static_string_init(&kname, kdata, 8192)) return tb_null; // init dictionary tb_object_ref_t dictionary = tb_object_dictionary_init(0, tb_false); tb_assert_and_check_return_val(dictionary, tb_null); // done tb_long_t ok = 0; tb_bool_t key = tb_false; while (!ok && (event = tb_xml_reader_next(reader->reader))) { switch (event) { case TB_XML_READER_EVENT_ELEMENT_BEG: case TB_XML_READER_EVENT_ELEMENT_EMPTY: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, ok, -1); tb_trace_d("%s", name); // is key if (!tb_stricmp(name, "key")) key = tb_true; else if (!key) { // func tb_object_xplist_reader_func_t func = tb_object_xplist_reader_func(name); tb_assert_and_check_break_state(func, ok, -1); // read tb_object_ref_t object = func(reader, event); tb_trace_d("%s => %p", tb_static_string_cstr(&kname), object); tb_assert_and_check_break_state(object, ok, -1); // set key & value if (tb_static_string_size(&kname) && dictionary) tb_object_dictionary_insert(dictionary, tb_static_string_cstr(&kname), object); // clear key name tb_static_string_clear(&kname); } } break; case TB_XML_READER_EVENT_ELEMENT_END: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, ok, -1); // is end? if (!tb_stricmp(name, "dict")) ok = 1; else if (!tb_stricmp(name, "key")) key = tb_false; } break; case TB_XML_READER_EVENT_TEXT: { if (key) { // text tb_char_t const* text = tb_xml_reader_text(reader->reader); tb_assert_and_check_break_state(text, ok, -1); // writ key name tb_static_string_cstrcpy(&kname, text); } } break; default: break; } } // failed if (ok < 0) { // exit it if (dictionary) tb_object_exit(dictionary); dictionary = tb_null; } // exit key name tb_static_string_exit(&kname); // ok? return dictionary; }
/* ////////////////////////////////////////////////////////////////////////////////////// * helper */ static __tb_inline__ tb_bool_t tb_option_is_bool(tb_char_t const* data) { // check tb_assert_and_check_return_val(data, tb_false); return (!tb_stricmp(data, "y") || !tb_stricmp(data, "n"))? tb_true : tb_false; }
static tb_object_ref_t tb_object_xplist_reader_func_number(tb_object_xplist_reader_t* reader, tb_size_t event) { // check tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); // empty? if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) return tb_object_number_init_from_uint32(0); // done tb_bool_t leave = tb_false; tb_object_ref_t number = tb_null; while (!leave && (event = tb_xml_reader_next(reader->reader))) { switch (event) { case TB_XML_READER_EVENT_ELEMENT_END: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, leave, tb_true); // is end? if (!tb_stricmp(name, "integer") || !tb_stricmp(name, "real")) leave = tb_true; } break; case TB_XML_READER_EVENT_TEXT: { // text tb_char_t const* text = tb_xml_reader_text(reader->reader); tb_assert_and_check_break_state(text, leave, tb_true); tb_trace_d("number: %s", text); // has sign? is float? tb_size_t s = 0; tb_size_t f = 0; tb_char_t const* p = text; for (; *p; p++) { if (!s && *p == '-') s = 1; if (!f && *p == '.') f = 1; if (s && f) break; } // number #ifdef TB_CONFIG_TYPE_HAVE_FLOAT if (f) number = tb_object_number_init_from_double(tb_atof(text)); #else if (f) tb_trace_noimpl(); #endif else number = s? tb_object_number_init_from_sint64(tb_stoi64(text)) : tb_object_number_init_from_uint64(tb_stou64(text)); tb_assert_and_check_break_state(number, leave, tb_true); } break; default: break; } } // ok? return number; }
static tb_object_ref_t tb_object_xplist_reader_func_array(tb_object_xplist_reader_t* reader, tb_size_t event) { // check tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); // empty? if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) return tb_object_array_init(TB_OBJECT_XPLIST_READER_ARRAY_GROW, tb_false); // init array tb_object_ref_t array = tb_object_array_init(TB_OBJECT_XPLIST_READER_ARRAY_GROW, tb_false); tb_assert_and_check_return_val(array, tb_null); // done tb_long_t ok = 0; while (!ok && (event = tb_xml_reader_next(reader->reader))) { switch (event) { case TB_XML_READER_EVENT_ELEMENT_BEG: case TB_XML_READER_EVENT_ELEMENT_EMPTY: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, ok, -1); tb_trace_d("item: %s", name); // func tb_object_xplist_reader_func_t func = tb_object_xplist_reader_func(name); tb_assert_and_check_break_state(func, ok, -1); // read tb_object_ref_t object = func(reader, event); // append object if (object) tb_object_array_append(array, object); } break; case TB_XML_READER_EVENT_ELEMENT_END: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, ok, -1); // is end? if (!tb_stricmp(name, "array")) ok = 1; } break; default: break; } } // failed? if (ok < 0) { // exit it if (array) tb_object_exit(array); array = tb_null; } // ok? return array; }
static tb_long_t tb_element_str_comp(tb_element_ref_t element, tb_cpointer_t ldata, tb_cpointer_t rdata) { // check tb_assert_and_check_return_val(element && ldata && rdata, 0); // compare it return element->flag? tb_strcmp((tb_char_t const*)ldata, (tb_char_t const*)rdata) : tb_stricmp((tb_char_t const*)ldata, (tb_char_t const*)rdata); }
tb_bool_t tb_option_done(tb_option_ref_t option, tb_size_t argc, tb_char_t** argv) { // check tb_option_impl_t* impl = (tb_option_impl_t*)option; tb_assert_and_check_return_val(impl && impl->list && impl->opts, tb_false); // walk arguments tb_size_t i = 0; tb_size_t more = 0; tb_option_item_t const* item = impl->opts; tb_option_item_t const* last = tb_null; for (i = 0; i < argc; i++) { // the argument tb_char_t* p = argv[i]; tb_char_t* e = p + tb_strlen(p); tb_assert_and_check_return_val(p && p < e, tb_false); // is long key? if (p + 2 < e && p[0] == '-' && p[1] == '-' && tb_isalpha(p[2])) { // the key tb_char_t key[512] = {0}; { tb_char_t* k = key; tb_char_t* e = key + 511; for (p += 2; *p && *p != '=' && k < e; p++, k++) *k = *p; } // the val tb_char_t* val = (*p == '=')? (p + 1) : tb_null; // trace tb_trace_d("[lname]: %s => %s", key, val); // find the item tb_option_item_t const* find = tb_option_item_find(impl->opts, key, '\0'); if (find) { // check key & val if (!val == !(find->mode == TB_OPTION_MODE_KEY_VAL)) { // has value? tb_object_ref_t object = tb_null; if (val) { // init the value object switch (find->type) { case TB_OPTION_TYPE_CSTR: object = tb_oc_string_init_from_cstr(val); break; case TB_OPTION_TYPE_INTEGER: tb_assert_and_check_return_val(tb_option_is_integer(val), tb_false); object = tb_oc_number_init_from_sint64(tb_atoll(val)); break; case TB_OPTION_TYPE_BOOL: tb_assert_and_check_return_val(tb_option_is_bool(val), tb_false); object = tb_oc_boolean_init(!tb_stricmp(val, "y")? tb_true : tb_false); break; #ifdef TB_CONFIG_TYPE_HAVE_FLOAT case TB_OPTION_TYPE_FLOAT: tb_assert_and_check_return_val(tb_option_is_float(val), tb_false); object = tb_oc_number_init_from_double(tb_atof(val)); break; #endif default: tb_assert_and_check_return_val(0, tb_false); break; } } else { // check tb_assert_and_check_return_val(find->type == TB_OPTION_TYPE_BOOL, tb_false); // key => true object = tb_oc_boolean_init(tb_true); } // add the value object if (object) { tb_oc_dictionary_insert(impl->list, key, object); if (tb_isalpha(find->sname)) { tb_char_t ch[2] = {0}; ch[0] = find->sname; tb_oc_dictionary_insert(impl->list, ch, object); tb_object_retain(object); } } } else if (val) { // print tb_trace_e("%s: unrecognized option value '--%s=%s'", impl->name, key, val); // next continue ; } else { // print tb_trace_e("%s: no option value '--%s='", impl->name, key); // next continue ; } } else { // print tb_trace_e("%s: unrecognized option '--%s'", impl->name, key); // next continue ; } } // is short key? else if (p + 1 < e && p[0] == '-' && tb_isalpha(p[1])) { // the key tb_char_t key[512] = {0}; { tb_char_t* k = key; tb_char_t* e = key + 511; for (p += 1; *p && *p != '=' && k < e; p++, k++) *k = *p; } // the val tb_char_t const* val = (*p == '=')? (p + 1) : tb_null; // trace tb_trace_d("[sname]: %s => %s", key, val); // is short name? if (tb_strlen(key) != 1) { // print tb_trace_e("%s: unrecognized option '-%s'", impl->name, key); // next continue ; } // find the item tb_option_item_t const* find = tb_option_item_find(impl->opts, tb_null, key[0]); if (find) { // check key & val if (!val == !(find->mode == TB_OPTION_MODE_KEY_VAL)) { // has value? tb_object_ref_t object = tb_null; if (val) { // add value switch (find->type) { case TB_OPTION_TYPE_CSTR: object = tb_oc_string_init_from_cstr(val); break; case TB_OPTION_TYPE_INTEGER: tb_assert_and_check_return_val(tb_option_is_integer(val), tb_false); object = tb_oc_number_init_from_sint64(tb_atoll(val)); break; case TB_OPTION_TYPE_BOOL: tb_assert_and_check_return_val(tb_option_is_bool(val), tb_false); object = tb_oc_boolean_init(!tb_stricmp(val, "y")? tb_true : tb_false); break; #ifdef TB_CONFIG_TYPE_HAVE_FLOAT case TB_OPTION_TYPE_FLOAT: tb_assert_and_check_return_val(tb_option_is_float(val), tb_false); object = tb_oc_number_init_from_double(tb_atof(val)); break; #endif default: tb_assert_and_check_return_val(0, tb_false); break; } } else { // check tb_assert_and_check_return_val(find->type == TB_OPTION_TYPE_BOOL, tb_false); // key => true object = tb_oc_boolean_init(tb_true); } // add the value object if (object) { tb_oc_dictionary_insert(impl->list, key, object); if (find->lname) { tb_oc_dictionary_insert(impl->list, find->lname, object); tb_object_retain(object); } } } else if (val) { // print tb_trace_e("%s: unrecognized option value '--%s=%s'", impl->name, key, val); // next continue ; } else { // print tb_trace_e("%s: no option value '--%s='", impl->name, key); // next continue ; } } else { // print tb_trace_e("%s: unrecognized option '-%s'", impl->name, key); // next continue ; } } // is value? else { // trace tb_trace_d("[val]: %s", p); // find the value item while (item && item->mode != TB_OPTION_MODE_VAL && item->mode != TB_OPTION_MODE_END && item->mode != TB_OPTION_MODE_MORE) item++; // has value item? if (item->mode == TB_OPTION_MODE_VAL) { // check tb_assert_and_check_return_val(item->lname, tb_false); // add value switch (item->type) { case TB_OPTION_TYPE_CSTR: tb_oc_dictionary_insert(impl->list, item->lname, tb_oc_string_init_from_cstr(p)); break; case TB_OPTION_TYPE_INTEGER: tb_assert_and_check_return_val(tb_option_is_integer(p), tb_false); tb_oc_dictionary_insert(impl->list, item->lname, tb_oc_number_init_from_sint64(tb_atoll(p))); break; case TB_OPTION_TYPE_BOOL: tb_assert_and_check_return_val(tb_option_is_bool(p), tb_false); tb_oc_dictionary_insert(impl->list, item->lname, tb_oc_boolean_init(!tb_stricmp(p, "y")? tb_true : tb_false)); break; #ifdef TB_CONFIG_TYPE_HAVE_FLOAT case TB_OPTION_TYPE_FLOAT: tb_assert_and_check_return_val(tb_option_is_float(p), tb_false); tb_oc_dictionary_insert(impl->list, item->lname, tb_oc_number_init_from_double(tb_atof(p))); break; #endif default: tb_assert_and_check_return_val(0, tb_false); break; } // save last last = item; // next item item++; } // has more item? else if (item->mode == TB_OPTION_MODE_MORE && last) { // the more name tb_char_t name[64] = {0}; tb_snprintf(name, 63, "more%lu", more); // add value switch (last->type) { case TB_OPTION_TYPE_CSTR: tb_oc_dictionary_insert(impl->list, name, tb_oc_string_init_from_cstr(p)); break; case TB_OPTION_TYPE_INTEGER: tb_assert_and_check_return_val(tb_option_is_integer(p), tb_false); tb_oc_dictionary_insert(impl->list, name, tb_oc_number_init_from_sint64(tb_atoll(p))); break; case TB_OPTION_TYPE_BOOL: tb_assert_and_check_return_val(tb_option_is_bool(p), tb_false); tb_oc_dictionary_insert(impl->list, name, tb_oc_boolean_init(!tb_stricmp(p, "y")? tb_true : tb_false)); break; #ifdef TB_CONFIG_TYPE_HAVE_FLOAT case TB_OPTION_TYPE_FLOAT: tb_assert_and_check_return_val(tb_option_is_float(p), tb_false); tb_oc_dictionary_insert(impl->list, name, tb_oc_number_init_from_double(tb_atof(p))); break; #endif default: tb_assert_and_check_return_val(0, tb_false); break; } // next more more++; } } } // ok return tb_true;//tb_option_check(impl); }
/* ////////////////////////////////////////////////////////////////////////////////////// * 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; }
static tb_void_t tb_demo_http_session_head_parse(tb_demo_http_session_ref_t session) { // check tb_assert_and_check_return(session); // the first line? tb_char_t const* p = session->line; if (!session->line_index) { // parse get if (!tb_strnicmp(p, "GET", 3)) { session->code = TB_HTTP_CODE_OK; session->method = TB_HTTP_METHOD_GET; p += 3; } // parse post else if (!tb_strnicmp(p, "POST", 4)) { session->code = TB_HTTP_CODE_NOT_IMPLEMENTED; session->method = TB_HTTP_METHOD_POST; p += 4; } // other method is not implemented else session->code = TB_HTTP_CODE_NOT_IMPLEMENTED; // get or post? parse the path if ( session->method == TB_HTTP_METHOD_GET || session->method == TB_HTTP_METHOD_POST) { // skip space while (*p && tb_isspace(*p)) p++; // append path tb_size_t i = 0; while (*p && !tb_isspace(*p) && i < sizeof(session->path) - 1) session->path[i++] = *p++; session->path[i] = '\0'; } } // key: value? else { // seek to value while (*p && *p != ':') p++; tb_assert_and_check_return(*p); p++; while (*p && tb_isspace(*p)) p++; // no value tb_check_return(*p); // parse content-length if (!tb_strnicmp(session->line, "Content-Length", 14)) session->content_size = tb_stou64(p); // parse connection else if (!tb_strnicmp(session->line, "Connection", 10)) session->keep_alive = !tb_stricmp(p, "keep-alive"); // parse range else if (!tb_strnicmp(session->line, "Range", 5)) session->code = TB_HTTP_CODE_NOT_IMPLEMENTED; } }
tb_bool_t tb_dns_cache_get(tb_char_t const* name, tb_ipv4_t* addr) { // check tb_assert_and_check_return_val(name && addr, tb_false); // trace tb_trace_d("get: %s", name); // is ipv4? tb_check_return_val(!tb_ipv4_set(addr, name), tb_true); // is localhost? if (!tb_stricmp(name, "localhost")) { tb_ipv4_set(addr, "127.0.0.1"); return tb_true; } // clear addr tb_ipv4_clr(addr); // enter tb_spinlock_enter(&g_lock); // done tb_bool_t ok = tb_false; do { // check tb_assert_and_check_break(g_cache.hash); // get the host address tb_dns_cache_addr_t* caddr = (tb_dns_cache_addr_t*)tb_hash_get(g_cache.hash, name); tb_check_break(caddr); // trace tb_trace_d("get: %s => %u.%u.%u.%u, time: %u => %u, size: %u", name , caddr->ipv4.u8[0] , caddr->ipv4.u8[1] , caddr->ipv4.u8[2] , caddr->ipv4.u8[3] , caddr->time , tb_dns_cache_now() , tb_hash_size(g_cache.hash)); // update time tb_assert_and_check_break(g_cache.times >= caddr->time); g_cache.times -= caddr->time; caddr->time = tb_dns_cache_now(); g_cache.times += caddr->time; // save addr *addr = caddr->ipv4; // ok ok = tb_true; } while (0); // leave tb_spinlock_leave(&g_lock); // ok? return ok; }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_bool_t tb_demo_spider_parser_open_html(tb_stream_ref_t stream, tb_char_t const* url) { // check tb_assert_and_check_return_val(stream && url, tb_false); // done tb_bool_t ok = tb_false; do { // find the .suffix tb_char_t const* p = tb_strrchr(url, '.'); if (p) { // not html? tb_check_break ( tb_stricmp(p, ".css") && tb_stricmp(p, ".js") && tb_stricmp(p, ".png") && tb_stricmp(p, ".jpg") && tb_stricmp(p, ".gif") && tb_stricmp(p, ".ico") && tb_stricmp(p, ".bmp") && tb_stricmp(p, ".mp4") && tb_stricmp(p, ".mp3") && tb_stricmp(p, ".flv") && tb_stricmp(p, ".avi") && tb_stricmp(p, ".exe") && tb_stricmp(p, ".msi") && tb_stricmp(p, ".zip") && tb_stricmp(p, ".rar") && tb_stricmp(p, ".7z")); } // ctrl stream if (!tb_stream_ctrl(stream, TB_STREAM_CTRL_SET_URL, url)) break; // open stream if (!tb_stream_open(stream)) break; // the stream size tb_hong_t size = tb_stream_size(stream); tb_check_break(size); // prefetch some data tb_byte_t* data = tb_null; tb_size_t need = tb_min((tb_size_t)size, 256); if (!tb_stream_need(stream, &data, need)) break; // is html? if (tb_strnistr((tb_char_t const*)data, need, "<!DOCTYPE html>")) { ok = tb_true; break; } // is html? ok = tb_strnistr((tb_char_t const*)data, need, "<html")? tb_true : tb_false; } while (0); // failed? if (!ok) { // clos stream if (stream) tb_stream_clos(stream); } // ok? return ok; }
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; }
static tb_object_ref_t tb_object_xplist_reader_func_data(tb_object_xplist_reader_t* reader, tb_size_t event) { // check tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); // empty? if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) return tb_object_data_init_from_data(tb_null, 0); // done tb_bool_t leave = tb_false; tb_char_t* base64 = tb_null; tb_object_ref_t data = tb_null; while (!leave && (event = tb_xml_reader_next(reader->reader))) { switch (event) { case TB_XML_READER_EVENT_ELEMENT_END: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, leave, tb_true); // is end? if (!tb_stricmp(name, "data")) { // empty? if (!data) data = tb_object_data_init_from_data(tb_null, 0); // leave it leave = tb_true; } } break; case TB_XML_READER_EVENT_TEXT: { // text tb_char_t const* text = tb_xml_reader_text(reader->reader); tb_assert_and_check_break_state(text, leave, tb_true); tb_trace_d("data: %s", text); // base64 base64 = tb_strdup(text); tb_char_t* p = base64; tb_char_t* q = p; for (; *p; p++) if (!tb_isspace(*p)) *q++ = *p; *q = '\0'; // decode base64 data tb_char_t const* ib = base64; tb_size_t in = tb_strlen(base64); if (in) { tb_size_t on = in; tb_byte_t* ob = tb_malloc0_bytes(on); tb_assert_and_check_break_state(ob && on, leave, tb_true); on = tb_base64_decode(ib, in, ob, on); tb_trace_d("base64: %u => %u", in, on); // init data data = tb_object_data_init_from_data(ob, on); tb_free(ob); } else data = tb_object_data_init_from_data(tb_null, 0); tb_assert_and_check_break_state(data, leave, tb_true); } break; default: break; } } // free if (base64) tb_free(base64); // ok? return data; }
static tb_size_t tb_demo_spider_parser_get_url(tb_xml_reader_ref_t reader, tb_url_ref_t url) { // check tb_assert_and_check_return_val(reader && url, tb_false); // done tb_size_t ok = 0; tb_size_t event = TB_XML_READER_EVENT_NONE; while (!ok && (event = tb_xml_reader_next(reader))) { switch (event) { case TB_XML_READER_EVENT_ELEMENT_EMPTY: case TB_XML_READER_EVENT_ELEMENT_BEG: { // the element name tb_char_t const* name = tb_xml_reader_element(reader); tb_check_break(name); // <a href="" />? // <link href="" /> // <img src="" />? // <script src="" />? // <source src="" />? // <frame src="" />? if ( !tb_stricmp(name, "a") || !tb_stricmp(name, "link") || !tb_stricmp(name, "img") || !tb_stricmp(name, "frame") || !tb_stricmp(name, "source")) { // walk attributes tb_xml_node_ref_t attr = (tb_xml_node_ref_t)tb_xml_reader_attributes(reader); for (; attr; attr = attr->next) { // href or src? if ( tb_string_size(&attr->data) && ( !tb_string_cstricmp(&attr->name, "href") || !tb_string_cstricmp(&attr->name, "src"))) { // the url protocol tb_size_t protocol = tb_url_protocol_probe(tb_string_cstr(&attr->data)); // http? if(protocol == TB_URL_PROTOCOL_HTTP) { // save url ok = tb_url_set(url, tb_string_cstr(&attr->data)); } // file? else if (protocol == TB_URL_PROTOCOL_FILE) { // save path tb_url_path_set(url, tb_string_cstr(&attr->data)); // ok ok = tb_true; } } } } } break; default: break; } } // ok? return ok; }