iERR ionizer_load_writer_symbol_table(hSYMTAB *p_hsymtab, char *symtab_file_name) { iENTER; FILE *f_symtab; FSTREAM_READER_STATE *reader; hSYMTAB hsymtab; ION_TYPE type; // open the file, then open the catalog f_symtab = fopen(symtab_file_name, "rb"); if (!f_symtab) { fprintf(stderr, "ERROR: can't open the catalog file: %s\n", symtab_file_name); FAILWITH(IERR_CANT_FIND_FILE); } CHECK(ionizer_reader_open_fstream(&reader, f_symtab, NULL), "symbol table reader open failed"); CHECK(ionizer_reader_next(reader->hreader, &type), "reading to the first value in the symbol table file"); if (type != tid_STRUCT) { fprintf(stderr, "ERROR - specified symbol table file doesn't start with a struct\n"); FAILWITH(IERR_INVALID_SYMBOL_TABLE); } // load it CHECK(ion_symbol_table_load(reader->hreader, g_hcatalog, &hsymtab), "loading a symbol table for the catalog"); // close up CHECK(ionizer_reader_close_fstream(reader), "closing a catalog reader"); fclose(f_symtab); // return the table handle *p_hsymtab = hsymtab; iRETURN; }
// // build symbol table routines, including load, init, fill, update and write // iERR ionizer_load_symbol_table(void) { iENTER; ION_STRING temp; SIZE len; if (!g_writer_options.pcatalog) { ionizer_print_help(); fprintf(stderr, "\nthe writer symbol table (%s) must be included in the catalog\n", g_ionizer_writer_symtab); } len = _ion_strnlen(g_ionizer_writer_symtab, (size_t)1024); // TODO, this is wrong-ish, what the max size of an command line arg? ion_string_assign_cstr(&temp, g_ionizer_writer_symtab, len); CHECK(ion_catalog_find_best_match(g_hcatalog , &temp , 0 ,&g_writer_hsymtab ), "finding the writer symbol table in the catalog"); // if we didn't find the symbol name in the catalog try to open it in a file if (!g_writer_hsymtab) { CHECK(ionizer_load_writer_symbol_table(&g_writer_hsymtab, g_ionizer_writer_symtab), "load writer symbol table from a file"); } if (!g_writer_hsymtab) { fprintf(stderr, "ERROR - couldn't find the symbol table \"%s\" in the catalog or as a file\n", g_ionizer_writer_symtab); FAILWITH(IERR_CANT_FIND_FILE); } g_writer_options.encoding_psymbol_table = (ION_SYMBOL_TABLE *)g_writer_hsymtab; // HACK - TODO - do the same that that we do for catalog iRETURN; }
// // catalog routines - load an additional catalog file (file with multiple shared // symbol tables in it) also the "load output (writer's) // shared symbol table for binary encoding. // iERR ionizer_load_catalog_list(hCATALOG *p_catalog) { iENTER; FILE *f_catalog; IONIZER_STR_NODE *str_node; FSTREAM_READER_STATE *reader; hCATALOG catalog; hREADER hreader; ION_TYPE t; BOOL is_symtab; BOOL saved_flag_return_shared_symbol_tables; hSYMTAB hsymtab; ION_STRING annotion_name; ION_STRING_INIT(&annotion_name); ion_string_assign_cstr(&annotion_name, ION_SYS_SYMBOL_SHARED_SYMBOL_TABLE, ION_SYS_STRLEN_SHARED_SYMBOL_TABLE); CHECK(ion_catalog_open(&catalog), "create empty catalog"); // since we (Ionize) want to handle the symbol table management we need to // tell the reader no to bother (we'll go back to what others wanted later) saved_flag_return_shared_symbol_tables = g_reader_options.return_shared_symbol_tables; g_reader_options.return_shared_symbol_tables = TRUE; for (str_node=g_ionizer_catalogs; str_node; str_node = str_node->next) { // open the file, then open the catalog f_catalog = fopen(str_node->str, "rb"); if (!f_catalog) { fprintf(stderr, "ERROR: can't open the catalog file: %s\n", str_node->str); FAILWITH(IERR_CANT_FIND_FILE); } // XXX g_reader_options.return_shared_symbol_tables = TRUE; CHECK(ionizer_reader_open_fstream(&reader, f_catalog, &g_reader_options), "catalog reader open failed"); // XXX g_reader_options.return_shared_symbol_tables = FALSE; // read the file and load all structs with the ion_shared_symbol_table // annotation into the hcatalog hreader = reader->hreader; // just because it's shorter for (;;) { CHECK(ionizer_reader_next(hreader, &t), "look for the next symtab in the catalog"); if (t == tid_EOF) break; if (t != tid_STRUCT) continue; // symbol tables are always structs CHECK(ion_reader_has_annotation(hreader, &annotion_name, &is_symtab), "checking annotation"); if (is_symtab) { CHECK(ion_symbol_table_load(hreader, catalog, &hsymtab), "loading a symbol table for the catalog"); CHECK(ion_catalog_add_symbol_table(catalog, hsymtab), "adding a symbol table to the catalog"); } } CHECK(ionizer_reader_close_fstream(reader), "closing a catalog reader"); // ion_reader_close_fstream closes this already: fclose(f_catalog); } // now return to our regularly scheduled behavior ... g_reader_options.return_shared_symbol_tables = saved_flag_return_shared_symbol_tables; *p_catalog = catalog; iRETURN; }
iERR _ion_strdup(hOWNER owner, iSTRING dst, iSTRING src) { iENTER; BOOL is_empty = (src->length == 0 && src->value); // Distinguishing from null string, which has NULL value. if (!owner || !dst || !src) FAILWITH(IERR_INVALID_ARG); if (dst->length < src->length || src->length == 0) { dst->value = (BYTE *)ion_alloc_with_owner(owner, (is_empty) ? 1 : src->length); if (!dst->value) FAILWITH(IERR_NO_MEMORY); } memcpy(dst->value, (is_empty) ? "\0" : src->value, (is_empty) ? 1 : src->length); dst->length = src->length; iRETURN; }
iERR _dbg_ion_strdup(hOWNER owner, iSTRING dst, iSTRING src, const char *file, int line) { iENTER; long cmd = debug_cmd_counter(); if (!owner || !dst || !src) FAILWITH(IERR_INVALID_ARG); if (dst->length < src->length) { dst->value = ion_alloc_with_owner(owner, src->length); if (!dst->value) FAILWITH(IERR_NO_MEMORY); } memcpy(dst->value, src->value, src->length); dst->length = src->length; _dbg_ion_message("___STR", ION_ALLOC_USER_PTR_TO_BLOCK(dst->value), src->length); iRETURN; }
iERR ionizer_writer_write_all_values( hWRITER hwriter, hREADER hreader ) { iENTER; ION_TYPE t; BOOL is_null; if (g_ionizer_include_type_counts == FALSE) { // just pass through and get out of the way CHECKREADER( ion_writer_write_all_values( hwriter, hreader ), "write all values, don't count", hreader ); } else { // if we have to count, we have to traverse the values here for (;;) { CHECKREADER(ionizer_reader_next(hreader, &t),"read next helper that counts values", hreader); switch(ION_TYPE_INT(t)) { case (intptr_t)tid_EOF: SUCCEED(); // we're done at this level case (intptr_t)tid_NULL: // also handled in the previous switch case (intptr_t)tid_BOOL: case (intptr_t)tid_INT: case (intptr_t)tid_FLOAT: case (intptr_t)tid_DECIMAL: case (intptr_t)tid_TIMESTAMP: case (intptr_t)tid_STRING: case (intptr_t)tid_SYMBOL: case (intptr_t)tid_CLOB: case (intptr_t)tid_BLOB: CHECKREADER(ion_writer_write_one_value(hwriter, hreader), "write one value", hreader); break; case (intptr_t)tid_STRUCT: case (intptr_t)tid_LIST: case (intptr_t)tid_SEXP: CHECKREADER(ion_reader_is_null(hreader, &is_null), "is null", hreader); if (is_null) { CHECKREADER(ion_writer_write_one_value(hwriter, hreader), "write one value", hreader); } else { CHECKREADER(ion_reader_step_in(hreader), "step in", hreader); CHECKREADER(ionizer_writer_write_all_values(hwriter, hreader), "write container", hreader); CHECKREADER(ion_reader_step_out(hreader), "step out", hreader); SUCCEED(); } default: FAILWITH(IERR_INVALID_STATE); } } } iRETURN; }
iERR test_bad_file(hREADER hreader) { iENTER; err = test_reader_read_all(hreader); if (IERR_OK == err) { FAILWITH(IERR_INVALID_ARG); } else { err = IERR_OK; } iRETURN; };
iERR symbol_table_write( hWRITER hwriter ) { iENTER; ION_STRING temp; ION_SYMBOL *sym; SID ii, sorted_count, sid, max_sid; SID *sidlist = NULL; if (!g_hsymtab) { fprintf(stderr, "No symbol table found to write."); SUCCEED(); } // first we prefix this with an ion version marker CHECK(ion_writer_write_symbol(hwriter, &ION_SYMBOL_VTM_STRING), "write ion version marker"); // now we write it out one way or another CHECK(ion_symbol_table_unload(g_hsymtab, hwriter), "writing the symbol table"); if (g_include_counts) { // we write the counts after the symbol table in an annotated struct IONCHECK(ion_writer_add_annotation(hwriter, &g_symbol_counts_str)); IONCHECK(ion_writer_start_container(hwriter, tid_LIST)); IONCHECK(ion_symbol_table_get_max_sid(g_hsymtab, &max_sid)); // allocate and initialize the array of sid so we can sort the symbols // in the list. This isn't particularly efficient since we'll call // ion_symbol_table_get_local_symbol twice (for the two symbols we're // comparing) to get the symbol data to compare with. We could use // a struct (or an array of symbols structs) to do this, but this was // easy and it's not exactly a critical path operation. sidlist = (int *)malloc(max_sid * sizeof(int)); if (!sidlist) { FAILWITH(IERR_NO_MEMORY); } sorted_count = 0; for (sid=1; sid<=max_sid; sid++) { IONCHECK(ion_symbol_table_get_local_symbol(g_hsymtab, sid, &sym)); // get symbol to see if it's a local symbol if (!sym) continue; sidlist[sorted_count++] = sid; } // we might want to sort by name some time later (perhaps even an option) qsort(sidlist, (size_t)sorted_count, sizeof(int), compare_sids_by_count); // now, with the sidlist as a level of indirection, we read the symbols // again in order to output the symbols with their use counts for (ii=0; ii<sorted_count; ii++) { sid = sidlist[ii]; IONCHECK(ion_symbol_table_get_local_symbol(g_hsymtab, sid, &sym)); // get symbols by sid, iterate from 1 to max_sid - returns all symbols if (!sym) continue; // not all symbols are local to this table IONCHECK(ion_writer_start_container(hwriter, tid_STRUCT)); IONCHECK(ion_writer_write_field_name(hwriter, ion_string_assign_cstr(&temp, "sid", 3))); IONCHECK(ion_writer_write_int(hwriter, sym->sid)); IONCHECK(ion_writer_write_field_name(hwriter, ion_string_assign_cstr(&temp, "name", 4))); IONCHECK(ion_writer_write_string(hwriter, &sym->value)); IONCHECK(ion_writer_write_field_name(hwriter, ion_string_assign_cstr(&temp, "count", 5))); IONCHECK(ion_writer_write_int(hwriter, sym->add_count)); IONCHECK(ion_writer_finish_container(hwriter)); } IONCHECK(ion_writer_finish_container(hwriter)); } iRETURN; }