static RawObject intFromByteslike()

in runtime/under-builtins-module.cpp [3175:3248]


static RawObject intFromByteslike(Thread* thread, const Byteslike& byteslike,
                                  word length, word base) {
  DCHECK_BOUND(length, byteslike.length());
  DCHECK(base == 0 || (base >= 2 && base <= 36), "invalid base");
  if (length <= 0) return Error::error();

  // Clamp the length at the last whitespace character.
  word idx = length;
  byte b = byteslike.byteAt(--idx);
  while (ASCII::isSpace(b)) {
    if (idx <= 0) return Error::error();
    b = byteslike.byteAt(--idx);
  }
  length = idx + 1;

  // Start the index from the first non-zero whitespace character.
  idx = 0;
  if (idx >= length) return Error::error();
  b = byteslike.byteAt(idx++);
  while (ASCII::isSpace(b)) {
    if (idx >= length) return Error::error();
    b = byteslike.byteAt(idx++);
  }
  word sign = 1;
  switch (b) {
    case '-':
      sign = -1;
      // fall through
    case '+':
      if (idx >= length) return Error::error();
      b = byteslike.byteAt(idx++);
      break;
  }

  word inferred_base = 10;
  if (b == '0') {
    if (idx >= length) return SmallInt::fromWord(0);
    inferred_base = inferBase(byteslike.byteAt(idx));
    if (base == 0) base = inferred_base;
    if (inferred_base != 10 && base == inferred_base) {
      if (++idx >= length) return Error::error();
      b = byteslike.byteAt(idx++);
    }
  } else if (base == 0) {
    base = 10;
  }

  Runtime* runtime = thread->runtime();
  HandleScope scope(thread);
  Int result(&scope, SmallInt::fromWord(0));
  Int digit(&scope, SmallInt::fromWord(0));
  Int base_obj(&scope, SmallInt::fromWord(base));
  word num_start = idx;
  for (;;) {
    if (b == '_') {
      // No leading underscores unless the number has a prefix
      if (idx == num_start && inferred_base == 10) return Error::error();
      // No trailing underscores
      if (idx >= length) return Error::error();
      b = byteslike.byteAt(idx++);
    }
    word digit_val = digitValue(b, base);
    if (digit_val == -1) return Error::error();
    digit = Int::cast(SmallInt::fromWord(digit_val));
    result = runtime->intAdd(thread, result, digit);
    if (idx >= length) break;
    b = byteslike.byteAt(idx++);
    result = runtime->intMultiply(thread, result, base_obj);
  }
  if (sign < 0) {
    result = runtime->intNegate(thread, result);
  }
  return *result;
}