Files

481 lines
14 KiB
C++

/*
+----------------------------------------------------------------------+
| PHP Version 7 |
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Darek Slusarczyk <marines@php.net> |
+----------------------------------------------------------------------+
*/
#ifndef MYSQL_XDEVAPI_UTIL_VALUE_H
#define MYSQL_XDEVAPI_UTIL_VALUE_H
#include "strings.h"
#include "string_utils.h"
#include <optional>
namespace mysqlx::util {
struct arg_string;
class zvalue
{
public:
enum class Type {
Undefined = IS_UNDEF,
Null = IS_NULL,
False = IS_FALSE,
True = IS_TRUE,
Long = IS_LONG,
Double = IS_DOUBLE,
String = IS_STRING,
Array = IS_ARRAY,
Object = IS_OBJECT,
Resource = IS_RESOURCE,
Reference = IS_REFERENCE,
Constant_ast = IS_CONSTANT_AST,
Internal_type_bool = _IS_BOOL,
Callable = IS_CALLABLE,
Void = IS_VOID
};
public:
zvalue();
zvalue(Type type);
zvalue(const zvalue& rhs);
zvalue(zvalue&& rhs);
zvalue(const zval& zv);
zvalue(zval&& zv);
zvalue(const zval* zv);
zvalue(const HashTable* ht);
zvalue(std::nullptr_t value);
zvalue(bool value);
zvalue(int32_t value);
zvalue(int64_t value);
zvalue(uint32_t value);
zvalue(uint64_t value);
zvalue(double value);
zvalue(char value);
zvalue(const string& value);
zvalue(const string_view& value);
zvalue(const std::string& value);
zvalue(const char* value);
zvalue(const arg_string& value);
zvalue(const char* value, std::size_t length);
zvalue(zend_string* value);
zvalue(std::initializer_list<std::pair<string_view, zvalue>> values);
template<typename T>
zvalue(std::initializer_list<T> values);
template<typename Iterator>
zvalue(Iterator begin, Iterator end);
template<typename T>
zvalue(const vector<T>& values);
template<typename T>
zvalue(const set<T>& values);
template<typename Key, typename Value>
zvalue(const map<Key, Value>& values);
static zvalue create_array(std::size_t size = 0);
static zvalue create_object();
~zvalue();
public:
// assignment
zvalue& operator=(const zvalue& rhs);
zvalue& operator=(zvalue&& rhs);
zvalue& operator=(const zval& rhs);
zvalue& operator=(zval&& rhs);
zvalue& operator=(const zval* rhs);
zvalue& operator=(const HashTable* ht);
zvalue& operator=(std::nullptr_t value);
zvalue& operator=(bool value);
zvalue& operator=(int32_t value);
zvalue& operator=(int64_t value);
zvalue& operator=(uint32_t value);
zvalue& operator=(uint64_t value);
zvalue& operator=(double value);
zvalue& operator=(char value);
zvalue& operator=(const string& value);
zvalue& operator=(const string_view& value);
zvalue& operator=(const std::string& value);
zvalue& operator=(const char* value);
zvalue& operator=(const arg_string& value);
zvalue& operator=(zend_string* value);
void assign(const char* value, std::size_t length);
zvalue& operator=(std::initializer_list<std::pair<string_view, zvalue>> values);
template<typename T>
zvalue& operator=(std::initializer_list<T> values);
template<typename T>
zvalue& operator=(const vector<T>& values);
template<typename T>
zvalue& operator=(const set<T>& values);
template<typename Key, typename Value>
zvalue& operator=(const map<Key, Value>& values);
public:
Type type() const;
bool is_undef() const;
bool is_null() const;
bool is_false() const;
bool is_true() const;
bool is_bool() const;
bool is_long() const;
bool is_double() const;
bool is_string() const;
bool is_array() const;
bool is_object() const;
bool is_reference() const;
bool is_instance_of(const zend_class_entry* class_entry) const;
// returns true if type is neither undefined nor null (i.e. type != Undefined && type != Null)
bool has_value() const;
// if type of zv is other than array then dispose it, and assign empty array
static void ensure_is_array(zval* zv);
public:
// call below methods only if U are fully sure they have proper type (or it may crash)
// else use to_optional_value or to_obligatory_value
bool to_bool() const;
int to_int() const;
long to_long() const;
zend_long to_zlong() const;
int32_t to_int32() const;
int64_t to_int64() const;
unsigned int to_uint() const;
unsigned long to_ulong() const;
zend_ulong to_zulong() const;
std::size_t to_size_t() const;
uint32_t to_uint32() const;
uint64_t to_uint64() const;
double to_double() const;
string to_string() const;
string_view to_string_view() const;
std::string to_std_string() const;
const char* c_str() const;
zend_string* z_str() const;
zend_object* z_obj() const;
template<typename T>
T to_value() const;
// if value is undefined or has incompatible type, then return std::nullopt
template<typename T>
std::optional<T> to_optional_value() const;
// if value is undefined or has incompatible type, then throws exception
template<typename T>
T to_obligatory_value() const;
public:
// applicable only for string and array
std::size_t size() const;
std::size_t length() const;
bool empty() const;
// clears current value, but keeps current type - applicable only for string and array
void clear();
// inits array with storage reserved for specified number of items
void reserve(std::size_t size = 0);
// frees current value, and sets type to undefined
void reset();
// returns duplicate - if it is reference type, it will be
// new fully separated item, not just next reference incremented
zvalue clone() const;
static zvalue clone_from(const zval* src);
static zvalue clone_from(const zval& src);
// take over ownership of passed zval
void acquire(zval* zv);
void acquire(zval& zv);
// copies value to zv
void copy_to(zval* zv);
void copy_to(zval& zv);
static void copy_from_to(zval* src, zval* dst);
// moves value to zv, and sets type to undefined
void move_to(zval* zv);
void move_to(zval& zv);
static void move_from_to(zval* src, zval* dst);
// increment / decrement reference counter if type is refcounted, else does nothing
void inc_ref() const;
void dec_ref() const;
// returns holded value, and sets type to undefined
zval release();
// set to undefined without releasing currently kept value
void invalidate();
void swap(zvalue& rhs) noexcept;
public:
// object
std::size_t properties_count() const;
bool has_property(const string& name) const;
bool has_property(const string_view& name) const;
bool has_property(const std::string& name) const;
bool has_property(const char* name) const;
bool has_property(const char* name, std::size_t name_length) const;
// in case property doesn't exists it returns 'undefined' zvalue, i.e. is_undef() == true
zvalue get_property(const string& name) const;
zvalue get_property(const string_view& name) const;
zvalue get_property(const std::string& name) const;
zvalue get_property(const char* name) const;
zvalue get_property(const char* name, std::size_t name_length) const;
// in case property doesn't exists it throws an exception
zvalue require_property(const string& name) const;
zvalue require_property(const string_view& name) const;
zvalue require_property(const std::string& name) const;
zvalue require_property(const char* name) const;
zvalue require_property(const char* name, std::size_t name_length) const;
void set_property(const string& name, const zvalue& value);
void set_property(const string_view& name, const zvalue& value);
void set_property(const std::string& name, const zvalue& value);
void set_property(const char* name, const zvalue& value);
void set_property(const char* name, std::size_t name_length, const zvalue& value);
void unset_property(const string& name);
void unset_property(const string_view& name);
void unset_property(const std::string& name);
void unset_property(const char* name);
void unset_property(const char* name, std::size_t name_length);
public:
// array / hash_table
bool contains(std::size_t index) const;
bool contains(long index) const;
bool contains(const string& key) const;
bool contains(const string_view& key) const;
bool contains(const std::string& key) const;
bool contains(const char* key) const;
bool contains(const char* key, std::size_t key_length) const;
// it returns value, not reference!
// returns empty result (is_undef() == true) in case given index/key not found
zvalue find(std::size_t index) const;
zvalue find(long index) const;
zvalue find(const string& key) const;
zvalue find(const string_view& key) const;
zvalue find(const std::string& key) const;
zvalue find(const char* key) const;
zvalue find(const char* key, std::size_t key_length) const;
// it returns value, not reference!
// returns empty result (is_undef() == true) in case given index/key not found
zvalue operator[](std::size_t index) const;
zvalue operator[](long index) const;
zvalue operator[](const string& key) const;
zvalue operator[](const string_view& key) const;
zvalue operator[](const std::string& key) const;
zvalue operator[](const char* key) const;
// it returns value, not reference!
// throws an exception in case given index/key not found
zvalue at(std::size_t index) const;
zvalue at(long index) const;
zvalue at(const string& key) const;
zvalue at(const string_view& key) const;
zvalue at(const std::string& key) const;
zvalue at(const char* key) const;
zvalue at(const char* key, std::size_t key_length) const;
// inserts new item, or overwrites existing one if given index/key already exists
void insert(std::size_t index, const zvalue& value);
void insert(long index, const zvalue& value);
void insert(std::size_t index, zvalue&& value);
void insert(long index, zvalue&& value);
void insert(const string& key, const zvalue& value);
void insert(const string_view& key, const zvalue& value);
void insert(const std::string& key, const zvalue& value);
void insert(const char* key, const zvalue& value);
void insert(const char* key, std::size_t key_length, const zvalue& value);
void insert(const string& key, zvalue&& value);
void insert(const string_view& key, zvalue&& value);
void insert(const std::string& key, zvalue&& value);
void insert(const char* key, zvalue&& value);
void insert(const char* key, std::size_t key_length, zvalue&& value);
template<typename Key, typename Value>
void insert(const std::pair<Key, Value>& key_value);
template<typename Key, typename Value>
void insert(std::initializer_list<std::pair<Key, Value>> values);
// adds new item at the next free index
void push_back(const zvalue& value);
void push_back(zvalue&& value);
template<typename T>
void push_back(std::initializer_list<T> values);
// returns true if item was erased, or false if given index/key didn't exist
bool erase(std::size_t index);
bool erase(long index);
bool erase(const string& key);
bool erase(const string_view& key);
bool erase(const std::string& key);
bool erase(const char* key);
bool erase(const char* key, std::size_t key_length);
public:
template<typename Value_type, typename Getter>
class generic_iterator
{
public:
using value_type = Value_type;
using difference_type = std::ptrdiff_t;
using pointer = value_type*;
using reference = value_type&;
using iterator_category = std::forward_iterator_tag;
public:
explicit generic_iterator(HashTable* ht, HashPosition size, HashPosition pos);
generic_iterator operator++(int);
generic_iterator& operator++();
value_type operator*() const;
bool operator==(const generic_iterator& rhs) const;
bool operator!=(const generic_iterator& rhs) const;
private:
HashTable* ht;
HashPosition size;
mutable HashPosition pos;
};
public:
// to iterate through array items as pair<key, value>
struct Getter_key_value
{
std::pair<zvalue, zvalue> operator()(HashTable* ht, HashPosition pos) const;
};
using iterator = generic_iterator<std::pair<zvalue, zvalue>, Getter_key_value>;
iterator begin() const;
iterator end() const;
public:
// to iterate through array items as keys (values are not returned)
struct Getter_key
{
zvalue operator()(HashTable* ht, HashPosition pos) const;
};
using key_iterator = generic_iterator<zvalue, Getter_key>;
key_iterator kbegin() const;
key_iterator kend() const;
struct keys_range
{
keys_range(const zvalue& ref);
key_iterator begin() const;
key_iterator end() const;
const zvalue& ref;
};
keys_range keys() const;
public:
// to iterate through array items as values (keys are not returned)
struct Getter_value
{
zvalue operator()(HashTable* ht, HashPosition pos) const;
};
using value_iterator = generic_iterator<zvalue, Getter_value>;
value_iterator vbegin() const;
value_iterator vend() const;
struct values_range
{
values_range(const zvalue& ref);
value_iterator begin() const;
value_iterator end() const;
const zvalue& ref;
};
values_range values() const;
public:
const zval& c_ref() const;
zval& ref() const;
const zval* c_ptr() const;
zval* ptr() const;
public:
util::string serialize(bool decorate = true) const;
private:
zval zv;
};
using zvalues = vector<zvalue>;
} // namespace mysqlx::util
#include "value.inl"
#endif // MYSQL_XDEVAPI_UTIL_VALUE_H