OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / text / unicode / bidi / core.go
1 // Copyright 2015 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package bidi
6
7 import "log"
8
9 // This implementation is a port based on the reference implementation found at:
10 // http://www.unicode.org/Public/PROGRAMS/BidiReferenceJava/
11 //
12 // described in Unicode Bidirectional Algorithm (UAX #9).
13 //
14 // Input:
15 // There are two levels of input to the algorithm, since clients may prefer to
16 // supply some information from out-of-band sources rather than relying on the
17 // default behavior.
18 //
19 // - Bidi class array
20 // - Bidi class array, with externally supplied base line direction
21 //
22 // Output:
23 // Output is separated into several stages:
24 //
25 //  - levels array over entire paragraph
26 //  - reordering array over entire paragraph
27 //  - levels array over line
28 //  - reordering array over line
29 //
30 // Note that for conformance to the Unicode Bidirectional Algorithm,
31 // implementations are only required to generate correct reordering and
32 // character directionality (odd or even levels) over a line. Generating
33 // identical level arrays over a line is not required. Bidi explicit format
34 // codes (LRE, RLE, LRO, RLO, PDF) and BN can be assigned arbitrary levels and
35 // positions as long as the rest of the input is properly reordered.
36 //
37 // As the algorithm is defined to operate on a single paragraph at a time, this
38 // implementation is written to handle single paragraphs. Thus rule P1 is
39 // presumed by this implementation-- the data provided to the implementation is
40 // assumed to be a single paragraph, and either contains no 'B' codes, or a
41 // single 'B' code at the end of the input. 'B' is allowed as input to
42 // illustrate how the algorithm assigns it a level.
43 //
44 // Also note that rules L3 and L4 depend on the rendering engine that uses the
45 // result of the bidi algorithm. This implementation assumes that the rendering
46 // engine expects combining marks in visual order (e.g. to the left of their
47 // base character in RTL runs) and that it adjusts the glyphs used to render
48 // mirrored characters that are in RTL runs so that they render appropriately.
49
50 // level is the embedding level of a character. Even embedding levels indicate
51 // left-to-right order and odd levels indicate right-to-left order. The special
52 // level of -1 is reserved for undefined order.
53 type level int8
54
55 const implicitLevel level = -1
56
57 // in returns if x is equal to any of the values in set.
58 func (c Class) in(set ...Class) bool {
59         for _, s := range set {
60                 if c == s {
61                         return true
62                 }
63         }
64         return false
65 }
66
67 // A paragraph contains the state of a paragraph.
68 type paragraph struct {
69         initialTypes []Class
70
71         // Arrays of properties needed for paired bracket evaluation in N0
72         pairTypes  []bracketType // paired Bracket types for paragraph
73         pairValues []rune        // rune for opening bracket or pbOpen and pbClose; 0 for pbNone
74
75         embeddingLevel level // default: = implicitLevel;
76
77         // at the paragraph levels
78         resultTypes  []Class
79         resultLevels []level
80
81         // Index of matching PDI for isolate initiator characters. For other
82         // characters, the value of matchingPDI will be set to -1. For isolate
83         // initiators with no matching PDI, matchingPDI will be set to the length of
84         // the input string.
85         matchingPDI []int
86
87         // Index of matching isolate initiator for PDI characters. For other
88         // characters, and for PDIs with no matching isolate initiator, the value of
89         // matchingIsolateInitiator will be set to -1.
90         matchingIsolateInitiator []int
91 }
92
93 // newParagraph initializes a paragraph. The user needs to supply a few arrays
94 // corresponding to the preprocessed text input. The types correspond to the
95 // Unicode BiDi classes for each rune. pairTypes indicates the bracket type for
96 // each rune. pairValues provides a unique bracket class identifier for each
97 // rune (suggested is the rune of the open bracket for opening and matching
98 // close brackets, after normalization). The embedding levels are optional, but
99 // may be supplied to encode embedding levels of styled text.
100 //
101 // TODO: return an error.
102 func newParagraph(types []Class, pairTypes []bracketType, pairValues []rune, levels level) *paragraph {
103         validateTypes(types)
104         validatePbTypes(pairTypes)
105         validatePbValues(pairValues, pairTypes)
106         validateParagraphEmbeddingLevel(levels)
107
108         p := &paragraph{
109                 initialTypes:   append([]Class(nil), types...),
110                 embeddingLevel: levels,
111
112                 pairTypes:  pairTypes,
113                 pairValues: pairValues,
114
115                 resultTypes: append([]Class(nil), types...),
116         }
117         p.run()
118         return p
119 }
120
121 func (p *paragraph) Len() int { return len(p.initialTypes) }
122
123 // The algorithm. Does not include line-based processing (Rules L1, L2).
124 // These are applied later in the line-based phase of the algorithm.
125 func (p *paragraph) run() {
126         p.determineMatchingIsolates()
127
128         // 1) determining the paragraph level
129         // Rule P1 is the requirement for entering this algorithm.
130         // Rules P2, P3.
131         // If no externally supplied paragraph embedding level, use default.
132         if p.embeddingLevel == implicitLevel {
133                 p.embeddingLevel = p.determineParagraphEmbeddingLevel(0, p.Len())
134         }
135
136         // Initialize result levels to paragraph embedding level.
137         p.resultLevels = make([]level, p.Len())
138         setLevels(p.resultLevels, p.embeddingLevel)
139
140         // 2) Explicit levels and directions
141         // Rules X1-X8.
142         p.determineExplicitEmbeddingLevels()
143
144         // Rule X9.
145         // We do not remove the embeddings, the overrides, the PDFs, and the BNs
146         // from the string explicitly. But they are not copied into isolating run
147         // sequences when they are created, so they are removed for all
148         // practical purposes.
149
150         // Rule X10.
151         // Run remainder of algorithm one isolating run sequence at a time
152         for _, seq := range p.determineIsolatingRunSequences() {
153                 // 3) resolving weak types
154                 // Rules W1-W7.
155                 seq.resolveWeakTypes()
156
157                 // 4a) resolving paired brackets
158                 // Rule N0
159                 resolvePairedBrackets(seq)
160
161                 // 4b) resolving neutral types
162                 // Rules N1-N3.
163                 seq.resolveNeutralTypes()
164
165                 // 5) resolving implicit embedding levels
166                 // Rules I1, I2.
167                 seq.resolveImplicitLevels()
168
169                 // Apply the computed levels and types
170                 seq.applyLevelsAndTypes()
171         }
172
173         // Assign appropriate levels to 'hide' LREs, RLEs, LROs, RLOs, PDFs, and
174         // BNs. This is for convenience, so the resulting level array will have
175         // a value for every character.
176         p.assignLevelsToCharactersRemovedByX9()
177 }
178
179 // determineMatchingIsolates determines the matching PDI for each isolate
180 // initiator and vice versa.
181 //
182 // Definition BD9.
183 //
184 // At the end of this function:
185 //
186 //  - The member variable matchingPDI is set to point to the index of the
187 //    matching PDI character for each isolate initiator character. If there is
188 //    no matching PDI, it is set to the length of the input text. For other
189 //    characters, it is set to -1.
190 //  - The member variable matchingIsolateInitiator is set to point to the
191 //    index of the matching isolate initiator character for each PDI character.
192 //    If there is no matching isolate initiator, or the character is not a PDI,
193 //    it is set to -1.
194 func (p *paragraph) determineMatchingIsolates() {
195         p.matchingPDI = make([]int, p.Len())
196         p.matchingIsolateInitiator = make([]int, p.Len())
197
198         for i := range p.matchingIsolateInitiator {
199                 p.matchingIsolateInitiator[i] = -1
200         }
201
202         for i := range p.matchingPDI {
203                 p.matchingPDI[i] = -1
204
205                 if t := p.resultTypes[i]; t.in(LRI, RLI, FSI) {
206                         depthCounter := 1
207                         for j := i + 1; j < p.Len(); j++ {
208                                 if u := p.resultTypes[j]; u.in(LRI, RLI, FSI) {
209                                         depthCounter++
210                                 } else if u == PDI {
211                                         if depthCounter--; depthCounter == 0 {
212                                                 p.matchingPDI[i] = j
213                                                 p.matchingIsolateInitiator[j] = i
214                                                 break
215                                         }
216                                 }
217                         }
218                         if p.matchingPDI[i] == -1 {
219                                 p.matchingPDI[i] = p.Len()
220                         }
221                 }
222         }
223 }
224
225 // determineParagraphEmbeddingLevel reports the resolved paragraph direction of
226 // the substring limited by the given range [start, end).
227 //
228 // Determines the paragraph level based on rules P2, P3. This is also used
229 // in rule X5c to find if an FSI should resolve to LRI or RLI.
230 func (p *paragraph) determineParagraphEmbeddingLevel(start, end int) level {
231         var strongType Class = unknownClass
232
233         // Rule P2.
234         for i := start; i < end; i++ {
235                 if t := p.resultTypes[i]; t.in(L, AL, R) {
236                         strongType = t
237                         break
238                 } else if t.in(FSI, LRI, RLI) {
239                         i = p.matchingPDI[i] // skip over to the matching PDI
240                         if i > end {
241                                 log.Panic("assert (i <= end)")
242                         }
243                 }
244         }
245         // Rule P3.
246         switch strongType {
247         case unknownClass: // none found
248                 // default embedding level when no strong types found is 0.
249                 return 0
250         case L:
251                 return 0
252         default: // AL, R
253                 return 1
254         }
255 }
256
257 const maxDepth = 125
258
259 // This stack will store the embedding levels and override and isolated
260 // statuses
261 type directionalStatusStack struct {
262         stackCounter        int
263         embeddingLevelStack [maxDepth + 1]level
264         overrideStatusStack [maxDepth + 1]Class
265         isolateStatusStack  [maxDepth + 1]bool
266 }
267
268 func (s *directionalStatusStack) empty()     { s.stackCounter = 0 }
269 func (s *directionalStatusStack) pop()       { s.stackCounter-- }
270 func (s *directionalStatusStack) depth() int { return s.stackCounter }
271
272 func (s *directionalStatusStack) push(level level, overrideStatus Class, isolateStatus bool) {
273         s.embeddingLevelStack[s.stackCounter] = level
274         s.overrideStatusStack[s.stackCounter] = overrideStatus
275         s.isolateStatusStack[s.stackCounter] = isolateStatus
276         s.stackCounter++
277 }
278
279 func (s *directionalStatusStack) lastEmbeddingLevel() level {
280         return s.embeddingLevelStack[s.stackCounter-1]
281 }
282
283 func (s *directionalStatusStack) lastDirectionalOverrideStatus() Class {
284         return s.overrideStatusStack[s.stackCounter-1]
285 }
286
287 func (s *directionalStatusStack) lastDirectionalIsolateStatus() bool {
288         return s.isolateStatusStack[s.stackCounter-1]
289 }
290
291 // Determine explicit levels using rules X1 - X8
292 func (p *paragraph) determineExplicitEmbeddingLevels() {
293         var stack directionalStatusStack
294         var overflowIsolateCount, overflowEmbeddingCount, validIsolateCount int
295
296         // Rule X1.
297         stack.push(p.embeddingLevel, ON, false)
298
299         for i, t := range p.resultTypes {
300                 // Rules X2, X3, X4, X5, X5a, X5b, X5c
301                 switch t {
302                 case RLE, LRE, RLO, LRO, RLI, LRI, FSI:
303                         isIsolate := t.in(RLI, LRI, FSI)
304                         isRTL := t.in(RLE, RLO, RLI)
305
306                         // override if this is an FSI that resolves to RLI
307                         if t == FSI {
308                                 isRTL = (p.determineParagraphEmbeddingLevel(i+1, p.matchingPDI[i]) == 1)
309                         }
310                         if isIsolate {
311                                 p.resultLevels[i] = stack.lastEmbeddingLevel()
312                                 if stack.lastDirectionalOverrideStatus() != ON {
313                                         p.resultTypes[i] = stack.lastDirectionalOverrideStatus()
314                                 }
315                         }
316
317                         var newLevel level
318                         if isRTL {
319                                 // least greater odd
320                                 newLevel = (stack.lastEmbeddingLevel() + 1) | 1
321                         } else {
322                                 // least greater even
323                                 newLevel = (stack.lastEmbeddingLevel() + 2) &^ 1
324                         }
325
326                         if newLevel <= maxDepth && overflowIsolateCount == 0 && overflowEmbeddingCount == 0 {
327                                 if isIsolate {
328                                         validIsolateCount++
329                                 }
330                                 // Push new embedding level, override status, and isolated
331                                 // status.
332                                 // No check for valid stack counter, since the level check
333                                 // suffices.
334                                 switch t {
335                                 case LRO:
336                                         stack.push(newLevel, L, isIsolate)
337                                 case RLO:
338                                         stack.push(newLevel, R, isIsolate)
339                                 default:
340                                         stack.push(newLevel, ON, isIsolate)
341                                 }
342                                 // Not really part of the spec
343                                 if !isIsolate {
344                                         p.resultLevels[i] = newLevel
345                                 }
346                         } else {
347                                 // This is an invalid explicit formatting character,
348                                 // so apply the "Otherwise" part of rules X2-X5b.
349                                 if isIsolate {
350                                         overflowIsolateCount++
351                                 } else { // !isIsolate
352                                         if overflowIsolateCount == 0 {
353                                                 overflowEmbeddingCount++
354                                         }
355                                 }
356                         }
357
358                 // Rule X6a
359                 case PDI:
360                         if overflowIsolateCount > 0 {
361                                 overflowIsolateCount--
362                         } else if validIsolateCount == 0 {
363                                 // do nothing
364                         } else {
365                                 overflowEmbeddingCount = 0
366                                 for !stack.lastDirectionalIsolateStatus() {
367                                         stack.pop()
368                                 }
369                                 stack.pop()
370                                 validIsolateCount--
371                         }
372                         p.resultLevels[i] = stack.lastEmbeddingLevel()
373
374                 // Rule X7
375                 case PDF:
376                         // Not really part of the spec
377                         p.resultLevels[i] = stack.lastEmbeddingLevel()
378
379                         if overflowIsolateCount > 0 {
380                                 // do nothing
381                         } else if overflowEmbeddingCount > 0 {
382                                 overflowEmbeddingCount--
383                         } else if !stack.lastDirectionalIsolateStatus() && stack.depth() >= 2 {
384                                 stack.pop()
385                         }
386
387                 case B: // paragraph separator.
388                         // Rule X8.
389
390                         // These values are reset for clarity, in this implementation B
391                         // can only occur as the last code in the array.
392                         stack.empty()
393                         overflowIsolateCount = 0
394                         overflowEmbeddingCount = 0
395                         validIsolateCount = 0
396                         p.resultLevels[i] = p.embeddingLevel
397
398                 default:
399                         p.resultLevels[i] = stack.lastEmbeddingLevel()
400                         if stack.lastDirectionalOverrideStatus() != ON {
401                                 p.resultTypes[i] = stack.lastDirectionalOverrideStatus()
402                         }
403                 }
404         }
405 }
406
407 type isolatingRunSequence struct {
408         p *paragraph
409
410         indexes []int // indexes to the original string
411
412         types          []Class // type of each character using the index
413         resolvedLevels []level // resolved levels after application of rules
414         level          level
415         sos, eos       Class
416 }
417
418 func (i *isolatingRunSequence) Len() int { return len(i.indexes) }
419
420 func maxLevel(a, b level) level {
421         if a > b {
422                 return a
423         }
424         return b
425 }
426
427 // Rule X10, second bullet: Determine the start-of-sequence (sos) and end-of-sequence (eos) types,
428 //                       either L or R, for each isolating run sequence.
429 func (p *paragraph) isolatingRunSequence(indexes []int) *isolatingRunSequence {
430         length := len(indexes)
431         types := make([]Class, length)
432         for i, x := range indexes {
433                 types[i] = p.resultTypes[x]
434         }
435
436         // assign level, sos and eos
437         prevChar := indexes[0] - 1
438         for prevChar >= 0 && isRemovedByX9(p.initialTypes[prevChar]) {
439                 prevChar--
440         }
441         prevLevel := p.embeddingLevel
442         if prevChar >= 0 {
443                 prevLevel = p.resultLevels[prevChar]
444         }
445
446         var succLevel level
447         lastType := types[length-1]
448         if lastType.in(LRI, RLI, FSI) {
449                 succLevel = p.embeddingLevel
450         } else {
451                 // the first character after the end of run sequence
452                 limit := indexes[length-1] + 1
453                 for ; limit < p.Len() && isRemovedByX9(p.initialTypes[limit]); limit++ {
454
455                 }
456                 succLevel = p.embeddingLevel
457                 if limit < p.Len() {
458                         succLevel = p.resultLevels[limit]
459                 }
460         }
461         level := p.resultLevels[indexes[0]]
462         return &isolatingRunSequence{
463                 p:       p,
464                 indexes: indexes,
465                 types:   types,
466                 level:   level,
467                 sos:     typeForLevel(maxLevel(prevLevel, level)),
468                 eos:     typeForLevel(maxLevel(succLevel, level)),
469         }
470 }
471
472 // Resolving weak types Rules W1-W7.
473 //
474 // Note that some weak types (EN, AN) remain after this processing is
475 // complete.
476 func (s *isolatingRunSequence) resolveWeakTypes() {
477
478         // on entry, only these types remain
479         s.assertOnly(L, R, AL, EN, ES, ET, AN, CS, B, S, WS, ON, NSM, LRI, RLI, FSI, PDI)
480
481         // Rule W1.
482         // Changes all NSMs.
483         preceedingCharacterType := s.sos
484         for i, t := range s.types {
485                 if t == NSM {
486                         s.types[i] = preceedingCharacterType
487                 } else {
488                         if t.in(LRI, RLI, FSI, PDI) {
489                                 preceedingCharacterType = ON
490                         }
491                         preceedingCharacterType = t
492                 }
493         }
494
495         // Rule W2.
496         // EN does not change at the start of the run, because sos != AL.
497         for i, t := range s.types {
498                 if t == EN {
499                         for j := i - 1; j >= 0; j-- {
500                                 if t := s.types[j]; t.in(L, R, AL) {
501                                         if t == AL {
502                                                 s.types[i] = AN
503                                         }
504                                         break
505                                 }
506                         }
507                 }
508         }
509
510         // Rule W3.
511         for i, t := range s.types {
512                 if t == AL {
513                         s.types[i] = R
514                 }
515         }
516
517         // Rule W4.
518         // Since there must be values on both sides for this rule to have an
519         // effect, the scan skips the first and last value.
520         //
521         // Although the scan proceeds left to right, and changes the type
522         // values in a way that would appear to affect the computations
523         // later in the scan, there is actually no problem. A change in the
524         // current value can only affect the value to its immediate right,
525         // and only affect it if it is ES or CS. But the current value can
526         // only change if the value to its right is not ES or CS. Thus
527         // either the current value will not change, or its change will have
528         // no effect on the remainder of the analysis.
529
530         for i := 1; i < s.Len()-1; i++ {
531                 t := s.types[i]
532                 if t == ES || t == CS {
533                         prevSepType := s.types[i-1]
534                         succSepType := s.types[i+1]
535                         if prevSepType == EN && succSepType == EN {
536                                 s.types[i] = EN
537                         } else if s.types[i] == CS && prevSepType == AN && succSepType == AN {
538                                 s.types[i] = AN
539                         }
540                 }
541         }
542
543         // Rule W5.
544         for i, t := range s.types {
545                 if t == ET {
546                         // locate end of sequence
547                         runStart := i
548                         runEnd := s.findRunLimit(runStart, ET)
549
550                         // check values at ends of sequence
551                         t := s.sos
552                         if runStart > 0 {
553                                 t = s.types[runStart-1]
554                         }
555                         if t != EN {
556                                 t = s.eos
557                                 if runEnd < len(s.types) {
558                                         t = s.types[runEnd]
559                                 }
560                         }
561                         if t == EN {
562                                 setTypes(s.types[runStart:runEnd], EN)
563                         }
564                         // continue at end of sequence
565                         i = runEnd
566                 }
567         }
568
569         // Rule W6.
570         for i, t := range s.types {
571                 if t.in(ES, ET, CS) {
572                         s.types[i] = ON
573                 }
574         }
575
576         // Rule W7.
577         for i, t := range s.types {
578                 if t == EN {
579                         // set default if we reach start of run
580                         prevStrongType := s.sos
581                         for j := i - 1; j >= 0; j-- {
582                                 t = s.types[j]
583                                 if t == L || t == R { // AL's have been changed to R
584                                         prevStrongType = t
585                                         break
586                                 }
587                         }
588                         if prevStrongType == L {
589                                 s.types[i] = L
590                         }
591                 }
592         }
593 }
594
595 // 6) resolving neutral types Rules N1-N2.
596 func (s *isolatingRunSequence) resolveNeutralTypes() {
597
598         // on entry, only these types can be in resultTypes
599         s.assertOnly(L, R, EN, AN, B, S, WS, ON, RLI, LRI, FSI, PDI)
600
601         for i, t := range s.types {
602                 switch t {
603                 case WS, ON, B, S, RLI, LRI, FSI, PDI:
604                         // find bounds of run of neutrals
605                         runStart := i
606                         runEnd := s.findRunLimit(runStart, B, S, WS, ON, RLI, LRI, FSI, PDI)
607
608                         // determine effective types at ends of run
609                         var leadType, trailType Class
610
611                         // Note that the character found can only be L, R, AN, or
612                         // EN.
613                         if runStart == 0 {
614                                 leadType = s.sos
615                         } else {
616                                 leadType = s.types[runStart-1]
617                                 if leadType.in(AN, EN) {
618                                         leadType = R
619                                 }
620                         }
621                         if runEnd == len(s.types) {
622                                 trailType = s.eos
623                         } else {
624                                 trailType = s.types[runEnd]
625                                 if trailType.in(AN, EN) {
626                                         trailType = R
627                                 }
628                         }
629
630                         var resolvedType Class
631                         if leadType == trailType {
632                                 // Rule N1.
633                                 resolvedType = leadType
634                         } else {
635                                 // Rule N2.
636                                 // Notice the embedding level of the run is used, not
637                                 // the paragraph embedding level.
638                                 resolvedType = typeForLevel(s.level)
639                         }
640
641                         setTypes(s.types[runStart:runEnd], resolvedType)
642
643                         // skip over run of (former) neutrals
644                         i = runEnd
645                 }
646         }
647 }
648
649 func setLevels(levels []level, newLevel level) {
650         for i := range levels {
651                 levels[i] = newLevel
652         }
653 }
654
655 func setTypes(types []Class, newType Class) {
656         for i := range types {
657                 types[i] = newType
658         }
659 }
660
661 // 7) resolving implicit embedding levels Rules I1, I2.
662 func (s *isolatingRunSequence) resolveImplicitLevels() {
663
664         // on entry, only these types can be in resultTypes
665         s.assertOnly(L, R, EN, AN)
666
667         s.resolvedLevels = make([]level, len(s.types))
668         setLevels(s.resolvedLevels, s.level)
669
670         if (s.level & 1) == 0 { // even level
671                 for i, t := range s.types {
672                         // Rule I1.
673                         if t == L {
674                                 // no change
675                         } else if t == R {
676                                 s.resolvedLevels[i] += 1
677                         } else { // t == AN || t == EN
678                                 s.resolvedLevels[i] += 2
679                         }
680                 }
681         } else { // odd level
682                 for i, t := range s.types {
683                         // Rule I2.
684                         if t == R {
685                                 // no change
686                         } else { // t == L || t == AN || t == EN
687                                 s.resolvedLevels[i] += 1
688                         }
689                 }
690         }
691 }
692
693 // Applies the levels and types resolved in rules W1-I2 to the
694 // resultLevels array.
695 func (s *isolatingRunSequence) applyLevelsAndTypes() {
696         for i, x := range s.indexes {
697                 s.p.resultTypes[x] = s.types[i]
698                 s.p.resultLevels[x] = s.resolvedLevels[i]
699         }
700 }
701
702 // Return the limit of the run consisting only of the types in validSet
703 // starting at index. This checks the value at index, and will return
704 // index if that value is not in validSet.
705 func (s *isolatingRunSequence) findRunLimit(index int, validSet ...Class) int {
706 loop:
707         for ; index < len(s.types); index++ {
708                 t := s.types[index]
709                 for _, valid := range validSet {
710                         if t == valid {
711                                 continue loop
712                         }
713                 }
714                 return index // didn't find a match in validSet
715         }
716         return len(s.types)
717 }
718
719 // Algorithm validation. Assert that all values in types are in the
720 // provided set.
721 func (s *isolatingRunSequence) assertOnly(codes ...Class) {
722 loop:
723         for i, t := range s.types {
724                 for _, c := range codes {
725                         if t == c {
726                                 continue loop
727                         }
728                 }
729                 log.Panicf("invalid bidi code %v present in assertOnly at position %d", t, s.indexes[i])
730         }
731 }
732
733 // determineLevelRuns returns an array of level runs. Each level run is
734 // described as an array of indexes into the input string.
735 //
736 // Determines the level runs. Rule X9 will be applied in determining the
737 // runs, in the way that makes sure the characters that are supposed to be
738 // removed are not included in the runs.
739 func (p *paragraph) determineLevelRuns() [][]int {
740         run := []int{}
741         allRuns := [][]int{}
742         currentLevel := implicitLevel
743
744         for i := range p.initialTypes {
745                 if !isRemovedByX9(p.initialTypes[i]) {
746                         if p.resultLevels[i] != currentLevel {
747                                 // we just encountered a new run; wrap up last run
748                                 if currentLevel >= 0 { // only wrap it up if there was a run
749                                         allRuns = append(allRuns, run)
750                                         run = nil
751                                 }
752                                 // Start new run
753                                 currentLevel = p.resultLevels[i]
754                         }
755                         run = append(run, i)
756                 }
757         }
758         // Wrap up the final run, if any
759         if len(run) > 0 {
760                 allRuns = append(allRuns, run)
761         }
762         return allRuns
763 }
764
765 // Definition BD13. Determine isolating run sequences.
766 func (p *paragraph) determineIsolatingRunSequences() []*isolatingRunSequence {
767         levelRuns := p.determineLevelRuns()
768
769         // Compute the run that each character belongs to
770         runForCharacter := make([]int, p.Len())
771         for i, run := range levelRuns {
772                 for _, index := range run {
773                         runForCharacter[index] = i
774                 }
775         }
776
777         sequences := []*isolatingRunSequence{}
778
779         var currentRunSequence []int
780
781         for _, run := range levelRuns {
782                 first := run[0]
783                 if p.initialTypes[first] != PDI || p.matchingIsolateInitiator[first] == -1 {
784                         currentRunSequence = nil
785                         // int run = i;
786                         for {
787                                 // Copy this level run into currentRunSequence
788                                 currentRunSequence = append(currentRunSequence, run...)
789
790                                 last := currentRunSequence[len(currentRunSequence)-1]
791                                 lastT := p.initialTypes[last]
792                                 if lastT.in(LRI, RLI, FSI) && p.matchingPDI[last] != p.Len() {
793                                         run = levelRuns[runForCharacter[p.matchingPDI[last]]]
794                                 } else {
795                                         break
796                                 }
797                         }
798                         sequences = append(sequences, p.isolatingRunSequence(currentRunSequence))
799                 }
800         }
801         return sequences
802 }
803
804 // Assign level information to characters removed by rule X9. This is for
805 // ease of relating the level information to the original input data. Note
806 // that the levels assigned to these codes are arbitrary, they're chosen so
807 // as to avoid breaking level runs.
808 func (p *paragraph) assignLevelsToCharactersRemovedByX9() {
809         for i, t := range p.initialTypes {
810                 if t.in(LRE, RLE, LRO, RLO, PDF, BN) {
811                         p.resultTypes[i] = t
812                         p.resultLevels[i] = -1
813                 }
814         }
815         // now propagate forward the levels information (could have
816         // propagated backward, the main thing is not to introduce a level
817         // break where one doesn't already exist).
818
819         if p.resultLevels[0] == -1 {
820                 p.resultLevels[0] = p.embeddingLevel
821         }
822         for i := 1; i < len(p.initialTypes); i++ {
823                 if p.resultLevels[i] == -1 {
824                         p.resultLevels[i] = p.resultLevels[i-1]
825                 }
826         }
827         // Embedding information is for informational purposes only so need not be
828         // adjusted.
829 }
830
831 //
832 // Output
833 //
834
835 // getLevels computes levels array breaking lines at offsets in linebreaks.
836 // Rule L1.
837 //
838 // The linebreaks array must include at least one value. The values must be
839 // in strictly increasing order (no duplicates) between 1 and the length of
840 // the text, inclusive. The last value must be the length of the text.
841 func (p *paragraph) getLevels(linebreaks []int) []level {
842         // Note that since the previous processing has removed all
843         // P, S, and WS values from resultTypes, the values referred to
844         // in these rules are the initial types, before any processing
845         // has been applied (including processing of overrides).
846         //
847         // This example implementation has reinserted explicit format codes
848         // and BN, in order that the levels array correspond to the
849         // initial text. Their final placement is not normative.
850         // These codes are treated like WS in this implementation,
851         // so they don't interrupt sequences of WS.
852
853         validateLineBreaks(linebreaks, p.Len())
854
855         result := append([]level(nil), p.resultLevels...)
856
857         // don't worry about linebreaks since if there is a break within
858         // a series of WS values preceding S, the linebreak itself
859         // causes the reset.
860         for i, t := range p.initialTypes {
861                 if t.in(B, S) {
862                         // Rule L1, clauses one and two.
863                         result[i] = p.embeddingLevel
864
865                         // Rule L1, clause three.
866                         for j := i - 1; j >= 0; j-- {
867                                 if isWhitespace(p.initialTypes[j]) { // including format codes
868                                         result[j] = p.embeddingLevel
869                                 } else {
870                                         break
871                                 }
872                         }
873                 }
874         }
875
876         // Rule L1, clause four.
877         start := 0
878         for _, limit := range linebreaks {
879                 for j := limit - 1; j >= start; j-- {
880                         if isWhitespace(p.initialTypes[j]) { // including format codes
881                                 result[j] = p.embeddingLevel
882                         } else {
883                                 break
884                         }
885                 }
886                 start = limit
887         }
888
889         return result
890 }
891
892 // getReordering returns the reordering of lines from a visual index to a
893 // logical index for line breaks at the given offsets.
894 //
895 // Lines are concatenated from left to right. So for example, the fifth
896 // character from the left on the third line is
897 //
898 //              getReordering(linebreaks)[linebreaks[1] + 4]
899 //
900 // (linebreaks[1] is the position after the last character of the second
901 // line, which is also the index of the first character on the third line,
902 // and adding four gets the fifth character from the left).
903 //
904 // The linebreaks array must include at least one value. The values must be
905 // in strictly increasing order (no duplicates) between 1 and the length of
906 // the text, inclusive. The last value must be the length of the text.
907 func (p *paragraph) getReordering(linebreaks []int) []int {
908         validateLineBreaks(linebreaks, p.Len())
909
910         return computeMultilineReordering(p.getLevels(linebreaks), linebreaks)
911 }
912
913 // Return multiline reordering array for a given level array. Reordering
914 // does not occur across a line break.
915 func computeMultilineReordering(levels []level, linebreaks []int) []int {
916         result := make([]int, len(levels))
917
918         start := 0
919         for _, limit := range linebreaks {
920                 tempLevels := make([]level, limit-start)
921                 copy(tempLevels, levels[start:])
922
923                 for j, order := range computeReordering(tempLevels) {
924                         result[start+j] = order + start
925                 }
926                 start = limit
927         }
928         return result
929 }
930
931 // Return reordering array for a given level array. This reorders a single
932 // line. The reordering is a visual to logical map. For example, the
933 // leftmost char is string.charAt(order[0]). Rule L2.
934 func computeReordering(levels []level) []int {
935         result := make([]int, len(levels))
936         // initialize order
937         for i := range result {
938                 result[i] = i
939         }
940
941         // locate highest level found on line.
942         // Note the rules say text, but no reordering across line bounds is
943         // performed, so this is sufficient.
944         highestLevel := level(0)
945         lowestOddLevel := level(maxDepth + 2)
946         for _, level := range levels {
947                 if level > highestLevel {
948                         highestLevel = level
949                 }
950                 if level&1 != 0 && level < lowestOddLevel {
951                         lowestOddLevel = level
952                 }
953         }
954
955         for level := highestLevel; level >= lowestOddLevel; level-- {
956                 for i := 0; i < len(levels); i++ {
957                         if levels[i] >= level {
958                                 // find range of text at or above this level
959                                 start := i
960                                 limit := i + 1
961                                 for limit < len(levels) && levels[limit] >= level {
962                                         limit++
963                                 }
964
965                                 for j, k := start, limit-1; j < k; j, k = j+1, k-1 {
966                                         result[j], result[k] = result[k], result[j]
967                                 }
968                                 // skip to end of level run
969                                 i = limit
970                         }
971                 }
972         }
973
974         return result
975 }
976
977 // isWhitespace reports whether the type is considered a whitespace type for the
978 // line break rules.
979 func isWhitespace(c Class) bool {
980         switch c {
981         case LRE, RLE, LRO, RLO, PDF, LRI, RLI, FSI, PDI, BN, WS:
982                 return true
983         }
984         return false
985 }
986
987 // isRemovedByX9 reports whether the type is one of the types removed in X9.
988 func isRemovedByX9(c Class) bool {
989         switch c {
990         case LRE, RLE, LRO, RLO, PDF, BN:
991                 return true
992         }
993         return false
994 }
995
996 // typeForLevel reports the strong type (L or R) corresponding to the level.
997 func typeForLevel(level level) Class {
998         if (level & 0x1) == 0 {
999                 return L
1000         }
1001         return R
1002 }
1003
1004 // TODO: change validation to not panic
1005
1006 func validateTypes(types []Class) {
1007         if len(types) == 0 {
1008                 log.Panic("types is null")
1009         }
1010         for i, t := range types[:len(types)-1] {
1011                 if t == B {
1012                         log.Panicf("B type before end of paragraph at index: %d", i)
1013                 }
1014         }
1015 }
1016
1017 func validateParagraphEmbeddingLevel(embeddingLevel level) {
1018         if embeddingLevel != implicitLevel &&
1019                 embeddingLevel != 0 &&
1020                 embeddingLevel != 1 {
1021                 log.Panicf("illegal paragraph embedding level: %d", embeddingLevel)
1022         }
1023 }
1024
1025 func validateLineBreaks(linebreaks []int, textLength int) {
1026         prev := 0
1027         for i, next := range linebreaks {
1028                 if next <= prev {
1029                         log.Panicf("bad linebreak: %d at index: %d", next, i)
1030                 }
1031                 prev = next
1032         }
1033         if prev != textLength {
1034                 log.Panicf("last linebreak was %d, want %d", prev, textLength)
1035         }
1036 }
1037
1038 func validatePbTypes(pairTypes []bracketType) {
1039         if len(pairTypes) == 0 {
1040                 log.Panic("pairTypes is null")
1041         }
1042         for i, pt := range pairTypes {
1043                 switch pt {
1044                 case bpNone, bpOpen, bpClose:
1045                 default:
1046                         log.Panicf("illegal pairType value at %d: %v", i, pairTypes[i])
1047                 }
1048         }
1049 }
1050
1051 func validatePbValues(pairValues []rune, pairTypes []bracketType) {
1052         if pairValues == nil {
1053                 log.Panic("pairValues is null")
1054         }
1055         if len(pairTypes) != len(pairValues) {
1056                 log.Panic("pairTypes is different length from pairValues")
1057         }
1058 }