2010-01-13 3 views
4

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

Любые ссылки на сайты, которые решают проблему?

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

Похоже, проблема может быть как-то решить с помощью «» SDL_RWops временной отмены функции ...

+0

Вы имеете в виду, что хотите создать структуру RWops из istream? –

+0

хороший намек, я попробую. –

+0

Это не было хитом, я не понимаю, что вы пытаетесь сделать. –

ответ

5

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

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-х никогда не освобожденным от СВД (и что они живут за счет эксплуатации). Также поддерживается только поддержка istream, для ostream будет выполняться отдельная функция - я знаю, что могу передавать iostream, но это не позволило бы передать istream в функцию преобразования: /.

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

+4

, используя тип rwops->, который вы могли бы разрешить либо istream, ostream, либо iostream. –

+3

с использованием NULL, поскольку функция записи кажется страшной. Возможно, было бы лучше создать функцию, которая использует SDL_SetError и возвращает -1. –

+0

@Caspin, спасибо, очень полезный совет! Тем не менее, код не работает. Я пытаюсь его отладить, но никаких подсказок:/ –

1

Если вы пытаетесь получить структуру 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 
+0

Я уже написал, что я не могу этого сделать, потому что я не хочу предварительно загружать весь файл в память. Если бы я хотел прочитать из файла, я бы использовал IMG_Load :). Я хочу загрузить из пользовательского контейнера, к которому осуществляется доступ через istream. –

+0

Вы только упоминали, что это проблема, потому что «вы заранее не знаете размер файла» –

+0

Ну да, это может работать с любым istream, я просто использовал ifstream для примера, потому что это самый простой способ сделать IStream. –

Смежные вопросы