dwg_decode_eed_data (Bit_Chain *restrict dat, Dwg_Eed_Data *restrict data,
                     unsigned long int end, BITCODE_BS size)
{
  int lenc;
  BITCODE_BS j;
  BITCODE_RS lens;

  data->code = bit_read_RC (dat);
  LOG_TRACE ("code: %d [RC], ", (int)data->code);
  switch (data->code)
    {
    case 0:
      PRE (R_2007)
      {
        if (eed_need_size (3, size))
          return DWG_ERR_INVALIDEED;
        data->u.eed_0.length = lenc = bit_read_RC (dat);
        data->u.eed_0.codepage = bit_read_RS_LE (dat);
        if ((long)lenc > size - 4)
          {
            LOG_ERROR ("Invalid EED string len %d, max %d", lenc,
                       (int)size - 4)
            dat->byte = end;
            break;
#if 0
            obj->num_eed = 0;
            if (obj->eed[idx].size)
              free(obj->eed[idx].raw);
            free(obj->eed[idx].data);
            free(obj->eed);
            obj->eed = NULL;
            dat->byte = end;
            return DWG_ERR_INVALIDEED; /* may not continue */
#endif
          }
        /* code:1 + len:1 + cp:2 */
        if (eed_need_size (lenc + 3, size))
          return DWG_ERR_INVALIDEED;
        bit_read_fixed (dat, (BITCODE_RC *)data->u.eed_0.string, lenc);
        data->u.eed_0.string[lenc] = '\0';
        LOG_TRACE ("string: len=%d [RC] cp=%d [RS_LE] \"%s\" [TF]\n", (int)lenc,
                   (int)data->u.eed_0.codepage, data->u.eed_0.string);
      }
      LATER_VERSIONS
      {
        if (eed_need_size (2, size))
          return DWG_ERR_INVALIDEED;
        data->u.eed_0_r2007.length = lens = bit_read_RS (dat);
        if (eed_need_size ((lens * 2) + 2, size))
          return DWG_ERR_INVALIDEED;
        /* code:1 + len:2 NUL? */
        for (j = 0; j < MIN (lens, (size - 3) / 2); j++)
          data->u.eed_0_r2007.string[j] = bit_read_RS_LE (dat);
          // data->u.eed_0_r2007.string[j] = 0; //already calloc'ed
#ifdef _WIN32
        LOG_TRACE ("wstring: len=%d [RS] \"" FORMAT_TU "\" [TU]\n",
                   (int)lens, data->u.eed_0_r2007.string);
#else
        if (DWG_LOGLEVEL >= DWG_LOGLEVEL_TRACE)
          {
            char *u8 = bit_convert_TU (data->u.eed_0_r2007.string);
            LOG_TRACE ("wstring: len=%d [RS] \"%s\" [TU]\n",
                       (int)lens, u8);
            free (u8);
          }
#endif
      }
      break;
    case 2:
      if (eed_need_size (1, size))
        return DWG_ERR_INVALIDEED;
      data->u.eed_2.byte = bit_read_RC (dat);
      LOG_TRACE ("byte: " FORMAT_RC " [RC]\n", data->u.eed_2.byte);
      break;
    case 3:
      if (eed_need_size (4, size))
        return DWG_ERR_INVALIDEED;
      data->u.eed_3.layer = bit_read_RL (dat);
      LOG_TRACE ("layer: " FORMAT_RL " [RL]\n", data->u.eed_3.layer);
      break;
    case 4:
      if (eed_need_size (1, size))
        return DWG_ERR_INVALIDEED;
      data->u.eed_4.length = lenc = bit_read_RC (dat);
      if (eed_need_size (lenc + 1, size))
        return DWG_ERR_INVALIDEED;
      /* code:1 + len:1 */
      for (j = 0; j < MIN (lenc, size - 2); j++)
        data->u.eed_4.data[j] = bit_read_RC (dat);
      LOG_TRACE ("binary[%d] \"%s\" [TF]\n", j-1, data->u.eed_4.data);
      break;
    case 5:
      if (eed_need_size (8, size))
        return DWG_ERR_INVALIDEED;
      data->u.eed_5.entity = bit_read_RLL (dat);
      LOG_TRACE ("entity: 0x%" PRIx64 " [RLL]\n", data->u.eed_5.entity);
      break;
    case 10:
    case 11:
    case 12:
    case 13:
    case 14:
    case 15:
      if (eed_need_size (3 * 8, size))
        return DWG_ERR_INVALIDEED;
      data->u.eed_10.point.x = bit_read_RD (dat);
      data->u.eed_10.point.y = bit_read_RD (dat);
      data->u.eed_10.point.z = bit_read_RD (dat);
      LOG_TRACE ("3dpoint: (%f, %f, %f) [3RD]\n", data->u.eed_10.point.x,
                 data->u.eed_10.point.y, data->u.eed_10.point.z);
      break;
    case 40:
    case 41:
    case 42: /*case 43: case 44: case 45: case 46:
case 51: case 54:*/
      if (eed_need_size (8, size))
        return DWG_ERR_INVALIDEED;
      data->u.eed_40.real = bit_read_RD (dat);
      LOG_TRACE ("real: %f [RD]\n", data->u.eed_40.real);
      break;
    case 70:
      if (eed_need_size (2, size))
        return DWG_ERR_INVALIDEED;
      data->u.eed_70.rs = bit_read_RS (dat);
      LOG_TRACE ("short: " FORMAT_RS " [RS]\n", data->u.eed_70.rs);
      break;
    case 71:
      if (eed_need_size (4, size))
        return DWG_ERR_INVALIDEED;
      data->u.eed_71.rl = bit_read_RL (dat);
      LOG_TRACE ("long: " FORMAT_RL " [RL]\n", data->u.eed_71.rl);
      break;
    default:
      LOG_ERROR ("unknown EED code %d", data->code);
      LOG_POS
      dat->byte = end;
      LOG_POS
      return DWG_ERR_INVALIDEED; /* may continue */
    }
  LOG_POS

#ifdef DEBUG
  // sanity checks
  if (obj->eed[idx].code == 0 || obj->eed[idx].code == 4)
    assert (obj->eed[idx].data->u.eed_0.length <= size - 1);
  if (obj->eed[idx].code == 10) // 3 double
    assert (size >= 1 + 3 * 8);
#endif

  return 0;
}
dwg_decode_eed_data (Bit_Chain *restrict dat, Dwg_Eed_Data *restrict data,
                     unsigned long int end, BITCODE_BS size)
{
  int lenc;
  BITCODE_BS j;
  BITCODE_RS lens;

  data->code = bit_read_RC (dat);
  LOG_TRACE ("code: %d [RC], ", (int)data->code);
  switch (data->code)
    {
    case 0:
      PRE (R_2007)
      {
        if (eed_need_size (3, size))
          return DWG_ERR_INVALIDEED;
        data->u.eed_0.length = lenc = bit_read_RC (dat);
        data->u.eed_0.codepage = bit_read_RS_LE (dat);
        if ((long)lenc > size - 4)
          {
            LOG_ERROR ("Invalid EED string len %d, max %d", lenc,
                       (int)size - 4)
            dat->byte = end;
            break;
#if 0
            obj->num_eed = 0;
            if (obj->eed[idx].size)
              free(obj->eed[idx].raw);
            free(obj->eed[idx].data);
            free(obj->eed);
            obj->eed = NULL;
            dat->byte = end;
            return DWG_ERR_INVALIDEED;  
#endif
          }
         
        if (eed_need_size (lenc + 3, size))
          return DWG_ERR_INVALIDEED;
        bit_read_fixed (dat, (BITCODE_RC *)data->u.eed_0.string, lenc);
        data->u.eed_0.string[lenc] = '\0';
        LOG_TRACE ("string: len=%d [RC] cp=%d [RS_LE] \"%s\" [TF]\n", (int)lenc,
                   (int)data->u.eed_0.codepage, data->u.eed_0.string);
      }
      LATER_VERSIONS
      {
        if (eed_need_size (2, size))
          return DWG_ERR_INVALIDEED;
        data->u.eed_0_r2007.length = lens = bit_read_RS (dat);
        if (eed_need_size ((lens * 2) + 2, size))
          return DWG_ERR_INVALIDEED;
         
        for (j = 0; j < MIN (lens, (size - 3) / 2); j++)
          data->u.eed_0_r2007.string[j] = bit_read_RS_LE (dat);
           
#ifdef _WIN32
        LOG_TRACE ("wstring: len=%d [RS] \"" FORMAT_TU "\" [TU]\n",
                   (int)lens, data->u.eed_0_r2007.string);
#else
        if (DWG_LOGLEVEL >= DWG_LOGLEVEL_TRACE)
          {
            char *u8 = bit_convert_TU (data->u.eed_0_r2007.string);
            LOG_TRACE ("wstring: len=%d [RS] \"%s\" [TU]\n",
                       (int)lens, u8);
            free (u8);
          }
#endif
      }
      break;
    case 2:
      if (eed_need_size (1, size))
        return DWG_ERR_INVALIDEED;
      data->u.eed_2.byte = bit_read_RC (dat);
      LOG_TRACE ("byte: " FORMAT_RC " [RC]\n", data->u.eed_2.byte);
      break;
    case 3:
      if (eed_need_size (4, size))
        return DWG_ERR_INVALIDEED;
      data->u.eed_3.layer = bit_read_RL (dat);
      LOG_TRACE ("layer: " FORMAT_RL " [RL]\n", data->u.eed_3.layer);
      break;
    case 4:
      if (eed_need_size (1, size))
        return DWG_ERR_INVALIDEED;
      data->u.eed_4.length = lenc = bit_read_RC (dat);
      if (eed_need_size (lenc + 1, size))
        return DWG_ERR_INVALIDEED;
       
      for (j = 0; j < MIN (lenc, size - 2); j++)
        data->u.eed_4.data[j] = bit_read_RC (dat);
      LOG_TRACE ("binary[%d] \"%s\" [TF]\n", j-1, data->u.eed_4.data);
      break;
    case 5:
      if (eed_need_size (8, size))
        return DWG_ERR_INVALIDEED;
      data->u.eed_5.entity = bit_read_RLL (dat);
      LOG_TRACE ("entity: 0x%" PRIx64 " [RLL]\n", data->u.eed_5.entity);
      break;
    case 10:
    case 11:
    case 12:
    case 13:
    case 14:
    case 15:
      if (eed_need_size (3 * 8, size))
        return DWG_ERR_INVALIDEED;
      data->u.eed_10.point.x = bit_read_RD (dat);
      data->u.eed_10.point.y = bit_read_RD (dat);
      data->u.eed_10.point.z = bit_read_RD (dat);
      LOG_TRACE ("3dpoint: (%f, %f, %f) [3RD]\n", data->u.eed_10.point.x,
                 data->u.eed_10.point.y, data->u.eed_10.point.z);
      break;
    case 40:
    case 41:
    case 42:  
      if (eed_need_size (8, size))
        return DWG_ERR_INVALIDEED;
      data->u.eed_40.real = bit_read_RD (dat);
      LOG_TRACE ("real: %f [RD]\n", data->u.eed_40.real);
      break;
    case 70:
      if (eed_need_size (2, size))
        return DWG_ERR_INVALIDEED;
      data->u.eed_70.rs = bit_read_RS (dat);
      LOG_TRACE ("short: " FORMAT_RS " [RS]\n", data->u.eed_70.rs);
      break;
    case 71:
      if (eed_need_size (4, size))
        return DWG_ERR_INVALIDEED;
      data->u.eed_71.rl = bit_read_RL (dat);
      LOG_TRACE ("long: " FORMAT_RL " [RL]\n", data->u.eed_71.rl);
      break;
    default:
      LOG_ERROR ("unknown EED code %d", data->code);
      LOG_POS
      dat->byte = end;
      LOG_POS
      return DWG_ERR_INVALIDEED;  
    }
  LOG_POS

#ifdef DEBUG
   
  if (obj->eed[idx].code == 0 || obj->eed[idx].code == 4)
    assert (obj->eed[idx].data->u.eed_0.length <= size - 1);
  if (obj->eed[idx].code == 10)  
    assert (size >= 1 + 3 * 8);
#endif

  return 0;
}