| // Copyright 2025 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 |
| |
| import ( |
| "errors" |
| "internal/strconv" |
| "internal/stringslite" |
| ) |
| |
| // IntSize is the size in bits of an int or uint value. |
| const IntSize = strconv.IntSize |
| |
| // ParseBool returns the boolean value represented by the string. |
| // It accepts 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False. |
| // Any other value returns an error. |
| func ParseBool(str string) (bool, error) { |
| x, err := strconv.ParseBool(str) |
| if err != nil { |
| return x, toError("ParseBool", str, 0, 0, err) |
| } |
| return x, nil |
| } |
| |
| // FormatBool returns "true" or "false" according to the value of b. |
| func FormatBool(b bool) string { |
| return strconv.FormatBool(b) |
| } |
| |
| // AppendBool appends "true" or "false", according to the value of b, |
| // to dst and returns the extended buffer. |
| func AppendBool(dst []byte, b bool) []byte { |
| return strconv.AppendBool(dst, b) |
| } |
| |
| // ParseComplex converts the string s to a complex number |
| // with the precision specified by bitSize: 64 for complex64, or 128 for complex128. |
| // When bitSize=64, the result still has type complex128, but it will be |
| // convertible to complex64 without changing its value. |
| // |
| // The number represented by s must be of the form N, Ni, or N±Ni, where N stands |
| // for a floating-point number as recognized by [ParseFloat], and i is the imaginary |
| // component. If the second N is unsigned, a + sign is required between the two components |
| // as indicated by the ±. If the second N is NaN, only a + sign is accepted. |
| // The form may be parenthesized and cannot contain any spaces. |
| // The resulting complex number consists of the two components converted by ParseFloat. |
| // |
| // The errors that ParseComplex returns have concrete type [*NumError] |
| // and include err.Num = s. |
| // |
| // If s is not syntactically well-formed, ParseComplex returns err.Err = ErrSyntax. |
| // |
| // If s is syntactically well-formed but either component is more than 1/2 ULP |
| // away from the largest floating point number of the given component's size, |
| // ParseComplex returns err.Err = ErrRange and c = ±Inf for the respective component. |
| func ParseComplex(s string, bitSize int) (complex128, error) { |
| x, err := strconv.ParseComplex(s, bitSize) |
| if err != nil { |
| return x, toError("ParseComplex", s, 0, bitSize, err) |
| } |
| return x, nil |
| } |
| |
| // ParseFloat converts the string s to a floating-point number |
| // with the precision specified by bitSize: 32 for float32, or 64 for float64. |
| // When bitSize=32, the result still has type float64, but it will be |
| // convertible to float32 without changing its value. |
| // |
| // ParseFloat accepts decimal and hexadecimal floating-point numbers |
| // as defined by the Go syntax for [floating-point literals]. |
| // If s is well-formed and near a valid floating-point number, |
| // ParseFloat returns the nearest floating-point number rounded |
| // using IEEE754 unbiased rounding. |
| // (Parsing a hexadecimal floating-point value only rounds when |
| // there are more bits in the hexadecimal representation than |
| // will fit in the mantissa.) |
| // |
| // The errors that ParseFloat returns have concrete type *NumError |
| // and include err.Num = s. |
| // |
| // If s is not syntactically well-formed, ParseFloat returns err.Err = ErrSyntax. |
| // |
| // If s is syntactically well-formed but is more than 1/2 ULP |
| // away from the largest floating point number of the given size, |
| // ParseFloat returns f = ±Inf, err.Err = ErrRange. |
| // |
| // ParseFloat recognizes the string "NaN", and the (possibly signed) strings "Inf" and "Infinity" |
| // as their respective special floating point values. It ignores case when matching. |
| // |
| // [floating-point literals]: https://go.dev/ref/spec#Floating-point_literals |
| func ParseFloat(s string, bitSize int) (float64, error) { |
| x, err := strconv.ParseFloat(s, bitSize) |
| if err != nil { |
| return x, toError("ParseFloat", s, 0, bitSize, err) |
| } |
| return x, nil |
| } |
| |
| // ParseUint is like [ParseInt] but for unsigned numbers. |
| // |
| // A sign prefix is not permitted. |
| func ParseUint(s string, base int, bitSize int) (uint64, error) { |
| x, err := strconv.ParseUint(s, base, bitSize) |
| if err != nil { |
| return x, toError("ParseUint", s, base, bitSize, err) |
| } |
| return x, 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_literals |
| func ParseInt(s string, base int, bitSize int) (i int64, err error) { |
| x, err := strconv.ParseInt(s, base, bitSize) |
| if err != nil { |
| return x, toError("ParseInt", s, base, bitSize, err) |
| } |
| return x, nil |
| } |
| |
| // Atoi is equivalent to ParseInt(s, 10, 0), converted to type int. |
| func Atoi(s string) (int, error) { |
| x, err := strconv.Atoi(s) |
| if err != nil { |
| return x, toError("Atoi", s, 0, 0, err) |
| } |
| return strconv.Atoi(s) |
| } |
| |
| // FormatComplex converts the complex number c to a string of the |
| // form (a+bi) where a and b are the real and imaginary parts, |
| // formatted according to the format fmt and precision prec. |
| // |
| // The format fmt and precision prec have the same meaning as in [FormatFloat]. |
| // It rounds the result assuming that the original was obtained from a complex |
| // value of bitSize bits, which must be 64 for complex64 and 128 for complex128. |
| func FormatComplex(c complex128, fmt byte, prec, bitSize int) string { |
| return strconv.FormatComplex(c, fmt, prec, bitSize) |
| } |
| |
| // FormatFloat converts the floating-point number f to a string, |
| // according to the format fmt and precision prec. It rounds the |
| // result assuming that the original was obtained from a floating-point |
| // value of bitSize bits (32 for float32, 64 for float64). |
| // |
| // The format fmt is one of |
| // - 'b' (-ddddp±ddd, a binary exponent), |
| // - 'e' (-d.dddde±dd, a decimal exponent), |
| // - 'E' (-d.ddddE±dd, a decimal exponent), |
| // - 'f' (-ddd.dddd, no exponent), |
| // - 'g' ('e' for large exponents, 'f' otherwise), |
| // - 'G' ('E' for large exponents, 'f' otherwise), |
| // - 'x' (-0xd.ddddp±ddd, a hexadecimal fraction and binary exponent), or |
| // - 'X' (-0Xd.ddddP±ddd, a hexadecimal fraction and binary exponent). |
| // |
| // The precision prec controls the number of digits (excluding the exponent) |
| // printed by the 'e', 'E', 'f', 'g', 'G', 'x', and 'X' formats. |
| // For 'e', 'E', 'f', 'x', and 'X', it is the number of digits after the decimal point. |
| // For 'g' and 'G' it is the maximum number of significant digits (trailing |
| // zeros are removed). |
| // The special precision -1 uses the smallest number of digits |
| // necessary such that ParseFloat will return f exactly. |
| // The exponent is written as a decimal integer; |
| // for all formats other than 'b', it will be at least two digits. |
| func FormatFloat(f float64, fmt byte, prec, bitSize int) string { |
| return strconv.FormatFloat(f, fmt, prec, bitSize) |
| } |
| |
| // AppendFloat appends the string form of the floating-point number f, |
| // as generated by [FormatFloat], to dst and returns the extended buffer. |
| func AppendFloat(dst []byte, f float64, fmt byte, prec, bitSize int) []byte { |
| return strconv.AppendFloat(dst, f, fmt, prec, bitSize) |
| } |
| |
| // FormatUint returns the string representation of i in the given base, |
| // for 2 <= base <= 36. The result uses the lower-case letters 'a' to 'z' |
| // for digit values >= 10. |
| func FormatUint(i uint64, base int) string { |
| return strconv.FormatUint(i, base) |
| } |
| |
| // FormatInt returns the string representation of i in the given base, |
| // for 2 <= base <= 36. The result uses the lower-case letters 'a' to 'z' |
| // for digit values >= 10. |
| func FormatInt(i int64, base int) string { |
| return strconv.FormatInt(i, base) |
| } |
| |
| // Itoa is equivalent to [FormatInt](int64(i), 10). |
| func Itoa(i int) string { |
| return strconv.Itoa(i) |
| } |
| |
| // AppendInt appends the string form of the integer i, |
| // as generated by [FormatInt], to dst and returns the extended buffer. |
| func AppendInt(dst []byte, i int64, base int) []byte { |
| return strconv.AppendInt(dst, i, base) |
| } |
| |
| // AppendUint appends the string form of the unsigned integer i, |
| // as generated by [FormatUint], to dst and returns the extended buffer. |
| func AppendUint(dst []byte, i uint64, base int) []byte { |
| return strconv.AppendUint(dst, i, base) |
| } |
| |
| // toError converts from internal/strconv.Error to the error guaranteed by this package's APIs. |
| func toError(fn, s string, base, bitSize int, err error) error { |
| switch err { |
| case strconv.ErrSyntax: |
| return syntaxError(fn, s) |
| case strconv.ErrRange: |
| return rangeError(fn, s) |
| case strconv.ErrBase: |
| return baseError(fn, s, base) |
| case strconv.ErrBitSize: |
| return bitSizeError(fn, s, bitSize) |
| } |
| return err |
| } |
| |
| // ErrRange indicates that a value is out of range for the target type. |
| var ErrRange = errors.New("value out of range") |
| |
| // ErrSyntax indicates that a value does not have the right syntax for the target type. |
| var ErrSyntax = errors.New("invalid syntax") |
| |
| // A NumError records a failed conversion. |
| type NumError struct { |
| Func string // the failing function (ParseBool, ParseInt, ParseUint, ParseFloat, ParseComplex) |
| Num string // the input |
| Err error // the reason the conversion failed (e.g. ErrRange, ErrSyntax, etc.) |
| } |
| |
| func (e *NumError) Error() string { |
| return "strconv." + e.Func + ": " + "parsing " + Quote(e.Num) + ": " + e.Err.Error() |
| } |
| |
| func (e *NumError) Unwrap() error { return e.Err } |
| |
| // All ParseXXX functions allow the input string to escape to the error value. |
| // This hurts strconv.ParseXXX(string(b)) calls where b is []byte since |
| // the conversion from []byte must allocate a string on the heap. |
| // If we assume errors are infrequent, then we can avoid escaping the input |
| // back to the output by copying it first. This allows the compiler to call |
| // strconv.ParseXXX without a heap allocation for most []byte to string |
| // conversions, since it can now prove that the string cannot escape Parse. |
| |
| func syntaxError(fn, str string) *NumError { |
| return &NumError{fn, stringslite.Clone(str), ErrSyntax} |
| } |
| |
| func rangeError(fn, str string) *NumError { |
| return &NumError{fn, stringslite.Clone(str), ErrRange} |
| } |
| |
| func baseError(fn, str string, base int) *NumError { |
| return &NumError{fn, stringslite.Clone(str), errors.New("invalid base " + Itoa(base))} |
| } |
| |
| func bitSizeError(fn, str string, bitSize int) *NumError { |
| return &NumError{fn, stringslite.Clone(str), errors.New("invalid bit size " + Itoa(bitSize))} |
| } |