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