strtod method

double strtod(
  1. String nptr, {
  2. List<String>? endptr,
})

Converts the string nptr to a double.

Trims leading whitespace, handles optional signs, INF, NAN, and scientific notation. Stops at the first invalid character. If endptr is provided, endptr[0] is set to the unparsed remainder of the string.

Implementation

double strtod(String nptr, {List<String>? endptr}) {
  if (nptr.isEmpty) {
    if (endptr != null && endptr.isNotEmpty) endptr[0] = nptr;
    return 0.0;
  }
  int i = 0;
  while (i < nptr.length) {
    int c = nptr.codeUnitAt(i);
    if (c == 32 || (c >= 9 && c <= 13)) {
      i++;
    } else {
      break;
    }
  }
  if (i >= nptr.length) {
    if (endptr != null && endptr.isNotEmpty) endptr[0] = nptr;
    return 0.0;
  }

  int start = i;
  bool negative = false;
  int c = nptr.codeUnitAt(i);
  if (c == 45) { // '-'
    negative = true;
    i++;
  } else if (c == 43) { // '+'
    i++;
  }

  String upper = nptr.substring(i).toUpperCase();
  if (upper.startsWith("INFINITY")) {
    i += 8;
    if (endptr != null && endptr.isNotEmpty) endptr[0] = nptr.substring(i);
    return negative ? double.negativeInfinity : double.infinity;
  } else if (upper.startsWith("INF")) {
    i += 3;
    if (endptr != null && endptr.isNotEmpty) endptr[0] = nptr.substring(i);
    return negative ? double.negativeInfinity : double.infinity;
  } else if (upper.startsWith("NAN")) {
    i += 3;
    if (endptr != null && endptr.isNotEmpty) endptr[0] = nptr.substring(i);
    return double.nan;
  }

  bool hasDigits = false;
  bool hasDot = false;

  while (i < nptr.length) {
    c = nptr.codeUnitAt(i);
    if (c >= 48 && c <= 57) {
      hasDigits = true;
      i++;
    } else if (c == 46 && !hasDot) { // '.'
      hasDot = true;
      i++;
    } else {
      break;
    }
  }

  if (!hasDigits) {
    if (endptr != null && endptr.isNotEmpty) endptr[0] = nptr;
    return 0.0;
  }

  // Check for exponent
  if (i < nptr.length) {
    c = nptr.codeUnitAt(i);
    if (c == 101 || c == 69) { // 'e' or 'E'
      int expStart = i;
      i++;
      if (i < nptr.length) {
        c = nptr.codeUnitAt(i);
        if (c == 45 || c == 43) i++;
      }
      bool hasExpDigits = false;
      while (i < nptr.length) {
        c = nptr.codeUnitAt(i);
        if (c >= 48 && c <= 57) {
          hasExpDigits = true;
          i++;
        } else {
          break;
        }
      }
      if (!hasExpDigits) {
        i = expStart;
      }
    }
  }

  if (endptr != null && endptr.isNotEmpty) {
    endptr[0] = nptr.substring(i);
  }

  String valStr = nptr.substring(start, i);
  return double.tryParse(valStr) ?? 0.0;
}