+static void php_ion_catalog_copy(php_ion_catalog *new_obj, php_ion_catalog *old_obj)
+{
+ // do not clone cache members
+ php_ion_catalog_ctor(new_obj);
+ OBJ_CHECK(new_obj);
+
+ ION_COLLECTION *col = php_ion_catalog_collection(old_obj);
+ if (!ION_COLLECTION_IS_EMPTY(col)) {
+ ION_COLLECTION_CURSOR cur;
+ ION_COLLECTION_OPEN(col, cur);
+ while (cur) {
+ ION_SYMBOL_TABLE **ptr;
+ ION_COLLECTION_NEXT(cur, ptr);
+ if (*ptr) {
+ ION_CHECK(ion_catalog_add_symbol_table(new_obj->cat, *ptr));
+ }
+ }
+ }
+}
+
+static zend_string *ion_symbol_table_to_key(ION_SYMBOL_TABLE *tab)
+{
+ int32_t version;
+ ION_STRING is;
+ ION_CHECK_RETURN(NULL, ion_symbol_table_get_name(tab, &is));
+ ION_CHECK_RETURN(NULL, ion_symbol_table_get_version(tab, &version));
+
+ smart_str s = {0};
+ smart_str_appendl(&s, (char *) is.value, is.length);
+ smart_str_appendc(&s, ':');
+ smart_str_append_long(&s, version);
+ smart_str_0(&s);
+
+ return s.s;
+}
+
+static void php_ion_catalog_add_symbol_table(php_ion_catalog *obj, php_ion_symbol_table *tab)
+{
+ OBJ_CHECK(obj);
+ OBJ_CHECK(tab);
+
+ zval tmp;
+ zval *ztabs = zend_read_property(obj->std.ce, &obj->std, ZEND_STRL("symbolTables"), 0, &tmp);
+ if (ztabs) {
+ zend_ulong idx = (uintptr_t) &tab->std.gc;
+ if (!zend_hash_index_exists(Z_ARRVAL_P(ztabs), idx)) {
+ zend_string *key = ion_symbol_table_to_key(tab->tab);
+ if (key) {
+ ION_CHECK(ion_catalog_add_symbol_table(obj->cat, tab->tab),
+ zend_string_release(key));
+ SEPARATE_ARRAY(ztabs);
+ GC_ADDREF(&tab->std);
+ add_index_object(ztabs, idx, &tab->std);
+ GC_ADDREF(&tab->std);
+ add_assoc_object_ex(ztabs, key->val, key->len, &tab->std);
+ zend_update_property(obj->std.ce, &obj->std, ZEND_STRL("symbolTables"), ztabs);
+ zend_string_release(key);
+ }
+ }
+ }
+}
+
+static void php_ion_catalog_symbol_table_zval(php_ion_catalog *obj, ION_SYMBOL_TABLE *tab, zval *return_value)
+{
+ zend_string *key = ion_symbol_table_to_key(tab);
+ PTR_CHECK(key);
+
+ zval tmp;
+ zval *ztabs = zend_read_property(obj->std.ce, &obj->std, ZEND_STRL("symbolTables"), 0, &tmp);
+ if (ztabs) {
+ zval *ztab = zend_hash_find(Z_ARRVAL_P(ztabs), key);
+ if (ztab) {
+ zend_string_release(key);
+ RETURN_COPY(ztab);
+ }
+ }
+
+ object_init_ex(return_value, ce_Symbol_Table_Shared);
+ php_ion_symbol_table *o_tab = php_ion_obj(symbol_table, Z_OBJ_P(return_value));
+ o_tab->tab = tab;
+ php_ion_symbol_table_ctor(o_tab);
+
+ if (ztabs) {
+ SEPARATE_ARRAY(ztabs);
+ ZVAL_ADDREF(return_value);
+ add_index_zval(ztabs, (uintptr_t) &o_tab->std.gc, return_value);
+ ZVAL_ADDREF(return_value);
+ add_assoc_zval_ex(ztabs, key->val, key->len, return_value);
+ }
+ zend_string_release(key);
+}