errorCode initSchema(EXIPSchema* schema, InitSchemaType initializationType) { errorCode tmp_err_code = UNEXPECTED_ERROR; TRY(initAllocList(&schema->memList)); schema->staticGrCount = 0; SET_CONTENT_INDEX(schema->docGrammar.props, 0); schema->docGrammar.count = 0; schema->docGrammar.props = 0; schema->docGrammar.rule = NULL; schema->simpleTypeTable.count = 0; schema->simpleTypeTable.sType = NULL; schema->grammarTable.count = 0; schema->grammarTable.grammar = NULL; schema->enumTable.count = 0; schema->enumTable.enumDef = NULL; /* Create and initialize initial string table entries */ TRY_CATCH(createDynArray(&schema->uriTable.dynArray, sizeof(UriEntry), DEFAULT_URI_ENTRIES_NUMBER), freeAllocList(&schema->memList)); TRY_CATCH(createUriTableEntries(&schema->uriTable, initializationType != INIT_SCHEMA_SCHEMA_LESS_MODE), freeAllocList(&schema->memList)); if(initializationType == INIT_SCHEMA_SCHEMA_ENABLED) { /* Create and initialize enumDef table */ TRY_CATCH(createDynArray(&schema->enumTable.dynArray, sizeof(EnumDefinition), DEFAULT_ENUM_TABLE), freeAllocList(&schema->memList)); } /* Create the schema grammar table */ TRY_CATCH(createDynArray(&schema->grammarTable.dynArray, sizeof(EXIGrammar), DEFAULT_GRAMMAR_TABLE), freeAllocList(&schema->memList)); if(initializationType != INIT_SCHEMA_SCHEMA_LESS_MODE) { /* Create and initialize simple type table */ TRY_CATCH(createDynArray(&schema->simpleTypeTable.dynArray, sizeof(SimpleType), DEFAULT_SIMPLE_GRAMMAR_TABLE), freeAllocList(&schema->memList)); TRY_CATCH(createBuiltInTypesDefinitions(&schema->simpleTypeTable, &schema->memList), freeAllocList(&schema->memList)); // Must be done after createBuiltInTypesDefinitions() TRY_CATCH(generateBuiltInTypesGrammars(schema), freeAllocList(&schema->memList)); schema->staticGrCount = SIMPLE_TYPE_COUNT; } return tmp_err_code; }
errorCode addProtoRule(ProtoGrammar* pg, Index prodDim, ProtoRuleEntry** ruleEntry) { errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR; Index ruleId; TRY(addEmptyDynEntry(&pg->dynArray, (void **) ruleEntry, &ruleId)); return createDynArray(&((*ruleEntry)->dynArray), sizeof(Production), prodDim); }
errorCode createValueTable(ValueTable* valueTable) { errorCode tmp_err_code; TRY(createDynArray(&valueTable->dynArray, sizeof(ValueEntry), DEFAULT_VALUE_ENTRIES_NUMBER)); valueTable->globalId = 0; #if HASH_TABLE_USE valueTable->hashTbl = NULL; #endif return EXIP_OK; }
END_TEST START_TEST (test_addLnEntry) { errorCode err = EXIP_UNEXPECTED_ERROR; LnTable lnTable; Index entryId = 55; String test_ln = {"test_ln_string", 14}; err = createDynArray(&lnTable.dynArray, sizeof(LnEntry), DEFAULT_LN_ENTRIES_NUMBER); fail_if(err != EXIP_OK); err = addLnEntry(&lnTable, test_ln, &entryId); fail_unless (err == EXIP_OK, "addLnEntry returns error code %d", err); fail_unless (lnTable.dynArray.arrayEntries == DEFAULT_LN_ENTRIES_NUMBER, "addLnEntry changed the dynArray.arrayEntries unnecessary"); fail_unless (lnTable.count == 1, "addLnEntry did not update rowCount properly"); fail_unless (stringEqual(lnTable.ln[0].lnStr, test_ln) == 1, "addLnEntry changed the lnStr"); fail_unless (entryId == 0, "addLnEntry returned wrong entryId: %d", entryId); #if VALUE_CROSSTABLE_USE fail_if(lnTable.ln[0].vxTable != NULL); #endif lnTable.count = DEFAULT_LN_ENTRIES_NUMBER; err = addLnEntry(&lnTable, test_ln, &entryId); fail_unless (err == EXIP_OK, "addLnEntry returns error code %d", err); fail_unless (lnTable.dynArray.arrayEntries == DEFAULT_LN_ENTRIES_NUMBER*2, "addLnEntry did not update the dynArray.arrayEntries properly"); fail_unless (lnTable.count == DEFAULT_LN_ENTRIES_NUMBER + 1, "addLnEntry did not update count properly"); fail_unless (stringEqual(lnTable.ln[DEFAULT_LN_ENTRIES_NUMBER].lnStr, test_ln) == 1, "addLnEntry changed the lnStr"); fail_unless (entryId == DEFAULT_LN_ENTRIES_NUMBER, "addLnEntry returned wrong entryId: %d", entryId); #if VALUE_CROSSTABLE_USE fail_if(lnTable.ln[DEFAULT_LN_ENTRIES_NUMBER].vxTable != NULL); #endif destroyDynArray(&lnTable.dynArray); }
END_TEST START_TEST (test_addUriEntry) { errorCode err = EXIP_UNEXPECTED_ERROR; UriTable uriTable; SmallIndex entryId = 55; String test_uri = {"test_uri_string", 15}; // Create the URI table err = createDynArray(&uriTable.dynArray, sizeof(UriEntry), DEFAULT_URI_ENTRIES_NUMBER); fail_if(err != EXIP_OK); err = addUriEntry(&uriTable, test_uri, &entryId); fail_unless (err == EXIP_OK, "addUriEntry returns error code %d", err); fail_unless (uriTable.dynArray.arrayEntries == DEFAULT_URI_ENTRIES_NUMBER, "addUriEntry changed the dynArray.arrayEntries unnecessary"); fail_unless (uriTable.count == 1, "addUriEntry did not update count properly"); fail_unless (stringEqual(uriTable.uri[0].uriStr, test_uri) == 1, "addUriEntry changed the uriStr"); fail_unless (entryId == 0, "addUriEntry returned wrong entryId: %d", entryId); fail_if(uriTable.uri[0].lnTable.ln == NULL); uriTable.count = DEFAULT_URI_ENTRIES_NUMBER; err = addUriEntry(&uriTable, test_uri, &entryId); fail_unless (err == EXIP_OK, "addUriEntry returns error code %d", err); fail_unless (uriTable.dynArray.arrayEntries == DEFAULT_URI_ENTRIES_NUMBER*2, "addUriEntry did not update the dynArray.arrayEntries properly"); fail_unless (uriTable.count == DEFAULT_URI_ENTRIES_NUMBER + 1, "addUriEntry did not update rowCount properly"); fail_unless (stringEqual(uriTable.uri[DEFAULT_URI_ENTRIES_NUMBER].uriStr, test_uri) == 1, "addUriEntry changed the uriStr"); fail_unless (entryId == DEFAULT_URI_ENTRIES_NUMBER, "addUriEntry returned wrong entryId: %d", entryId); fail_if(uriTable.uri[DEFAULT_URI_ENTRIES_NUMBER].lnTable.ln == NULL); destroyDynArray(&uriTable.dynArray); }
errorCode addUriEntry(UriTable* uriTable, String uriStr, SmallIndex* uriEntryId) { errorCode tmp_err_code; UriEntry* uriEntry; Index uriLEntryId; TRY(addEmptyDynEntry(&uriTable->dynArray, (void**)&uriEntry, &uriLEntryId)); // Fill in URI entry uriEntry->uriStr = uriStr; // Prefix table is created independently uriEntry->pfxTable = NULL; // Create local names table for this URI // TODO RCC 20120201: Should this be separate (empty string URI has no local names)? TRY(createDynArray(&uriEntry->lnTable.dynArray, sizeof(LnEntry), DEFAULT_LN_ENTRIES_NUMBER)); *uriEntryId = (SmallIndex)uriLEntryId; return EXIP_OK; }
END_TEST START_TEST (test_addValueEntry) { EXIStream testStrm; errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR; String testStr = {"TEST-007", 8}; // IV: Initialize the stream { tmp_err_code = initAllocList(&(testStrm.memList)); testStrm.context.bitPointer = 0; testStrm.buffer.bufLen = 0; testStrm.buffer.bufContent = 0; tmp_err_code += createValueTable(&testStrm.valueTable); testStrm.schema = memManagedAllocate(&testStrm.memList, sizeof(EXIPSchema)); fail_unless (testStrm.schema != NULL, "Memory alloc error"); /* Create and initialize initial string table entries */ tmp_err_code += createDynArray(&testStrm.schema->uriTable.dynArray, sizeof(UriEntry), DEFAULT_URI_ENTRIES_NUMBER); tmp_err_code += createUriTableEntries(&testStrm.schema->uriTable, FALSE); } fail_unless (tmp_err_code == EXIP_OK, "initStream returns an error code %d", tmp_err_code); testStrm.gStack->currQNameID.uriId = 1; // http://www.w3.org/XML/1998/namespace testStrm.gStack->currQNameID.lnId = 2; // lang tmp_err_code = addValueEntry(&testStrm, testStr, testStrm.gStack->currQNameID); fail_unless (tmp_err_code == EXIP_OK, "addValueEntry returns an error code %d", tmp_err_code); #if VALUE_CROSSTABLE_USE fail_unless (testStrm.schema->uriTable.uri[testStrm.gStack->currQNameID.uriId].lnTable.ln[testStrm.gStack->currQNameID.lnId].vxTable != NULL, "addValueEntry does not create vxTable"); fail_unless (testStrm.schema->uriTable.uri[testStrm.gStack->currQNameID.uriId].lnTable.ln[testStrm.gStack->currQNameID.lnId].vxTable->count == 1, "addValueEntry does not create correct vxTable"); #endif fail_unless (testStrm.valueTable.count == 1, "addValueEntry does not create global value entry"); destroyDynArray(&testStrm.valueTable.dynArray); destroyDynArray(&testStrm.schema->uriTable.dynArray); freeAllocList(&testStrm.memList); }
errorCode initSchema(EXIPSchema* schema, unsigned char initializationType) { errorCode tmp_err_code = UNEXPECTED_ERROR; tmp_err_code = initAllocList(&schema->memList); if(tmp_err_code != ERR_OK) return tmp_err_code; schema->staticGrCount = 0; schema->docGrammar.contentIndex = 0; schema->docGrammar.count = 0; schema->docGrammar.props = 0; schema->docGrammar.rule = NULL; schema->simpleTypeTable.count = 0; schema->simpleTypeTable.sType = NULL; schema->grammarTable.count = 0; schema->grammarTable.grammar = NULL; schema->enumTable.count = 0; schema->enumTable.enumDef = NULL; /* Create and initialize initial string table entries */ tmp_err_code = createDynArray(&schema->uriTable.dynArray, sizeof(UriEntry), DEFAULT_URI_ENTRIES_NUMBER); if(tmp_err_code != ERR_OK) { freeAllocList(&schema->memList); return tmp_err_code; } tmp_err_code = createUriTableEntries(&schema->uriTable, initializationType != INIT_SCHEMA_SCHEMA_LESS_MODE); if(tmp_err_code != ERR_OK) { freeAllocList(&schema->memList); return tmp_err_code; } if(initializationType == INIT_SCHEMA_SCHEMA_ENABLED) { /* Create and initialize enumDef table */ tmp_err_code = createDynArray(&schema->enumTable.dynArray, sizeof(EnumDefinition), DEFAULT_ENUM_TABLE); if(tmp_err_code != ERR_OK) { freeAllocList(&schema->memList); return tmp_err_code; } } /* Create the schema grammar table */ tmp_err_code = createDynArray(&schema->grammarTable.dynArray, sizeof(EXIGrammar), DEFAULT_GRAMMAR_TABLE); if(tmp_err_code != ERR_OK) { freeAllocList(&schema->memList); return tmp_err_code; } if(initializationType != INIT_SCHEMA_SCHEMA_LESS_MODE) { /* Create and initialize simple type table */ tmp_err_code = createDynArray(&schema->simpleTypeTable.dynArray, sizeof(SimpleType), DEFAULT_SIMPLE_GRAMMAR_TABLE); if(tmp_err_code != ERR_OK) { freeAllocList(&schema->memList); return tmp_err_code; } tmp_err_code = createBuiltInTypesDefinitions(&schema->simpleTypeTable, &schema->memList); if(tmp_err_code != ERR_OK) { freeAllocList(&schema->memList); return tmp_err_code; } // Must be done after createBuiltInTypesDefinitions() tmp_err_code = generateBuiltInTypesGrammars(schema); if(tmp_err_code != ERR_OK) { freeAllocList(&schema->memList); } schema->staticGrCount = SIMPLE_TYPE_COUNT; } return tmp_err_code; }
errorCode createProtoGrammar(Index rulesDim, ProtoGrammar* pg) { pg->contentIndex = 0; return createDynArray(&pg->dynArray, sizeof(ProtoRuleEntry), rulesDim); }
errorCode addValueEntry(EXIStream* strm, String valueStr, QNameID qnameID) { errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR; ValueEntry* valueEntry = NULL; Index valueEntryId; #if VALUE_CROSSTABLE_USE Index vxEntryId; { struct LnEntry* lnEntry; VxEntry vxEntry; // Find the local name entry from QNameID lnEntry = &GET_LN_URI_QNAME(strm->schema->uriTable, qnameID); // Add entry to the local name entry's value cross table (vxTable) if(lnEntry->vxTable == NULL) { lnEntry->vxTable = memManagedAllocate(&strm->memList, sizeof(VxTable)); if(lnEntry->vxTable == NULL) return EXIP_MEMORY_ALLOCATION_ERROR; // First value entry - create the vxTable TRY(createDynArray(&lnEntry->vxTable->dynArray, sizeof(VxEntry), DEFAULT_VX_ENTRIES_NUMBER)); } assert(lnEntry->vxTable->vx); // Set the global ID in the value cross table entry vxEntry.globalId = strm->valueTable.globalId; // Add the entry TRY(addDynEntry(&lnEntry->vxTable->dynArray, (void*) &vxEntry, &vxEntryId)); } #endif // If the global ID is less than the actual array size, we must have wrapped around // In this case, we must reuse an existing entry if(strm->valueTable.globalId < strm->valueTable.count) { // Get the existing value entry valueEntry = &strm->valueTable.value[strm->valueTable.globalId]; #if VALUE_CROSSTABLE_USE assert(GET_LN_URI_QNAME(strm->schema->uriTable, valueEntry->locValuePartition.forQNameId).vxTable); // Null out the existing cross table entry GET_LN_URI_QNAME(strm->schema->uriTable, valueEntry->locValuePartition.forQNameId).vxTable->vx[valueEntry->locValuePartition.vxEntryId].globalId = INDEX_MAX; #endif #if HASH_TABLE_USE // Remove existing value string from hash table (if present) if(strm->valueTable.hashTbl != NULL) { hashtable_remove(strm->valueTable.hashTbl, valueEntry->valueStr); } #endif // Free the memory allocated by the previous string entry EXIP_MFREE(valueEntry->valueStr.str); } else { // We are filling up the array and have not wrapped round yet // See http://www.w3.org/TR/exi/#encodingOptimizedForMisses TRY(addEmptyDynEntry(&strm->valueTable.dynArray, (void**)&valueEntry, &valueEntryId)); } // Set the value entry fields valueEntry->valueStr = valueStr; #if VALUE_CROSSTABLE_USE valueEntry->locValuePartition.forQNameId = qnameID; valueEntry->locValuePartition.vxEntryId = vxEntryId; #endif #if HASH_TABLE_USE // Add value string to hash table (if present) if(strm->valueTable.hashTbl != NULL) { TRY(hashtable_insert(strm->valueTable.hashTbl, valueStr, strm->valueTable.globalId)); } #endif // Increment global ID strm->valueTable.globalId++; // The value table is limited by valuePartitionCapacity. If we have exceeded, we wrap around // to the beginning of the value table and null out existing IDs in the corresponding // cross table IDs if(strm->valueTable.globalId == strm->header.opts.valuePartitionCapacity) strm->valueTable.globalId = 0; return EXIP_OK; }