Exemplo n.º 1
0
tb_xml_node_ref_t tb_xml_reader_attributes(tb_xml_reader_ref_t reader)
{
    // check
    tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader;
    tb_assert_and_check_return_val(impl && ( impl->event == TB_XML_READER_EVENT_DOCUMENT
                                            ||  impl->event == TB_XML_READER_EVENT_ELEMENT_BEG
                                            ||  impl->event == TB_XML_READER_EVENT_ELEMENT_END
                                            ||  impl->event == TB_XML_READER_EVENT_ELEMENT_EMPTY), tb_null);

    // init
    tb_char_t const* p = tb_string_cstr(&impl->element);
    tb_char_t const* e = p + tb_string_size(&impl->element);

    // skip name
    while (p < e && *p && !tb_isspace(*p)) p++;
    while (p < e && *p && tb_isspace(*p)) p++;

    // parse attributes
    tb_size_t n = 0;
    while (p < e)
    {
        // parse name
        tb_string_clear(&impl->attribute_name);
        for (; p < e && *p != '='; p++) if (!tb_isspace(*p)) tb_string_chrcat(&impl->attribute_name, *p);
        if (*p != '=') break;

        // parse data
        tb_string_clear(&impl->attribute_data);
        for (p++; p < e && (*p != '\'' && *p != '\"'); p++) ;
        if (*p != '\'' && *p != '\"') break;
        for (p++; p < e && (*p != '\'' && *p != '\"'); p++) tb_string_chrcat(&impl->attribute_data, *p);
        if (*p != '\'' && *p != '\"') break;
        p++;

        // append node
        if (tb_string_cstr(&impl->attribute_name) && tb_string_cstr(&impl->attribute_data))
        {
            // node
            tb_xml_node_ref_t prev = n > 0? (tb_xml_node_ref_t)&impl->attributes[n - 1] : tb_null;
            tb_xml_node_ref_t node = (tb_xml_node_ref_t)&impl->attributes[n];

            // init node
            tb_string_strcpy(&node->name, &impl->attribute_name);
            tb_string_strcpy(&node->data, &impl->attribute_data);

            // append node
            if (prev) prev->next = node;
            node->next = tb_null;

            // next
            n++;
        }
    }

    // ok?
    return n? (tb_xml_node_ref_t)&impl->attributes[0] : tb_null;
}
Exemplo n.º 2
0
Arquivo: string.c Projeto: richwu/tbox
tb_char_t const* tb_string_ltrim(tb_string_ref_t string)
{
    // check
    tb_assert_and_check_return_val(string, tb_null);

    // init
    tb_char_t*  s = (tb_char_t*)tb_string_cstr(string);
    tb_size_t   n = tb_string_size(string);
    tb_check_return_val(s && n, tb_null);

    // done
    tb_char_t*  p = s;
    tb_char_t*  e = s + n;
    while (p < e && tb_isspace(*p)) p++;

    // strip it
    if (p < e)
    {
        // move it if exists spaces
        if (p > s) tb_buffer_memmov(string, p - s);
    }
    // clear it
    else tb_string_clear(string);

    // ok?
    return tb_string_cstr(string);
}
Exemplo n.º 3
0
Arquivo: json.c Projeto: luxuan/tbox
static tb_object_ref_t tb_object_json_reader_done(tb_stream_ref_t stream)
{
    // check
    tb_assert_and_check_return_val(stream, tb_null);

    // init reader
    tb_object_json_reader_t reader = {0};
    reader.stream = stream;

    // skip spaces
    tb_char_t type = '\0';
    while (tb_stream_left(stream)) 
    {
        type = tb_stream_bread_s8(stream);
        if (!tb_isspace(type)) break;
    }

    // empty?
    tb_check_return_val(tb_stream_left(stream), tb_null);

    // the func
    tb_object_json_reader_func_t func = tb_object_json_reader_func(type);
    tb_assert_and_check_return_val(func, tb_null);

    // read it
    return func(&reader, type);
}
Exemplo n.º 4
0
Arquivo: parser.c Projeto: 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;
}
Exemplo n.º 5
0
Arquivo: parser.c Projeto: waruqi/vm86
tb_bool_t vm86_parser_get_number_value(tb_char_t const** pp, tb_char_t const* e, tb_uint32_t* value)
{ 
    // check
    tb_assert(pp && e && value);

    // done
    tb_bool_t           ok = tb_false;
    tb_char_t const*    p = *pp;
    do
    {
        // check
        tb_check_break(p < e && (tb_isdigit16(*p) || *p == '-'));

        // is sign?
        tb_bool_t is_sign = tb_false;
        if (*p == '-')
        {
            is_sign = tb_true;
            p++;
        }

        // save the base
        tb_char_t const* b = p;

        // skip the value
        while (p < e && tb_isdigit16(*p)) p++;
        
        // is hex?
        tb_bool_t is_hex = tb_false;
        if (p < e && *p == 'h') 
        {
            is_hex = tb_true;
            p++;
        }

        // check end, exclude variable name
        tb_check_break(!tb_isalpha(*p) && *p != '_');

        // save value
        *value = is_hex? tb_s16tou32(b) : tb_s10tou32(b);
        if (is_sign) *value = (tb_uint32_t)(((tb_sint32_t)*value) * -1);

        // skip the space
        while (p < e && tb_isspace(*p)) p++;

        // ok
        ok = tb_true;

    } while (0);

    // update the code pointer if ok
    if (ok) *pp = p;

    // ok?
    return ok;
}
Exemplo n.º 6
0
Arquivo: parser.c Projeto: waruqi/vm86
tb_bool_t vm86_parser_get_instruction_name(tb_char_t const** pp, tb_char_t const* e, tb_char_t* name, tb_size_t maxn)
{
    // check
    tb_assert(pp && e && name && maxn);

    // done
    tb_bool_t           ok = tb_false;
    tb_char_t const*    p = *pp;
    do
    {
        // save base
        tb_char_t const* b = p;

        // skip name
        while (p < e && tb_isalpha(*p)) p++;
        tb_check_break(p <= e && p - b < maxn);

        // not instruction name?
        if (p < e && !tb_isspace(*p)) break;

        // save name
        tb_memcpy(name, b, p - b);

        // end
        name[p - b] = '\0';

        // skip the space
        while (p < e && tb_isspace(*p)) p++;

        // ok
        ok = tb_true;

    } while (0);

    // update the code pointer if ok
    if (ok) *pp = p;

    // ok?
    return ok;
}
Exemplo n.º 7
0
static tb_void_t tb_check_is()
{
    tb_int_t i = 0;
    for (i = 0; i < 256; i++)
    {
        if ((tb_isspace(i)? 1 : 0) != (isspace(i)? 1 : 0)) tb_printf("[e] isspace: 0x%02x\n", i);
        if ((tb_isalpha(i)? 1 : 0) != (isalpha(i)? 1 : 0)) tb_printf("[e] isalpha: 0x%02x\n", i);
        if ((tb_isdigit(i)? 1 : 0) != (isdigit(i)? 1 : 0)) tb_printf("[e] isdigit: 0x%02x\n", i);
        if ((tb_isupper(i)? 1 : 0) != (isupper(i)? 1 : 0)) tb_printf("[e] isupper: 0x%02x\n", i);
        if ((tb_islower(i)? 1 : 0) != (islower(i)? 1 : 0)) tb_printf("[e] islower: 0x%02x\n", i);
        if ((tb_isascii(i)? 1 : 0) != (isascii(i)? 1 : 0)) tb_printf("[e] isascii: 0x%02x\n", i);
    }
}
Exemplo n.º 8
0
static tb_bool_t tb_demo_spider_make_ourl(tb_demo_spider_t* spider, tb_char_t const* url, tb_char_t* data, tb_size_t maxn)
{
    // check
    tb_assert_and_check_return_val(spider && url && data && maxn, tb_false);

    // skip protocol
	tb_char_t* p = (tb_char_t*)url;
	if (!tb_strnicmp(p, "http://", 7)) p += 7;
	else if (!tb_strnicmp(p, "https://", 8)) p += 8;

    // skip space
    while (*p && tb_isspace(*p)) p++;

	// format ourl
	tb_long_t n = tb_snprintf(data, maxn, "%s/%s", spider->root, p);
    tb_assert_and_check_return_val(n > 0 && n < maxn, tb_false);

    // no root? append '/'
    if (!tb_strchr(p, '/') && !tb_strchr(p, '\\')) data[n++] = '/';
    tb_assert_and_check_return_val(n < maxn, tb_false);

    // '\\' => '/'
    if (data[n - 1] == '/') data[n - 1] = '/';

    // directory? append index.html
    if (data[n - 1] == '/') n += tb_snprintf(data + n, maxn - n, "%s", "index.html");
    tb_assert_and_check_return_val(n > 0 && n < maxn, tb_false);

    // end
	data[n] = '\0';

    // replace '?' => '_'
    p = data;
    while (*p)
    {
        // replace
        if (*p == '?') *p = '_';

        // next
        p++;
    }

	// trace
	tb_trace_d("make: %s => %s", url, data);

	// ok?
	return n > 0? tb_true : tb_false;
}
Exemplo n.º 9
0
Arquivo: json.c Projeto: luxuan/tbox
static tb_object_ref_t tb_object_json_reader_func_array(tb_object_json_reader_t* reader, tb_char_t type)
{
    // check
    tb_assert_and_check_return_val(reader && reader->stream && type == '[', tb_null);

    // init array
    tb_object_ref_t array = tb_object_array_init(TB_OBJECT_JSON_READER_ARRAY_GROW, tb_false);
    tb_assert_and_check_return_val(array, tb_null);

    // done
    tb_char_t ch;
    tb_bool_t ok = tb_true;
    while (ok && tb_stream_left(reader->stream)) 
    {
        // read one character
        ch = tb_stream_bread_s8(reader->stream);

        // end?
        if (ch == ']') break;
        // no space? skip ','
        else if (!tb_isspace(ch) && ch != ',')
        {
            // the func
            tb_object_json_reader_func_t func = tb_object_json_reader_func(ch);
            tb_assert_and_check_break_state(func, ok, tb_false);

            // read item
            tb_object_ref_t item = func(reader, ch);
            tb_assert_and_check_break_state(item, ok, tb_false);

            // append item
            tb_object_array_append(array, item);
        }
    }

    // failed?
    if (!ok)
    {
        // exit it
        if (array) tb_object_exit(array);
        array = tb_null;
    }

    // ok?
    return array;
}
Exemplo n.º 10
0
tb_uint64_t tb_s16tou64(tb_char_t const* s)
{
    // check
    tb_assert_and_check_return_val(s, 0);

    // skip space
    while (tb_isspace(*s)) s++;

    // has sign?
    tb_int_t sign = 0;
    if (*s == '-') 
    {
        sign = 1;
        s++;
    }

    // skip "0x"
    if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
        s += 2;

    // skip '0'
    while ((*s) == '0') s++;

    // compute number
    tb_uint64_t val = 0;
    while (*s)
    {
        tb_char_t ch = *s;
        if (tb_isdigit10(ch))
            val = (val << 4) + (ch - '0');
        else if (ch > ('a' - 1) && ch < ('f' + 1))
            val = (val << 4) + (ch - 'a') + 10;
        else if (ch > ('A' - 1) && ch < ('F' + 1))
            val = (val << 4) + (ch - 'A') + 10;
        else break;
    
        s++;
    }

    // is negative number?
    if (sign) val = ~val + 1;

    // the value
    return val;
}
Exemplo n.º 11
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * implementation
 */
tb_uint64_t tb_s2tou64(tb_char_t const* s)
{
    // check
    tb_assert_and_check_return_val(s, 0);

    // skip space
    while (tb_isspace(*s)) s++;

    // has sign?
    tb_int_t sign = 0;
    if (*s == '-') 
    {
        sign = 1;
        s++;
    }

    // skip "0b"
    if (s[0] == '0' && (s[1] == 'b' || s[1] == 'B'))
        s += 2;

    // skip '0'
    while ((*s) == '0') s++;

    // compute number
    tb_uint64_t val = 0;
    while (*s)
    {
        tb_char_t ch = *s;
        if (tb_isdigit2(ch))
            val = (val << 1) + (ch - '0');
        else break;
    
        s++;
    }

    // is negative number?
    if (sign) val = ~val + 1;

    // the value
    return val;
}
Exemplo n.º 12
0
tb_char_t const* tb_xml_reader_element(tb_xml_reader_ref_t reader)
{
    // check
    tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader;
    tb_assert_and_check_return_val(impl && ( impl->event == TB_XML_READER_EVENT_ELEMENT_BEG
                                            ||  impl->event == TB_XML_READER_EVENT_ELEMENT_END
                                            ||  impl->event == TB_XML_READER_EVENT_ELEMENT_EMPTY), tb_null);

    // init
    tb_char_t const* p = tb_null;
    tb_char_t const* b = tb_string_cstr(&impl->element);
    tb_char_t const* e = b + tb_string_size(&impl->element);
    tb_assert_and_check_return_val(b, tb_null);

    // </name> or <name ... />
    if (b < e && *b == '/') b++;
    for (p = b; p < e && *p && !tb_isspace(*p) && *p != '/'; p++) ;

    // ok?
    return p > b? tb_string_cstrncpy(&impl->element_name, b, p - b) : tb_null;
}
Exemplo n.º 13
0
static tb_void_t g2_svg_element_polygon_points(g2_svg_element_polygon_t* element, tb_char_t const* data)
{
	// init
	tb_char_t const* p = data;
	tb_assert_and_check_return(p);

	// size
	tb_size_t size = 0;

	// trace
	tb_trace_impl("polygon: points");
	while (*p)
	{
		if (!tb_isspace(*p) && tb_isdigit(*p))
			p = g2_svg_element_polygon_point(element, p, &size);
		else p++;
	}

	// close path
	if (element->path) g2_path_close(element->path);
}
Exemplo n.º 14
0
Arquivo: object.c Projeto: luxuan/tbox
tb_object_ref_t tb_object_dump(tb_object_ref_t object, tb_size_t format)
{
    // check
    tb_assert_and_check_return_val(object, tb_null);

    // data
    tb_object_ref_t odata = tb_object_data(object, format);
    if (odata)
    {
        // the data and size 
        tb_byte_t const*    data = (tb_byte_t const*)tb_object_data_getp(odata);
        tb_size_t           size = tb_object_data_size(odata);
        if (data && size)
        {
            // done
            tb_char_t const*    p = (tb_char_t const*)data;
            tb_char_t const*    e = (tb_char_t const*)data + size;
            tb_char_t           b[4096 + 1];
            if (p && p < e)
            {
                while (p < e && *p && tb_isspace(*p)) p++;
                while (p < e && *p)
                {
                    tb_char_t*          q = b;
                    tb_char_t const*    d = b + 4096;
                    for (; p < e && q < d && *p; p++, q++) *q = *p;
                    *q = '\0';
                    tb_printf("%s", b);
                }
                tb_printf("\n");
            }
        }

        // exit data
        tb_object_exit(odata);
    }

    // the object
    return object;
}
Exemplo n.º 15
0
tb_object_ref_t tb_object_dump(tb_object_ref_t object)
{
    // check
    tb_assert_and_check_return_val(object, tb_null);

    // data
    tb_object_ref_t odata = tb_object_data(object, TB_OBJECT_FORMAT_XML);
    if (odata)
    {
        // data & size 
        tb_byte_t const*    data = (tb_byte_t const*)tb_object_data_getp(odata);
        tb_size_t           size = tb_object_data_size(odata);
        if (data && size)
        {
            tb_char_t const*    p = tb_strstr((tb_char_t const*)data, "?>");
            tb_char_t const*    e = (tb_char_t const*)data + size;
            tb_char_t           b[4096 + 1];
            if (p && p + 2 < e)
            {
                p += 2;
                while (p < e && *p && tb_isspace(*p)) p++;
                while (p < e && *p)
                {
                    tb_char_t*          q = b;
                    tb_char_t const*    d = b + 4096;
                    for (; p < e && q < d && *p; p++, q++) *q = *p;
                    *q = '\0';
                    tb_printf("%s", b);
                }
                tb_printf("\n");
            }
        }

        // exit data
        tb_object_exit(odata);
    }

    return object;
}
Exemplo n.º 16
0
Arquivo: string.c Projeto: richwu/tbox
tb_char_t const* tb_string_rtrim(tb_string_ref_t string)
{
    // check
    tb_assert_and_check_return_val(string, tb_null);

    // init
    tb_char_t*  s = (tb_char_t*)tb_string_cstr(string);
    tb_size_t   n = tb_string_size(string);
    tb_check_return_val(s && n, tb_null);

    // done
    tb_char_t*  e = s + n - 1;
    while (e >= s && tb_isspace(*e)) e--;

    // strip it
    if (e >= s) tb_string_strip(string, e - s + 1);
    // clear it
    else tb_string_clear(string);

    // ok?
    return tb_string_cstr(string);
}
Exemplo n.º 17
0
Arquivo: parser.c Projeto: waruqi/vm86
/* //////////////////////////////////////////////////////////////////////////////////////
 * implementation
 */
tb_bool_t vm86_parser_get_variable_name(tb_char_t const** pp, tb_char_t const* e, tb_char_t* name, tb_size_t maxn)
{
    // check
    tb_assert(pp && e && name && maxn);

    // done
    tb_bool_t           ok = tb_false;
    tb_char_t const*    p = *pp;
    do
    {
        // save base
        tb_char_t const* b = p;

        // check
        tb_check_break(p < e && (tb_isalpha(*p) || *p == '_'));
        p++;

        // get name
        while (p < e && (tb_isalpha(*p) || *p == '_' || tb_isdigit(*p))) p++;
        tb_check_break(p <= e && p - b < maxn);
        tb_memcpy(name, b, p - b);

        // end
        name[p - b] = '\0';

        // skip the space
        while (p < e && tb_isspace(*p)) p++;

        // ok
        ok = tb_true;

    } while (0);

    // update the code pointer if ok
    if (ok) *pp = p;

    // ok?
    return ok;
}
Exemplo n.º 18
0
tb_double_t tb_stod(tb_char_t const* s)
{
    // check
    tb_assert_and_check_return_val(s, 0);

    // skip space
    tb_char_t const* p = s;
    while (tb_isspace(*p)) p++;

    // has sign?
    if (*p == '-') p++;

    // is hex?
    if (*p++ == '0')
    {
        if (*p == 'x' || *p == 'X')
            return tb_s16tod(s);
        else if (*p == 'b' || *p == 'B')
            return tb_s2tod(s);
        else return tb_s8tod(s);
    }
    else return tb_s10tod(s);
}
Exemplo n.º 19
0
tb_uint64_t tb_s10tou64(tb_char_t const* s)
{
    // check
    tb_assert_and_check_return_val(s, 0);

    // skip space
    while (tb_isspace(*s)) s++;

    // has sign?
    tb_int_t sign = 0;
    if (*s == '-') 
    {
        sign = 1;
        s++;
    }

    // skip '0'
    while ((*s) == '0') s++;

    // compute number
    tb_uint64_t val = 0;
    while (*s)
    {
        tb_char_t ch = *s;
        if (tb_isdigit10(ch))
            val = val * 10 + (ch - '0');
        else break;
    
        s++;
    }

    // is negative number?
    if (sign) val = ~val + 1;

    // the value
    return val;
}
Exemplo n.º 20
0
Arquivo: json.c Projeto: luxuan/tbox
static tb_object_ref_t tb_object_json_reader_func_dictionary(tb_object_json_reader_t* reader, tb_char_t type)
{
    // check
    tb_assert_and_check_return_val(reader && reader->stream && type == '{', tb_null);

    // init key name
    tb_static_string_t  kname;
    tb_char_t           kdata[8192];
    if (!tb_static_string_init(&kname, kdata, 8192)) return tb_null;

    // init dictionary
    tb_object_ref_t dictionary = tb_object_dictionary_init(0, tb_false);
    tb_assert_and_check_return_val(dictionary, tb_null);

    // walk
    tb_char_t ch;
    tb_bool_t ok = tb_true;
    tb_bool_t bkey = tb_false;
    tb_size_t bstr = 0;
    while (ok && tb_stream_left(reader->stream)) 
    {
        // read one character
        ch = tb_stream_bread_s8(reader->stream);

        // end?
        if (ch == '}') break;
        // no space? skip ','
        else if (!tb_isspace(ch) && ch != ',')
        {
            // no key?
            if (!bkey)
            {
                // is str?
                if (ch == '\"' || ch == '\'') bstr = !bstr;
                // is key end?
                else if (!bstr && ch == ':') bkey = tb_true;
                // append key
                else if (bstr) tb_static_string_chrcat(&kname, ch);
            }
            // key ok? read val
            else
            {
                // trace
                tb_trace_d("key: %s", tb_static_string_cstr(&kname));

                // the func
                tb_object_json_reader_func_t func = tb_object_json_reader_func(ch);
                tb_assert_and_check_break_state(func, ok, tb_false);

                // read val
                tb_object_ref_t val = func(reader, ch);
                tb_assert_and_check_break_state(val, ok, tb_false);

                // set key => val
                tb_object_dictionary_insert(dictionary, tb_static_string_cstr(&kname), val);

                // reset key
                bstr = 0;
                bkey = tb_false;
                tb_static_string_clear(&kname);
            }
        }
    }

    // failed?
    if (!ok)
    {
        // exit it
        if (dictionary) tb_object_exit(dictionary);
        dictionary = tb_null;
    }

    // exit key name
    tb_static_string_exit(&kname);

    // ok?
    return dictionary;
}
Exemplo n.º 21
0
tb_double_t tb_s16tod(tb_char_t const* s)
{
    // check
    tb_assert_and_check_return_val(s, 0);

    // skip space
    while (tb_isspace(*s)) s++;

    // has sign?
    tb_int_t sign = 0;
    if (*s == '-') 
    {
        sign = 1;
        s++;
    }

    // nan?
    if (s[0] == 'n' && s[1] == 'a' && s[2] == 'n')
        return TB_NAN;

    // inf or -inf?
    if (s[0] == 'i' && s[1] == 'n' && s[2] == 'f')
        return sign? -TB_INF : TB_INF;

    // skip "0x"
    if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
        s += 2;

    // compute double: lhs.rhs
    tb_int_t    dec = 0;
    tb_uint64_t lhs = 0;
    tb_double_t rhs = 0.;
    tb_int_t    zeros = 0;
    tb_int8_t   decimals[256];
    tb_int8_t*  d = decimals;
    tb_int8_t*  e = decimals + 256;
    while (*s)
    {
        tb_char_t ch = *s;

        // is the part of decimal?
        if (ch == '.')
        {
            if (!dec) 
            {
                dec = 1;
                s++;
                continue ;
            }
            else break;
        }

        // parse integer & decimal
        if (tb_isdigit10(ch))
        {
            // save decimals
            if (dec) 
            {
                if (d < e)
                {
                    if (ch != '0')
                    {
                        // fill '0'
                        while (zeros--) *d++ = 0;
                        zeros = 0;

                        // save decimal
                        *d++ = ch - '0';
                    }
                    else zeros++;
                }
            }
            else lhs = (lhs << 4) + (ch - '0');
        }
        else if (ch > ('a' - 1) && ch < ('f' + 1))
        {
            // save decimals
            if (dec) 
            {
                if (d < e)
                {
                    if (ch != '0')
                    {
                        // fill '0'
                        while (zeros--) *d++ = 0;
                        zeros = 0;

                        // save decimal
                        *d++ = (ch - 'a') + 10;
                    }
                    else zeros++;
                }
            }
            else lhs = (lhs << 4) + (ch - 'a') + 10;
        }
        else if (ch > ('A' - 1) && ch < ('F' + 1))
        {
            // save decimals
            if (dec) 
            {
                if (d < e)
                {
                    if (ch != '0')
                    {
                        // fill '0'
                        while (zeros--) *d++ = 0;
                        zeros = 0;

                        // save decimal
                        *d++ = (ch - 'A') + 10;
                    }
                    else zeros++;
                }
            }
            else lhs = (lhs << 4) + (ch - 'A') + 10;
        }
        else break;
    
        s++;
    }

    // check
    tb_assert_and_check_return_val(d <= decimals + 256, 0);

    // compute decimal
    while (d-- > decimals) rhs = (rhs + *d) / 16;

    // merge 
    return (sign? ((tb_double_t)lhs + rhs) * -1. : ((tb_double_t)lhs + rhs));
}
Exemplo n.º 22
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * main
 */ 
tb_int_t tb_demo_stream_async_stream_main(tb_int_t argc, tb_char_t** argv)
{
    // done
    tb_demo_context_t   context = {0};
    do
    {
        // init option
        context.option = tb_option_init("astream", "the astream demo", g_options);
        tb_assert_and_check_break(context.option);
    
        // done option
        if (tb_option_done(context.option, argc - 1, &argv[1]))
        {
            // debug and verbose
            context.debug   = tb_option_find(context.option, "debug")? tb_false : tb_true;
            context.verbose = tb_option_find(context.option, "no-verbose")? tb_false : tb_true;
        
            // done url
            if (tb_option_find(context.option, "url")) 
            {
                // init event
                context.event = tb_event_init();
                tb_assert_and_check_break(context.event);

                // init istream
                context.istream = tb_async_stream_init_from_url(tb_null, tb_option_item_cstr(context.option, "url"));
                tb_assert_and_check_break(context.istream);

                // ctrl http
                if (tb_async_stream_type(context.istream) == TB_STREAM_TYPE_HTTP) 
                {
                    // enable gzip?
                    if (tb_option_find(context.option, "gzip"))
                    {
                        // auto unzip
                        if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_AUTO_UNZIP, 1)) break;

                        // need gzip
                        if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_HEAD, "Accept-Encoding", "gzip,deflate")) break;
                    }

                    // enable debug?
                    if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_HEAD_FUNC, context.debug? tb_demo_istream_head_func : tb_null)) break;

                    // custem header?
                    if (tb_option_find(context.option, "header"))
                    {
                        // init
                        tb_string_t key;
                        tb_string_t val;
                        tb_string_init(&key);
                        tb_string_init(&val);

                        // done
                        tb_bool_t           k = tb_true;
                        tb_char_t const*    p = tb_option_item_cstr(context.option, "header");
                        while (*p)
                        {
                            // is key?
                            if (k)
                            {
                                if (*p != ':' && !tb_isspace(*p)) tb_string_chrcat(&key, *p++);
                                else if (*p == ':') 
                                {
                                    // skip ':'
                                    p++;

                                    // skip space
                                    while (*p && tb_isspace(*p)) p++;

                                    // is val now
                                    k = tb_false;
                                }
                                else p++;
                            }
                            // is val?
                            else
                            {
                                if (*p != ';') tb_string_chrcat(&val, *p++);
                                else
                                {
                                    // skip ';'
                                    p++;

                                    // skip space
                                    while (*p && tb_isspace(*p)) p++;

                                    // set header
                                    if (tb_string_size(&key) && tb_string_size(&val))
                                    {
                                        if (context.debug) tb_printf("header: %s: %s\n", tb_string_cstr(&key), tb_string_cstr(&val));
                                        if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_HEAD, tb_string_cstr(&key), tb_string_cstr(&val))) break;
                                    }

                                    // is key now
                                    k = tb_true;

                                    // clear key & val
                                    tb_string_clear(&key);
                                    tb_string_clear(&val);
                                }
                            }
                        }

                        // set header
                        if (tb_string_size(&key) && tb_string_size(&val))
                        {
                            if (context.debug) tb_printf("header: %s: %s\n", tb_string_cstr(&key), tb_string_cstr(&val));
                            if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_HEAD, tb_string_cstr(&key), tb_string_cstr(&val))) break;
                        }

                        // exit 
                        tb_string_exit(&key);
                        tb_string_exit(&val);
                    }

                    // keep alive?
                    if (tb_option_find(context.option, "keep-alive"))
                    {
                        if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_HEAD, "Connection", "keep-alive")) break;
                    }

                    // post-data?
                    if (tb_option_find(context.option, "post-data"))
                    {
                        tb_char_t const*    post_data = tb_option_item_cstr(context.option, "post-data");
                        tb_hize_t           post_size = tb_strlen(post_data);
                        if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_METHOD, TB_HTTP_METHOD_POST)) break;
                        if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_POST_DATA, post_data, post_size)) break;
                        if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_POST_FUNC, tb_demo_http_post_func)) break;
                        if (context.debug) tb_printf("post: %llu\n", post_size);
                    }
                    // post-file?
                    else if (tb_option_find(context.option, "post-file"))
                    {
                        tb_char_t const* url = tb_option_item_cstr(context.option, "post-file");
                        if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_METHOD, TB_HTTP_METHOD_POST)) break;
                        if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_POST_URL, url)) break;
                        if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_POST_FUNC, tb_demo_http_post_func)) break;
                        if (context.debug) tb_printf("post: %s\n", url);
                    }
                }

                // set range
                if (tb_option_find(context.option, "range"))
                {
                    tb_char_t const* p = tb_option_item_cstr(context.option, "range");
                    if (p)
                    {
                        // the bof
                        tb_hize_t eof = 0;
                        tb_hize_t bof = tb_atoll(p);
                        while (*p && tb_isdigit(*p)) p++;
                        if (*p == '-')
                        {
                            p++;
                            eof = tb_atoll(p);
                        }
                        if (!tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_HTTP_SET_RANGE, bof, eof)) break;
                    }
                }

                // set timeout
                if (tb_option_find(context.option, "timeout"))
                {
                    tb_size_t timeout = tb_option_item_uint32(context.option, "timeout");
                    tb_async_stream_ctrl(context.istream, TB_STREAM_CTRL_SET_TIMEOUT, &timeout);
                }

                // print verbose info
                if (context.verbose) tb_printf("open: %s: ..\n", tb_option_item_cstr(context.option, "url"));

                // open istream
                if (!tb_async_stream_open(context.istream, tb_demo_istream_open_func, &context)) 
                {
                    // print verbose info
                    if (context.verbose) tb_printf("open: failed\n");
                    break;
                }

                // wait it
                tb_event_wait(context.event, -1);
            }
            else tb_option_help(context.option);
        }
        else tb_option_help(context.option);

    } while (0);

    // exit transfer
    if (context.transfer) tb_async_transfer_exit(context.transfer);
    context.transfer = tb_null;

    // exit istream
    if (context.istream) tb_async_stream_exit(context.istream);
    context.istream = tb_null;

    // exit ostream
    if (context.ostream) tb_async_stream_exit(context.ostream);
    context.ostream = tb_null;

    // exit option
    if (context.option) tb_option_exit(context.option);
    context.option = tb_null;

    // exit event
    if (context.event) tb_event_exit(context.event);
    context.event = tb_null;

    return 0;
}
Exemplo n.º 23
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;
}
Exemplo n.º 24
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * implementation
 */
tb_time_t tb_http_date_from_cstr(tb_char_t const* cstr, tb_size_t size)
{
    // check
    tb_assert_and_check_return_val(cstr && size, 0);

    // done
    tb_tm_t             tm = {0};
    tb_time_t           date = 0;
    tb_char_t const*    p = cstr;
    tb_char_t const*    e = cstr + size;
    do
    {
        // skip space
        while (p < e && tb_isspace(*p)) p++;

        // ignore
#if 0
        // parse week
        if ((p + 6 < e && !tb_strnicmp(p, "Monday", 6)) || (p + 3 < e && !tb_strnicmp(p, "Mon", 3)))
            tm.week = 1;
        else if ((p + 7 < e && !tb_strnicmp(p, "Tuesday", 7)) || (p + 3 < e && !tb_strnicmp(p, "Tue", 3)))
            tm.week = 2;
        else if ((p + 9 < e && !tb_strnicmp(p, "Wednesday", 9)) || (p + 3 < e && !tb_strnicmp(p, "Wed", 3)))
            tm.week = 3;    
        else if ((p + 8 < e && !tb_strnicmp(p, "Thursday", 8)) || (p + 3 < e && !tb_strnicmp(p, "Thu", 3)))
            tm.week = 4;
        else if ((p + 6 < e && !tb_strnicmp(p, "Friday", 6)) || (p + 3 < e && !tb_strnicmp(p, "Fri", 3)))
            tm.week = 5;
        else if ((p + 8 < e && !tb_strnicmp(p, "Saturday", 8)) || (p + 3 < e && !tb_strnicmp(p, "Sat", 3)))
            tm.week = 6;
        else if ((p + 6 < e && !tb_strnicmp(p, "Sunday", 6)) || (p + 3 < e && !tb_strnicmp(p, "Sun", 3)))
            tm.week = 7;
#endif

        // skip week
        while (p < e && *p != ',' && !tb_isspace(*p)) p++;

        if (p < e && (*p == ',' || tb_isspace(*p))) p++;

        // skip space
        while (p < e && tb_isspace(*p)) p++;

        // is day?
        tb_bool_t year_suffix = tb_true;
        if (p < e && tb_isdigit(*p))
        {
            /* prefix year
             * 
             * .e.g 
             * year_suffix == false: Sun, 06-Nov-1994 08:49:37
             * year_suffix == true: Sun Nov 6 08:49:37 1994
             */
            year_suffix = tb_false;

            // parse day
            tm.mday = tb_s10tou32(p);

            // skip day
            while (p < e && *p != '-' && !tb_isspace(*p)) p++;

            if (p < e && (*p == '-' || tb_isspace(*p))) p++;
        }

        // parse month
        if (p + 3 < e && !tb_strnicmp(p, "Jan", 3))
            tm.month = 1;
        else if (p + 3 < e && !tb_strnicmp(p, "Feb", 3))
            tm.month = 2;
        else if (p + 3 < e && !tb_strnicmp(p, "Mar", 3))
            tm.month = 3;
        else if (p + 3 < e && !tb_strnicmp(p, "Apr", 3))
            tm.month = 4;
        else if (p + 3 < e && !tb_strnicmp(p, "May", 3))
            tm.month = 5;
        else if (p + 3 < e && !tb_strnicmp(p, "Jun", 3))
            tm.month = 6;
        else if (p + 3 < e && !tb_strnicmp(p, "Jul", 3))
            tm.month = 7;
        else if (p + 3 < e && !tb_strnicmp(p, "Aug", 3))
            tm.month = 8;
        else if (p + 3 < e && !tb_strnicmp(p, "Sep", 3))
            tm.month = 9;
        else if (p + 3 < e && !tb_strnicmp(p, "Oct", 3))
            tm.month = 10;
        else if (p + 3 < e && !tb_strnicmp(p, "Nov", 3))
            tm.month = 11;
        else if (p + 3 < e && !tb_strnicmp(p, "Dec", 3))
            tm.month = 12;

        // skip month
        while (p < e && *p != '-' && !tb_isspace(*p)) p++;

        if (p < e && (*p == '-' || tb_isspace(*p))) p++;

        // year suffix?
        if (year_suffix)
        {   
            // parse day
            tm.mday = tb_s10tou32(p);
        }
        else
        {
            // parse year
            tm.year = tb_s10tou32(p);
            if (tm.year < 100) tm.year += 2000;
        }

        // skip year or day
        while (p < e && !tb_isspace(*p)) p++; 
        while (p < e && tb_isspace(*p)) p++; 

        // parse hour
        tm.hour = tb_s10tou32(p);

        // skip hour
        while (p < e && *p != ':') p++;

        if (p < e && *p == ':') p++;

        // parse minute
        tm.minute = tb_s10tou32(p);

        // skip minute
        while (p < e && *p != ':') p++;

        if (p < e && *p == ':') p++;

        // parse second
        tm.second = tb_s10tou32(p);

        // year suffix?
        if (year_suffix)
        {
            // skip time
            while (p < e && !tb_isspace(*p)) p++; 
            while (p < e && tb_isspace(*p)) p++; 

            // parse year
            tm.year = tb_s10tou32(p);
            if (tm.year < 100) tm.year += 1900;
        }

        // make date
        date = tb_gmmktime(&tm);

    } while (0);

    // ok?
    return date;
}
Exemplo n.º 25
0
Arquivo: parser.c Projeto: waruqi/vm86
tb_bool_t vm86_parser_get_register(tb_char_t const** pp, tb_char_t const* e, tb_uint16_t* r)
{
    // check
    tb_assert(pp && e && r);

    // done
    tb_bool_t           ok = tb_false;
    tb_char_t const*    p = *pp;
    do
    {
        // save base
        tb_char_t const* b = p;

        // get instruction name
        tb_char_t name[64] = {0};
        while (p < e && tb_isalpha(*p)) p++;
        tb_check_break(p <= e && p - b < sizeof(name));
        tb_memcpy(name, b, p - b);

        // skip the space
        while (p < e && tb_isspace(*p)) p++;

        // the register entry type
        typedef struct __vm86_register_entry_t
        {
            // the register name
            tb_char_t const*        name;

            // the register index
            tb_uint8_t              index;

        }vm86_register_entry_t, *vm86_register_entry_ref_t;

        // the registers
        static vm86_register_entry_t s_registers[] =
        {
            { "ah",     VM86_REGISTER_EAX | VM86_REGISTER_AH }
        ,   { "al",     VM86_REGISTER_EAX | VM86_REGISTER_AL }
        ,   { "ax",     VM86_REGISTER_EAX | VM86_REGISTER_AX }
        ,   { "bh",     VM86_REGISTER_EBX | VM86_REGISTER_BH }
        ,   { "bl",     VM86_REGISTER_EBX | VM86_REGISTER_BL }
        ,   { "bx",     VM86_REGISTER_EBX | VM86_REGISTER_BX }
        ,   { "ch",     VM86_REGISTER_ECX | VM86_REGISTER_CH }
        ,   { "cl",     VM86_REGISTER_ECX | VM86_REGISTER_CL }
        ,   { "cx",     VM86_REGISTER_ECX | VM86_REGISTER_CX }
        ,   { "dh",     VM86_REGISTER_EDX | VM86_REGISTER_DH }
        ,   { "dl",     VM86_REGISTER_EDX | VM86_REGISTER_DL }
        ,   { "dx",     VM86_REGISTER_EDX | VM86_REGISTER_DX }
        ,   { "eax",    VM86_REGISTER_EAX }
        ,   { "ebp",    VM86_REGISTER_EBP }
        ,   { "ebx",    VM86_REGISTER_EBX }
        ,   { "ecx",    VM86_REGISTER_ECX }
        ,   { "edi",    VM86_REGISTER_EDI }
        ,   { "edx",    VM86_REGISTER_EDX }
        ,   { "esi",    VM86_REGISTER_ESI }
        ,   { "esp",    VM86_REGISTER_ESP }
        };

        // init iterator
        tb_array_iterator_t array_iterator;
        tb_iterator_ref_t   iterator = tb_array_iterator_init_mem(&array_iterator, s_registers, tb_arrayn(s_registers), sizeof(vm86_register_entry_t));

        // find register by the binary search
        tb_size_t itor = tb_binary_find_all_if(iterator, vm86_parser_comp_register, name);
        tb_check_break(itor != tb_iterator_tail(iterator));

        // get the register
        vm86_register_entry_ref_t entry = (vm86_register_entry_ref_t)tb_iterator_item(iterator, itor);
        tb_assert_and_check_break(entry && (entry->index & VM86_REGISTER_MASK) < VM86_REGISTER_MAXN);

        // save register
        *r = entry->index;

        // trace
        tb_trace_d("register: %s: %x", name, entry->index);

        // ok 
        ok = tb_true;

    } while (0);

    // update the code pointer if ok
    if (ok) *pp = p;

    // ok?
    return ok;
}
Exemplo n.º 26
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;
    }
}
Exemplo n.º 27
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * main
 */ 
tb_int_t tb_demo_stream_main(tb_int_t argc, tb_char_t** argv)
{
    // done
    tb_option_ref_t     option = tb_null;
    tb_stream_ref_t     istream = tb_null;
    tb_stream_ref_t     ostream = tb_null;
    tb_stream_ref_t     pstream = tb_null;
    do
    {
        // init option
        option = tb_option_init("stream", "the stream demo", g_options);
        tb_assert_and_check_break(option);
    
        // done option
        if (tb_option_done(option, argc - 1, &argv[1]))
        {
            // debug & verbose
            tb_bool_t debug = tb_option_find(option, "debug");
            tb_bool_t verbose = tb_option_find(option, "no-verbose")? tb_false : tb_true;
        
            // done url
            if (tb_option_find(option, "url")) 
            {
                // init istream
                istream = tb_stream_init_from_url(tb_option_item_cstr(option, "url"));
                tb_assert_and_check_break(istream);
    
                // ctrl http
                if (tb_stream_type(istream) == TB_STREAM_TYPE_HTTP) 
                {
                    // enable gzip?
                    if (tb_option_find(option, "gzip"))
                    {
                        // auto unzip
                        if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_AUTO_UNZIP, 1)) break;

                        // need gzip
                        if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_HEAD, "Accept-Encoding", "gzip,deflate")) break;
                    }

                    // enable debug?
                    if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_HEAD_FUNC, debug? tb_demo_stream_head_func : tb_null)) break;

                    // custem header?
                    if (tb_option_find(option, "header"))
                    {
                        // init
                        tb_string_t key;
                        tb_string_t val;
                        tb_string_init(&key);
                        tb_string_init(&val);

                        // done
                        tb_bool_t           k = tb_true;
                        tb_char_t const*    p = tb_option_item_cstr(option, "header");
                        while (*p)
                        {
                            // is key?
                            if (k)
                            {
                                if (*p != ':' && !tb_isspace(*p)) tb_string_chrcat(&key, *p++);
                                else if (*p == ':') 
                                {
                                    // skip ':'
                                    p++;

                                    // skip space
                                    while (*p && tb_isspace(*p)) p++;

                                    // is val now
                                    k = tb_false;
                                }
                                else p++;
                            }
                            // is val?
                            else
                            {
                                if (*p != ';') tb_string_chrcat(&val, *p++);
                                else
                                {
                                    // skip ';'
                                    p++;

                                    // skip space
                                    while (*p && tb_isspace(*p)) p++;

                                    // set header
                                    if (tb_string_size(&key) && tb_string_size(&val))
                                    {
                                        if (debug) tb_printf("header: %s: %s\n", tb_string_cstr(&key), tb_string_cstr(&val));
                                        if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_HEAD, tb_string_cstr(&key), tb_string_cstr(&val))) break;
                                    }

                                    // is key now
                                    k = tb_true;

                                    // clear key & val
                                    tb_string_clear(&key);
                                    tb_string_clear(&val);
                                }
                            }
                        }

                        // set header
                        if (tb_string_size(&key) && tb_string_size(&val))
                        {
                            if (debug) tb_printf("header: %s: %s\n", tb_string_cstr(&key), tb_string_cstr(&val));
                            if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_HEAD, tb_string_cstr(&key), tb_string_cstr(&val))) break;
                        }

                        // exit 
                        tb_string_exit(&key);
                        tb_string_exit(&val);
                    }

                    // keep alive?
                    if (tb_option_find(option, "keep-alive"))
                    {
                        if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_HEAD, "Connection", "keep-alive")) break;
                    }

                    // post-data?
                    if (tb_option_find(option, "post-data"))
                    {
                        tb_char_t const*    post_data = tb_option_item_cstr(option, "post-data");
                        tb_hize_t           post_size = tb_strlen(post_data);
                        if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_METHOD, TB_HTTP_METHOD_POST)) break;
                        if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_POST_DATA, post_data, post_size)) break;
                        if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_POST_FUNC, tb_demo_http_post_func)) break;
                        if (debug) tb_printf("post: %llu\n", post_size);
                    }
                    // post-file?
                    else if (tb_option_find(option, "post-file"))
                    {
                        tb_char_t const* url = tb_option_item_cstr(option, "post-file");
                        if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_METHOD, TB_HTTP_METHOD_POST)) break;
                        if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_POST_URL, url)) break;
                        if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_POST_FUNC, tb_demo_http_post_func)) break;
                        if (debug) tb_printf("post: %s\n", url);
                    }
                }

                // set range
                if (tb_option_find(option, "range"))
                {
                    tb_char_t const* p = tb_option_item_cstr(option, "range");
                    if (p)
                    {
                        // the bof
                        tb_hize_t eof = 0;
                        tb_hize_t bof = tb_atoll(p);
                        while (*p && tb_isdigit(*p)) p++;
                        if (*p == '-')
                        {
                            p++;
                            eof = tb_atoll(p);
                        }
                        if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_RANGE, bof, eof)) break;
                    }
                }

                // set timeout
                if (tb_option_find(option, "timeout"))
                {
                    tb_size_t timeout = tb_option_item_uint32(option, "timeout");
                    if (!tb_stream_ctrl(istream, TB_STREAM_CTRL_SET_TIMEOUT, timeout)) break;
                }

                // print verbose info
                if (verbose) tb_printf("open: %s: ..\n", tb_option_item_cstr(option, "url"));

                // open istream
                if (!tb_stream_open(istream)) 
                {
                    // print verbose info
                    if (verbose) tb_printf("open: %s\n", tb_state_cstr(tb_stream_state(istream)));
                    break;
                }

                // print verbose info
                if (verbose) tb_printf("open: ok\n");

                // init ostream
                if (tb_option_find(option, "more0"))
                {
                    // the path
                    tb_char_t const* path = tb_option_item_cstr(option, "more0");

                    // init
                    ostream = tb_stream_init_from_file(path, TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_BINARY | TB_FILE_MODE_TRUNC);

                    // print verbose info
                    if (verbose) tb_printf("save: %s\n", path);
                }
                else 
                {
                    // the name
                    tb_char_t const* name = tb_strrchr(tb_option_item_cstr(option, "url"), '/');
                    if (!name) name = tb_strrchr(tb_option_item_cstr(option, "url"), '\\');
                    if (!name) name = "/stream.file";

                    // the path
                    tb_char_t path[TB_PATH_MAXN] = {0};
                    if (tb_directory_current(path, TB_PATH_MAXN))
                        tb_strcat(path, name);
                    else break;

                    // init file
                    ostream = tb_stream_init_from_file(path, TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_BINARY | TB_FILE_MODE_TRUNC);

                    // print verbose info
                    if (verbose) tb_printf("save: %s\n", path);
                }
                tb_assert_and_check_break(ostream);

                // the limit rate
                tb_size_t limitrate = 0;
                if (tb_option_find(option, "limitrate"))
                    limitrate = tb_option_item_uint32(option, "limitrate");

                // save it
                tb_hong_t           save = 0;
                tb_demo_context_t   context = {0}; 
                context.verbose     = verbose;
                if ((save = tb_transfer_done(istream, ostream, limitrate, tb_demo_stream_save_func, &context)) < 0) break;
            }
            else tb_option_help(option);
        }
        else tb_option_help(option);

    } while (0);

    // exit pstream
    if (pstream) tb_stream_exit(pstream);
    pstream = tb_null;

    // exit istream
    if (istream) tb_stream_exit(istream);
    istream = tb_null;

    // exit ostream
    if (ostream) tb_stream_exit(ostream);
    ostream = tb_null;

    // exit option
    if (option) tb_option_exit(option);
    option = tb_null;

    return 0;
}