Black Lives Matter. Support the Equal Justice Initiative.

Source file src/strconv/atoc.go

Documentation: strconv

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

View as plain text