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; }