decompress_R2004_section (Bit_Chain *restrict dat, BITCODE_RC *restrict decomp,
                          uint32_t decomp_data_size, uint32_t comp_data_size)
{
  unsigned int i, lit_length;
  uint32_t comp_offset, comp_bytes, bytes_left;
  unsigned char opcode1 = 0, opcode2;
  long unsigned int start_byte = dat->byte;
  BITCODE_RC *src, *dst = decomp;
  BITCODE_RC *maxdst = decomp + decomp_data_size;

  bytes_left = decomp_data_size;               // to write to
  if (comp_data_size > dat->size - start_byte) // bytes left to read from
    {
      LOG_WARN ("Invalid comp_data_size %lu > %lu bytes left",
                (unsigned long)bytes_left, dat->size - dat->byte)
      return DWG_ERR_VALUEOUTOFBOUNDS;
    }
  // length of the first sequence of uncompressed or literal data.
  lit_length = read_literal_length (dat, &opcode1);
  if (lit_length > bytes_left)
    {
      LOG_ERROR ("Invalid literal_length %u > %u bytes left",
                 lit_length, (unsigned)decomp_data_size)
      return DWG_ERR_VALUEOUTOFBOUNDS;
    }
  bit_read_fixed (dat, decomp, lit_length);
  dst += lit_length;
  bytes_left -= lit_length;

  opcode1 = 0x00;
  while (dat->byte - start_byte < comp_data_size)
    {
      LOG_INSANE ("-O %x ", opcode1)
      if (opcode1 == 0x00)
        {
          opcode1 = bit_read_RC (dat);
          LOG_INSANE ("<O %x ", opcode1)
        }

      if (opcode1 >= 0x40)
        {
          comp_bytes = ((opcode1 & 0xF0) >> 4) - 1;
          opcode2 = bit_read_RC (dat);
          LOG_INSANE ("<O %x ", opcode2)
          comp_offset = (opcode2 << 2) | ((opcode1 & 0x0C) >> 2);

          if (opcode1 & 0x03)
            {
              lit_length = (opcode1 & 0x03);
              opcode1 = 0x00;
            }
          else
            lit_length = read_literal_length (dat, &opcode1);
        }
      else if (opcode1 >= 0x21
               && opcode1 <= 0x3F) // lgtm [cpp/constant-comparison]
        {
          comp_bytes = opcode1 - 0x1E;
          comp_offset = read_two_byte_offset (dat, &lit_length);

          if (lit_length != 0)
            opcode1 = 0x00;
          else
            lit_length = read_literal_length (dat, &opcode1);
        }
      else if (opcode1 == 0x20)
        {
          comp_bytes = read_long_compression_offset (dat) + 0x21;
          comp_offset = read_two_byte_offset (dat, &lit_length);

          if (lit_length != 0)
            opcode1 = 0x00;
          else
            lit_length = read_literal_length (dat, &opcode1);
        }
      else if (opcode1 >= 0x12 && opcode1 <= 0x1F)
        {
          comp_bytes = (opcode1 & 0x0F) + 2;
          comp_offset = read_two_byte_offset (dat, &lit_length) + 0x3FFF;

          if (lit_length != 0)
            opcode1 = 0x00;
          else
            lit_length = read_literal_length (dat, &opcode1);
        }
      else if (opcode1 == 0x10)
        {
          comp_bytes = read_long_compression_offset (dat) + 9;
          comp_offset = read_two_byte_offset (dat, &lit_length) + 0x3FFF;

          if (lit_length != 0)
            opcode1 = 0x00;
          else
            lit_length = read_literal_length (dat, &opcode1);
        }
      else if (opcode1 == 0x11)
        break; // Terminates the input stream, everything is ok
      else
        {
          LOG_ERROR ("Invalid opcode 0x%x in input stream at pos %lu", opcode1,
                     dat->byte);
          return DWG_ERR_INTERNALERROR; // error in input stream
        }

      src = dst - comp_offset - 1;
      if (src < decomp) // was assert (src >= decomp);
        {
          LOG_ERROR ("decompress_R2004_section: src offset underflow");
          return DWG_ERR_INTERNALERROR;
        }
      if (comp_bytes)
        {
          LOG_INSANE ("<C %d ", comp_bytes)
          // copy "compressed data"
          if ((uint32_t)comp_bytes > bytes_left || // bytes left to write
              dst + comp_bytes > maxdst)
            {
              LOG_ERROR ("Invalid comp_bytes %lu > %lu bytes left",
                         (unsigned long)comp_bytes, (unsigned long)bytes_left)
              return DWG_ERR_VALUEOUTOFBOUNDS;
            }
          for (i = 0; i < comp_bytes; ++i)
            *dst++ = *src++;
          bytes_left -= comp_bytes;
        }
      // copy "literal data"
      LOG_INSANE ("<L %d\n", lit_length)
      if (lit_length)
        {
          if ((lit_length > bytes_left) // bytes left to write
              || dst + lit_length > maxdst)       // dst overflow
            {
              LOG_ERROR ("Invalid lit_length %u > %lu bytes left",
                         lit_length, (unsigned long)bytes_left)
              return DWG_ERR_VALUEOUTOFBOUNDS;
            }
          for (i = 0; i < lit_length; ++i)
            *dst++ = bit_read_RC (dat);
        }
    }

  return 0; // Success
}
decompress_R2004_section (Bit_Chain *restrict dat, BITCODE_RC *restrict decomp,
                          uint32_t decomp_data_size, uint32_t comp_data_size)
{
  unsigned int i, lit_length;
  uint32_t comp_offset, comp_bytes, bytes_left;
  unsigned char opcode1 = 0, opcode2;
  long unsigned int start_byte = dat->byte;
  BITCODE_RC *src, *dst = decomp;
  BITCODE_RC *maxdst = decomp + decomp_data_size;

  bytes_left = decomp_data_size;                
  if (comp_data_size > dat->size - start_byte)  
    {
      LOG_WARN ("Invalid comp_data_size %lu > %lu bytes left",
                (unsigned long)bytes_left, dat->size - dat->byte)
      return DWG_ERR_VALUEOUTOFBOUNDS;
    }
   
  lit_length = read_literal_length (dat, &opcode1);
  if (lit_length > bytes_left)
    {
      LOG_ERROR ("Invalid literal_length %u > %u bytes left",
                 lit_length, (unsigned)decomp_data_size)
      return DWG_ERR_VALUEOUTOFBOUNDS;
    }
  bit_read_fixed (dat, decomp, lit_length);
  dst += lit_length;
  bytes_left -= lit_length;

  opcode1 = 0x00;
  while (dat->byte - start_byte < comp_data_size)
    {
      LOG_INSANE ("-O %x ", opcode1)
      if (opcode1 == 0x00)
        {
          opcode1 = bit_read_RC (dat);
          LOG_INSANE ("<O %x ", opcode1)
        }

      if (opcode1 >= 0x40)
        {
          comp_bytes = ((opcode1 & 0xF0) >> 4) - 1;
          opcode2 = bit_read_RC (dat);
          LOG_INSANE ("<O %x ", opcode2)
          comp_offset = (opcode2 << 2) | ((opcode1 & 0x0C) >> 2);

          if (opcode1 & 0x03)
            {
              lit_length = (opcode1 & 0x03);
              opcode1 = 0x00;
            }
          else
            lit_length = read_literal_length (dat, &opcode1);
        }
      else if (opcode1 >= 0x21
               && opcode1 <= 0x3F)  
        {
          comp_bytes = opcode1 - 0x1E;
          comp_offset = read_two_byte_offset (dat, &lit_length);

          if (lit_length != 0)
            opcode1 = 0x00;
          else
            lit_length = read_literal_length (dat, &opcode1);
        }
      else if (opcode1 == 0x20)
        {
          comp_bytes = read_long_compression_offset (dat) + 0x21;
          comp_offset = read_two_byte_offset (dat, &lit_length);

          if (lit_length != 0)
            opcode1 = 0x00;
          else
            lit_length = read_literal_length (dat, &opcode1);
        }
      else if (opcode1 >= 0x12 && opcode1 <= 0x1F)
        {
          comp_bytes = (opcode1 & 0x0F) + 2;
          comp_offset = read_two_byte_offset (dat, &lit_length) + 0x3FFF;

          if (lit_length != 0)
            opcode1 = 0x00;
          else
            lit_length = read_literal_length (dat, &opcode1);
        }
      else if (opcode1 == 0x10)
        {
          comp_bytes = read_long_compression_offset (dat) + 9;
          comp_offset = read_two_byte_offset (dat, &lit_length) + 0x3FFF;

          if (lit_length != 0)
            opcode1 = 0x00;
          else
            lit_length = read_literal_length (dat, &opcode1);
        }
      else if (opcode1 == 0x11)
        break;  
      else
        {
          LOG_ERROR ("Invalid opcode 0x%x in input stream at pos %lu", opcode1,
                     dat->byte);
          return DWG_ERR_INTERNALERROR;  
        }

      src = dst - comp_offset - 1;
      if (src < decomp)  
        {
          LOG_ERROR ("decompress_R2004_section: src offset underflow");
          return DWG_ERR_INTERNALERROR;
        }
      if (comp_bytes)
        {
          LOG_INSANE ("<C %d ", comp_bytes)
           
          if ((uint32_t)comp_bytes > bytes_left ||  
              dst + comp_bytes > maxdst)
            {
              LOG_ERROR ("Invalid comp_bytes %lu > %lu bytes left",
                         (unsigned long)comp_bytes, (unsigned long)bytes_left)
              return DWG_ERR_VALUEOUTOFBOUNDS;
            }
          for (i = 0; i < comp_bytes; ++i)
            *dst++ = *src++;
          bytes_left -= comp_bytes;
        }
       
      LOG_INSANE ("<L %d\n", lit_length)
      if (lit_length)
        {
          if ((lit_length > bytes_left)  
              || dst + lit_length > maxdst)        
            {
              LOG_ERROR ("Invalid lit_length %u > %lu bytes left",
                         lit_length, (unsigned long)bytes_left)
              return DWG_ERR_VALUEOUTOFBOUNDS;
            }
          for (i = 0; i < lit_length; ++i)
            *dst++ = bit_read_RC (dat);
        }
    }

  return 0;  
}