Чтение SDL_RWops из std :: istream - PullRequest
4 голосов
/ 13 января 2010

Я очень удивлен, что Google не нашел решения.Я ищу решение, которое позволяет использовать SDL_RWops с std :: istream.SDL_RWops - это альтернативный механизм чтения / записи данных в SDL.

Есть ли ссылки на сайты, которые занимаются этой проблемой?

Очевидным решением будет предварительное чтение данных в память и затем использование SDL_RWFromMem.Однако в этом есть и обратная сторона: мне нужно знать размер файла заранее.

Похоже, проблему можно как-то решить, "переопределив" функции SDL_RWops ...

Ответы [ 2 ]

5 голосов
/ 13 января 2010

Я чувствую себя плохо, отвечая на свой вопрос, но это заняло меня некоторое время, и вот решение, которое я придумала:

int istream_seek( struct SDL_RWops *context, int offset, int whence)
{
    std::istream* stream = (std::istream*) context->hidden.unknown.data1;

         if ( whence == SEEK_SET )
        stream->seekg ( offset, std::ios::beg );
    else if ( whence == SEEK_CUR )
        stream->seekg ( offset, std::ios::cur );
    else if ( whence == SEEK_END )
         stream->seekg ( offset, std::ios::end );

    return stream->fail() ? -1 : stream->tellg();
}


int istream_read(SDL_RWops *context, void *ptr, int size, int maxnum)
{
    if ( size == 0 ) return -1;
    std::istream* stream = (std::istream*) context->hidden.unknown.data1;
    stream->read( (char*)ptr, size * maxnum );

    return stream->bad() ? -1 : stream->gcount() / size;
}

int istream_close( SDL_RWops *context )
{
    if ( context ) {
        SDL_FreeRW( context );
    }
    return 0;
}


SDL_RWops *SDL_RWFromIStream( std::istream& stream )
{
    SDL_RWops *rwops;
    rwops = SDL_AllocRW();

    if ( rwops != NULL ) 
    {
        rwops->seek = istream_seek;
        rwops->read = istream_read;
        rwops->write = NULL;
        rwops->close = istream_close;
        rwops->hidden.unknown.data1 = &stream;
    }
    return rwops;
}

Работает в предположении, что istream никогда не освобождается SDL (и что они переживают операцию). Также включена только поддержка istream, для ostream будет сделана отдельная функция - я знаю, что мог бы передать iostream, но это не позволило бы передать istream в функцию преобразования: /.

Любые советы по ошибкам или обновлениям приветствуются.

1 голос
/ 13 января 2010

Если вы пытаетесь получить структуру SDL_RWops из istream, вы можете сделать это, прочитав весь istream в память, а затем используя SDL_RWFromMem, чтобы получить структуру, представляющую его.

Ниже приведен быстрый пример; обратите внимание, что это небезопасно, так как никаких проверок работоспособности не делается. Например, если размер файла равен 0, доступ к буферу [0] может вызвать исключение или утверждение в отладочных сборках.

// Open a bitmap
std::ifstream bitmap("bitmap.bmp");

// Find the bitmap file's size
bitmap.seekg(0, std::ios_base::end);
std::istream::pos_tye fileSize = bitmap.tellg();
bitmap.seekg(0);

// Allocate a buffer to store the file in
std::vector<unsigned char> buffer(fileSize);

// Copy the istream into the buffer
std::copy(std::istreambuf_iterator<unsigned char>(bitmap), std::istreambuf_iterator<unsigned char>(), buffer.begin());

// Get an SDL_RWops struct for the file
SDL_RWops* rw = SDL_RWFromMem(&buffer[0], buffer.size());

// Do stuff with the SDL_RWops struct
...