read_data_section (Bit_Chain *sec_dat, Bit_Chain *dat,
                   r2007_section *restrict sections_map,
                   r2007_page *restrict pages_map, Dwg_Section_Type sec_type)
{
  r2007_section *section;
  r2007_page *page;
  uint64_t max_decomp_size;
  BITCODE_RC *decomp;
  int error = 0, i;

  section = get_section (sections_map, sec_type);
  sec_dat->chain = NULL;
  if (section == NULL)
    {
      if (sec_type < SECTION_REVHISTORY
          && sec_type != SECTION_TEMPLATE
          && sec_type != SECTION_OBJFREESPACE)
        {
          LOG_WARN ("Failed to find section_info[%u]", (int)sec_type)
          return DWG_ERR_SECTIONNOTFOUND;
        }
      else
        {
          LOG_TRACE ("Found no section_info[%u]\n", (int)sec_type)
          return DWG_ERR_VALUEOUTOFBOUNDS;
        }
    }

  max_decomp_size = section->data_size;
  if (max_decomp_size > 0x2f000000) // 790Mb
    {
      LOG_ERROR ("Invalid max decompression size %" PRIu64, max_decomp_size);
      return DWG_ERR_INVALIDDWG;
    }
  decomp = (BITCODE_RC *)calloc (max_decomp_size, 1);
  if (decomp == NULL)
    {
      LOG_ERROR ("Out of memory")
      return DWG_ERR_OUTOFMEM;
    }
  LOG_HANDLE ("Alloc data section of size %" PRIu64 "\n", max_decomp_size)

  sec_dat->bit = 0;
  sec_dat->byte = 0;
  sec_dat->size = max_decomp_size;
  sec_dat->version = dat->version;
  sec_dat->from_version = dat->from_version;

  for (i = 0; i < (int)section->num_pages; i++)
    {
      r2007_section_page *section_page = section->pages[i];
      page = get_page (pages_map, section_page->id);
      if (page == NULL)
        {
          free (decomp);
          LOG_ERROR ("Failed to find page %d", (int)section_page->id)
          return DWG_ERR_PAGENOTFOUND;
        }
      if (section_page->offset > max_decomp_size)
        {
          free (decomp);
          LOG_ERROR ("Invalid section_page->offset %ld > %ld",
                     (long)section_page->offset, (long)max_decomp_size)
          return DWG_ERR_VALUEOUTOFBOUNDS;
        }
      if (max_decomp_size < section_page->uncomp_size)
        {
          free (decomp);
          LOG_ERROR ("Invalid section size %ld < %ld",
                     (long)max_decomp_size, (long)section_page->uncomp_size)
          return DWG_ERR_VALUEOUTOFBOUNDS;
        }

      dat->byte = page->offset;
      // only if compressed. TODO: Isn't there a compressed flag as with 2004+?
      // theoretically the sizes could still be the same.
      if (section_page->comp_size != section_page->uncomp_size)
        {
          error = read_data_page (dat, &decomp[section_page->offset],
                                  page->size, section_page->comp_size,
                                  section_page->uncomp_size);
          if (error)
            {
              free (decomp);
              LOG_ERROR ("Failed to read compressed page")
              return error;
            }
        }
      else
        {
          memcpy (&decomp[section_page->offset], &dat->chain[dat->byte],
                  section_page->uncomp_size);
        }
    }
  sec_dat->chain = decomp;
  return 0;
}
read_data_section (Bit_Chain *sec_dat, Bit_Chain *dat,
                   r2007_section *restrict sections_map,
                   r2007_page *restrict pages_map, Dwg_Section_Type sec_type)
{
  r2007_section *section;
  r2007_page *page;
  uint64_t max_decomp_size;
  BITCODE_RC *decomp;
  int error = 0, i;

  section = get_section (sections_map, sec_type);
  sec_dat->chain = NULL;
  if (section == NULL)
    {
      if (sec_type < SECTION_REVHISTORY
          && sec_type != SECTION_TEMPLATE
          && sec_type != SECTION_OBJFREESPACE)
        {
          LOG_WARN ("Failed to find section_info[%u]", (int)sec_type)
          return DWG_ERR_SECTIONNOTFOUND;
        }
      else
        {
          LOG_TRACE ("Found no section_info[%u]\n", (int)sec_type)
          return DWG_ERR_VALUEOUTOFBOUNDS;
        }
    }

  max_decomp_size = section->data_size;
  if (max_decomp_size > 0x2f000000)  
    {
      LOG_ERROR ("Invalid max decompression size %" PRIu64, max_decomp_size);
      return DWG_ERR_INVALIDDWG;
    }
  decomp = (BITCODE_RC *)calloc (max_decomp_size, 1);
  if (decomp == NULL)
    {
      LOG_ERROR ("Out of memory")
      return DWG_ERR_OUTOFMEM;
    }
  LOG_HANDLE ("Alloc data section of size %" PRIu64 "\n", max_decomp_size)

  sec_dat->bit = 0;
  sec_dat->byte = 0;
  sec_dat->size = max_decomp_size;
  sec_dat->version = dat->version;
  sec_dat->from_version = dat->from_version;

  for (i = 0; i < (int)section->num_pages; i++)
    {
      r2007_section_page *section_page = section->pages[i];
      page = get_page (pages_map, section_page->id);
      if (page == NULL)
        {
          free (decomp);
          LOG_ERROR ("Failed to find page %d", (int)section_page->id)
          return DWG_ERR_PAGENOTFOUND;
        }
      if (section_page->offset > max_decomp_size)
        {
          free (decomp);
          LOG_ERROR ("Invalid section_page->offset %ld > %ld",
                     (long)section_page->offset, (long)max_decomp_size)
          return DWG_ERR_VALUEOUTOFBOUNDS;
        }
      if (max_decomp_size < section_page->uncomp_size)
        {
          free (decomp);
          LOG_ERROR ("Invalid section size %ld < %ld",
                     (long)max_decomp_size, (long)section_page->uncomp_size)
          return DWG_ERR_VALUEOUTOFBOUNDS;
        }

      dat->byte = page->offset;
       
       
      if (section_page->comp_size != section_page->uncomp_size)
        {
          error = read_data_page (dat, &decomp[section_page->offset],
                                  page->size, section_page->comp_size,
                                  section_page->uncomp_size);
          if (error)
            {
              free (decomp);
              LOG_ERROR ("Failed to read compressed page")
              return error;
            }
        }
      else
        {
          memcpy (&decomp[section_page->offset], &dat->chain[dat->byte],
                  section_page->uncomp_size);
        }
    }
  sec_dat->chain = decomp;
  return 0;
}