/*
**********************************************************************
-* Copyright (c) 2002-2006, International Business Machines
+* Copyright (c) 2002-2009, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
*/
if (fRB->fSetBuilder->sawBOF()) {
RBBINode *bofTop = new RBBINode(RBBINode::opCat);
RBBINode *bofLeaf = new RBBINode(RBBINode::leafChar);
+ // Delete and exit if memory allocation failed.
+ if (bofTop == NULL || bofLeaf == NULL) {
+ *fStatus = U_MEMORY_ALLOCATION_ERROR;
+ delete bofTop;
+ delete bofLeaf;
+ return;
+ }
bofTop->fLeftChild = bofLeaf;
bofTop->fRightChild = fTree;
bofLeaf->fParent = bofTop;
// right child being the end marker.
//
RBBINode *cn = new RBBINode(RBBINode::opCat);
+ // Exit if memory allocation failed.
+ if (cn == NULL) {
+ *fStatus = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
cn->fLeftChild = fTree;
fTree->fParent = cn;
cn->fRightChild = new RBBINode(RBBINode::endMark);
+ // Delete and exit if memory allocation failed.
+ if (cn->fRightChild == NULL) {
+ *fStatus = U_MEMORY_ALLOCATION_ERROR;
+ delete cn;
+ return;
+ }
cn->fRightChild->fParent = cn;
fTree = cn;
// don't chain from it.
// TODO: Add rule syntax for this behavior, get specifics out of here and
// into the rule file.
- if (fRB->fLBCMNoChain) {
+ if (fRB->fLBCMNoChain || fRB->fRINoChain) {
UChar32 c = this->fRB->fSetBuilder->getFirstChar(endNode->fVal);
if (c != -1) {
// c == -1 occurs with sets containing only the {eof} marker string.
- ULineBreak cLBProp = (ULineBreak)u_getIntPropertyValue(c, UCHAR_LINE_BREAK);
- if (cLBProp == U_LB_COMBINING_MARK) {
- continue;
+ if (fRB->fLBCMNoChain) {
+ ULineBreak cLBProp = (ULineBreak)u_getIntPropertyValue(c, UCHAR_LINE_BREAK);
+ if (cLBProp == U_LB_COMBINING_MARK) {
+ continue;
+ }
+ }
+ if (fRB->fRINoChain) {
+ UGraphemeClusterBreak cGBProp = (UGraphemeClusterBreak)u_getIntPropertyValue(c, UCHAR_GRAPHEME_CLUSTER_BREAK);
+ if (cGBProp == U_GCB_REGIONAL_INDICATOR) {
+ continue;
+ }
}
}
}
if (U_FAILURE(*fStatus)) {
return;
}
+ RBBIStateDescriptor *failState;
+ // Set it to NULL to avoid uninitialized warning
+ RBBIStateDescriptor *initialState = NULL;
//
// Add a dummy state 0 - the stop state. Not from Aho.
int lastInputSymbol = fRB->fSetBuilder->getNumCharCategories() - 1;
- RBBIStateDescriptor *failState = new RBBIStateDescriptor(lastInputSymbol, fStatus);
+ failState = new RBBIStateDescriptor(lastInputSymbol, fStatus);
+ if (failState == NULL) {
+ *fStatus = U_MEMORY_ALLOCATION_ERROR;
+ goto ExitBuildSTdeleteall;
+ }
failState->fPositions = new UVector(*fStatus);
- if (U_FAILURE(*fStatus)) {
- return;
+ if (failState->fPositions == NULL) {
+ *fStatus = U_MEMORY_ALLOCATION_ERROR;
+ }
+ if (failState->fPositions == NULL || U_FAILURE(*fStatus)) {
+ goto ExitBuildSTdeleteall;
}
fDStates->addElement(failState, *fStatus);
if (U_FAILURE(*fStatus)) {
- return;
+ goto ExitBuildSTdeleteall;
}
// initially, the only unmarked state in Dstates is firstpos(root),
// where toot is the root of the syntax tree for (r)#;
- RBBIStateDescriptor *initialState = new RBBIStateDescriptor(lastInputSymbol, fStatus);
+ initialState = new RBBIStateDescriptor(lastInputSymbol, fStatus);
+ if (initialState == NULL) {
+ *fStatus = U_MEMORY_ALLOCATION_ERROR;
+ }
if (U_FAILURE(*fStatus)) {
- return;
+ goto ExitBuildSTdeleteall;
}
initialState->fPositions = new UVector(*fStatus);
+ if (initialState->fPositions == NULL) {
+ *fStatus = U_MEMORY_ALLOCATION_ERROR;
+ }
if (U_FAILURE(*fStatus)) {
- return;
+ goto ExitBuildSTdeleteall;
}
setAdd(initialState->fPositions, fTree->fFirstPosSet);
fDStates->addElement(initialState, *fStatus);
if (U_FAILURE(*fStatus)) {
- return;
+ goto ExitBuildSTdeleteall;
}
// while there is an unmarked state T in Dstates do begin
if ((p->fType == RBBINode::leafChar) && (p->fVal == a)) {
if (U == NULL) {
U = new UVector(*fStatus);
+ if (U == NULL) {
+ *fStatus = U_MEMORY_ALLOCATION_ERROR;
+ goto ExitBuildSTdeleteall;
+ }
}
setAdd(U, p->fFollowPos);
}
if (!UinDstates)
{
RBBIStateDescriptor *newState = new RBBIStateDescriptor(lastInputSymbol, fStatus);
+ if (newState == NULL) {
+ *fStatus = U_MEMORY_ALLOCATION_ERROR;
+ }
if (U_FAILURE(*fStatus)) {
- return;
+ goto ExitBuildSTdeleteall;
}
newState->fPositions = U;
fDStates->addElement(newState, *fStatus);
}
}
}
+ return;
+ // delete local pointers only if error occured.
+ExitBuildSTdeleteall:
+ delete initialState;
+ delete failState;
}
//
//-----------------------------------------------------------------------------
void RBBITableBuilder::setAdd(UVector *dest, UVector *source) {
- int destOriginalSize = dest->size();
- int sourceSize = source->size();
+ int32_t destOriginalSize = dest->size();
+ int32_t sourceSize = source->size();
int32_t di = 0;
- void *(destS[16]), *(sourceS[16]); // Handle small cases without malloc
- void **destH = 0, **sourceH = 0;
- void **destBuff, **sourceBuff;
+ MaybeStackArray<void *, 16> destArray, sourceArray; // Handle small cases without malloc
+ void **destPtr, **sourcePtr;
void **destLim, **sourceLim;
- if (destOriginalSize > sizeof(destS)/sizeof(destS[0])) {
- destH = (void **)uprv_malloc(sizeof(void *) * destOriginalSize);
- destBuff = destH;
- }
- else {
- destBuff = destS;
- }
- if (destBuff == 0) {
- return;
+ if (destOriginalSize > destArray.getCapacity()) {
+ if (destArray.resize(destOriginalSize) == NULL) {
+ return;
+ }
}
- destLim = destBuff + destOriginalSize;
+ destPtr = destArray.getAlias();
+ destLim = destPtr + destOriginalSize; // destArray.getArrayLimit()?
- if (sourceSize > sizeof(sourceS)/sizeof(sourceS[0])) {
- sourceH = (void **)uprv_malloc(sizeof(void *) * sourceSize);
- sourceBuff = sourceH;
- }
- else {
- sourceBuff = sourceS;
- }
- if (sourceBuff == 0) {
- if (destH) {
- uprv_free(destH);
+ if (sourceSize > sourceArray.getCapacity()) {
+ if (sourceArray.resize(sourceSize) == NULL) {
+ return;
}
- return;
}
- sourceLim = sourceBuff + sourceSize;
+ sourcePtr = sourceArray.getAlias();
+ sourceLim = sourcePtr + sourceSize; // sourceArray.getArrayLimit()?
// Avoid multiple "get element" calls by getting the contents into arrays
- (void) dest->toArray(destBuff);
- (void) source->toArray(sourceBuff);
+ (void) dest->toArray(destPtr);
+ (void) source->toArray(sourcePtr);
- dest->setSize(sourceSize+destOriginalSize);
+ dest->setSize(sourceSize+destOriginalSize, *fStatus);
- while (sourceBuff < sourceLim && destBuff < destLim) {
- if (*destBuff < *sourceBuff) {
- dest->setElementAt(*destBuff++, di++);
+ while (sourcePtr < sourceLim && destPtr < destLim) {
+ if (*destPtr == *sourcePtr) {
+ dest->setElementAt(*sourcePtr++, di++);
+ destPtr++;
}
- else if (*sourceBuff < *destBuff) {
- dest->setElementAt(*sourceBuff++, di++);
+ // This check is required for machines with segmented memory, like i5/OS.
+ // Direct pointer comparison is not recommended.
+ else if (uprv_memcmp(destPtr, sourcePtr, sizeof(void *)) < 0) {
+ dest->setElementAt(*destPtr++, di++);
}
- else {
- dest->setElementAt(*sourceBuff++, di++);
- destBuff++;
+ else { /* *sourcePtr < *destPtr */
+ dest->setElementAt(*sourcePtr++, di++);
}
}
// At most one of these two cleanup loops will execute
- while (destBuff < destLim) {
- dest->setElementAt(*destBuff++, di++);
+ while (destPtr < destLim) {
+ dest->setElementAt(*destPtr++, di++);
}
- while (sourceBuff < sourceLim) {
- dest->setElementAt(*sourceBuff++, di++);
+ while (sourcePtr < sourceLim) {
+ dest->setElementAt(*sourcePtr++, di++);
}
- dest->setSize(di);
- if (destH) {
- uprv_free(destH);
- }
- if (sourceH) {
- uprv_free(sourceH);
- }
+ dest->setSize(di, *fStatus);
}
*fStatus = U_MEMORY_ALLOCATION_ERROR;
return;
}
- fDtran->setSize(lastInputSymbol+1); // fDtran needs to be pre-sized.
+ fDtran->setSize(lastInputSymbol+1, *fStatus); // fDtran needs to be pre-sized.
// It is indexed by input symbols, and will
// hold the next state number for each
// symbol.