// File: /workspace/github_c_makefile_star2_O3/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 $0x28, %rsp
movq %r9, %r12
movq %r8, %r14
movq %rcx, %r13
movq %rdx, %rbp
movq %rsi, %r15
testq %rdi, %rdi
movq %rdi, 0x18(%rsp)
je 0x1a2fc
cmpb $0x0, 0x49(%rdi)
sete 0xf(%rsp)
movq (%rdi), %rsi
jmp 0x1a308
leaq 0x133ee(%rip), %rsi     # 0x2d6f1
movb $0x1, 0xf(%rsp)
leaq 0x133e9(%rip), %rdi     # 0x2d6f8
xorl %ebx, %ebx
movq %rsi, 0x20(%rsp)
movq %r13, %rdx
movq %r14, %rcx
xorl %eax, %eax
callq 0x1cd55
movq %r13, %rax
shrq $0x3, %rax
cmpq %rax, %rbp
jbe 0x1a49c
andl $0x7, %r13d
testq %r14, %r14
setne %cl
sete %dl
subq %rax, %rbp
movq $0x0, (%r12)
sete %sil
orb %dl, %sil
movq %r13, 0x10(%rsp)
jne 0x1a3e6
addq %rax, %r15
xorl %r8d, %r8d
xorl %edi, %edi
movq %r14, %rbx
xorl %edx, %edx
movq %rdi, %r10
movl $0x8, %esi
subq %r13, %rsi
cmpq %r14, %rsi
cmovaeq %r14, %rsi
movq $-0x1, %rdi
movl %esi, %ecx
shlq %cl, %rdi
movq %r8, %r11
notq %rdi
movq %rdi, %r8
movl %r13d, %ecx
shlq %cl, %r8
movzbl (%r15), %ecx
andl %ecx, %r8d
movl %r13d, %ecx
shrq %cl, %r8
movl %edx, %ecx
shlq %cl, %r8
shlq %cl, %rdi
orq %r11, %r8
movq %r8, (%r12)
orq %r10, %rdi
leaq (%rsi,%r13), %rcx
xorl %r10d, %r10d
cmpq $0x8, %rcx
setae %r11b
leaq -0x8(%rsi,%r13), %r13
cmovbq %rcx, %r13
subq %rsi, %r14
setne %cl
je 0x1a3ee
addq %rsi, %rdx
movb %r11b, %r10b
addq %r10, %r15
subq %r10, %rbp
jne 0x1a36a
jmp 0x1a3ee
movq %r14, %rbx
xorl %r8d, %r8d
xorl %edi, %edi
testb %cl, %cl
je 0x1a40c
leaq 0x13329(%rip), %rdi     # 0x2d722
xorl %ebx, %ebx
movq 0x20(%rsp), %rsi
xorl %eax, %eax
callq 0x1cd55
jmp 0x1a49c
movq 0x60(%rsp), %rax
cmpb $0x0, 0xf(%rsp)
je 0x1a435
movq 0x18(%rsp), %rsi
testq %rsi, %rsi
movq %rbx, %rcx
movq 0x10(%rsp), %rdx
je 0x1a479
movslq 0x28(%rsi), %rsi
testq %rsi, %rsi
jne 0x1a453
jmp 0x1a479
shrq %rdi
movq 0x18(%rsp), %rsi
testq %rsi, %rsi
movq %rbx, %rcx
movq 0x10(%rsp), %rdx
je 0x1a45f
movslq 0x28(%rsi), %rsi
testq %rsi, %rsi
je 0x1a45f
addq %rsi, %r8
movq %r8, (%r12)
addq %rsi, %rdi
jmp 0x1a479
leal -0x1(%rcx), %esi
movzbl %sil, %esi
btq %rsi, %r8
jae 0x1a479
movq %rdi, %rsi
notq %rsi
orq %rsi, %r8
movq %r8, (%r12)
movq %rdi, (%rax)
movq (%r12), %r8
movq %rdi, (%rsp)
leaq 0x132c6(%rip), %rdi     # 0x2d751
movq 0x20(%rsp), %rsi
movq %r8, %r9
xorl %eax, %eax
callq 0x1cd55
movb $0x1, %bl
movl %ebx, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq