示例#1
0
static tb_void_t tb_test_strncmp(tb_char_t const* s1, tb_char_t const* s2, tb_size_t size)
{
    __tb_volatile__ tb_long_t   n = 1000000;
    __tb_volatile__ tb_long_t   r = 0;
    tb_hong_t t = tb_mclock();
    while (n--)
    {
        r = tb_strncmp(s1, s2, size);
    }
    t = tb_mclock() - t;
    tb_printf("%lld ms, tb_test_strncmp(%s, %s, %u) = %ld\n", t, s1, s2, size, r);
}
示例#2
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * implementation
 */
tb_int_t xm_string_startswith(lua_State* lua)
{
    // check
    tb_assert_and_check_return_val(lua, 0);

    // get the string and prefix
    size_t              prefix_size = 0;
    tb_char_t const*    string = luaL_checkstring(lua, 1);
    tb_char_t const*    prefix = luaL_checklstring(lua, 2, &prefix_size);
    tb_check_return_val(string && prefix, 0);

    // string:startswith(prefix)? 
    lua_pushboolean(lua, !tb_strncmp(string, prefix, (tb_size_t)prefix_size));

    // ok
    return 1;
}
示例#3
0
文件: path.c 项目: richwu/tbox
tb_char_t const* tb_path_relative_to(tb_char_t const* root, tb_char_t const* path, tb_char_t* data, tb_size_t maxn)
{
    // check
    tb_assert_and_check_return_val(path && data && maxn, tb_null);

    // trace
    tb_trace_d("path: %s", path);

    // the root is the current and the path is absolute? return path directly
    if (!root && !tb_path_is_absolute(path))
    {
        // copy it
        tb_strlcpy(data, path, maxn);

        // translate it
        return tb_path_translate(data, 0, maxn)? data : tb_null;
    }

    // get the absolute path
    tb_size_t path_size = 0;
    tb_char_t path_absolute[TB_PATH_MAXN];
    tb_size_t path_maxn = sizeof(path_absolute);
    path        = tb_path_absolute(path, path_absolute, path_maxn);
    path_size   = tb_strlen(path);
    tb_assert_and_check_return_val(path && path_size && path_size < path_maxn, tb_null);

    // trace
    tb_trace_d("path_absolute: %s", path);

    // get the absolute root
    tb_size_t root_size = 0;
    tb_char_t root_absolute[TB_PATH_MAXN];
    tb_size_t root_maxn = sizeof(root_absolute);
    if (root) 
    {
        // get the absolute root
        root        = tb_path_absolute(root, root_absolute, root_maxn);
        root_size   = tb_strlen(root);
    }
    else
    {
        // get the current directory
        if (!(root_size = tb_directory_current(root_absolute, root_maxn))) return tb_null;

        // translate it
        if (!(root_size = tb_path_translate(root_absolute, root_size, root_maxn))) return tb_null;
        root = root_absolute;
    }
    tb_assert_and_check_return_val(root && root_size && root_size < root_maxn, tb_null);

    // trace
    tb_trace_d("root_absolute: %s", root);

    // same directory? return "."
    if (path_size == root_size && !tb_strncmp(path, root, root_size)) 
    {
        // check
        tb_assert_and_check_return_val(maxn >= 2, ".");

        // return "."
        data[0] = '.';
        data[1] = '\0';
        return data;
    }

    // append separator
    if (path_size + 1 < path_maxn)
    {
        path_absolute[path_size++] = TB_PATH_SEPARATOR;
        path_absolute[path_size] = '\0';
    }
    if (root_size + 1 < root_maxn) 
    {
        root_absolute[root_size++] = TB_PATH_SEPARATOR;
        root_absolute[root_size] = '\0';
    }

    // find the common leading directory
    tb_char_t const*    p = path;
    tb_char_t const*    q = root;
    tb_long_t           last = -1;
    for (; *p && *q && *p == *q; q++, p++)
    {
        // save the last separator
        if (*p == TB_PATH_SEPARATOR) last = q - root;
    }

    // is different directory or outside the windows drive root? using the absolute path
    if (last <= 0 || (last == 2 && root[1] == ':'))
    {
        // the path size
        tb_size_t size = tb_min(path_size - 1, maxn);

        // copy it
        tb_strncpy(data, path, size);
        data[size] = '\0';
    }
    // exists same root?
    else
    {
        // count the remaining levels in root
        tb_size_t count = 0;
        tb_char_t const* l = root + last + 1;
        for (; *l; l++)
        {
            if (*l == TB_PATH_SEPARATOR) count++;
        }

        // append "../" or "..\\"
        tb_char_t* d = data;
        tb_char_t* e = data + maxn;
        while (count--)
        {
            if (d + 3 < e)
            {
                d[0] = '.';
                d[1] = '.';
                d[2] = TB_PATH_SEPARATOR;
                d += 3;
            }
        }

        // append the left path
        l = path + last + 1;
        while (*l && d < e) *d++ = *l++;

        // remove the last separator
        if (d > data) d--;

        // end
        *d = '\0';
    }

    // trace    
    tb_trace_d("relative: %s", data);
    
    // ok?
    return data;
}
示例#4
0
文件: string.c 项目: richwu/tbox
tb_long_t tb_string_cstrncmp(tb_string_ref_t string, tb_char_t const* s, tb_size_t n)
{
    // check
    tb_assert_and_check_return_val(string && s, 0);
    return tb_strncmp(tb_string_cstr(string), s, n);
}
示例#5
0
文件: bplist.c 项目: 1060460048/tbox
static tb_object_ref_t tb_object_bplist_reader_done(tb_stream_ref_t stream)
{
    // check
    tb_assert_and_check_return_val(stream, tb_null);

    // init root
    tb_object_ref_t root = tb_null;

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

    // init size
    tb_hize_t size = tb_stream_size(stream);
    tb_assert_and_check_return_val(size, tb_null);

    // init data
    tb_byte_t data[32] = {0};
    
    // read magic & version
    if (!tb_stream_bread(stream, data, 8)) return tb_null;

    // check magic & version
    if (tb_strncmp((tb_char_t const*)data, "bplist00", 8)) return tb_null;

    // seek to tail
    if (!tb_stream_seek(stream, size - 26)) return tb_null;
    
    // read offset size
    tb_size_t offset_size = tb_stream_bread_u8(stream);
    tb_trace_d("offset_size: %lu", offset_size);
    
    // read item size for array and dictionary
    tb_size_t item_size = tb_stream_bread_u8(stream);
    tb_trace_d("item_size: %lu", item_size);
    
    // read object count
    tb_size_t object_count = (tb_size_t)tb_stream_bread_u64_be(stream);
    tb_trace_d("object_count: %lu", object_count);
    
    // read root object
    tb_size_t root_object = (tb_size_t)tb_stream_bread_u64_be(stream);
    tb_trace_d("root_object: %lu", root_object);

    // read offset table index
    tb_size_t offset_table_index = (tb_size_t)tb_stream_bread_u64_be(stream);
    tb_trace_d("offset_table_index: %lu", offset_table_index);

    // check
    tb_assert_and_check_return_val(item_size && offset_size && object_count, tb_null);

    // init object hash
    tb_object_ref_t* object_hash = (tb_object_ref_t*)tb_malloc0(sizeof(tb_object_ref_t) * object_count);
    tb_assert_and_check_return_val(object_hash, tb_null);

    // done
    tb_bool_t failed = tb_false;
    do
    {
        // walk
        tb_size_t i = 0;
        for (i = 0; i < object_count; i++)
        {
            // seek to the offset entry
            if (!tb_stream_seek(stream, offset_table_index + i * offset_size)) 
            {
                failed = tb_true;
                break;
            }

            // read the object offset
            tb_hize_t offset = 0;
            switch (offset_size)
            {
            case 1:
                offset = tb_stream_bread_u8(stream);
                break;
            case 2:
                offset = tb_stream_bread_u16_be(stream);
                break;
            case 4:
                offset = tb_stream_bread_u32_be(stream);
                break;
            case 8:
                offset = tb_stream_bread_u64_be(stream);
                break;
            default:
                return tb_null;
                break;
            }

            // seek to the object offset 
            if (!tb_stream_seek(stream, offset)) 
            {
                failed = tb_true;
                break;
            }

            // read object
            object_hash[i] = tb_object_bplist_reader_func_object(&reader, item_size);
    //      if (object_hash[i]) tb_object_dump(object_hash[i]);
        }

        // failed?
        tb_check_break(!failed);

        // build array & dictionary items
        for (i = 0; i < object_count; i++)
        {
            tb_object_ref_t object = object_hash[i];
            if (object)
            {
                switch (tb_object_type(object))
                {
                case TB_OBJECT_TYPE_ARRAY:
                    {
                        // the priv data
                        tb_byte_t* priv = (tb_byte_t*)tb_object_getp(object);
                        if (priv)
                        {
                            // count
                            tb_size_t count = (tb_size_t)tb_bits_get_u32_ne(priv);
                            if (count)
                            {
                                // goto item data
                                tb_byte_t const* p = priv + sizeof(tb_uint32_t);

                                // walk items
                                tb_size_t j = 0;
                                for (i = 0; j < count; j++)
                                {
                                    // the item index
                                    tb_size_t item = tb_object_bplist_bits_get(p + j * item_size, item_size);
                                    tb_assert(item < object_count && object_hash[item]);
    //                              tb_trace_d("item: %d", item);

                                    // append item
                                    if (item < object_count && object_hash[item])
                                    {
                                        tb_object_inc(object_hash[item]);
                                        tb_object_array_append(object, object_hash[item]);
                                    }
                                }
                            }

                            // exit priv
                            tb_free(priv);
                            tb_object_setp(object, tb_null);
    //                      tb_object_dump(object);
                        }
                    }
                    break;
                case TB_OBJECT_TYPE_DICTIONARY:
                    { 
                        // the priv data
                        tb_byte_t* priv = (tb_byte_t*)tb_object_getp(object);
                        if (priv)
                        {
                            // count
                            tb_size_t count = (tb_size_t)tb_bits_get_u32_ne(priv);
                            if (count)
                            {
                                // goto item data
                                tb_byte_t const* p = priv + sizeof(tb_uint32_t);

                                // walk items
                                tb_size_t j = 0;
                                for (i = 0; j < count; j++)
                                {
                                    // the key & val
                                    tb_size_t key = tb_object_bplist_bits_get(p + j * item_size, item_size);
                                    tb_size_t val = tb_object_bplist_bits_get(p + (count + j) * item_size, item_size);
                                    tb_assert(key < object_count && object_hash[key]);
                                    tb_assert(val < object_count && object_hash[val]);
    //                              tb_trace_d("key_val: %u => %lu", key, val);

                                    // append the key & val
                                    if (key < object_count && val < object_count && object_hash[key] && object_hash[val])
                                    {
                                        // key must be string now.
                                        tb_assert(tb_object_type(object_hash[key]) == TB_OBJECT_TYPE_STRING);
                                        if (tb_object_type(object_hash[key]) == TB_OBJECT_TYPE_STRING)
                                        {
                                            // set key => val
                                            tb_char_t const* skey = tb_object_string_cstr(object_hash[key]);
                                            if (skey) 
                                            {
                                                tb_object_inc(object_hash[val]);
                                                tb_object_dictionary_set(object, skey, object_hash[val]);
                                            }
                                            tb_assert(skey);
                                        }
                                    }
                                }
                            }

                            // exit priv
                            tb_free(priv);
                            tb_object_setp(object, tb_null);
//                          tb_object_dump(object);
                        }
                    }
                    break;
                default:
                    break;
                }
            }
        }   

    } while (0);

    // exit object hash
    if (object_hash)
    {
        // root
        if (root_object < object_count) root = object_hash[root_object];

        // refn--
        tb_size_t i;
        for (i = 0; i < object_count; i++)
        {
            if (object_hash[i] && i != root_object)
                tb_object_dec(object_hash[i]);
        }

        // exit object hash
        tb_free(object_hash);
        object_hash = tb_null;
    }

    // ok?
    return root;
}
示例#6
0
文件: reader.c 项目: 1060460048/tbox
tb_size_t tb_xml_reader_next(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->rstream, TB_XML_READER_EVENT_NONE);

    // reset event
    impl->event = TB_XML_READER_EVENT_NONE;

    // next
    while (!impl->event)
    {
        // peek character
        tb_char_t* pc = tb_null;
        if (!tb_stream_need(impl->rstream, (tb_byte_t**)&pc, 1) || !pc) break;

        // is element?
        if (*pc == '<') 
        {
            // parse element: <...>
            tb_char_t const* element = tb_xml_reader_element_parse(impl);
            tb_assert_and_check_break(element);

            // is document begin: <?xml version="..." charset=".." ?>
            tb_size_t size = tb_string_size(&impl->element);
            if (size > 4 && !tb_strnicmp(element, "?xml", 4))
            {
                // update event
                impl->event = TB_XML_READER_EVENT_DOCUMENT;

                // update version & charset
                tb_xml_node_ref_t attr = (tb_xml_node_ref_t)tb_xml_reader_attributes(reader); 
                for (; attr; attr = attr->next)
                {
                    if (!tb_string_cstricmp(&attr->name, "version")) tb_string_strcpy(&impl->version, &attr->data);
                    if (!tb_string_cstricmp(&attr->name, "encoding")) tb_string_strcpy(&impl->charset, &attr->data);
                }

                // transform stream => utf-8
                if (tb_string_cstricmp(&impl->charset, "utf-8") && tb_string_cstricmp(&impl->charset, "utf8"))
                {
                    // charset
                    tb_size_t charset = TB_CHARSET_TYPE_UTF8;
                    if (!tb_string_cstricmp(&impl->charset, "gb2312") || !tb_string_cstricmp(&impl->charset, "gbk")) 
                        charset = TB_CHARSET_TYPE_GB2312;
                    else tb_trace_e("the charset: %s is not supported", tb_string_cstr(&impl->charset));

                    // init transform stream
                    if (charset != TB_CHARSET_TYPE_UTF8)
                    {
#ifdef TB_CONFIG_MODULE_HAVE_CHARSET
                        // init the filter stream
                        if (!impl->fstream) impl->fstream = tb_stream_init_filter_from_charset(impl->istream, charset, TB_CHARSET_TYPE_UTF8);
                        else
                        {
                            // ctrl stream
                            if (!tb_stream_ctrl(impl->fstream, TB_STREAM_CTRL_FLTR_SET_STREAM, impl->istream)) break;

                            // the filter
                            tb_stream_filter_ref_t filter = tb_null;
                            if (!tb_stream_ctrl(impl->fstream, TB_STREAM_CTRL_FLTR_GET_FILTER, &filter)) break;
                            tb_assert_and_check_break(filter);

                            // ctrl filter
                            if (!tb_stream_filter_ctrl(filter, TB_STREAM_FILTER_CTRL_CHARSET_SET_FTYPE, charset)) break;
                        }

                        // open the filter stream
                        if (impl->fstream && tb_stream_open(impl->fstream))
                            impl->rstream = impl->fstream;
                        tb_string_cstrcpy(&impl->charset, "utf-8");
#else
                        // trace
                        tb_trace_e("unicode type is not supported, please enable charset module config if you want to use it!");
#endif
                    }
                }
            }
            // is document type: <!DOCTYPE ... >
            else if (size > 8 && !tb_strnicmp(element, "!DOCTYPE", 8))
            {
                // update event
                impl->event = TB_XML_READER_EVENT_DOCUMENT_TYPE;
            }
            // is element end: </name>
            else if (size > 1 && element[0] == '/')
            {
                // check
                tb_check_break(impl->level);

                // update event
                impl->event = TB_XML_READER_EVENT_ELEMENT_END;

                // leave
                impl->level--;
            }
            // is comment: <!-- text -->
            else if (size >= 3 && !tb_strncmp(element, "!--", 3))
            {
                // no comment end?
                if (element[size - 2] != '-' || element[size - 1] != '-')
                {
                    // patch '>'
                    tb_string_chrcat(&impl->element, '>');

                    // seek to comment end
                    tb_char_t ch = '\0';
                    tb_int_t n = 0;
                    while ((ch = tb_stream_bread_s8(impl->rstream)))
                    {
                        // -->
                        if (n == 2 && ch == '>') break;
                        else
                        {
                            // append it
                            tb_string_chrcat(&impl->element, ch);

                            if (ch == '-') n++;
                            else n = 0;
                        }
                    }

                    // update event
                    if (ch != '\0') impl->event = TB_XML_READER_EVENT_COMMENT;
                }
                else impl->event = TB_XML_READER_EVENT_COMMENT;
            }
            // is cdata: <![CDATA[ text ]]>
            else if (size >= 8 && !tb_strnicmp(element, "![CDATA[", 8))
            {
                if (element[size - 2] != ']' || element[size - 1] != ']')
                {
                    // patch '>'
                    tb_string_chrcat(&impl->element, '>');

                    // seek to cdata end
                    tb_char_t ch = '\0';
                    tb_int_t n = 0;
                    while ((ch = tb_stream_bread_s8(impl->rstream)))
                    {
                        // ]]>
                        if (n == 2 && ch == '>') break;
                        else
                        {
                            // append it
                            tb_string_chrcat(&impl->element, ch);

                            if (ch == ']') n++;
                            else n = 0;
                        }
                    }

                    // update event
                    if (ch != '\0') impl->event = TB_XML_READER_EVENT_CDATA;
                }
                else impl->event = TB_XML_READER_EVENT_CDATA;
            }
            // is empty element: <name/>
            else if (size > 1 && element[size - 1] == '/')
            {
                // update event
                impl->event = TB_XML_READER_EVENT_ELEMENT_EMPTY;
            }
            // is element begin: <name>
            else
            {
                // update event
                impl->event = TB_XML_READER_EVENT_ELEMENT_BEG;

                // enter
                impl->level++;
            }

            // trace
//          tb_trace_d("<%s>", element);
        }
        // is text: <> text </>
        else if (*pc)
        {
            // parse text: <> ... <>
            tb_char_t const* text = tb_xml_reader_text_parse(impl);
            if (text && tb_string_cstrcmp(&impl->text, "\r\n") && tb_string_cstrcmp(&impl->text, "\n"))
                impl->event = TB_XML_READER_EVENT_TEXT;

            // trace
//          tb_trace_d("%s", text);
        }
        else 
        {
            // skip the invalid character
            if (!tb_stream_skip(impl->rstream, 1)) break;
        }
    }

    // ok?
    return impl->event;
}