LCOV - code coverage report
Current view: top level - intl/icu/source/common - ubidiwrt.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 280 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 4 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // © 2016 and later: Unicode, Inc. and others.
       2             : // License & terms of use: http://www.unicode.org/copyright.html
       3             : /*
       4             : ******************************************************************************
       5             : *
       6             : *   Copyright (C) 2000-2015, International Business Machines
       7             : *   Corporation and others.  All Rights Reserved.
       8             : *
       9             : ******************************************************************************
      10             : *   file name:  ubidiwrt.c
      11             : *   encoding:   UTF-8
      12             : *   tab size:   8 (not used)
      13             : *   indentation:4
      14             : *
      15             : *   created on: 1999aug06
      16             : *   created by: Markus W. Scherer, updated by Matitiahu Allouche
      17             : *
      18             : * This file contains implementations for BiDi functions that use
      19             : * the core algorithm and core API to write reordered text.
      20             : */
      21             : 
      22             : #include "unicode/utypes.h"
      23             : #include "unicode/ustring.h"
      24             : #include "unicode/uchar.h"
      25             : #include "unicode/ubidi.h"
      26             : #include "unicode/utf16.h"
      27             : #include "cmemory.h"
      28             : #include "ustr_imp.h"
      29             : #include "ubidiimp.h"
      30             : 
      31             : /*
      32             :  * The function implementations in this file are designed
      33             :  * for UTF-16 and UTF-32, not for UTF-8.
      34             :  *
      35             :  * Assumptions that are not true for UTF-8:
      36             :  * - Any code point always needs the same number of code units
      37             :  *   ("minimum-length-problem" of UTF-8)
      38             :  * - The BiDi control characters need only one code unit each
      39             :  *
      40             :  * Further assumptions for all UTFs:
      41             :  * - u_charMirror(c) needs the same number of code units as c
      42             :  */
      43             : #if UTF_SIZE==8
      44             : # error reimplement ubidi_writeReordered() for UTF-8, see comment above
      45             : #endif
      46             : 
      47             : #define IS_COMBINING(type) ((1UL<<(type))&(1UL<<U_NON_SPACING_MARK|1UL<<U_COMBINING_SPACING_MARK|1UL<<U_ENCLOSING_MARK))
      48             : 
      49             : /*
      50             :  * When we have UBIDI_OUTPUT_REVERSE set on ubidi_writeReordered(), then we
      51             :  * semantically write RTL runs in reverse and later reverse them again.
      52             :  * Instead, we actually write them in forward order to begin with.
      53             :  * However, if the RTL run was to be mirrored, we need to mirror here now
      54             :  * since the implicit second reversal must not do it.
      55             :  * It looks strange to do mirroring in LTR output, but it is only because
      56             :  * we are writing RTL output in reverse.
      57             :  */
      58             : static int32_t
      59           0 : doWriteForward(const UChar *src, int32_t srcLength,
      60             :                UChar *dest, int32_t destSize,
      61             :                uint16_t options,
      62             :                UErrorCode *pErrorCode) {
      63             :     /* optimize for several combinations of options */
      64           0 :     switch(options&(UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING)) {
      65             :     case 0: {
      66             :         /* simply copy the LTR run to the destination */
      67           0 :         int32_t length=srcLength;
      68           0 :         if(destSize<length) {
      69           0 :             *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
      70           0 :             return srcLength;
      71             :         }
      72           0 :         do {
      73           0 :             *dest++=*src++;
      74             :         } while(--length>0);
      75           0 :         return srcLength;
      76             :     }
      77             :     case UBIDI_DO_MIRRORING: {
      78             :         /* do mirroring */
      79           0 :         int32_t i=0, j=0;
      80             :         UChar32 c;
      81             : 
      82           0 :         if(destSize<srcLength) {
      83           0 :             *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
      84           0 :             return srcLength;
      85             :         }
      86           0 :         do {
      87           0 :             U16_NEXT(src, i, srcLength, c);
      88           0 :             c=u_charMirror(c);
      89           0 :             U16_APPEND_UNSAFE(dest, j, c);
      90           0 :         } while(i<srcLength);
      91           0 :         return srcLength;
      92             :     }
      93             :     case UBIDI_REMOVE_BIDI_CONTROLS: {
      94             :         /* copy the LTR run and remove any BiDi control characters */
      95           0 :         int32_t remaining=destSize;
      96             :         UChar c;
      97           0 :         do {
      98           0 :             c=*src++;
      99           0 :             if(!IS_BIDI_CONTROL_CHAR(c)) {
     100           0 :                 if(--remaining<0) {
     101           0 :                     *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
     102             : 
     103             :                     /* preflight the length */
     104           0 :                     while(--srcLength>0) {
     105           0 :                         c=*src++;
     106           0 :                         if(!IS_BIDI_CONTROL_CHAR(c)) {
     107           0 :                             --remaining;
     108             :                         }
     109             :                     }
     110           0 :                     return destSize-remaining;
     111             :                 }
     112           0 :                 *dest++=c;
     113             :             }
     114             :         } while(--srcLength>0);
     115           0 :         return destSize-remaining;
     116             :     }
     117             :     default: {
     118             :         /* remove BiDi control characters and do mirroring */
     119           0 :         int32_t remaining=destSize;
     120           0 :         int32_t i, j=0;
     121             :         UChar32 c;
     122           0 :         do {
     123           0 :             i=0;
     124           0 :             U16_NEXT(src, i, srcLength, c);
     125           0 :             src+=i;
     126           0 :             srcLength-=i;
     127           0 :             if(!IS_BIDI_CONTROL_CHAR(c)) {
     128           0 :                 remaining-=i;
     129           0 :                 if(remaining<0) {
     130           0 :                     *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
     131             : 
     132             :                     /* preflight the length */
     133           0 :                     while(srcLength>0) {
     134           0 :                         c=*src++;
     135           0 :                         if(!IS_BIDI_CONTROL_CHAR(c)) {
     136           0 :                             --remaining;
     137             :                         }
     138           0 :                         --srcLength;
     139             :                     }
     140           0 :                     return destSize-remaining;
     141             :                 }
     142           0 :                 c=u_charMirror(c);
     143           0 :                 U16_APPEND_UNSAFE(dest, j, c);
     144             :             }
     145           0 :         } while(srcLength>0);
     146           0 :         return j;
     147             :     }
     148             :     } /* end of switch */
     149             : }
     150             : 
     151             : static int32_t
     152           0 : doWriteReverse(const UChar *src, int32_t srcLength,
     153             :                UChar *dest, int32_t destSize,
     154             :                uint16_t options,
     155             :                UErrorCode *pErrorCode) {
     156             :     /*
     157             :      * RTL run -
     158             :      *
     159             :      * RTL runs need to be copied to the destination in reverse order
     160             :      * of code points, not code units, to keep Unicode characters intact.
     161             :      *
     162             :      * The general strategy for this is to read the source text
     163             :      * in backward order, collect all code units for a code point
     164             :      * (and optionally following combining characters, see below),
     165             :      * and copy all these code units in ascending order
     166             :      * to the destination for this run.
     167             :      *
     168             :      * Several options request whether combining characters
     169             :      * should be kept after their base characters,
     170             :      * whether BiDi control characters should be removed, and
     171             :      * whether characters should be replaced by their mirror-image
     172             :      * equivalent Unicode characters.
     173             :      */
     174             :     int32_t i, j;
     175             :     UChar32 c;
     176             : 
     177             :     /* optimize for several combinations of options */
     178           0 :     switch(options&(UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING|UBIDI_KEEP_BASE_COMBINING)) {
     179             :     case 0:
     180             :         /*
     181             :          * With none of the "complicated" options set, the destination
     182             :          * run will have the same length as the source run,
     183             :          * and there is no mirroring and no keeping combining characters
     184             :          * with their base characters.
     185             :          */
     186           0 :         if(destSize<srcLength) {
     187           0 :             *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
     188           0 :             return srcLength;
     189             :         }
     190           0 :         destSize=srcLength;
     191             : 
     192             :         /* preserve character integrity */
     193           0 :         do {
     194             :             /* i is always after the last code unit known to need to be kept in this segment */
     195           0 :             i=srcLength;
     196             : 
     197             :             /* collect code units for one base character */
     198           0 :             U16_BACK_1(src, 0, srcLength);
     199             : 
     200             :             /* copy this base character */
     201           0 :             j=srcLength;
     202           0 :             do {
     203           0 :                 *dest++=src[j++];
     204           0 :             } while(j<i);
     205           0 :         } while(srcLength>0);
     206           0 :         break;
     207             :     case UBIDI_KEEP_BASE_COMBINING:
     208             :         /*
     209             :          * Here, too, the destination
     210             :          * run will have the same length as the source run,
     211             :          * and there is no mirroring.
     212             :          * We do need to keep combining characters with their base characters.
     213             :          */
     214           0 :         if(destSize<srcLength) {
     215           0 :             *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
     216           0 :             return srcLength;
     217             :         }
     218           0 :         destSize=srcLength;
     219             : 
     220             :         /* preserve character integrity */
     221           0 :         do {
     222             :             /* i is always after the last code unit known to need to be kept in this segment */
     223           0 :             i=srcLength;
     224             : 
     225             :             /* collect code units and modifier letters for one base character */
     226           0 :             do {
     227           0 :                 U16_PREV(src, 0, srcLength, c);
     228           0 :             } while(srcLength>0 && IS_COMBINING(u_charType(c)));
     229             : 
     230             :             /* copy this "user character" */
     231           0 :             j=srcLength;
     232           0 :             do {
     233           0 :                 *dest++=src[j++];
     234           0 :             } while(j<i);
     235           0 :         } while(srcLength>0);
     236           0 :         break;
     237             :     default:
     238             :         /*
     239             :          * With several "complicated" options set, this is the most
     240             :          * general and the slowest copying of an RTL run.
     241             :          * We will do mirroring, remove BiDi controls, and
     242             :          * keep combining characters with their base characters
     243             :          * as requested.
     244             :          */
     245           0 :         if(!(options&UBIDI_REMOVE_BIDI_CONTROLS)) {
     246           0 :             i=srcLength;
     247             :         } else {
     248             :             /* we need to find out the destination length of the run,
     249             :                which will not include the BiDi control characters */
     250           0 :             int32_t length=srcLength;
     251             :             UChar ch;
     252             : 
     253           0 :             i=0;
     254           0 :             do {
     255           0 :                 ch=*src++;
     256           0 :                 if(!IS_BIDI_CONTROL_CHAR(ch)) {
     257           0 :                     ++i;
     258             :                 }
     259             :             } while(--length>0);
     260           0 :             src-=srcLength;
     261             :         }
     262             : 
     263           0 :         if(destSize<i) {
     264           0 :             *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
     265           0 :             return i;
     266             :         }
     267           0 :         destSize=i;
     268             : 
     269             :         /* preserve character integrity */
     270           0 :         do {
     271             :             /* i is always after the last code unit known to need to be kept in this segment */
     272           0 :             i=srcLength;
     273             : 
     274             :             /* collect code units for one base character */
     275           0 :             U16_PREV(src, 0, srcLength, c);
     276           0 :             if(options&UBIDI_KEEP_BASE_COMBINING) {
     277             :                 /* collect modifier letters for this base character */
     278           0 :                 while(srcLength>0 && IS_COMBINING(u_charType(c))) {
     279           0 :                     U16_PREV(src, 0, srcLength, c);
     280             :                 }
     281             :             }
     282             : 
     283           0 :             if(options&UBIDI_REMOVE_BIDI_CONTROLS && IS_BIDI_CONTROL_CHAR(c)) {
     284             :                 /* do not copy this BiDi control character */
     285           0 :                 continue;
     286             :             }
     287             : 
     288             :             /* copy this "user character" */
     289           0 :             j=srcLength;
     290           0 :             if(options&UBIDI_DO_MIRRORING) {
     291             :                 /* mirror only the base character */
     292           0 :                 int32_t k=0;
     293           0 :                 c=u_charMirror(c);
     294           0 :                 U16_APPEND_UNSAFE(dest, k, c);
     295           0 :                 dest+=k;
     296           0 :                 j+=k;
     297             :             }
     298           0 :             while(j<i) {
     299           0 :                 *dest++=src[j++];
     300             :             }
     301           0 :         } while(srcLength>0);
     302           0 :         break;
     303             :     } /* end of switch */
     304             : 
     305           0 :     return destSize;
     306             : }
     307             : 
     308             : U_CAPI int32_t U_EXPORT2
     309           0 : ubidi_writeReverse(const UChar *src, int32_t srcLength,
     310             :                    UChar *dest, int32_t destSize,
     311             :                    uint16_t options,
     312             :                    UErrorCode *pErrorCode) {
     313             :     int32_t destLength;
     314             : 
     315           0 :     if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
     316           0 :         return 0;
     317             :     }
     318             : 
     319             :     /* more error checking */
     320           0 :     if( src==NULL || srcLength<-1 ||
     321           0 :         destSize<0 || (destSize>0 && dest==NULL))
     322             :     {
     323           0 :         *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
     324           0 :         return 0;
     325             :     }
     326             : 
     327             :     /* do input and output overlap? */
     328           0 :     if( dest!=NULL &&
     329           0 :         ((src>=dest && src<dest+destSize) ||
     330           0 :          (dest>=src && dest<src+srcLength)))
     331             :     {
     332           0 :         *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
     333           0 :         return 0;
     334             :     }
     335             : 
     336           0 :     if(srcLength==-1) {
     337           0 :         srcLength=u_strlen(src);
     338             :     }
     339           0 :     if(srcLength>0) {
     340           0 :         destLength=doWriteReverse(src, srcLength, dest, destSize, options, pErrorCode);
     341             :     } else {
     342             :         /* nothing to do */
     343           0 :         destLength=0;
     344             :     }
     345             : 
     346           0 :     return u_terminateUChars(dest, destSize, destLength, pErrorCode);
     347             : }
     348             : 
     349             : U_CAPI int32_t U_EXPORT2
     350           0 : ubidi_writeReordered(UBiDi *pBiDi,
     351             :                      UChar *dest, int32_t destSize,
     352             :                      uint16_t options,
     353             :                      UErrorCode *pErrorCode) {
     354             :     const UChar *text;
     355             :     UChar *saveDest;
     356             :     int32_t length, destCapacity;
     357             :     int32_t run, runCount, logicalStart, runLength;
     358             : 
     359           0 :     if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
     360           0 :         return 0;
     361             :     }
     362             : 
     363             :     /* more error checking */
     364           0 :     if( pBiDi==NULL ||
     365           0 :         (text=pBiDi->text)==NULL || (length=pBiDi->length)<0 ||
     366           0 :         destSize<0 || (destSize>0 && dest==NULL))
     367             :     {
     368           0 :         *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
     369           0 :         return 0;
     370             :     }
     371             : 
     372             :     /* do input and output overlap? */
     373           0 :     if( dest!=NULL &&
     374           0 :         ((text>=dest && text<dest+destSize) ||
     375           0 :          (dest>=text && dest<text+pBiDi->originalLength)))
     376             :     {
     377           0 :         *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
     378           0 :         return 0;
     379             :     }
     380             : 
     381           0 :     if(length==0) {
     382             :         /* nothing to do */
     383           0 :         return u_terminateUChars(dest, destSize, 0, pErrorCode);
     384             :     }
     385             : 
     386           0 :     runCount=ubidi_countRuns(pBiDi, pErrorCode);
     387           0 :     if(U_FAILURE(*pErrorCode)) {
     388           0 :         return 0;
     389             :     }
     390             : 
     391             :     /* destSize shrinks, later destination length=destCapacity-destSize */
     392           0 :     saveDest=dest;
     393           0 :     destCapacity=destSize;
     394             : 
     395             :     /*
     396             :      * Option "insert marks" implies UBIDI_INSERT_LRM_FOR_NUMERIC if the
     397             :      * reordering mode (checked below) is appropriate.
     398             :      */
     399           0 :     if(pBiDi->reorderingOptions & UBIDI_OPTION_INSERT_MARKS) {
     400           0 :         options|=UBIDI_INSERT_LRM_FOR_NUMERIC;
     401           0 :         options&=~UBIDI_REMOVE_BIDI_CONTROLS;
     402             :     }
     403             :     /*
     404             :      * Option "remove controls" implies UBIDI_REMOVE_BIDI_CONTROLS
     405             :      * and cancels UBIDI_INSERT_LRM_FOR_NUMERIC.
     406             :      */
     407           0 :     if(pBiDi->reorderingOptions & UBIDI_OPTION_REMOVE_CONTROLS) {
     408           0 :         options|=UBIDI_REMOVE_BIDI_CONTROLS;
     409           0 :         options&=~UBIDI_INSERT_LRM_FOR_NUMERIC;
     410             :     }
     411             :     /*
     412             :      * If we do not perform the "inverse BiDi" algorithm, then we
     413             :      * don't need to insert any LRMs, and don't need to test for it.
     414             :      */
     415           0 :     if((pBiDi->reorderingMode != UBIDI_REORDER_INVERSE_NUMBERS_AS_L) &&
     416           0 :        (pBiDi->reorderingMode != UBIDI_REORDER_INVERSE_LIKE_DIRECT)  &&
     417           0 :        (pBiDi->reorderingMode != UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL) &&
     418           0 :        (pBiDi->reorderingMode != UBIDI_REORDER_RUNS_ONLY)) {
     419           0 :         options&=~UBIDI_INSERT_LRM_FOR_NUMERIC;
     420             :     }
     421             :     /*
     422             :      * Iterate through all visual runs and copy the run text segments to
     423             :      * the destination, according to the options.
     424             :      *
     425             :      * The tests for where to insert LRMs ignore the fact that there may be
     426             :      * BN codes or non-BMP code points at the beginning and end of a run;
     427             :      * they may insert LRMs unnecessarily but the tests are faster this way
     428             :      * (this would have to be improved for UTF-8).
     429             :      *
     430             :      * Note that the only errors that are set by doWriteXY() are buffer overflow
     431             :      * errors. Ignore them until the end, and continue for preflighting.
     432             :      */
     433           0 :     if(!(options&UBIDI_OUTPUT_REVERSE)) {
     434             :         /* forward output */
     435           0 :         if(!(options&UBIDI_INSERT_LRM_FOR_NUMERIC)) {
     436             :             /* do not insert BiDi controls */
     437           0 :             for(run=0; run<runCount; ++run) {
     438           0 :                 if(UBIDI_LTR==ubidi_getVisualRun(pBiDi, run, &logicalStart, &runLength)) {
     439           0 :                     runLength=doWriteForward(text+logicalStart, runLength,
     440             :                                              dest, destSize,
     441           0 :                                              (uint16_t)(options&~UBIDI_DO_MIRRORING), pErrorCode);
     442             :                 } else {
     443           0 :                     runLength=doWriteReverse(text+logicalStart, runLength,
     444             :                                              dest, destSize,
     445             :                                              options, pErrorCode);
     446             :                 }
     447           0 :                 if(dest!=NULL) {
     448           0 :                   dest+=runLength;
     449             :                 }
     450           0 :                 destSize-=runLength;
     451             :             }
     452             :         } else {
     453             :             /* insert BiDi controls for "inverse BiDi" */
     454           0 :             const DirProp *dirProps=pBiDi->dirProps;
     455             :             const UChar *src;
     456             :             UChar uc;
     457             :             UBiDiDirection dir;
     458             :             int32_t markFlag;
     459             : 
     460           0 :             for(run=0; run<runCount; ++run) {
     461           0 :                 dir=ubidi_getVisualRun(pBiDi, run, &logicalStart, &runLength);
     462           0 :                 src=text+logicalStart;
     463             :                 /* check if something relevant in insertPoints */
     464           0 :                 markFlag=pBiDi->runs[run].insertRemove;
     465           0 :                 if(markFlag<0) {        /* BiDi controls count */
     466           0 :                     markFlag=0;
     467             :                 }
     468             : 
     469           0 :                 if(UBIDI_LTR==dir) {
     470           0 :                     if((pBiDi->isInverse) &&
     471           0 :                        (/*run>0 &&*/ dirProps[logicalStart]!=L)) {
     472           0 :                         markFlag |= LRM_BEFORE;
     473             :                     }
     474           0 :                     if (markFlag & LRM_BEFORE) {
     475           0 :                         uc=LRM_CHAR;
     476             :                     }
     477           0 :                     else if (markFlag & RLM_BEFORE) {
     478           0 :                         uc=RLM_CHAR;
     479             :                     }
     480           0 :                     else  uc=0;
     481           0 :                     if(uc) {
     482           0 :                         if(destSize>0) {
     483           0 :                             *dest++=uc;
     484             :                         }
     485           0 :                         --destSize;
     486             :                     }
     487             : 
     488           0 :                     runLength=doWriteForward(src, runLength,
     489             :                                              dest, destSize,
     490           0 :                                              (uint16_t)(options&~UBIDI_DO_MIRRORING), pErrorCode);
     491           0 :                     if(dest!=NULL) {
     492           0 :                       dest+=runLength;
     493             :                     }
     494           0 :                     destSize-=runLength;
     495             : 
     496           0 :                     if((pBiDi->isInverse) &&
     497           0 :                        (/*run<runCount-1 &&*/ dirProps[logicalStart+runLength-1]!=L)) {
     498           0 :                         markFlag |= LRM_AFTER;
     499             :                     }
     500           0 :                     if (markFlag & LRM_AFTER) {
     501           0 :                         uc=LRM_CHAR;
     502             :                     }
     503           0 :                     else if (markFlag & RLM_AFTER) {
     504           0 :                         uc=RLM_CHAR;
     505             :                     }
     506           0 :                     else  uc=0;
     507           0 :                     if(uc) {
     508           0 :                         if(destSize>0) {
     509           0 :                             *dest++=uc;
     510             :                         }
     511           0 :                         --destSize;
     512             :                     }
     513             :                 } else {                /* RTL run */
     514           0 :                     if((pBiDi->isInverse) &&
     515           0 :                        (/*run>0 &&*/ !(MASK_R_AL&DIRPROP_FLAG(dirProps[logicalStart+runLength-1])))) {
     516           0 :                         markFlag |= RLM_BEFORE;
     517             :                     }
     518           0 :                     if (markFlag & LRM_BEFORE) {
     519           0 :                         uc=LRM_CHAR;
     520             :                     }
     521           0 :                     else if (markFlag & RLM_BEFORE) {
     522           0 :                         uc=RLM_CHAR;
     523             :                     }
     524           0 :                     else  uc=0;
     525           0 :                     if(uc) {
     526           0 :                         if(destSize>0) {
     527           0 :                             *dest++=uc;
     528             :                         }
     529           0 :                         --destSize;
     530             :                     }
     531             : 
     532           0 :                     runLength=doWriteReverse(src, runLength,
     533             :                                              dest, destSize,
     534             :                                              options, pErrorCode);
     535           0 :                     if(dest!=NULL) {
     536           0 :                       dest+=runLength;
     537             :                     }
     538           0 :                     destSize-=runLength;
     539             : 
     540           0 :                     if((pBiDi->isInverse) &&
     541           0 :                        (/*run<runCount-1 &&*/ !(MASK_R_AL&DIRPROP_FLAG(dirProps[logicalStart])))) {
     542           0 :                         markFlag |= RLM_AFTER;
     543             :                     }
     544           0 :                     if (markFlag & LRM_AFTER) {
     545           0 :                         uc=LRM_CHAR;
     546             :                     }
     547           0 :                     else if (markFlag & RLM_AFTER) {
     548           0 :                         uc=RLM_CHAR;
     549             :                     }
     550           0 :                     else  uc=0;
     551           0 :                     if(uc) {
     552           0 :                         if(destSize>0) {
     553           0 :                             *dest++=uc;
     554             :                         }
     555           0 :                         --destSize;
     556             :                     }
     557             :                 }
     558             :             }
     559             :         }
     560             :     } else {
     561             :         /* reverse output */
     562           0 :         if(!(options&UBIDI_INSERT_LRM_FOR_NUMERIC)) {
     563             :             /* do not insert BiDi controls */
     564           0 :             for(run=runCount; --run>=0;) {
     565           0 :                 if(UBIDI_LTR==ubidi_getVisualRun(pBiDi, run, &logicalStart, &runLength)) {
     566           0 :                     runLength=doWriteReverse(text+logicalStart, runLength,
     567             :                                              dest, destSize,
     568           0 :                                              (uint16_t)(options&~UBIDI_DO_MIRRORING), pErrorCode);
     569             :                 } else {
     570           0 :                     runLength=doWriteForward(text+logicalStart, runLength,
     571             :                                              dest, destSize,
     572             :                                              options, pErrorCode);
     573             :                 }
     574           0 :                 if(dest!=NULL) {
     575           0 :                   dest+=runLength;
     576             :                 }
     577           0 :                 destSize-=runLength;
     578             :             }
     579             :         } else {
     580             :             /* insert BiDi controls for "inverse BiDi" */
     581           0 :             const DirProp *dirProps=pBiDi->dirProps;
     582             :             const UChar *src;
     583             :             UBiDiDirection dir;
     584             : 
     585           0 :             for(run=runCount; --run>=0;) {
     586             :                 /* reverse output */
     587           0 :                 dir=ubidi_getVisualRun(pBiDi, run, &logicalStart, &runLength);
     588           0 :                 src=text+logicalStart;
     589             : 
     590           0 :                 if(UBIDI_LTR==dir) {
     591           0 :                     if(/*run<runCount-1 &&*/ dirProps[logicalStart+runLength-1]!=L) {
     592           0 :                         if(destSize>0) {
     593           0 :                             *dest++=LRM_CHAR;
     594             :                         }
     595           0 :                         --destSize;
     596             :                     }
     597             : 
     598           0 :                     runLength=doWriteReverse(src, runLength,
     599             :                                              dest, destSize,
     600           0 :                                              (uint16_t)(options&~UBIDI_DO_MIRRORING), pErrorCode);
     601           0 :                     if(dest!=NULL) {
     602           0 :                       dest+=runLength;
     603             :                     }
     604           0 :                     destSize-=runLength;
     605             : 
     606           0 :                     if(/*run>0 &&*/ dirProps[logicalStart]!=L) {
     607           0 :                         if(destSize>0) {
     608           0 :                             *dest++=LRM_CHAR;
     609             :                         }
     610           0 :                         --destSize;
     611             :                     }
     612             :                 } else {
     613           0 :                     if(/*run<runCount-1 &&*/ !(MASK_R_AL&DIRPROP_FLAG(dirProps[logicalStart]))) {
     614           0 :                         if(destSize>0) {
     615           0 :                             *dest++=RLM_CHAR;
     616             :                         }
     617           0 :                         --destSize;
     618             :                     }
     619             : 
     620           0 :                     runLength=doWriteForward(src, runLength,
     621             :                                              dest, destSize,
     622             :                                              options, pErrorCode);
     623           0 :                     if(dest!=NULL) {
     624           0 :                       dest+=runLength;
     625             :                     }
     626           0 :                     destSize-=runLength;
     627             : 
     628           0 :                     if(/*run>0 &&*/ !(MASK_R_AL&DIRPROP_FLAG(dirProps[logicalStart+runLength-1]))) {
     629           0 :                         if(destSize>0) {
     630           0 :                             *dest++=RLM_CHAR;
     631             :                         }
     632           0 :                         --destSize;
     633             :                     }
     634             :                 }
     635             :             }
     636             :         }
     637             :     }
     638             : 
     639           0 :     return u_terminateUChars(saveDest, destCapacity, destCapacity-destSize, pErrorCode);
     640             : }

Generated by: LCOV version 1.13