INLINE void MemoryStream::grow_if_necessary(uint64 new_required_size)
{
 if(new_required_size > data_buffer_size)
 {
  if(new_required_size > data_buffer_alloced)
  {
   uint64 new_required_alloced = round_up_pow2(new_required_size);
   uint8 *new_data_buffer;

   // first condition will happen at new_required_size > (UINT64_C(1) << 63) due to round_up_pow2() "wrapping".
   // second condition can occur when running on a 32-bit system.
   if(new_required_alloced < new_required_size || new_required_alloced > SIZE_MAX)
    new_required_alloced = SIZE_MAX;

   // If constrained alloc size isn't enough, throw an out-of-memory/address-space type error.
   if(new_required_alloced < new_required_size)
    throw MDFN_Error(ErrnoHolder(ENOMEM));

   if(!(new_data_buffer = (uint8*)realloc(data_buffer, (size_t)new_required_alloced)))
    throw MDFN_Error(ErrnoHolder(errno));

   //
   // Assign all in one go after the realloc() so we don't leave our object in an inconsistent state if the realloc() fails.
   //
   data_buffer = new_data_buffer;
   data_buffer_size = new_required_size;
   data_buffer_alloced = new_required_alloced;
  }
  else
   data_buffer_size = new_required_size;
 }
}
void MemoryStream::seek(int64 offset, int whence)
{
 uint64 new_position;

 switch(whence)
 {
  default:
	throw MDFN_Error(ErrnoHolder(EINVAL));
	break;

  case SEEK_SET:
	new_position = offset;
	break;

  case SEEK_CUR:
	new_position = position + offset;
	break;

  case SEEK_END:
	new_position = data_buffer_size + offset;
	break;
 }

 if(new_position < 0)
  throw MDFN_Error(ErrnoHolder(EINVAL));

 position = new_position;
}
MemoryStream::MemoryStream() : data_buffer(NULL), data_buffer_size(0), data_buffer_alloced(0), position(0)
{
 data_buffer_size = 0;
 data_buffer_alloced = 64;
 if(!(data_buffer = (uint8*)realloc(data_buffer, (size_t)data_buffer_alloced)))
  throw MDFN_Error(ErrnoHolder(errno));
}
uint64 CDIF_Stream_Thing::read(void *data, uint64 count, bool error_on_eos)
{
   uint64_t rp;

   if(count > (((uint64)sector_count * 2048) - position))
   {
      if(error_on_eos)
         throw MDFN_Error(0, "EOF");

      count = ((uint64)sector_count * 2048) - position;
   }

   if(!count)
      return(0);

   for(rp = position; rp < (position + count); rp = (rp &~ 2047) + 2048)
   {
      uint8_t buf[2048];  

      if(!cdintf->ReadSector(buf, start_lba + (rp / 2048), 1))
         throw MDFN_Error(ErrnoHolder(EIO));

      memcpy((uint8_t*)data + (rp - position),
            buf + (rp & 2047),
            std::min<uint64>(2048 - (rp & 2047),count - (rp - position))
            );
   }

   position += count;

   return count;
}
MemoryStream::MemoryStream(uint64 size_hint) : data_buffer(NULL), data_buffer_size(0), data_buffer_alloced(0), position(0)
{
 data_buffer_size = 0;
 data_buffer_alloced = (size_hint > SIZE_MAX) ? SIZE_MAX : size_hint;

 if(!(data_buffer = (uint8*)realloc(data_buffer, (size_t)data_buffer_alloced)))
  throw MDFN_Error(ErrnoHolder(errno));
}
MemoryStream::MemoryStream(const MemoryStream *zs)
{
 data_buffer_size = zs->data_buffer_size;
 data_buffer_alloced = zs->data_buffer_alloced;
 if(!(data_buffer = (uint8*)malloc((size_t)data_buffer_alloced)))
  throw MDFN_Error(ErrnoHolder(errno));

 memcpy(data_buffer, zs->data_buffer, (size_t)data_buffer_size);

 position = zs->position;
}
void MemoryStream::write(const void *data, uint64 count)
{
 uint64 nrs = position + count;

 if(nrs < position)
  throw MDFN_Error(ErrnoHolder(EFBIG));

 grow_if_necessary(nrs);

 memmove(&data_buffer[position], data, (size_t)count);
 position += count;
}
MemoryStream::MemoryStream(Stream *stream) : data_buffer(NULL), data_buffer_size(0), data_buffer_alloced(0), position(0)
{
   if((position = stream->tell()) != 0)
      stream->seek(0, SEEK_SET);

   data_buffer_size = stream->size();
   data_buffer_alloced = data_buffer_size;
   if(!(data_buffer = (uint8*)realloc(data_buffer, (size_t)data_buffer_alloced)))
      throw MDFN_Error(ErrnoHolder(errno));

   stream->read(data_buffer, data_buffer_size);

   stream->close();
   delete stream;
}
MemoryStream::MemoryStream(uint64 alloc_hint, int alloc_hint_is_size) : data_buffer(NULL), data_buffer_size(0), data_buffer_alloced(0), position(0)
{
 if(alloc_hint_is_size != 0)
 {
  data_buffer_size = alloc_hint;
  data_buffer_alloced = alloc_hint;

  if(alloc_hint > SIZE_MAX)
   throw MDFN_Error(ErrnoHolder(ENOMEM));
 }
 else
 {
  data_buffer_size = 0;
  data_buffer_alloced = (alloc_hint > SIZE_MAX) ? SIZE_MAX : alloc_hint;
 }

 data_buffer_alloced = std::max<uint64>(data_buffer_alloced, 1);

 if(!(data_buffer = (uint8*)realloc(data_buffer, data_buffer_alloced)))
  throw MDFN_Error(ErrnoHolder(errno));

 if(alloc_hint_is_size > 0)
  memset(data_buffer, 0, data_buffer_size);
}
示例#10
0
void ExtMemStream::write(const void *data, uint64 count)
{
 uint64 nrs = position + count;

 if(ro)
  throw MDFN_Error(EINVAL, _("Write attempted to read-only ExtMemStream."));

 if(nrs < position)
  throw MDFN_Error(ErrnoHolder(EFBIG));

 grow_if_necessary(nrs, position);

 memmove(&data_buffer[position], data, count);
 position += count;
}
示例#11
0
MemoryStream & MemoryStream::operator=(const MemoryStream &zs)
{
 if(this != &zs)
 {
  if(data_buffer)
  {
   free(data_buffer);
   data_buffer = NULL;
  }

  data_buffer_size = zs.data_buffer_size;
  data_buffer_alloced = zs.data_buffer_alloced;

  if(!(data_buffer = (uint8*)malloc(data_buffer_alloced)))
   throw MDFN_Error(ErrnoHolder(errno));

  memcpy(data_buffer, zs.data_buffer, data_buffer_size);

  position = zs.position;
 }
 return(*this);
}
void CDIF_Stream_Thing::seek(int64 offset, int whence)
{
   int64 new_position;

   switch(whence)
   {
      case SEEK_SET:
         new_position = offset;
         break;

      case SEEK_CUR:
         new_position = position + offset;
         break;

      case SEEK_END:
         new_position = ((int64)sector_count * 2048) + offset;
         break;
   }

   if(new_position < 0 || new_position > ((int64)sector_count * 2048))
      throw MDFN_Error(ErrnoHolder(EINVAL));

   position = new_position;
}
示例#13
0
uint64 Stream::alloc_and_read(void** data_out, uint64 size_limit)
{
 uint8 *data_buffer = NULL;
 uint64 data_buffer_size = 0;
 uint64 data_buffer_alloced = 0;

 try
 {
  if(attributes() & ATTRIBUTE_SLOW_SIZE)
  {
   uint64 rti;

   data_buffer_size = 0;
   data_buffer_alloced = 65536;

   if(!(data_buffer = (uint8*)realloc(data_buffer, data_buffer_alloced)))
    throw MDFN_Error(ErrnoHolder(errno));

   while((rti = read(data_buffer + data_buffer_size, data_buffer_alloced - data_buffer_size, false)) > 0)
   {
    uint8* new_data_buffer;

    data_buffer_size += rti;

    if(data_buffer_size == data_buffer_alloced)
    {
     data_buffer_alloced <<= 1;

     if(data_buffer_alloced >= SIZE_MAX)
      throw MDFN_Error(ErrnoHolder(ENOMEM));

     if(data_buffer_alloced > size_limit)	// So we can test against our size limit without going far far over it in temporary memory allocations.
      data_buffer_alloced = size_limit + 1;

     if(data_buffer_size > size_limit)
      throw MDFN_Error(0, _("Size limit of %llu bytes would be exceeded."), (unsigned long long)size_limit);

     if(data_buffer_alloced > SIZE_MAX)
      throw MDFN_Error(ErrnoHolder(ENOMEM));

     if(!(new_data_buffer = (uint8 *)realloc(data_buffer, data_buffer_alloced)))
      throw MDFN_Error(ErrnoHolder(errno));
     data_buffer = new_data_buffer;
    }
    else	// EOS
     break;
   }

   if(data_buffer_alloced > data_buffer_size)
   {
    uint8 *new_data_buffer;
    const uint64 new_data_buffer_alloced = std::max<uint64>(data_buffer_size, 1);

    new_data_buffer = (uint8*)realloc(data_buffer, new_data_buffer_alloced);

    if(new_data_buffer != NULL)
    {
     data_buffer = new_data_buffer;
     data_buffer_alloced = new_data_buffer_alloced;
    }
   }
  }
  else
  {
   data_buffer_size = size();
   data_buffer_size -= std::min<uint64>(data_buffer_size, tell());
   data_buffer_alloced = std::max<uint64>(data_buffer_size, 1);

   if(data_buffer_size > size_limit)
    throw MDFN_Error(0, _("Size limit of %llu bytes would be exceeded."), (unsigned long long)size_limit);

   if(data_buffer_alloced > SIZE_MAX)
    throw MDFN_Error(ErrnoHolder(ENOMEM));

   if(!(data_buffer = (uint8*)realloc(data_buffer, data_buffer_alloced)))
    throw MDFN_Error(ErrnoHolder(errno));

   read(data_buffer, data_buffer_size);
  }
 }
 catch(...)
 {
  if(data_buffer)
  {
   free(data_buffer);
   data_buffer = NULL;
  }
  throw;
 }

 *data_out = data_buffer;
 return data_buffer_size;
}
void CDIF_Stream_Thing::write(const void *data, uint64 count)
{
   throw MDFN_Error(ErrnoHolder(EBADF));
}