Source file src/strconv/atoc.go
1 // Copyright 2020 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package strconv 6 7 import "internal/stringslite" 8 9 const fnParseComplex = "ParseComplex" 10 11 // convErr splits an error returned by parseFloatPrefix 12 // into a syntax or range error for ParseComplex. 13 func convErr(err error, s string) (syntax, range_ error) { 14 if x, ok := err.(*NumError); ok { 15 x.Func = fnParseComplex 16 x.Num = stringslite.Clone(s) 17 if x.Err == ErrRange { 18 return nil, x 19 } 20 } 21 return err, nil 22 } 23 24 // ParseComplex converts the string s to a complex number 25 // with the precision specified by bitSize: 64 for complex64, or 128 for complex128. 26 // When bitSize=64, the result still has type complex128, but it will be 27 // convertible to complex64 without changing its value. 28 // 29 // The number represented by s must be of the form N, Ni, or N±Ni, where N stands 30 // for a floating-point number as recognized by [ParseFloat], and i is the imaginary 31 // component. If the second N is unsigned, a + sign is required between the two components 32 // as indicated by the ±. If the second N is NaN, only a + sign is accepted. 33 // The form may be parenthesized and cannot contain any spaces. 34 // The resulting complex number consists of the two components converted by ParseFloat. 35 // 36 // The errors that ParseComplex returns have concrete type [*NumError] 37 // and include err.Num = s. 38 // 39 // If s is not syntactically well-formed, ParseComplex returns err.Err = ErrSyntax. 40 // 41 // If s is syntactically well-formed but either component is more than 1/2 ULP 42 // away from the largest floating point number of the given component's size, 43 // ParseComplex returns err.Err = ErrRange and c = ±Inf for the respective component. 44 func ParseComplex(s string, bitSize int) (complex128, error) { 45 size := 64 46 if bitSize == 64 { 47 size = 32 // complex64 uses float32 parts 48 } 49 50 orig := s 51 52 // Remove parentheses, if any. 53 if len(s) >= 2 && s[0] == '(' && s[len(s)-1] == ')' { 54 s = s[1 : len(s)-1] 55 } 56 57 var pending error // pending range error, or nil 58 59 // Read real part (possibly imaginary part if followed by 'i'). 60 re, n, err := parseFloatPrefix(s, size) 61 if err != nil { 62 err, pending = convErr(err, orig) 63 if err != nil { 64 return 0, err 65 } 66 } 67 s = s[n:] 68 69 // If we have nothing left, we're done. 70 if len(s) == 0 { 71 return complex(re, 0), pending 72 } 73 74 // Otherwise, look at the next character. 75 switch s[0] { 76 case '+': 77 // Consume the '+' to avoid an error if we have "+NaNi", but 78 // do this only if we don't have a "++" (don't hide that error). 79 if len(s) > 1 && s[1] != '+' { 80 s = s[1:] 81 } 82 case '-': 83 // ok 84 case 'i': 85 // If 'i' is the last character, we only have an imaginary part. 86 if len(s) == 1 { 87 return complex(0, re), pending 88 } 89 fallthrough 90 default: 91 return 0, syntaxError(fnParseComplex, orig) 92 } 93 94 // Read imaginary part. 95 im, n, err := parseFloatPrefix(s, size) 96 if err != nil { 97 err, pending = convErr(err, orig) 98 if err != nil { 99 return 0, err 100 } 101 } 102 s = s[n:] 103 if s != "i" { 104 return 0, syntaxError(fnParseComplex, orig) 105 } 106 return complex(re, im), pending 107 } 108