// File: /workspace/github_c_makefile_star2_O1/patriciogonzalezvivo[P]tprint/include/serial/unix.cc
// Function: serial::Serial::SerialImpl::read(unsigned char*, unsigned long)
size_t
Serial::SerialImpl::read (uint8_t *buf, size_t size)
{
  // If the port is not open, throw
  if (!is_open_) {
    throw PortNotOpenedException ("Serial::read");
  }
  size_t bytes_read = 0;

  // Calculate total timeout in milliseconds t_c + (t_m * N)
  long total_timeout_ms = timeout_.read_timeout_constant;
  total_timeout_ms += timeout_.read_timeout_multiplier * static_cast<long> (size);
  MillisecondTimer total_timeout(total_timeout_ms);

  // Pre-fill buffer with available bytes
  {
    ssize_t bytes_read_now = ::read (fd_, buf, size);
    if (bytes_read_now > 0) {
      bytes_read = bytes_read_now;
    }
  }

  while (bytes_read < size) {
    int64_t timeout_remaining_ms = total_timeout.remaining();
    if (timeout_remaining_ms <= 0) {
      // Timed out
      break;
    }
    // Timeout for the next select is whichever is less of the remaining
    // total read timeout and the inter-byte timeout.
    uint32_t timeout = std::min(static_cast<uint32_t> (timeout_remaining_ms),
                                timeout_.inter_byte_timeout);
    // Wait for the device to be readable, and then attempt to read.
    if (waitReadable(timeout)) {
      // If it's a fixed-length multi-byte read, insert a wait here so that
      // we can attempt to grab the whole thing in a single IO call. Skip
      // this wait if a non-max inter_byte_timeout is specified.
      if (size > 1 && timeout_.inter_byte_timeout == Timeout::max()) {
        size_t bytes_available = available();
        if (bytes_available + bytes_read < size) {
          waitByteTimes(size - (bytes_available + bytes_read));
        }
      }
      // This should be non-blocking returning only what is available now
      //  Then returning so that select can block again.
      ssize_t bytes_read_now =
        ::read (fd_, buf + bytes_read, size - bytes_read);
      // read should always return some data as select reported it was
      // ready to read when we get to this point.
      if (bytes_read_now < 1) {
        // Disconnected devices, at least on Linux, show the
        // behavior that they are always ready to read immediately
        // but reading returns nothing.
        throw SerialException ("device reports readiness to read but "
                               "returned no data (device disconnected?)");
      }
      // Update bytes_read
      bytes_read += static_cast<size_t> (bytes_read_now);
      // If bytes_read == size then we have read everything we need
      if (bytes_read == size) {
        break;
      }
      // If bytes_read < size then we have more to read
      if (bytes_read < size) {
        continue;
      }
      // If bytes_read > size then we have over read, which shouldn't happen
      if (bytes_read > size) {
        throw SerialException ("read over read, too many bytes where "
                               "read, this shouldn't happen, might be "
                               "a logical error!");
      }
    }
  }
  return bytes_read;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
cmpb $0x0, 0x2c(%rdi)
je 0xc9fd
movq %rdx, %r14
movq %rsi, %r12
movq %rdi, %r15
movl 0x38(%rdi), %esi
imull %r14d, %esi
addl 0x34(%rdi), %esi
leaq -0x58(%rbp), %rbx
movq %rbx, %rdi
callq 0xb720
movl 0x28(%r15), %edi
movq %r12, -0x40(%rbp)
movq %r12, %rsi
movq %r14, %rdx
callq 0x84b0
movq %rax, %r12
xorl %eax, %eax
testq %r12, %r12
cmovleq %rax, %r12
movq (%rbx), %rax
movq %rax, -0x48(%rbp)
movq 0x8(%rbx), %r13
movq %r14, %rbx
subq %r12, %rbx
jbe 0xc99b
xorl %edi, %edi
leaq -0x38(%rbp), %rsi
callq 0x82d0
movq -0x48(%rbp), %rax
subq -0x38(%rbp), %rax
movq %r13, %rcx
subq -0x30(%rbp), %rcx
xorps %xmm0, %xmm0
cvtsi2sd %rax, %xmm0
mulsd 0x1488e(%rip), %xmm0    # 0x21168
cvttsd2si %xmm0, %rax
xorps %xmm0, %xmm0
cvtsi2sd %rcx, %xmm0
divsd 0x14871(%rip), %xmm0    # 0x21160
xorps %xmm1, %xmm1
cvtsi2sd %rax, %xmm1
addsd %xmm0, %xmm1
cvttsd2si %xmm1, %rax
testq %rax, %rax
jle 0xc98d
movl 0x30(%r15), %esi
cmpl %eax, %esi
jb 0xc913
movl %eax, %esi
movq %r15, %rdi
callq 0xc5f2
testb %al, %al
je 0xc991
cmpq $0x2, %r14
jb 0xc967
cmpl $-0x1, 0x30(%r15)
jne 0xc967
movq %r15, %rdi
callq 0xc514
addq %r12, %rax
movq %r14, %rcx
subq %rax, %rcx
jbe 0xc967
movq $0x0, -0x38(%rbp)
movl 0x50(%r15), %eax
imulq %rax, %rcx
movq %rcx, -0x30(%rbp)
xorl %edi, %edi
xorl %esi, %esi
xorl %edx, %edx
xorl %ecx, %ecx
leaq -0x38(%rbp), %r8
xorl %r9d, %r9d
callq 0x8370
movl 0x28(%r15), %edi
movq -0x40(%rbp), %rax
leaq (%rax,%r12), %rsi
movq %rbx, %rdx
callq 0x84b0
testq %rax, %rax
jle 0xc9cb
addq %rax, %r12
cmpq %r14, %r12
sete %al
jbe 0xc993
jmp 0xc9ad
movb $0x1, %al
jmp 0xc993
xorl %eax, %eax
testb %al, %al
je 0xc8a4
movq %r12, %rax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x28, %edi
callq 0x81a0
movq %rax, %rbx
leaq 0x149a0(%rip), %rsi     # 0x21361
movq %rax, %rdi
callq 0xe21e
jmp 0xc9e7
movl $0x28, %edi
callq 0x81a0
movq %rax, %rbx
leaq 0x14935(%rip), %rsi     # 0x21314
movq %rax, %rdi
callq 0xe21e
leaq 0x1b2b2(%rip), %rsi     # 0x27ca0
leaq 0x1991(%rip), %rdx      # 0xe386
movq %rbx, %rdi
callq 0x85c0
movl $0x28, %edi
callq 0x81a0
movq %rax, %rbx
leaq 0x148f6(%rip), %rsi     # 0x21307
movq %rax, %rdi
callq 0xe848
leaq 0x1b2b0(%rip), %rsi     # 0x27cd0
leaq 0x1f89(%rip), %rdx      # 0xe9b0
jmp 0xc9f5
jmp 0xca2d
jmp 0xca2d
movq %rax, %r14
movq %rbx, %rdi
callq 0x8250
movq %r14, %rdi
callq 0x8600