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