示例#1
0
文件: parser.c 项目: waruqi/vm86
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;
}
示例#2
0
文件: sqlite3.c 项目: ljx0305/tbox
/* //////////////////////////////////////////////////////////////////////////////////////
 * 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;
}
示例#3
0
文件: json.c 项目: luxuan/tbox
/* //////////////////////////////////////////////////////////////////////////////////////
 * 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;
}
示例#4
0
文件: charset.c 项目: waruqi/tbox
/* //////////////////////////////////////////////////////////////////////////////////////
 * 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);
}
示例#5
0
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);
}
示例#6
0
文件: parser.c 项目: waruqi/vm86
/* //////////////////////////////////////////////////////////////////////////////////////
 * 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);
}
示例#7
0
文件: str.c 项目: siwuxian/xmake
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);
}
示例#8
0
文件: demo.c 项目: ljx0305/tbox
/* //////////////////////////////////////////////////////////////////////////////////////
 * 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;
}
示例#9
0
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);
}
示例#10
0
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);
}
示例#11
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * 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;
}
示例#12
0
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;
}
示例#13
0
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;
}
示例#14
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * 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;
}
示例#15
0
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;
}
示例#16
0
文件: option.c 项目: waruqi/tbox
/* //////////////////////////////////////////////////////////////////////////////////////
 * 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;
}
示例#17
0
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;
}
示例#18
0
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;
}
示例#19
0
文件: str.c 项目: luxuan/tbox
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);
}
示例#20
0
文件: option.c 项目: waruqi/tbox
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);
}
示例#21
0
文件: demo.c 项目: ahnan4arch/tbox
/* //////////////////////////////////////////////////////////////////////////////////////
 * 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;
}
示例#22
0
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;
    }
}
示例#23
0
文件: cache.c 项目: DonkeyWs/tbox
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;
}
示例#24
0
文件: spider.c 项目: ahnan4arch/tbox
/* //////////////////////////////////////////////////////////////////////////////////////
 * 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;
}
示例#25
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;
}
示例#26
0
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;
}
示例#27
0
文件: spider.c 项目: ahnan4arch/tbox
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;
}