github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/internal/bytealg/bytealg.go (about) 1 package bytealg 2 3 // Some code in this file has been copied from the Go source code, and has 4 // copyright of their original authors: 5 // 6 // Copyright 2020 The Go Authors. All rights reserved. 7 // Use of this source code is governed by a BSD-style 8 // license that can be found in the LICENSE file. 9 // 10 // This is indicated specifically in the file. 11 12 const ( 13 // Index can search any valid length of string. 14 15 MaxLen = int(-1) >> 31 16 MaxBruteForce = MaxLen 17 ) 18 19 // Compare two byte slices. 20 // Returns -1 if the first differing byte is lower in a, or 1 if the first differing byte is greater in b. 21 // If the byte slices are equal, returns 0. 22 // If the lengths are different and there are no differing bytes, compares based on length. 23 func Compare(a, b []byte) int { 24 // Compare for differing bytes. 25 for i := 0; i < len(a) && i < len(b); i++ { 26 switch { 27 case a[i] < b[i]: 28 return -1 29 case a[i] > b[i]: 30 return 1 31 } 32 } 33 34 // Compare lengths. 35 switch { 36 case len(a) > len(b): 37 return 1 38 case len(a) < len(b): 39 return -1 40 default: 41 return 0 42 } 43 } 44 45 // Count the number of instances of a byte in a slice. 46 func Count(b []byte, c byte) int { 47 // Use a simple implementation, as there is no intrinsic that does this like we want. 48 n := 0 49 for _, v := range b { 50 if v == c { 51 n++ 52 } 53 } 54 return n 55 } 56 57 // Count the number of instances of a byte in a string. 58 func CountString(s string, c byte) int { 59 // Use a simple implementation, as there is no intrinsic that does this like we want. 60 // Currently, the compiler does not generate zero-copy byte-string conversions, so this needs to be seperate from Count. 61 n := 0 62 for i := 0; i < len(s); i++ { 63 if s[i] == c { 64 n++ 65 } 66 } 67 return n 68 } 69 70 // Cutover is not reachable in TinyGo, but must exist as it is referenced. 71 func Cutover(n int) int { 72 // Setting MaxLen and MaxBruteForce should force a different path to be taken. 73 // This should never be called. 74 panic("cutover is unreachable") 75 } 76 77 // Equal checks if two byte slices are equal. 78 // It is equivalent to bytes.Equal. 79 func Equal(a, b []byte) bool { 80 if len(a) != len(b) { 81 return false 82 } 83 84 for i, v := range a { 85 if v != b[i] { 86 return false 87 } 88 } 89 90 return true 91 } 92 93 // Index finds the base index of the first instance of the byte sequence b in a. 94 // If a does not contain b, this returns -1. 95 func Index(a, b []byte) int { 96 for i := 0; i <= len(a)-len(b); i++ { 97 if Equal(a[i:i+len(b)], b) { 98 return i 99 } 100 } 101 return -1 102 } 103 104 // Index finds the index of the first instance of the specified byte in the slice. 105 // If the byte is not found, this returns -1. 106 func IndexByte(b []byte, c byte) int { 107 for i, v := range b { 108 if v == c { 109 return i 110 } 111 } 112 return -1 113 } 114 115 // Index finds the index of the first instance of the specified byte in the string. 116 // If the byte is not found, this returns -1. 117 func IndexByteString(s string, c byte) int { 118 for i := 0; i < len(s); i++ { 119 if s[i] == c { 120 return i 121 } 122 } 123 return -1 124 } 125 126 // Index finds the base index of the first instance of a substring in a string. 127 // If the substring is not found, this returns -1. 128 func IndexString(str, sub string) int { 129 for i := 0; i <= len(str)-len(sub); i++ { 130 if str[i:i+len(sub)] == sub { 131 return i 132 } 133 } 134 return -1 135 } 136 137 // The following code has been copied from the Go 1.15 release tree. 138 139 // PrimeRK is the prime base used in Rabin-Karp algorithm. 140 const PrimeRK = 16777619 141 142 // HashStrBytes returns the hash and the appropriate multiplicative 143 // factor for use in Rabin-Karp algorithm. 144 // 145 // This function was removed in Go 1.22. 146 func HashStrBytes(sep []byte) (uint32, uint32) { 147 hash := uint32(0) 148 for i := 0; i < len(sep); i++ { 149 hash = hash*PrimeRK + uint32(sep[i]) 150 } 151 var pow, sq uint32 = 1, PrimeRK 152 for i := len(sep); i > 0; i >>= 1 { 153 if i&1 != 0 { 154 pow *= sq 155 } 156 sq *= sq 157 } 158 return hash, pow 159 } 160 161 // HashStr returns the hash and the appropriate multiplicative 162 // factor for use in Rabin-Karp algorithm. 163 // 164 // This function was removed in Go 1.22. 165 func HashStr[T string | []byte](sep T) (uint32, uint32) { 166 hash := uint32(0) 167 for i := 0; i < len(sep); i++ { 168 hash = hash*PrimeRK + uint32(sep[i]) 169 } 170 var pow, sq uint32 = 1, PrimeRK 171 for i := len(sep); i > 0; i >>= 1 { 172 if i&1 != 0 { 173 pow *= sq 174 } 175 sq *= sq 176 } 177 return hash, pow 178 } 179 180 // HashStrRevBytes returns the hash of the reverse of sep and the 181 // appropriate multiplicative factor for use in Rabin-Karp algorithm. 182 // 183 // This function was removed in Go 1.22. 184 func HashStrRevBytes(sep []byte) (uint32, uint32) { 185 hash := uint32(0) 186 for i := len(sep) - 1; i >= 0; i-- { 187 hash = hash*PrimeRK + uint32(sep[i]) 188 } 189 var pow, sq uint32 = 1, PrimeRK 190 for i := len(sep); i > 0; i >>= 1 { 191 if i&1 != 0 { 192 pow *= sq 193 } 194 sq *= sq 195 } 196 return hash, pow 197 } 198 199 // HashStrRev returns the hash of the reverse of sep and the 200 // appropriate multiplicative factor for use in Rabin-Karp algorithm. 201 // 202 // Copied from the Go 1.22rc1 source tree. 203 func HashStrRev[T string | []byte](sep T) (uint32, uint32) { 204 hash := uint32(0) 205 for i := len(sep) - 1; i >= 0; i-- { 206 hash = hash*PrimeRK + uint32(sep[i]) 207 } 208 var pow, sq uint32 = 1, PrimeRK 209 for i := len(sep); i > 0; i >>= 1 { 210 if i&1 != 0 { 211 pow *= sq 212 } 213 sq *= sq 214 } 215 return hash, pow 216 } 217 218 // IndexRabinKarpBytes uses the Rabin-Karp search algorithm to return the index of the 219 // first occurence of substr in s, or -1 if not present. 220 // 221 // This function was removed in Go 1.22. 222 func IndexRabinKarpBytes(s, sep []byte) int { 223 // Rabin-Karp search 224 hashsep, pow := HashStrBytes(sep) 225 n := len(sep) 226 var h uint32 227 for i := 0; i < n; i++ { 228 h = h*PrimeRK + uint32(s[i]) 229 } 230 if h == hashsep && Equal(s[:n], sep) { 231 return 0 232 } 233 for i := n; i < len(s); { 234 h *= PrimeRK 235 h += uint32(s[i]) 236 h -= pow * uint32(s[i-n]) 237 i++ 238 if h == hashsep && Equal(s[i-n:i], sep) { 239 return i - n 240 } 241 } 242 return -1 243 } 244 245 // IndexRabinKarp uses the Rabin-Karp search algorithm to return the index of the 246 // first occurrence of sep in s, or -1 if not present. 247 // 248 // Copied from the Go 1.22rc1 source tree. 249 func IndexRabinKarp[T string | []byte](s, sep T) int { 250 // Rabin-Karp search 251 hashss, pow := HashStr(sep) 252 n := len(sep) 253 var h uint32 254 for i := 0; i < n; i++ { 255 h = h*PrimeRK + uint32(s[i]) 256 } 257 if h == hashss && string(s[:n]) == string(sep) { 258 return 0 259 } 260 for i := n; i < len(s); { 261 h *= PrimeRK 262 h += uint32(s[i]) 263 h -= pow * uint32(s[i-n]) 264 i++ 265 if h == hashss && string(s[i-n:i]) == string(sep) { 266 return i - n 267 } 268 } 269 return -1 270 } 271 272 // MakeNoZero makes a slice of length and capacity n without zeroing the bytes. 273 // It is the caller's responsibility to ensure uninitialized bytes 274 // do not leak to the end user. 275 func MakeNoZero(n int) []byte { 276 // Note: this does zero the buffer even though that's not necessary. 277 // For performance reasons we might want to change this (similar to the 278 // malloc function implemented in the runtime). 279 return make([]byte, n) 280 } 281 282 // Copied from the Go 1.22rc1 source tree. 283 func LastIndexByte(s []byte, c byte) int { 284 for i := len(s) - 1; i >= 0; i-- { 285 if s[i] == c { 286 return i 287 } 288 } 289 return -1 290 } 291 292 // Copied from the Go 1.22rc1 source tree. 293 func LastIndexByteString(s string, c byte) int { 294 for i := len(s) - 1; i >= 0; i-- { 295 if s[i] == c { 296 return i 297 } 298 } 299 return -1 300 } 301 302 // LastIndexRabinKarp uses the Rabin-Karp search algorithm to return the last index of the 303 // occurrence of sep in s, or -1 if not present. 304 // 305 // Copied from the Go 1.22rc1 source tree. 306 func LastIndexRabinKarp[T string | []byte](s, sep T) int { 307 // Rabin-Karp search from the end of the string 308 hashss, pow := HashStrRev(sep) 309 n := len(sep) 310 last := len(s) - n 311 var h uint32 312 for i := len(s) - 1; i >= last; i-- { 313 h = h*PrimeRK + uint32(s[i]) 314 } 315 if h == hashss && string(s[last:]) == string(sep) { 316 return last 317 } 318 for i := last - 1; i >= 0; i-- { 319 h *= PrimeRK 320 h += uint32(s[i]) 321 h -= pow * uint32(s[i+n]) 322 if h == hashss && string(s[i:i+n]) == string(sep) { 323 return i 324 } 325 } 326 return -1 327 }