// File: /workspace/github_c_makefile_star2_O2/canboat[P]canboat/analyzer/print.c
// Function: extractNumber
bool extractNumber(const Field   *field,
                   const uint8_t *data,
                   size_t         dataLen,
                   size_t         startBit,
                   size_t         bits,
                   int64_t       *value,
                   int64_t       *maxValue)
{
  const bool  hasSign = field ? field->hasSign : false;
  const char *name    = field ? field->name : "<bits>";

  size_t   firstBit;
  size_t   bitsRemaining = bits;
  size_t   magnitude     = 0;
  size_t   bitsInThisByte;
  uint64_t bitMask;
  uint64_t allOnes;
  uint64_t valueInThisByte;
  uint64_t maxv;

  logDebug("extractNumber <%s> startBit=%zu bits=%zu\n", name, startBit, bits);

  if (!adjustDataLenStart(&data, &dataLen, &startBit))
  {
    return false;
  }

  firstBit = startBit;
  *value   = 0;
  maxv     = 0;

  while (bitsRemaining > 0 && dataLen > 0)
  {
    bitsInThisByte = min(8 - firstBit, bitsRemaining);
    allOnes        = (uint64_t) ((((uint64_t) 1) << bitsInThisByte) - 1);

    // How are bits ordered in bytes for bit fields? There are two ways, first field at LSB or first
    // field as MSB.
    // Experimentation, using the 129026 PGN, has shown that the most likely candidate is LSB.
    bitMask         = allOnes << firstBit;
    valueInThisByte = (*data & bitMask) >> firstBit;

    *value |= valueInThisByte << magnitude;
    maxv |= allOnes << magnitude;

    magnitude += bitsInThisByte;
    bitsRemaining -= bitsInThisByte;
    firstBit += bitsInThisByte;
    if (firstBit >= 8)
    {
      firstBit -= 8;
      data++;
      dataLen--;
    }
  }
  if (bitsRemaining > 0)
  {
    logDebug("Insufficient length in PGN to fill field '%s'\n", name);
    return false;
  }

  if (hasSign)
  {
    maxv >>= 1;

    if (field && field->offset) /* J1939 Excess-K notation */
    {
      *value += field->offset;
      maxv += field->offset;
    }
    else
    {
      bool negative = (*value & (((uint64_t) 1) << (bits - 1))) > 0;

      if (negative)
      {
        /* Sign extend value for cases where bits < 64 */
        /* Assume we have bits = 16 and value = -2 then we do: */
        /* 0000.0000.0000.0000.0111.1111.1111.1101 value    */
        /* 0000.0000.0000.0000.0111.1111.1111.1111 maxvalue */
        /* 1111.1111.1111.1111.1000.0000.0000.0000 ~maxvalue */
        *value |= ~maxv;
      }
    }
  }
  else
  {
    if (field && field->offset) /* J1939 Excess-K notation */
    {
      *value += field->offset;
      maxv += field->offset;
    }
  }

  *maxValue = (int64_t) maxv;

  logDebug("extractNumber <%s> startBit=%zu bits=%zu value=%" PRId64 " (%" PRIx64 ") max=%" PRId64 "\n",
           name,
           startBit,
           bits,
           *value,
           *value,
           *maxValue);

  return true;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %r9, %r12
movq %r8, %r14
movq %rcx, %r13
movq %rdx, %rbp
movq %rsi, %r15
testq %rdi, %rdi
movq %rdi, 0x20(%rsp)
je 0x1940e
cmpb $0x0, 0x49(%rdi)
sete 0x17(%rsp)
movq (%rdi), %rsi
jmp 0x1941a
leaq 0x132dc(%rip), %rsi     # 0x2c6f1
movb $0x1, 0x17(%rsp)
leaq 0x132d7(%rip), %rdi     # 0x2c6f8
xorl %ebx, %ebx
movq %rsi, 0x28(%rsp)
movq %r13, %rdx
movq %r14, %rcx
xorl %eax, %eax
callq 0x1bd48
movq %r13, %rax
shrq $0x3, %rax
subq %rax, %rbp
jbe 0x1958b
movq %r13, %rdx
movq 0x70(%rsp), %r13
addq %rax, %r15
andq $0x0, (%r12)
andl $0x7, %edx
xorl %r8d, %r8d
pushq $0x8
popq %r10
movq %r14, %rbx
pushq $-0x1
popq %r14
xorl %eax, %eax
movq %rbx, 0x18(%rsp)
movq %rdx, 0x30(%rsp)
xorl %r9d, %r9d
testq %rbx, %rbx
je 0x194e2
testq %rbp, %rbp
je 0x194e2
movq %r10, %rsi
subq %rdx, %rsi
cmpq %rbx, %rsi
cmovaeq %rbx, %rsi
movq %r14, %rdi
movl %esi, %ecx
shlq %cl, %rdi
notq %rdi
movq %rdi, %r11
movl %edx, %ecx
shlq %cl, %r11
movzbl (%r15), %ecx
andl %ecx, %r11d
movl %edx, %ecx
shrq %cl, %r11
movl %eax, %ecx
shlq %cl, %r11
orq %r11, %r8
movq %r8, (%r12)
shlq %cl, %rdi
orq %rdi, %r9
addq %rsi, %rax
subq %rsi, %rbx
leaq (%rsi,%rdx), %rcx
xorl %edi, %edi
cmpq $0x8, %rcx
setae %dil
leaq -0x8(%rsi,%rdx), %rdx
cmovbq %rcx, %rdx
addq %rdi, %r15
subq %rdi, %rbp
jmp 0x19475
testq %rbx, %rbx
je 0x19501
leaq 0x13234(%rip), %rdi     # 0x2c722
xorl %ebx, %ebx
movq 0x28(%rsp), %rsi
xorl %eax, %eax
callq 0x1bd48
jmp 0x1958b
cmpb $0x0, 0x17(%rsp)
movq 0x28(%rsp), %rsi
je 0x19527
movq 0x20(%rsp), %rax
testq %rax, %rax
movq 0x18(%rsp), %rcx
je 0x19567
movslq 0x28(%rax), %rax
testq %rax, %rax
jne 0x19542
jmp 0x19567
shrq %r9
movq 0x20(%rsp), %rax
testq %rax, %rax
movq 0x18(%rsp), %rcx
je 0x1954e
movslq 0x28(%rax), %rax
testq %rax, %rax
je 0x1954e
addq %rax, %r8
movq %r8, (%r12)
addq %rax, %r9
jmp 0x19567
leal -0x1(%rcx), %eax
movzbl %al, %eax
btq %rax, %r8
jae 0x19567
movq %r9, %rax
notq %rax
orq %rax, %r8
movq %r8, (%r12)
movq %r9, (%r13)
movq (%r12), %r8
movq %r9, (%rsp)
leaq 0x131d7(%rip), %rdi     # 0x2c751
movq 0x30(%rsp), %rdx
movq %r8, %r9
xorl %eax, %eax
callq 0x1bd48
movb $0x1, %bl
movl %ebx, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq