/* ******************************************************************************* * Copyright (C) 1997-1999, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ //=============================================================================== // // File tcoldata.cpp // // Internal file. Implements TableCollationData, an internal class which is shared // by TableCollation objects, and which contains all the invariant (and large) // pieces of data. Once created, TableCollationData objects do not change. // // Created by: Alan Liu // // Modification History: // // Date Name Description // 2/5/97 aliu Creation. // 3/5/97 aliu Don't stream rule table in or out. //=============================================================================== #include "ucmp32.h" #include "tcoldata.h" #include "tables.h" #include "mutex.h" #include "unicode/tblcoll.h" //=============================================================================== CollationCache TableCollationData::fgCache; //=============================================================================== TableCollationData::TableCollationData() : isFrenchSec(FALSE), maxSecOrder(0), maxTerOrder(0), fBogus(FALSE), isRuleTableLoaded(FALSE) { mapping = 0; contractTable = 0; expandTable = 0; } TableCollationData::~TableCollationData() { ucmp32_close(mapping); delete contractTable; delete expandTable; } UBool TableCollationData::isBogus() const { return fBogus; } void TableCollationData::streamIn(FileStream* is) { if (!T_FileStream_error(is)) { // Stream in large objects char isNull; T_FileStream_read(is, &isNull, sizeof(isNull)); if (isNull) { ucmp32_close(mapping); mapping = 0; } else { // Slight ugliness: We are a friend of TableCollation solely so // we can access the constant UNMAPPED here. In fact, this code // path shouldn't really happen, because mapping should always != 0. // if (mapping == 0) mapping = ucmp32_open(RuleBasedCollator::UNMAPPED); if (mapping->fBogus ){ fBogus = TRUE; return; } ucmp32_streamIn(mapping, is); if (mapping->fBogus) { fBogus = TRUE; ucmp32_close(mapping); mapping = 0; return; } } T_FileStream_read(is, &isNull, sizeof(isNull)); if (isNull) { delete contractTable; contractTable = 0; } else { if (contractTable == 0) contractTable = new VectorOfPToContractTable; if (contractTable->isBogus()) { fBogus = TRUE; return; } contractTable->streamIn(is); if (contractTable->isBogus()) { fBogus = TRUE; ucmp32_close(mapping); mapping = 0; delete contractTable; contractTable = 0; return; } } T_FileStream_read(is, &isNull, sizeof(isNull)); if (isNull) { delete expandTable; expandTable = 0; } else { if (expandTable == 0) expandTable = new VectorOfPToExpandTable; if (expandTable->isBogus()) { fBogus = TRUE; return; } expandTable->streamIn(is); if (expandTable->isBogus()) { fBogus = TRUE; ucmp32_close(mapping); mapping = 0; delete contractTable; contractTable = 0; delete expandTable; expandTable = 0; return; } } // We don't stream in or out the rule table, in order to keep // binary files small. We reconstruct rules on the fly. ruleTable.remove(); isRuleTableLoaded = FALSE; // Stream in the small objects T_FileStream_read(is, &isFrenchSec, sizeof(isFrenchSec)); T_FileStream_read(is, &maxSecOrder, sizeof(maxSecOrder)); T_FileStream_read(is, &maxTerOrder, sizeof(maxTerOrder)); } } void TableCollationData::streamOut(FileStream* os) const { if (!T_FileStream_error(os)) { // Stream out the large objects char isNull; isNull = (mapping == 0); T_FileStream_write(os, &isNull, sizeof(isNull)); if (!isNull) ucmp32_streamOut(mapping, os); isNull = (contractTable == 0); T_FileStream_write(os, &isNull, sizeof(isNull)); if (!isNull) contractTable->streamOut(os); isNull = (expandTable == 0); T_FileStream_write(os, &isNull, sizeof(isNull)); if (!isNull) expandTable->streamOut(os); // We don't stream out the rule table, in order to keep // binary files small. We reconstruct rules on the fly. // Stream out the small objects T_FileStream_write(os, &isFrenchSec, sizeof(isFrenchSec)); T_FileStream_write(os, &maxSecOrder, sizeof(maxSecOrder)); T_FileStream_write(os, &maxTerOrder, sizeof(maxTerOrder)); } } void TableCollationData::streamIn(UMemoryStream* is, UErrorCode &status) { if (!uprv_mstrm_error(is) && U_SUCCESS(status)) { // Stream in large objects char isNull; uprv_mstrm_read(is, &isNull, sizeof(isNull)); if (isNull) { ucmp32_close(mapping); mapping = 0; } else { // Slight ugliness: We are a friend of TableCollation solely so // we can access the constant UNMAPPED here. In fact, this code // path shouldn't really happen, because mapping should always != 0. if (mapping == 0) mapping = ucmp32_openAlias(NULL, NULL, 0); if (mapping->fBogus ){ fBogus = TRUE; return; } int32_t len = 0; const uint8_t *map = uprv_mstrm_getCurrentBuffer(is, &len); ucmp32_initFromData(mapping, &map, &status); uprv_mstrm_jump(is, map); // ucmp32_streamMemIn(mapping, is); if (mapping->fBogus) { fBogus = TRUE; ucmp32_close(mapping); mapping = 0; status = U_MISSING_RESOURCE_ERROR; return; } } uprv_mstrm_read(is, &isNull, sizeof(isNull)); if (isNull) { delete contractTable; contractTable = 0; } else { if (contractTable == 0) contractTable = new VectorOfPToContractTable; if (contractTable->isBogus()) { fBogus = TRUE; return; } contractTable->streamIn(is); if (contractTable->isBogus()) { fBogus = TRUE; ucmp32_close(mapping); mapping = 0; delete contractTable; contractTable = 0; return; } } uprv_mstrm_read(is, &isNull, sizeof(isNull)); if (isNull) { delete expandTable; expandTable = 0; } else { if (expandTable == 0) expandTable = new VectorOfPToExpandTable; if (expandTable->isBogus()) { fBogus = TRUE; return; } expandTable->streamIn(is); if (expandTable->isBogus()) { fBogus = TRUE; ucmp32_close(mapping); mapping = 0; delete contractTable; contractTable = 0; delete expandTable; expandTable = 0; return; } } // We don't stream in or out the rule table, in order to keep // binary files small. We reconstruct rules on the fly. ruleTable.remove(); isRuleTableLoaded = FALSE; // Stream in the small objects uprv_mstrm_read(is, &isFrenchSec, sizeof(isFrenchSec)); uprv_mstrm_read(is, &maxSecOrder, sizeof(maxSecOrder)); uprv_mstrm_read(is, &maxTerOrder, sizeof(maxTerOrder)); } } void TableCollationData::streamOut(UMemoryStream* os) const { if (!uprv_mstrm_error(os)) { // Stream out the large objects char isNull; isNull = (mapping == 0); uprv_mstrm_write(os, (uint8_t *)&isNull, sizeof(isNull)); // if (!isNull) ucmp32_streamMemOut(mapping, os); if (!isNull) ucmp32_flattenMem(mapping, os); isNull = (contractTable == 0); uprv_mstrm_write(os, (uint8_t *)&isNull, sizeof(isNull)); if (!isNull) contractTable->streamOut(os); isNull = (expandTable == 0); uprv_mstrm_write(os, (uint8_t *)&isNull, sizeof(isNull)); if (!isNull) expandTable->streamOut(os); // We don't stream out the rule table, in order to keep // binary files small. We reconstruct rules on the fly. // Stream out the small objects uprv_mstrm_write(os, (uint8_t *)&isFrenchSec, sizeof(isFrenchSec)); uprv_mstrm_write(os, (uint8_t *)&maxSecOrder, sizeof(maxSecOrder)); uprv_mstrm_write(os, (uint8_t *)&maxTerOrder, sizeof(maxTerOrder)); } } void TableCollationData::addToCache(const UnicodeString& key, TableCollationData* collation) { Mutex lock; fgCache.Add(key, collation); } TableCollationData* TableCollationData::findInCache(const UnicodeString& key) { Mutex lock; return fgCache.Find(key); } //eof