// Copyright 2009 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package strconv// lower(c) is a lower-case letter if and only if// c is either that lower-case letter or the equivalent upper-case letter.// Instead of writing c == 'x' || c == 'X' one can write lower(c) == 'x'.// Note that lower of non-letters can produce other non-letters.func lower( byte) byte {return | ('x' - 'X')}typeErrorintconst ( _ Error = iotaErrRangeErrSyntaxErrBaseErrBitSize)func ( Error) () string {switch {caseErrRange:return"value out of range"caseErrSyntax:return"invalid syntax"caseErrBase:return"invalid base"caseErrBitSize:return"invalid bit size" }return"unknown error"}const intSize = 32 << (^uint(0) >> 63)// IntSize is the size in bits of an int or uint value.constIntSize = intSize// ParseUint is like [ParseInt] but for unsigned numbers.//// A sign prefix is not permitted.func ( string, int, int) (uint64, error) {const = "ParseUint"if == "" {return0, ErrSyntax } := == 0 := switch {case2 <= && <= 36:// valid base; nothing to docase == 0:// Look for octal, hex prefix. = 10if [0] == '0' {switch {caselen() >= 3 && lower([1]) == 'b': = 2 = [2:]caselen() >= 3 && lower([1]) == 'o': = 8 = [2:]caselen() >= 3 && lower([1]) == 'x': = 16 = [2:]default: = 8 = [1:] } }default:return0, ErrBase }if == 0 { = IntSize } elseif < 0 || > 64 {return0, ErrBitSize }// Cutoff is the smallest number such that cutoff*base > maxUint64. // Use compile-time constants for common cases.varuint64switch {case10: = maxUint64/10 + 1case16: = maxUint64/16 + 1default: = maxUint64/uint64() + 1 } := uint64(1)<<uint() - 1 := falsevaruint64for , := range []byte() {varbyteswitch {case == '_' && : = truecontinuecase'0' <= && <= '9': = - '0'case'a' <= lower() && lower() <= 'z': = lower() - 'a' + 10default:return0, ErrSyntax }if >= byte() {return0, ErrSyntax }if >= {// n*base overflowsreturn , ErrRange } *= uint64() := + uint64()if < || > {// n+d overflowsreturn , ErrRange } = }if && !underscoreOK() {return0, ErrSyntax }return , nil}// ParseInt interprets a string s in the given base (0, 2 to 36) and// bit size (0 to 64) and returns the corresponding value i.//// The string may begin with a leading sign: "+" or "-".//// If the base argument is 0, the true base is implied by the string's// prefix following the sign (if present): 2 for "0b", 8 for "0" or "0o",// 16 for "0x", and 10 otherwise. Also, for argument base 0 only,// underscore characters are permitted as defined by the Go syntax for// [integer literals].//// The bitSize argument specifies the integer type// that the result must fit into. Bit sizes 0, 8, 16, 32, and 64// correspond to int, int8, int16, int32, and int64.// If bitSize is below 0 or above 64, an error is returned.//// The errors that ParseInt returns have concrete type [*NumError]// and include err.Num = s. If s is empty or contains invalid// digits, err.Err = [ErrSyntax] and the returned value is 0;// if the value corresponding to s cannot be represented by a// signed integer of the given size, err.Err = [ErrRange] and the// returned value is the maximum magnitude integer of the// appropriate bitSize and sign.//// [integer literals]: https://go.dev/ref/spec#Integer_literalsfunc ( string, int, int) ( int64, error) {const = "ParseInt"if == "" {return0, ErrSyntax }// Pick off leading sign. := falseswitch [0] {case'+': = [1:]case'-': = [1:] = true }// Convert unsigned and check range.varuint64 , = ParseUint(, , )if != nil && != ErrRange {return0, }if == 0 { = IntSize } := uint64(1 << uint(-1))if ! && >= {returnint64( - 1), ErrRange }if && > {return -int64(), ErrRange } := int64()if { = - }return , nil}// Atoi is equivalent to ParseInt(s, 10, 0), converted to type int.func ( string) (int, error) {const = "Atoi" := len()ifintSize == 32 && (0 < && < 10) ||intSize == 64 && (0 < && < 19) {// Fast path for small integers that fit int type. := if [0] == '-' || [0] == '+' { = [1:]iflen() < 1 {return0, ErrSyntax } } := 0for , := range []byte() { -= '0'if > 9 {return0, ErrSyntax } = *10 + int() }if [0] == '-' { = - }return , nil }// Slow path for invalid, big, or underscored integers. , := ParseInt(, 10, 0)returnint(), }// underscoreOK reports whether the underscores in s are allowed.// Checking them in this one function lets all the parsers skip over them simply.// Underscore must appear only between digits or between a base prefix and a digit.func underscoreOK( string) bool {// saw tracks the last character (class) we saw: // ^ for beginning of number, // 0 for a digit or base prefix, // _ for an underscore, // ! for none of the above. := '^' := 0// Optional sign.iflen() >= 1 && ([0] == '-' || [0] == '+') { = [1:] }// Optional base prefix. := falseiflen() >= 2 && [0] == '0' && (lower([1]) == 'b' || lower([1]) == 'o' || lower([1]) == 'x') { = 2 = '0'// base prefix counts as a digit for "underscore as digit separator" = lower([1]) == 'x' }// Number proper.for ; < len(); ++ {// Digits are always okay.if'0' <= [] && [] <= '9' || && 'a' <= lower([]) && lower([]) <= 'f' { = '0'continue }// Underscore must follow digit.if [] == '_' {if != '0' {returnfalse } = '_'continue }// Underscore must also be followed by digit.if == '_' {returnfalse }// Saw non-digit, non-underscore. = '!' }return != '_'}
The pages are generated with Goldsv0.8.3-preview. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.