for( i = 0 ; i < length; ) { /* i is incremented by U16_NEXT */
U16_NEXT(text, i, length, uchar);
dir = u_charDirection(uchar); if( dir == U_LEFT_TO_RIGHT ) return UBIDI_LTR; if( dir == U_RIGHT_TO_LEFT || dir ==U_RIGHT_TO_LEFT_ARABIC ) return UBIDI_RTL;
} return UBIDI_NEUTRAL;
}
int32_t i=0, originalLength=pBiDi->originalLength;
Flags flags=0; /* collect all directionalities in the text */
UChar32 uchar;
DirProp dirProp=0, defaultParaLevel=0; /* initialize to avoid compiler warnings */
UBool isDefaultLevel=IS_DEFAULT_LEVEL(pBiDi->paraLevel); /* for inverse BiDi, the default para level is set to RTL if there is a
strong R or AL character at either end of the text */
UBool isDefaultLevelInverse = isDefaultLevel && static_cast<UBool>(
pBiDi->reorderingMode == UBIDI_REORDER_INVERSE_LIKE_DIRECT ||
pBiDi->reorderingMode == UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL);
int32_t lastArabicPos=-1;
int32_t controlCount=0;
UBool removeBiDiControls =
static_cast<UBool>(pBiDi->reorderingOptions & UBIDI_OPTION_REMOVE_CONTROLS);
enum State {
NOT_SEEKING_STRONG, /* 0: not contextual paraLevel, not after FSI */
SEEKING_STRONG_FOR_PARA, /* 1: looking for first strong char in para */
SEEKING_STRONG_FOR_FSI, /* 2: looking for first strong after FSI */
LOOKING_FOR_PDI /* 3: found strong after FSI, looking for PDI */
};
State state;
DirProp lastStrong=ON; /* for default level & inverse BiDi */ /* The following stacks are used to manage isolate sequences. Those sequencesmaybenested,butobviouslynevermoredeeplythanthe maximumexplicitembeddinglevel. lastStackistheindexofthelastusedentryinthestack.Avalueof-1 meansthatthereisnoopenisolatesequence.
lastStack is reset to -1 on paragraph boundaries. */ /* The following stack contains the position of the initiator of
each open isolate sequence */
int32_t isolateStartStack[UBIDI_MAX_EXPLICIT_LEVEL+1]; /* The following stack contains the last known state before
encountering the initiator of an isolate sequence */
State previousStateStack[UBIDI_MAX_EXPLICIT_LEVEL+1];
int32_t stackLast=-1;
if(pBiDi->reorderingOptions & UBIDI_OPTION_STREAMING)
pBiDi->length=0;
defaultParaLevel=pBiDi->paraLevel&1; if(isDefaultLevel) {
pBiDi->paras[0].level=defaultParaLevel;
lastStrong=defaultParaLevel; if(pBiDi->proLength>0 && /* there is a prologue */
(dirProp=firstL_R_AL(pBiDi))!=ON) { /* with a strong character */ if(dirProp==L)
pBiDi->paras[0].level=0; /* set the default para level */ else
pBiDi->paras[0].level=1; /* set the default para level */
state=NOT_SEEKING_STRONG;
} else {
state=SEEKING_STRONG_FOR_PARA;
}
} else {
pBiDi->paras[0].level=pBiDi->paraLevel;
state=NOT_SEEKING_STRONG;
} /* count paragraphs and determine the paragraph level (P2..P3) */ /* *seecommentinubidi.h: *theUBIDI_DEFAULT_XXXvaluesaredesignedsothat *theirbit0aloneyieldstheintendeddefault
*/ for( /* i=0 above */ ; i<originalLength; ) { /* i is incremented by U16_NEXT */
U16_NEXT(text, i, originalLength, uchar);
flags|=DIRPROP_FLAG(dirProp=(DirProp)ubidi_getCustomizedClass(pBiDi, uchar));
dirProps[i-1]=dirProp; if(uchar>0xffff) { /* set the lead surrogate's property to BN */
flags|=DIRPROP_FLAG(BN);
dirProps[i-2]=BN;
} if(removeBiDiControls && IS_BIDI_CONTROL_CHAR(uchar))
controlCount++; if(dirProp==L) { if(state==SEEKING_STRONG_FOR_PARA) {
pBiDi->paras[pBiDi->paraCount-1].level=0;
state=NOT_SEEKING_STRONG;
} elseif(state==SEEKING_STRONG_FOR_FSI) { if(stackLast<=UBIDI_MAX_EXPLICIT_LEVEL) { /* no need for next statement, already set by default */ /* dirProps[isolateStartStack[stackLast]]=LRI; */
flags|=DIRPROP_FLAG(LRI);
}
state=LOOKING_FOR_PDI;
}
lastStrong=L; continue;
} if(dirProp==R || dirProp==AL) { if(state==SEEKING_STRONG_FOR_PARA) {
pBiDi->paras[pBiDi->paraCount-1].level=1;
state=NOT_SEEKING_STRONG;
} elseif(state==SEEKING_STRONG_FOR_FSI) { if(stackLast<=UBIDI_MAX_EXPLICIT_LEVEL) {
dirProps[isolateStartStack[stackLast]]=RLI;
flags|=DIRPROP_FLAG(RLI);
}
state=LOOKING_FOR_PDI;
}
lastStrong=R; if(dirProp==AL)
lastArabicPos=i-1; continue;
} if(dirProp>=FSI && dirProp<=RLI) { /* FSI, LRI or RLI */
stackLast++; if(stackLast<=UBIDI_MAX_EXPLICIT_LEVEL) {
isolateStartStack[stackLast]=i-1;
previousStateStack[stackLast]=state;
} if(dirProp==FSI) {
dirProps[i-1]=LRI; /* default if no strong char */
state=SEEKING_STRONG_FOR_FSI;
} else
state=LOOKING_FOR_PDI; continue;
} if(dirProp==PDI) { if(state==SEEKING_STRONG_FOR_FSI) { if(stackLast<=UBIDI_MAX_EXPLICIT_LEVEL) { /* no need for next statement, already set by default */ /* dirProps[isolateStartStack[stackLast]]=LRI; */
flags|=DIRPROP_FLAG(LRI);
}
} if(stackLast>=0) { if(stackLast<=UBIDI_MAX_EXPLICIT_LEVEL)
state=previousStateStack[stackLast];
stackLast--;
} continue;
} if(dirProp==B) { if(i<originalLength && uchar==CR && text[i]==LF) /* do nothing on the CR */ continue;
pBiDi->paras[pBiDi->paraCount-1].limit=i; if(isDefaultLevelInverse && lastStrong==R)
pBiDi->paras[pBiDi->paraCount-1].level=1; if(pBiDi->reorderingOptions & UBIDI_OPTION_STREAMING) { /* When streaming, we only process whole paragraphs
thus some updates are only done on paragraph boundaries */
pBiDi->length=i; /* i is index to next character */
pBiDi->controlCount=controlCount;
} if(i<originalLength) { /* B not last char in text */
pBiDi->paraCount++; if(checkParaCount(pBiDi)==false) /* not enough memory for a new para entry */ returnfalse; if(isDefaultLevel) {
pBiDi->paras[pBiDi->paraCount-1].level=defaultParaLevel;
state=SEEKING_STRONG_FOR_PARA;
lastStrong=defaultParaLevel;
} else {
pBiDi->paras[pBiDi->paraCount-1].level=pBiDi->paraLevel;
state=NOT_SEEKING_STRONG;
}
stackLast=-1;
} continue;
}
} /* Ignore still open isolate sequences with overflow */ if(stackLast>UBIDI_MAX_EXPLICIT_LEVEL) {
stackLast=UBIDI_MAX_EXPLICIT_LEVEL;
state=SEEKING_STRONG_FOR_FSI; /* to be on the safe side */
} /* Resolve direction of still unresolved open FSI sequences */ while(stackLast>=0) { if(state==SEEKING_STRONG_FOR_FSI) { /* no need for next statement, already set by default */ /* dirProps[isolateStartStack[stackLast]]=LRI; */
flags|=DIRPROP_FLAG(LRI); break;
}
state=previousStateStack[stackLast];
stackLast--;
} /* When streaming, ignore text after the last paragraph separator */ if(pBiDi->reorderingOptions & UBIDI_OPTION_STREAMING) { if(pBiDi->length<originalLength)
pBiDi->paraCount--;
} else {
pBiDi->paras[pBiDi->paraCount-1].limit=originalLength;
pBiDi->controlCount=controlCount;
} /* For inverse bidi, default para direction is RTL if there is
a strong R or AL at either end of the paragraph */ if(isDefaultLevelInverse && lastStrong==R) {
pBiDi->paras[pBiDi->paraCount-1].level=1;
} if(isDefaultLevel) {
pBiDi->paraLevel=static_cast<UBiDiLevel>(pBiDi->paras[0].level);
} /* The following is needed to resolve the text direction for default level
paragraphs containing no strong character */ for(i=0; i<pBiDi->paraCount; i++)
flags|=DIRPROP_FLAG_LR(pBiDi->paras[i].level);
/* determine the paragraph level at position index */
U_CFUNC UBiDiLevel
ubidi_getParaLevelAtIndex(const UBiDi *pBiDi, int32_t pindex) {
int32_t i; for(i=0; i<pBiDi->paraCount; i++) if(pindex<pBiDi->paras[i].limit) break; if(i>=pBiDi->paraCount)
i=pBiDi->paraCount-1; return (UBiDiLevel)(pBiDi->paras[i].level);
}
/* Functions for handling paired brackets ----------------------------------- */
/* In the isoRuns array, the first entry is used for text outside of any isolatesequence.Higherentriesareusedforeachmoredeeplynested isolatesequence.isoRunLastistheindexofthelastusedentry.The openingsarrayisusedtonotethedataofopeningbracketsnotyet matchedbyaclosingbracket,ormatchedbutstillsusceptibletochange level. EachisoRunentrycontainstheindexofthefirstand one-after-lastopeningsentriesforpendingopeningbracketsit contains.Thenextopeningsentrytouseistheone-after-lastofthe mostdeeplynestedisoRunentry. isoRunentriesalsocontaintheircurrentembeddinglevelandthelast encounteredstrongcharacter,sincethesewillbeneededtoresolve
the level of paired brackets. */
/* newly found opening bracket: create an openings entry */ static UBool /* return true if success */
bracketAddOpening(BracketData *bd, char16_t match, int32_t position) {
IsoRun *pLastIsoRun=&bd->isoRuns[bd->isoRunLast];
Opening *pOpening; if(pLastIsoRun->limit>=bd->openingsCount) { /* no available new entry */
UBiDi *pBiDi=bd->pBiDi; if(!getInitialOpeningsMemory(pBiDi, pLastIsoRun->limit * 2)) returnfalse; if(bd->openings==bd->simpleOpenings)
uprv_memcpy(pBiDi->openingsMemory, bd->simpleOpenings,
SIMPLE_OPENINGS_COUNT * sizeof(Opening));
bd->openings=pBiDi->openingsMemory; /* may have changed */
bd->openingsCount=pBiDi->openingsSize / sizeof(Opening);
}
pOpening=&bd->openings[pLastIsoRun->limit];
pOpening->position=position;
pOpening->match=match;
pOpening->contextDir=pLastIsoRun->contextDir;
pOpening->contextPos=pLastIsoRun->contextPos;
pOpening->flags=0;
pLastIsoRun->limit++; return true;
}
/* change N0c1 to N0c2 when a preceding bracket is assigned the embedding level */ staticvoid
fixN0c(BracketData *bd, int32_t openingIndex, int32_t newPropPosition, DirProp newProp) { /* This function calls itself recursively */
IsoRun *pLastIsoRun=&bd->isoRuns[bd->isoRunLast];
Opening *qOpening;
DirProp *dirProps=bd->pBiDi->dirProps;
int32_t k, openingPosition, closingPosition; for(k=openingIndex+1, qOpening=&bd->openings[k]; k<pLastIsoRun->limit; k++, qOpening++) { if(qOpening->match>=0) /* not an N0c match */ continue; if(newPropPosition<qOpening->contextPos) break; if(newPropPosition>=qOpening->position) continue; if(newProp==qOpening->contextDir) break;
openingPosition=qOpening->position;
dirProps[openingPosition]=newProp;
closingPosition=-(qOpening->match);
dirProps[closingPosition]=newProp;
qOpening->match=0; /* prevent further changes */
fixN0c(bd, k, openingPosition, newProp);
fixN0c(bd, k, closingPosition, newProp);
}
}
/* process closing bracket */ static DirProp /* return L or R if N0b or N0c, ON if N0d */
bracketProcessClosing(BracketData *bd, int32_t openIdx, int32_t position) {
IsoRun *pLastIsoRun=&bd->isoRuns[bd->isoRunLast];
Opening *pOpening, *qOpening;
UBiDiDirection direction;
UBool stable;
DirProp newProp;
pOpening=&bd->openings[openIdx];
direction = static_cast<UBiDiDirection>(pLastIsoRun->level & 1);
stable=true; /* assume stable until proved otherwise */
/* The stable flag is set when brackets are paired and their levelisresolvedandcannotbechangedbywhatwillbe foundlaterinthesourcestring. AnunstablematchcanoccuronlywhenapplyingN0c,where theresolvedleveldependsontheprecedingcontext,and thiscontextmaybeaffectedbytextoccurringlater. Example:RTLparagraphcontaining:abc[(latin)HEBREW] Whentheclosingparenthesisisencountered,itappears thatN0c1mustbeappliedsince'abc'setsanopposite directioncontextandbothparenthesesreceivelevel2. However,whentheclosingsquarebracketisprocessed, N0bappliesbecauseof'HEBREW'beingincludedwithinthe brackets,thusthesquarebracketsaretreatedlikeRand receivelevel1.However,thischangesthepreceding contextoftheopeningparenthesis,anditnowappears thatN0c2mustbeappliedtotheparenthesesratherthan
N0c1. */
if((direction==0 && pOpening->flags&FOUND_L) ||
(direction==1 && pOpening->flags&FOUND_R)) { /* N0b */
newProp=static_cast<DirProp>(direction);
} elseif(pOpening->flags&(FOUND_L|FOUND_R)) { /* N0c */ /* it is stable if there is no containing pair or in
conditions too complicated and not worth checking */
stable=(openIdx==pLastIsoRun->start); if(direction!=pOpening->contextDir)
newProp= static_cast<DirProp>(pOpening->contextDir); /* N0c1 */ else
newProp= static_cast<DirProp>(direction); /* N0c2 */
} else { /* forget this and any brackets nested within this pair */
pLastIsoRun->limit= static_cast<uint16_t>(openIdx); return ON; /* N0d */
}
bd->pBiDi->dirProps[pOpening->position]=newProp;
bd->pBiDi->dirProps[position]=newProp; /* Update nested N0c pairs that may be affected */
fixN0c(bd, openIdx, pOpening->position, newProp); if(stable) {
pLastIsoRun->limit= static_cast<uint16_t>(openIdx); /* forget any brackets nested within this pair */ /* remove lower located synonyms if any */ while(pLastIsoRun->limit>pLastIsoRun->start &&
bd->openings[pLastIsoRun->limit-1].position==pOpening->position)
pLastIsoRun->limit--;
} else {
int32_t k;
pOpening->match=-position; /* neutralize lower located synonyms if any */
k=openIdx-1; while(k>=pLastIsoRun->start &&
bd->openings[k].position==pOpening->position)
bd->openings[k--].match=0; /* neutralize any unmatched opening between the current pair;
this will also neutralize higher located synonyms if any */ for(k=openIdx+1; k<pLastIsoRun->limit; k++) {
qOpening=&bd->openings[k]; if(qOpening->position>=position) break; if(qOpening->match>0)
qOpening->match=0;
}
} return newProp;
}
/* handle strong characters, digits and candidates for closing brackets */ static UBool /* return true if success */
bracketProcessChar(BracketData *bd, int32_t position) {
IsoRun *pLastIsoRun=&bd->isoRuns[bd->isoRunLast];
DirProp *dirProps, dirProp, newProp;
UBiDiLevel level;
dirProps=bd->pBiDi->dirProps;
dirProp=dirProps[position]; if(dirProp==ON) {
char16_t c, match;
int32_t idx; /* First see if it is a matching closing bracket. Hopefully, this is
more efficient than checking if it is a closing bracket at all */
c=bd->pBiDi->text[position]; for(idx=pLastIsoRun->limit-1; idx>=pLastIsoRun->start; idx--) { if(bd->openings[idx].match!=c) continue; /* We have a match */
newProp=bracketProcessClosing(bd, idx, position); if(newProp==ON) { /* N0d */
c=0; /* prevent handling as an opening */ break;
}
pLastIsoRun->lastBase=ON;
pLastIsoRun->contextDir = static_cast<UBiDiDirection>(newProp);
pLastIsoRun->contextPos=position;
level=bd->pBiDi->levels[position]; if(level&UBIDI_LEVEL_OVERRIDE) { /* X4, X5 */
uint16_t flag;
int32_t i;
newProp=level&1;
pLastIsoRun->lastStrong=newProp;
flag=DIRPROP_FLAG(newProp); for(i=pLastIsoRun->start; i<idx; i++)
bd->openings[i].flags|=flag; /* matching brackets are not overridden by LRO/RLO */
bd->pBiDi->levels[position]&=~UBIDI_LEVEL_OVERRIDE;
} /* matching brackets are not overridden by LRO/RLO */
bd->pBiDi->levels[bd->openings[idx].position]&=~UBIDI_LEVEL_OVERRIDE; return true;
} /* We get here only if the ON character is not a matching closing
bracket or it is a case of N0d */ /* Now see if it is an opening bracket */ if(c)
match= static_cast<char16_t>(u_getBidiPairedBracket(c)); /* get the matching char */ else
match=0; if(match!=c && /* has a matching char */
ubidi_getPairedBracketType(c)==U_BPT_OPEN) { /* opening bracket */ /* special case: process synonyms
create an opening entry for each synonym */ if(match==0x232A) { /* RIGHT-POINTING ANGLE BRACKET */ if(!bracketAddOpening(bd, 0x3009, position)) returnfalse;
} elseif(match==0x3009) { /* RIGHT ANGLE BRACKET */ if(!bracketAddOpening(bd, 0x232A, position)) returnfalse;
} if(!bracketAddOpening(bd, match, position)) returnfalse;
}
}
level=bd->pBiDi->levels[position]; if(level&UBIDI_LEVEL_OVERRIDE) { /* X4, X5 */
newProp=level&1; if(dirProp!=S && dirProp!=WS && dirProp!=ON)
dirProps[position]=newProp;
pLastIsoRun->lastBase=newProp;
pLastIsoRun->lastStrong=newProp;
pLastIsoRun->contextDir = static_cast<UBiDiDirection>(newProp);
pLastIsoRun->contextPos=position;
} elseif(dirProp<=R || dirProp==AL) {
newProp= static_cast<DirProp>(DIR_FROM_STRONG(dirProp));
pLastIsoRun->lastBase=dirProp;
pLastIsoRun->lastStrong=dirProp;
pLastIsoRun->contextDir = static_cast<UBiDiDirection>(newProp);
pLastIsoRun->contextPos=position;
} elseif(dirProp==EN) {
pLastIsoRun->lastBase=EN; if(pLastIsoRun->lastStrong==L) {
newProp=L; /* W7 */ if(!bd->isNumbersSpecial)
dirProps[position]=ENL;
pLastIsoRun->contextDir = static_cast<UBiDiDirection>(L);
pLastIsoRun->contextPos=position;
} else {
newProp=R; /* N0 */ if(pLastIsoRun->lastStrong==AL)
dirProps[position]=AN; /* W2 */ else
dirProps[position]=ENR;
pLastIsoRun->contextDir = static_cast<UBiDiDirection>(R);
pLastIsoRun->contextPos=position;
}
} elseif(dirProp==AN) {
newProp=R; /* N0 */
pLastIsoRun->lastBase=AN;
pLastIsoRun->contextDir = static_cast<UBiDiDirection>(R);
pLastIsoRun->contextPos=position;
} elseif(dirProp==NSM) { /* if the last real char was ON, change NSM to ON so that it willstayONevenifthelastrealcharisabracketwhich
may be changed to L or R */
newProp=pLastIsoRun->lastBase; if(newProp==ON)
dirProps[position]=newProp;
} else {
newProp=dirProp;
pLastIsoRun->lastBase=dirProp;
} if(newProp<=R || newProp==AL) {
int32_t i;
uint16_t flag=DIRPROP_FLAG(DIR_FROM_STRONG(newProp)); for(i=pLastIsoRun->start; i<pLastIsoRun->limit; i++) if(position>bd->openings[i].position)
bd->openings[i].flags|=flag;
} return true;
}
/* determine if the text is mixed-directional or single-directional */ static UBiDiDirection
directionFromFlags(UBiDi *pBiDi) {
Flags flags=pBiDi->flags; /* if the text contains AN and neutrals, then some neutrals may become RTL */ if(!(flags&MASK_RTL || ((flags&DIRPROP_FLAG(AN)) && (flags&MASK_POSSIBLE_N)))) { return UBIDI_LTR;
} elseif(!(flags&MASK_LTR)) { return UBIDI_RTL;
} else { return UBIDI_MIXED;
}
}
int32_t i=0, length=pBiDi->length;
Flags flags=pBiDi->flags; /* collect all directionalities in the text */
DirProp dirProp;
UBiDiLevel level=GET_PARALEVEL(pBiDi, 0);
UBiDiDirection direction;
pBiDi->isolateCount=0;
if(U_FAILURE(*pErrorCode)) { return UBIDI_LTR; }
/* determine if the text is mixed-directional or single-directional */
direction=directionFromFlags(pBiDi);
/* we may not need to resolve any explicit levels */ if((direction!=UBIDI_MIXED)) { /* not mixed directionality: levels don't matter - trailingWSStart will be 0 */ return direction;
} if(pBiDi->reorderingMode > UBIDI_REORDER_LAST_LOGICAL_TO_VISUAL) { /* inverse BiDi: mixed, but all characters are at the same embedding level */ /* set all levels to the paragraph level */
int32_t paraIndex, start, limit; for(paraIndex=0; paraIndex<pBiDi->paraCount; paraIndex++) { if(paraIndex==0)
start=0; else
start=pBiDi->paras[paraIndex-1].limit;
limit=pBiDi->paras[paraIndex].limit;
level= static_cast<UBiDiLevel>(pBiDi->paras[paraIndex].level); for(i=start; i<limit; i++)
levels[i]=level;
} return direction; /* no bracket matching for inverse BiDi */
} if(!(flags&(MASK_EXPLICIT|MASK_ISO))) { /* no embeddings, set all levels to the paragraph level */ /* we still have to perform bracket matching */
int32_t paraIndex, start, limit;
BracketData bracketData;
bracketInit(pBiDi, &bracketData); for(paraIndex=0; paraIndex<pBiDi->paraCount; paraIndex++) { if(paraIndex==0)
start=0; else
start=pBiDi->paras[paraIndex-1].limit;
limit=pBiDi->paras[paraIndex].limit;
level= static_cast<UBiDiLevel>(pBiDi->paras[paraIndex].level); for(i=start; i<limit; i++) {
levels[i]=level;
dirProp=dirProps[i]; if(dirProp==BN) continue; if(dirProp==B) { if((i+1)<length) { if(text[i]==CR && text[i+1]==LF) continue; /* skip CR when followed by LF */
bracketProcessB(&bracketData, level);
} continue;
} if(!bracketProcessChar(&bracketData, i)) {
*pErrorCode=U_MEMORY_ALLOCATION_ERROR; return UBIDI_LTR;
}
}
} return direction;
}
{ /* continue to perform (Xn) */
/* (X1) level is set for all codes, embeddingLevel keeps track of the push/pop operations */ /* both variables may carry the UBIDI_LEVEL_OVERRIDE flag to indicate the override status */
UBiDiLevel embeddingLevel=level, newLevel;
UBiDiLevel previousLevel=level; /* previous level for regular (not CC) characters */
int32_t lastCcPos=0; /* index of last effective LRx,RLx, PDx */
/* The following stack remembers the embedding level and the ISOLATE flag of level runs.
stackLast points to its current entry. */
uint16_t stack[UBIDI_MAX_EXPLICIT_LEVEL+2]; /* we never push anything >=UBIDI_MAX_EXPLICIT_LEVEL
but we need one more entry as base */
uint32_t stackLast=0;
int32_t overflowIsolateCount=0;
int32_t overflowEmbeddingCount=0;
int32_t validIsolateCount=0;
BracketData bracketData;
bracketInit(pBiDi, &bracketData);
stack[0]=level; /* initialize base entry to para level, no override, no isolate */
/* recalculate the flags */
flags=0;
for(i=0; i<length; ++i) {
dirProp=dirProps[i]; switch(dirProp) { case LRE: case RLE: case LRO: case RLO: /* (X2, X3, X4, X5) */
flags|=DIRPROP_FLAG(BN);
levels[i]=previousLevel; if (dirProp==LRE || dirProp==LRO) /* least greater even level */
newLevel = static_cast<UBiDiLevel>((embeddingLevel + 2) & ~(UBIDI_LEVEL_OVERRIDE | 1)); else /* least greater odd level */
newLevel = static_cast<UBiDiLevel>((NO_OVERRIDE(embeddingLevel) + 1) | 1); if(newLevel<=UBIDI_MAX_EXPLICIT_LEVEL && overflowIsolateCount==0 &&
overflowEmbeddingCount==0) {
lastCcPos=i;
embeddingLevel=newLevel; if(dirProp==LRO || dirProp==RLO)
embeddingLevel|=UBIDI_LEVEL_OVERRIDE;
stackLast++;
stack[stackLast]=embeddingLevel; /* we don't need to set UBIDI_LEVEL_OVERRIDE off for LRE and RLE sincethishasalreadybeendonefornewLevelwhichis thesourceforembeddingLevel.
*/
} else { if(overflowIsolateCount==0)
overflowEmbeddingCount++;
} break; case PDF: /* (X7) */
flags|=DIRPROP_FLAG(BN);
levels[i]=previousLevel; /* handle all the overflow cases first */ if(overflowIsolateCount) { break;
} if(overflowEmbeddingCount) {
overflowEmbeddingCount--; break;
} if(stackLast>0 && stack[stackLast]<ISOLATE) { /* not an isolate entry */
lastCcPos=i;
stackLast--;
embeddingLevel = static_cast<UBiDiLevel>(stack[stackLast]);
} break; case LRI: case RLI:
flags|=(DIRPROP_FLAG(ON)|DIRPROP_FLAG_LR(embeddingLevel));
levels[i]=NO_OVERRIDE(embeddingLevel); if(NO_OVERRIDE(embeddingLevel)!=NO_OVERRIDE(previousLevel)) {
bracketProcessBoundary(&bracketData, lastCcPos,
previousLevel, embeddingLevel);
flags|=DIRPROP_FLAG_MULTI_RUNS;
}
previousLevel=embeddingLevel; /* (X5a, X5b) */ if(dirProp==LRI) /* least greater even level */
newLevel = static_cast<UBiDiLevel>((embeddingLevel + 2) & ~(UBIDI_LEVEL_OVERRIDE | 1)); else /* least greater odd level */
newLevel = static_cast<UBiDiLevel>((NO_OVERRIDE(embeddingLevel) + 1) | 1); if(newLevel<=UBIDI_MAX_EXPLICIT_LEVEL && overflowIsolateCount==0 &&
overflowEmbeddingCount==0) {
flags|=DIRPROP_FLAG(dirProp);
lastCcPos=i;
validIsolateCount++; if(validIsolateCount>pBiDi->isolateCount)
pBiDi->isolateCount=validIsolateCount;
embeddingLevel=newLevel; /* we can increment stackLast without checking because newLevel
will exceed UBIDI_MAX_EXPLICIT_LEVEL before stackLast overflows */
stackLast++;
stack[stackLast]=embeddingLevel+ISOLATE;
bracketProcessLRI_RLI(&bracketData, embeddingLevel);
} else { /* make it WS so that it is handled by adjustWSLevels() */
dirProps[i]=WS;
overflowIsolateCount++;
} break; case PDI: if(NO_OVERRIDE(embeddingLevel)!=NO_OVERRIDE(previousLevel)) {
bracketProcessBoundary(&bracketData, lastCcPos,
previousLevel, embeddingLevel);
flags|=DIRPROP_FLAG_MULTI_RUNS;
} /* (X6a) */ if(overflowIsolateCount) {
overflowIsolateCount--; /* make it WS so that it is handled by adjustWSLevels() */
dirProps[i]=WS;
} elseif(validIsolateCount) {
flags|=DIRPROP_FLAG(PDI);
lastCcPos=i;
overflowEmbeddingCount=0; while(stack[stackLast]<ISOLATE) /* pop embedding entries */
stackLast--; /* until the last isolate entry */
stackLast--; /* pop also the last isolate entry */
validIsolateCount--;
bracketProcessPDI(&bracketData);
} else /* make it WS so that it is handled by adjustWSLevels() */
dirProps[i]=WS;
embeddingLevel = static_cast<UBiDiLevel>(stack[stackLast]) & ~ISOLATE;
flags|=(DIRPROP_FLAG(ON)|DIRPROP_FLAG_LR(embeddingLevel));
previousLevel=embeddingLevel;
levels[i]=NO_OVERRIDE(embeddingLevel); break; case B:
flags|=DIRPROP_FLAG(B);
levels[i]=GET_PARALEVEL(pBiDi, i); if((i+1)<length) { if(text[i]==CR && text[i+1]==LF) break; /* skip CR when followed by LF */
overflowEmbeddingCount=overflowIsolateCount=0;
validIsolateCount=0;
stackLast=0;
previousLevel=embeddingLevel=GET_PARALEVEL(pBiDi, i+1);
stack[0]=embeddingLevel; /* initialize base entry to para level, no override, no isolate */
bracketProcessB(&bracketData, embeddingLevel);
} break; case BN: /* BN, LRE, RLE, and PDF are supposed to be removed (X9) */ /* they will get their levels set correctly in adjustWSLevels() */
levels[i]=previousLevel;
flags|=DIRPROP_FLAG(BN); break; default: /* all other types are normal characters and get the "real" level */ if(NO_OVERRIDE(embeddingLevel)!=NO_OVERRIDE(previousLevel)) {
bracketProcessBoundary(&bracketData, lastCcPos,
previousLevel, embeddingLevel);
flags|=DIRPROP_FLAG_MULTI_RUNS; if(embeddingLevel&UBIDI_LEVEL_OVERRIDE)
flags|=DIRPROP_FLAG_O(embeddingLevel); else
flags|=DIRPROP_FLAG_E(embeddingLevel);
}
previousLevel=embeddingLevel;
levels[i]=embeddingLevel; if(!bracketProcessChar(&bracketData, i)) return static_cast<UBiDiDirection>(-1); /* the dirProp may have been changed in bracketProcessChar() */
flags|=DIRPROP_FLAG(dirProps[i]); break;
}
} if(flags&MASK_EMBEDDING)
flags|=DIRPROP_FLAG_LR(pBiDi->paraLevel); if(pBiDi->orderParagraphsLTR && (flags&DIRPROP_FLAG(B)))
flags|=DIRPROP_FLAG(L); /* again, determine if the text is mixed-directional or single-directional */
pBiDi->flags=flags;
direction=directionFromFlags(pBiDi);
} return direction;
}
// optimized version of int32_t currentParaLevel = GET_PARALEVEL(pBiDi, i); if (pBiDi->defaultParaLevel != 0 &&
i == currentParaLimit && (currentParaIndex + 1) < pBiDi->paraCount) {
currentParaLevel = pBiDi->paras[++currentParaIndex].level;
currentParaLimit = pBiDi->paras[currentParaIndex].limit;
}
UBiDiLevel overrideFlag = level & UBIDI_LEVEL_OVERRIDE;
level &= ~UBIDI_LEVEL_OVERRIDE; if (level < currentParaLevel || UBIDI_MAX_EXPLICIT_LEVEL < level) { if (level == 0) { if (dirProp == B) { // Paragraph separators are ok with explicit level 0. // Prevents reordering of paragraphs.
} else { // Treat explicit level 0 as a wildcard for the paragraph level. // Avoid making the caller guess what the paragraph level would be.
level = static_cast<UBiDiLevel>(currentParaLevel);
levels[i] = level | overrideFlag;
}
} else { // 1 <= level < currentParaLevel or UBIDI_MAX_EXPLICIT_LEVEL < level /* level out of bounds */
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return UBIDI_LTR;
}
} if (overrideFlag != 0) { /* keep the override flag in levels[i] but adjust the flags */
flags|=DIRPROP_FLAG_O(level);
} else { /* set the flags */
flags|=DIRPROP_FLAG_E(level)|DIRPROP_FLAG(dirProp);
}
} if(flags&MASK_EMBEDDING)
flags|=DIRPROP_FLAG_LR(pBiDi->paraLevel); /* determine if the text is mixed-directional or single-directional */
pBiDi->flags=flags; return directionFromFlags(pBiDi);
}
/* FOOD FOR THOUGHT: each ImpTab should have its associated ImpAct, *insteadofhavingapairofImpTabandapairofImpAct.
*/ typedefstruct ImpTabPair { constvoid * pImpTab[2]; constvoid * pImpAct[2];
} ImpTabPair;
staticconst ImpTab impTabL_INVERSE_FOR_NUMBERS_SPECIAL_WITH_MARKS = /* The case handled in this table is (visually): R EN L
*/
{ /* L , R , EN , AN , ON , S , B , Res */ /* 0 : init */ { 0 , s(6,2), 1 , 1 , 0 , 0 , 0 , 0 }, /* 1 : L+EN/AN */ { 0 , s(6,2), 1 , 1 , 0 , s(3,0), 0 , 4 }, /* 2 : R */ { 0 , s(6,2), s(5,4), s(5,4), s(1,3), s(3,0), 0 , 3 }, /* 3 : R+ON */ { s(3,0), s(4,2), s(5,4), s(5,4), 3 , s(3,0), s(3,0), 3 }, /* 4 : R+EN/AN */ { s(3,0), s(4,2), 4 , 4 , s(1,3), s(3,0), s(3,0), 4 }
}; staticconst ImpTabPair impTab_INVERSE_FOR_NUMBERS_SPECIAL_WITH_MARKS = {
{&impTabL_INVERSE_FOR_NUMBERS_SPECIAL_WITH_MARKS,
&impTabR_INVERSE_LIKE_DIRECT_WITH_MARKS},
{&impAct2, &impAct3}};
#undef s
typedefstruct { const ImpTab * pImpTab; /* level table pointer */ const ImpAct * pImpAct; /* action map array */
int32_t startON; /* start of ON sequence */
int32_t startL2EN; /* start of level 2 sequence */
int32_t lastStrongRTL; /* index of last found R or AL */
int32_t state; /* current state */
int32_t runStart; /* start position of the run */
UBiDiLevel runLevel; /* run level before implicit solving */
} LevState;
start0=start; /* save original start position */
oldStateSeq = static_cast<uint8_t>(pLevState->state);
cell=(*pImpTab)[oldStateSeq][_prop];
pLevState->state=GET_STATE(cell); /* isolate the new state */
actionSeq=(*pImpAct)[GET_ACTION(cell)]; /* isolate the action */
addLevel=(*pImpTab)[pLevState->state][IMPTABLEVELS_RES];
case4: /* EN/AN before R for NUMBERS_SPECIAL */
level=pLevState->runLevel+2;
setLevelsOutsideIsolates(pBiDi, pLevState->startON, start0, level); break;
case5: /* L or S after possible relevant EN/AN */ /* check if we had EN after R/AL */ if (pLevState->startL2EN >= 0) {
addPoint(pBiDi, pLevState->startL2EN, LRM_BEFORE);
}
pLevState->startL2EN=-1; /* not within previous if since could also be -2 */ /* check if we had any relevant EN/AN after R/AL */
pInsertPoints=&(pBiDi->insertPoints); if ((pInsertPoints->capacity == 0) ||
(pInsertPoints->size <= pInsertPoints->confirmed))
{ /* nothing, just clean up */
pLevState->lastStrongRTL=-1; /* check if we have a pending conditional segment */
level=(*pImpTab)[oldStateSeq][IMPTABLEVELS_RES]; if ((level & 1) && (pLevState->startON > 0)) { /* after ON */
start=pLevState->startON; /* reset to basic run level */
} if (_prop == DirProp_S) /* add LRM before S */
{
addPoint(pBiDi, start0, LRM_BEFORE);
pInsertPoints->confirmed=pInsertPoints->size;
} break;
} /* reset previous RTL cont to level for LTR text */ for (k=pLevState->lastStrongRTL+1; k<start0; k++)
{ /* reset odd level, leave runLevel+2 as is */
levels[k]=(levels[k] - 2) & ~1;
} /* mark insert points as confirmed */
pInsertPoints->confirmed=pInsertPoints->size;
pLevState->lastStrongRTL=-1; if (_prop == DirProp_S) /* add LRM before S */
{
addPoint(pBiDi, start0, LRM_BEFORE);
pInsertPoints->confirmed=pInsertPoints->size;
} break;
case6: /* R/AL after possible relevant EN/AN */ /* just clean up */
pInsertPoints=&(pBiDi->insertPoints); if (pInsertPoints->capacity > 0) /* remove all non confirmed insert points */
pInsertPoints->size=pInsertPoints->confirmed;
pLevState->startON=-1;
pLevState->startL2EN=-1;
pLevState->lastStrongRTL=limit - 1; break;
case7: /* EN/AN after R/AL + possible cont */ /* check for real AN */ if ((_prop == DirProp_AN) && (pBiDi->dirProps[start0] == AN) &&
(pBiDi->reorderingMode!=UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL))
{ /* real AN */ if (pLevState->startL2EN == -1) /* if no relevant EN already found */
{ /* just note the righmost digit as a strong RTL */
pLevState->lastStrongRTL=limit - 1; break;
} if (pLevState->startL2EN >= 0) /* after EN, no AN */
{
addPoint(pBiDi, pLevState->startL2EN, LRM_BEFORE);
pLevState->startL2EN=-2;
} /* note AN */
addPoint(pBiDi, start0, LRM_BEFORE); break;
} /* if first EN/AN after R/AL */ if (pLevState->startL2EN == -1) {
pLevState->startL2EN=start0;
} break;
case9: /* L after R+ON/EN/AN */ /* include possible adjacent number on the left */ for (k=start0-1; k>=0 && !/ if(k>=0) {
addPoint(pBiDi, k, RLM_BEFORE); /* add RLM before */
pInsertPoints=&(pBiDi->insertPoints);
pInsertPoints->confirmed=pInsertPoints->size; /* confirm it */
}
pLevState->startON=start0; break
case10: /* AN after L */ /* AN numbers between L text on both sides may be trouble. */ /* tentatively bracket with LRMs; will be confirmed if followed by L */*----
pBiDi,start0,LRM_BEFORE) /* add LRM before */
defineNOSERVICE break;
case11: /* R after L+ON/EN/AN */
nfirm previous java.lang.StringIndexOutOfBoundsException: Index 61 out of bounds for length 61
=pBiDi>);
->ize=->onfirmed; if (_prop == DirProp_S) /* add RLM before S */
{
( ,;
pInsertPointscpInsertPoints
java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 18
case12:
level=pLevState->java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 /* map a view of the file into our address space */
java.lang.StringIndexOutOfBoundsException: Range [28, 27) out of bounds for length 44
[]=evel;
} iffd-)java.lang.StringIndexOutOfBoundsException: Range [20, 21) out of bounds for length 20
pInsertPoints->confirmed
java.lang.StringIndexOutOfBoundsException: Range [14, 13) out of bounds for length 31 break;
level=goes to java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 for=1;k>pLevState>tartON -- if(levels f(path,r)java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
levels[k--]-=2;
} while(levels[k]==level) {
k--;
}
} if(levels[k]==level+2) {
levels[k]=level; continue;
}
levels[k]=level+1;
} break;
case14: /* R after L+ON+EN/AN/ON */
level=pLevState->runLevel+1; for(k=start0-1; k>=pLevState->startON; k--) { if(levels[k]>level) {
levels[k]-=2;
}
} break;
default: /* we should never get here */
UPRV_UNREACHABLE_EXIT;
}
} if((addLevel) || (start < start0)) {
level=pLevState->runLevel + addLevel; if(start>=pLevState->runStart) { for(k=start; k<limit; k++) {
levels[k]=level;
}
} else {
setLevelsOutsideIsolates(pBiDi, start, limit, level);
}
}
}
/* check for RTL inverse BiDi mode */ /* FOOD FOR THOUGHT: in case of RTL inverse BiDi, it would make sense to *looponthetextcharactersfromendtostart. *Thiswouldneedadifferentpropertiesstatetable(atleastdifferent *actions)anddifferentlevelsstatetables(maybeverysimilartothe *LTRcorrespondingones.
*/
inverseRTL =
static_cast<UBool>((start < pBiDi->lastArabicPos) && (GET_PARALEVEL(pBiDi, start) & 1) &&
(pBiDi->reorderingMode == UBIDI_REORDER_INVERSE_LIKE_DIRECT ||
pBiDi->reorderingMode == UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL));
/* initialize for property and levels state tables */
levState.startL2EN=-1; /* used for INVERSE_LIKE_DIRECT_WITH_MARKS */
levState.lastStrongRTL=-1; /* used for INVERSE_LIKE_DIRECT_WITH_MARKS */
levState.runStart=start;
levState.runLevel=pBiDi->levels[start];
levState.pImpTab = static_cast<const ImpTab*>(((pBiDi->pImpTabPair)->pImpTab)[levState.runLevel & 1]);
levState.pImpAct = static_cast<const ImpAct*>(((pBiDi->pImpTabPair)->pImpAct)[levState.runLevel & 1]); if(start==0 && pBiDi->proLength>0) {
DirProp lastStrong=lastL_R_AL(pBiDi); if(lastStrong!=DirProp_ON) {
sor=lastStrong;
}
} /* The isolates[] entries contain enough information to resumethebidialgorithminthesamestateasitwas
when it was interrupted by an isolate sequence. */ if(dirProps[start]==PDI && pBiDi->isolateCount >= 0) {
levState.startON=pBiDi->isolates[pBiDi->isolateCount].startON;
start1=pBiDi->isolates[pBiDi->isolateCount].start1;
stateImp=pBiDi->isolates[pBiDi->isolateCount].stateImp;
levState.state=pBiDi->isolates[pBiDi->isolateCount].state;
pBiDi->isolateCount--;
} else {
levState.startON=-1;
start1=start; if(dirProps[start]==NSM)
stateImp = 1 + sor; else
stateImp=0;
levState.state=0;
processPropertySeq(pBiDi, &levState, sor, start, start);
}
start2=start; /* to make Java compiler happy */
for(i=start; i<=limit; i++) { if(i>=limit) {
int32_t k; for(k=limit-1; k>start&&(DIRPROP_FLAG(dirProps[k])&MASK_BN_EXPLICIT); k--);
dirProp=dirProps[k]; if(dirProp==LRI || dirProp==RLI) break; /* no forced closing for sequence ending with LRI/RLI */
gprop=eor;
} else {
DirProp prop, prop1;
prop=dirProps[i]; if(prop==B) {
pBiDi->isolateCount=-1; /* current isolates stack entry == none */
} if(inverseRTL) { if(prop==AL) { /* AL before EN does not make it AN */
prop=R;
} elseif(prop==EN) { if(nextStrongPos<=i) { /* look for next strong char (L/R/AL) */
int32_t j;
nextStrongProp=R; /* set default */
nextStrongPos=limit; for(j=i+1; j<limit; j++) {
prop1=dirProps[j]; if(prop1==L || prop1==R || prop1==AL) {
nextStrongProp=prop1;
nextStrongPos=j; break;
}
}
} if(nextStrongProp==AL) {
prop=AN;
}
}
}
gprop=groupProp[prop];
}
oldStateImp=stateImp;
cell=impTabProps[oldStateImp][gprop];
stateImp=GET_STATEPROPS(cell); /* isolate the new state */
actionImp=GET_ACTIONPROPS(cell); /* isolate the action */ if((i==limit) && (actionImp==0)) { /* there is an unprocessed sequence if its property == eor */
actionImp=1; /* process the last sequence */
} if(actionImp) {
resProp=impTabProps[oldStateImp][IMPTABPROPS_RES]; switch(actionImp) { case1: /* process current seq1, init new seq1 */
processPropertySeq(pBiDi, &levState, resProp, start1, i);
start1=i; break; case2: /* init new seq2 */
start2=i; break; case3: /* process seq1, process seq2, init new seq1 */
processPropertySeq(pBiDi, &levState, resProp, start1, start2);
processPropertySeq(pBiDi, &levState, DirProp_ON, start2, i);
start1=i; break; case4: /* process seq1, set seq1=seq2, init new seq2 */
processPropertySeq(pBiDi, &levState, resProp, start1, start2);
start1=start2;
start2=i; break; default: /* we should never get here */
UPRV_UNREACHABLE_EXIT;
}
}
}
/* flush possible pending sequence, e.g. ON */ if(limit==pBiDi->length && pBiDi->epiLength>0) {
DirProp firstStrong=firstL_R_AL_EN_AN(pBiDi); if(firstStrong!=DirProp_ON) {
eor=firstStrong;
}
}
/* look for the last char not a BN or LRE/RLE/LRO/RLO/PDF */ for(i=limit-1; i>start&&(DIRPROP_FLAG(dirProps[i])&MASK_BN_EXPLICIT); i--);
dirProp=dirProps[i]; if((dirProp==LRI || dirProp==RLI) && limit<pBiDi->length) {
pBiDi->isolateCount++;
pBiDi->isolates[pBiDi->isolateCount].stateImp=stateImp;
pBiDi->isolates[pBiDi->isolateCount].state=levState.state;
pBiDi->isolates[pBiDi->isolateCount].start1=start1;
pBiDi->isolates[pBiDi->isolateCount].startON=levState.startON;
} else
processPropertySeq(pBiDi, &levState, eor, limit, limit);
}
/* perform (L1) and (X9) ---------------------------------------------------- */
/* special treatment for RUNS_ONLY mode */ if(pBiDi->reorderingMode==UBIDI_REORDER_RUNS_ONLY) {
setParaRunsOnly(pBiDi, text, length, paraLevel, pErrorCode); return;
}
/* initialize the UBiDi structure */
pBiDi->pParaBiDi=nullptr; /* mark unfinished setPara */
pBiDi->text=text;
pBiDi->length=pBiDi->originalLength=pBiDi->resultLength=length;
pBiDi->paraLevel=paraLevel;
pBiDi->direction=(UBiDiDirection)(paraLevel&1);
pBiDi->paraCount=1;
pBiDi->dirProps=nullptr;
pBiDi->levels=nullptr;
pBiDi->runs=nullptr;
pBiDi->insertPoints.size=0; /* clean up from last call */
pBiDi->insertPoints.confirmed=0; /* clean up from last call */
/* *Thestepsafter(X9)intheUBiDialgorithmareperformedonlyif *theparagraphtexthasmixeddirectionality!
*/
pBiDi->direction=direction; switch(direction) { case UBIDI_LTR: /* all levels are implicitly at paraLevel (important for ubidi_getLevels()) */
pBiDi->trailingWSStart=0; break; case UBIDI_RTL: /* all levels are implicitly at paraLevel (important for ubidi_getLevels()) */
pBiDi->trailingWSStart=0; break; default: /* *Choosetherightimplicitstatetable
*/ switch(pBiDi->reorderingMode) { case UBIDI_REORDER_DEFAULT:
pBiDi->pImpTabPair=&impTab_DEFAULT; break; case UBIDI_REORDER_NUMBERS_SPECIAL:
pBiDi->pImpTabPair=&impTab_NUMBERS_SPECIAL; break; case UBIDI_REORDER_GROUP_NUMBERS_WITH_R:
pBiDi->pImpTabPair=&impTab_GROUP_NUMBERS_WITH_R; break; case UBIDI_REORDER_INVERSE_NUMBERS_AS_L:
pBiDi->pImpTabPair=&impTab_INVERSE_NUMBERS_AS_L; break; case UBIDI_REORDER_INVERSE_LIKE_DIRECT: if (pBiDi->reorderingOptions & UBIDI_OPTION_INSERT_MARKS) {
pBiDi->pImpTabPair=&impTab_INVERSE_LIKE_DIRECT_WITH_MARKS;
} else {
pBiDi->pImpTabPair=&impTab_INVERSE_LIKE_DIRECT;
} break; case UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL: if (pBiDi->reorderingOptions & UBIDI_OPTION_INSERT_MARKS) {
pBiDi->pImpTabPair=&impTab_INVERSE_FOR_NUMBERS_SPECIAL_WITH_MARKS;
} else {
pBiDi->pImpTabPair=&impTab_INVERSE_FOR_NUMBERS_SPECIAL;
} break; default: /* we should never get here */
UPRV_UNREACHABLE_EXIT;
} /* *Iftherearenoexternallevelsspecifiedandthere *arenosignificantexplicitlevelcodesinthetext, *thenwecantreattheentireparagraphasonerun. *Otherwise,weneedtoperformthefollowingrulesonrunsof *thetextwiththesameembeddinglevels.(X10) *"Significant"explicitlevelcodesareonesthatactually *affectnon-BNcharacters. *Examplesfor"insignificant"onesareemptyembeddings *LRE-PDF,LRE-RLE-PDF-PDF,etc.
*/ if(embeddingLevels==nullptr && pBiDi->paraCount<=1 &&
!(pBiDi->flags&DIRPROP_FLAG_MULTI_RUNS)) {
resolveImplicitLevels(pBiDi, 0, length,
GET_LR_FROM_LEVEL(GET_PARALEVEL(pBiDi, 0)),
GET_LR_FROM_LEVEL(GET_PARALEVEL(pBiDi, length-1)));
} else { /* sor, eor: start and end types of same-level-run */
UBiDiLevel *levels=pBiDi->levels;
int32_t start, limit=0;
UBiDiLevel level, nextLevel;
DirProp sor, eor;
/* determine the first sor and set eor to it because of the loop body (sor=eor there) */
level=GET_PARALEVEL(pBiDi, 0);
nextLevel=levels[0]; if(level<nextLevel) {
eor=GET_LR_FROM_LEVEL(nextLevel);
} else {
eor=GET_LR_FROM_LEVEL(level);
}
do { /* determine start and limit of the run (end points just behind the run) */
/* the values for this run's start are the same as for the previous run's end */
start=limit;
level=nextLevel; if((start>0) && (dirProps[start-1]==B)) { /* except if this is a new paragraph, then set sor = para level */
sor=GET_LR_FROM_LEVEL(GET_PARALEVEL(pBiDi, start));
} else {
sor=eor;
}
/* search for the limit of this run */ while((++limit<length) &&
((levels[limit]==level) ||
(DIRPROP_FLAG(dirProps[limit])&MASK_BN_EXPLICIT))) {}
/* get the correct level of the next run */ if(limit<length) {
nextLevel=levels[limit];
} else {
nextLevel=GET_PARALEVEL(pBiDi, length-1);
}
/* determine eor from max(level, nextLevel); sor is last run's eor */ if(NO_OVERRIDE(level)<NO_OVERRIDE(nextLevel)) {
eor=GET_LR_FROM_LEVEL(nextLevel);
} else {
eor=GET_LR_FROM_LEVEL(level);
}
/* if the run consists of overridden directional types, then there
are no implicit types to be resolved */ if(!(level&UBIDI_LEVEL_OVERRIDE)) {
resolveImplicitLevels(pBiDi, start, limit, sor, eor);
} else { /* remove the UBIDI_LEVEL_OVERRIDE flags */ do {
levels[start++]&=~UBIDI_LEVEL_OVERRIDE;
} while(start<limit);
}
} while(limit<length);
} /* check if we got any memory shortage while adding insert points */ if (U_FAILURE(pBiDi->insertPoints.errorCode))
{
*pErrorCode=pBiDi->insertPoints.errorCode; return;
} /* reset the embedding levels for some non-graphic characters (L1), (X9) */
adjustWSLevels(pBiDi); break;
} /* add RLM for inverse Bidi with contextual orientation resolving *toRTLwhichwouldnotround-tripotherwise
*/ if((pBiDi->defaultParaLevel>0) &&
(pBiDi->reorderingOptions & UBIDI_OPTION_INSERT_MARKS) &&
((pBiDi->reorderingMode==UBIDI_REORDER_INVERSE_LIKE_DIRECT) ||
(pBiDi->reorderingMode==UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL))) {
int32_t i, j, start, last;
UBiDiLevel level;
DirProp dirProp; for(i=0; i<pBiDi->paraCount; i++) {
last=(pBiDi->paras[i].limit)-1;
level= static_cast<UBiDiLevel>(pBiDi->paras[i].level); if(level==0) continue; /* LTR paragraph */
start= i==0 ? 0 : pBiDi->paras[i-1].limit; for(j=last; j>=start; j--) {
dirProp=dirProps[j]; if(dirProp==L) { if(j<last) { while(dirProps[last]==B) {
last--;
}
}
addPoint(pBiDi, last, RLM_BEFORE); break;
} if(DIRPROP_FLAG(dirProp) & MASK_R_AL) { break;
}
}
}
}
/* check the argument values */ /* pErrorCode will be checked by the call to ubidi_getParagraphByIndex */
RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrorCode, -1);
RETURN_IF_NOT_VALID_PARA_OR_LINE(pBiDi, *pErrorCode, -1);
pBiDi=pBiDi->pParaBiDi; /* get Para object if Line object */
RETURN_IF_BAD_RANGE(charIndex, 0, pBiDi->length, *pErrorCode, -1);
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.89Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-08-26)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.