// File: tomfunkhouser[P]gaps/pkgs/RNBasics/json.cpp
// Function: Json::Reader::decodeNumber(Json::Reader::Token&, Json::Value&)
bool Reader::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::maxLargestInt) + 1
                 : 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 && value == maxIntegerValue)
    decoded = Value::minLargestInt;
  else if (isNegative)
    decoded = -Value::LargestInt(value);
  else if (value <= Value::LargestUInt(Value::maxInt))
    decoded = Value::LargestInt(value);
  else
    decoded = value;
  return true;
}

// Assembly:
subq $0x138, %rsp            # imm = 0x138
movq %rdi, 0x128(%rsp)
movq %rsi, 0x120(%rsp)
movq %rdx, 0x118(%rsp)
movq 0x128(%rsp), %rax
movq %rax, 0x30(%rsp)
movq 0x120(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x110(%rsp)
movq 0x110(%rsp), %rax
movsbl (%rax), %eax
cmpl $0x2d, %eax
sete %al
andb $0x1, %al
movb %al, 0x10f(%rsp)
testb $0x1, 0x10f(%rsp)
je 0xe2b18
movq 0x110(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x110(%rsp)
testb $0x1, 0x10f(%rsp)
je 0xe2b34
movq 0x875a7(%rip), %rax     # 0x16a0d0
addq $0x1, %rax
movq %rax, 0x28(%rsp)
jmp 0xe2b40
movq 0x8759d(%rip), %rax     # 0x16a0d8
movq %rax, 0x28(%rsp)
movq 0x28(%rsp), %rax
movq %rax, 0x100(%rsp)
movq 0x100(%rsp), %rax
movl $0xa, %ecx
xorl %edx, %edx
divq %rcx
movq %rax, 0xf8(%rsp)
movq $0x0, 0xf0(%rsp)
movq 0x110(%rsp), %rax
movq 0x120(%rsp), %rcx
cmpq 0x10(%rcx), %rax
jae 0xe2cad
movq 0x110(%rsp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, 0x110(%rsp)
movb (%rax), %al
movb %al, 0xef(%rsp)
movsbl 0xef(%rsp), %eax
cmpl $0x30, %eax
jl 0xe2bc7
movsbl 0xef(%rsp), %eax
cmpl $0x39, %eax
jle 0xe2bef
movq 0x30(%rsp), %rdi
movq 0x120(%rsp), %rsi
movq 0x118(%rsp), %rdx
callq 0xe3370
andb $0x1, %al
movb %al, 0x137(%rsp)
jmp 0xe2e6d
movsbl 0xef(%rsp), %eax
subl $0x30, %eax
movl %eax, 0xe8(%rsp)
movq 0xf0(%rsp), %rax
cmpq 0xf8(%rsp), %rax
jb 0xe2c8d
movq 0xf0(%rsp), %rax
cmpq 0xf8(%rsp), %rax
ja 0xe2c63
movq 0x110(%rsp), %rax
movq 0x120(%rsp), %rcx
cmpq 0x10(%rcx), %rax
jne 0xe2c63
movl 0xe8(%rsp), %eax
movq %rax, 0x20(%rsp)
movq 0x100(%rsp), %rax
movl $0xa, %ecx
xorl %edx, %edx
divq %rcx
movq 0x20(%rsp), %rax
cmpq %rdx, %rax
jbe 0xe2c8b
movq 0x30(%rsp), %rdi
movq 0x120(%rsp), %rsi
movq 0x118(%rsp), %rdx
callq 0xe3370
andb $0x1, %al
movb %al, 0x137(%rsp)
jmp 0xe2e6d
jmp 0xe2c8d
imulq $0xa, 0xf0(%rsp), %rax
movl 0xe8(%rsp), %ecx
addq %rcx, %rax
movq %rax, 0xf0(%rsp)
jmp 0xe2b73
testb $0x1, 0x10f(%rsp)
je 0xe2d2e
movq 0xf0(%rsp), %rax
cmpq 0x100(%rsp), %rax
jne 0xe2d2e
movq 0x87410(%rip), %rsi     # 0x16a0e0
leaq 0xc0(%rsp), %rdi
movq %rdi, 0x18(%rsp)
callq 0xecde0
movq 0x18(%rsp), %rsi
movq 0x118(%rsp), %rdi
callq 0xe3700
jmp 0xe2cf6
leaq 0xc0(%rsp), %rdi
callq 0xed680
jmp 0xe2e65
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb8(%rsp)
movl %eax, 0xb4(%rsp)
leaq 0xc0(%rsp), %rdi
callq 0xed680
jmp 0xe2e7e
testb $0x1, 0x10f(%rsp)
je 0xe2da1
movq 0xf0(%rsp), %rsi
negq %rsi
leaq 0x88(%rsp), %rdi
movq %rdi, 0x10(%rsp)
callq 0xecde0
movq 0x10(%rsp), %rsi
movq 0x118(%rsp), %rdi
callq 0xe3700
jmp 0xe2d69
leaq 0x88(%rsp), %rdi
callq 0xed680
jmp 0xe2e63
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb8(%rsp)
movl %eax, 0xb4(%rsp)
leaq 0x88(%rsp), %rdi
callq 0xed680
jmp 0xe2e7e
movq 0xf0(%rsp), %rax
movslq 0x87338(%rip), %rcx     # 0x16a0e8
cmpq %rcx, %rax
ja 0xe2e0c
movq 0xf0(%rsp), %rsi
leaq 0x60(%rsp), %rdi
movq %rdi, 0x8(%rsp)
callq 0xecde0
movq 0x8(%rsp), %rsi
movq 0x118(%rsp), %rdi
callq 0xe3700
jmp 0xe2de0
leaq 0x60(%rsp), %rdi
callq 0xed680
jmp 0xe2e61
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb8(%rsp)
movl %eax, 0xb4(%rsp)
leaq 0x60(%rsp), %rdi
callq 0xed680
jmp 0xe2e7e
movq 0xf0(%rsp), %rsi
leaq 0x38(%rsp), %rdi
movq %rdi, (%rsp)
callq 0xece20
movq (%rsp), %rsi
movq 0x118(%rsp), %rdi
callq 0xe3700
jmp 0xe2e35
leaq 0x38(%rsp), %rdi
callq 0xed680
jmp 0xe2e61
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb8(%rsp)
movl %eax, 0xb4(%rsp)
leaq 0x38(%rsp), %rdi
callq 0xed680
jmp 0xe2e7e
jmp 0xe2e63
jmp 0xe2e65
movb $0x1, 0x137(%rsp)
movb 0x137(%rsp), %al
andb $0x1, %al
addq $0x138, %rsp            # imm = 0x138
retq
movq 0xb8(%rsp), %rdi
callq 0x12c20
nopl (%rax,%rax)