Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/intl/icu/source/common/ubidiwrt.cpp
Line
Count
Source (jump to first uncovered line)
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
0
#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
doWriteForward(const UChar *src, int32_t srcLength,
60
               UChar *dest, int32_t destSize,
61
               uint16_t options,
62
0
               UErrorCode *pErrorCode) {
63
0
    /* optimize for several combinations of options */
64
0
    switch(options&(UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING)) {
65
0
    case 0: {
66
0
        /* 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
0
        }
72
0
        do {
73
0
            *dest++=*src++;
74
0
        } while(--length>0);
75
0
        return srcLength;
76
0
    }
77
0
    case UBIDI_DO_MIRRORING: {
78
0
        /* do mirroring */
79
0
        int32_t i=0, j=0;
80
0
        UChar32 c;
81
0
82
0
        if(destSize<srcLength) {
83
0
            *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
84
0
            return srcLength;
85
0
        }
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
0
    }
93
0
    case UBIDI_REMOVE_BIDI_CONTROLS: {
94
0
        /* copy the LTR run and remove any BiDi control characters */
95
0
        int32_t remaining=destSize;
96
0
        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
0
103
0
                    /* preflight the length */
104
0
                    while(--srcLength>0) {
105
0
                        c=*src++;
106
0
                        if(!IS_BIDI_CONTROL_CHAR(c)) {
107
0
                            --remaining;
108
0
                        }
109
0
                    }
110
0
                    return destSize-remaining;
111
0
                }
112
0
                *dest++=c;
113
0
            }
114
0
        } while(--srcLength>0);
115
0
        return destSize-remaining;
116
0
    }
117
0
    default: {
118
0
        /* remove BiDi control characters and do mirroring */
119
0
        int32_t remaining=destSize;
120
0
        int32_t i, j=0;
121
0
        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
0
132
0
                    /* preflight the length */
133
0
                    while(srcLength>0) {
134
0
                        c=*src++;
135
0
                        if(!IS_BIDI_CONTROL_CHAR(c)) {
136
0
                            --remaining;
137
0
                        }
138
0
                        --srcLength;
139
0
                    }
140
0
                    return destSize-remaining;
141
0
                }
142
0
                c=u_charMirror(c);
143
0
                U16_APPEND_UNSAFE(dest, j, c);
144
0
            }
145
0
        } while(srcLength>0);
146
0
        return j;
147
0
    }
148
0
    } /* end of switch */
149
0
}
150
151
static int32_t
152
doWriteReverse(const UChar *src, int32_t srcLength,
153
               UChar *dest, int32_t destSize,
154
               uint16_t options,
155
0
               UErrorCode *pErrorCode) {
156
0
    /*
157
0
     * RTL run -
158
0
     *
159
0
     * RTL runs need to be copied to the destination in reverse order
160
0
     * of code points, not code units, to keep Unicode characters intact.
161
0
     *
162
0
     * The general strategy for this is to read the source text
163
0
     * in backward order, collect all code units for a code point
164
0
     * (and optionally following combining characters, see below),
165
0
     * and copy all these code units in ascending order
166
0
     * to the destination for this run.
167
0
     *
168
0
     * Several options request whether combining characters
169
0
     * should be kept after their base characters,
170
0
     * whether BiDi control characters should be removed, and
171
0
     * whether characters should be replaced by their mirror-image
172
0
     * equivalent Unicode characters.
173
0
     */
174
0
    int32_t i, j;
175
0
    UChar32 c;
176
0
177
0
    /* optimize for several combinations of options */
178
0
    switch(options&(UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING|UBIDI_KEEP_BASE_COMBINING)) {
179
0
    case 0:
180
0
        /*
181
0
         * With none of the "complicated" options set, the destination
182
0
         * run will have the same length as the source run,
183
0
         * and there is no mirroring and no keeping combining characters
184
0
         * with their base characters.
185
0
         */
186
0
        if(destSize<srcLength) {
187
0
            *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
188
0
            return srcLength;
189
0
        }
190
0
        destSize=srcLength;
191
0
192
0
        /* preserve character integrity */
193
0
        do {
194
0
            /* i is always after the last code unit known to need to be kept in this segment */
195
0
            i=srcLength;
196
0
197
0
            /* collect code units for one base character */
198
0
            U16_BACK_1(src, 0, srcLength);
199
0
200
0
            /* 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
0
    case UBIDI_KEEP_BASE_COMBINING:
208
0
        /*
209
0
         * Here, too, the destination
210
0
         * run will have the same length as the source run,
211
0
         * and there is no mirroring.
212
0
         * We do need to keep combining characters with their base characters.
213
0
         */
214
0
        if(destSize<srcLength) {
215
0
            *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
216
0
            return srcLength;
217
0
        }
218
0
        destSize=srcLength;
219
0
220
0
        /* preserve character integrity */
221
0
        do {
222
0
            /* i is always after the last code unit known to need to be kept in this segment */
223
0
            i=srcLength;
224
0
225
0
            /* 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
0
230
0
            /* 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
0
    default:
238
0
        /*
239
0
         * With several "complicated" options set, this is the most
240
0
         * general and the slowest copying of an RTL run.
241
0
         * We will do mirroring, remove BiDi controls, and
242
0
         * keep combining characters with their base characters
243
0
         * as requested.
244
0
         */
245
0
        if(!(options&UBIDI_REMOVE_BIDI_CONTROLS)) {
246
0
            i=srcLength;
247
0
        } else {
248
0
            /* we need to find out the destination length of the run,
249
0
               which will not include the BiDi control characters */
250
0
            int32_t length=srcLength;
251
0
            UChar ch;
252
0
253
0
            i=0;
254
0
            do {
255
0
                ch=*src++;
256
0
                if(!IS_BIDI_CONTROL_CHAR(ch)) {
257
0
                    ++i;
258
0
                }
259
0
            } while(--length>0);
260
0
            src-=srcLength;
261
0
        }
262
0
263
0
        if(destSize<i) {
264
0
            *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
265
0
            return i;
266
0
        }
267
0
        destSize=i;
268
0
269
0
        /* preserve character integrity */
270
0
        do {
271
0
            /* i is always after the last code unit known to need to be kept in this segment */
272
0
            i=srcLength;
273
0
274
0
            /* collect code units for one base character */
275
0
            U16_PREV(src, 0, srcLength, c);
276
0
            if(options&UBIDI_KEEP_BASE_COMBINING) {
277
0
                /* 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
0
                }
281
0
            }
282
0
283
0
            if(options&UBIDI_REMOVE_BIDI_CONTROLS && IS_BIDI_CONTROL_CHAR(c)) {
284
0
                /* do not copy this BiDi control character */
285
0
                continue;
286
0
            }
287
0
288
0
            /* copy this "user character" */
289
0
            j=srcLength;
290
0
            if(options&UBIDI_DO_MIRRORING) {
291
0
                /* 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
0
            }
298
0
            while(j<i) {
299
0
                *dest++=src[j++];
300
0
            }
301
0
        } while(srcLength>0);
302
0
        break;
303
0
    } /* end of switch */
304
0
305
0
    return destSize;
306
0
}
307
308
U_CAPI int32_t U_EXPORT2
309
ubidi_writeReverse(const UChar *src, int32_t srcLength,
310
                   UChar *dest, int32_t destSize,
311
                   uint16_t options,
312
0
                   UErrorCode *pErrorCode) {
313
0
    int32_t destLength;
314
0
315
0
    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
316
0
        return 0;
317
0
    }
318
0
319
0
    /* more error checking */
320
0
    if( src==NULL || srcLength<-1 ||
321
0
        destSize<0 || (destSize>0 && dest==NULL))
322
0
    {
323
0
        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
324
0
        return 0;
325
0
    }
326
0
327
0
    /* 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
0
    {
332
0
        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
333
0
        return 0;
334
0
    }
335
0
336
0
    if(srcLength==-1) {
337
0
        srcLength=u_strlen(src);
338
0
    }
339
0
    if(srcLength>0) {
340
0
        destLength=doWriteReverse(src, srcLength, dest, destSize, options, pErrorCode);
341
0
    } else {
342
0
        /* nothing to do */
343
0
        destLength=0;
344
0
    }
345
0
346
0
    return u_terminateUChars(dest, destSize, destLength, pErrorCode);
347
0
}
348
349
U_CAPI int32_t U_EXPORT2
350
ubidi_writeReordered(UBiDi *pBiDi,
351
                     UChar *dest, int32_t destSize,
352
                     uint16_t options,
353
0
                     UErrorCode *pErrorCode) {
354
0
    const UChar *text;
355
0
    UChar *saveDest;
356
0
    int32_t length, destCapacity;
357
0
    int32_t run, runCount, logicalStart, runLength;
358
0
359
0
    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
360
0
        return 0;
361
0
    }
362
0
363
0
    /* 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
0
    {
368
0
        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
369
0
        return 0;
370
0
    }
371
0
372
0
    /* 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
0
    {
377
0
        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
378
0
        return 0;
379
0
    }
380
0
381
0
    if(length==0) {
382
0
        /* nothing to do */
383
0
        return u_terminateUChars(dest, destSize, 0, pErrorCode);
384
0
    }
385
0
386
0
    runCount=ubidi_countRuns(pBiDi, pErrorCode);
387
0
    if(U_FAILURE(*pErrorCode)) {
388
0
        return 0;
389
0
    }
390
0
391
0
    /* destSize shrinks, later destination length=destCapacity-destSize */
392
0
    saveDest=dest;
393
0
    destCapacity=destSize;
394
0
395
0
    /*
396
0
     * Option "insert marks" implies UBIDI_INSERT_LRM_FOR_NUMERIC if the
397
0
     * reordering mode (checked below) is appropriate.
398
0
     */
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
0
    }
403
0
    /*
404
0
     * Option "remove controls" implies UBIDI_REMOVE_BIDI_CONTROLS
405
0
     * and cancels UBIDI_INSERT_LRM_FOR_NUMERIC.
406
0
     */
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
0
    }
411
0
    /*
412
0
     * If we do not perform the "inverse BiDi" algorithm, then we
413
0
     * don't need to insert any LRMs, and don't need to test for it.
414
0
     */
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
0
    }
421
0
    /*
422
0
     * Iterate through all visual runs and copy the run text segments to
423
0
     * the destination, according to the options.
424
0
     *
425
0
     * The tests for where to insert LRMs ignore the fact that there may be
426
0
     * BN codes or non-BMP code points at the beginning and end of a run;
427
0
     * they may insert LRMs unnecessarily but the tests are faster this way
428
0
     * (this would have to be improved for UTF-8).
429
0
     *
430
0
     * Note that the only errors that are set by doWriteXY() are buffer overflow
431
0
     * errors. Ignore them until the end, and continue for preflighting.
432
0
     */
433
0
    if(!(options&UBIDI_OUTPUT_REVERSE)) {
434
0
        /* forward output */
435
0
        if(!(options&UBIDI_INSERT_LRM_FOR_NUMERIC)) {
436
0
            /* 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
0
                                             dest, destSize,
441
0
                                             (uint16_t)(options&~UBIDI_DO_MIRRORING), pErrorCode);
442
0
                } else {
443
0
                    runLength=doWriteReverse(text+logicalStart, runLength,
444
0
                                             dest, destSize,
445
0
                                             options, pErrorCode);
446
0
                }
447
0
                if(dest!=NULL) {
448
0
                  dest+=runLength;
449
0
                }
450
0
                destSize-=runLength;
451
0
            }
452
0
        } else {
453
0
            /* insert BiDi controls for "inverse BiDi" */
454
0
            const DirProp *dirProps=pBiDi->dirProps;
455
0
            const UChar *src;
456
0
            UChar uc;
457
0
            UBiDiDirection dir;
458
0
            int32_t markFlag;
459
0
460
0
            for(run=0; run<runCount; ++run) {
461
0
                dir=ubidi_getVisualRun(pBiDi, run, &logicalStart, &runLength);
462
0
                src=text+logicalStart;
463
0
                /* 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
0
                }
468
0
469
0
                if(UBIDI_LTR==dir) {
470
0
                    if((pBiDi->isInverse) &&
471
0
                       (/*run>0 &&*/ dirProps[logicalStart]!=L)) {
472
0
                        markFlag |= LRM_BEFORE;
473
0
                    }
474
0
                    if (markFlag & LRM_BEFORE) {
475
0
                        uc=LRM_CHAR;
476
0
                    }
477
0
                    else if (markFlag & RLM_BEFORE) {
478
0
                        uc=RLM_CHAR;
479
0
                    }
480
0
                    else  uc=0;
481
0
                    if(uc) {
482
0
                        if(destSize>0) {
483
0
                            *dest++=uc;
484
0
                        }
485
0
                        --destSize;
486
0
                    }
487
0
488
0
                    runLength=doWriteForward(src, runLength,
489
0
                                             dest, destSize,
490
0
                                             (uint16_t)(options&~UBIDI_DO_MIRRORING), pErrorCode);
491
0
                    if(dest!=NULL) {
492
0
                      dest+=runLength;
493
0
                    }
494
0
                    destSize-=runLength;
495
0
496
0
                    if((pBiDi->isInverse) &&
497
0
                       (/*run<runCount-1 &&*/ dirProps[logicalStart+runLength-1]!=L)) {
498
0
                        markFlag |= LRM_AFTER;
499
0
                    }
500
0
                    if (markFlag & LRM_AFTER) {
501
0
                        uc=LRM_CHAR;
502
0
                    }
503
0
                    else if (markFlag & RLM_AFTER) {
504
0
                        uc=RLM_CHAR;
505
0
                    }
506
0
                    else  uc=0;
507
0
                    if(uc) {
508
0
                        if(destSize>0) {
509
0
                            *dest++=uc;
510
0
                        }
511
0
                        --destSize;
512
0
                    }
513
0
                } 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
0
                    }
518
0
                    if (markFlag & LRM_BEFORE) {
519
0
                        uc=LRM_CHAR;
520
0
                    }
521
0
                    else if (markFlag & RLM_BEFORE) {
522
0
                        uc=RLM_CHAR;
523
0
                    }
524
0
                    else  uc=0;
525
0
                    if(uc) {
526
0
                        if(destSize>0) {
527
0
                            *dest++=uc;
528
0
                        }
529
0
                        --destSize;
530
0
                    }
531
0
532
0
                    runLength=doWriteReverse(src, runLength,
533
0
                                             dest, destSize,
534
0
                                             options, pErrorCode);
535
0
                    if(dest!=NULL) {
536
0
                      dest+=runLength;
537
0
                    }
538
0
                    destSize-=runLength;
539
0
540
0
                    if((pBiDi->isInverse) &&
541
0
                       (/*run<runCount-1 &&*/ !(MASK_R_AL&DIRPROP_FLAG(dirProps[logicalStart])))) {
542
0
                        markFlag |= RLM_AFTER;
543
0
                    }
544
0
                    if (markFlag & LRM_AFTER) {
545
0
                        uc=LRM_CHAR;
546
0
                    }
547
0
                    else if (markFlag & RLM_AFTER) {
548
0
                        uc=RLM_CHAR;
549
0
                    }
550
0
                    else  uc=0;
551
0
                    if(uc) {
552
0
                        if(destSize>0) {
553
0
                            *dest++=uc;
554
0
                        }
555
0
                        --destSize;
556
0
                    }
557
0
                }
558
0
            }
559
0
        }
560
0
    } else {
561
0
        /* reverse output */
562
0
        if(!(options&UBIDI_INSERT_LRM_FOR_NUMERIC)) {
563
0
            /* 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
0
                                             dest, destSize,
568
0
                                             (uint16_t)(options&~UBIDI_DO_MIRRORING), pErrorCode);
569
0
                } else {
570
0
                    runLength=doWriteForward(text+logicalStart, runLength,
571
0
                                             dest, destSize,
572
0
                                             options, pErrorCode);
573
0
                }
574
0
                if(dest!=NULL) {
575
0
                  dest+=runLength;
576
0
                }
577
0
                destSize-=runLength;
578
0
            }
579
0
        } else {
580
0
            /* insert BiDi controls for "inverse BiDi" */
581
0
            const DirProp *dirProps=pBiDi->dirProps;
582
0
            const UChar *src;
583
0
            UBiDiDirection dir;
584
0
585
0
            for(run=runCount; --run>=0;) {
586
0
                /* reverse output */
587
0
                dir=ubidi_getVisualRun(pBiDi, run, &logicalStart, &runLength);
588
0
                src=text+logicalStart;
589
0
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
0
                        }
595
0
                        --destSize;
596
0
                    }
597
0
598
0
                    runLength=doWriteReverse(src, runLength,
599
0
                                             dest, destSize,
600
0
                                             (uint16_t)(options&~UBIDI_DO_MIRRORING), pErrorCode);
601
0
                    if(dest!=NULL) {
602
0
                      dest+=runLength;
603
0
                    }
604
0
                    destSize-=runLength;
605
0
606
0
                    if(/*run>0 &&*/ dirProps[logicalStart]!=L) {
607
0
                        if(destSize>0) {
608
0
                            *dest++=LRM_CHAR;
609
0
                        }
610
0
                        --destSize;
611
0
                    }
612
0
                } 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
0
                        }
617
0
                        --destSize;
618
0
                    }
619
0
620
0
                    runLength=doWriteForward(src, runLength,
621
0
                                             dest, destSize,
622
0
                                             options, pErrorCode);
623
0
                    if(dest!=NULL) {
624
0
                      dest+=runLength;
625
0
                    }
626
0
                    destSize-=runLength;
627
0
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
0
                        }
632
0
                        --destSize;
633
0
                    }
634
0
                }
635
0
            }
636
0
        }
637
0
    }
638
0
639
0
    return u_terminateUChars(saveDest, destCapacity, destCapacity-destSize, pErrorCode);
640
0
}