read_2007_section_classes (Bit_Chain *restrict dat, Dwg_Data *restrict dwg,
                           r2007_section *restrict sections_map,
                           r2007_page *restrict pages_map)
{
  BITCODE_RL size, i;
  BITCODE_BS max_num;
  Bit_Chain sec_dat = { 0 }, str = { 0 };
  Dwg_Object *obj = NULL;
  int error;
  char c;

  error = read_data_section (&sec_dat, dat, sections_map, pages_map,
                             SECTION_CLASSES);
  if (error)
    {
      LOG_ERROR ("Failed to read class section");
      if (sec_dat.chain)
        free (sec_dat.chain);
      return error;
    }

  if (bit_search_sentinel (&sec_dat, dwg_sentinel (DWG_SENTINEL_CLASS_BEGIN)))
    {
      BITCODE_RL bitsize = 0;
      LOG_TRACE ("\nClasses\n-------------------\n")
      size = bit_read_RL (&sec_dat); // size of class data area
      LOG_TRACE ("size: " FORMAT_RL " [RL]\n", size)
      /*
      if (dat->from_version >= R_2010 && dwg->header.maint_version > 3)
        {
          BITCODE_RL hsize = bit_read_RL(&sec_dat);
          LOG_TRACE("hsize: " FORMAT_RL " [RL]\n", hsize)
        }
      */
      if (dat->from_version >= R_2007)
        {
          bitsize = bit_read_RL (&sec_dat);
          LOG_TRACE ("bitsize: " FORMAT_RL " [RL]\n", bitsize)
        }
      max_num = bit_read_BS (&sec_dat); // Maximum class number
      LOG_TRACE ("max_num: " FORMAT_BS " [BS]\n", max_num)
      c = bit_read_RC (&sec_dat); // 0x00
      LOG_HANDLE ("c: " FORMAT_RC " [RC]\n", c)
      c = bit_read_RC (&sec_dat); // 0x00
      LOG_HANDLE ("c: " FORMAT_RC " [RC]\n", c)
      c = bit_read_B (&sec_dat); // 1
      LOG_HANDLE ("c: " FORMAT_B " [B]\n", c);

      dwg->layout_type = 0;
      dwg->num_classes = max_num - 499;
      if (max_num < 500 || max_num > 5000)
        {
          LOG_ERROR ("Invalid max class number %d", max_num)
          dwg->num_classes = 0;
          if (sec_dat.chain)
            free (sec_dat.chain);
          return DWG_ERR_VALUEOUTOFBOUNDS;
        }
      assert (max_num >= 500);
      assert (max_num < 5000);

      section_string_stream (dwg, &sec_dat, bitsize, &str);

      dwg->dwg_class
          = (Dwg_Class *)calloc (dwg->num_classes, sizeof (Dwg_Class));
      if (!dwg->dwg_class)
        {
          LOG_ERROR ("Out of memory");
          if (sec_dat.chain)
            free (sec_dat.chain);
          return DWG_ERR_OUTOFMEM;
        }

      for (i = 0; i < dwg->num_classes; i++)
        {
          dwg->dwg_class[i].number = bit_read_BS (&sec_dat);
          dwg->dwg_class[i].proxyflag = bit_read_BS (&sec_dat);
          dwg->dwg_class[i].appname = (char *)bit_read_TU (&str);
          dwg->dwg_class[i].cppname = (char *)bit_read_TU (&str);
          dwg->dwg_class[i].dxfname_u = bit_read_TU (&str);
          dwg->dwg_class[i].is_zombie = bit_read_B (&sec_dat); // DXF 280
          dwg->dwg_class[i].item_class_id = bit_read_BS (&sec_dat); // DXF 281, is_entity is 0x1f3

          dwg->dwg_class[i].num_instances = bit_read_BL (&sec_dat); // DXF 91
          dwg->dwg_class[i].dwg_version = bit_read_BS (&sec_dat);
          dwg->dwg_class[i].maint_version = bit_read_BS (&sec_dat);
          dwg->dwg_class[i].unknown_1 = bit_read_BL (&sec_dat); // 0
          dwg->dwg_class[i].unknown_2 = bit_read_BL (&sec_dat); // 0

          LOG_TRACE ("-------------------\n")
          LOG_TRACE ("Number:           %d\n", dwg->dwg_class[i].number)
          LOG_TRACE ("Proxyflag:        0x%x\n", dwg->dwg_class[i].proxyflag)
          LOG_TRACE_TU ("Application name", dwg->dwg_class[i].appname, 0)
          LOG_TRACE_TU ("C++ class name  ", dwg->dwg_class[i].cppname, 0)
          LOG_TRACE_TU ("DXF record name ", dwg->dwg_class[i].dxfname_u, 0)
          LOG_TRACE ("Class ID:         0x%x "
                     "(0x1f3 for object, 0x1f2 for entity)\n",
                     dwg->dwg_class[i].item_class_id)
          LOG_TRACE ("instance count:   %u\n", dwg->dwg_class[i].num_instances)
          LOG_TRACE ("dwg version:      %u (%u)\n",
                     dwg->dwg_class[i].dwg_version,
                     dwg->dwg_class[i].maint_version)
          LOG_HANDLE ("unknown:          %u %u\n", dwg->dwg_class[i].unknown_1,
                      dwg->dwg_class[i].unknown_2)

          dwg->dwg_class[i].dxfname
              = bit_convert_TU (dwg->dwg_class[i].dxfname_u);
          if (dwg->dwg_class[i].dxfname
              && strEQc (dwg->dwg_class[i].dxfname, "LAYOUT"))
            dwg->layout_type = dwg->dwg_class[i].number;
        }
    }
  else
    {
      LOG_ERROR ("Failed to find class section sentinel");
      free (sec_dat.chain);
      return DWG_ERR_CLASSESNOTFOUND;
    }

  if (sec_dat.chain)
    free (sec_dat.chain);

  return 0;
}
read_2007_section_classes (Bit_Chain *restrict dat, Dwg_Data *restrict dwg,
                           r2007_section *restrict sections_map,
                           r2007_page *restrict pages_map)
{
  BITCODE_RL size, i;
  BITCODE_BS max_num;
  Bit_Chain sec_dat = { 0 }, str = { 0 };
  Dwg_Object *obj = NULL;
  int error;
  char c;

  error = read_data_section (&sec_dat, dat, sections_map, pages_map,
                             SECTION_CLASSES);
  if (error)
    {
      LOG_ERROR ("Failed to read class section");
      if (sec_dat.chain)
        free (sec_dat.chain);
      return error;
    }

  if (bit_search_sentinel (&sec_dat, dwg_sentinel (DWG_SENTINEL_CLASS_BEGIN)))
    {
      BITCODE_RL bitsize = 0;
      LOG_TRACE ("\nClasses\n-------------------\n")
      size = bit_read_RL (&sec_dat);  
      LOG_TRACE ("size: " FORMAT_RL " [RL]\n", size)
       
      if (dat->from_version >= R_2007)
        {
          bitsize = bit_read_RL (&sec_dat);
          LOG_TRACE ("bitsize: " FORMAT_RL " [RL]\n", bitsize)
        }
      max_num = bit_read_BS (&sec_dat);  
      LOG_TRACE ("max_num: " FORMAT_BS " [BS]\n", max_num)
      c = bit_read_RC (&sec_dat);  
      LOG_HANDLE ("c: " FORMAT_RC " [RC]\n", c)
      c = bit_read_RC (&sec_dat);  
      LOG_HANDLE ("c: " FORMAT_RC " [RC]\n", c)
      c = bit_read_B (&sec_dat);  
      LOG_HANDLE ("c: " FORMAT_B " [B]\n", c);

      dwg->layout_type = 0;
      dwg->num_classes = max_num - 499;
      if (max_num < 500 || max_num > 5000)
        {
          LOG_ERROR ("Invalid max class number %d", max_num)
          dwg->num_classes = 0;
          if (sec_dat.chain)
            free (sec_dat.chain);
          return DWG_ERR_VALUEOUTOFBOUNDS;
        }
      assert (max_num >= 500);
      assert (max_num < 5000);

      section_string_stream (dwg, &sec_dat, bitsize, &str);

      dwg->dwg_class
          = (Dwg_Class *)calloc (dwg->num_classes, sizeof (Dwg_Class));
      if (!dwg->dwg_class)
        {
          LOG_ERROR ("Out of memory");
          if (sec_dat.chain)
            free (sec_dat.chain);
          return DWG_ERR_OUTOFMEM;
        }

      for (i = 0; i < dwg->num_classes; i++)
        {
          dwg->dwg_class[i].number = bit_read_BS (&sec_dat);
          dwg->dwg_class[i].proxyflag = bit_read_BS (&sec_dat);
          dwg->dwg_class[i].appname = (char *)bit_read_TU (&str);
          dwg->dwg_class[i].cppname = (char *)bit_read_TU (&str);
          dwg->dwg_class[i].dxfname_u = bit_read_TU (&str);
          dwg->dwg_class[i].is_zombie = bit_read_B (&sec_dat);  
          dwg->dwg_class[i].item_class_id = bit_read_BS (&sec_dat);  

          dwg->dwg_class[i].num_instances = bit_read_BL (&sec_dat);  
          dwg->dwg_class[i].dwg_version = bit_read_BS (&sec_dat);
          dwg->dwg_class[i].maint_version = bit_read_BS (&sec_dat);
          dwg->dwg_class[i].unknown_1 = bit_read_BL (&sec_dat);  
          dwg->dwg_class[i].unknown_2 = bit_read_BL (&sec_dat);  

          LOG_TRACE ("-------------------\n")
          LOG_TRACE ("Number:           %d\n", dwg->dwg_class[i].number)
          LOG_TRACE ("Proxyflag:        0x%x\n", dwg->dwg_class[i].proxyflag)
          LOG_TRACE_TU ("Application name", dwg->dwg_class[i].appname, 0)
          LOG_TRACE_TU ("C++ class name  ", dwg->dwg_class[i].cppname, 0)
          LOG_TRACE_TU ("DXF record name ", dwg->dwg_class[i].dxfname_u, 0)
          LOG_TRACE ("Class ID:         0x%x "
                     "(0x1f3 for object, 0x1f2 for entity)\n",
                     dwg->dwg_class[i].item_class_id)
          LOG_TRACE ("instance count:   %u\n", dwg->dwg_class[i].num_instances)
          LOG_TRACE ("dwg version:      %u (%u)\n",
                     dwg->dwg_class[i].dwg_version,
                     dwg->dwg_class[i].maint_version)
          LOG_HANDLE ("unknown:          %u %u\n", dwg->dwg_class[i].unknown_1,
                      dwg->dwg_class[i].unknown_2)

          dwg->dwg_class[i].dxfname
              = bit_convert_TU (dwg->dwg_class[i].dxfname_u);
          if (dwg->dwg_class[i].dxfname
              && strEQc (dwg->dwg_class[i].dxfname, "LAYOUT"))
            dwg->layout_type = dwg->dwg_class[i].number;
        }
    }
  else
    {
      LOG_ERROR ("Failed to find class section sentinel");
      free (sec_dat.chain);
      return DWG_ERR_CLASSESNOTFOUND;
    }

  if (sec_dat.chain)
    free (sec_dat.chain);

  return 0;
}