php_ion_symbol_table *o_symtab = php_ion_obj(symbol_table, zo_symtab);
php_ion_catalog_add_symbol_table(obj, o_symtab);
}
-struct remove_symtab_ctx {
- const char *name;
- zend_bool deleted;
-};
-static int remove_symtab(zval *ztab, void *ctx)
-{
- struct remove_symtab_ctx *rsc = ctx;
- php_ion_symbol_table *tab = php_ion_obj(symbol_table, Z_OBJ_P(ztab));
- if (tab && tab->tab) {
- ION_STRING is;
- if (IERR_OK == ion_symbol_table_get_name(tab->tab, &is)) {
- if (strcmp((const char *) is.value, rsc->name)) {
- return ZEND_HASH_APPLY_KEEP;
- }
- }
- }
- rsc->deleted = true;
- return ZEND_HASH_APPLY_REMOVE;
-}
static ZEND_METHOD(ion_Catalog, remove)
{
php_ion_catalog *obj = php_ion_obj(catalog, Z_OBJ_P(ZEND_THIS));
if (zo_symtab) {
// fast path
zend_ulong idx = (uintptr_t) &zo_symtab->gc;
- RETURN_BOOL(SUCCESS == zend_hash_index_del(Z_ARRVAL_P(ztabs), idx));
+ RETVAL_BOOL(SUCCESS == zend_hash_index_del(Z_ARRVAL_P(ztabs), idx));
+ ION_CHECK(ion_catalog_release_symbol_table(obj->cat, php_ion_obj(symbol_table, zo_symtab)->tab));
} else {
- // iterate over all symbol tables and delete any with matching name
- struct remove_symtab_ctx ctx = {zs_symtab->val, false};
- zend_hash_apply_with_argument(Z_ARRVAL_P(ztabs), remove_symtab, &ctx);
- RETURN_BOOL(ctx.deleted);
+ bool deleted = false;
+ ION_SYMBOL_TABLE *tab;
+ ION_STRING is;
+ ion_string_from_zend(&is, zs_symtab);
+ do {
+ tab = NULL;
+ ION_CHECK(ion_catalog_find_best_match(obj->cat, &is, 0, &tab));
+ if (tab) {
+ ION_CHECK(ion_catalog_release_symbol_table(obj->cat, tab));
+ deleted = true;
+ }
+ } while(tab);
+ RETVAL_BOOL(deleted);
}
}
}
return IERR_OK;
}
+static inline ION_COLLECTION *php_ion_catalog_collection(php_ion_catalog *cat)
+{
+ /* do not look too close */
+ struct {
+ void *owner;
+ ION_SYMBOL_TABLE *sys;
+ ION_COLLECTION collection;
+ } *cat_ptr = (void *) cat->cat;
+ return &cat_ptr->collection;
+}
+
+static inline void php_ion_writer_options_init_shared_imports(php_ion_writer_options *opt)
+{
+ php_ion_catalog *cat = php_ion_obj(catalog, opt->cat);
+ OBJ_CHECK(cat);
+
+ ION_CHECK(ion_writer_options_initialize_shared_imports(&opt->opt));
+
+ ION_COLLECTION *col = php_ion_catalog_collection(cat);
+ if (!ION_COLLECTION_IS_EMPTY(col)) {
+ // holy, nah, forget it batman...
+#ifndef IPCN_pNODE_TO_pDATA
+# define IPCN_pNODE_TO_pDATA(x) (&((x)->_data[0]))
+#endif
+ 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_writer_options_add_shared_imports_symbol_tables(&opt->opt, ptr, 1));
+ } else {
+ break;
+ }
+ }
+ }
+}
+
static inline void php_ion_writer_ctor(php_ion_writer *obj)
{
+ php_ion_writer_options *opt = NULL;
+
if (obj->opt) {
update_property_obj(&obj->std, ZEND_STRL("options"), obj->opt);
+ opt = php_ion_obj(writer_options, obj->opt);
+ if (opt->cat) {
+ php_ion_writer_options_init_shared_imports(opt);
+ }
}
- php_ion_writer_options *opt = php_ion_obj(writer_options, obj->opt);
ION_STREAM_HANDLER h;
if (obj->type == STREAM_WRITER) {
h = php_ion_writer_stream_handler;
php_ion_writer_buffer_init(obj);
}
+
ION_CHECK(ion_writer_open_stream(&obj->writer, h, obj, opt ? &opt->opt : NULL));
OBJ_CHECK(obj);
}
if (obj->writer) {
ion_writer_close(obj->writer);
}
+ if (obj->opt) {
+ php_ion_writer_options *opt = php_ion_obj(writer_options, obj->opt);
+ if (opt->cat) {
+ ion_writer_options_close_shared_imports(&opt->opt);
+ }
+ }
if (obj->type == STREAM_WRITER) {
if (obj->stream.buf.value) {
efree(obj->stream.buf.value);
var_dump($c->find("shared", 1));
var_dump($c->findBest("shared"));
+$c->remove("shared");
+var_dump(count($c));
?>
DONE
--EXPECTF--
array(0) {
}
}
+int(1)
DONE
+++ /dev/null
---TEST--
-Symbol\Table\Shared/roundtrip
---EXTENSIONS--
-ion
---FILE--
-TEST
-<?php
-$s = '$ion_shared_symbol_table::{name:"shared",version:1,symbols:["foo","bar","baz"]}';
-$t = new ion\Symbol\Table\Shared(name: "shared", symbols: ["foo","bar","baz"]);
-var_dump(
- ion\serialize(
- ion\unserialize(
- ion\serialize(
- ion\unserialize(
- ion\serialize($t)
- )
- )
- )
- )
-);
-
-var_dump(
- ion\unserialize(
- ion\serialize(
- ion\unserialize(
- ion\serialize(
- ion\unserialize($s)
- )
- )
- )
- )
-);
-?>
-DONE
---EXPECTF--
-TEST
-string(79) "$ion_shared_symbol_table::{name:"shared",version:1,symbols:["foo","bar","baz"]}"
-object(ion\Symbol\Table\Shared)#%d (3) {
- ["name"]=>
- string(6) "shared"
- ["version"]=>
- int(1)
- ["symbols":"ion\Symbol\Table\Shared":private]=>
- array(0) {
- }
-}
-DONE
--- /dev/null
+--TEST--
+ion\Symbol\Table\Local
+--EXTENSIONS--
+ion
+--FILE--
+TEST
+<?php
+
+$w = new ion\Writer\Buffer\Writer($buf,
+ new ion\Writer\Options(outputBinary: true));
+
+$w->writeSymbol("local1");
+$w->writeSymbol("local1");
+$w->writeSymbol("local2");
+$w->writeSymbol("local2");
+
+$w->finish();
+
+foreach (str_split($buf, 8) as $line) {
+ printf("%-26s", chunk_split(bin2hex($line), 2, " "));
+ foreach (str_split($line) as $byte) {
+ echo ctype_print($byte) ? $byte : ".";
+ }
+ echo "\n";
+}
+echo "\n";
+
+$u = new ion\Unserializer\PHP(multiSequence: true);
+var_dump($u($buf));
+
+?>
+DONE
+--EXPECTF--
+TEST
+e0 01 00 ea ee 95 81 83 ........
+de 91 87 be 8e 86 6c 6f ......lo
+63 61 6c 31 86 6c 6f 63 cal1.loc
+61 6c 32 71 0a 71 0a 71 al2q.q.q
+0b 71 0b .q.
+
+array(4) {
+ [0]=>
+ object(ion\Symbol)#%d (3) {
+ ["value"]=>
+ string(6) "local1"
+ ["sid"]=>
+ int(10)
+ ["importLocation"]=>
+ NULL
+ }
+ [1]=>
+ object(ion\Symbol)#%d (3) {
+ ["value"]=>
+ string(6) "local1"
+ ["sid"]=>
+ int(10)
+ ["importLocation"]=>
+ NULL
+ }
+ [2]=>
+ object(ion\Symbol)#%d (3) {
+ ["value"]=>
+ string(6) "local2"
+ ["sid"]=>
+ int(11)
+ ["importLocation"]=>
+ NULL
+ }
+ [3]=>
+ object(ion\Symbol)#%d (3) {
+ ["value"]=>
+ string(6) "local2"
+ ["sid"]=>
+ int(11)
+ ["importLocation"]=>
+ NULL
+ }
+}
+DONE
--- /dev/null
+--TEST--
+ion\Symbol\Table\Shared
+--EXTENSIONS--
+ion
+--FILE--
+TEST
+<?php
+
+$c = new ion\Catalog;
+$c->add(new ion\Symbol\Table\Shared("shared", 1, ["shared1", "shared2"]));
+$w = new ion\Writer\Buffer\Writer($buf,
+ new ion\Writer\Options(catalog: $c, outputBinary: true));
+
+$w->writeSymbol("shared1");
+$w->writeSymbol("shared1");
+$w->writeSymbol("shared2");
+$w->writeSymbol("shared2");
+
+$w->finish();
+
+foreach (str_split($buf, 8) as $line) {
+ printf("%-26s", chunk_split(bin2hex($line), 2, " "));
+ foreach (str_split($line) as $byte) {
+ echo ctype_print($byte) ? $byte : ".";
+ }
+ echo "\n";
+}
+echo "\n";
+
+$u = new ion\Unserializer\PHP(multiSequence: true);
+var_dump($u($buf));
+
+$u = new ion\Unserializer\PHP(multiSequence: true,
+ readerOptions: new ion\Reader\Options(catalog: $c));
+var_dump($u($buf));
+
+?>
+DONE
+--EXPECTF--
+TEST
+e0 01 00 ea ee 97 81 83 ........
+de 93 86 be 90 de 8e 84 ........
+86 73 68 61 72 65 64 85 .shared.
+21 01 88 21 02 71 0a 71 !..!.q.q
+0a 71 0b 71 0b .q.q.
+
+array(4) {
+ [0]=>
+ object(ion\Symbol)#%d (3) {
+ ["value"]=>
+ string(0) ""
+ ["sid"]=>
+ int(10)
+ ["importLocation"]=>
+ object(ion\Symbol\ImportLocation)#%d (2) {
+ ["name"]=>
+ string(6) "shared"
+ ["location"]=>
+ int(1)
+ }
+ }
+ [1]=>
+ object(ion\Symbol)#%d (3) {
+ ["value"]=>
+ string(0) ""
+ ["sid"]=>
+ int(10)
+ ["importLocation"]=>
+ object(ion\Symbol\ImportLocation)#%d (2) {
+ ["name"]=>
+ string(6) "shared"
+ ["location"]=>
+ int(1)
+ }
+ }
+ [2]=>
+ object(ion\Symbol)#%d (3) {
+ ["value"]=>
+ string(0) ""
+ ["sid"]=>
+ int(11)
+ ["importLocation"]=>
+ object(ion\Symbol\ImportLocation)#%d (2) {
+ ["name"]=>
+ string(6) "shared"
+ ["location"]=>
+ int(2)
+ }
+ }
+ [3]=>
+ object(ion\Symbol)#%d (3) {
+ ["value"]=>
+ string(0) ""
+ ["sid"]=>
+ int(11)
+ ["importLocation"]=>
+ object(ion\Symbol\ImportLocation)#%d (2) {
+ ["name"]=>
+ string(6) "shared"
+ ["location"]=>
+ int(2)
+ }
+ }
+}
+on_context_change
+array(4) {
+ [0]=>
+ object(ion\Symbol)#%d (3) {
+ ["value"]=>
+ string(7) "shared1"
+ ["sid"]=>
+ int(10)
+ ["importLocation"]=>
+ object(ion\Symbol\ImportLocation)#%d (2) {
+ ["name"]=>
+ string(6) "shared"
+ ["location"]=>
+ int(1)
+ }
+ }
+ [1]=>
+ object(ion\Symbol)#%d (3) {
+ ["value"]=>
+ string(7) "shared1"
+ ["sid"]=>
+ int(10)
+ ["importLocation"]=>
+ object(ion\Symbol\ImportLocation)#%d (2) {
+ ["name"]=>
+ string(6) "shared"
+ ["location"]=>
+ int(1)
+ }
+ }
+ [2]=>
+ object(ion\Symbol)#%d (3) {
+ ["value"]=>
+ string(7) "shared2"
+ ["sid"]=>
+ int(11)
+ ["importLocation"]=>
+ object(ion\Symbol\ImportLocation)#%d (2) {
+ ["name"]=>
+ string(6) "shared"
+ ["location"]=>
+ int(2)
+ }
+ }
+ [3]=>
+ object(ion\Symbol)#%d (3) {
+ ["value"]=>
+ string(7) "shared2"
+ ["sid"]=>
+ int(11)
+ ["importLocation"]=>
+ object(ion\Symbol\ImportLocation)#%d (2) {
+ ["name"]=>
+ string(6) "shared"
+ ["location"]=>
+ int(2)
+ }
+ }
+}
+DONE
--- /dev/null
+--TEST--
+Symbol\Table\Shared/roundtrip
+--EXTENSIONS--
+ion
+--FILE--
+TEST
+<?php
+$s = '$ion_shared_symbol_table::{name:"shared",version:1,symbols:["foo","bar","baz"]}';
+$t = new ion\Symbol\Table\Shared(name: "shared", symbols: ["foo","bar","baz"]);
+var_dump(
+ ion\serialize(
+ ion\unserialize(
+ ion\serialize(
+ ion\unserialize(
+ ion\serialize($t)
+ )
+ )
+ )
+ )
+);
+
+var_dump(
+ ion\unserialize(
+ ion\serialize(
+ ion\unserialize(
+ ion\serialize(
+ ion\unserialize($s)
+ )
+ )
+ )
+ )
+);
+?>
+DONE
+--EXPECTF--
+TEST
+string(79) "$ion_shared_symbol_table::{name:"shared",version:1,symbols:["foo","bar","baz"]}"
+object(ion\Symbol\Table\Shared)#%d (3) {
+ ["name"]=>
+ string(6) "shared"
+ ["version"]=>
+ int(1)
+ ["symbols":"ion\Symbol\Table\Shared":private]=>
+ array(0) {
+ }
+}
+DONE