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  

View as plain text