Commit b3bc81de authored by Frederick Zhang's avatar Frederick Zhang

search function

parent 0c22db58
......@@ -301,3 +301,46 @@ zval * bdict::to_array(const bool include_meta) const {
}
return zv;
}
zval * bdict::search(const std::string &needle, const std::string &mode, const std::string path) const {
bool modek = (mode.find('k') == std::string::npos) ? false : true;
bool modev = (mode.find('v') == std::string::npos) ? false : true;
if (!(modek || modev))
bitem::throw_general_exception("Illegal search mode");
zval _zv;
zval *zv = &_zv;
array_init(zv);
for(zend_hash_internal_pointer_reset(_data);
zend_hash_has_more_elements(_data) == SUCCESS;
zend_hash_move_forward(_data)) {
zend_string *str_index;
zend_ulong num_index;
zend_hash_get_current_key(_data, &str_index, &num_index);
zval *value = zend_hash_get_current_data(_data);
std::string class_name = zend_container::bnode_object_get_class_name(value);
std::string _str_index(ZSTR_VAL(str_index));
if (modek && _str_index.find(needle) != std::string::npos) {
add_next_index_string(zv, (path + "/" + bitem::escape_key(_str_index)).c_str());
continue;
}
if (class_name == "bdict") {
zval *next_result = (zend_container::bdict_fetch_object(Z_OBJ_P(value)))->bdict_data->search(needle, mode, path);
zend_hash_merge(Z_ARRVAL_P(zv), Z_ARRVAL_P(next_result), (copy_ctor_func_t) zval_add_ref, false);
} else if (class_name == "blist") {
zval *next_result = (zend_container::blist_fetch_object(Z_OBJ_P(value)))->blist_data->search(needle, mode, path);
zend_hash_merge(Z_ARRVAL_P(zv), Z_ARRVAL_P(next_result), (copy_ctor_func_t) zval_add_ref, false);
} else if (modev && class_name == "bstr") {
if ((zend_container::bstr_fetch_object(Z_OBJ_P(value)))->bstr_data->_value.find(needle) != std::string::npos)
add_next_index_string(zv, (path + "/" + bitem::escape_key(_str_index)).c_str());
} else if (modev && class_name == "bint") {
if ((zend_container::bint_fetch_object(Z_OBJ_P(value)))->bint_data->_value == std::stoll(needle))
add_next_index_string(zv, (path + "/" + bitem::escape_key(_str_index)).c_str());
}
}
return zv;
}
......@@ -31,6 +31,7 @@ class bdict : public bitem {
static zval * parse(const std::string &ben, size_t &pt);
std::string encode() const;
zval * to_array(const bool include_meta) const;
zval * search(const std::string &needle, const std::string &mode, const std::string path) const;
};
#endif
......@@ -67,3 +67,7 @@ zval * bint::to_array(const bool include_meta) const {
}
return zv;
}
zval * bint::search(const std::string &needle, const std::string &mode, const std::string path) const {
return nullptr;
}
......@@ -28,6 +28,7 @@ class bint : public bitem {
static zval * parse(const std::string &ben, size_t &pt);
std::string encode() const;
zval * to_array(const bool include_meta) const;
zval * search(const std::string &needle, const std::string &mode, const std::string path) const;
};
#endif
......@@ -31,6 +31,22 @@ std::string bitem::get_current_key(const std::string &path, size_t &pt) {
return current_key;
}
std::string bitem::escape_key(const std::string &key) {
std::string result = "";
size_t pt = 0;
size_t to_esc = std::min(key.find('/', pt), key.find('\\', pt));
while (to_esc < key.length()) {
result += key.substr(pt, to_esc - pt);
if (key[to_esc] == '/')
result += "\\/";
else if (key[to_esc] == '\\')
result += "\\\\";
pt = to_esc + 1;
to_esc = std::min(key.find('/', pt), key.find('\\', pt));
}
return result;
}
bool bitem::is_ull(const std::string &s) {
if(s.empty() || !isdigit(s[0])) return false;
char *p;
......
......@@ -15,6 +15,7 @@ class bitem {
static zval * throw_general_exception(const std::string message);
static zval * get_zval_bool(const bool value);
static std::string get_current_key(const std::string &path, size_t &pt);
static std::string escape_key(const std::string &key);
static bool is_ull(const std::string &s);
public:
......@@ -27,6 +28,7 @@ class bitem {
virtual std::string encode() const = 0;
static zval * load(const std::string &file_path);
void save(const std::string &file_path) const;
virtual zval * search(const std::string &needle, const std::string &mode, const std::string path) const = 0;
};
#endif
......@@ -322,3 +322,41 @@ zval * blist::to_array(const bool include_meta) const {
}
return zv;
}
zval * blist::search(const std::string &needle, const std::string &mode, const std::string path) const {
bool modek = (mode.find('k') == std::string::npos) ? false : true;
bool modev = (mode.find('v') == std::string::npos) ? false : true;
if (!(modek || modev))
bitem::throw_general_exception("Illegal search mode");
zval _zv;
zval *zv = &_zv;
array_init(zv);
for(zend_hash_internal_pointer_reset(_data);
zend_hash_has_more_elements(_data) == SUCCESS;
zend_hash_move_forward(_data)) {
zend_string *str_index;
zend_ulong num_index;
zend_hash_get_current_key(_data, &str_index, &num_index);
zval *value = zend_hash_get_current_data(_data);
std::string class_name = zend_container::bnode_object_get_class_name(value);
std::string _str_index(ZSTR_VAL(str_index));
if (class_name == "bdict") {
zval *next_result = (zend_container::bdict_fetch_object(Z_OBJ_P(value)))->bdict_data->search(needle, mode, path);
zend_hash_merge(Z_ARRVAL_P(zv), Z_ARRVAL_P(next_result), (copy_ctor_func_t) zval_add_ref, false);
} else if (class_name == "blist") {
zval *next_result = (zend_container::blist_fetch_object(Z_OBJ_P(value)))->blist_data->search(needle, mode, path);
zend_hash_merge(Z_ARRVAL_P(zv), Z_ARRVAL_P(next_result), (copy_ctor_func_t) zval_add_ref, false);
} else if (modev && class_name == "bstr") {
if ((zend_container::bstr_fetch_object(Z_OBJ_P(value)))->bstr_data->_value.find(needle) != std::string::npos)
add_next_index_string(zv, (path + "/" + std::to_string(num_index)).c_str());
} else if (modev && class_name == "bint") {
if ((zend_container::bint_fetch_object(Z_OBJ_P(value)))->bint_data->_value == std::stoll(needle))
add_next_index_string(zv, (path + "/" + std::to_string(num_index)).c_str());
}
}
return zv;
}
......@@ -32,6 +32,7 @@ class blist : public bitem {
static zval * parse(const std::string &ben, size_t &pt);
std::string encode() const;
zval * to_array(const bool include_meta) const;
zval * search(const std::string &needle, const std::string &mode, const std::string path) const;
};
#endif
......@@ -71,3 +71,7 @@ zval * bstr::to_array(const bool include_meta) const {
}
return zv;
}
zval * bstr::search(const std::string &needle, const std::string &mode, const std::string path) const {
return nullptr;
}
......@@ -28,6 +28,7 @@ class bstr : public bitem {
static zval * parse(const std::string &ben, size_t &pt);
std::string encode() const;
zval * to_array(const bool include_meta) const;
zval * search(const std::string &needle, const std::string &mode, const std::string path) const;
};
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment