return SUCCESS;
}
+static struct {
+ zend_string *Year, *Month, *Day, *Min, *Sec, *Frac, *MinTZ, *SecTZ, *FracTZ;
+} g_intern_str;
+
+static void g_intern_str_init()
+{
+#define NEW_INTERN_STR(s) \
+ g_intern_str.s = zend_string_init_interned(#s, sizeof(#s)-1, 1)
+ NEW_INTERN_STR(Year);
+ NEW_INTERN_STR(Month);
+ NEW_INTERN_STR(Day);
+ NEW_INTERN_STR(Min);
+ NEW_INTERN_STR(Sec);
+ NEW_INTERN_STR(Frac);
+ NEW_INTERN_STR(MinTZ);
+ NEW_INTERN_STR(SecTZ);
+ NEW_INTERN_STR(FracTZ);
+#undef NEW_INTERN_STR
+}
+
typedef struct php_ion_serializer {
ION_WRITER *writer;
ION_WRITER_OPTIONS *options;
*ce_Symbol_Table_Shared,
*ce_Symbol_Table_System,
*ce_Timestamp,
+ *ce_Timestamp_Format,
*ce_Timestamp_Precision,
*ce_Type,
*ce_Unserializer,
php_ion_ ## type *old_obj = php_ion_obj(type, std), \
*new_obj = php_ion_obj(type, create_ion_ ## cname(std->ce)); \
php_ion_ ## type ## _copy(new_obj, old_obj); \
+ (void) old_obj; \
return &new_obj->std; \
}
#define php_ion_register(type, cname, ...) do { \
return decQuadDivide(frac, decQuadFromInt32(&us, usec), decQuadFromInt32(µsecs, 1000000), ctx);
}
+LOCAL zend_string *php_ion_timestamp_format_fetch(zend_string *fmt_case)
+{
+ return Z_STR_P(zend_enum_fetch_case_value(zend_enum_get_case(ce_Timestamp_Format, fmt_case)));
+}
+
LOCAL zend_string *php_dt_format_from_precision(uint8_t precision)
{
- switch (precision & 0x7f) {
+ switch (precision) {
+ case ION_TS_FRAC | 0x80:
+ return php_ion_timestamp_format_fetch(g_intern_str.FracTZ);
case ION_TS_FRAC:
- return zend_string_init(ZEND_STRL("c"), 0);
+ return php_ion_timestamp_format_fetch(g_intern_str.Frac);
+ case ION_TS_SEC | 0x80:
+ return php_ion_timestamp_format_fetch(g_intern_str.SecTZ);
case ION_TS_SEC:
- return zend_string_init(ZEND_STRL("Y-m-d\\TH:i:sP"), 0);
+ return php_ion_timestamp_format_fetch(g_intern_str.Sec);
+ case ION_TS_MIN | 0x80:
+ return php_ion_timestamp_format_fetch(g_intern_str.MinTZ);
case ION_TS_MIN:
- return zend_string_init(ZEND_STRL("Y-m-d\\TH:iP"), 0);
+ return php_ion_timestamp_format_fetch(g_intern_str.Min);
case ION_TS_DAY:
- return zend_string_init(ZEND_STRL("Y-m-d\\T"), 0);
+ return php_ion_timestamp_format_fetch(g_intern_str.Day);
case ION_TS_MONTH:
- return zend_string_init(ZEND_STRL("Y-m\\T"), 0);
+ return php_ion_timestamp_format_fetch(g_intern_str.Month);
case ION_TS_YEAR:
- return zend_string_init(ZEND_STRL("Y\\T"), 0);
+ return php_ion_timestamp_format_fetch(g_intern_str.Year);
default:
- return zend_string_init(ZEND_STRL("c"), 0);
+ return zend_one_char_string['c'];
}
}
{
timelib_time *time = ecalloc(1, sizeof(*time));
- int precision = ION_TS_FRAC;
- ion_timestamp_get_precision(ts, &precision);
- switch (precision) {
+ switch (ts->precision & 0x7f) {
case ION_TS_FRAC:
time->us = php_usec_from_ion(&ts->fraction, ctx);
/* fallthrough */
/* fallthrough */
default:
time->z = ts->tz_offset * 60;
- if (time->z) {
+ if (time->z || ts->precision & 0x80) {
time->zone_type = TIMELIB_ZONETYPE_OFFSET;
} else {
time->zone_type = TIMELIB_ZONETYPE_ID;
}
if (fmt) {
- *fmt = php_dt_format_from_precision(precision);
+ *fmt = php_dt_format_from_precision(ts->precision);
}
return time;
}
zval tmp;
int precision = Z_LVAL_P(zend_read_property(ts->std.ce, &ts->std, ZEND_STRL("precision"), 0, &tmp));
- if (!precision || precision > ION_TS_FRAC) {
+ if (!precision || precision > (ION_TS_FRAC|0x80)) {
zend_throw_exception_ex(spl_ce_InvalidArgumentException, IERR_INVALID_ARG,
"Invalid precision (%d) of ion\\Timestamp", precision);
- } else switch ((buf->precision = precision)) {
+ } else switch ((buf->precision = precision) & 0x7f) {
case ION_TS_FRAC:
ion_ts_frac_from_usec(&buf->fraction, (int) ts->time->us, ctx);
/* fallthrough */
LOCAL void php_ion_unserialize_object_enum(php_ion_unserializer *ser, zval *return_value)
{
zend_string *zs_case = zval_get_string(return_value);
+ zend_hash_next_index_insert(ser->tmp, return_value);
+ ZVAL_NULL(return_value);
ION_CATCH();
zend_class_entry *ce = zend_lookup_class(ser->annotations.object_class);
zend_class_entry *ce = zend_lookup_class(ser->annotations.object_class);
if (can_call_iface_unserialize(ser, ce)) {
zend_string *s = zval_get_string(return_value);
+ zend_hash_next_index_insert(ser->tmp, return_value);
ZVAL_NULL(return_value);
zval *backref = zend_hash_next_index_insert(ser->ids, return_value);
if (SUCCESS == ce->unserialize(backref, ce, (BYTE *) s->val, s->len, NULL)) {
}
}
-LOCAL void php_ion_unserialize_field_name(php_ion_unserializer *ser, zend_string **key)
+LOCAL void php_ion_unserialize_field_name_ex(php_ion_unserializer *ser, ION_STRING *name, SID *sid)
{
- // FIXME: symbol table
- ION_STRING name;
- ION_CHECK(ion_reader_get_field_name(ser->reader, &name));
- if (!name.length) {
+ ION_CHECK(ion_reader_get_field_name(ser->reader, name));
+ if (!name->length) {
ION_SYMBOL *is_ptr;
ION_CHECK(ion_reader_get_field_name_symbol(ser->reader, &is_ptr));
if (!ION_SYMBOL_IS_NULL(is_ptr) && is_ptr->value.length) {
- name = is_ptr->value;
- } else if (is_ptr) {
- char buf[MAX_LENGTH_OF_LONG + 1 + 1] = {0}, *end = buf + sizeof(buf) - 1, *ptr;
- ptr = zend_print_long_to_buf(end, is_ptr->sid);
- *--ptr = '$';
- *key = zend_string_init(ptr, end - ptr, 0);
- return;
+ ION_STRING_ASSIGN(name, &is_ptr->value);
+ } else {
+ *sid = is_ptr->sid;
+ }
+ }
+}
+
+LOCAL void php_ion_unserialize_field_name(php_ion_unserializer *ser, zend_string **key, bool is_prop)
+{
+ // FIXME: symbol table
+ ION_STRING name;
+ SID sid = UNKNOWN_SID;
+ char buf[MAX_LENGTH_OF_LONG + 1 + 1] = {0}, *end = buf + sizeof(buf) - 1, *ptr;
+
+ php_ion_unserialize_field_name_ex(ser, &name, &sid);
+ ION_CATCH();
+
+ switch (name.length) {
+ case 0:
+ ptr = zend_print_long_to_buf(end, sid);
+ *--ptr = '$';
+ *key = zend_string_init(ptr, end - ptr, 0);
+ break;
+ case 1:
+ *key = zend_one_char_string[*name.value];
+ break;
+ default:
+ if (is_prop) {
+ *key = zend_string_init_interned((char *) name.value, name.length, 0);
+ } else {
+ *key = zend_string_from_ion(&name);
}
+ break;
}
- *key = zend_string_from_ion(&name);
}
static void php_ion_unserialize_props(php_ion_unserializer *ser, zval *return_value)
}
zend_string *key;
- php_ion_unserialize_field_name(ser, &key);
+ php_ion_unserialize_field_name(ser, &key, true);
ION_CATCH();
zval zvalue;
}
zend_string *key;
- php_ion_unserialize_field_name(ser, &key);
+ php_ion_unserialize_field_name(ser, &key, false);
ION_CATCH();
zval zvalue;
{
// backup possible backref to array returned by magic/custom __serialize()
zval *input = zend_hash_next_index_insert(ser->tmp, return_value);
-
+ ZVAL_NULL(return_value);
php_ion_unserialize_class(ser, return_value);
ION_CATCH();
ION_CHECK(ion_reader_read_ion_symbol(ser->reader, &sym));
php_ion_symbol_zval(&sym, return_value);
if (ser->annotations.object_type) {
- zend_hash_next_index_insert(ser->tmp, return_value);
goto unserialize_struct;
}
zend_hash_next_index_insert(ser->ids, return_value);
ION_CHECK(ion_reader_read_string(ser->reader, &str));
RETVAL_STRINGL((char *) str.value, str.length);
if (ser->annotations.object_type) {
- zend_hash_next_index_insert(ser->tmp, return_value);
goto unserialize_struct;
}
zend_hash_next_index_insert(ser->ids, return_value);
case tid_BLOB_INT:
php_ion_reader_read_lob(ser->reader, return_value);
if (ser->annotations.object_type) {
- zend_hash_next_index_insert(ser->tmp, return_value);
goto unserialize_struct;
}
zend_hash_next_index_insert(ser->ids, return_value);
reader->buffer = zval_get_string(zdata);
} else {
zend_throw_exception_ex(spl_ce_InvalidArgumentException, IERR_INVALID_ARG,
- "Invalid source to unserialize; expected string or resource");
+ "Invalid source to unserialize: expected string or resource, got %s",
+ zend_zval_type_name(zdata));
if (zo_ser) {
OBJ_RELEASE(zo_ser);
}