~ubuntu-branches/debian/sid/php-cassandra/sid

« back to all changes in this revision

Viewing changes to cassandra-1.3.0/src/Duration.c

  • Committer: Package Import Robot
  • Author(s): Ondřej Surý
  • Date: 2017-04-18 17:16:30 UTC
  • Revision ID: package-import@ubuntu.com-20170418171630-fw8udixss0879s32
Tags: upstream-1.3.0
Import upstream version 1.3.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "php_driver.h"
 
2
#include "php_driver_globals.h"
 
3
#include "php_driver_types.h"
 
4
 
 
5
#include "util/hash.h"
 
6
#include "util/math.h"
 
7
#include "util/types.h"
 
8
 
 
9
#include "Duration.h"
 
10
 
 
11
#if !defined(HAVE_STDINT_H) && !defined(_MSC_STDINT_H_)
 
12
#  define INT32_MAX 2147483647L
 
13
#  define INT32_MIN (-INT32_MAX-1)
 
14
#endif
 
15
 
 
16
zend_class_entry *php_driver_duration_ce = NULL;
 
17
 
 
18
static void to_string(zval *result, cass_int32_t value)
 
19
{
 
20
  char *string;
 
21
  spprintf(&string, 0, "%d", value);
 
22
  PHP5TO7_ZVAL_STRING(result, string);
 
23
  efree(string);
 
24
}
 
25
 
 
26
static int get_int32(zval* value, cass_int32_t* destination, const char* param_name TSRMLS_DC)
 
27
{
 
28
  // Adapted from Bigint __construct method.
 
29
  if (Z_TYPE_P(value) == IS_LONG) {
 
30
    cass_int64_t long_value = Z_LVAL_P(value);
 
31
 
 
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);
 
36
      return 0;
 
37
    }
 
38
 
 
39
    *destination = long_value;
 
40
  } else if (Z_TYPE_P(value) == IS_DOUBLE) {
 
41
    double double_value = Z_DVAL_P(value);
 
42
 
 
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);
 
47
      return 0;
 
48
    }
 
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)) {
 
53
      return 0;
 
54
    }
 
55
 
 
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);
 
60
      return 0;
 
61
    }
 
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;
 
67
 
 
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);
 
72
      return 0;
 
73
    }
 
74
 
 
75
    *destination = (cass_int32_t) bigint_value;
 
76
  } else {
 
77
    throw_invalid_argument(value, param_name, "a long, a double, a numeric string or a " \
 
78
                            PHP_DRIVER_NAMESPACE "\\Bigint" TSRMLS_CC);
 
79
    return 0;
 
80
  }
 
81
  return 1;
 
82
}
 
83
 
 
84
char *php_driver_duration_to_string(php_driver_duration *duration)
 
85
{
 
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
 
88
  // -3mo2d1ns.
 
89
 
 
90
  char* rep;
 
91
  int is_negative = 0;
 
92
  cass_int32_t final_months = duration->months;
 
93
  cass_int32_t final_days = duration->days;
 
94
  cass_int32_t final_nanos = duration->nanos;
 
95
  
 
96
  is_negative = final_months < 0 || final_days < 0 || final_nanos < 0;
 
97
  if (final_months < 0)
 
98
    final_months = -final_months;
 
99
  if (final_days < 0)
 
100
    final_days = -final_days;
 
101
  if (final_nanos < 0)
 
102
    final_nanos = -final_nanos;
 
103
  
 
104
  spprintf(&rep, 0, "%s%dmo%dd%dns", is_negative ? "-" : "", final_months, final_days, final_nanos);
 
105
  return rep;
 
106
}
 
107
 
 
108
void
 
109
php_driver_duration_init(INTERNAL_FUNCTION_PARAMETERS)
 
110
{
 
111
  zval *months, *days, *nanos;
 
112
  php_driver_duration *self = NULL;
 
113
 
 
114
  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zzz", &months, &days, &nanos) == FAILURE) {
 
115
    return;
 
116
  }
 
117
 
 
118
  self = PHP_DRIVER_GET_DURATION(getThis());
 
119
 
 
120
  if (!get_int32(months, &self->months, "months" TSRMLS_CC)) {
 
121
    return;
 
122
  }
 
123
  if (!get_int32(days, &self->days, "days" TSRMLS_CC)) {
 
124
    return;
 
125
  }
 
126
 
 
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);
 
130
 
 
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"
 
136
    );
 
137
  }
 
138
}
 
139
 
 
140
PHP_METHOD(Duration, __construct)
 
141
{
 
142
  php_driver_duration_init(INTERNAL_FUNCTION_PARAM_PASSTHRU);
 
143
}
 
144
 
 
145
PHP_METHOD(Duration, __toString)
 
146
{
 
147
  char* rep;
 
148
  php_driver_duration *self = NULL;
 
149
 
 
150
  if (zend_parse_parameters_none() == FAILURE)
 
151
    return;
 
152
 
 
153
  self = PHP_DRIVER_GET_DURATION(getThis());
 
154
 
 
155
  // Build up string representation of this duration.
 
156
  rep = php_driver_duration_to_string(self);
 
157
  PHP5TO7_RETVAL_STRING(rep);
 
158
  efree(rep);
 
159
}
 
160
 
 
161
PHP_METHOD(Duration, type)
 
162
{
 
163
  php5to7_zval type = php_driver_type_scalar(CASS_VALUE_TYPE_DURATION TSRMLS_CC);
 
164
  RETURN_ZVAL(PHP5TO7_ZVAL_MAYBE_P(type), 1, 1);
 
165
}
 
166
 
 
167
PHP_METHOD(Duration, months)
 
168
{
 
169
  php_driver_duration *self = NULL;
 
170
 
 
171
  if (zend_parse_parameters_none() == FAILURE)
 
172
    return;
 
173
 
 
174
  self = PHP_DRIVER_GET_DURATION(getThis());
 
175
  to_string(return_value, self->months);
 
176
}
 
177
 
 
178
PHP_METHOD(Duration, days)
 
179
{
 
180
  php_driver_duration *self = NULL;
 
181
 
 
182
  if (zend_parse_parameters_none() == FAILURE)
 
183
    return;
 
184
 
 
185
  self = PHP_DRIVER_GET_DURATION(getThis());
 
186
  to_string(return_value, self->days);
 
187
}
 
188
 
 
189
PHP_METHOD(Duration, nanos)
 
190
{
 
191
  php_driver_duration *self = NULL;
 
192
 
 
193
  if (zend_parse_parameters_none() == FAILURE)
 
194
    return;
 
195
 
 
196
  self = PHP_DRIVER_GET_DURATION(getThis());
 
197
  to_string(return_value, self->nanos);
 
198
}
 
199
 
 
200
ZEND_BEGIN_ARG_INFO_EX(arginfo_none, 0, ZEND_RETURN_VALUE, 0)
 
201
ZEND_END_ARG_INFO()
 
202
 
 
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)
 
207
ZEND_END_ARG_INFO()
 
208
 
 
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)
 
216
  PHP_FE_END
 
217
};
 
218
 
 
219
static php_driver_value_handlers php_driver_duration_handlers;
 
220
 
 
221
static HashTable *
 
222
php_driver_duration_properties(zval *object TSRMLS_DC)
 
223
{
 
224
  HashTable *props = zend_std_get_properties(object TSRMLS_CC);
 
225
  php_driver_duration  *self = PHP_DRIVER_GET_DURATION(object);
 
226
 
 
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));
 
237
 
 
238
  return props;
 
239
}
 
240
 
 
241
static int
 
242
php_driver_duration_compare(zval *obj1, zval *obj2 TSRMLS_DC)
 
243
{
 
244
  php_driver_duration *left, *right;
 
245
 
 
246
  if (Z_OBJCE_P(obj1) != Z_OBJCE_P(obj2))
 
247
    return 1; /* different classes */
 
248
 
 
249
  left = PHP_DRIVER_GET_DURATION(obj1);
 
250
  right = PHP_DRIVER_GET_DURATION(obj2);
 
251
 
 
252
  // Comparisons compare months, then days, then nanos.
 
253
 
 
254
  if (left->months < right->months)
 
255
    return -1;
 
256
 
 
257
  if (left->months > right->months)
 
258
    return 1;
 
259
 
 
260
  // months are the same; compare days.
 
261
  if (left->days < right->days)
 
262
    return -1;
 
263
 
 
264
  if (left->days > right->days)
 
265
    return 1;
 
266
 
 
267
  // days are the same; compare nanos.
 
268
  if (left->nanos < right->nanos)
 
269
    return -1;
 
270
 
 
271
  return (left->nanos == right->nanos) ? 0 : 1;
 
272
}
 
273
 
 
274
static unsigned
 
275
php_driver_duration_hash_value(zval *obj TSRMLS_DC)
 
276
{
 
277
  php_driver_duration *self = PHP_DRIVER_GET_DURATION(obj);
 
278
  unsigned hashv = 0;
 
279
 
 
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);
 
283
 
 
284
  return hashv;
 
285
}
 
286
 
 
287
static void
 
288
php_driver_duration_free(php5to7_zend_object_free *object TSRMLS_DC)
 
289
{
 
290
  php_driver_duration *self = PHP5TO7_ZEND_OBJECT_GET(duration, object);
 
291
 
 
292
  /* Clean up */
 
293
 
 
294
  zend_object_std_dtor(&self->zval TSRMLS_CC);
 
295
  PHP5TO7_MAYBE_EFREE(self);
 
296
}
 
297
 
 
298
static php5to7_zend_object
 
299
php_driver_duration_new(zend_class_entry *ce TSRMLS_DC)
 
300
{
 
301
  php_driver_duration *self = PHP5TO7_ZEND_OBJECT_ECALLOC(duration, ce);
 
302
  PHP5TO7_ZEND_OBJECT_INIT(duration, self, ce);
 
303
}
 
304
 
 
305
void php_driver_define_Duration(TSRMLS_D)
 
306
{
 
307
  zend_class_entry ce;
 
308
 
 
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);
 
312
 
 
313
  php_driver_duration_ce->ce_flags     |= PHP5TO7_ZEND_ACC_FINAL;
 
314
  php_driver_duration_ce->create_object = php_driver_duration_new;
 
315
 
 
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;
 
319
 
 
320
  php_driver_duration_handlers.hash_value = php_driver_duration_hash_value;
 
321
  php_driver_duration_handlers.std.clone_obj = NULL;
 
322
}