unidecode.go 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. // Package unidecode implements a unicode transliterator
  2. // which replaces non-ASCII characters with their ASCII
  3. // approximations.
  4. package unidecode
  5. import (
  6. "sync"
  7. "unicode"
  8. )
  9. const pooledCapacity = 64
  10. var (
  11. slicePool sync.Pool
  12. decodingOnce sync.Once
  13. )
  14. // Unidecode implements a unicode transliterator, which
  15. // replaces non-ASCII characters with their ASCII
  16. // counterparts.
  17. // Given an unicode encoded string, returns
  18. // another string with non-ASCII characters replaced
  19. // with their closest ASCII counterparts.
  20. // e.g. Unicode("áéíóú") => "aeiou"
  21. func Unidecode(s string) string {
  22. decodingOnce.Do(decodeTransliterations)
  23. l := len(s)
  24. var r []rune
  25. if l > pooledCapacity {
  26. r = make([]rune, 0, len(s))
  27. } else {
  28. if x := slicePool.Get(); x != nil {
  29. r = x.([]rune)[:0]
  30. } else {
  31. r = make([]rune, 0, pooledCapacity)
  32. }
  33. }
  34. for _, c := range s {
  35. if c <= unicode.MaxASCII {
  36. r = append(r, c)
  37. continue
  38. }
  39. if c > unicode.MaxRune || c > transCount {
  40. /* Ignore reserved chars */
  41. continue
  42. }
  43. if d := transliterations[c]; d != nil {
  44. r = append(r, d...)
  45. }
  46. }
  47. res := string(r)
  48. if l <= pooledCapacity {
  49. slicePool.Put(r)
  50. }
  51. return res
  52. }