|  | // Copyright 2020 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 | 
|  |  | 
|  | const fnParseComplex = "ParseComplex" | 
|  |  | 
|  | // convErr splits an error returned by parseFloatPrefix | 
|  | // into a syntax or range error for ParseComplex. | 
|  | func convErr(err error, s string) (syntax, range_ error) { | 
|  | if x, ok := err.(*NumError); ok { | 
|  | x.Func = fnParseComplex | 
|  | x.Num = s | 
|  | if x.Err == ErrRange { | 
|  | return nil, x | 
|  | } | 
|  | } | 
|  | return err, nil | 
|  | } | 
|  |  | 
|  | // 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) { | 
|  | size := 64 | 
|  | if bitSize == 64 { | 
|  | size = 32 // complex64 uses float32 parts | 
|  | } | 
|  |  | 
|  | orig := s | 
|  |  | 
|  | // Remove parentheses, if any. | 
|  | if len(s) >= 2 && s[0] == '(' && s[len(s)-1] == ')' { | 
|  | s = s[1 : len(s)-1] | 
|  | } | 
|  |  | 
|  | var pending error // pending range error, or nil | 
|  |  | 
|  | // Read real part (possibly imaginary part if followed by 'i'). | 
|  | re, n, err := parseFloatPrefix(s, size) | 
|  | if err != nil { | 
|  | err, pending = convErr(err, orig) | 
|  | if err != nil { | 
|  | return 0, err | 
|  | } | 
|  | } | 
|  | s = s[n:] | 
|  |  | 
|  | // If we have nothing left, we're done. | 
|  | if len(s) == 0 { | 
|  | return complex(re, 0), pending | 
|  | } | 
|  |  | 
|  | // Otherwise, look at the next character. | 
|  | switch s[0] { | 
|  | case '+': | 
|  | // Consume the '+' to avoid an error if we have "+NaNi", but | 
|  | // do this only if we don't have a "++" (don't hide that error). | 
|  | if len(s) > 1 && s[1] != '+' { | 
|  | s = s[1:] | 
|  | } | 
|  | case '-': | 
|  | // ok | 
|  | case 'i': | 
|  | // If 'i' is the last character, we only have an imaginary part. | 
|  | if len(s) == 1 { | 
|  | return complex(0, re), pending | 
|  | } | 
|  | fallthrough | 
|  | default: | 
|  | return 0, syntaxError(fnParseComplex, orig) | 
|  | } | 
|  |  | 
|  | // Read imaginary part. | 
|  | im, n, err := parseFloatPrefix(s, size) | 
|  | if err != nil { | 
|  | err, pending = convErr(err, orig) | 
|  | if err != nil { | 
|  | return 0, err | 
|  | } | 
|  | } | 
|  | s = s[n:] | 
|  | if s != "i" { | 
|  | return 0, syntaxError(fnParseComplex, orig) | 
|  | } | 
|  | return complex(re, im), pending | 
|  | } |