1
#include "php_driver.h"
2
#include "php_driver_globals.h"
3
#include "php_driver_types.h"
7
#include "util/types.h"
11
#if !defined(HAVE_STDINT_H) && !defined(_MSC_STDINT_H_)
12
# define INT32_MAX 2147483647L
13
# define INT32_MIN (-INT32_MAX-1)
16
zend_class_entry *php_driver_duration_ce = NULL;
18
static void to_string(zval *result, cass_int32_t value)
21
spprintf(&string, 0, "%d", value);
22
PHP5TO7_ZVAL_STRING(result, string);
26
static int get_int32(zval* value, cass_int32_t* destination, const char* param_name TSRMLS_DC)
28
// Adapted from Bigint __construct method.
29
if (Z_TYPE_P(value) == IS_LONG) {
30
cass_int64_t long_value = Z_LVAL_P(value);
32
if (long_value > INT32_MAX || long_value < INT32_MIN) {
33
zend_throw_exception_ex(php_driver_range_exception_ce, 0 TSRMLS_CC,
34
"%s must be between %d and %d, " LL_FORMAT " given",
35
param_name, INT32_MIN, INT32_MAX, long_value);
39
*destination = long_value;
40
} else if (Z_TYPE_P(value) == IS_DOUBLE) {
41
double double_value = Z_DVAL_P(value);
43
if (double_value > INT32_MAX || double_value < INT32_MIN) {
44
zend_throw_exception_ex(php_driver_range_exception_ce, 0 TSRMLS_CC,
45
"%s must be between %d and %d, %g given",
46
param_name, INT32_MIN, INT32_MAX, double_value);
49
*destination = (cass_int32_t) double_value;
50
} else if (Z_TYPE_P(value) == IS_STRING) {
51
cass_int64_t parsed_big_int;
52
if (!php_driver_parse_bigint(Z_STRVAL_P(value), Z_STRLEN_P(value), &parsed_big_int TSRMLS_CC)) {
56
if (parsed_big_int > INT32_MAX || parsed_big_int < INT32_MIN) {
57
zend_throw_exception_ex(php_driver_range_exception_ce, 0 TSRMLS_CC,
58
"%s must be between %d and %d, " LL_FORMAT " given",
59
param_name, INT32_MIN, INT32_MAX, parsed_big_int);
62
*destination = (cass_int32_t) parsed_big_int;
63
} else if (Z_TYPE_P(value) == IS_OBJECT &&
64
instanceof_function(Z_OBJCE_P(value), php_driver_bigint_ce TSRMLS_CC)) {
65
php_driver_numeric *bigint = PHP_DRIVER_GET_NUMERIC(value);
66
cass_int64_t bigint_value = bigint->data.bigint.value;
68
if (bigint_value > INT32_MAX || bigint_value < INT32_MIN) {
69
zend_throw_exception_ex(php_driver_range_exception_ce, 0 TSRMLS_CC,
70
"%s must be between %d and %d, " LL_FORMAT " given",
71
param_name, INT32_MIN, INT32_MAX, bigint_value);
75
*destination = (cass_int32_t) bigint_value;
77
throw_invalid_argument(value, param_name, "a long, a double, a numeric string or a " \
78
PHP_DRIVER_NAMESPACE "\\Bigint" TSRMLS_CC);
84
char *php_driver_duration_to_string(php_driver_duration *duration)
86
// String representation of Duration is of the form -?MmoDdNns, for int M, D, N.
87
// Negative durations lead with a minus sign. So (-3, -2, -1) results in
92
cass_int32_t final_months = duration->months;
93
cass_int32_t final_days = duration->days;
94
cass_int32_t final_nanos = duration->nanos;
96
is_negative = final_months < 0 || final_days < 0 || final_nanos < 0;
98
final_months = -final_months;
100
final_days = -final_days;
102
final_nanos = -final_nanos;
104
spprintf(&rep, 0, "%s%dmo%dd%dns", is_negative ? "-" : "", final_months, final_days, final_nanos);
109
php_driver_duration_init(INTERNAL_FUNCTION_PARAMETERS)
111
zval *months, *days, *nanos;
112
php_driver_duration *self = NULL;
114
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zzz", &months, &days, &nanos) == FAILURE) {
118
self = PHP_DRIVER_GET_DURATION(getThis());
120
if (!get_int32(months, &self->months, "months" TSRMLS_CC)) {
123
if (!get_int32(days, &self->days, "days" TSRMLS_CC)) {
127
// No need to check the result of nanos parsing; get_int64 sets the exception if there's
128
// a failure, and we have no more work to do anyway.
129
get_int32(nanos, &self->nanos, "nanos" TSRMLS_CC);
131
// Verify that all three attributes are non-negative or non-positive.
132
if (!(self->months <= 0 && self->days <= 0 && self->nanos <=0) &&
133
!(self->months >= 0 && self->days >= 0 && self->nanos >=0)) {
134
zend_throw_exception_ex(spl_ce_BadFunctionCallException, 0 TSRMLS_CC, "%s",
135
"A duration must have all non-negative or non-positive attributes"
140
PHP_METHOD(Duration, __construct)
142
php_driver_duration_init(INTERNAL_FUNCTION_PARAM_PASSTHRU);
145
PHP_METHOD(Duration, __toString)
148
php_driver_duration *self = NULL;
150
if (zend_parse_parameters_none() == FAILURE)
153
self = PHP_DRIVER_GET_DURATION(getThis());
155
// Build up string representation of this duration.
156
rep = php_driver_duration_to_string(self);
157
PHP5TO7_RETVAL_STRING(rep);
161
PHP_METHOD(Duration, type)
163
php5to7_zval type = php_driver_type_scalar(CASS_VALUE_TYPE_DURATION TSRMLS_CC);
164
RETURN_ZVAL(PHP5TO7_ZVAL_MAYBE_P(type), 1, 1);
167
PHP_METHOD(Duration, months)
169
php_driver_duration *self = NULL;
171
if (zend_parse_parameters_none() == FAILURE)
174
self = PHP_DRIVER_GET_DURATION(getThis());
175
to_string(return_value, self->months);
178
PHP_METHOD(Duration, days)
180
php_driver_duration *self = NULL;
182
if (zend_parse_parameters_none() == FAILURE)
185
self = PHP_DRIVER_GET_DURATION(getThis());
186
to_string(return_value, self->days);
189
PHP_METHOD(Duration, nanos)
191
php_driver_duration *self = NULL;
193
if (zend_parse_parameters_none() == FAILURE)
196
self = PHP_DRIVER_GET_DURATION(getThis());
197
to_string(return_value, self->nanos);
200
ZEND_BEGIN_ARG_INFO_EX(arginfo_none, 0, ZEND_RETURN_VALUE, 0)
203
ZEND_BEGIN_ARG_INFO_EX(arginfo__construct, 0, ZEND_RETURN_VALUE, 3)
204
ZEND_ARG_INFO(0, months)
205
ZEND_ARG_INFO(0, days)
206
ZEND_ARG_INFO(0, nanos)
209
static zend_function_entry php_driver_duration_methods[] = {
210
PHP_ME(Duration, __construct, arginfo__construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
211
PHP_ME(Duration, type, arginfo_none, ZEND_ACC_PUBLIC)
212
PHP_ME(Duration, months, arginfo_none, ZEND_ACC_PUBLIC)
213
PHP_ME(Duration, days, arginfo_none, ZEND_ACC_PUBLIC)
214
PHP_ME(Duration, nanos, arginfo_none, ZEND_ACC_PUBLIC)
215
PHP_ME(Duration, __toString, arginfo_none, ZEND_ACC_PUBLIC)
219
static php_driver_value_handlers php_driver_duration_handlers;
222
php_driver_duration_properties(zval *object TSRMLS_DC)
224
HashTable *props = zend_std_get_properties(object TSRMLS_CC);
225
php_driver_duration *self = PHP_DRIVER_GET_DURATION(object);
227
php5to7_zval wrapped_months, wrapped_days, wrapped_nanos;
228
PHP5TO7_ZVAL_MAYBE_MAKE(wrapped_months);
229
PHP5TO7_ZVAL_MAYBE_MAKE(wrapped_days);
230
PHP5TO7_ZVAL_MAYBE_MAKE(wrapped_nanos);
231
ZVAL_LONG(PHP5TO7_ZVAL_MAYBE_P(wrapped_months), self->months);
232
ZVAL_LONG(PHP5TO7_ZVAL_MAYBE_P(wrapped_days), self->days);
233
ZVAL_LONG(PHP5TO7_ZVAL_MAYBE_P(wrapped_nanos), self->nanos);
234
PHP5TO7_ZEND_HASH_UPDATE(props, "months", sizeof("months"), PHP5TO7_ZVAL_MAYBE_P(wrapped_months), sizeof(zval));
235
PHP5TO7_ZEND_HASH_UPDATE(props, "days", sizeof("days"), PHP5TO7_ZVAL_MAYBE_P(wrapped_days), sizeof(zval));
236
PHP5TO7_ZEND_HASH_UPDATE(props, "nanos", sizeof("nanos"), PHP5TO7_ZVAL_MAYBE_P(wrapped_nanos), sizeof(zval));
242
php_driver_duration_compare(zval *obj1, zval *obj2 TSRMLS_DC)
244
php_driver_duration *left, *right;
246
if (Z_OBJCE_P(obj1) != Z_OBJCE_P(obj2))
247
return 1; /* different classes */
249
left = PHP_DRIVER_GET_DURATION(obj1);
250
right = PHP_DRIVER_GET_DURATION(obj2);
252
// Comparisons compare months, then days, then nanos.
254
if (left->months < right->months)
257
if (left->months > right->months)
260
// months are the same; compare days.
261
if (left->days < right->days)
264
if (left->days > right->days)
267
// days are the same; compare nanos.
268
if (left->nanos < right->nanos)
271
return (left->nanos == right->nanos) ? 0 : 1;
275
php_driver_duration_hash_value(zval *obj TSRMLS_DC)
277
php_driver_duration *self = PHP_DRIVER_GET_DURATION(obj);
280
hashv = php_driver_combine_hash(hashv, (unsigned) self->months);
281
hashv = php_driver_combine_hash(hashv, (unsigned) self->days);
282
hashv = php_driver_combine_hash(hashv, (unsigned) self->nanos);
288
php_driver_duration_free(php5to7_zend_object_free *object TSRMLS_DC)
290
php_driver_duration *self = PHP5TO7_ZEND_OBJECT_GET(duration, object);
294
zend_object_std_dtor(&self->zval TSRMLS_CC);
295
PHP5TO7_MAYBE_EFREE(self);
298
static php5to7_zend_object
299
php_driver_duration_new(zend_class_entry *ce TSRMLS_DC)
301
php_driver_duration *self = PHP5TO7_ZEND_OBJECT_ECALLOC(duration, ce);
302
PHP5TO7_ZEND_OBJECT_INIT(duration, self, ce);
305
void php_driver_define_Duration(TSRMLS_D)
309
INIT_CLASS_ENTRY(ce, PHP_DRIVER_NAMESPACE "\\Duration", php_driver_duration_methods);
310
php_driver_duration_ce = zend_register_internal_class(&ce TSRMLS_CC);
311
zend_class_implements(php_driver_duration_ce TSRMLS_CC, 1, php_driver_value_ce);
313
php_driver_duration_ce->ce_flags |= PHP5TO7_ZEND_ACC_FINAL;
314
php_driver_duration_ce->create_object = php_driver_duration_new;
316
memcpy(&php_driver_duration_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
317
php_driver_duration_handlers.std.get_properties = php_driver_duration_properties;
318
php_driver_duration_handlers.std.compare_objects = php_driver_duration_compare;
320
php_driver_duration_handlers.hash_value = php_driver_duration_hash_value;
321
php_driver_duration_handlers.std.clone_obj = NULL;