// File: /workspace/github_c_makefile_star2_O3/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 $0x28, %rsp
cmpb $0x0, 0x2c(%rdi)
je 0xc932
movq %rdx, %rbx
movq %rsi, %r12
movq %rdi, %r15
movl 0x38(%rdi), %esi
imull %ebx, %esi
addl 0x34(%rdi), %esi
leaq -0x50(%rbp), %rdi
callq 0xb6d0
movl 0x28(%r15), %edi
movq %r12, %rsi
movq %rbx, %rdx
callq 0x84a0
xorl %r14d, %r14d
testq %rax, %rax
cmovgq %rax, %r14
cmpq %rbx, %r14
jae 0xc8cb
movq %r12, -0x40(%rbp)
movq -0x50(%rbp), %r13
movq -0x48(%rbp), %r12
xorl %edi, %edi
leaq -0x38(%rbp), %rsi
callq 0x82c0
movq %r13, %rax
subq -0x38(%rbp), %rax
movq %r12, %rcx
subq -0x30(%rbp), %rcx
xorps %xmm0, %xmm0
cvtsi2sd %rax, %xmm0
mulsd 0x13963(%rip), %xmm0    # 0x20168
cvttsd2si %xmm0, %rax
xorps %xmm0, %xmm0
cvtsi2sd %rcx, %xmm0
divsd 0x13946(%rip), %xmm0    # 0x20160
xorps %xmm1, %xmm1
cvtsi2sd %rax, %xmm1
addsd %xmm0, %xmm1
cvttsd2si %xmm1, %rax
testq %rax, %rax
jle 0xc8cb
movl 0x30(%r15), %esi
cmpl %eax, %esi
jb 0xc83e
movl %eax, %esi
movq %r15, %rdi
callq 0xc530
testb %al, %al
je 0xc8ba
cmpq $0x2, %rbx
jb 0xc892
cmpl $-0x1, 0x30(%r15)
jne 0xc892
movq %r15, %rdi
callq 0xc456
addq %r14, %rax
movq %rbx, %rcx
subq %rax, %rcx
jbe 0xc892
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 0x8360
movl 0x28(%r15), %edi
movq -0x40(%rbp), %rax
leaq (%rax,%r14), %rsi
movq %rbx, %rdx
subq %r14, %rdx
callq 0x84a0
testq %rax, %rax
jle 0xc8e2
addq %r14, %rax
cmpq %rbx, %rax
je 0xc8dd
jbe 0xc8bd
jmp 0xc900
movq %r14, %rax
movq %rax, %r14
cmpq %rbx, %rax
jb 0xc7dc
jmp 0xc8ce
movq %r14, %rax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rbx, %rax
jmp 0xc8ce
movl $0x28, %edi
callq 0x8190
movq %rax, %rbx
leaq 0x13a1e(%rip), %rsi     # 0x20314
movq %rax, %rdi
callq 0xe0e2
jmp 0xc91c
movl $0x28, %edi
callq 0x8190
movq %rax, %rbx
leaq 0x13a4d(%rip), %rsi     # 0x20361
movq %rax, %rdi
callq 0xe0e2
leaq 0x1a365(%rip), %rsi     # 0x26c88
leaq 0x1920(%rip), %rdx      # 0xe24a
movq %rbx, %rdi
callq 0x85b0
movl $0x28, %edi
callq 0x8190
movq %rax, %rbx
leaq 0x139c1(%rip), %rsi     # 0x20307
movq %rax, %rdi
callq 0xe70c
leaq 0x1a363(%rip), %rsi     # 0x26cb8
leaq 0x1f18(%rip), %rdx      # 0xe874
jmp 0xc92a
jmp 0xc962
jmp 0xc962
movq %rax, %r14
movq %rbx, %rdi
callq 0x8240
movq %r14, %rdi
callq 0x85f0
nop