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