From a27ad479f151c10a9568e0dc676c011fd24cb358 Mon Sep 17 00:00:00 2001 From: andot Date: Thu, 10 Jul 2014 19:24:53 +0800 Subject: [PATCH 1/3] Add properties method for Php::Value This method can get property names. When the only_public argument is false, we can get all properties. and the private & protected property names are also the normal names, no such prefix `\0XXX\0`. This is the different place with the `keys` method. --- include/value.h | 7 +++++++ zend/value.cpp | 53 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/include/value.h b/include/value.h index f72304cf..520b585d 100644 --- a/include/value.h +++ b/include/value.h @@ -507,6 +507,13 @@ class Value : private HashParent return result; } + /** + * Get object property names. + * @param only_public + * @return std::vector + */ + std::vector properties(bool only_public = true) const; + /** * Define the iterator type */ diff --git a/zend/value.cpp b/zend/value.cpp index 9a1a5dbb..0c2e50f6 100644 --- a/zend/value.cpp +++ b/zend/value.cpp @@ -1618,6 +1618,59 @@ std::map Value::mapValue() const return result; } +/** + * Get object property names. + * @param only_public + * @return std::vector + */ +std::vector Value::properties(bool only_public) const { + if (isObject()) { + std::vector result; + + // we need the TSRMLS_CC variable + TSRMLS_FETCH(); + + HashTable *table = Z_OBJPROP_P(_val); + Bucket *position = nullptr; + + // move to first position + zend_hash_internal_pointer_reset_ex(table, &position); + + do { + char *string_key; + unsigned int str_len; + unsigned long num_key; + + // get the current key + int type = zend_hash_get_current_key_ex(table, &string_key, &str_len, &num_key, 0, &position); + + // if key is not found, the iterator is at an invalid position + if (type == HASH_KEY_NON_EXISTANT) continue; + + // if only_public is true, only store public property + if (only_public) { + if (string_key[0] == '\0') continue; + result.push_back(std::string(string_key, str_len - 1)); + } + else { + std::string key = std::string(string_key, str_len - 1); + if (key[0] == '\0') { + key = key.substr(key.find('\0', 1) + 1); + } + if (std::find(result.begin(), result.end(), key) == result.end()) { + result.push_back(std::move(key)); + } + } + + // move the iterator forward + } while (zend_hash_move_forward_ex(table, &position) == SUCCESS); + + return result; + + } + return std::vector(); +} + /** * Internal helper method to retrieve an iterator * @param begin Should the iterator start at the begin From d6988cda71de419ae6df88efc3bfb80a72734920 Mon Sep 17 00:00:00 2001 From: andot Date: Thu, 10 Jul 2014 20:46:51 +0800 Subject: [PATCH 2/3] add #include in includes.h. --- zend/includes.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zend/includes.h b/zend/includes.h index 63b435eb..9d138367 100644 --- a/zend/includes.h +++ b/zend/includes.h @@ -20,7 +20,8 @@ #include #include #include - +#include + // for debug #include From 6bb8329bf3556877c61a0fbe8fa8e39def90652b Mon Sep 17 00:00:00 2001 From: andot Date: Fri, 11 Jul 2014 17:41:13 +0800 Subject: [PATCH 3/3] Optimized implementation of properties. --- zend/value.cpp | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/zend/value.cpp b/zend/value.cpp index 0c2e50f6..b9b98c8e 100644 --- a/zend/value.cpp +++ b/zend/value.cpp @@ -1625,7 +1625,7 @@ std::map Value::mapValue() const */ std::vector Value::properties(bool only_public) const { if (isObject()) { - std::vector result; + std::set result; // we need the TSRMLS_CC variable TSRMLS_FETCH(); @@ -1647,25 +1647,18 @@ std::vector Value::properties(bool only_public) const { // if key is not found, the iterator is at an invalid position if (type == HASH_KEY_NON_EXISTANT) continue; - // if only_public is true, only store public property - if (only_public) { - if (string_key[0] == '\0') continue; - result.push_back(std::string(string_key, str_len - 1)); - } - else { - std::string key = std::string(string_key, str_len - 1); - if (key[0] == '\0') { - key = key.substr(key.find('\0', 1) + 1); - } - if (std::find(result.begin(), result.end(), key) == result.end()) { - result.push_back(std::move(key)); - } + std::string key = std::string(string_key, str_len - 1); + if (key[0] == '\0') { + // if only_public is true, only store public property + if (only_public) continue; + key = key.substr(key.find('\0', 1) + 1); } + result.insert(std::move(key)); // move the iterator forward } while (zend_hash_move_forward_ex(table, &position) == SUCCESS); - return result; + return std::vector(result.begin(), result.end()); } return std::vector();