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