static __tb_inline__ tb_bool_t tb_option_is_float(tb_char_t const* data) { // check tb_assert_and_check_return_val(data, tb_false); // init tb_char_t const* p = data; // walk for (; *p && (tb_isdigit10(*p) || *p == '.'); p++); // ok? return *p? tb_false : tb_true; }
tb_bool_t tb_ipv4_cstr_set(tb_ipv4_ref_t ipv4, tb_char_t const* cstr) { // check tb_assert_and_check_return_val(cstr, tb_false); // done tb_uint32_t r = 0; tb_uint32_t v = 0; tb_char_t c = '\0'; tb_size_t i = 0; tb_char_t const* p = cstr; do { // the character c = *p++; // digit? if (tb_isdigit10(c) && v <= 0xff) { v *= 10; v += (tb_uint32_t)(c - '0') & 0xff; } // '.' or '\0'? else if ((c == '.' || !c) && v <= 0xff) { r |= ((tb_uint32_t)v) << ((i++) << 3); v = 0; } // failed? else { // trace tb_trace_d("invalid ipv4 addr: %s", cstr); // clear it i = 0; break; } } while (c); // save it if ok if (ipv4) ipv4->u32 = r; // ok? return i == 4; }
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; }
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; }
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; }
tb_bool_t tb_hwaddr_cstr_set(tb_hwaddr_ref_t hwaddr, tb_char_t const* cstr) { // check tb_assert_and_check_return_val(cstr, tb_false); // done tb_uint32_t v = 0; tb_char_t c = '\0'; tb_size_t i = 0; tb_char_t const* p = cstr; tb_bool_t ok = tb_true; tb_hwaddr_t temp; do { // the character c = *p++; // digit? if (tb_isdigit16(c) && v <= 0xff) { // update value if (tb_isdigit10(c)) v = (v << 4) + (c - '0'); else if (c > ('a' - 1) && c < ('f' + 1)) v = (v << 4) + (c - 'a') + 10; else if (c > ('A' - 1) && c < ('F' + 1)) v = (v << 4) + (c - 'A') + 10; else { // abort tb_assert(0); // failed ok = tb_false; break; } } // ':' or "-" or '\0'? else if (i < 6 && (c == ':' || c == '-' || !c) && v <= 0xff) { // save value temp.u8[i++] = v; // clear value v = 0; } // failed? else { ok = tb_false; break; } } while (c); // failed if (i != 6) ok = tb_false; // save it if ok if (ok && hwaddr) *hwaddr = temp; // trace // tb_assertf(ok, "invalid hwaddr: %s", cstr); // ok? return ok; }
tb_object_ref_t tb_object_seek(tb_object_ref_t object, tb_char_t const* path, tb_size_t type) { // check tb_assert_and_check_return_val(object, tb_null); // null? tb_check_return_val(path, object); // walk tb_char_t const* p = path; tb_char_t const* e = path + tb_strlen(path); while (p < e && object) { // done seek switch (*p) { case '.': { // check tb_assert_and_check_return_val(tb_object_type(object) == TB_OBJECT_TYPE_DICTIONARY, tb_null); // skip p++; // read the key name tb_char_t key[4096] = {0}; tb_char_t* kb = key; tb_char_t* ke = key + 4095; for (; p < e && kb < ke && *p && (*p != '.' && *p != '[' && *p != ']'); p++, kb++) { if (*p == '\\') p++; *kb = *p; } // trace tb_trace_d("key: %s", key); // the value object = tb_object_dictionary_val(object, key); } break; case '[': { // check tb_assert_and_check_return_val(tb_object_type(object) == TB_OBJECT_TYPE_ARRAY, tb_null); // skip p++; // read the item index tb_char_t index[32] = {0}; tb_char_t* ib = index; tb_char_t* ie = index + 31; for (; p < e && ib < ie && *p && tb_isdigit10(*p); p++, ib++) *ib = *p; // trace tb_trace_d("index: %s", index); // check tb_size_t i = tb_atoi(index); tb_assert_and_check_return_val(i < tb_object_array_size(object), tb_null); // the value object = tb_object_array_item(object, i); } break; case ']': default: p++; break; } } // check it, if not none if (object && type != TB_OBJECT_TYPE_NONE) { // is this type? if (tb_object_type(object) != type) return tb_null; } // ok? return object; }
tb_object_ref_t tb_object_seek(tb_object_ref_t object, tb_char_t const* path, tb_bool_t bmacro) { // check tb_assert_and_check_return_val(object, tb_null); // null? tb_check_return_val(path, object); // done tb_object_ref_t root = object; tb_char_t const* p = path; tb_char_t const* e = path + tb_strlen(path); while (p < e && object) { // done seek switch (*p) { case '.': { // check tb_assert_and_check_return_val(tb_object_type(object) == TB_OBJECT_TYPE_DICTIONARY, tb_null); // skip p++; // read the key name tb_char_t key[4096] = {0}; tb_char_t* kb = key; tb_char_t* ke = key + 4095; for (; p < e && kb < ke && *p && (*p != '.' && *p != '[' && *p != ']'); p++, kb++) { if (*p == '\\') p++; *kb = *p; } // trace tb_trace_d("key: %s", key); // the value object = tb_object_dictionary_value(object, key); } break; case '[': { // check tb_assert_and_check_return_val(tb_object_type(object) == TB_OBJECT_TYPE_ARRAY, tb_null); // skip p++; // read the item index tb_char_t index[32] = {0}; tb_char_t* ib = index; tb_char_t* ie = index + 31; for (; p < e && ib < ie && *p && tb_isdigit10(*p); p++, ib++) *ib = *p; // trace tb_trace_d("index: %s", index); // check tb_size_t i = tb_atoi(index); tb_assert_and_check_return_val(i < tb_object_array_size(object), tb_null); // the value object = tb_object_array_item(object, i); } break; case ']': default: p++; break; } // is macro? done it if be enabled if ( object && bmacro && tb_object_type(object) == TB_OBJECT_TYPE_STRING && tb_object_string_size(object) && tb_object_string_cstr(object)[0] == '$') { // the next path path = tb_object_string_cstr(object) + 1; // continue to seek it object = tb_object_seek(root, path, bmacro); } } // ok? return object; }
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)); }