예제 #1
0
파일: json.c 프로젝트: richwu/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;
}
예제 #2
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * private implementation
 */
static tb_long_t tb_ifaddrs_netlink_socket_init()
{
    // done
    tb_long_t sock = -1;
    tb_bool_t ok = tb_false;
    do
    {
        // make socket
        sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
        tb_check_break(sock >= 0);

        // bind socket
        struct sockaddr_nl addr;
        memset(&addr, 0, sizeof(addr));
        addr.nl_family = AF_NETLINK;
        if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) break;

        // ok
        ok = tb_true;

    } while (0);
    
    // failed?
    if (!ok)
    {
        // exit it
        if (sock >= 0) close(sock);
        sock = -1;
    }

    // ok?
    return sock;
}
예제 #3
0
파일: memory.c 프로젝트: siwuxian/xmake
/* //////////////////////////////////////////////////////////////////////////////////////
 * implementation
 */
tb_bool_t tb_native_memory_init()
{   
    // enter
    tb_spinlock_enter_without_profiler(&g_lock);

    // done
    tb_bool_t ok = tb_false;
    do
    {
        // have been inited?
        tb_check_break_state(!g_heap, ok, tb_true);

        // make heap
        g_heap = (tb_handle_t)HeapCreate(0, 0, 0);
        tb_check_break(g_heap);

        // ok
        ok = tb_true;

    } while (0);

    // leave
    tb_spinlock_leave(&g_lock);

    // ok?
    return ok;
}
예제 #4
0
파일: directory.c 프로젝트: waruqi/tbox
tb_size_t tb_directory_home(tb_char_t* path, tb_size_t maxn)
{
    // check
    tb_assert_and_check_return_val(path && maxn, 0);

    // the home directory
    tb_bool_t   ok = tb_false;
    tb_handle_t pidl = tb_null;
    tb_wchar_t  home[TB_PATH_MAXN] = {0};
    do
    {
        // get the appdata folder location
        if (S_OK != tb_shell32()->SHGetSpecialFolderLocation(tb_null, 0x1a /* CSIDL_APPDATA */, &pidl)) break;
        tb_check_break(pidl);

        // get the home directory   
        if (!tb_shell32()->SHGetPathFromIDListW(pidl, home)) break;

        // ok
        ok = tb_true;

    } while (0);

    // exit pidl
    if (pidl) GlobalFree(pidl);
    pidl = tb_null;

    // wtoa
    tb_size_t size = ok? tb_wtoa(path, home, maxn) : 0;

    // ok?
    return size != -1? size : 0;
}
예제 #5
0
파일: looker.c 프로젝트: luxuan/tbox
static tb_long_t tb_dns_looker_resp(tb_dns_looker_impl_t* impl, tb_ipaddr_ref_t addr)
{
    // check
    tb_check_return_val(!(impl->step & TB_DNS_LOOKER_STEP_RESP), 1);

    // need wait if no data
    impl->step &= ~TB_DNS_LOOKER_STEP_NEVT;

    // recv response data
    tb_byte_t rpkt[4096];
    while (1)
    {
        // read data
        tb_long_t read = tb_socket_urecv(impl->sock, tb_null, rpkt, 4096);
        //tb_trace_d("read %d", read);
        tb_assert_and_check_return_val(read >= 0, -1);

        // no data? 
        if (!read)
        {
            // end? read x, read 0
            tb_check_break(!tb_static_buffer_size(&impl->rpkt));
    
            // abort? read 0, read 0
            tb_check_return_val(!impl->tryn, -1);
            
            // tryn++
            impl->tryn++;

            // continue 
            return 0;
        }
        else impl->tryn = 0;

        // copy data
        tb_static_buffer_memncat(&impl->rpkt, rpkt, read);
    }

    // done
    if (!tb_dns_looker_resp_done(impl, addr)) return -1;

    // check
    tb_assert_and_check_return_val(tb_static_string_size(&impl->name) && !tb_ipaddr_ip_is_empty(addr), -1);

    // save address to cache
    tb_dns_cache_set(tb_static_string_cstr(&impl->name), addr);

    // finish it
    impl->step |= TB_DNS_LOOKER_STEP_RESP;
    impl->tryn = 0;

    // reset rpkt
    impl->size = 0;
    tb_static_buffer_clear(&impl->rpkt);

    // ok
    tb_trace_d("response: ok");
    return 1;
}
예제 #6
0
파일: looker.c 프로젝트: waruqi/tbox
tb_long_t tb_dns_looker_spak(tb_dns_looker_ref_t self, tb_ipaddr_ref_t addr)
{
    // check
    tb_dns_looker_t* looker = (tb_dns_looker_t*)self;
    tb_assert_and_check_return_val(looker && addr, -1);

    // init 
    tb_long_t r = -1;
    do
    {
        // request
        r = tb_dns_looker_reqt(looker);
        tb_check_break(r > 0);
            
        // response
        r = tb_dns_looker_resp(looker, addr);
        tb_check_break(r > 0);

    } while (0);

    // failed?
    if (r < 0)
    {
        // next
        if (looker->itor + 1 <= looker->maxn) looker->itor++;
        else looker->itor = 0;

        // has next?
        if (looker->itor)
        {
            // reset step, no event now, need not wait
            looker->step = TB_DNS_LOOKER_STEP_NONE | TB_DNS_LOOKER_STEP_NEVT;

            // reset rpkt
            looker->size = 0;
            tb_static_buffer_clear(&looker->rpkt);

            // continue 
            r = 0;
        }
    }

    // ok?
    return r;
}
예제 #7
0
파일: looker.c 프로젝트: waruqi/tbox
/* //////////////////////////////////////////////////////////////////////////////////////
 * interfaces
 */
tb_dns_looker_ref_t tb_dns_looker_init(tb_char_t const* name)
{
    // check
    tb_assert_and_check_return_val(name, tb_null);

    // must be not address
    tb_assert(!tb_ipaddr_ip_cstr_set(tb_null, name, TB_IPADDR_FAMILY_NONE));

    // done
    tb_bool_t           ok = tb_false;
    tb_dns_looker_t*    looker = tb_null;
    do
    {
        // make looker
        looker = tb_malloc0_type(tb_dns_looker_t);
        tb_assert_and_check_return_val(looker, tb_null);

        // dump server
//      tb_dns_server_dump();

        // get the dns server list
        looker->maxn = tb_dns_server_get(looker->list);
        tb_check_break(looker->maxn && looker->maxn <= tb_arrayn(looker->list));

        // init name
        if (!tb_static_string_init(&looker->name, (tb_char_t*)looker->data, TB_DNS_NAME_MAXN)) break;
        tb_static_string_cstrcpy(&looker->name, name);

        // init rpkt
        if (!tb_static_buffer_init(&looker->rpkt, looker->data + TB_DNS_NAME_MAXN, TB_DNS_RPKT_MAXN)) break;

        // init family
        looker->family = TB_IPADDR_FAMILY_IPV4;

        // init sock
        looker->sock = tb_socket_init(TB_SOCKET_TYPE_UDP, looker->family);
        tb_assert_and_check_break(looker->sock);

        // init itor
        looker->itor = 1;

        // ok
        ok = tb_true;

    } while (0);

    // failed?
    if (!ok)
    {
        // exit it
        if (looker) tb_dns_looker_exit((tb_dns_looker_ref_t)looker);
        looker = tb_null;
    }

    // ok?
    return (tb_dns_looker_ref_t)looker;
}
예제 #8
0
파일: parser.c 프로젝트: 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;
}
예제 #9
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * implementation
 */
tb_size_t tb_environment_load(tb_environment_ref_t environment, tb_char_t const* name)
{
    // check
    tb_assert_and_check_return_val(environment && name, 0);

    // clear environment first
    tb_vector_clear(environment);

    // get values
    tb_char_t const* values = tb_environment_get_impl(name, tb_null);
    tb_check_return_val(values, 0);

    // init value string
    tb_string_t value;
    if (tb_string_init(&value)) 
    {
        // done
        tb_char_t const*    p = values;
        tb_char_t           c = '\0';
        while (1)
        {
            // the character
            c = *p++;

            // make value
            if (c != ';' && c) tb_string_chrcat(&value, c);
            else 
            {
                // save value to environment
                if (tb_string_size(&value)) 
                    tb_vector_insert_tail(environment, tb_string_cstr(&value));

                // clear value 
                tb_string_clear(&value);

                // end?
                tb_check_break(c);
            }
        }

        // exit value string
        tb_string_exit(&value);
    }

    // exit values
    if (values) tb_free(values);
    values = tb_null;

    // ok?
    return tb_vector_size(environment);
}
예제 #10
0
파일: thread_pool.c 프로젝트: luxuan/tbox
tb_thread_pool_task_ref_t tb_thread_pool_task_init(tb_thread_pool_ref_t pool, tb_char_t const* name, tb_thread_pool_task_done_func_t done, tb_thread_pool_task_exit_func_t exit, tb_cpointer_t priv, tb_bool_t urgent)
{
    // check
    tb_thread_pool_impl_t* impl = (tb_thread_pool_impl_t*)pool;
    tb_assert_and_check_return_val(impl && done, tb_null);

    // init the post size
    tb_size_t post_size = 0;

    // enter
    tb_spinlock_enter(&impl->lock);

    // done
    tb_bool_t               ok = tb_false;
    tb_thread_pool_job_t*   job = tb_null;
    do
    {
        // stoped?
        tb_check_break(!impl->bstoped);

        // init task
        tb_thread_pool_task_t task = {0};
        task.name       = name;
        task.done       = done;
        task.exit       = exit;
        task.priv       = priv;
        task.urgent     = urgent;

        // post task
        job = tb_thread_pool_jobs_post_task(impl, &task, &post_size);
        tb_assert_and_check_break(job);

        // refn++
        job->refn++;

        // ok
        ok = tb_true;

    } while (0);

    // leave
    tb_spinlock_leave(&impl->lock);

    // post the workers
    if (ok && post_size) tb_thread_pool_worker_post(impl, post_size);
    // failed?
    else if (!ok) job = tb_null;

    // ok?
    return (tb_thread_pool_task_ref_t)job;
}
예제 #11
0
파일: heap.c 프로젝트: 1060460048/tbox
static tb_void_t tb_heap_check(tb_heap_impl_t* impl)
{
    // init
    tb_byte_t*  data = impl->data;
    tb_size_t   tail = impl->size;
    tb_size_t   step = impl->func.size;
    tb_size_t   parent = 0;

    // walk
    for (; parent < tail; parent++)
    {   
        // the left child node
        tb_size_t   lchild  = (parent << 1) + 1;
        tb_check_break(lchild < tail);

        // the parent data
        tb_pointer_t parent_data = impl->func.data(&impl->func, data + parent * step);

        // check?
        if (impl->func.comp(&impl->func, impl->func.data(&impl->func, data + lchild * step), parent_data) < 0) 
        {
            tb_trace_d("lchild[%lu]: invalid, parent: %lu", lchild, parent);
            break;
        }

        // the right child node
        tb_size_t   rchild  = (parent << 1) + 2;
        tb_check_break(rchild < tail);

        // check?
        if (impl->func.comp(&impl->func, impl->func.data(&impl->func, data + rchild * step), parent_data) < 0) 
        {
            tb_trace_d("rchild[%lu]: invalid, parent: %lu", rchild, parent);
            break;
        }
    }
}
예제 #12
0
static tb_bool_t tb_async_transfer_ostream_open_func(tb_async_stream_ref_t stream, tb_size_t state, tb_cpointer_t priv)
{
    // check
    tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)priv;
    tb_assert_and_check_return_val(stream && impl && impl->open.func, tb_false);

    // trace
    tb_trace_d("open: ostream: %s, state: %s", tb_url_cstr(tb_async_stream_url(stream)), tb_state_cstr(state));

    // done
    tb_bool_t ok = tb_true;
    do
    {
        // ok?
        tb_check_break(state == TB_STATE_OK);

        // reset state
        state = TB_STATE_UNKNOWN_ERROR;

        // check
        tb_assert_and_check_break(impl->istream);
 
        // killed?
        if (TB_STATE_KILLING == tb_atomic_get(&impl->state))
        {
            state = TB_STATE_KILLED;
            break;
        }

        // done func
        ok = tb_async_transfer_open_func(impl, TB_STATE_OK, tb_async_stream_offset(impl->istream), tb_async_stream_size(impl->istream), impl->open.func, impl->open.priv);

        // ok
        state = TB_STATE_OK;

    } while (0);

    // failed?
    if (state != TB_STATE_OK) 
    {
        // done func
        ok = tb_async_transfer_open_func(impl, state, 0, 0, impl->open.func, impl->open.priv);
    }

    // ok
    return ok;
}
예제 #13
0
static tb_fixed_pool_slot_t* tb_fixed_pool_slot_find(tb_fixed_pool_impl_t* impl, tb_pointer_t data)
{
    // check
    tb_assert_and_check_return_val(impl && data, tb_null);

    // done
    tb_fixed_pool_slot_t* slot = tb_null;
    do
    {
        // belong to the current slot?
        if (impl->current_slot && tb_fixed_pool_slot_exists(impl->current_slot, data))
        {
            slot = impl->current_slot;
            break;
        }
            
        // find the slot from the partial slots
        tb_for_all_if(tb_fixed_pool_slot_t*, partial_slot, tb_list_entry_itor(&impl->partial_slots), partial_slot)
        {
            // is this?
            if (tb_fixed_pool_slot_exists(partial_slot, data))
            {
                slot = partial_slot;
                break;
            }
        }
        
        // no found?
        tb_check_break(!slot);

        // find the slot from the full slots
        tb_for_all_if(tb_fixed_pool_slot_t*, full_slot, tb_list_entry_itor(&impl->full_slots), full_slot)
        {
            // is this?
            if (tb_fixed_pool_slot_exists(full_slot, data))
            {
                slot = full_slot;
                break;
            }
        }

    } while (0);

    // ok?
    return slot;
}
예제 #14
0
tb_bool_t tb_ssl_clos(tb_ssl_ref_t self)
{
    // the ssl
    tb_ssl_t* ssl = (tb_ssl_t*)self;
    tb_assert_and_check_return_val(ssl, tb_false);

    // open it
    tb_long_t ok = -1;
    while (!(ok = tb_ssl_clos_try(self)))
    {
        // wait it
        ok = tb_ssl_wait(self, TB_SOCKET_EVENT_RECV | TB_SOCKET_EVENT_SEND, ssl->timeout);
        tb_check_break(ok > 0);
    }

    // ok?
    return ok > 0? tb_true : tb_false;
}
예제 #15
0
파일: thread_pool.c 프로젝트: luxuan/tbox
tb_long_t tb_thread_pool_task_wait_all(tb_thread_pool_ref_t pool, tb_long_t timeout)
{
    // check
    tb_thread_pool_impl_t* impl = (tb_thread_pool_impl_t*)pool;
    tb_assert_and_check_return_val(impl, -1);

    // wait it
    tb_size_t size = 0;
    tb_hong_t time = tb_cache_time_spak();
    while ((timeout < 0 || tb_cache_time_spak() < time + timeout))
    {
        // enter
        tb_spinlock_enter(&impl->lock);

        // the jobs count
        size = impl->jobs_pool? tb_fixed_pool_size(impl->jobs_pool) : 0;

        // trace
        tb_trace_d("wait: jobs: %lu, waiting: %lu, pending: %lu, urgent: %lu: .."
                    , size
                    , tb_list_entry_size(&impl->jobs_waiting)
                    , tb_list_entry_size(&impl->jobs_pending) 
                    , tb_list_entry_size(&impl->jobs_urgent));

#if 0
        tb_for_all_if (tb_thread_pool_job_t*, job, tb_list_entry_itor(&impl->jobs_pending), job)
        {
            tb_trace_d("wait: job: %s from pending", tb_state_cstr(tb_atomic_get(&job->state)));
        }
#endif

        // leave
        tb_spinlock_leave(&impl->lock);

        // ok?
        tb_check_break(size);

        // wait some time
        tb_msleep(200);
    }

    // ok?
    return !size? 1 : 0;
}
예제 #16
0
파일: scheduler_io.c 프로젝트: waruqi/tbox
static tb_void_t tb_lo_scheduler_io_loop(tb_lo_coroutine_ref_t coroutine, tb_cpointer_t priv)
{
    // check
    tb_lo_scheduler_io_ref_t scheduler_io = (tb_lo_scheduler_io_ref_t)priv;
    tb_assert(scheduler_io && scheduler_io->poller);

    // the scheduler
    tb_lo_scheduler_t* scheduler = scheduler_io->scheduler;
    tb_assert(scheduler);

    // enter coroutine
    tb_lo_coroutine_enter(coroutine)
    {
        // loop
        while (!scheduler->stopped)
        {
            // finish all other ready coroutines first
            while (tb_lo_scheduler_ready_count(scheduler) > 1)
            {
                // yield it
                tb_lo_coroutine_yield();
 
#ifndef TB_CONFIG_MICRO_ENABLE
                // spak timer
                if (!tb_lo_scheduler_io_timer_spak(scheduler_io)) break;
#endif
            }

            // no more suspended coroutines? loop end
            tb_check_break(tb_lo_scheduler_suspend_count(scheduler));

            // trace
            tb_trace_d("loop: wait %ld ms ..", tb_lo_scheduler_io_timer_delay(scheduler_io));

            // no more ready coroutines? wait io events and timers (TODO)
            if (tb_poller_wait(scheduler_io->poller, tb_lo_scheduler_io_events, tb_lo_scheduler_io_timer_delay(scheduler_io)) < 0) break;
 
#ifndef TB_CONFIG_MICRO_ENABLE
            // spak timer
            if (!tb_lo_scheduler_io_timer_spak(scheduler_io)) break;
#endif
        }
    }
}
예제 #17
0
static tb_bool_t tb_async_transfer_open_done_func(tb_size_t state, tb_hize_t offset, tb_hong_t size, tb_cpointer_t priv)
{
    // the impl
    tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)priv;
    tb_assert_and_check_return_val(impl && impl->done.func, tb_false);

    // trace
    tb_trace_d("open_done: offset: %llu, size: %lld, state: %s", offset, size, tb_state_cstr(state));

    // done
    tb_bool_t ok = tb_true;
    do
    {
        // ok? 
        tb_check_break(state == TB_STATE_OK);

        // reset state
        state = TB_STATE_UNKNOWN_ERROR;
        
        // killed?
        if (TB_STATE_KILLING == tb_atomic_get(&impl->state))
        {
            state = TB_STATE_KILLED;
            break;
        }

        // done it
        if (!tb_async_transfer_done((tb_async_transfer_ref_t)impl, impl->done.func, impl->done.priv)) break;

        // ok
        state = TB_STATE_OK;

    } while (0);

    // failed? 
    if (state != TB_STATE_OK) 
    {   
        // done func for closing it
        ok = tb_async_transfer_done_func(impl, state);
    }

    // ok?
    return ok;
}
예제 #18
0
tb_bool_t tb_async_transfer_resume(tb_async_transfer_ref_t transfer)
{
    // check
    tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)transfer;
    tb_assert_and_check_return_val(impl && impl->aicp, tb_false);

    // done
    tb_bool_t ok = tb_false;
    tb_size_t state_pause = TB_STATE_OK;
    do
    {
        // must be opened?
        tb_check_break(TB_STATE_OPENED == tb_atomic_get(&impl->state));

        // resume it
        tb_size_t state_pause = tb_atomic_fetch_and_set(&impl->state_pause, TB_STATE_OK);

        // pausing or ok? return ok directly
        tb_check_return_val(state_pause == TB_STATE_PAUSED, tb_true);

        // check
        tb_assert_and_check_break(impl->istream);
        tb_assert_and_check_break(impl->ostream);

        // init some rate info
        impl->done.base_time      = tb_aicp_time(impl->aicp);
        impl->done.base_time1s    = impl->done.base_time;
        impl->done.saved_size1s   = 0;
        impl->done.current_rate   = 0;

        // read it
        if (!tb_async_stream_read(impl->istream, (tb_size_t)tb_atomic_get(&impl->limited_rate), tb_async_transfer_istream_read_func, impl)) break;

        // ok
        ok = tb_true;

    } while (0);

    // failed? restore state
    if (!ok && state_pause != TB_STATE_OK) tb_atomic_pset(&impl->state_pause, TB_STATE_OK, state_pause);

    // ok?
    return ok;
}
예제 #19
0
파일: timer.c 프로젝트: 1060460048/tbox
tb_void_t tb_timer_task_kill(tb_timer_ref_t timer, tb_timer_task_ref_t task)
{
    // check
    tb_timer_impl_t*        impl = (tb_timer_impl_t*)timer;
    tb_timer_task_impl_t*   task_impl = (tb_timer_task_impl_t*)task;
    tb_assert_and_check_return(impl && impl->pool && task_impl);

    // trace
    tb_trace_d("kill: when: %lld, period: %u, refn: %u", task_impl->when, task_impl->period, task_impl->refn);

    // enter
    tb_spinlock_enter(&impl->lock);

    // done
    do
    {
        // expired or removed?
        tb_check_break(task_impl->refn == 2);

        // find it
        tb_size_t itor = tb_find_all_if(impl->heap, tb_timer_comp_by_task, task_impl);
        tb_assert_and_check_break(itor != tb_iterator_tail(impl->heap));

        // del this task_impl
        tb_heap_del(impl->heap, itor);

        // killed
        task_impl->killed = 1;

        // no repeat
        task_impl->repeat = 0;
                
        // modify when => now
        task_impl->when = tb_timer_now(impl);

        // re-add task_impl
        tb_heap_put(impl->heap, task_impl);

    } while (0);

    // leave
    tb_spinlock_leave(&impl->lock);
}
예제 #20
0
파일: sql.c 프로젝트: richwu/tbox
/* //////////////////////////////////////////////////////////////////////////////////////
 * test
 */
static tb_void_t tb_demo_database_sql_test_done(tb_database_sql_ref_t database, tb_char_t const* sql)
{
    // check
    tb_assert_and_check_return(database && sql);

    // done
    do
    {
        // done sql
        if (!tb_database_sql_done(database, sql))
        {
            // trace
            tb_trace_e("done %s failed, error: %s", sql, tb_state_cstr(tb_database_sql_state(database)));
            break ;
        }

        // load result
//      tb_iterator_ref_t result = tb_database_sql_result_load(database, tb_true);
        tb_iterator_ref_t result = tb_database_sql_result_load(database, tb_false);
        tb_check_break(result);

        // trace
        tb_trace_i("==============================================================================");
        tb_trace_i("row: size: %lu", tb_iterator_size(result));

        // walk result
        tb_for_all_if (tb_iterator_ref_t, row, result, row)
        {
            // trace
            tb_tracef_i("[row: %lu, col: size: %lu]: ", row_itor, tb_iterator_size(row));

            // walk items
            tb_for_all_if (tb_database_sql_value_t*, value, row, value)
            {
                // trace
                tb_tracet_i("[%s:%s] ", tb_database_sql_value_name(value), tb_database_sql_value_text(value));
            }

            // trace
            tb_tracet_i(__tb_newline__);
        }
예제 #21
0
파일: timer.c 프로젝트: 1060460048/tbox
tb_void_t tb_timer_loop(tb_timer_ref_t timer)
{
    // check
    tb_timer_impl_t* impl = (tb_timer_impl_t*)timer;
    tb_assert_and_check_return(impl);

    // work++
    tb_atomic_fetch_and_inc(&impl->work);

    // init event 
    tb_spinlock_enter(&impl->lock);
    if (!impl->event) impl->event = tb_event_init();
    tb_spinlock_leave(&impl->lock);

    // loop
    while (!tb_atomic_get(&impl->stop))
    {
        // the delay
        tb_size_t delay = tb_timer_delay(timer);
        if (delay)
        {
            // the event
            tb_spinlock_enter(&impl->lock);
            tb_event_ref_t event = impl->event;
            tb_spinlock_leave(&impl->lock);
            tb_check_break(event);

            // wait some time
            if (tb_event_wait(event, delay) < 0) break;
        }

        // spak ctime
        if (impl->ctime) tb_cache_time_spak();

        // spak it
        if (!tb_timer_spak(timer)) break;
    }

    // work--
    tb_atomic_fetch_and_dec(&impl->work);
}
예제 #22
0
파일: parser.c 프로젝트: 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;
}
예제 #23
0
tb_long_t tb_transfer_pool_wait_all(tb_transfer_pool_ref_t pool, tb_long_t timeout)
{
    // check
    tb_transfer_pool_impl_t* impl = (tb_transfer_pool_impl_t*)pool;
    tb_assert_and_check_return_val(impl, -1);

    // wait it
    tb_size_t size = 0;
    tb_hong_t time = tb_cache_time_spak();
    while ((timeout < 0 || tb_cache_time_spak() < time + timeout))
    {
        // enter
        tb_spinlock_enter(&impl->lock);

        // the size
        tb_size_t size = tb_list_entry_size(&impl->work);

        // trace
        tb_trace_d("wait: %lu: ..", size);

        // trace work
#ifdef __tb_debug__
        if (size) tb_walk_all(tb_list_entry_itor(&impl->work), tb_transfer_pool_work_wait, tb_null);
#endif

        // leave
        tb_spinlock_leave(&impl->lock);

        // ok?
        tb_check_break(size);

        // wait some time
        tb_msleep(200);
    }

    // ok?
    return !size? 1 : 0;
}
예제 #24
0
tb_long_t tb_aicp_wait_all(tb_aicp_ref_t aicp, tb_long_t timeout)
{
    // check
    tb_aicp_impl_t* impl = (tb_aicp_impl_t*)aicp;
    tb_assert_and_check_return_val(impl, -1);

    // trace
    tb_trace_d("wait: all: ..");

    // wait it
    tb_size_t size = 0;
    tb_hong_t time = tb_cache_time_spak();
    while ((timeout < 0 || tb_cache_time_spak() < time + timeout))
    {
        // enter
        tb_spinlock_enter(&impl->lock);

        // the aico count
        size = impl->pool? tb_fixed_pool_size(impl->pool) : 0;

        // trace
        tb_trace_d("wait: count: %lu: ..", size);

        // leave
        tb_spinlock_leave(&impl->lock);

        // ok?
        tb_check_break(size);

        // wait some time
        tb_msleep(200);
    }

    // ok?
    return !size? 1 : 0;
}
예제 #25
0
static tb_void_t tb_async_transfer_istream_clos_func(tb_async_stream_ref_t stream, tb_size_t state, tb_cpointer_t priv)
{
    // check
    tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)priv;
    tb_assert_and_check_return(stream && impl);

    // trace
    tb_trace_d("clos: istream: %s, state: %s", tb_url_cstr(tb_async_stream_url(stream)), tb_state_cstr(state));

    // done
    do
    {
        // ok?
        tb_check_break(state == TB_STATE_OK);

        // reset state
        state = TB_STATE_UNKNOWN_ERROR;
           
        // clos it
        if (!tb_async_stream_clos(impl->ostream, tb_async_transfer_ostream_clos_func, impl)) break;

        // ok
        state = TB_STATE_OK;

    } while (0);

    // failed?
    if (state != TB_STATE_OK) 
    {
        // trace
        tb_trace_e("clos: failed: %s", tb_state_cstr(state));

        // done func
        tb_async_transfer_clos_func(impl, state);
    }
}
예제 #26
0
파일: pcre2.c 프로젝트: waruqi/tbox
tb_char_t const* tb_regex_replace(tb_regex_ref_t self, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_char_t const* replace_cstr, tb_size_t replace_size, tb_size_t* plength)
{
    // check
    tb_regex_t* regex = (tb_regex_t*)self;
    tb_assert_and_check_return_val(regex && regex->code && cstr && replace_cstr, tb_null);

    // done
    tb_char_t const* result = tb_null;
    do
    {
        // clear length first
        if (plength) *plength = 0;

        // end?
        tb_check_break(start < size);

        // init options
#ifdef __tb_debug__
        tb_uint32_t options = 0;
#else
        tb_uint32_t options = PCRE2_NO_UTF_CHECK;
#endif
        if (regex->mode & TB_REGEX_MODE_GLOBAL) options |= PCRE2_SUBSTITUTE_GLOBAL;

        // init buffer
        if (!regex->buffer_data)
        {
            regex->buffer_maxn = tb_max(size + replace_size + 64, 256);
            regex->buffer_data = (PCRE2_UCHAR*)tb_malloc_bytes(regex->buffer_maxn);
        }
        tb_assert_and_check_break(regex->buffer_data);

        // done
        tb_long_t   ok = -1;
        PCRE2_SIZE  length = 0;
        while (1)
        {
            // replace it
            length = (PCRE2_SIZE)regex->buffer_maxn;
            ok = pcre2_substitute(regex->code, (PCRE2_SPTR)cstr, (PCRE2_SIZE)size, (PCRE2_SIZE)start, options, tb_null, tb_null, (PCRE2_SPTR)replace_cstr, (PCRE2_SIZE)replace_size, regex->buffer_data, &length);

            // no space?
            if (ok == PCRE2_ERROR_NOMEMORY)
            {
                // grow buffer
                regex->buffer_maxn <<= 1;
                regex->buffer_data = (PCRE2_UCHAR*)tb_ralloc_bytes(regex->buffer_data, regex->buffer_maxn);
                tb_assert_and_check_break(regex->buffer_data);
            }
            // failed
            else if (ok < 0)
            {
#if defined(__tb_debug__) && !defined(TB_CONFIG_OS_WINDOWS)
                // get error info
                PCRE2_UCHAR info[256];
                pcre2_get_error_message(ok, info, sizeof(info));

                // trace
                tb_trace_d("replace failed at offset %lu: error: %ld, %s\n", start, ok, info);
#endif

                // end
                break;
            }
            else break;
        }

        // check
        tb_check_break(ok > 0);
        tb_assert_and_check_break(length < regex->buffer_maxn);

        // end
        regex->buffer_data[length] = '\0';

        // trace
        tb_trace_d("    replace: [%lu]: %s", length, regex->buffer_data);

        // save length 
        if (plength) *plength = (tb_size_t)length;

        // ok
        result = (tb_char_t const*)regex->buffer_data;

    } while (0);

    // ok?
    return result;
}
예제 #27
0
파일: pcre2.c 프로젝트: waruqi/tbox
tb_long_t tb_regex_match(tb_regex_ref_t self, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_size_t* plength, tb_vector_ref_t* presults)
{
    // check
    tb_regex_t* regex = (tb_regex_t*)self;
    tb_assert_and_check_return_val(regex && regex->code && regex->match_data && cstr, -1);

    // done
    tb_long_t ok = -1;
    do
    {
        // clear length first
        if (plength) *plength = 0;

        // end?
        tb_check_break(start < size);

        // init options
#ifdef __tb_debug__
        tb_uint32_t options = 0;
#else
        tb_uint32_t options = PCRE2_NO_UTF_CHECK;
#endif

        // match it
        tb_long_t count = pcre2_match(regex->code, (PCRE2_SPTR)cstr, (PCRE2_SIZE)size, (PCRE2_SIZE)start, options, regex->match_data, tb_null);
        if (count < 0)
        {
            // no match?
            tb_check_break(count != PCRE2_ERROR_NOMATCH);

#if defined(__tb_debug__) && !defined(TB_CONFIG_OS_WINDOWS)
            // get error info
            PCRE2_UCHAR info[256];
            pcre2_get_error_message(count, info, sizeof(info));

            // trace
            tb_trace_d("match failed at offset %lu: error: %ld, %s\n", start, count, info);
#endif

            // end
            break;
        }

        // check
        tb_assertf_and_check_break(count, "ovector has not enough space!");

        // get output vector
        PCRE2_SIZE* ovector = pcre2_get_ovector_pointer(regex->match_data);
        tb_assert_and_check_break(ovector);

        // get the match offset and length
        tb_size_t offset = (tb_size_t)ovector[0];
        tb_size_t length = (tb_size_t)ovector[1] - ovector[0];
        tb_assert_and_check_break(offset + length <= size);

        // trace
        tb_trace_d("matched count: %lu, offset: %lu, length: %lu", count, offset, length);

        // save results
        if (presults)
        {
            // init results if not exists
            tb_vector_ref_t results = *presults;
            if (!results)
            {
                // init it
                if (!regex->results) regex->results = tb_vector_init(16, tb_element_mem(sizeof(tb_regex_match_t), tb_regex_match_exit, tb_null));

                // save it
                *presults = results = regex->results;
            }
            tb_assert_and_check_break(results);

            // clear it first
            tb_vector_clear(results);

            // done
            tb_long_t           i = 0;
            tb_regex_match_t    entry;
            for (i = 0; i < count; i++)
            {
                // get substring offset and length
                tb_size_t substr_offset = ovector[i << 1];
                tb_size_t substr_length = ovector[(i << 1) + 1] - ovector[i << 1];
                tb_assert_and_check_break(substr_offset + substr_length <= size);

                // make match entry
                entry.cstr  = tb_strndup(cstr + substr_offset, substr_length);
                entry.size  = substr_length;
                entry.start = substr_offset;
                tb_assert_and_check_break(entry.cstr);
                
                // trace
                tb_trace_d("    matched: [%lu, %lu]: %s", entry.start, entry.size, entry.cstr);

                // append it
                tb_vector_insert_tail(results, &entry);
            }
            tb_assert_and_check_break(i == count);
        }

        // save length 
        if (plength) *plength = length;

        // ok
        ok = offset;

    } while (0);

    // ok?
    return ok;
}
예제 #28
0
파일: json.c 프로젝트: luxuan/tbox
static tb_object_ref_t tb_object_json_reader_func_number(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 number = tb_null;
    do
    {
        // append character
        tb_static_string_chrcat(&data, type);

        // walk
        tb_bool_t bs = (type == '-')? tb_true : tb_false;
        tb_bool_t bf = (type == '.')? tb_true : tb_false;
        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;

            // is float?
            if (!bf && ch == '.') bf = tb_true;
            else if (bf && ch == '.') 
            {
                failed = tb_true;
                break;
            }

            // append character
            if (tb_isdigit10(ch) || ch == '.' || ch == 'e' || ch == 'E' || ch == '-' || 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("number: %s", tb_static_string_cstr(&data));

        // init number 
#ifdef TB_CONFIG_TYPE_FLOAT
        if (bf) number = tb_object_number_init_from_float(tb_stof(tb_static_string_cstr(&data)));
#else
        if (bf) tb_trace_noimpl();
#endif
        else if (bs) 
        {
            tb_sint64_t value = tb_stoi64(tb_static_string_cstr(&data));
            tb_size_t   bytes = tb_object_need_bytes(-value);
            switch (bytes)
            {
            case 1: number = tb_object_number_init_from_sint8((tb_sint8_t)value); break;
            case 2: number = tb_object_number_init_from_sint16((tb_sint16_t)value); break;
            case 4: number = tb_object_number_init_from_sint32((tb_sint32_t)value); break;
            case 8: number = tb_object_number_init_from_sint64((tb_sint64_t)value); break;
            default: break;
            }
            
        }
        else 
        {
            tb_uint64_t value = tb_stou64(tb_static_string_cstr(&data));
            tb_size_t   bytes = tb_object_need_bytes(value);
            switch (bytes)
            {
            case 1: number = tb_object_number_init_from_uint8((tb_uint8_t)value); break;
            case 2: number = tb_object_number_init_from_uint16((tb_uint16_t)value); break;
            case 4: number = tb_object_number_init_from_uint32((tb_uint32_t)value); break;
            case 8: number = tb_object_number_init_from_uint64((tb_uint64_t)value); break;
            default: break;
            }
        }

    } while (0);

    // exit data
    tb_static_string_exit(&data);

    // ok?
    return number;
}
예제 #29
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * implementation
 */
tb_database_sql_ref_t tb_database_sql_init(tb_char_t const* url)
{
    // check
    tb_assert_and_check_return_val(url, tb_null);

    // done
    tb_bool_t                   ok = tb_false;
    tb_database_sql_ref_t       database = tb_null;
    tb_url_t                    database_url;
    do
    {
        // trace
        tb_trace_d("init: %s: ..", url);

        // init url
        if (!tb_url_init(&database_url)) break;

        // make url
        if (!tb_url_cstr_set(&database_url, url)) break;

        // check protocol
        tb_size_t protocol = tb_url_protocol(&database_url);
        tb_assert_and_check_break(protocol == TB_URL_PROTOCOL_SQL || protocol == TB_URL_PROTOCOL_FILE);

        // the probe func
        static tb_size_t (*s_probe[])(tb_url_ref_t) = 
        {
            tb_null
#ifdef TB_CONFIG_PACKAGE_HAVE_MYSQL
        ,   tb_database_mysql_probe
#endif
#ifdef TB_CONFIG_PACKAGE_HAVE_SQLITE3
        ,   tb_database_sqlite3_probe
#endif
        };

        // the init func
        static tb_database_sql_ref_t (*s_init[])(tb_url_ref_t) = 
        {
            tb_null
#ifdef TB_CONFIG_PACKAGE_HAVE_MYSQL
        ,   tb_database_mysql_init
#endif
#ifdef TB_CONFIG_PACKAGE_HAVE_SQLITE3
        ,   tb_database_sqlite3_init
#endif
        };

        // probe the database type
        tb_size_t i = 1;
        tb_size_t n = tb_arrayn(s_probe);
        tb_size_t s = 0;
        tb_size_t m = 0;
        for (; i < n; i++)
        {
            if (s_probe[i]) 
            {
                // probe it
                tb_size_t score = s_probe[i](&database_url);
                if (score > s) 
                {
                    // save the max score
                    s = score;
                    m = i;

                    // ok?
                    if (score == 100) break;
                }
            }
        }
        tb_check_break(m < n && s_init[m]);

        // init it
        database = s_init[m](&database_url);
        tb_assert_and_check_break(database);

        // trace
        tb_trace_d("init: %s: ok", url);

        // ok
        ok = tb_true;

    } while (0);

    // exit url
    tb_url_exit(&database_url);

    // failed?
    if (!ok)
    {
        // trace
        tb_trace_d("init: %s: no", url);

        // exit database
        if (database) tb_database_sql_exit(database);
        database = tb_null;
    }

    // ok?
    return database;
}
예제 #30
0
파일: file.c 프로젝트: ljx0305/tbox
tb_bool_t tb_file_copy(tb_char_t const* path, tb_char_t const* dest)
{
    // check
    tb_assert_and_check_return_val(path && dest, tb_false);

#ifdef TB_CONFIG_POSIX_HAVE_COPYFILE

    // the full path
    tb_char_t full0[TB_PATH_MAXN];
    path = tb_path_absolute(path, full0, TB_PATH_MAXN);
    tb_assert_and_check_return_val(path, tb_false);

    // the dest path
    tb_char_t full1[TB_PATH_MAXN];
    dest = tb_path_absolute(dest, full1, TB_PATH_MAXN);
    tb_assert_and_check_return_val(dest, tb_false);

    // attempt to copy it directly
    if (!copyfile(path, dest, 0, COPYFILE_ALL)) return tb_true;
    else
    {
        // attempt to copy it again after creating directory
        tb_char_t dir[TB_PATH_MAXN];
        if (tb_directory_create(tb_path_directory(dest, dir, sizeof(dir))))
            return !copyfile(path, dest, 0, COPYFILE_ALL);
    }

    // failed
    return tb_false;
#else
    tb_int_t    ifd = -1;
    tb_int_t    ofd = -1;
    tb_bool_t   ok = tb_false;
    do
    {
        // get the absolute source path
        tb_char_t data[8192];
        path = tb_path_absolute(path, data, sizeof(data));
        tb_assert_and_check_break(path);

        // get stat.st_mode first
#ifdef TB_CONFIG_POSIX_HAVE_STAT64
        struct stat64 st = {0};
        if (stat64(path, &st)) break;
#else
        struct stat st = {0};
        if (stat(path, &st)) break;
#endif

        // open source file
        ifd = open(path, O_RDONLY);
        tb_check_break(ifd >= 0);

        // get the absolute source path
        dest = tb_path_absolute(dest, data, sizeof(data));
        tb_assert_and_check_break(dest);

        // open destinate file and copy file mode
        ofd = open(dest, O_RDWR | O_CREAT | O_TRUNC, st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO));
        if (ofd < 0)
        {
            // attempt to open it again after creating directory
            tb_char_t dir[TB_PATH_MAXN];
            if (tb_directory_create(tb_path_directory(dest, dir, sizeof(dir))))
                ofd = open(dest, O_RDWR | O_CREAT | O_TRUNC, st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO));
        }
        tb_check_break(ofd >= 0);

        // get file size
        tb_hize_t size = tb_file_size(tb_fd2file(ifd));

        // init write size
        tb_hize_t writ = 0; 
       
        // attempt to copy file using `sendfile`
#ifdef TB_CONFIG_POSIX_HAVE_SENDFILE
        while (writ < size)
        {
            off_t seek = writ;
            tb_hong_t real = sendfile(ofd, ifd, &seek, (size_t)(size - writ));
            if (real > 0) writ += real;
            else break;
        }

        /* attempt to copy file directly if sendfile failed 
         *
         * sendfile() supports regular file only after "since Linux 2.6.33".
         */
        if (writ != size) 
        {
            lseek(ifd, 0, SEEK_SET);
            lseek(ofd, 0, SEEK_SET);
        }
        else
        {
            ok = tb_true;
            break;
        }
#endif

        // copy file using `read` and `write`
        writ = 0;
        while (writ < size)
        {
            // read some data
            tb_int_t real = read(ifd, data, (size_t)tb_min(size - writ, sizeof(data)));
            if (real > 0)
            {
                real = write(ofd, data, real);
                if (real > 0) writ += real;
                else break;
            }
            else break;
        }

        // ok?
        ok = (writ == size);

    } while (0);

    // close source file
    if (ifd >= 0) close(ifd);
    ifd = -1;

    // close destinate file
    if (ofd >= 0) close(ofd);
    ofd = -1;

    // ok?
    return ok;
#endif
}