#include #include #include "common.h" #include "sdlrwops_stub.h" #define RWOPS_DATA(r) ((r)->hidden.unknown.data1) #define CHECK_RWOPS(r) do{ \ if(! RWOPS_DATA(r)) { \ SDL_SetError("closed Sdl.rwops") ; \ return -1; } \ } while(0) struct mem_pos_data { void *base; size_t off; size_t max; }; #define RWmem_pos_data(r) (r->hidden.unknown.data1) static int mlsdl_mem_seek(SDL_RWops *context, int offset, int whence) { size_t newoff; struct mem_pos_data *pdata = RWmem_pos_data(context); CHECK_RWOPS(context); switch (whence) { case SEEK_SET: newoff = offset; break; case SEEK_CUR: newoff = pdata->off+offset; break; case SEEK_END: newoff = pdata->max+offset; break; default: SDL_SetError("Unknown value for 'whence'"); return -1; } if ( newoff < 0 || newoff > pdata->max ) return -1; pdata->off = newoff; return newoff; } static int mlsdl_mem_read(SDL_RWops *context, void *ptr, int size, int maxnum) { int num; struct mem_pos_data *pdata = RWmem_pos_data(context); CHECK_RWOPS(context); num = maxnum; if (pdata->off + (num*size) > pdata->max) num = (pdata->max - pdata->off)/size; memcpy(ptr, ((char *)pdata->base) + pdata->off, num*size); pdata->off += num*size; return num; } static int mlsdl_mem_write(SDL_RWops *context, const void *ptr, int size, int num) { return -1; } static int mlsdl_mem_close(SDL_RWops *context) { struct mem_pos_data *pdata = RWmem_pos_data(context); void *base; if(! pdata) return 0; base = &pdata->base; remove_global_root(base); stat_free(pdata); RWmem_pos_data(context) = NULL; return 0; } CAMLprim value mlsdl_rwops_finalise(value rw) { SDL_RWops *rwops = SDLRWops_val(rw); if(RWOPS_DATA(rwops)) rwops->close(rwops); stat_free(rwops); return Val_unit; } CAMLprim value mlsdl_rw_from_mem(value buff) { SDL_RWops *rwops; struct mem_pos_data *pdata; void *base; rwops = stat_alloc(sizeof *rwops); pdata = stat_alloc(sizeof *pdata); rwops->seek = mlsdl_mem_seek; rwops->read = mlsdl_mem_read; rwops->write = mlsdl_mem_write; rwops->close = mlsdl_mem_close; rwops->type = MLSDL_RWOPS_MEM; RWmem_pos_data(rwops) = pdata; pdata->base = String_val(buff); base = &pdata->base; register_global_root(base); pdata->off = 0; pdata->max = string_length(buff); return abstract_ptr(rwops); } CAMLprim value mlsdl_rwops_close(value rw) { SDL_RWops *rwops = SDLRWops_val(rw); if(RWOPS_DATA(rwops)) rwops->close(rwops); return Val_unit; }