• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright 2015 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /**
20  * class Timeval
21  * @see https://github.com/grpc/grpc/tree/master/src/php/ext/grpc/timeval.c
22  */
23 
24 #include "timeval.h"
25 
26 #include <ext/spl/spl_exceptions.h>
27 #include <zend_exceptions.h>
28 
29 zend_class_entry *grpc_ce_timeval;
30 PHP_GRPC_DECLARE_OBJECT_HANDLER(timeval_ce_handlers)
31 
32 /* Frees and destroys an instance of wrapped_grpc_call */
PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_timeval)33 PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_timeval)
34 PHP_GRPC_FREE_WRAPPED_FUNC_END()
35 
36 /* Initializes an instance of wrapped_grpc_timeval to be associated with an
37  * object of a class specified by class_type */
38 php_grpc_zend_object create_wrapped_grpc_timeval(zend_class_entry *class_type
39                                                  TSRMLS_DC) {
40   PHP_GRPC_ALLOC_CLASS_OBJECT(wrapped_grpc_timeval);
41   zend_object_std_init(&intern->std, class_type TSRMLS_CC);
42   object_properties_init(&intern->std, class_type);
43   PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_timeval, timeval_ce_handlers);
44 }
45 
grpc_php_wrap_timeval(gpr_timespec wrapped TSRMLS_DC)46 zval *grpc_php_wrap_timeval(gpr_timespec wrapped TSRMLS_DC) {
47   zval *timeval_object;
48   PHP_GRPC_MAKE_STD_ZVAL(timeval_object);
49   object_init_ex(timeval_object, grpc_ce_timeval);
50   wrapped_grpc_timeval *timeval =
51     PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, timeval_object);
52   memcpy(&timeval->wrapped, &wrapped, sizeof(gpr_timespec));
53   return timeval_object;
54 }
55 
56 /**
57  * Constructs a new instance of the Timeval class
58  * @param number $microseconds The number of microseconds in the interval
59  */
PHP_METHOD(Timeval,__construct)60 PHP_METHOD(Timeval, __construct) {
61   wrapped_grpc_timeval *timeval =
62     PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, getThis());
63   int64_t microseconds = 0;
64 
65   /* parse $microseconds as long */
66   if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
67                                ZEND_NUM_ARGS() TSRMLS_CC, "l",
68                                &microseconds) == FAILURE) {
69     double microsecondsDouble = 0.0;
70     /* parse $microseconds as double */
71     if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
72                               ZEND_NUM_ARGS() TSRMLS_CC, "d",
73                               &microsecondsDouble) == FAILURE) {
74       zend_throw_exception(spl_ce_InvalidArgumentException,
75                            "Timeval expects a long or double", 1 TSRMLS_CC);
76       return;
77     }
78     microseconds = (int64_t)microsecondsDouble;
79   }
80   gpr_timespec time = gpr_time_from_micros(microseconds, GPR_TIMESPAN);
81   memcpy(&timeval->wrapped, &time, sizeof(gpr_timespec));
82 }
83 
84 /**
85  * Adds another Timeval to this one and returns the sum. Calculations saturate
86  * at infinities.
87  * @param Timeval $other_obj The other Timeval object to add
88  * @return Timeval A new Timeval object containing the sum
89  */
PHP_METHOD(Timeval,add)90 PHP_METHOD(Timeval, add) {
91   zval *other_obj;
92 
93   /* "O" == 1 Object */
94   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &other_obj,
95                             grpc_ce_timeval) == FAILURE) {
96     zend_throw_exception(spl_ce_InvalidArgumentException,
97                          "add expects a Timeval", 1 TSRMLS_CC);
98     return;
99   }
100   wrapped_grpc_timeval *self =
101     PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, getThis());
102   wrapped_grpc_timeval *other =
103     PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, other_obj);
104   zval *sum =
105     grpc_php_wrap_timeval(gpr_time_add(self->wrapped, other->wrapped)
106                           TSRMLS_CC);
107   RETURN_DESTROY_ZVAL(sum);
108 }
109 
110 /**
111  * Subtracts another Timeval from this one and returns the difference.
112  * Calculations saturate at infinities.
113  * @param Timeval $other_obj The other Timeval object to subtract
114  * @return Timeval A new Timeval object containing the diff
115  */
PHP_METHOD(Timeval,subtract)116 PHP_METHOD(Timeval, subtract) {
117   zval *other_obj;
118 
119   /* "O" == 1 Object */
120   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &other_obj,
121                             grpc_ce_timeval) == FAILURE) {
122     zend_throw_exception(spl_ce_InvalidArgumentException,
123                          "subtract expects a Timeval", 1 TSRMLS_CC);
124     return;
125   }
126   wrapped_grpc_timeval *self =
127     PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, getThis());
128   wrapped_grpc_timeval *other =
129     PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, other_obj);
130   zval *diff =
131     grpc_php_wrap_timeval(gpr_time_sub(self->wrapped, other->wrapped)
132                           TSRMLS_CC);
133   RETURN_DESTROY_ZVAL(diff);
134 }
135 
136 /**
137  * Return negative, 0, or positive according to whether a < b, a == b,
138  * or a > b respectively.
139  * @param Timeval $a_obj The first time to compare
140  * @param Timeval $b_obj The second time to compare
141  * @return long
142  */
PHP_METHOD(Timeval,compare)143 PHP_METHOD(Timeval, compare) {
144   zval *a_obj;
145   zval *b_obj;
146 
147   /* "OO" == 2 Objects */
148   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &a_obj,
149                             grpc_ce_timeval, &b_obj,
150                             grpc_ce_timeval) == FAILURE) {
151     zend_throw_exception(spl_ce_InvalidArgumentException,
152                          "compare expects two Timevals", 1 TSRMLS_CC);
153     return;
154   }
155   wrapped_grpc_timeval *a =
156     PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, a_obj);
157   wrapped_grpc_timeval *b =
158     PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, b_obj);
159   long result = gpr_time_cmp(a->wrapped, b->wrapped);
160   RETURN_LONG(result);
161 }
162 
163 /**
164  * Checks whether the two times are within $threshold of each other
165  * @param Timeval $a_obj The first time to compare
166  * @param Timeval $b_obj The second time to compare
167  * @param Timeval $thresh_obj The threshold to check against
168  * @return bool True if $a and $b are within $threshold, False otherwise
169  */
PHP_METHOD(Timeval,similar)170 PHP_METHOD(Timeval, similar) {
171   zval *a_obj;
172   zval *b_obj;
173   zval *thresh_obj;
174 
175   /* "OOO" == 3 Objects */
176   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OOO", &a_obj,
177                             grpc_ce_timeval, &b_obj, grpc_ce_timeval,
178                             &thresh_obj, grpc_ce_timeval) == FAILURE) {
179     zend_throw_exception(spl_ce_InvalidArgumentException,
180                          "compare expects three Timevals", 1 TSRMLS_CC);
181     return;
182   }
183   wrapped_grpc_timeval *a =
184     PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, a_obj);
185   wrapped_grpc_timeval *b =
186     PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, b_obj);
187   wrapped_grpc_timeval *thresh =
188     PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, thresh_obj);
189   int result = gpr_time_similar(a->wrapped, b->wrapped, thresh->wrapped);
190   RETURN_BOOL(result);
191 }
192 
193 /**
194  * Returns the current time as a timeval object
195  * @return Timeval The current time
196  */
PHP_METHOD(Timeval,now)197 PHP_METHOD(Timeval, now) {
198   zval *now = grpc_php_wrap_timeval(gpr_now(GPR_CLOCK_REALTIME) TSRMLS_CC);
199   RETURN_DESTROY_ZVAL(now);
200 }
201 
202 /**
203  * Returns the zero time interval as a timeval object
204  * @return Timeval Zero length time interval
205  */
PHP_METHOD(Timeval,zero)206 PHP_METHOD(Timeval, zero) {
207   zval *grpc_php_timeval_zero =
208     grpc_php_wrap_timeval(gpr_time_0(GPR_CLOCK_REALTIME) TSRMLS_CC);
209   RETURN_DESTROY_ZVAL(grpc_php_timeval_zero);
210 }
211 
212 /**
213  * Returns the infinite future time value as a timeval object
214  * @return Timeval Infinite future time value
215  */
PHP_METHOD(Timeval,infFuture)216 PHP_METHOD(Timeval, infFuture) {
217   zval *grpc_php_timeval_inf_future =
218     grpc_php_wrap_timeval(gpr_inf_future(GPR_CLOCK_REALTIME) TSRMLS_CC);
219   RETURN_DESTROY_ZVAL(grpc_php_timeval_inf_future);
220 }
221 
222 /**
223  * Returns the infinite past time value as a timeval object
224  * @return Timeval Infinite past time value
225  */
PHP_METHOD(Timeval,infPast)226 PHP_METHOD(Timeval, infPast) {
227   zval *grpc_php_timeval_inf_past =
228     grpc_php_wrap_timeval(gpr_inf_past(GPR_CLOCK_REALTIME) TSRMLS_CC);
229   RETURN_DESTROY_ZVAL(grpc_php_timeval_inf_past);
230 }
231 
232 /**
233  * Sleep until this time, interpreted as an absolute timeout
234  * @return void
235  */
PHP_METHOD(Timeval,sleepUntil)236 PHP_METHOD(Timeval, sleepUntil) {
237   wrapped_grpc_timeval *this =
238     PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, getThis());
239   gpr_sleep_until(this->wrapped);
240 }
241 
242 ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 1)
243   ZEND_ARG_INFO(0, microseconds)
244 ZEND_END_ARG_INFO()
245 
246 ZEND_BEGIN_ARG_INFO_EX(arginfo_add, 0, 0, 1)
247   ZEND_ARG_INFO(0, timeval)
248 ZEND_END_ARG_INFO()
249 
250 ZEND_BEGIN_ARG_INFO_EX(arginfo_compare, 0, 0, 2)
251   ZEND_ARG_INFO(0, a_timeval)
252   ZEND_ARG_INFO(0, b_timeval)
253 ZEND_END_ARG_INFO()
254 
255 ZEND_BEGIN_ARG_INFO_EX(arginfo_infFuture, 0, 0, 0)
256 ZEND_END_ARG_INFO()
257 
258 ZEND_BEGIN_ARG_INFO_EX(arginfo_infPast, 0, 0, 0)
259 ZEND_END_ARG_INFO()
260 
261 ZEND_BEGIN_ARG_INFO_EX(arginfo_now, 0, 0, 0)
262 ZEND_END_ARG_INFO()
263 
264 ZEND_BEGIN_ARG_INFO_EX(arginfo_similar, 0, 0, 3)
265   ZEND_ARG_INFO(0, a_timeval)
266   ZEND_ARG_INFO(0, b_timeval)
267   ZEND_ARG_INFO(0, threshold_timeval)
268 ZEND_END_ARG_INFO()
269 
270 ZEND_BEGIN_ARG_INFO_EX(arginfo_sleepUntil, 0, 0, 0)
271 ZEND_END_ARG_INFO()
272 
273 ZEND_BEGIN_ARG_INFO_EX(arginfo_subtract, 0, 0, 1)
274   ZEND_ARG_INFO(0, timeval)
275 ZEND_END_ARG_INFO()
276 
277 ZEND_BEGIN_ARG_INFO_EX(arginfo_zero, 0, 0, 0)
278 ZEND_END_ARG_INFO()
279 
280 static zend_function_entry timeval_methods[] = {
281   PHP_ME(Timeval, __construct, arginfo_construct,
282          ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
283   PHP_ME(Timeval, add, arginfo_add,
284          ZEND_ACC_PUBLIC)
285   PHP_ME(Timeval, compare, arginfo_compare,
286          ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
287   PHP_ME(Timeval, infFuture, arginfo_infFuture,
288          ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
289   PHP_ME(Timeval, infPast, arginfo_infPast,
290          ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
291   PHP_ME(Timeval, now, arginfo_now,
292          ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
293   PHP_ME(Timeval, similar, arginfo_similar,
294          ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
295   PHP_ME(Timeval, sleepUntil, arginfo_sleepUntil,
296          ZEND_ACC_PUBLIC)
297   PHP_ME(Timeval, subtract, arginfo_subtract,
298          ZEND_ACC_PUBLIC)
299   PHP_ME(Timeval, zero, arginfo_zero,
300          ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
301   PHP_FE_END
302 };
303 
grpc_init_timeval(TSRMLS_D)304 void grpc_init_timeval(TSRMLS_D) {
305   zend_class_entry ce;
306   INIT_CLASS_ENTRY(ce, "Grpc\\Timeval", timeval_methods);
307   ce.create_object = create_wrapped_grpc_timeval;
308   grpc_ce_timeval = zend_register_internal_class(&ce TSRMLS_CC);
309   PHP_GRPC_INIT_HANDLER(wrapped_grpc_timeval, timeval_ce_handlers);
310 }
311 
grpc_shutdown_timeval(TSRMLS_D)312 void grpc_shutdown_timeval(TSRMLS_D) {}
313