properly check whether an ion int/decimal fits a zend_long
[awesomized/ext-ion] / ion.c
1 /*
2 +--------------------------------------------------------------------+
3 | PECL :: ion |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the conditions mentioned |
7 | in the accompanying LICENSE file are met. |
8 +--------------------------------------------------------------------+
9 | Copyright (c) 2021, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 #ifdef HAVE_CONFIG_H
14 # include "config.h"
15 #endif
16
17 #include "php.h"
18 #include "ext/standard/info.h"
19
20 #include "Zend/zend_enum.h"
21 #include "Zend/zend_exceptions.h"
22 #include "Zend/zend_closures.h"
23 #include "Zend/zend_interfaces.h"
24 #include "Zend/zend_smart_str.h"
25
26 #include "ext/date/php_date.h"
27 #include "ext/spl/spl_exceptions.h"
28 #include "ext/spl/spl_iterators.h"
29
30 #define DECNUMDIGITS 34 /* DECQUAD_Pmax */
31 #include "ionc/ion.h"
32
33 static decContext g_dec_ctx;
34 static ION_INT *g_ion_int_zend_max, *g_ion_int_zend_min;
35 static ION_DECIMAL g_ion_dec_zend_max, g_ion_dec_zend_min;
36
37 #include "php_ion.h"
38 #define ZEND_ARG_VARIADIC_OBJ_TYPE_MASK(pass_by_ref, name, classname, type_mask, default_value) \
39 { #name, ZEND_TYPE_INIT_CLASS_CONST_MASK(#classname, type_mask | _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1, 0)), default_value },
40 #include "ion_arginfo.h"
41 #include "ion_private.h"
42
43 ZEND_METHOD(ion_Symbol_ImportLocation, __construct)
44 {
45 php_ion_symbol_iloc *obj = php_ion_obj(symbol_iloc, Z_OBJ_P(ZEND_THIS));
46 PTR_CHECK(obj);
47
48 zend_long location;
49 ZEND_PARSE_PARAMETERS_START(2, 2)
50 Z_PARAM_STR(obj->name)
51 Z_PARAM_LONG(location)
52 ZEND_PARSE_PARAMETERS_END();
53
54 obj->loc.location = location;
55 php_ion_symbol_iloc_ctor(obj);
56 }
57 ZEND_METHOD(ion_Symbol, __construct)
58 {
59 php_ion_symbol *obj = php_ion_obj(symbol, Z_OBJ_P(ZEND_THIS));
60 PTR_CHECK(obj);
61
62 zend_long sid = -1;
63 ZEND_PARSE_PARAMETERS_START(0, 3)
64 Z_PARAM_OPTIONAL
65 Z_PARAM_STR_OR_NULL(obj->value)
66 Z_PARAM_LONG(sid)
67 Z_PARAM_OBJ_OF_CLASS_OR_NULL(obj->iloc, ce_Symbol_ImportLocation)
68 ZEND_PARSE_PARAMETERS_END();
69
70 obj->sym.sid = sid;
71 php_ion_symbol_ctor(obj);
72 }
73 ZEND_METHOD(ion_Symbol, equals)
74 {
75 php_ion_symbol *sym = php_ion_obj(symbol, Z_OBJ_P(ZEND_THIS));
76 OBJ_CHECK(sym);
77
78 zend_object *other_obj;
79 ZEND_PARSE_PARAMETERS_START(1, 1)
80 Z_PARAM_OBJ_OF_CLASS(other_obj, ce_Symbol)
81 ZEND_PARSE_PARAMETERS_END();
82
83 BOOL eq = FALSE;
84 iERR err = ion_symbol_is_equal(
85 &sym->sym,
86 &php_ion_obj(symbol, other_obj)->sym, &eq);
87 ION_CHECK(err);
88 RETVAL_BOOL(eq);
89 }
90 ZEND_METHOD(ion_Symbol, __toString)
91 {
92 php_ion_symbol *sym = php_ion_obj(symbol, Z_OBJ_P(ZEND_THIS));
93 OBJ_CHECK(sym);
94
95 ZEND_PARSE_PARAMETERS_NONE();
96
97 if (!sym->value) {
98 RETURN_EMPTY_STRING();
99 }
100 RETURN_STR_COPY(sym->value);
101 }
102 ZEND_METHOD(ion_Timestamp, __construct)
103 {
104 php_ion_timestamp *obj = php_ion_obj(timestamp, Z_OBJ_P(ZEND_THIS));
105 PTR_CHECK(obj);
106
107 zend_long precision;
108 zend_object *precision_obj;
109 zend_string *fmt = NULL, *dt = NULL;
110 zval *tz = NULL;
111 ZEND_PARSE_PARAMETERS_START(1, 4)
112 Z_PARAM_OBJ_OF_CLASS_OR_LONG(precision_obj, ce_Timestamp_Precision, precision)
113 Z_PARAM_OPTIONAL
114 Z_PARAM_STR_OR_NULL(fmt)
115 Z_PARAM_STR_OR_NULL(dt)
116 Z_PARAM_ZVAL(tz)
117 ZEND_PARSE_PARAMETERS_END();
118
119 if (precision_obj) {
120 precision = Z_LVAL_P(zend_enum_fetch_case_value(precision_obj));
121 }
122 php_ion_timestamp_ctor(obj, precision, fmt, dt, tz);
123 }
124 ZEND_METHOD(ion_Timestamp, __toString)
125 {
126 php_ion_timestamp *obj = php_ion_obj(timestamp, Z_OBJ_P(ZEND_THIS));
127 OBJ_CHECK(obj);
128
129 ZEND_PARSE_PARAMETERS_NONE();
130
131 zval fmt;
132 ZVAL_NULL(&fmt);
133 zend_call_method_with_1_params(&obj->std, obj->std.ce, NULL, "format", return_value,
134 zend_read_property(obj->std.ce, &obj->std, ZEND_STRL("format"), 0, &fmt));
135 }
136 ZEND_METHOD(ion_Decimal_Context, __construct)
137 {
138 php_ion_decimal_ctx *obj = php_ion_obj(decimal_ctx, Z_OBJ_P(ZEND_THIS));
139 PTR_CHECK(obj);
140
141 zend_long bits = 128;
142 ZEND_PARSE_PARAMETERS_START(0, 1)
143 Z_PARAM_OPTIONAL
144 Z_PARAM_LONG(bits)
145 ZEND_PARSE_PARAMETERS_END();
146
147 zend_update_property_long(obj->std.ce, &obj->std, ZEND_STRL("bits"), bits);
148 php_ion_decimal_ctx_ctor(obj);
149 }
150 ZEND_METHOD(ion_Decimal, __construct)
151 {
152 php_ion_decimal *obj = php_ion_obj(decimal, Z_OBJ_P(ZEND_THIS));
153 PTR_CHECK(obj);
154
155 zend_long num;
156 zend_string *zstr;
157 ZEND_PARSE_PARAMETERS_START(1, 2)
158 Z_PARAM_STR_OR_LONG(zstr, num)
159 Z_PARAM_OPTIONAL
160 Z_PARAM_OBJ_OF_CLASS_OR_NULL(obj->ctx, ce_Decimal_Context)
161 ZEND_PARSE_PARAMETERS_END();
162
163 if (obj->ctx) {
164 GC_ADDREF(obj->ctx);
165 } else {
166 zval zdc;
167 object_init_ex(&zdc, ce_Decimal_Context);
168 obj->ctx = Z_OBJ(zdc);
169 php_ion_decimal_ctx_ctor(php_ion_obj(decimal_ctx, obj->ctx));
170 }
171
172 if (zstr) {
173 ION_CHECK(ion_decimal_from_string(&obj->dec, zstr->val,
174 obj->ctx ? &php_ion_obj(decimal_ctx, obj->ctx)->ctx : NULL));
175 } else if (num <= INT32_MAX && num >= INT32_MIN) {
176 ION_CHECK(ion_decimal_from_int32(&obj->dec, num));
177 } else if (num > 0 && num <= UINT32_MAX) {
178 ION_CHECK(ion_decimal_from_uint32(&obj->dec, num));
179 } else {
180 zend_throw_exception_ex(spl_ce_OverflowException, 0,
181 "Integer value out of bounds: " ZEND_LONG_FMT " (INT32_MIN < n < UINT32_MAX)", num);
182 return;
183 }
184
185 php_ion_decimal_ctor(obj);
186 OBJ_RELEASE(obj->ctx);
187 }
188 ZEND_METHOD(ion_Decimal, equals)
189 {
190 php_ion_decimal *obj = php_ion_obj(decimal, Z_OBJ_P(ZEND_THIS));
191 PTR_CHECK(obj);
192
193 zend_object *dec_obj;
194 ZEND_PARSE_PARAMETERS_START(1, 1)
195 Z_PARAM_OBJ_OF_CLASS(dec_obj, ce_Decimal)
196 ZEND_PARSE_PARAMETERS_END();
197
198 BOOL is = FALSE;
199 ION_CHECK(ion_decimal_equals(&obj->dec, &php_ion_obj(decimal, dec_obj)->dec,
200 obj->ctx ? &php_ion_obj(decimal_ctx, obj->ctx)->ctx : NULL, &is));
201 RETURN_BOOL(is);
202 }
203 ZEND_METHOD(ion_Decimal, __toString)
204 {
205 php_ion_decimal *obj = php_ion_obj(decimal, Z_OBJ_P(ZEND_THIS));
206 PTR_CHECK(obj);
207
208 ZEND_PARSE_PARAMETERS_NONE();
209
210 RETURN_STR(php_ion_decimal_to_string(&obj->dec));
211 }
212 ZEND_METHOD(ion_Decimal, toInt)
213 {
214 php_ion_decimal *obj = php_ion_obj(decimal, Z_OBJ_P(ZEND_THIS));
215 PTR_CHECK(obj);
216
217 ZEND_PARSE_PARAMETERS_NONE();
218
219 zend_long l;
220 php_ion_decimal_to_int(&obj->dec, &php_ion_obj(decimal_ctx, obj->ctx)->ctx, &l);
221 RETURN_LONG(l);
222 }
223 ZEND_METHOD(ion_Decimal, isInt)
224 {
225 php_ion_decimal *obj = php_ion_obj(decimal, Z_OBJ_P(ZEND_THIS));
226 PTR_CHECK(obj);
227
228 ZEND_PARSE_PARAMETERS_NONE();
229
230 RETURN_BOOL(ion_decimal_is_integer(&obj->dec));
231 }
232 ZEND_METHOD(ion_LOB, __construct)
233 {
234 zend_string *value;
235 zend_object *type = NULL;
236 ZEND_PARSE_PARAMETERS_START(1, 2)
237 Z_PARAM_STR(value)
238 Z_PARAM_OPTIONAL
239 Z_PARAM_OBJ_OF_CLASS(type, ce_Type)
240 ZEND_PARSE_PARAMETERS_END();
241
242 if (!type) {
243 type = zend_enum_get_case_cstr(ce_Type, "CLob");
244 }
245 update_property_obj(Z_OBJ_P(ZEND_THIS), ZEND_STRL("type"), type);
246 zend_update_property_str(Z_OBJCE_P(ZEND_THIS), Z_OBJ_P(ZEND_THIS), ZEND_STRL("value"), value);
247 }
248 ZEND_METHOD(ion_Reader_Options, __construct)
249 {
250 php_ion_reader_options *opt = php_ion_obj(reader_options, Z_OBJ_P(ZEND_THIS));
251 zend_bool ret_sys_val = false, skip_validation = false;
252 zend_long ch_nl = 0xa, max_depth = 10, max_ann, max_ann_buf = 512,
253 sym_thr = 0x1000, uval_thr = 0x1000, chunk_thr = 0x1000, alloc_pgsz = 0x1000;
254
255 PTR_CHECK(opt);
256
257 ZEND_PARSE_PARAMETERS_START(0, 13)
258 Z_PARAM_OPTIONAL
259 // public readonly ?\ion\Catalog $catalog = null,
260 Z_PARAM_OBJ_OF_CLASS_OR_NULL(opt->cat, ce_Catalog)
261 // public readonly ?\ion\Decimal\Context $decimalContext = null,
262 Z_PARAM_OBJ_OF_CLASS_OR_NULL(opt->dec_ctx, ce_Decimal_Context)
263 // public readonly ?\Closure $onContextChange = null,
264 Z_PARAM_OBJ_OF_CLASS_OR_NULL(opt->cb, zend_ce_closure);
265 // public readonly bool $returnSystemValues = false,
266 Z_PARAM_BOOL(ret_sys_val)
267 // public readonly int $newLine = 0xa,
268 Z_PARAM_LONG(ch_nl)
269 // public readonly int $maxContainerDepth = 10,
270 Z_PARAM_LONG(max_depth)
271 // public readonly int $maxAnnotations = 10,
272 Z_PARAM_LONG(max_ann)
273 // public readonly int $maxAnnotationBuffered = 512,
274 Z_PARAM_LONG(max_ann_buf)
275 // public readonly int $symbolThreshold = 4096,
276 Z_PARAM_LONG(sym_thr)
277 // public readonly int $userValueThreshold = 4096,
278 Z_PARAM_LONG(uval_thr)
279 // public readonly int $chunkThreshold = 4096,
280 Z_PARAM_LONG(chunk_thr)
281 // public readonly int $allocationPageSize = 4096,
282 Z_PARAM_LONG(alloc_pgsz)
283 // public readonly bool $skipCharacterValidation = false,
284 Z_PARAM_BOOL(skip_validation)
285 ZEND_PARSE_PARAMETERS_END();
286
287 opt->opt.context_change_notifier = EMPTY_READER_CHANGE_NOTIFIER;
288 if (opt->cb) {
289 update_property_obj(&opt->std, ZEND_STRL("onContextChange"), opt->cb);
290 }
291 if (opt->cat) {
292 update_property_obj(&opt->std, ZEND_STRL("catalog"), opt->cat);
293 opt->opt.pcatalog = php_ion_obj(catalog, opt->cat)->cat;
294 }
295 if (opt->dec_ctx) {
296 update_property_obj(&opt->std, ZEND_STRL("decimalContext"), opt->dec_ctx);
297 opt->opt.decimal_context = &php_ion_obj(decimal_ctx, opt->dec_ctx)->ctx;
298 }
299 zend_update_property_bool(opt->std.ce, &opt->std, ZEND_STRL("returnSystemValues"),
300 opt->opt.return_system_values = ret_sys_val);
301 zend_update_property_long(opt->std.ce, &opt->std, ZEND_STRL("newLine"),
302 opt->opt.new_line_char = ch_nl);
303 zend_update_property_long(opt->std.ce, &opt->std, ZEND_STRL("maxContainerDepth"),
304 opt->opt.max_container_depth = max_depth);
305 zend_update_property_long(opt->std.ce, &opt->std, ZEND_STRL("maxAnnotationCount"),
306 opt->opt.max_annotation_count = max_ann);
307 zend_update_property_long(opt->std.ce, &opt->std, ZEND_STRL("maxAnnotationBuffered"),
308 opt->opt.max_annotation_buffered = max_ann_buf);
309 zend_update_property_long(opt->std.ce, &opt->std, ZEND_STRL("symbolThreshold"),
310 opt->opt.symbol_threshold = sym_thr);
311 zend_update_property_long(opt->std.ce, &opt->std, ZEND_STRL("userValueThreshold"),
312 opt->opt.user_value_threshold = uval_thr);
313 zend_update_property_long(opt->std.ce, &opt->std, ZEND_STRL("chunkThreshold"),
314 opt->opt.chunk_threshold = chunk_thr);
315 zend_update_property_long(opt->std.ce, &opt->std, ZEND_STRL("allocationPageSize"),
316 opt->opt.allocation_page_size = alloc_pgsz);
317 zend_update_property_long(opt->std.ce, &opt->std, ZEND_STRL("skipCharacterValidation"),
318 opt->opt.skip_character_validation = skip_validation);
319 }
320 ZEND_METHOD(ion_Reader_Reader, hasChildren)
321 {
322 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
323
324 OBJ_CHECK(obj);
325 ZEND_PARSE_PARAMETERS_NONE();
326
327 ION_TYPE t;
328 ION_CHECK(ion_reader_get_type(obj->reader, &t));
329 switch (ION_TYPE_INT(t)) {
330 case tid_LIST_INT:
331 case tid_SEXP_INT:
332 case tid_STRUCT_INT:
333 RETVAL_TRUE;
334 break;
335 default:
336 RETVAL_FALSE;
337 break;
338 }
339 }
340 ZEND_METHOD(ion_Reader_Reader, getChildren)
341 {
342 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
343 OBJ_CHECK(obj);
344
345 ZEND_PARSE_PARAMETERS_NONE();
346
347 ION_CHECK(ion_reader_step_in(obj->reader));
348
349 RETURN_ZVAL(ZEND_THIS, 1, 0);
350 }
351 ZEND_METHOD(ion_Reader_Reader, rewind)
352 {
353 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
354 OBJ_CHECK(obj);
355
356 ZEND_PARSE_PARAMETERS_NONE();
357
358 ION_CHECK(ion_reader_next(obj->reader, &obj->state));
359 }
360 ZEND_METHOD(ion_Reader_Reader, next)
361 {
362 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
363 OBJ_CHECK(obj);
364
365 ZEND_PARSE_PARAMETERS_NONE();
366
367 if (obj->state == tid_EOF) {
368 SIZE depth = 0;
369 ION_CHECK(ion_reader_get_depth(obj->reader, &depth));
370 if (depth) {
371 ION_CHECK(ion_reader_step_out(obj->reader));
372 }
373 }
374 ION_CHECK(ion_reader_next(obj->reader, &obj->state));
375 }
376 ZEND_METHOD(ion_Reader_Reader, valid)
377 {
378 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
379 OBJ_CHECK(obj);
380
381 ZEND_PARSE_PARAMETERS_NONE();
382 RETURN_BOOL(obj->state != tid_none && obj->state != tid_EOF);
383 }
384 ZEND_METHOD(ion_Reader_Reader, key)
385 {
386 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
387 OBJ_CHECK(obj);
388
389 ZEND_PARSE_PARAMETERS_NONE();
390 RETURN_IONTYPE(obj->state);
391 }
392 ZEND_METHOD(ion_Reader_Reader, current)
393 {
394 ZEND_PARSE_PARAMETERS_NONE();
395 RETURN_ZVAL(ZEND_THIS, 1, 0);
396 }
397 ZEND_METHOD(ion_Reader_Reader, getType)
398 {
399 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
400 OBJ_CHECK(obj);
401
402 ZEND_PARSE_PARAMETERS_NONE();
403
404 ION_TYPE typ;
405 ION_CHECK(ion_reader_get_type(obj->reader, &typ));
406 RETURN_IONTYPE(typ);
407 }
408 ZEND_METHOD(ion_Reader_Reader, hasAnnotations)
409 {
410 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
411 OBJ_CHECK(obj);
412
413 ZEND_PARSE_PARAMETERS_NONE();
414
415 BOOL has = FALSE;
416 ION_CHECK(ion_reader_has_any_annotations(obj->reader, &has));
417 RETURN_BOOL(has);
418 }
419 ZEND_METHOD(ion_Reader_Reader, hasAnnotation)
420 {
421 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
422 OBJ_CHECK(obj);
423
424 zend_string *ann_zstr;
425 ZEND_PARSE_PARAMETERS_START(1, 1);
426 Z_PARAM_STR(ann_zstr);
427 ZEND_PARSE_PARAMETERS_END();
428
429 ION_STRING ann_istr;
430 BOOL has = FALSE;
431 ION_CHECK(ion_reader_has_annotation(obj->reader, ion_string_from_zend(&ann_istr, ann_zstr), &has));
432 RETURN_BOOL(has);
433 }
434 ZEND_METHOD(ion_Reader_Reader, isNull)
435 {
436 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
437 OBJ_CHECK(obj);
438
439 ZEND_PARSE_PARAMETERS_NONE();
440
441 BOOL is = FALSE;
442 ION_CHECK(ion_reader_is_null(obj->reader, &is));
443 RETURN_BOOL(is);
444 }
445 ZEND_METHOD(ion_Reader_Reader, isInStruct)
446 {
447 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
448 OBJ_CHECK(obj);
449
450 ZEND_PARSE_PARAMETERS_NONE();
451
452 BOOL is = FALSE;
453 ION_CHECK(ion_reader_is_in_struct(obj->reader, &is));
454 RETURN_BOOL(is);
455 }
456 ZEND_METHOD(ion_Reader_Reader, getFieldName)
457 {
458 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
459 OBJ_CHECK(obj);
460
461 ZEND_PARSE_PARAMETERS_NONE();
462
463 ION_STRING name;
464 ION_CHECK(ion_reader_get_field_name(obj->reader, &name));
465 RETURN_STRINGL((char *) name.value, name.length);
466 }
467 ZEND_METHOD(ion_Reader_Reader, getFieldNameSymbol)
468 {
469 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
470 OBJ_CHECK(obj);
471
472 ZEND_PARSE_PARAMETERS_NONE();
473
474 ION_SYMBOL *sym_ptr;
475 ION_CHECK(ion_reader_get_field_name_symbol(obj->reader, &sym_ptr));
476
477 php_ion_symbol_zval(sym_ptr, return_value);
478 }
479 ZEND_METHOD(ion_Reader_Reader, getAnnotations)
480 {
481 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
482 OBJ_CHECK(obj);
483
484 ZEND_PARSE_PARAMETERS_NONE();
485
486 int32_t count, max;
487 if (obj->opt) {
488 max = php_ion_obj(reader_options, obj->opt)->opt.max_annotation_count;
489 } else {
490 max = 10;
491 }
492 ION_STRING *ptr = ecalloc(sizeof(*ptr), max);
493 iERR err = ion_reader_get_annotations(obj->reader, ptr, max, &count);
494 if (!err) {
495 array_init_size(return_value, count);
496 for (int32_t i = 0; i < count; ++i) {
497 add_next_index_str(return_value, zend_string_from_ion(&ptr[i]));
498 }
499 }
500 efree(ptr);
501 ION_CHECK(err);
502 }
503 ZEND_METHOD(ion_Reader_Reader, getAnnotationSymbols)
504 {
505 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
506 OBJ_CHECK(obj);
507
508 ZEND_PARSE_PARAMETERS_NONE();
509
510 int32_t count, max = php_ion_obj(reader_options, obj->opt)->opt.max_annotation_count;
511 ION_SYMBOL *ptr = ecalloc(sizeof(*ptr), max);
512 iERR err = ion_reader_get_annotation_symbols(obj->reader, ptr, max, &count);
513 if (!err) {
514 array_init_size(return_value, count);
515 for (int32_t i = 0; i < count; ++i) {
516 zval zsym;
517 php_ion_symbol_zval(&ptr[i], &zsym);
518 add_next_index_zval(return_value, &zsym);
519 }
520 }
521 efree(ptr);
522 ION_CHECK(err);
523 }
524 ZEND_METHOD(ion_Reader_Reader, countAnnotations)
525 {
526 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
527 OBJ_CHECK(obj);
528
529 ZEND_PARSE_PARAMETERS_NONE();
530
531 SIZE sz = 0;
532 ION_CHECK(ion_reader_get_annotation_count(obj->reader, &sz));
533 RETURN_LONG(sz);
534 }
535 ZEND_METHOD(ion_Reader_Reader, getAnnotation)
536 {
537 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
538 OBJ_CHECK(obj);
539
540 zend_long idx;
541 ZEND_PARSE_PARAMETERS_START(1, 1)
542 Z_PARAM_LONG(idx);
543 ZEND_PARSE_PARAMETERS_END();
544
545 ION_STRING ann;
546 ION_CHECK(ion_reader_get_an_annotation(obj->reader, idx, &ann));
547 RETURN_STRINGL((char *) ann.value, ann.length);
548 }
549 ZEND_METHOD(ion_Reader_Reader, getAnnotationSymbol)
550 {
551 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
552 OBJ_CHECK(obj);
553
554 zend_long idx;
555 ZEND_PARSE_PARAMETERS_START(1, 1)
556 Z_PARAM_LONG(idx);
557 ZEND_PARSE_PARAMETERS_END();
558
559 ION_SYMBOL sym;
560 ION_CHECK(ion_reader_get_an_annotation_symbol(obj->reader, idx, &sym));
561 php_ion_symbol_zval(&sym, return_value);
562 }
563 ZEND_METHOD(ion_Reader_Reader, readNull)
564 {
565 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
566 OBJ_CHECK(obj);
567
568 ZEND_PARSE_PARAMETERS_NONE();
569
570 ION_TYPE typ;
571 ION_CHECK(ion_reader_read_null(obj->reader, &typ));
572 RETURN_OBJ_COPY(php_ion_type_fetch(typ));
573 }
574 ZEND_METHOD(ion_Reader_Reader, readBool)
575 {
576 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
577 OBJ_CHECK(obj);
578
579 ZEND_PARSE_PARAMETERS_NONE();
580
581 BOOL b;
582 ION_CHECK(ion_reader_read_bool(obj->reader, &b));
583 RETURN_BOOL(b);
584 }
585 ZEND_METHOD(ion_Reader_Reader, readInt)
586 {
587 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
588 OBJ_CHECK(obj);
589
590 ZEND_PARSE_PARAMETERS_NONE();
591
592 php_ion_reader_read_int(obj->reader, return_value);
593 }
594 ZEND_METHOD(ion_Reader_Reader, readFloat)
595 {
596 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
597 OBJ_CHECK(obj);
598
599 ZEND_PARSE_PARAMETERS_NONE();
600
601 ION_CHECK(ion_reader_read_double(obj->reader, &Z_DVAL_P(return_value)));
602 }
603 ZEND_METHOD(ion_Reader_Reader, readDecimal)
604 {
605 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
606 OBJ_CHECK(obj);
607
608 ZEND_PARSE_PARAMETERS_NONE();
609
610 object_init_ex(return_value, ce_Decimal);
611 php_ion_decimal *dec = php_ion_obj(decimal, Z_OBJ_P(return_value));
612 ION_CHECK(ion_reader_read_ion_decimal(obj->reader, &dec->dec));
613 php_ion_decimal_ctor(dec);
614 }
615 ZEND_METHOD(ion_Reader_Reader, readTimestamp)
616 {
617 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
618 OBJ_CHECK(obj);
619
620 ZEND_PARSE_PARAMETERS_NONE();
621
622 php_ion_reader_read_timestamp(obj->reader, obj->opt ? &php_ion_obj(reader_options, obj->opt)->opt : NULL, return_value);
623 }
624 ZEND_METHOD(ion_Reader_Reader, readSymbol)
625 {
626 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
627 OBJ_CHECK(obj);
628
629 ZEND_PARSE_PARAMETERS_NONE();
630
631 ION_SYMBOL sym;
632 ION_CHECK(ion_reader_read_ion_symbol(obj->reader, &sym));
633 php_ion_symbol_zval(&sym, return_value);
634 }
635 ZEND_METHOD(ion_Reader_Reader, readString)
636 {
637 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
638 OBJ_CHECK(obj);
639
640 ZEND_PARSE_PARAMETERS_NONE();
641
642 ION_STRING str;
643 ION_CHECK(ion_reader_read_string(obj->reader, &str));
644 RETURN_STRINGL((char *) str.value, str.length);
645 }
646
647 typedef iERR (*read_part_fn)(ION_READER *, BYTE *, SIZE, SIZE *);
648 static void read_part(INTERNAL_FUNCTION_PARAMETERS, read_part_fn fn)
649 {
650 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
651 OBJ_CHECK(obj);
652
653 zval *ref;
654 zend_string *zstr;
655 zend_long len = 0x1000;
656 ZEND_PARSE_PARAMETERS_START(1, 1)
657 Z_PARAM_ZVAL(ref)
658 Z_PARAM_OPTIONAL
659 Z_PARAM_LONG(len)
660 ZEND_PARSE_PARAMETERS_END();
661
662 ZVAL_DEREF(ref);
663
664 if (Z_TYPE_P(ref) == IS_STRING && Z_STRLEN_P(ref) == len) {
665 /* reuse */
666 zstr = Z_STR_P(ref);
667 } else {
668 zval_dtor(ref);
669 zstr = zend_string_alloc(len, 0);
670 }
671
672 SIZE read = 0;
673 ION_CHECK(fn(obj->reader, (BYTE *) zstr->val, zstr->len, &read), goto fail);
674 if (read > 0) {
675 if (read < zstr->len) {
676 zstr = zend_string_truncate(zstr, read, 0);
677 }
678 ZVAL_STR(ref, zstr);
679 RETURN_TRUE;
680 }
681 fail:
682 if (zstr != Z_STR_P(ref)) {
683 zend_string_release(zstr);
684 }
685 ZVAL_EMPTY_STRING(ref);
686 RETURN_FALSE;
687 }
688 ZEND_METHOD(ion_Reader_Reader, readStringPart)
689 {
690 read_part(INTERNAL_FUNCTION_PARAM_PASSTHRU, ion_reader_read_partial_string);
691 }
692 ZEND_METHOD(ion_Reader_Reader, readLob)
693 {
694 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
695 OBJ_CHECK(obj);
696
697 ZEND_PARSE_PARAMETERS_NONE();
698
699 php_ion_reader_read_lob(obj->reader, return_value);
700 }
701 ZEND_METHOD(ion_Reader_Reader, readLobPart)
702 {
703 read_part(INTERNAL_FUNCTION_PARAM_PASSTHRU, ion_reader_read_lob_partial_bytes);
704 }
705 ZEND_METHOD(ion_Reader_Reader, getPosition)
706 {
707 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
708 OBJ_CHECK(obj);
709
710 ZEND_PARSE_PARAMETERS_NONE();
711
712 int64_t bytes = 0;
713 int32_t dummy;
714 ION_CHECK(ion_reader_get_position(obj->reader, &bytes, &dummy, &dummy));
715 RETURN_LONG(bytes);
716 }
717 ZEND_METHOD(ion_Reader_Reader, getDepth)
718 {
719 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
720 OBJ_CHECK(obj);
721
722 ZEND_PARSE_PARAMETERS_NONE();
723
724 SIZE depth = 0;
725 ION_CHECK(ion_reader_get_depth(obj->reader, &depth));
726 RETURN_LONG(depth);
727 }
728 ZEND_METHOD(ion_Reader_Reader, seek)
729 {
730 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
731 OBJ_CHECK(obj);
732
733 zend_long off, len = -1;
734 ZEND_PARSE_PARAMETERS_START(1, 2)
735 Z_PARAM_LONG(off)
736 Z_PARAM_OPTIONAL
737 Z_PARAM_LONG(len)
738 ZEND_PARSE_PARAMETERS_END();
739
740 ION_CHECK(ion_reader_seek(obj->reader, off, len));
741 }
742 ZEND_METHOD(ion_Reader_Reader, getValueOffset)
743 {
744 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
745 OBJ_CHECK(obj);
746
747 ZEND_PARSE_PARAMETERS_NONE();
748
749 POSITION off = 0;
750 ION_CHECK(ion_reader_get_value_offset(obj->reader, &off));
751 RETURN_LONG(off);
752 }
753 ZEND_METHOD(ion_Reader_Reader, getValueLength)
754 {
755 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
756 OBJ_CHECK(obj);
757
758 ZEND_PARSE_PARAMETERS_NONE();
759
760 SIZE len = 0;
761 ION_CHECK(ion_reader_get_value_length(obj->reader, &len));
762 RETURN_LONG(len);
763 }
764 ZEND_METHOD(ion_Reader_Buffer_Reader, __construct)
765 {
766 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
767 PTR_CHECK(obj);
768
769 zend_string *zstr;
770 ZEND_PARSE_PARAMETERS_START(1, 2)
771 Z_PARAM_STR(zstr)
772 Z_PARAM_OPTIONAL
773 Z_PARAM_OBJ_OF_CLASS_OR_NULL(obj->opt, ce_Reader_Options)
774 ZEND_PARSE_PARAMETERS_END();
775
776 obj->type = BUFFER_READER;
777 obj->buffer = zend_string_copy(zstr);
778
779 php_ion_reader_ctor(obj);
780 }
781 ZEND_METHOD(ion_Reader_Buffer_Reader, getBuffer)
782 {
783 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
784 OBJ_CHECK(obj);
785
786 ZEND_PARSE_PARAMETERS_NONE();
787 RETURN_STR_COPY(obj->buffer);
788 }
789
790 ZEND_METHOD(ion_Reader_Stream_Reader, __construct)
791 {
792 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
793 PTR_CHECK(obj);
794
795 zval *zstream;
796 ZEND_PARSE_PARAMETERS_START(1, 2)
797 Z_PARAM_RESOURCE(zstream)
798 Z_PARAM_OPTIONAL
799 Z_PARAM_OBJ_OF_CLASS_OR_NULL(obj->opt, ce_Reader_Options)
800 ZEND_PARSE_PARAMETERS_END();
801
802 obj->type = STREAM_READER;
803 php_stream_from_zval_no_verify(obj->stream.ptr, zstream);
804
805 php_ion_reader_ctor(obj);
806 }
807 ZEND_METHOD(ion_Reader_Stream_Reader, getStream)
808 {
809 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
810 OBJ_CHECK(obj);
811
812 ZEND_PARSE_PARAMETERS_NONE();
813 PTR_CHECK(obj->stream.ptr);
814
815 GC_ADDREF(obj->stream.ptr->res);
816 RETURN_RES(obj->stream.ptr->res);
817 }
818 ZEND_METHOD(ion_Reader_Stream_Reader, resetStream)
819 {
820 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
821 OBJ_CHECK(obj);
822
823 zval *zstream;
824 ZEND_PARSE_PARAMETERS_START(1, 1);
825 Z_PARAM_RESOURCE(zstream);
826 ZEND_PARSE_PARAMETERS_END();
827
828 ION_CHECK(ion_reader_reset_stream(&obj->reader, obj, php_ion_reader_stream_handler));
829
830 if (obj->stream.ptr) {
831 zend_list_delete(obj->stream.ptr->res);
832 }
833 php_stream_from_zval_no_verify(obj->stream.ptr, zstream);
834 PTR_CHECK(obj->stream.ptr);
835 Z_ADDREF_P(zstream);
836 }
837 ZEND_METHOD(ion_Reader_Stream_Reader, resetStreamWithLength)
838 {
839 php_ion_reader *obj = php_ion_obj(reader, Z_OBJ_P(ZEND_THIS));
840 OBJ_CHECK(obj);
841
842 zval *zstream;
843 zend_long length;
844 ZEND_PARSE_PARAMETERS_START(1, 2);
845 Z_PARAM_RESOURCE(zstream);
846 Z_PARAM_LONG(length)
847 ZEND_PARSE_PARAMETERS_END();
848
849 ION_CHECK(ion_reader_reset_stream_with_length(&obj->reader, obj, php_ion_reader_stream_handler, length));
850
851 if (obj->stream.ptr) {
852 zend_list_delete(obj->stream.ptr->res);
853 }
854 php_stream_from_zval_no_verify(obj->stream.ptr, zstream);
855 PTR_CHECK(obj->stream.ptr);
856 Z_ADDREF_P(zstream);
857 }
858 ZEND_METHOD(ion_Writer_Options, __construct)
859 {
860 php_ion_writer_options *obj = php_ion_obj(writer_options, Z_OBJ_P(ZEND_THIS));
861 PTR_CHECK(obj);
862
863 zend_bool binary = false, compact_floats = false, escape = false, pretty = false,
864 tabs = true, small_cntr_inl = true, suppress_sys = false, flush = false;
865 zend_long indent = 2, max_depth = 10, max_ann = 10, temp = 0x400, alloc = 0x1000;
866 ZEND_PARSE_PARAMETERS_START(0, 16)
867 Z_PARAM_OPTIONAL
868 //public readonly ?\ion\Catalog $catalog = null,
869 Z_PARAM_OBJ_OF_CLASS_OR_NULL(obj->cat, ce_Catalog)
870 //public readonly ?\ion\Collection $encodingSymbolTable = null,
871 Z_PARAM_OBJ_OF_CLASS_OR_NULL(obj->col, ce_Collection)
872 //public readonly ?\ion\Decimal\Context $decimalContext = null,
873 Z_PARAM_OBJ_OF_CLASS_OR_NULL(obj->dec_ctx, ce_Decimal_Context)
874 //public readonly bool $outputBinary = false,
875 Z_PARAM_BOOL(binary)
876 //public readonly bool $compactFloats = false,
877 Z_PARAM_BOOL(compact_floats)
878 //public readonly bool $escapeNonAscii = false,
879 Z_PARAM_BOOL(escape)
880 //public readonly bool $prettyPrint = false,
881 Z_PARAM_BOOL(pretty)
882 //public readonly bool $indentTabs = true,
883 Z_PARAM_BOOL(tabs)
884 //public readonly int $indentSize = 2,
885 Z_PARAM_LONG(indent)
886 //public readonly bool $smallContainersInline = true,
887 Z_PARAM_BOOL(small_cntr_inl)
888 //public readonly bool $suppressSystemValues = false,
889 Z_PARAM_BOOL(suppress_sys)
890 //public readonly bool $flushEveryValue = false,
891 Z_PARAM_BOOL(flush)
892 //public readonly int $maxContainerDepth = 10,
893 Z_PARAM_LONG(max_depth)
894 //public readonly int $maxAnnotations = 10,
895 Z_PARAM_LONG(max_ann)
896 //public readonly int $tempBufferSize = 0x400,
897 Z_PARAM_LONG(temp)
898 //public readonly int $allocationPageSize = 0x1000,
899 Z_PARAM_LONG(alloc)
900 ZEND_PARSE_PARAMETERS_END();
901
902 if (obj->cat) {
903 update_property_obj(&obj->std, ZEND_STRL("catalog"), obj->cat);
904 obj->opt.pcatalog = php_ion_obj(catalog, obj->cat)->cat;
905 }
906 if (obj->col) {
907 // TODO
908 }
909 if (obj->dec_ctx) {
910 update_property_obj(&obj->std, ZEND_STRL("decimalContext"), obj->dec_ctx);
911 obj->opt.decimal_context = &php_ion_obj(decimal_ctx, obj->dec_ctx)->ctx;
912 }
913 zend_update_property_bool(obj->std.ce, &obj->std, ZEND_STRL("outputBinary"),
914 obj->opt.output_as_binary = binary);
915 zend_update_property_bool(obj->std.ce, &obj->std, ZEND_STRL("comactFloats"),
916 obj->opt.compact_floats = compact_floats);
917 zend_update_property_bool(obj->std.ce, &obj->std, ZEND_STRL("excapeNonAscii"),
918 obj->opt.escape_all_non_ascii = escape);
919 zend_update_property_bool(obj->std.ce, &obj->std, ZEND_STRL("prettyPrint"),
920 obj->opt.pretty_print = pretty);
921 zend_update_property_bool(obj->std.ce, &obj->std, ZEND_STRL("indentTabs"),
922 obj->opt.indent_with_tabs = tabs);
923 zend_update_property_long(obj->std.ce, &obj->std, ZEND_STRL("indentSize"),
924 obj->opt.indent_size = indent);
925 zend_update_property_bool(obj->std.ce, &obj->std, ZEND_STRL("smallContainersInline"),
926 obj->opt.small_containers_in_line = small_cntr_inl);
927 zend_update_property_bool(obj->std.ce, &obj->std, ZEND_STRL("suppressSystemValues"),
928 obj->opt.supress_system_values = suppress_sys);
929 zend_update_property_bool(obj->std.ce, &obj->std, ZEND_STRL("flushEveryValue"),
930 obj->opt.flush_every_value = flush);
931 zend_update_property_long(obj->std.ce, &obj->std, ZEND_STRL("maxContainerDepth"),
932 obj->opt.max_container_depth = max_depth);
933 zend_update_property_long(obj->std.ce, &obj->std, ZEND_STRL("maxAnnotations"),
934 obj->opt.max_annotation_count = max_ann);
935 zend_update_property_long(obj->std.ce, &obj->std, ZEND_STRL("tempBufferSize"),
936 obj->opt.temp_buffer_size = temp);
937 zend_update_property_long(obj->std.ce, &obj->std, ZEND_STRL("allocationPageSize"),
938 obj->opt.allocation_page_size = alloc);
939 }
940 ZEND_METHOD(ion_Writer_Writer, writeNull)
941 {
942 php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS));
943 OBJ_CHECK(obj);
944
945 ZEND_PARSE_PARAMETERS_NONE();
946
947 ION_CHECK(ion_writer_write_null(obj->writer));
948 }
949 ZEND_METHOD(ion_Writer_Writer, writeTypedNull)
950 {
951 php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS));
952 OBJ_CHECK(obj);
953
954 zend_object *typ_obj;
955 ZEND_PARSE_PARAMETERS_START(1, 1)
956 Z_PARAM_OBJ_OF_CLASS(typ_obj, ce_Type)
957 ZEND_PARSE_PARAMETERS_END();
958
959 php_ion_type *typ = php_ion_obj(type, typ_obj);
960 OBJ_CHECK(typ);
961 ION_CHECK(ion_writer_write_typed_null(obj->writer, php_ion_obj(type, typ)->typ));
962 }
963 ZEND_METHOD(ion_Writer_Writer, writeBool)
964 {
965 php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS));
966 OBJ_CHECK(obj);
967
968 zend_bool b;
969 ZEND_PARSE_PARAMETERS_START(1, 1)
970 Z_PARAM_BOOL(b)
971 ZEND_PARSE_PARAMETERS_END();
972
973 ION_CHECK(ion_writer_write_bool(obj->writer, b));
974 }
975 ZEND_METHOD(ion_Writer_Writer, writeInt)
976 {
977 php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS));
978 OBJ_CHECK(obj);
979
980 zend_long l;
981 zend_string *s;
982 ZEND_PARSE_PARAMETERS_START(1, 1)
983 Z_PARAM_STR_OR_LONG(s, l)
984 ZEND_PARSE_PARAMETERS_END();
985
986 if (s) {
987 ION_INT *i;
988 ION_CHECK(ion_int_alloc(obj->writer, &i));
989 ION_CHECK(ion_int_from_chars(i, s->val, s->len));
990 ION_CHECK(ion_writer_write_ion_int(obj->writer, i));
991 ion_int_free(i);
992 } else {
993 ION_CHECK(ion_writer_write_int64(obj->writer, l));
994 }
995 }
996 ZEND_METHOD(ion_Writer_Writer, writeFloat)
997 {
998 php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS));
999 OBJ_CHECK(obj);
1000
1001 double d;
1002 ZEND_PARSE_PARAMETERS_START(1, 1)
1003 Z_PARAM_DOUBLE(d)
1004 ZEND_PARSE_PARAMETERS_END();
1005
1006 ION_CHECK(ion_writer_write_double(obj->writer, d));
1007 }
1008 ZEND_METHOD(ion_Writer_Writer, writeDecimal)
1009 {
1010 php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS));
1011 OBJ_CHECK(obj);
1012
1013 zend_object *dec_obj;
1014 zend_string *dec_str;
1015 ZEND_PARSE_PARAMETERS_START(1, 1)
1016 Z_PARAM_OBJ_OF_CLASS_OR_STR(dec_obj, ce_Decimal, dec_str)
1017 ZEND_PARSE_PARAMETERS_END();
1018
1019 if (dec_str) {
1020 ION_STRING s;
1021 ION_CHECK(ion_writer_write_string(obj->writer, ion_string_from_zend(&s, dec_str)));
1022 } else {
1023 php_ion_decimal *dec = php_ion_obj(decimal, dec_obj);
1024 ION_CHECK(ion_writer_write_ion_decimal(obj->writer, &dec->dec));
1025 }
1026 }
1027 ZEND_METHOD(ion_Writer_Writer, writeTimestamp)
1028 {
1029 php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS));
1030 OBJ_CHECK(obj);
1031
1032 zend_object *ts_obj;
1033 zend_string *ts_str;
1034 ZEND_PARSE_PARAMETERS_START(1, 1)
1035 Z_PARAM_OBJ_OF_CLASS_OR_STR(ts_obj, ce_Timestamp, ts_str)
1036 ZEND_PARSE_PARAMETERS_END();
1037
1038 decContext *ctx = NULL;
1039 if (obj->opt) {
1040 ctx = php_ion_obj(reader_options, obj->opt)->opt.decimal_context;
1041 }
1042
1043 ION_TIMESTAMP tmp = {0};
1044 if (ts_str) {
1045 SIZE used;
1046 ION_CHECK(ion_timestamp_parse(&tmp, ts_str->val, ts_str->len, &used, ctx));
1047 } else {
1048 php_ion_timestamp *ts = php_ion_obj(timestamp, ts_obj);
1049 OBJ_CHECK(ts);
1050 ion_timestamp_from_php(&tmp, ts, ctx);
1051 }
1052 ION_CHECK(ion_writer_write_timestamp(obj->writer, &tmp));
1053 }
1054 ZEND_METHOD(ion_Writer_Writer, writeSymbol)
1055 {
1056 php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS));
1057 OBJ_CHECK(obj);
1058
1059 zend_object *sym_obj;
1060 zend_string *sym_str;
1061 ZEND_PARSE_PARAMETERS_START(1, 1)
1062 Z_PARAM_OBJ_OF_CLASS_OR_STR(sym_obj, ce_Symbol, sym_str);
1063 ZEND_PARSE_PARAMETERS_END();
1064
1065 if (sym_str) {
1066 ION_STRING is;
1067 ION_CHECK(ion_writer_write_symbol(obj->writer, ion_string_from_zend(&is, sym_str)));
1068 } else {
1069 php_ion_symbol *sym = php_ion_obj(symbol, sym_obj);
1070 PTR_CHECK(sym);
1071 ION_CHECK(ion_writer_write_ion_symbol(obj->writer, &sym->sym));
1072 }
1073 }
1074 ZEND_METHOD(ion_Writer_Writer, writeString)
1075 {
1076 php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS));
1077 OBJ_CHECK(obj);
1078
1079 zend_string *str;
1080 ZEND_PARSE_PARAMETERS_START(1, 1)
1081 Z_PARAM_STR(str)
1082 ZEND_PARSE_PARAMETERS_END();
1083
1084 ION_STRING is;
1085 ION_CHECK(ion_writer_write_string(obj->writer, ion_string_from_zend(&is, str)));
1086 }
1087 ZEND_METHOD(ion_Writer_Writer, writeCLob)
1088 {
1089 php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS));
1090 OBJ_CHECK(obj);
1091
1092 zend_string *str;
1093 ZEND_PARSE_PARAMETERS_START(1, 1)
1094 Z_PARAM_STR(str)
1095 ZEND_PARSE_PARAMETERS_END();
1096
1097 ION_CHECK(ion_writer_write_clob(obj->writer, (BYTE *) str->val, str->len));
1098 }
1099 ZEND_METHOD(ion_Writer_Writer, writeBLob)
1100 {
1101 php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS));
1102 OBJ_CHECK(obj);
1103
1104 zend_string *str;
1105 ZEND_PARSE_PARAMETERS_START(1, 1)
1106 Z_PARAM_STR(str)
1107 ZEND_PARSE_PARAMETERS_END();
1108
1109 ION_CHECK(ion_writer_write_blob(obj->writer, (BYTE *) str->val, str->len));
1110 }
1111 ZEND_METHOD(ion_Writer_Writer, startLob)
1112 {
1113 php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS));
1114 OBJ_CHECK(obj);
1115
1116 zend_object *typ_obj;
1117 ZEND_PARSE_PARAMETERS_START(1, 1)
1118 Z_PARAM_OBJ_OF_CLASS(typ_obj, ce_Type)
1119 ZEND_PARSE_PARAMETERS_END();
1120
1121 php_ion_type *typ = php_ion_obj(type, typ_obj);
1122 OBJ_CHECK(typ);
1123 ION_CHECK(ion_writer_start_lob(obj->writer, php_ion_obj(type, typ)->typ));
1124 }
1125 ZEND_METHOD(ion_Writer_Writer, appendLob)
1126 {
1127 php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS));
1128 OBJ_CHECK(obj);
1129
1130 zend_string *str;
1131 ZEND_PARSE_PARAMETERS_START(1, 1)
1132 Z_PARAM_STR(str)
1133 ZEND_PARSE_PARAMETERS_END();
1134
1135 ION_CHECK(ion_writer_append_lob(obj->writer, (BYTE *) str->val, str->len));
1136 }
1137 ZEND_METHOD(ion_Writer_Writer, finishLob)
1138 {
1139 php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS));
1140 OBJ_CHECK(obj);
1141
1142 ZEND_PARSE_PARAMETERS_NONE();
1143
1144 ION_CHECK(ion_writer_finish_lob(obj->writer));
1145 }
1146 ZEND_METHOD(ion_Writer_Writer, startContainer)
1147 {
1148 php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS));
1149 OBJ_CHECK(obj);
1150
1151 zend_object *typ_obj;
1152 ZEND_PARSE_PARAMETERS_START(1, 1)
1153 Z_PARAM_OBJ_OF_CLASS(typ_obj, ce_Type)
1154 ZEND_PARSE_PARAMETERS_END();
1155
1156 php_ion_type *typ = php_ion_obj(type, typ_obj);
1157 OBJ_CHECK(typ);
1158 ION_CHECK(ion_writer_start_container(obj->writer, php_ion_obj(type, typ)->typ));
1159 }
1160 ZEND_METHOD(ion_Writer_Writer, finishContainer)
1161 {
1162 php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS));
1163 OBJ_CHECK(obj);
1164
1165 ZEND_PARSE_PARAMETERS_NONE();
1166
1167 ION_CHECK(ion_writer_finish_container(obj->writer));
1168 }
1169 ZEND_METHOD(ion_Writer_Writer, writeFieldName)
1170 {
1171 php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS));
1172 OBJ_CHECK(obj);
1173
1174 zend_object *sym_obj;
1175 zend_string *sym_str;
1176 ZEND_PARSE_PARAMETERS_START(1, 1)
1177 Z_PARAM_OBJ_OF_CLASS_OR_STR(sym_obj, ce_Symbol, sym_str);
1178 ZEND_PARSE_PARAMETERS_END();
1179
1180 if (sym_str) {
1181 ION_STRING is;
1182 ION_CHECK(ion_writer_write_field_name(obj->writer, ion_string_from_zend(&is, sym_str)));
1183 } else {
1184 php_ion_symbol *sym = php_ion_obj(symbol, sym_obj);
1185 PTR_CHECK(sym);
1186 ION_CHECK(ion_writer_write_field_name_symbol(obj->writer, &sym->sym));
1187 }
1188 }
1189 ZEND_METHOD(ion_Writer_Writer, writeAnnotation)
1190 {
1191 php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS));
1192 OBJ_CHECK(obj);
1193
1194 zval *args;
1195 unsigned argc;
1196 ZEND_PARSE_PARAMETERS_START(1, -1)
1197 Z_PARAM_VARIADIC('+', args, argc);
1198 ZEND_PARSE_PARAMETERS_END();
1199
1200 for (unsigned i = 0; i < argc; ++i) {
1201 switch (Z_TYPE(args[i])) {
1202 case IS_STRING:
1203 ION_STRING is;
1204 ION_CHECK(ion_writer_add_annotation(obj->writer, ion_string_from_zend(&is, Z_STR(args[i]))));
1205 break;
1206
1207 case IS_OBJECT:
1208 ION_CHECK(ion_writer_add_annotation_symbol(obj->writer, &php_ion_obj(symbol, Z_OBJ(args[i]))->sym));
1209 break;
1210 }
1211 }
1212 }
1213 ZEND_METHOD(ion_Writer_Writer, getDepth)
1214 {
1215 php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS));
1216 OBJ_CHECK(obj);
1217
1218 ZEND_PARSE_PARAMETERS_NONE();
1219
1220 SIZE depth;
1221 ION_CHECK(ion_writer_get_depth(obj->writer, &depth));
1222 RETURN_LONG(depth);
1223 }
1224 ZEND_METHOD(ion_Writer_Writer, flush)
1225 {
1226 php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS));
1227 OBJ_CHECK(obj);
1228
1229 ZEND_PARSE_PARAMETERS_NONE();
1230
1231 SIZE flushed;
1232 ION_CHECK(ion_writer_flush(obj->writer, &flushed));
1233 if (obj->type == BUFFER_WRITER) {
1234 smart_str_0(&obj->buffer.str);
1235 }
1236 RETURN_LONG(flushed);
1237 }
1238 ZEND_METHOD(ion_Writer_Writer, finish)
1239 {
1240 php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS));
1241 OBJ_CHECK(obj);
1242
1243 ZEND_PARSE_PARAMETERS_NONE();
1244
1245 SIZE flushed;
1246 ION_CHECK(ion_writer_finish(obj->writer, &flushed));
1247 if (obj->type == BUFFER_WRITER) {
1248 smart_str_0(&obj->buffer.str);
1249 }
1250 RETURN_LONG(flushed);
1251 }
1252 ZEND_METHOD(ion_Writer_Writer, writeOne)
1253 {
1254 }
1255 ZEND_METHOD(ion_Writer_Writer, writeAll)
1256 {
1257 }
1258 ZEND_METHOD(ion_Writer_Buffer_Writer, __construct)
1259 {
1260 php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS));
1261 PTR_CHECK(obj);
1262
1263 zval *ref;
1264 ZEND_PARSE_PARAMETERS_START(1, 2)
1265 Z_PARAM_ZVAL(ref)
1266 Z_PARAM_OPTIONAL
1267 Z_PARAM_OBJ_OF_CLASS_OR_NULL(obj->opt, ce_Writer_Options)
1268 ZEND_PARSE_PARAMETERS_END();
1269
1270 obj->type = BUFFER_WRITER;
1271 ZVAL_COPY(&obj->buffer.val, ref);
1272 zval_dtor(Z_REFVAL_P(ref));
1273
1274 php_ion_writer_ctor(obj);
1275 }
1276 ZEND_METHOD(ion_Writer_Buffer_Writer, getBuffer)
1277 {
1278 php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS));
1279 OBJ_CHECK(obj);
1280
1281 ZEND_PARSE_PARAMETERS_NONE();
1282
1283 RETVAL_STR(zend_string_dup(obj->buffer.str.s, 0));
1284 }
1285 ZEND_METHOD(ion_Writer_Stream_Writer, __construct)
1286 {
1287 php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS));
1288 PTR_CHECK(obj);
1289
1290 zval *zstream;
1291 ZEND_PARSE_PARAMETERS_START(1, 2)
1292 Z_PARAM_RESOURCE(zstream)
1293 Z_PARAM_OPTIONAL
1294 Z_PARAM_OBJ_OF_CLASS_OR_NULL(obj->opt, ce_Writer_Options)
1295 ZEND_PARSE_PARAMETERS_END();
1296
1297 obj->type = STREAM_WRITER;
1298 php_stream_from_zval_no_verify(obj->stream.ptr, zstream);
1299
1300 php_ion_writer_ctor(obj);
1301 }
1302 ZEND_METHOD(ion_Writer_Stream_Writer, getStream)
1303 {
1304 php_ion_writer *obj = php_ion_obj(writer, Z_OBJ_P(ZEND_THIS));
1305 OBJ_CHECK(obj);
1306
1307 ZEND_PARSE_PARAMETERS_NONE();
1308 PTR_CHECK(obj->stream.ptr);
1309
1310 GC_ADDREF(obj->stream.ptr->res);
1311 RETURN_RES(obj->stream.ptr->res);
1312 }
1313
1314 ZEND_METHOD(ion_Serializer_PHP, __construct)
1315 {
1316 php_ion_serializer_php *obj = php_ion_obj(serializer_php, Z_OBJ_P(ZEND_THIS));
1317 PTR_CHECK(obj);
1318
1319 ZEND_PARSE_PARAMETERS_START(0, 3)
1320 Z_PARAM_OPTIONAL
1321 Z_PARAM_OBJ_OF_CLASS_OR_NULL(obj->opt, ce_Writer_Options)
1322 Z_PARAM_BOOL(obj->serializer.call_magic)
1323 Z_PARAM_STR_OR_NULL(obj->serializer.call_custom)
1324 ZEND_PARSE_PARAMETERS_END();
1325
1326 php_ion_serializer_php_ctor(obj);
1327 }
1328 ZEND_METHOD(ion_Serializer_PHP, __invoke)
1329 {
1330 zend_object *obj = Z_OBJ_P(ZEND_THIS);
1331
1332 zval *data;
1333 ZEND_PARSE_PARAMETERS_START(1, 1)
1334 Z_PARAM_ZVAL(data)
1335 ZEND_PARSE_PARAMETERS_END();
1336
1337 if (obj->ce == ce_Serializer_PHP) {
1338 // default, fast path
1339 php_ion_serialize(&php_ion_obj(serializer_php, obj)->serializer, data, return_value);
1340 } else {
1341 zend_call_method_with_1_params(obj, obj->ce, NULL /* TODO */, "serialize", return_value, data);
1342 }
1343 }
1344 ZEND_FUNCTION(ion_serialize)
1345 {
1346 zval *data;
1347 zend_object *zo_ser = NULL;
1348 ZEND_PARSE_PARAMETERS_START(1, 2)
1349 Z_PARAM_ZVAL(data)
1350 Z_PARAM_OPTIONAL
1351 Z_PARAM_OBJ_OF_CLASS_OR_NULL(zo_ser, ce_Serializer)
1352 ZEND_PARSE_PARAMETERS_END();
1353
1354 if (!zo_ser || zo_ser->ce == ce_Serializer_PHP) {
1355 // default, fast path
1356 php_ion_serializer *ser = zo_ser ? &php_ion_obj(serializer_php, zo_ser)->serializer : NULL;
1357 php_ion_serialize(ser, data, return_value);
1358 } else {
1359 zend_call_method_with_1_params(zo_ser, NULL, NULL, "__invoke", return_value, data);
1360 }
1361 }
1362 ZEND_METHOD(ion_Serializer_PHP, serialize)
1363 {
1364 //zend_object *obj = Z_OBJ_P(ZEND_THIS);
1365
1366 zval *data;
1367 ZEND_PARSE_PARAMETERS_START(1, 1)
1368 Z_PARAM_ZVAL(data)
1369 ZEND_PARSE_PARAMETERS_END();
1370
1371 // TODO
1372 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Not implemented");
1373 }
1374
1375 ZEND_METHOD(ion_Unserializer_PHP, __construct)
1376 {
1377 php_ion_unserializer_php *obj = php_ion_obj(unserializer_php, Z_OBJ_P(ZEND_THIS));
1378
1379 ZEND_PARSE_PARAMETERS_START(0, 3)
1380 Z_PARAM_OPTIONAL
1381 Z_PARAM_OBJ_OF_CLASS_OR_NULL(obj->opt, ce_Reader_Options)
1382 Z_PARAM_BOOL(obj->unserializer.call_magic)
1383 Z_PARAM_STR_OR_NULL(obj->unserializer.call_custom)
1384 ZEND_PARSE_PARAMETERS_END();
1385
1386 php_ion_unserializer_php_ctor(obj);
1387 }
1388 ZEND_METHOD(ion_Unserializer_PHP, __invoke)
1389 {
1390 zend_object *obj = Z_OBJ_P(ZEND_THIS);
1391
1392 zval *data;
1393 ZEND_PARSE_PARAMETERS_START(1, 1)
1394 Z_PARAM_ZVAL(data)
1395 ZEND_PARSE_PARAMETERS_END();
1396
1397 if (obj->ce == ce_Unserializer_PHP) {
1398 php_ion_unserialize(&php_ion_obj(unserializer_php, obj)->unserializer, data, return_value);
1399 } else {
1400 zend_call_method_with_1_params(obj, obj->ce, NULL /* TODO */, "unserialize", return_value, data);
1401 }
1402 }
1403 ZEND_FUNCTION(ion_unserialize)
1404 {
1405 zval *data;
1406 zend_object *zo_ser = NULL;
1407 ZEND_PARSE_PARAMETERS_START(1, 2)
1408 Z_PARAM_ZVAL(data)
1409 Z_PARAM_OPTIONAL
1410 Z_PARAM_OBJ_OF_CLASS_OR_NULL(zo_ser, ce_Unserializer)
1411 ZEND_PARSE_PARAMETERS_END();
1412
1413 if (!zo_ser || zo_ser->ce == ce_Unserializer_PHP) {
1414 // default, fast path
1415 php_ion_unserializer *ser = zo_ser ? &php_ion_obj(unserializer_php, zo_ser)->unserializer : NULL;
1416 php_ion_unserialize(ser, data, return_value);
1417 } else {
1418 zend_call_method_with_1_params(zo_ser, NULL, NULL, "__invoke", return_value, data);
1419 }
1420 }
1421 ZEND_METHOD(ion_Unserializer_PHP, unserialize)
1422 {
1423 //zend_object *obj = Z_OBJ_P(ZEND_THIS);
1424
1425 zval *data;
1426 ZEND_PARSE_PARAMETERS_START(1, 1)
1427 Z_PARAM_ZVAL(data)
1428 ZEND_PARSE_PARAMETERS_END();
1429
1430 // TODO
1431 zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Not implemented");
1432 }
1433
1434 PHP_RINIT_FUNCTION(ion)
1435 {
1436 #if defined(ZTS) && defined(COMPILE_DL_ION)
1437 ZEND_TSRMLS_CACHE_UPDATE();
1438 #endif
1439
1440 php_ion_globals_serializer_init();
1441 php_ion_globals_unserializer_init();
1442 return SUCCESS;
1443 }
1444
1445 PHP_RSHUTDOWN_FUNCTION(ion)
1446 {
1447 php_ion_globals_serializer_dtor();
1448 php_ion_globals_unserializer_dtor();
1449 return SUCCESS;
1450 }
1451
1452 PHP_MINIT_FUNCTION(ion)
1453 {
1454 if (!g_ion_int_zend_max) {
1455 decContextDefault(&g_dec_ctx, DEC_INIT_DECIMAL64);
1456
1457 ion_int_alloc(NULL, &g_ion_int_zend_max);
1458 ion_int_from_long(g_ion_int_zend_max, ZEND_LONG_MAX);
1459 ion_decimal_from_ion_int(&g_ion_dec_zend_max, &g_dec_ctx, g_ion_int_zend_max);
1460
1461 ion_int_alloc(NULL, &g_ion_int_zend_min);
1462 ion_int_from_long(g_ion_int_zend_min, ZEND_LONG_MIN);
1463 ion_decimal_from_ion_int(&g_ion_dec_zend_min, &g_dec_ctx, g_ion_int_zend_min);
1464 }
1465
1466 ce_Annotation = register_class_ion_Annotation();
1467
1468 php_ion_register(type, Type);
1469 php_ion_register(symbol, Symbol);
1470 php_ion_register(symbol_iloc, Symbol_ImportLocation);
1471 php_ion_register(symbol_table, Symbol_Table);
1472
1473 ce_Symbol_System = register_class_ion_Symbol_System();
1474 ce_Symbol_System_SID = register_class_ion_Symbol_System_SID();
1475
1476 ce_Collection = register_class_ion_Collection();
1477 ce_LOB = register_class_ion_LOB();
1478
1479 php_ion_register(decimal, Decimal);
1480 php_ion_register(decimal_ctx, Decimal_Context);
1481 php_ion_register(timestamp, Timestamp, php_date_get_date_ce());
1482 ce_Timestamp_Precision = register_class_ion_Timestamp_Precision();
1483 php_ion_register(catalog, Catalog);
1484
1485 ce_Reader = register_class_ion_Reader(spl_ce_RecursiveIterator);
1486
1487 php_ion_register(reader_options, Reader_Options);
1488 php_ion_register(reader, Reader_Reader, ce_Reader);
1489
1490 ce_Reader_Buffer = register_class_ion_Reader_Buffer(ce_Reader);
1491 ce_Reader_Buffer_Reader = register_class_ion_Reader_Buffer_Reader(ce_Reader_Reader, ce_Reader_Buffer);
1492 ce_Reader_Stream = register_class_ion_Reader_Stream(ce_Reader);
1493 ce_Reader_Stream_Reader = register_class_ion_Reader_Stream_Reader(ce_Reader_Reader, ce_Reader_Stream);
1494
1495 ce_Writer = register_class_ion_Writer();
1496
1497 php_ion_register(writer_options, Writer_Options);
1498 php_ion_register(writer, Writer_Writer, ce_Writer);
1499
1500 ce_Writer_Buffer = register_class_ion_Writer_Buffer(ce_Writer);
1501 ce_Writer_Buffer_Writer = register_class_ion_Writer_Buffer_Writer(ce_Writer_Writer, ce_Writer_Buffer);
1502 ce_Writer_Stream = register_class_ion_Writer_Stream(ce_Writer);
1503 ce_Writer_Stream_Writer = register_class_ion_Writer_Stream_Writer(ce_Writer_Writer, ce_Writer_Stream);
1504
1505 ce_Serializer = register_class_ion_Serializer();
1506 php_ion_register(serializer_php, Serializer_PHP, ce_Serializer);
1507 ce_Unserializer = register_class_ion_Unserializer();
1508 php_ion_register(unserializer_php, Unserializer_PHP, ce_Unserializer);
1509
1510 return SUCCESS;
1511 }
1512
1513 PHP_MSHUTDOWN_FUNCTION(ion)
1514 {
1515 if (g_ion_int_zend_max) {
1516 ion_int_free(g_ion_int_zend_max);
1517 ion_int_free(g_ion_int_zend_min);
1518 }
1519 return SUCCESS;
1520 }
1521 PHP_MINFO_FUNCTION(ion)
1522 {
1523 php_info_print_table_start();
1524 php_info_print_table_header(2, "ion support", "enabled");
1525 php_info_print_table_end();
1526 }
1527
1528 PHP_GINIT_FUNCTION(ion)
1529 {
1530 memset(ion_globals, 0, sizeof(*ion_globals));
1531 }
1532 PHP_GSHUTDOWN_FUNCTION(ion)
1533 {
1534 }
1535
1536 static zend_module_dep ion_module_deps[] = {
1537 ZEND_MOD_REQUIRED("spl")
1538 ZEND_MOD_END
1539 };
1540
1541 zend_module_entry ion_module_entry = {
1542 STANDARD_MODULE_HEADER_EX,
1543 NULL,
1544 ion_module_deps,
1545 "ion", /* Extension name */
1546 ext_functions, /* zend_function_entry */
1547 PHP_MINIT(ion), /* PHP_MINIT - Module initialization */
1548 PHP_MSHUTDOWN(ion), /* PHP_MSHUTDOWN - Module shutdown */
1549 PHP_RINIT(ion), /* PHP_RINIT - Request initialization */
1550 PHP_RSHUTDOWN(ion), /* PHP_RSHUTDOWN - Request shutdown */
1551 PHP_MINFO(ion), /* PHP_MINFO - Module info */
1552 PHP_ION_VERSION, /* Version */
1553 ZEND_MODULE_GLOBALS(ion),
1554 PHP_GINIT(ion), /* PHP_GINIT */
1555 PHP_GSHUTDOWN(ion), /* PHP_GSHUTDOWN */
1556 NULL,
1557 STANDARD_MODULE_PROPERTIES_EX
1558 };
1559
1560 #ifdef COMPILE_DL_ION
1561 # ifdef ZTS
1562 ZEND_TSRMLS_CACHE_DEFINE()
1563 # endif
1564 ZEND_GET_MODULE(ion)
1565 #endif