Commit 73fc806e authored by Frederick Zhang's avatar Frederick Zhang

get_path support

parent 2b105a46
......@@ -83,6 +83,40 @@ bool bdict::del(const std::string &key) {
}
}
zval * bdict::get_path(const std::string &key, size_t &pt) const {
size_t start = pt;
while (!(key[pt] == '/' && key[pt - 1] != '\\') && pt < key.length()) ++pt;
std::string current_key = key.substr(start, pt - start);
++pt;
size_t escape = current_key.find("\\/");
while (escape >= 0 && escape < current_key.length()) {
current_key.replace(escape, 2, "/");
escape = current_key.find("\\/");
}
if (!zend_hash_str_exists(_data, current_key.c_str(), current_key.length())) {
zval _zv;
zval *zv = &_zv;
ZVAL_BOOL(zv, 0);
return zv;
}
if (pt >= key.length()) {
return zend_hash_str_find(_data, current_key.c_str(), current_key.length());
} else {
zval *subnode = zend_hash_str_find(_data, current_key.c_str(), current_key.length());
std::string class_name = zend_container::bnode_object_get_class_name(subnode);
if (class_name == "bdict") {
return zend_container::bdict_fetch_object(Z_OBJ_P(subnode))->bdict_data->get_path(key, pt);
} else if (class_name == "blist") {
return zend_container::blist_fetch_object(Z_OBJ_P(subnode))->blist_data->get_path(key, pt);
} else {
zval _zv;
zval *zv = &_zv;
ZVAL_BOOL(zv, 0);
return zv;
}
}
}
size_t bdict::length() const {
return (encode().length() / sizeof(char));
}
......@@ -93,10 +127,7 @@ size_t bdict::count() const {
zval * bdict::parse(const std::string &ben, size_t &pt) {
if (ben[pt] != 'd')
zend_throw_exception(
zend_container::bdict_ce,
"Error parsing bdict",
1);
return bitem::throw_general_exception("Error parsing bdict");
zval _zv;
zval *zv = &_zv;
object_init_ex(zv, zend_container::bdict_ce);
......@@ -124,10 +155,7 @@ zval * bdict::parse(const std::string &ben, size_t &pt) {
zval bnode = *bint::parse(ben, pt);
zend_hash_str_add(intern->bdict_data->_data, key.c_str(), key.length(), &bnode);
} else {
zend_throw_exception(
zend_container::bdict_ce,
"Error parsing bdict",
1);
return bitem::throw_general_exception("Error parsing bdict");
}
}
++pt;
......@@ -146,7 +174,7 @@ std::string bdict::encode() const {
std::string class_name = zend_container::bnode_object_get_class_name(value);
std::string _str_index(ZSTR_VAL(str_index));
result += bitem::numtos(_str_index.length()) + ":" + _str_index;
result += std::to_string(_str_index.length()) + ":" + _str_index;
if (class_name == "bdict") {
result += (zend_container::bdict_fetch_object(Z_OBJ_P(value)))->bdict_data->encode();
} else if (class_name == "blist") {
......
......@@ -22,6 +22,7 @@ class bdict : public bitem {
bool has(const std::string &key) const;
void set(const std::string &key, zval *value);
bool del(const std::string &key);
zval * get_path(const std::string &key, size_t &pt) const;
size_t length() const;
size_t count() const;
......
......@@ -93,6 +93,18 @@ PHP_METHOD(bdict, get)
std::string _key(key);
RETURN_ZVAL(intern->bdict_data->get(_key), 1, 0);
}
PHP_METHOD(bdict, get_path)
{
char *key;
size_t key_len = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len) == FAILURE) {
RETURN_NULL();
}
bdict_object *intern = Z_BDICT_OBJ_P(getThis());
std::string _key(key);
size_t pt = 0;
RETURN_ZVAL(intern->bdict_data->get_path(_key, pt), 1, 0);
}
PHP_METHOD(bdict, get_copy)
{
char *key;
......@@ -104,6 +116,18 @@ PHP_METHOD(bdict, get_copy)
std::string _key(key);
RETURN_OBJ(zend_container::bnode_object_clone(intern->bdict_data->get(_key)));
}
PHP_METHOD(bdict, get_path_copy)
{
char *key;
size_t key_len = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len) == FAILURE) {
RETURN_NULL();
}
bdict_object *intern = Z_BDICT_OBJ_P(getThis());
std::string _key(key);
size_t pt = 0;
RETURN_OBJ(zend_container::bnode_object_clone(intern->bdict_data->get_path(_key, pt)));
}
PHP_METHOD(bdict, set)
{
char *key;
......@@ -189,7 +213,9 @@ static zend_function_entry bdict_methods[] = {
PHP_ME(bdict, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
PHP_ME(bdict, get_type, NULL, ZEND_ACC_PUBLIC)
PHP_ME(bdict, get, NULL, ZEND_ACC_PUBLIC)
PHP_ME(bdict, get_path, NULL, ZEND_ACC_PUBLIC)
PHP_ME(bdict, get_copy, NULL, ZEND_ACC_PUBLIC)
PHP_ME(bdict, get_path_copy, NULL, ZEND_ACC_PUBLIC)
PHP_ME(bdict, set, NULL, ZEND_ACC_PUBLIC)
PHP_ME(bdict, has, NULL, ZEND_ACC_PUBLIC)
PHP_ME(bdict, del, NULL, ZEND_ACC_PUBLIC)
......@@ -231,6 +257,18 @@ PHP_METHOD(blist, get)
blist_object *intern = Z_BLIST_OBJ_P(getThis());
RETURN_ZVAL(intern->blist_data->get(key), 1, 0);
}
PHP_METHOD(blist, get_path)
{
char *key;
size_t key_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len) == FAILURE) {
RETURN_NULL();
}
blist_object *intern = Z_BLIST_OBJ_P(getThis());
std::string _key(key);
size_t pt = 0;
RETURN_ZVAL(intern->blist_data->get_path(_key, pt), 1, 0);
}
PHP_METHOD(blist, get_copy)
{
long key;
......@@ -243,6 +281,18 @@ PHP_METHOD(blist, get_copy)
blist_object *intern = Z_BLIST_OBJ_P(getThis());
RETURN_OBJ(zend_container::bnode_object_clone(intern->blist_data->get(key)));
}
PHP_METHOD(blist, get_path_copy)
{
char *key;
size_t key_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len) == FAILURE) {
RETURN_NULL();
}
blist_object *intern = Z_BLIST_OBJ_P(getThis());
std::string _key(key);
size_t pt = 0;
RETURN_OBJ(zend_container::bnode_object_clone(intern->blist_data->get_path(_key, pt)));
}
PHP_METHOD(blist, add)
{
zval *zv;
......@@ -338,7 +388,9 @@ static zend_function_entry blist_methods[] = {
PHP_ME(blist, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
PHP_ME(blist, get_type, NULL, ZEND_ACC_PUBLIC)
PHP_ME(blist, get, NULL, ZEND_ACC_PUBLIC)
PHP_ME(blist, get_path, NULL, ZEND_ACC_PUBLIC)
PHP_ME(blist, get_copy, NULL, ZEND_ACC_PUBLIC)
PHP_ME(blist, get_path_copy, NULL, ZEND_ACC_PUBLIC)
PHP_ME(blist, add, NULL, ZEND_ACC_PUBLIC)
PHP_ME(blist, set, NULL, ZEND_ACC_PUBLIC)
PHP_ME(blist, has, NULL, ZEND_ACC_PUBLIC)
......
......@@ -26,10 +26,7 @@ size_t bint::length() const {
zval * bint::parse(const std::string &ben, size_t &pt) {
if (ben[pt] != 'i')
zend_throw_exception(
zend_container::bint_ce,
"Error parsing bint",
1);
return bitem::throw_general_exception("Error parsing bint");
++pt;
std::string strint = "";
while (ben[pt] != 'e') strint += ben[pt++];
......@@ -45,7 +42,7 @@ zval * bint::parse(const std::string &ben, size_t &pt) {
}
std::string bint::encode() const {
return "i" + bitem::numtos(_value) + "e";
return "i" + std::to_string(_value) + "e";
}
zval * bint::to_array(const bool include_meta) const {
......
......@@ -6,6 +6,14 @@
#include "bint.h"
#include "zend_container.h"
zval * bitem::throw_general_exception(const std::string message) {
zend_throw_exception(NULL, message.c_str(), 1);
zval _zv;
zval *zv = &_zv;
ZVAL_BOOL(zv, 0);
return zv;
}
std::string bitem::get_type() const {
return "bitem";
}
......@@ -21,20 +29,14 @@ zval * bitem::parse(const std::string &ben) {
} else if (ben[0] == 'i') {
return bint::parse(ben, pt);
} else {
zend_throw_exception(
zend_container::bitem_ce,
"Error parsing bitem",
1);
return bitem::throw_general_exception("Error parsing bitem");
}
}
zval * bitem::load(const std::string &file_path) {
std::ifstream ben_file(file_path);
if (!ben_file.is_open()) {
zend_throw_exception(
zend_container::bitem_ce,
"Error opening file",
1);
return bitem::throw_general_exception("Error opening file");
}
std::string ben((std::istreambuf_iterator<char>(ben_file)),
(std::istreambuf_iterator<char>()));
......@@ -47,10 +49,8 @@ zval * bitem::load(const std::string &file_path) {
void bitem::save(const std::string &file_path) const {
std::ofstream ben_file(file_path);
if (!ben_file.is_open()) {
zend_throw_exception(
zend_container::bitem_ce,
"Error opening file",
1);
bitem::throw_general_exception("Error opening file");
return;
}
ben_file << encode();
ben_file.close();
......
......@@ -12,15 +12,7 @@ extern "C" {
class bitem {
protected:
template<typename T>
static std::string numtos(const T &value) {
std::string result;
std::stringstream ss;
ss << value;
ss >> result;
return result;
}
static zval * throw_general_exception(const std::string message);
public:
bitem() {}
bitem(const bitem *that) {}
......
......@@ -106,6 +106,48 @@ bool blist::del(const size_t &key) {
}
}
zval * blist::get_path(const std::string &key, size_t &pt) const {
size_t start = pt;
while (!(key[pt] == '/' && key[pt - 1] != '\\') && pt < key.length()) ++pt;
std::string current_key = key.substr(start, pt - start);
++pt;
size_t escape = current_key.find("\\/");
while (escape >= 0 && escape < current_key.length())
current_key.replace(escape, 2, "/");
size_t current_key_long;
try {
current_key_long = std::stoull(current_key);
} catch (int e) {
return bitem::throw_general_exception("Invalid key for blist, only positive integer is allowed");
}
if (std::to_string(current_key_long) != current_key) {
return bitem::throw_general_exception("Invalid key for blist, only positive integer is allowed");
}
if (!zend_hash_index_exists(_data, current_key_long)) {
zval _zv;
zval *zv = &_zv;
ZVAL_BOOL(zv, 0);
return zv;
}
if (pt >= key.length()) {
return zend_hash_index_find(_data, current_key_long);
} else {
zval *subnode = zend_hash_index_find(_data, current_key_long);
std::string class_name = zend_container::bnode_object_get_class_name(subnode);
if (class_name == "bdict") {
return zend_container::bdict_fetch_object(Z_OBJ_P(subnode))->bdict_data->get_path(key, pt);
} else if (class_name == "blist") {
return zend_container::blist_fetch_object(Z_OBJ_P(subnode))->blist_data->get_path(key, pt);
} else {
zval _zv;
zval *zv = &_zv;
ZVAL_BOOL(zv, 0);
return zv;
}
}
}
size_t blist::length() const {
return (encode().length() / sizeof(char));
}
......@@ -116,10 +158,7 @@ size_t blist::count() const {
zval * blist::parse(const std::string &ben, size_t &pt) {
if (ben[pt] != 'l')
zend_throw_exception(
zend_container::blist_ce,
"Error parsing blist",
1);
return bitem::throw_general_exception("Error parsing blist");
++pt;
zval _zv;
zval *zv = &_zv;
......@@ -141,10 +180,7 @@ zval * blist::parse(const std::string &ben, size_t &pt) {
zval bnode = *bint::parse(ben, pt);
zend_hash_next_index_insert(intern->blist_data->_data, &bnode);
} else {
zend_throw_exception(
zend_container::blist_ce,
"Error parsing blist",
1);
return bitem::throw_general_exception("Error parsing blist");
}
}
++pt;
......
......@@ -23,6 +23,7 @@ class blist : public bitem {
void add(zval *value);
void set(const size_t &key, zval *value);
bool del(const size_t &key);
zval * get_path(const std::string &key, size_t &pt) const;
size_t length() const;
size_t count() const;
......
......@@ -25,10 +25,7 @@ size_t bstr::length() const {
zval * bstr::parse(const std::string &ben, size_t &pt) {
if (ben[pt] < '0' || ben[pt] > '9')
zend_throw_exception(
zend_container::bstr_ce,
"Error parsing bstr",
1);
return bitem::throw_general_exception("Error parsing bstr");
const size_t start = pt;
while (ben[pt] >= '0' && ben[pt] <= '9') ++pt;
std::string len = ben.substr(start, pt - start);
......@@ -44,7 +41,7 @@ zval * bstr::parse(const std::string &ben, size_t &pt) {
}
std::string bstr::encode() const {
return bitem::numtos(_value.length()) + ":" + _value;
return std::to_string(_value.length()) + ":" + _value;
}
zval * bstr::to_array(const bool include_meta) const {
......
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