// File: /workspace/github_c_makefile_star2_O1/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, %r14
movq %r8, %r12
movq %rcx, %r15
movq %rdx, %r13
movq %rsi, %rbp
testq %rdi, %rdi
je 0x22964
cmpb $0x0, 0x49(%rdi)
sete 0x17(%rsp)
jmp 0x22969
movb $0x1, 0x17(%rsp)
testq %rdi, %rdi
movq %rdi, 0x18(%rsp)
je 0x22978
movq (%rdi), %rsi
jmp 0x2297f
leaq 0x18002(%rip), %rsi     # 0x3a981
leaq 0x18002(%rip), %rdi     # 0x3a988
xorl %ebx, %ebx
movq %rsi, 0x20(%rsp)
movq %r15, %rdx
movq %r12, %rcx
xorl %eax, %eax
callq 0x254dd
movq %r15, %rax
shrq $0x3, %rax
movl %r15d, %edx
andl $0x7, %edx
cmpq %rax, %r13
cmovbeq %r15, %rdx
jbe 0x22b05
testq %r12, %r12
setne %cl
sete %sil
subq %rax, %r13
movq $0x0, (%r14)
sete %dil
orb %sil, %dil
jne 0x22a5e
addq %rax, %rbp
movq (%r14), %r8
xorl %r9d, %r9d
movq %rdx, %rax
movq %r12, %r15
xorl %esi, %esi
movq %r9, %r11
movl $0x8, %edi
subq %rax, %rdi
cmpq %r12, %rdi
cmovaeq %r12, %rdi
movq $-0x1, %r9
movl %edi, %ecx
shlq %cl, %r9
movq %r8, %rbx
notq %r9
movq %r9, %r8
movl %eax, %ecx
shlq %cl, %r8
movzbl (%rbp), %ecx
andl %ecx, %r8d
movl %eax, %ecx
shrq %cl, %r8
movl %esi, %ecx
shlq %cl, %r8
shlq %cl, %r9
orq %rbx, %r8
movq %r8, (%r14)
orq %r11, %r9
leaq (%rdi,%rax), %rcx
xorl %r11d, %r11d
cmpq $0x8, %rcx
setae %bl
leaq -0x8(%rdi,%rax), %rax
cmovbq %rcx, %rax
subq %rdi, %r12
setne %cl
je 0x22a64
addq %rdi, %rsi
movb %bl, %r11b
addq %r11, %rbp
subq %r11, %r13
jne 0x229e6
jmp 0x22a64
movq %r12, %r15
xorl %r9d, %r9d
testb %cl, %cl
je 0x22a82
leaq 0x17f43(%rip), %rdi     # 0x3a9b2
xorl %ebx, %ebx
movq 0x20(%rsp), %rsi
xorl %eax, %eax
callq 0x254dd
jmp 0x22b05
movq 0x60(%rsp), %rax
cmpb $0x0, 0x17(%rsp)
je 0x22aa6
movq 0x18(%rsp), %rsi
testq %rsi, %rsi
movq %r15, %rcx
je 0x22ae3
movslq 0x28(%rsi), %rsi
testq %rsi, %rsi
jne 0x22abf
jmp 0x22ae3
shrq %r9
movq 0x18(%rsp), %rsi
testq %rsi, %rsi
movq %r15, %rcx
je 0x22ac7
movslq 0x28(%rsi), %rsi
testq %rsi, %rsi
je 0x22ac7
addq %rsi, (%r14)
addq %rsi, %r9
jmp 0x22ae3
movq (%r14), %rdi
leal -0x1(%rcx), %esi
movzbl %sil, %esi
btq %rsi, %rdi
jae 0x22ae3
movq %r9, %rsi
notq %rsi
orq %rsi, %rdi
movq %rdi, (%r14)
movq %r9, (%rax)
movq (%r14), %r8
movq %r9, (%rsp)
leaq 0x17eed(%rip), %rdi     # 0x3a9e1
movq 0x20(%rsp), %rsi
movq %r8, %r9
xorl %eax, %eax
callq 0x254dd
movb $0x1, %bl
movl %ebx, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq