summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-03-15 18:31:42 +0100
committerEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-03-15 18:31:42 +0100
commit3bcd6e21d1142b5ec35f99c4bdcd925bf7ae5083 (patch)
tree08903d9b7e7b2bd57fa1a01fc873d618a17b0a8f
parent38b866988761f4da01eab769dc660b06b07e97be (diff)
added empty() function, and added HardCoded class
-rw-r--r--include/call.h10
-rw-r--r--include/hashmember.h20
-rw-r--r--include/init.h23
-rw-r--r--include/value.h57
-rw-r--r--phpcpp.h1
-rw-r--r--src/arithmetic.h13
-rw-r--r--src/classbase.cpp6
-rw-r--r--src/includes.h1
-rw-r--r--src/value.cpp81
9 files changed, 152 insertions, 60 deletions
diff --git a/include/call.h b/include/call.h
index bae0a0a..7cf68bb 100644
--- a/include/call.h
+++ b/include/call.h
@@ -44,8 +44,14 @@ Value call(const char *name, Params&&... params)
* make the code run on the highway), it is not expected that these functions
* are going to be used very often anyway.
*/
-inline Value array_keys(const Value &value) { return call("array_keys", value); }
-inline Value array_values(const Value &value) { return call("array_values", value); }
+inline Value array_keys(const Value &value) { return call("array_keys", value); }
+inline Value array_values(const Value &value) { return call("array_values", value); }
+inline Value empty(const Value &value) { return call("empty", value); }
+inline Value empty(const HashMember<std::string> &member) { return !member.exists() || empty(member.value()); }
+inline Value empty(const HashMember<int> &member) { return !member.exists() || empty(member.value()); }
+//inline Value isset(const Value &value) { return call("isset", value); }
+//inline Value isset(const HashMember<std::string> &member) { return member.exists() && isset(member.value()); }
+//inline Value isset(const HashMember<int> &member) { return member.exists() && isset(member.value()); }
/**
* End of namespace
diff --git a/include/hashmember.h b/include/hashmember.h
index 41c40d3..d61e5c9 100644
--- a/include/hashmember.h
+++ b/include/hashmember.h
@@ -53,6 +53,16 @@ public:
}
/**
+ * Is this an existing hash member (true) or only one that is ready
+ * to be assigned a new value to, but that is not yet in the hashtable
+ * @return bool
+ */
+ bool exists() const
+ {
+ return _base->contains(_index);
+ }
+
+ /**
* Retrieve the original value
* @return Value
*/
@@ -179,6 +189,7 @@ public:
HashMember &operator+=(char value) { return operator=(this->value() + value); }
HashMember &operator+=(const std::string &value) { return operator=(this->value() + value); }
HashMember &operator+=(const char *value) { return operator=(this->value() + value); }
+ HashMember &operator+=(const HardCoded &value) { return operator=(this->value() + value); }
HashMember &operator+=(double value) { return operator=(this->value() + value); }
/**
@@ -194,6 +205,7 @@ public:
HashMember &operator-=(char value) { return operator=(this->value() - value); }
HashMember &operator-=(const std::string &value) { return operator=(this->value() - value); }
HashMember &operator-=(const char *value) { return operator=(this->value() - value); }
+ HashMember &operator-=(const HardCoded &value) { return operator=(this->value() - value); }
HashMember &operator-=(double value) { return operator=(this->value() - value); }
/**
@@ -209,6 +221,7 @@ public:
HashMember &operator*=(char value) { return operator=(this->value() * value); }
HashMember &operator*=(const std::string &value) { return operator=(this->value() * value); }
HashMember &operator*=(const char *value) { return operator=(this->value() * value); }
+ HashMember &operator*=(const HardCoded &value) { return operator=(this->value() * value); }
HashMember &operator*=(double value) { return operator=(this->value() * value); }
/**
@@ -224,6 +237,7 @@ public:
HashMember &operator/=(char value) { return operator=(this->value() / value); }
HashMember &operator/=(const std::string &value) { return operator=(this->value() / value); }
HashMember &operator/=(const char *value) { return operator=(this->value() / value); }
+ HashMember &operator/=(const HardCoded &value) { return operator=(this->value() / value); }
HashMember &operator/=(double value) { return operator=(this->value() / value); }
/**
@@ -239,6 +253,7 @@ public:
HashMember &operator%=(char value) { return operator=(this->value() % value); }
HashMember &operator%=(const std::string &value) { return operator=(this->value() % value); }
HashMember &operator%=(const char *value) { return operator=(this->value() % value); }
+ HashMember &operator%=(const HardCoded &value) { return operator=(this->value() % value); }
HashMember &operator%=(double value) { return operator=(this->value() % value); }
/**
@@ -254,6 +269,7 @@ public:
Value operator+(char value) { return this->value() + value; }
Value operator+(const std::string &value) { return this->value() + value; }
Value operator+(const char *value) { return this->value() + value; }
+ Value operator+(const HardCoded &value) { return this->value() + value; }
Value operator+(double value) { return this->value() + value; }
/**
@@ -269,6 +285,7 @@ public:
Value operator-(char value) { return this->value() - value; }
Value operator-(const std::string &value) { return this->value() - value; }
Value operator-(const char *value) { return this->value() - value; }
+ Value operator-(const HardCoded &value) { return this->value() - value; }
Value operator-(double value) { return this->value() - value; }
/**
@@ -284,6 +301,7 @@ public:
Value operator*(char value) { return this->value() * value; }
Value operator*(const std::string &value) { return this->value() * value; }
Value operator*(const char *value) { return this->value() * value; }
+ Value operator*(const HardCoded &value) { return this->value() * value; }
Value operator*(double value) { return this->value() * value; }
/**
@@ -299,6 +317,7 @@ public:
Value operator/(char value) { return this->value() / value; }
Value operator/(const std::string &value) { return this->value() / value; }
Value operator/(const char *value) { return this->value() / value; }
+ Value operator/(const HardCoded &value) { return this->value() / value; }
Value operator/(double value) { return this->value() / value; }
/**
@@ -314,6 +333,7 @@ public:
Value operator%(char value) { return this->value() % value; }
Value operator%(const std::string &value) { return this->value() % value; }
Value operator%(const char *value) { return this->value() % value; }
+ Value operator%(const HardCoded &value) { return this->value() % value; }
Value operator%(double value) { return this->value() % value; }
/**
diff --git a/include/init.h b/include/init.h
index ca6ff65..8f914f5 100644
--- a/include/init.h
+++ b/include/init.h
@@ -14,26 +14,23 @@
namespace Php {
/**
- * The way how PHP C API deals with "global" variables is stupid.
+ * The way how PHP C API deals with "global" variables is peculiar.
*
- * This is supposed to turn into a structure that is going to be
- * instantiated for each parallel running request, and for which the
- * PHP engine allocates a certain amount of memory, and a magic
- * pointer that is passed and should be forwarded to every thinkable
- * PHP function.
+ * The following macros are supposed to turn into a structure that is going
+ * to be instantiated for each parallel running request, and for which the
+ * PHP engine allocates a certain amount of memory, and a magic pointer that
+ * is passed and should be forwarded to every thinkable PHP function.
*
- * We don't like this architecture. We have our own environment object
- * that makes much more sense, and that we use. However, we need
- * to assign this object somewhere, so that's what we do in this
- * one and only global variable
+ * We don't use this architecture. We have our own environment object
+ * that makes much more sense, and that we use. However, the Zend engine
+ * expects this structure and this structure to exist.
*/
ZEND_BEGIN_MODULE_GLOBALS(phpcpp)
ZEND_END_MODULE_GLOBALS(phpcpp)
/**
- * And now we're going to define a macro. This also is a ridiculous
- * architecture from PHP to get access to a variable from the
- * structure above.
+ * And now we're going to define a macro. This also is a uncommon architecture
+ * from PHP to get access to a variable from the structure above.
*/
#ifdef ZTS
#define PHPCPP_G(v) TSRMG(phpcpp_globals_id, phpcpp_globals *, v)
diff --git a/include/value.h b/include/value.h
index fce8750..13cea38 100644
--- a/include/value.h
+++ b/include/value.h
@@ -57,6 +57,7 @@ public:
Value(char value);
Value(const std::string &value);
Value(const char *value, int size = -1);
+ Value(const HardCoded &value);
Value(double value);
/**
@@ -161,6 +162,7 @@ public:
Value &operator=(char value);
Value &operator=(const std::string &value);
Value &operator=(const char *value);
+ Value &operator=(const HardCoded &value);
Value &operator=(double value);
/**
@@ -176,6 +178,7 @@ public:
Value &operator+=(char value);
Value &operator+=(const std::string &value);
Value &operator+=(const char *value);
+ Value &operator+=(const HardCoded &value);
Value &operator+=(double value);
/**
@@ -191,6 +194,7 @@ public:
Value &operator-=(char value);
Value &operator-=(const std::string &value);
Value &operator-=(const char *value);
+ Value &operator-=(const HardCoded &value);
Value &operator-=(double value);
/**
@@ -206,6 +210,7 @@ public:
Value &operator*=(char value);
Value &operator*=(const std::string &value);
Value &operator*=(const char *value);
+ Value &operator*=(const HardCoded &value);
Value &operator*=(double value);
/**
@@ -221,6 +226,7 @@ public:
Value &operator/=(char value);
Value &operator/=(const std::string &value);
Value &operator/=(const char *value);
+ Value &operator/=(const HardCoded &value);
Value &operator/=(double value);
/**
@@ -236,6 +242,7 @@ public:
Value &operator%=(char value);
Value &operator%=(const std::string &value);
Value &operator%=(const char *value);
+ Value &operator%=(const HardCoded &value);
Value &operator%=(double value);
/**
@@ -251,6 +258,7 @@ public:
Value operator+(char value);
Value operator+(const std::string &value);
Value operator+(const char *value);
+ Value operator+(const HardCoded &value);
Value operator+(double value);
/**
@@ -266,6 +274,7 @@ public:
Value operator-(char value);
Value operator-(const std::string &value);
Value operator-(const char *value);
+ Value operator-(const HardCoded &value);
Value operator-(double value);
/**
@@ -281,6 +290,7 @@ public:
Value operator*(char value);
Value operator*(const std::string &value);
Value operator*(const char *value);
+ Value operator*(const HardCoded &value);
Value operator*(double value);
/**
@@ -296,6 +306,7 @@ public:
Value operator/(char value);
Value operator/(const std::string &value);
Value operator/(const char *value);
+ Value operator/(const HardCoded &value);
Value operator/(double value);
/**
@@ -311,18 +322,19 @@ public:
Value operator%(char value);
Value operator%(const std::string &value);
Value operator%(const char *value);
+ Value operator%(const HardCoded &value);
Value operator%(double value);
/**
* Comparison operators for hardcoded strings
* @param value
*/
- bool operator==(const char *value) const { return stringValue() == value; }
- bool operator!=(const char *value) const { return stringValue() != value; }
- bool operator<=(const char *value) const { return stringValue() <= value; }
- bool operator>=(const char *value) const { return stringValue() >= value; }
- bool operator< (const char *value) const { return stringValue() < value; }
- bool operator> (const char *value) const { return stringValue() > value; }
+ bool operator==(const char *value) const { return ::strcmp(rawValue(), value) == 0; }
+ bool operator!=(const char *value) const { return ::strcmp(rawValue(), value) != 0; }
+ bool operator<=(const char *value) const { return ::strcmp(rawValue(), value) <= 0; }
+ bool operator>=(const char *value) const { return ::strcmp(rawValue(), value) >= 0; }
+ bool operator< (const char *value) const { return ::strcmp(rawValue(), value) < 0; }
+ bool operator> (const char *value) const { return ::strcmp(rawValue(), value) > 0; }
/**
* Comparison operators
@@ -372,12 +384,20 @@ public:
bool isObject() const { return type() == Type::Object; }
bool isArray() const { return type() == Type::Array; }
bool isCallable() const;
+
+ /**
+ * Get access to the raw buffer - you can use this for direct reading and
+ * writing to and from the buffer. Note that this only works for string
+ * variables - other variables return nullptr
+ * @return char *
+ */
+ char *buffer() const;
/**
- * Is the variable empty?
- * @return bool
+ * Get access to the raw buffer for read operationrs.
+ * @return const char *
*/
- bool isEmpty() const;
+ const char *rawValue() const;
/**
* Retrieve the value as number
@@ -398,14 +418,6 @@ public:
bool boolValue() const;
/**
- * Retrieve the raw string value
- * Warning: Only use this for NULL terminated strings, or use it in combination
- * with the string size to prevent that you access data outside the buffer
- * @return const char *
- */
- const char *rawValue() const;
-
- /**
* Retrieve the value as a string
* @return string
*/
@@ -529,6 +541,17 @@ public:
* @return bool
*/
bool contains(const char *key, int size) const;
+
+ /**
+ * Is a certain key set in the array
+ * @param key
+ * @param size
+ * @return bool
+ */
+ bool contains(const char *key) const
+ {
+ return contains(key, strlen(key));
+ }
/**
* Cast to a number
diff --git a/phpcpp.h b/phpcpp.h
index f58eb8d..83ac804 100644
--- a/phpcpp.h
+++ b/phpcpp.h
@@ -27,6 +27,7 @@
*/
#include <phpcpp/exception.h>
#include <phpcpp/type.h>
+#include <phpcpp/hardcoded.h>
#include <phpcpp/value.h>
#include <phpcpp/array.h>
#include <phpcpp/object.h>
diff --git a/src/arithmetic.h b/src/arithmetic.h
index 21343d1..00d5641 100644
--- a/src/arithmetic.h
+++ b/src/arithmetic.h
@@ -127,7 +127,7 @@ public:
// convert string to integer
return apply(atoi(value.c_str()));
}
-
+
/**
* Apply a string (representing a number), and return a new value object after running the arithmetic function
* @param value
@@ -138,6 +138,17 @@ public:
// convert string to integer
return apply(atoi(value));
}
+
+ /**
+ * Apply a string (representing a number), and return a new value object after running the arithmetic function
+ * @param value
+ * @return Value
+ */
+ Value apply(const HardCoded &value)
+ {
+ // convert string to integer
+ return apply(atoi(value.buffer()));
+ }
/**
* Apply a string (representing a number), and return a new value object after running the arithmetic function
diff --git a/src/classbase.cpp b/src/classbase.cpp
index 0de62dd..fbc6ed2 100644
--- a/src/classbase.cpp
+++ b/src/classbase.cpp
@@ -739,9 +739,9 @@ int ClassBase::hasDimension(zval *object, zval *member, int check_empty)
// we know for certain that the offset exists, but should we check
// more, like whether the value is empty or not?
if (!check_empty) return true;
-
- // it should not be empty
- return !arrayaccess->offsetGet(member).isEmpty();
+
+ // the user wants to know if the property is empty
+ return empty(arrayaccess->offsetGet(member));
}
catch (Exception &exception)
{
diff --git a/src/includes.h b/src/includes.h
index 0c00df3..55aa103 100644
--- a/src/includes.h
+++ b/src/includes.h
@@ -46,6 +46,7 @@
*/
#include "../include/exception.h"
#include "../include/type.h"
+#include "../include/hardcoded.h"
#include "../include/value.h"
#include "../include/array.h"
#include "../include/object.h"
diff --git a/src/value.cpp b/src/value.cpp
index 9af2d14..7ce49fe 100644
--- a/src/value.cpp
+++ b/src/value.cpp
@@ -130,6 +130,17 @@ Value::Value(const char *value, int size)
}
/**
+ * Contructor based on hardcoded string that does not have to be copied
+ * @param value
+ */
+Value::Value(const HardCoded &value)
+{
+ // create a string zval
+ MAKE_STD_ZVAL(_val);
+ ZVAL_STRINGL(_val, value.buffer(), value.size(), 0);
+}
+
+/**
* Constructor based on decimal value
* @param value
*/
@@ -663,6 +674,26 @@ Value &Value::operator=(const char *value)
return *this;
}
+/**
+ * Assignment operator
+ * @param value
+ * @return Value
+ */
+Value &Value::operator=(const HardCoded &value)
+{
+ // if this is not a reference variable, we should detach it to implement copy on write
+ SEPARATE_ZVAL_IF_NOT_REF(&_val);
+
+ // deallocate current zval (without cleaning the zval structure)
+ zval_dtor(_val);
+
+ // set new non-duplicated value
+ ZVAL_STRINGL(_val, value.buffer(), value.size(), 0);
+
+ // update the object
+ return *this;
+}
+
/**
* Assignment operator
* @param value
@@ -696,6 +727,7 @@ Value &Value::operator+=(bool value) { return Arithmetic<std::plu
Value &Value::operator+=(char value) { return Arithmetic<std::plus>(this).assign(value); }
Value &Value::operator+=(const std::string &value) { return Arithmetic<std::plus>(this).assign(value); }
Value &Value::operator+=(const char *value) { return Arithmetic<std::plus>(this).assign(value); }
+Value &Value::operator+=(const HardCoded &value) { return Arithmetic<std::plus>(this).assign(value); }
Value &Value::operator+=(double value) { return Arithmetic<std::plus>(this).assign(value); }
/**
@@ -711,6 +743,7 @@ Value &Value::operator-=(bool value) { return Arithmetic<std::min
Value &Value::operator-=(char value) { return Arithmetic<std::minus>(this).assign(value); }
Value &Value::operator-=(const std::string &value) { return Arithmetic<std::minus>(this).assign(value); }
Value &Value::operator-=(const char *value) { return Arithmetic<std::minus>(this).assign(value); }
+Value &Value::operator-=(const HardCoded &value) { return Arithmetic<std::minus>(this).assign(value); }
Value &Value::operator-=(double value) { return Arithmetic<std::minus>(this).assign(value); }
/**
@@ -726,6 +759,7 @@ Value &Value::operator*=(bool value) { return Arithmetic<std::mul
Value &Value::operator*=(char value) { return Arithmetic<std::multiplies>(this).assign(value); }
Value &Value::operator*=(const std::string &value) { return Arithmetic<std::multiplies>(this).assign(value); }
Value &Value::operator*=(const char *value) { return Arithmetic<std::multiplies>(this).assign(value); }
+Value &Value::operator*=(const HardCoded &value) { return Arithmetic<std::multiplies>(this).assign(value); }
Value &Value::operator*=(double value) { return Arithmetic<std::multiplies>(this).assign(value); }
/**
@@ -741,6 +775,7 @@ Value &Value::operator/=(bool value) { return Arithmetic<std::div
Value &Value::operator/=(char value) { return Arithmetic<std::divides>(this).assign(value); }
Value &Value::operator/=(const std::string &value) { return Arithmetic<std::divides>(this).assign(value); }
Value &Value::operator/=(const char *value) { return Arithmetic<std::divides>(this).assign(value); }
+Value &Value::operator/=(const HardCoded &value) { return Arithmetic<std::divides>(this).assign(value); }
Value &Value::operator/=(double value) { return Arithmetic<std::divides>(this).assign(value); }
/**
@@ -757,6 +792,7 @@ Value &Value::operator%=(bool value) { return operator=(numericVa
Value &Value::operator%=(char value) { return operator=(numericValue() % value); }
Value &Value::operator%=(const std::string &value) { return operator=(numericValue() % atoi(value.c_str())); }
Value &Value::operator%=(const char *value) { return operator=(numericValue() % atoi(value)); }
+Value &Value::operator%=(const HardCoded &value) { return operator=(numericValue() % atoi(value.buffer())); }
Value &Value::operator%=(double value) { return operator=(numericValue() % (int)value); }
/**
@@ -772,6 +808,7 @@ Value Value::operator+(bool value) { return Arithmetic<std::plu
Value Value::operator+(char value) { return Arithmetic<std::plus>(this).apply(value); }
Value Value::operator+(const std::string &value) { return Arithmetic<std::plus>(this).apply(value); }
Value Value::operator+(const char *value) { return Arithmetic<std::plus>(this).apply(value); }
+Value Value::operator+(const HardCoded &value) { return Arithmetic<std::plus>(this).apply(value); }
Value Value::operator+(double value) { return Arithmetic<std::plus>(this).apply(value); }
/**
@@ -787,6 +824,7 @@ Value Value::operator-(bool value) { return Arithmetic<std::min
Value Value::operator-(char value) { return Arithmetic<std::minus>(this).apply(value); }
Value Value::operator-(const std::string &value) { return Arithmetic<std::minus>(this).apply(value); }
Value Value::operator-(const char *value) { return Arithmetic<std::minus>(this).apply(value); }
+Value Value::operator-(const HardCoded &value) { return Arithmetic<std::minus>(this).apply(value); }
Value Value::operator-(double value) { return Arithmetic<std::minus>(this).apply(value); }
/**
@@ -802,6 +840,7 @@ Value Value::operator*(bool value) { return Arithmetic<std::mul
Value Value::operator*(char value) { return Arithmetic<std::multiplies>(this).apply(value); }
Value Value::operator*(const std::string &value) { return Arithmetic<std::multiplies>(this).apply(value); }
Value Value::operator*(const char *value) { return Arithmetic<std::multiplies>(this).apply(value); }
+Value Value::operator*(const HardCoded &value) { return Arithmetic<std::multiplies>(this).apply(value); }
Value Value::operator*(double value) { return Arithmetic<std::multiplies>(this).apply(value); }
/**
@@ -817,6 +856,7 @@ Value Value::operator/(bool value) { return Arithmetic<std::div
Value Value::operator/(char value) { return Arithmetic<std::divides>(this).apply(value); }
Value Value::operator/(const std::string &value) { return Arithmetic<std::divides>(this).apply(value); }
Value Value::operator/(const char *value) { return Arithmetic<std::divides>(this).apply(value); }
+Value Value::operator/(const HardCoded &value) { return Arithmetic<std::divides>(this).apply(value); }
Value Value::operator/(double value) { return Arithmetic<std::divides>(this).apply(value); }
/**
@@ -832,6 +872,7 @@ Value Value::operator%(bool value) { return Value(numericValue(
Value Value::operator%(char value) { return Value(numericValue() % value); }
Value Value::operator%(const std::string &value) { return Value(numericValue() % atoi(value.c_str())); }
Value Value::operator%(const char *value) { return Value(numericValue() % atoi(value)); }
+Value Value::operator%(const HardCoded &value) { return Value(numericValue() % atoi(value.buffer())); }
Value Value::operator%(double value) { return Value(numericValue() % (int)value); }
/**
@@ -1355,27 +1396,6 @@ bool Value::isCallable() const
}
/**
- * Is the variable empty?
- * @return bool
- */
-bool Value::isEmpty() const
-{
- switch (type()) {
- case Type::Null: return true;
- case Type::Numeric: return numericValue() == 0;
- case Type::Float: return floatValue() == 0.0;
- case Type::Bool: return boolValue() == false;
- case Type::Array: return size() == 0;
- case Type::Object: return false;
- case Type::String: return size() == 0;
- case Type::Callable: return false;
- default: return false;
- }
-
- // for the time being we consider resources and consts to be not-empty
-}
-
-/**
* Make a clone of the type
* @return Value
*/
@@ -1451,15 +1471,28 @@ std::string Value::stringValue() const
}
/**
- * Retrieve raw string value
+ * Access to the raw buffer
+ * @return char *
+ */
+char *Value::buffer() const
+{
+ // must be a string
+ if (!isString()) return nullptr;
+
+ // already a string?
+ return Z_STRVAL_P(_val);
+}
+
+/**
+ * Access to the raw buffer
* @return const char *
*/
const char *Value::rawValue() const
{
- // already a string?
+ // must be a string
if (isString()) return Z_STRVAL_P(_val);
- // make a clone
+ // make a clone and return that buffer
return clone(Type::String).rawValue();
}