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