github.com/cockroachdb/pebble@v0.0.0-20231214172447-ab4952c5f87b/internal/testkeys/strconv.go (about) 1 /* 2 Copyright 2013 The Perkeep Authors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package testkeys 18 19 import ( 20 "strconv" 21 22 "github.com/cockroachdb/errors" 23 ) 24 25 // parseUintBytes is like strconv.ParseUint, but using a []byte. Use of this 26 // function avoids an allocation when parsing an integer out of a []byte. 27 // 28 // This function is copied from go4.org/strconv. 29 func parseUintBytes(s []byte, base int, bitSize int) (n uint64, err error) { 30 var cutoff, maxVal uint64 31 32 if bitSize == 0 { 33 bitSize = int(strconv.IntSize) 34 } 35 36 s0 := s 37 switch { 38 case len(s) < 1: 39 err = strconv.ErrSyntax 40 goto Error 41 42 case 2 <= base && base <= 36: 43 // valid base; nothing to do 44 45 case base == 0: 46 // Look for octal, hex prefix. 47 switch { 48 case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'): 49 base = 16 50 s = s[2:] 51 if len(s) < 1 { 52 err = strconv.ErrSyntax 53 goto Error 54 } 55 case s[0] == '0': 56 base = 8 57 default: 58 base = 10 59 } 60 61 default: 62 err = errors.New("invalid base " + strconv.Itoa(base)) 63 goto Error 64 } 65 66 n = 0 67 cutoff = cutoff64(base) 68 maxVal = 1<<uint(bitSize) - 1 69 70 for i := 0; i < len(s); i++ { 71 var v byte 72 d := s[i] 73 switch { 74 case '0' <= d && d <= '9': 75 v = d - '0' 76 case 'a' <= d && d <= 'z': 77 v = d - 'a' + 10 78 case 'A' <= d && d <= 'Z': 79 v = d - 'A' + 10 80 default: 81 n = 0 82 err = strconv.ErrSyntax 83 goto Error 84 } 85 if int(v) >= base { 86 n = 0 87 err = strconv.ErrSyntax 88 goto Error 89 } 90 91 if n >= cutoff { 92 // n*base overflows 93 n = 1<<64 - 1 94 err = strconv.ErrRange 95 goto Error 96 } 97 n *= uint64(base) 98 99 n1 := n + uint64(v) 100 if n1 < n || n1 > maxVal { 101 // n+v overflows 102 n = 1<<64 - 1 103 err = strconv.ErrRange 104 goto Error 105 } 106 n = n1 107 } 108 109 return n, nil 110 111 Error: 112 return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err} 113 } 114 115 // Return the first number n such that n*base >= 1<<64. 116 func cutoff64(base int) uint64 { 117 if base < 2 { 118 return 0 119 } 120 return (1<<64-1)/uint64(base) + 1 121 }