2
* Copyright 2015-2016 DataStax, Inc.
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
17
#include "php_driver.h"
18
#include "php_driver_types.h"
19
#include "util/collections.h"
20
#include "util/hash.h"
21
#include "util/types.h"
24
zend_class_entry *php_driver_set_ce = NULL;
27
php_driver_set_add(php_driver_set *set, zval *object TSRMLS_DC)
29
php_driver_set_entry *entry;
30
php_driver_type *type;
32
if (Z_TYPE_P(object) == IS_NULL) {
33
zend_throw_exception_ex(php_driver_invalid_argument_exception_ce, 0 TSRMLS_CC,
34
"Invalid value: null is not supported inside sets");
38
type = PHP_DRIVER_GET_TYPE(PHP5TO7_ZVAL_MAYBE_P(set->type));
40
if (!php_driver_validate_object(object, PHP5TO7_ZVAL_MAYBE_P(type->data.set.value_type) TSRMLS_CC)) {
44
HASH_FIND_ZVAL(set->entries, object, entry);
47
entry = (php_driver_set_entry *) emalloc(sizeof(php_driver_set_entry));
48
PHP5TO7_ZVAL_COPY(PHP5TO7_ZVAL_MAYBE_P(entry->value), object);
49
HASH_ADD_ZVAL(set->entries, value, entry);
56
php_driver_set_del(php_driver_set *set, zval *object TSRMLS_DC)
58
php_driver_set_entry *entry;
59
php_driver_type *type;
62
type = PHP_DRIVER_GET_TYPE(PHP5TO7_ZVAL_MAYBE_P(set->type));
64
if (!php_driver_validate_object(object, PHP5TO7_ZVAL_MAYBE_P(type->data.set.value_type) TSRMLS_CC)) {
68
HASH_FIND_ZVAL(set->entries, object, entry);
71
if (entry == set->iter_temp) {
72
set->iter_temp = (php_driver_set_entry *)set->iter_temp->hh.next;
74
HASH_DEL(set->entries, entry);
75
zval_ptr_dtor(&entry->value);
84
php_driver_set_has(php_driver_set *set, zval *object TSRMLS_DC)
86
php_driver_set_entry *entry;
87
php_driver_type *type;
90
type = PHP_DRIVER_GET_TYPE(PHP5TO7_ZVAL_MAYBE_P(set->type));
92
if (!php_driver_validate_object(object, PHP5TO7_ZVAL_MAYBE_P(type->data.set.value_type) TSRMLS_CC)) {
96
HASH_FIND_ZVAL(set->entries, object, entry);
105
php_driver_set_populate(php_driver_set *set, zval *array TSRMLS_DC)
107
php_driver_set_entry *curr, *temp;
108
HASH_ITER(hh, set->entries, curr, temp) {
109
if (add_next_index_zval(array, PHP5TO7_ZVAL_MAYBE_P(curr->value)) != SUCCESS) {
112
Z_TRY_ADDREF_P(PHP5TO7_ZVAL_MAYBE_P(curr->value));
116
/* {{{ Set::__construct(type) */
117
PHP_METHOD(Set, __construct)
119
php_driver_set *self;
122
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &type) == FAILURE)
125
self = PHP_DRIVER_GET_SET(getThis());
127
if (Z_TYPE_P(type) == IS_STRING) {
128
CassValueType value_type;
129
if (!php_driver_value_type(Z_STRVAL_P(type), &value_type TSRMLS_CC))
131
self->type = php_driver_type_set_from_value_type(value_type TSRMLS_CC);
132
} else if (Z_TYPE_P(type) == IS_OBJECT &&
133
instanceof_function(Z_OBJCE_P(type), php_driver_type_ce TSRMLS_CC)) {
134
if (!php_driver_type_validate(type, "type" TSRMLS_CC)) {
137
self->type = php_driver_type_set(type TSRMLS_CC);
140
INVALID_ARGUMENT(type, "a string or an instance of " PHP_DRIVER_NAMESPACE "\\Type");
145
/* {{{ Set::type() */
146
PHP_METHOD(Set, type)
148
php_driver_set *self = PHP_DRIVER_GET_SET(getThis());
149
RETURN_ZVAL(PHP5TO7_ZVAL_MAYBE_P(self->type), 1, 0);
153
/* {{{ Set::values() */
154
PHP_METHOD(Set, values)
156
php_driver_set *set = NULL;
157
array_init(return_value);
158
set = PHP_DRIVER_GET_SET(getThis());
159
php_driver_set_populate(set, return_value TSRMLS_CC);
163
/* {{{ Set::add(value) */
166
php_driver_set *self = NULL;
169
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &object) == FAILURE)
172
self = PHP_DRIVER_GET_SET(getThis());
174
if (php_driver_set_add(self, object TSRMLS_CC))
181
/* {{{ Set::remove(value) */
182
PHP_METHOD(Set, remove)
184
php_driver_set *self = NULL;
187
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &object) == FAILURE)
190
self = PHP_DRIVER_GET_SET(getThis());
192
if (php_driver_set_del(self, object TSRMLS_CC))
199
/* {{{ Set::has(value) */
202
php_driver_set *self = NULL;
205
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &object) == FAILURE)
208
self = PHP_DRIVER_GET_SET(getThis());
210
if (php_driver_set_has(self, object TSRMLS_CC))
217
/* {{{ Set::count() */
218
PHP_METHOD(Set, count)
220
php_driver_set *self = PHP_DRIVER_GET_SET(getThis());
221
RETURN_LONG((long)HASH_COUNT(self->entries));
225
/* {{{ Set::current() */
226
PHP_METHOD(Set, current)
228
php_driver_set *self = PHP_DRIVER_GET_SET(getThis());
229
if (self->iter_curr != NULL)
230
RETURN_ZVAL(PHP5TO7_ZVAL_MAYBE_P(self->iter_curr->value), 1, 0);
237
php_driver_set *self = PHP_DRIVER_GET_SET(getThis());
238
RETURN_LONG(self->iter_index);
242
/* {{{ Set::next() */
243
PHP_METHOD(Set, next)
245
php_driver_set *self = PHP_DRIVER_GET_SET(getThis());
246
self->iter_curr = self->iter_temp;
247
self->iter_temp = self->iter_temp != NULL ? (php_driver_set_entry *)self->iter_temp->hh.next : NULL;
252
/* {{{ Set::valid() */
253
PHP_METHOD(Set, valid)
255
php_driver_set *self = PHP_DRIVER_GET_SET(getThis());
256
RETURN_BOOL(self->iter_curr != NULL);
260
/* {{{ Set::rewind() */
261
PHP_METHOD(Set, rewind)
263
php_driver_set *self = PHP_DRIVER_GET_SET(getThis());
264
self->iter_curr = self->entries;
265
self->iter_temp = self->entries != NULL ? (php_driver_set_entry *)self->entries->hh.next : NULL;
266
self->iter_index = 0;
270
ZEND_BEGIN_ARG_INFO_EX(arginfo__construct, 0, ZEND_RETURN_VALUE, 1)
271
ZEND_ARG_INFO(0, type)
274
ZEND_BEGIN_ARG_INFO_EX(arginfo_one, 0, ZEND_RETURN_VALUE, 1)
275
ZEND_ARG_INFO(0, value)
278
ZEND_BEGIN_ARG_INFO_EX(arginfo_none, 0, ZEND_RETURN_VALUE, 0)
281
static zend_function_entry php_driver_set_methods[] = {
282
PHP_ME(Set, __construct, arginfo__construct, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC)
283
PHP_ME(Set, type, arginfo_none, ZEND_ACC_PUBLIC)
284
PHP_ME(Set, values, arginfo_none, ZEND_ACC_PUBLIC)
285
PHP_ME(Set, add, arginfo_one, ZEND_ACC_PUBLIC)
286
PHP_ME(Set, has, arginfo_one, ZEND_ACC_PUBLIC)
287
PHP_ME(Set, remove, arginfo_one, ZEND_ACC_PUBLIC)
289
PHP_ME(Set, count, arginfo_none, ZEND_ACC_PUBLIC)
291
PHP_ME(Set, current, arginfo_none, ZEND_ACC_PUBLIC)
292
PHP_ME(Set, key, arginfo_none, ZEND_ACC_PUBLIC)
293
PHP_ME(Set, next, arginfo_none, ZEND_ACC_PUBLIC)
294
PHP_ME(Set, valid, arginfo_none, ZEND_ACC_PUBLIC)
295
PHP_ME(Set, rewind, arginfo_none, ZEND_ACC_PUBLIC)
299
static php_driver_value_handlers php_driver_set_handlers;
302
php_driver_set_gc(zval *object, php5to7_zval_gc table, int *n TSRMLS_DC)
306
return zend_std_get_properties(object TSRMLS_CC);
310
php_driver_set_properties(zval *object TSRMLS_DC)
314
php_driver_set *self = PHP_DRIVER_GET_SET(object);
315
HashTable *props = zend_std_get_properties(object TSRMLS_CC);
318
PHP5TO7_ZEND_HASH_UPDATE(props,
319
"type", sizeof("type"),
320
PHP5TO7_ZVAL_MAYBE_P(self->type), sizeof(zval));
321
Z_ADDREF_P(PHP5TO7_ZVAL_MAYBE_P(self->type));
323
PHP5TO7_ZVAL_MAYBE_MAKE(values);
324
array_init(PHP5TO7_ZVAL_MAYBE_P(values));
325
php_driver_set_populate(self , PHP5TO7_ZVAL_MAYBE_P(values) TSRMLS_CC);
326
PHP5TO7_ZEND_HASH_SORT(Z_ARRVAL_P(PHP5TO7_ZVAL_MAYBE_P(values)), php_driver_data_compare, 1);
327
PHP5TO7_ZEND_HASH_UPDATE(props, "values", sizeof("values"), PHP5TO7_ZVAL_MAYBE_P(values), sizeof(zval));
333
php_driver_set_compare(zval *obj1, zval *obj2 TSRMLS_DC)
335
php_driver_set_entry *curr, *temp;
336
php_driver_set *set1;
337
php_driver_set *set2;
338
php_driver_type *type1;
339
php_driver_type *type2;
342
if (Z_OBJCE_P(obj1) != Z_OBJCE_P(obj2))
343
return 1; /* different classes */
345
set1 = PHP_DRIVER_GET_SET(obj1);
346
set2 = PHP_DRIVER_GET_SET(obj2);
348
type1 = PHP_DRIVER_GET_TYPE(PHP5TO7_ZVAL_MAYBE_P(set1->type));
349
type2 = PHP_DRIVER_GET_TYPE(PHP5TO7_ZVAL_MAYBE_P(set2->type));
351
result = php_driver_type_compare(type1, type2 TSRMLS_CC);
352
if (result != 0) return result;
354
if (HASH_COUNT(set1->entries) != HASH_COUNT(set1->entries)) {
355
return HASH_COUNT(set1->entries) < HASH_COUNT(set1->entries) ? -1 : 1;
358
HASH_ITER(hh, set1->entries, curr, temp) {
359
php_driver_set_entry *entry;
360
HASH_FIND_ZVAL(set2->entries, PHP5TO7_ZVAL_MAYBE_P(curr->value), entry);
370
php_driver_set_hash_value(zval *obj TSRMLS_DC)
373
php_driver_set_entry *curr, *temp;
374
php_driver_set *self = PHP_DRIVER_GET_SET(obj);
376
if (!self->dirty) return self->hashv;
378
HASH_ITER(hh, self->entries, curr, temp) {
379
hashv = php_driver_combine_hash(hashv, php_driver_value_hash(PHP5TO7_ZVAL_MAYBE_P(curr->value) TSRMLS_CC));
389
php_driver_set_free(php5to7_zend_object_free *object TSRMLS_DC)
391
php_driver_set *self = PHP5TO7_ZEND_OBJECT_GET(set, object);
392
php_driver_set_entry *curr, *temp;
394
HASH_ITER(hh, self->entries, curr, temp) {
395
zval_ptr_dtor(&curr->value);
396
HASH_DEL(self->entries, curr);
400
PHP5TO7_ZVAL_MAYBE_DESTROY(self->type);
402
zend_object_std_dtor(&self->zval TSRMLS_CC);
403
PHP5TO7_MAYBE_EFREE(self);
406
static php5to7_zend_object
407
php_driver_set_new(zend_class_entry *ce TSRMLS_DC)
409
php_driver_set *self =
410
PHP5TO7_ZEND_OBJECT_ECALLOC(set, ce);
412
self->entries = self->iter_curr = self->iter_temp = NULL;
413
self->iter_index = 0;
415
PHP5TO7_ZVAL_UNDEF(self->type);
417
PHP5TO7_ZEND_OBJECT_INIT(set, self, ce);
420
void php_driver_define_Set(TSRMLS_D)
424
INIT_CLASS_ENTRY(ce, PHP_DRIVER_NAMESPACE "\\Set", php_driver_set_methods);
425
php_driver_set_ce = zend_register_internal_class(&ce TSRMLS_CC);
426
zend_class_implements(php_driver_set_ce TSRMLS_CC, 1, php_driver_value_ce);
427
memcpy(&php_driver_set_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
428
php_driver_set_handlers.std.get_properties = php_driver_set_properties;
429
#if PHP_VERSION_ID >= 50400
430
php_driver_set_handlers.std.get_gc = php_driver_set_gc;
432
php_driver_set_handlers.std.compare_objects = php_driver_set_compare;
433
php_driver_set_ce->ce_flags |= PHP5TO7_ZEND_ACC_FINAL;
434
php_driver_set_ce->create_object = php_driver_set_new;
435
zend_class_implements(php_driver_set_ce TSRMLS_CC, 2, spl_ce_Countable, zend_ce_iterator);
437
php_driver_set_handlers.hash_value = php_driver_set_hash_value;
438
php_driver_set_handlers.std.clone_obj = NULL;