// File: tomfunkhouser[P]gaps/pkgs/RNBasics/json.cpp
// Function: Json::OurReader::decodeNumber(Json::OurReader::Token&, Json::Value&)
bool OurReader::decodeNumber(Token& token, Value& decoded) {
  // Attempts to parse the number as an integer. If the number is
  // larger than the maximum supported value of an integer then
  // we decode the number as a double.
  Location current = token.start_;
  bool isNegative = *current == '-';
  if (isNegative)
    ++current;
  // TODO: Help the compiler do the div and mod at compile time or get rid of them.
  Value::LargestUInt maxIntegerValue =
      isNegative ? Value::LargestUInt(-Value::minLargestInt)
                 : Value::maxLargestUInt;
  Value::LargestUInt threshold = maxIntegerValue / 10;
  Value::LargestUInt value = 0;
  while (current < token.end_) {
    Char c = *current++;
    if (c < '0' || c > '9')
      return decodeDouble(token, decoded);
    Value::UInt digit(static_cast<Value::UInt>(c - '0'));
    if (value >= threshold) {
      // We've hit or exceeded the max value divided by 10 (rounded down). If
      // a) we've only just touched the limit, b) this is the last digit, and
      // c) it's small enough to fit in that rounding delta, we're okay.
      // Otherwise treat this number as a double to avoid overflow.
      if (value > threshold || current != token.end_ ||
          digit > maxIntegerValue % 10) {
        return decodeDouble(token, decoded);
      }
    }
    value = value * 10 + digit;
  }
  if (isNegative)
    decoded = -Value::LargestInt(value);
  else if (value <= Value::LargestUInt(Value::maxInt))
    decoded = Value::LargestInt(value);
  else
    decoded = value;
  return true;
}

// Assembly:
subq $0x108, %rsp            # imm = 0x108
movq %rdi, 0xf8(%rsp)
movq %rsi, 0xf0(%rsp)
movq %rdx, 0xe8(%rsp)
movq 0xf8(%rsp), %rax
movq %rax, 0x28(%rsp)
movq 0xf0(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0xe0(%rsp)
movq 0xe0(%rsp), %rax
movsbl (%rax), %eax
cmpl $0x2d, %eax
sete %al
andb $0x1, %al
movb %al, 0xdf(%rsp)
testb $0x1, 0xdf(%rsp)
je 0xe7dd8
movq 0xe0(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xe0(%rsp)
testb $0x1, 0xdf(%rsp)
je 0xe7df2
xorl %eax, %eax
subq 0x822f5(%rip), %rax     # 0x16a0e0
movq %rax, 0x20(%rsp)
jmp 0xe7dfe
movq 0x822df(%rip), %rax     # 0x16a0d8
movq %rax, 0x20(%rsp)
movq 0x20(%rsp), %rax
movq %rax, 0xd0(%rsp)
movq 0xd0(%rsp), %rax
movl $0xa, %ecx
xorl %edx, %edx
divq %rcx
movq %rax, 0xc8(%rsp)
movq $0x0, 0xc0(%rsp)
movq 0xe0(%rsp), %rax
movq 0xf0(%rsp), %rcx
cmpq 0x10(%rcx), %rax
jae 0xe7f6b
movq 0xe0(%rsp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, 0xe0(%rsp)
movb (%rax), %al
movb %al, 0xbf(%rsp)
movsbl 0xbf(%rsp), %eax
cmpl $0x30, %eax
jl 0xe7e85
movsbl 0xbf(%rsp), %eax
cmpl $0x39, %eax
jle 0xe7ead
movq 0x28(%rsp), %rdi
movq 0xf0(%rsp), %rsi
movq 0xe8(%rsp), %rdx
callq 0xe8180
andb $0x1, %al
movb %al, 0x107(%rsp)
jmp 0xe80a8
movsbl 0xbf(%rsp), %eax
subl $0x30, %eax
movl %eax, 0xb8(%rsp)
movq 0xc0(%rsp), %rax
cmpq 0xc8(%rsp), %rax
jb 0xe7f4b
movq 0xc0(%rsp), %rax
cmpq 0xc8(%rsp), %rax
ja 0xe7f21
movq 0xe0(%rsp), %rax
movq 0xf0(%rsp), %rcx
cmpq 0x10(%rcx), %rax
jne 0xe7f21
movl 0xb8(%rsp), %eax
movq %rax, 0x18(%rsp)
movq 0xd0(%rsp), %rax
movl $0xa, %ecx
xorl %edx, %edx
divq %rcx
movq 0x18(%rsp), %rax
cmpq %rdx, %rax
jbe 0xe7f49
movq 0x28(%rsp), %rdi
movq 0xf0(%rsp), %rsi
movq 0xe8(%rsp), %rdx
callq 0xe8180
andb $0x1, %al
movb %al, 0x107(%rsp)
jmp 0xe80a8
jmp 0xe7f4b
imulq $0xa, 0xc0(%rsp), %rax
movl 0xb8(%rsp), %ecx
addq %rcx, %rax
movq %rax, 0xc0(%rsp)
jmp 0xe7e31
testb $0x1, 0xdf(%rsp)
je 0xe7fde
movq 0xc0(%rsp), %rsi
negq %rsi
leaq 0x90(%rsp), %rdi
movq %rdi, 0x10(%rsp)
callq 0xecde0
movq 0x10(%rsp), %rsi
movq 0xe8(%rsp), %rdi
callq 0xe3700
jmp 0xe7fa6
leaq 0x90(%rsp), %rdi
callq 0xed680
jmp 0xe80a0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x88(%rsp)
movl %eax, 0x84(%rsp)
leaq 0x90(%rsp), %rdi
callq 0xed680
jmp 0xe80b9
movq 0xc0(%rsp), %rax
movslq 0x820fb(%rip), %rcx     # 0x16a0e8
cmpq %rcx, %rax
ja 0xe8049
movq 0xc0(%rsp), %rsi
leaq 0x58(%rsp), %rdi
movq %rdi, 0x8(%rsp)
callq 0xecde0
movq 0x8(%rsp), %rsi
movq 0xe8(%rsp), %rdi
callq 0xe3700
jmp 0xe801d
leaq 0x58(%rsp), %rdi
callq 0xed680
jmp 0xe809e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x88(%rsp)
movl %eax, 0x84(%rsp)
leaq 0x58(%rsp), %rdi
callq 0xed680
jmp 0xe80b9
movq 0xc0(%rsp), %rsi
leaq 0x30(%rsp), %rdi
movq %rdi, (%rsp)
callq 0xece20
movq (%rsp), %rsi
movq 0xe8(%rsp), %rdi
callq 0xe3700
jmp 0xe8072
leaq 0x30(%rsp), %rdi
callq 0xed680
jmp 0xe809e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x88(%rsp)
movl %eax, 0x84(%rsp)
leaq 0x30(%rsp), %rdi
callq 0xed680
jmp 0xe80b9
jmp 0xe80a0
movb $0x1, 0x107(%rsp)
movb 0x107(%rsp), %al
andb $0x1, %al
addq $0x108, %rsp            # imm = 0x108
retq
movq 0x88(%rsp), %rdi
callq 0x12c20
nopw %cs:(%rax,%rax)