@@ -18,6 +18,7 @@ package bidi // import "golang.org/x/text/unicode/bidi"
1818
1919import (
2020 "bytes"
21+ "unicode"
2122)
2223
2324// This API tries to avoid dealing with embedding levels for now. Under the hood
@@ -321,23 +322,36 @@ func (r *Run) Pos() (start, end int) {
321322// and returns the result. Modifiers will still follow the runes they modify.
322323// Brackets are replaced with their counterparts.
323324func AppendReverse (out , in []byte ) []byte {
324- ret := make ([]byte , len (in )+ len (out ))
325- copy (ret , out )
326325 inRunes := bytes .Runes (in )
327-
326+ li := len (inRunes )
327+ ret := make ([]rune , li )
328+ modifiers := make ([]rune , 0 , li )
328329 for i , r := range inRunes {
330+ if unicode .In (r , unicode .M , unicode .Sk ) {
331+ modifiers = append (modifiers , r )
332+ continue
333+ }
334+ if len (modifiers ) > 0 {
335+ ret [li - i ] = ret [li - i + len (modifiers )]
336+ copy (ret [li - i + 1 :li - i + 1 + len (modifiers )], modifiers )
337+ modifiers = nil
338+ }
329339 prop , _ := LookupRune (r )
330340 if prop .IsBracket () {
331- inRunes [i ] = prop .reverseBracket (r )
341+ ret [li - i - 1 ] = prop .reverseBracket (r )
342+ } else {
343+ ret [li - i - 1 ] = r
332344 }
333345 }
334-
335- for i , j := 0 , len (inRunes ) - 1 ; i < j ; i , j = i + 1 , j - 1 {
336- inRunes [ i ], inRunes [ j ] = inRunes [ j ], inRunes [ i ]
346+ if len ( modifiers ) > 0 {
347+ ret [ 0 ] = ret [ len (modifiers )]
348+ copy ( ret [ 1 : 1 + len ( modifiers ) ], modifiers )
337349 }
338- copy (ret [len (out ):], string (inRunes ))
339350
340- return ret
351+ res := make ([]byte , len (in )+ len (out ))
352+ copy (res , out )
353+ copy (res [len (out ):], string (ret ))
354+ return res
341355}
342356
343357// ReverseString reverses the order of characters in s and returns a new string.
@@ -347,13 +361,27 @@ func ReverseString(s string) string {
347361 input := []rune (s )
348362 li := len (input )
349363 ret := make ([]rune , li )
364+ modifiers := make ([]rune , 0 , li )
350365 for i , r := range input {
366+ if unicode .In (r , unicode .M , unicode .Sk ) {
367+ modifiers = append (modifiers , r )
368+ continue
369+ }
370+ if len (modifiers ) > 0 {
371+ ret [li - i ] = ret [li - i + len (modifiers )]
372+ copy (ret [li - i + 1 :li - i + 1 + len (modifiers )], modifiers )
373+ modifiers = nil
374+ }
351375 prop , _ := LookupRune (r )
352376 if prop .IsBracket () {
353377 ret [li - i - 1 ] = prop .reverseBracket (r )
354378 } else {
355379 ret [li - i - 1 ] = r
356380 }
357381 }
382+ if len (modifiers ) > 0 {
383+ ret [0 ] = ret [len (modifiers )]
384+ copy (ret [1 :1 + len (modifiers )], modifiers )
385+ }
358386 return string (ret )
359387}
0 commit comments