Source file src/pkg/vendor/golang.org/x/text/unicode/bidi/core.go
1
2
3
4
5 package bidi
6
7 import "log"
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 type level int8
54
55 const implicitLevel level = -1
56
57
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
68 type paragraph struct {
69 initialTypes []Class
70
71
72 pairTypes []bracketType
73 pairValues []rune
74
75 embeddingLevel level
76
77
78 resultTypes []Class
79 resultLevels []level
80
81
82
83
84
85 matchingPDI []int
86
87
88
89
90 matchingIsolateInitiator []int
91 }
92
93
94
95
96
97
98
99
100
101
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 := ¶graph{
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
124
125 func (p *paragraph) run() {
126 p.determineMatchingIsolates()
127
128
129
130
131
132 if p.embeddingLevel == implicitLevel {
133 p.embeddingLevel = p.determineParagraphEmbeddingLevel(0, p.Len())
134 }
135
136
137 p.resultLevels = make([]level, p.Len())
138 setLevels(p.resultLevels, p.embeddingLevel)
139
140
141
142 p.determineExplicitEmbeddingLevels()
143
144
145
146
147
148
149
150
151
152 for _, seq := range p.determineIsolatingRunSequences() {
153
154
155 seq.resolveWeakTypes()
156
157
158
159 resolvePairedBrackets(seq)
160
161
162
163 seq.resolveNeutralTypes()
164
165
166
167 seq.resolveImplicitLevels()
168
169
170 seq.applyLevelsAndTypes()
171 }
172
173
174
175
176 p.assignLevelsToCharactersRemovedByX9()
177 }
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
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
226
227
228
229
230 func (p *paragraph) determineParagraphEmbeddingLevel(start, end int) level {
231 var strongType Class = unknownClass
232
233
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]
240 if i > end {
241 log.Panic("assert (i <= end)")
242 }
243 }
244 }
245
246 switch strongType {
247 case unknownClass:
248
249 return 0
250 case L:
251 return 0
252 default:
253 return 1
254 }
255 }
256
257 const maxDepth = 125
258
259
260
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
292 func (p *paragraph) determineExplicitEmbeddingLevels() {
293 var stack directionalStatusStack
294 var overflowIsolateCount, overflowEmbeddingCount, validIsolateCount int
295
296
297 stack.push(p.embeddingLevel, ON, false)
298
299 for i, t := range p.resultTypes {
300
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
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
320 newLevel = (stack.lastEmbeddingLevel() + 1) | 1
321 } else {
322
323 newLevel = (stack.lastEmbeddingLevel() + 2) &^ 1
324 }
325
326 if newLevel <= maxDepth && overflowIsolateCount == 0 && overflowEmbeddingCount == 0 {
327 if isIsolate {
328 validIsolateCount++
329 }
330
331
332
333
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
343 if !isIsolate {
344 p.resultLevels[i] = newLevel
345 }
346 } else {
347
348
349 if isIsolate {
350 overflowIsolateCount++
351 } else {
352 if overflowIsolateCount == 0 {
353 overflowEmbeddingCount++
354 }
355 }
356 }
357
358
359 case PDI:
360 if overflowIsolateCount > 0 {
361 overflowIsolateCount--
362 } else if validIsolateCount == 0 {
363
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
375 case PDF:
376
377 p.resultLevels[i] = stack.lastEmbeddingLevel()
378
379 if overflowIsolateCount > 0 {
380
381 } else if overflowEmbeddingCount > 0 {
382 overflowEmbeddingCount--
383 } else if !stack.lastDirectionalIsolateStatus() && stack.depth() >= 2 {
384 stack.pop()
385 }
386
387 case B:
388
389
390
391
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
411
412 types []Class
413 resolvedLevels []level
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
428
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
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
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
473
474
475
476 func (s *isolatingRunSequence) resolveWeakTypes() {
477
478
479 s.assertOnly(L, R, AL, EN, ES, ET, AN, CS, B, S, WS, ON, NSM, LRI, RLI, FSI, PDI)
480
481
482
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
496
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
511 for i, t := range s.types {
512 if t == AL {
513 s.types[i] = R
514 }
515 }
516
517
518
519
520
521
522
523
524
525
526
527
528
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
544 for i, t := range s.types {
545 if t == ET {
546
547 runStart := i
548 runEnd := s.findRunLimit(runStart, ET)
549
550
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
565 i = runEnd
566 }
567 }
568
569
570 for i, t := range s.types {
571 if t.in(ES, ET, CS) {
572 s.types[i] = ON
573 }
574 }
575
576
577 for i, t := range s.types {
578 if t == EN {
579
580 prevStrongType := s.sos
581 for j := i - 1; j >= 0; j-- {
582 t = s.types[j]
583 if t == L || t == R {
584 prevStrongType = t
585 break
586 }
587 }
588 if prevStrongType == L {
589 s.types[i] = L
590 }
591 }
592 }
593 }
594
595
596 func (s *isolatingRunSequence) resolveNeutralTypes() {
597
598
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
605 runStart := i
606 runEnd := s.findRunLimit(runStart, B, S, WS, ON, RLI, LRI, FSI, PDI)
607
608
609 var leadType, trailType Class
610
611
612
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
633 resolvedType = leadType
634 } else {
635
636
637
638 resolvedType = typeForLevel(s.level)
639 }
640
641 setTypes(s.types[runStart:runEnd], resolvedType)
642
643
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
662 func (s *isolatingRunSequence) resolveImplicitLevels() {
663
664
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 {
671 for i, t := range s.types {
672
673 if t == L {
674
675 } else if t == R {
676 s.resolvedLevels[i] += 1
677 } else {
678 s.resolvedLevels[i] += 2
679 }
680 }
681 } else {
682 for i, t := range s.types {
683
684 if t == R {
685
686 } else {
687 s.resolvedLevels[i] += 1
688 }
689 }
690 }
691 }
692
693
694
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
703
704
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
715 }
716 return len(s.types)
717 }
718
719
720
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
734
735
736
737
738
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
748 if currentLevel >= 0 {
749 allRuns = append(allRuns, run)
750 run = nil
751 }
752
753 currentLevel = p.resultLevels[i]
754 }
755 run = append(run, i)
756 }
757 }
758
759 if len(run) > 0 {
760 allRuns = append(allRuns, run)
761 }
762 return allRuns
763 }
764
765
766 func (p *paragraph) determineIsolatingRunSequences() []*isolatingRunSequence {
767 levelRuns := p.determineLevelRuns()
768
769
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
786 for {
787
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
805
806
807
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
816
817
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
828
829 }
830
831
832
833
834
835
836
837
838
839
840
841 func (p *paragraph) getLevels(linebreaks []int) []level {
842
843
844
845
846
847
848
849
850
851
852
853 validateLineBreaks(linebreaks, p.Len())
854
855 result := append([]level(nil), p.resultLevels...)
856
857
858
859
860 for i, t := range p.initialTypes {
861 if t.in(B, S) {
862
863 result[i] = p.embeddingLevel
864
865
866 for j := i - 1; j >= 0; j-- {
867 if isWhitespace(p.initialTypes[j]) {
868 result[j] = p.embeddingLevel
869 } else {
870 break
871 }
872 }
873 }
874 }
875
876
877 start := 0
878 for _, limit := range linebreaks {
879 for j := limit - 1; j >= start; j-- {
880 if isWhitespace(p.initialTypes[j]) {
881 result[j] = p.embeddingLevel
882 } else {
883 break
884 }
885 }
886 start = limit
887 }
888
889 return result
890 }
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907 func (p *paragraph) getReordering(linebreaks []int) []int {
908 validateLineBreaks(linebreaks, p.Len())
909
910 return computeMultilineReordering(p.getLevels(linebreaks), linebreaks)
911 }
912
913
914
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
932
933
934 func computeReordering(levels []level) []int {
935 result := make([]int, len(levels))
936
937 for i := range result {
938 result[i] = i
939 }
940
941
942
943
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
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
969 i = limit
970 }
971 }
972 }
973
974 return result
975 }
976
977
978
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
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
997 func typeForLevel(level level) Class {
998 if (level & 0x1) == 0 {
999 return L
1000 }
1001 return R
1002 }
1003
1004
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 }
1059
View as plain text