/* ********************************************************************** * Copyright (C) 1999-2002 International Business Machines Corporation * * and others. All rights reserved. * ********************************************************************** */ #include "unicode/utypes.h" #include "cmemory.h" #include "rbbidata.h" #include "utrie.h" #include "udatamem.h" #include #include U_NAMESPACE_BEGIN //----------------------------------------------------------------------------- // // Constructors. // //----------------------------------------------------------------------------- RBBIDataWrapper::RBBIDataWrapper(const RBBIDataHeader *data, UErrorCode &status) { init(data, status); } RBBIDataWrapper::RBBIDataWrapper(UDataMemory* udm, UErrorCode &status) { const RBBIDataHeader *d = (const RBBIDataHeader *) ((char *)&(udm->pHeader->info) + udm->pHeader->info.size); init(d, status); fUDataMem = udm; } //----------------------------------------------------------------------------------- // // Trie access folding function. Copied as-is from properties code in uchar.c // //----------------------------------------------------------------------------------- U_CDECL_BEGIN static int32_t U_CALLCONV getFoldingOffset(uint32_t data) { /* if bit 15 is set, then the folding offset is in bits 14..0 of the 16-bit trie result */ if(data&0x8000) { return (int32_t)(data&0x7fff); } else { return 0; } } U_CDECL_END //----------------------------------------------------------------------------- // // init(). Does most of the work of construction, shared between the // constructors. // //----------------------------------------------------------------------------- void RBBIDataWrapper::init(const RBBIDataHeader *data, UErrorCode &status) { if (U_FAILURE(status)) { return; } fHeader = data; if (fHeader->fMagic != 0xb1a0) { status = U_BRK_INTERNAL_ERROR; return; } fUDataMem = NULL; fForwardTable = (RBBIStateTable *)((char *)data + fHeader->fFTable); fReverseTable = NULL; if (data->fRTableLen != 0) { fReverseTable = (RBBIStateTable *)((char *)data + fHeader->fRTable); } utrie_unserialize(&fTrie, (uint8_t *)data + fHeader->fTrie, fHeader->fTrieLen, &status); if (U_FAILURE(status)) { return; } fTrie.getFoldingOffset=getFoldingOffset; fRuleSource = (UChar *)((char *)data + fHeader->fRuleSource); fRuleString.setTo(TRUE, fRuleSource, -1); fRefCount = 1; char *debugEnv = getenv("U_RBBIDEBUG"); // TODO: make conditional on some compile time setting if (debugEnv && strstr(debugEnv, "data")) {this->printData();} } //----------------------------------------------------------------------------- // // Destructor. Don't call this - use removeReferenc() instead. // //----------------------------------------------------------------------------- RBBIDataWrapper::~RBBIDataWrapper() { assert(fRefCount == 0); if (fUDataMem) { udata_close(fUDataMem); } else { uprv_free((void *)fHeader); } } //----------------------------------------------------------------------------- // // Operator == Consider two RBBIDataWrappers to be equal if they // refer to the same underlying data. Although // the data wrappers are normally shared between // iterator instances, it's possible to independently // open the same data twice, and get two instances, which // should still be ==. // //----------------------------------------------------------------------------- UBool RBBIDataWrapper::operator ==(const RBBIDataWrapper &other) const { if (fHeader == other.fHeader) { return TRUE; } if (fHeader->fLength != other.fHeader->fLength) { return FALSE; } if (uprv_memcmp(fHeader, other.fHeader, fHeader->fLength) == 0) { return TRUE; } return FALSE; } int32_t RBBIDataWrapper::hashCode() { return fHeader->fFTableLen; ; }; //----------------------------------------------------------------------------- // // Reference Counting. A single RBBIDataWrapper object is shared among // however many RulesBasedBreakIterator instances are // referencing the same data. // //----------------------------------------------------------------------------- void RBBIDataWrapper::removeReference() { if (--fRefCount <= 0) { // TODO needs synchronization delete this; } }; RBBIDataWrapper *RBBIDataWrapper::addReference() { ++fRefCount; // TODO: needs synchronization return this; }; //----------------------------------------------------------------------------- // // getRuleSourceString // //----------------------------------------------------------------------------- const UnicodeString &RBBIDataWrapper::getRuleSourceString() { return fRuleString; } //----------------------------------------------------------------------------- // // print - debugging function to dump the runtime data tables. // //----------------------------------------------------------------------------- void RBBIDataWrapper::printData() { uint32_t c, s; printf("RBBI Data at %x\n", fHeader); printf(" Version = %d\n", fHeader->fVersion); printf(" total length of data = %d\n", fHeader->fLength); printf(" number of character categories = %d\n\n", fHeader->fCatCount); printf(" Forward State Transition Table\n"); printf("State | Acc LA Tag"); for (c=0; cfCatCount; c++) {printf("%3d ", c);}; printf("\n------|---------------"); for (c=0;cfCatCount; c++) {printf("----");} printf("\n"); for (s=0; sfNumStates; s++) { RBBIStateTableRow *row = (RBBIStateTableRow *) (fForwardTable->fTableData + (fForwardTable->fRowLen * s)); printf("%4d | %3d %3d ", s, row->fAccepting, row->fLookAhead, row->fTag); for (c=0; cfCatCount; c++) { printf("%3d ", row->fNextState[c]); }; printf("\n"); } printf("\nOrignal Rules source:\n"); c = 0; for (;;) { if (fRuleSource[c] == 0) break; putchar(fRuleSource[c]); c++; } printf("\n\n"); } U_NAMESPACE_END