// File: jBlinden[P]private-codis/protocol.cpp
// Function: SendLargePacked(CSocket*, unsigned char, unsigned long, unsigned char*)
void SendLargePacked(CSocket* socket, uint8_t bitsPerMsg, uint64_t length, uint8_t* data){
  //Assumes bitsPerMsg <= 8
  uint64_t newLength = packLength(length, bitsPerMsg);
  uint8_t* buffer = new uint8_t[newLength];
  memset(buffer, 0, newLength);
  
  uint8_t bitPointer = 0;
  uint64_t index = 0;

  for (int i = 0; i < length; i++){
    if (bitPointer + bitsPerMsg <= 8){
      buffer[index] += data[i] << bitPointer;
      bitPointer += bitsPerMsg;
      if (bitPointer == 8){
        index += 1;
        bitPointer = 0;
      }
    }
    else{
      uint8_t rightBits = 8 - bitPointer;
      uint8_t mask = (1 << rightBits) - 1;
      buffer[index] += (data[i] & mask) << bitPointer;
      
      index += 1;
      buffer[index] =  data[i] >> rightBits;
      bitPointer = bitsPerMsg - rightBits;
    }
  }

#if LOGGING
  struct timespec start, stop;
  uint64_t duration;
  clock_gettime(CLOCK_REALTIME, &start);
#endif

  socket->SendLarge(buffer, newLength);

#if LOGGING
  clock_gettime(CLOCK_REALTIME, &stop);
  duration = (stop.tv_sec - start.tv_sec) * BILLION + stop.tv_nsec - start.tv_nsec;
  cout << "Time to send: " << duration << " ns with size: " << newLength << endl;
#endif
  
  delete[] buffer;
}

// Assembly:
subq $0x58, %rsp
movb %sil, %al
movq %rdi, 0x50(%rsp)
movb %al, 0x4f(%rsp)
movq %rdx, 0x40(%rsp)
movq %rcx, 0x38(%rsp)
movq 0x40(%rsp), %rdi
movzbl 0x4f(%rsp), %esi
callq 0x6f20
movq %rax, 0x30(%rsp)
movq 0x30(%rsp), %rdi
callq 0x3030
movq %rax, 0x28(%rsp)
movq 0x28(%rsp), %rdi
movq 0x30(%rsp), %rdx
xorl %esi, %esi
callq 0x3170
movb $0x0, 0x27(%rsp)
movq $0x0, 0x18(%rsp)
movl $0x0, 0x14(%rsp)
movslq 0x14(%rsp), %rax
cmpq 0x40(%rsp), %rax
jae 0x7e25
movzbl 0x27(%rsp), %eax
movzbl 0x4f(%rsp), %ecx
addl %ecx, %eax
cmpl $0x8, %eax
jg 0x7d7f
movq 0x38(%rsp), %rax
movslq 0x14(%rsp), %rcx
movzbl (%rax,%rcx), %esi
movzbl 0x27(%rsp), %ecx
shll %cl, %esi
movq 0x28(%rsp), %rax
movq 0x18(%rsp), %rcx
movzbl (%rax,%rcx), %edx
addl %esi, %edx
movb %dl, (%rax,%rcx)
movzbl 0x4f(%rsp), %ecx
movzbl 0x27(%rsp), %eax
addl %ecx, %eax
movb %al, 0x27(%rsp)
movzbl 0x27(%rsp), %eax
cmpl $0x8, %eax
jne 0x7d7a
movq 0x18(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x18(%rsp)
movb $0x0, 0x27(%rsp)
jmp 0x7e13
movzbl 0x27(%rsp), %ecx
movl $0x8, %eax
subl %ecx, %eax
movb %al, 0x13(%rsp)
movzbl 0x13(%rsp), %ecx
movl $0x1, %eax
shll %cl, %eax
subl $0x1, %eax
movb %al, 0x12(%rsp)
movq 0x38(%rsp), %rax
movslq 0x14(%rsp), %rcx
movzbl (%rax,%rcx), %esi
movzbl 0x12(%rsp), %eax
andl %eax, %esi
movzbl 0x27(%rsp), %ecx
shll %cl, %esi
movq 0x28(%rsp), %rax
movq 0x18(%rsp), %rcx
movzbl (%rax,%rcx), %edx
addl %esi, %edx
movb %dl, (%rax,%rcx)
movq 0x18(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x18(%rsp)
movq 0x38(%rsp), %rax
movslq 0x14(%rsp), %rcx
movzbl (%rax,%rcx), %eax
movzbl 0x13(%rsp), %ecx
sarl %cl, %eax
movb %al, %dl
movq 0x28(%rsp), %rax
movq 0x18(%rsp), %rcx
movb %dl, (%rax,%rcx)
movzbl 0x4f(%rsp), %eax
movzbl 0x13(%rsp), %ecx
subl %ecx, %eax
movb %al, 0x27(%rsp)
jmp 0x7e15
movl 0x14(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x14(%rsp)
jmp 0x7d04
movq 0x50(%rsp), %rdi
movq 0x28(%rsp), %rsi
movq 0x30(%rsp), %rdx
callq 0x84d0
movq 0x28(%rsp), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, %rax
je 0x7e53
movq 0x8(%rsp), %rdi
callq 0x3370
addq $0x58, %rsp
retq
nopl (%rax,%rax)