2010-01-13 18 views
4

Je suis assez surpris que Google n'ait pas trouvé de solution. Je suis à la recherche d'une solution qui permette l'utilisation de SDL_RWops avec std :: istream. SDL_RWops est le mécanisme alternatif pour lire/écrire des données dans SDL.Lecture SDL_RWops d'un std :: istream

Des liens vers des sites qui traitent le problème?

Une solution évidente serait de pré-lire suffisamment de données en mémoire, puis d'utiliser SDL_RWFromMem. Cependant, cela a l'inconvénient que j'ai besoin de connaître la taille du fichier à l'avance.

On dirait que le problème pourrait être résolu en quelque sorte par « dominante » fonctions SDL_RWops ...

+0

Vous voulez créer une structure RWops à partir d'un istream? –

+0

bon indice, je vais l'essayer. –

+0

Ce n'était pas un succès, je ne comprends pas ce que vous essayez de faire. –

Répondre

5

Je me sens mal répondre à ma propre question, mais il me preocupied pendant un certain temps, et c'est la solution que je suis venu avec :

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; 
} 

Fonctionne sous les hypothèses qui ne sont jamais IStream de libéré par SDL (et qu'ils vivent à travers l'opération). De plus, seul le support istream est en place, une fonction séparée serait faite pour ostream - je sais que je pourrais passer iostream, mais cela ne permettrait pas de passer un istream à la fonction de conversion: /.

Tous les conseils sur les erreurs ou les mises à niveau sont les bienvenus.

+4

en utilisant rwops-> type vous pouvez autoriser istream, ostream ou iostream. –

+3

en utilisant NULL comme la fonction d'écriture semble effrayante. Il pourrait être préférable de créer une fonction qui utilise SDL_SetError et renvoie -1. –

+0

@Caspin, merci, conseil très utile! Pourtant, le code affiché ne fonctionne pas .... J'essaie de le déboguer, mais pas d'indices:/ –

1

Si vous essayez d'obtenir une structure SDL_RWops à partir d'un istream, vous pouvez le faire en lisant l'ensemble de l'istream en mémoire, puis en utilisant SDL_RWFromMem pour obtenir une structure pour le représenter.

Voici un exemple rapide. Notez qu'il est dangereux, car aucune vérification de santé mentale n'est faite. Par exemple, si la taille du fichier est 0, l'accès au tampon [0] peut générer une exception ou être affirmé dans les versions de débogage.

// 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

J'ai déjà écrit que je ne peux pas le faire parce que je ne veux pas précharger le fichier entier dans la mémoire. Si j'avais voulu lire à partir d'un fichier, j'utiliserais IMG_Load :). Je veux charger à partir d'un conteneur personnalisé auquel on accède via un istream. –

+0

Vous avez seulement mentionné que c'est un problème car 'vous ne connaissez pas la taille du fichier à l'avance' –

+0

Eh bien oui, cela peut fonctionner avec n'importe quel istream, je viens d'utiliser un ifstream pour l'exemple car c'est le moyen le plus simple Istream. –