strings.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. package strings
  2. import "unicode/utf8"
  3. // IndexNotByte is similar with strings.IndexByte but showing the opposite behavior.
  4. func IndexNotByte(s string, c byte) int {
  5. n := len(s)
  6. for i := 0; i < n; i++ {
  7. if s[i] != c {
  8. return i
  9. }
  10. }
  11. return -1
  12. }
  13. // LastIndexNotByte is similar with strings.LastIndexByte but showing the opposite behavior.
  14. func LastIndexNotByte(s string, c byte) int {
  15. for i := len(s) - 1; i >= 0; i-- {
  16. if s[i] != c {
  17. return i
  18. }
  19. }
  20. return -1
  21. }
  22. type asciiSet [8]uint32
  23. func (as *asciiSet) notContains(c byte) bool {
  24. return (as[c>>5] & (1 << uint(c&31))) == 0
  25. }
  26. func makeASCIISet(chars string) (as asciiSet, ok bool) {
  27. for i := 0; i < len(chars); i++ {
  28. c := chars[i]
  29. if c >= utf8.RuneSelf {
  30. return as, false
  31. }
  32. as[c>>5] |= 1 << uint(c&31)
  33. }
  34. return as, true
  35. }
  36. // IndexNotAny is similar with strings.IndexAny but showing the opposite behavior.
  37. func IndexNotAny(s, chars string) int {
  38. if len(chars) > 0 {
  39. if len(s) > 8 {
  40. if as, isASCII := makeASCIISet(chars); isASCII {
  41. for i := 0; i < len(s); i++ {
  42. if as.notContains(s[i]) {
  43. return i
  44. }
  45. }
  46. return -1
  47. }
  48. }
  49. LabelFirstLoop:
  50. for i, c := range s {
  51. for j, m := range chars {
  52. if c != m && j == len(chars)-1 {
  53. return i
  54. } else if c != m {
  55. continue
  56. } else {
  57. continue LabelFirstLoop
  58. }
  59. }
  60. }
  61. }
  62. return -1
  63. }
  64. // LastIndexNotAny is similar with strings.LastIndexAny but showing the opposite behavior.
  65. func LastIndexNotAny(s, chars string) int {
  66. if len(chars) > 0 {
  67. if len(s) > 8 {
  68. if as, isASCII := makeASCIISet(chars); isASCII {
  69. for i := len(s) - 1; i >= 0; i-- {
  70. if as.notContains(s[i]) {
  71. return i
  72. }
  73. }
  74. return -1
  75. }
  76. }
  77. LabelFirstLoop:
  78. for i := len(s); i > 0; {
  79. r, size := utf8.DecodeLastRuneInString(s[:i])
  80. i -= size
  81. for j, m := range chars {
  82. if r != m && j == len(chars)-1 {
  83. return i
  84. } else if r != m {
  85. continue
  86. } else {
  87. continue LabelFirstLoop
  88. }
  89. }
  90. }
  91. }
  92. return -1
  93. }