/* ////////////////////////////////////////////////////////////////////////////////////// * 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; }
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; }
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; }
static tb_object_ref_t tb_object_xplist_reader_func_dictionary(tb_object_xplist_reader_t* reader, tb_size_t event) { // check tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); // empty? if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) return tb_object_dictionary_init(TB_OBJECT_DICTIONARY_SIZE_MICRO, tb_false); // init key name tb_static_string_t kname; tb_char_t kdata[8192]; if (!tb_static_string_init(&kname, kdata, 8192)) return tb_null; // init dictionary tb_object_ref_t dictionary = tb_object_dictionary_init(0, tb_false); tb_assert_and_check_return_val(dictionary, tb_null); // done tb_long_t ok = 0; tb_bool_t key = tb_false; while (!ok && (event = tb_xml_reader_next(reader->reader))) { switch (event) { case TB_XML_READER_EVENT_ELEMENT_BEG: case TB_XML_READER_EVENT_ELEMENT_EMPTY: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, ok, -1); tb_trace_d("%s", name); // is key if (!tb_stricmp(name, "key")) key = tb_true; else if (!key) { // func tb_object_xplist_reader_func_t func = tb_object_xplist_reader_func(name); tb_assert_and_check_break_state(func, ok, -1); // read tb_object_ref_t object = func(reader, event); tb_trace_d("%s => %p", tb_static_string_cstr(&kname), object); tb_assert_and_check_break_state(object, ok, -1); // set key & value if (tb_static_string_size(&kname) && dictionary) tb_object_dictionary_insert(dictionary, tb_static_string_cstr(&kname), object); // clear key name tb_static_string_clear(&kname); } } break; case TB_XML_READER_EVENT_ELEMENT_END: { // name tb_char_t const* name = tb_xml_reader_element(reader->reader); tb_assert_and_check_break_state(name, ok, -1); // is end? if (!tb_stricmp(name, "dict")) ok = 1; else if (!tb_stricmp(name, "key")) key = tb_false; } break; case TB_XML_READER_EVENT_TEXT: { if (key) { // text tb_char_t const* text = tb_xml_reader_text(reader->reader); tb_assert_and_check_break_state(text, ok, -1); // writ key name tb_static_string_cstrcpy(&kname, text); } } break; default: break; } } // failed if (ok < 0) { // exit it if (dictionary) tb_object_exit(dictionary); dictionary = tb_null; } // exit key name tb_static_string_exit(&kname); // ok? return dictionary; }
static tb_long_t tb_dns_looker_resp(tb_dns_looker_t* looker, tb_ipaddr_ref_t addr) { // check tb_check_return_val(!(looker->step & TB_DNS_LOOKER_STEP_RESP), 1); // need wait if no data looker->step &= ~TB_DNS_LOOKER_STEP_NEVT; // recv response data tb_size_t size = tb_static_buffer_size(&looker->rpkt); tb_size_t maxn = tb_static_buffer_maxn(&looker->rpkt); tb_byte_t* data = tb_static_buffer_data(&looker->rpkt); while (size < maxn) { // read data tb_long_t read = tb_socket_urecv(looker->sock, tb_null, data + size, maxn - size); 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(&looker->rpkt)); // abort? read 0, read 0 tb_check_return_val(!looker->tryn, -1); // tryn++ looker->tryn++; // continue return 0; } else looker->tryn = 0; // update buffer size tb_static_buffer_resize(&looker->rpkt, size + read); size = tb_static_buffer_size(&looker->rpkt); } // done if (!tb_dns_looker_resp_done(looker, addr)) return -1; // check tb_assert_and_check_return_val(tb_static_string_size(&looker->name) && !tb_ipaddr_ip_is_empty(addr), -1); // save address to cache tb_dns_cache_set(tb_static_string_cstr(&looker->name), addr); // finish it looker->step |= TB_DNS_LOOKER_STEP_RESP; looker->tryn = 0; // reset rpkt looker->size = 0; tb_static_buffer_clear(&looker->rpkt); // ok tb_trace_d("response: ok"); return 1; }
tb_bool_t tb_xml_reader_goto(tb_xml_reader_ref_t reader, tb_char_t const* path) { // check tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader; tb_assert_and_check_return_val(impl && impl->rstream && path, tb_false); tb_trace_d("goto: %s", path); // init level impl->level = 0; // seek to the stream head if (!tb_stream_seek(impl->rstream, 0)) return tb_false; // init tb_static_string_t s; tb_char_t data[8192]; if (!tb_static_string_init(&s, data, 8192)) return tb_false; // save the current offset tb_hize_t save = tb_stream_offset(impl->rstream); // done tb_bool_t ok = tb_false; tb_bool_t leave = tb_false; tb_size_t event = TB_XML_READER_EVENT_NONE; while (!leave && !ok && (event = tb_xml_reader_next(reader))) { switch (event) { case TB_XML_READER_EVENT_ELEMENT_EMPTY: { // name tb_char_t const* name = tb_xml_reader_element(reader); tb_assert_and_check_break_state(name, leave, tb_true); // append tb_size_t n = tb_static_string_size(&s); tb_static_string_chrcat(&s, '/'); tb_static_string_cstrcat(&s, name); // ok? if (!tb_static_string_cstricmp(&s, path)) ok = tb_true; tb_trace_d("path: %s", tb_static_string_cstr(&s)); // remove tb_static_string_strip(&s, n); // restore if (ok) if (!(ok = tb_stream_seek(impl->rstream, save))) leave = tb_true; } break; case TB_XML_READER_EVENT_ELEMENT_BEG: { // name tb_char_t const* name = tb_xml_reader_element(reader); tb_assert_and_check_break_state(name, leave, tb_true); // append tb_static_string_chrcat(&s, '/'); tb_static_string_cstrcat(&s, name); // ok? if (!tb_static_string_cstricmp(&s, path)) ok = tb_true; tb_trace_d("path: %s", tb_static_string_cstr(&s)); // restore if (ok) if (!(ok = tb_stream_seek(impl->rstream, save))) leave = tb_true; } break; case TB_XML_READER_EVENT_ELEMENT_END: { // remove tb_long_t p = tb_static_string_strrchr(&s, 0, '/'); if (p >= 0) tb_static_string_strip(&s, p); // ok? if (!tb_static_string_cstricmp(&s, path)) ok = tb_true; tb_trace_d("path: %s", tb_static_string_cstr(&s)); // restore if (ok) if (!(ok = tb_stream_seek(impl->rstream, save))) leave = tb_true; } break; default: break; } // save save = tb_stream_offset(impl->rstream); } // exit string tb_static_string_exit(&s); // clear level impl->level = 0; // failed? restore to the stream head if (!ok) tb_stream_seek(impl->rstream, 0); // ok? return ok; }