SDLRWwrapper.cpp 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /*
  2. * SDLRWwrapper.cpp, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #include "StdInc.h"
  11. #include "SDLRWwrapper.h"
  12. #include "../lib/filesystem/CInputStream.h"
  13. #include <SDL_rwops.h>
  14. static inline CInputStream* get_stream(SDL_RWops* context)
  15. {
  16. return static_cast<CInputStream*>(context->hidden.unknown.data1);
  17. }
  18. static Sint64 impl_size(SDL_RWops* context)
  19. {
  20. return get_stream(context)->getSize();
  21. }
  22. static Sint64 impl_seek(SDL_RWops* context, Sint64 offset, int whence)
  23. {
  24. auto stream = get_stream(context);
  25. switch (whence)
  26. {
  27. case RW_SEEK_SET:
  28. return stream->seek(offset);
  29. break;
  30. case RW_SEEK_CUR:
  31. return stream->seek(stream->tell() + offset);
  32. break;
  33. case RW_SEEK_END:
  34. return stream->seek(stream->getSize() + offset);
  35. break;
  36. default:
  37. return -1;
  38. }
  39. }
  40. static std::size_t impl_read(SDL_RWops* context, void *ptr, size_t size, size_t maxnum)
  41. {
  42. auto stream = get_stream(context);
  43. auto oldpos = stream->tell();
  44. auto count = stream->read(static_cast<ui8*>(ptr), size*maxnum);
  45. if (count != 0 && count != size*maxnum)
  46. {
  47. // if not a whole amount of objects of size has been read, we need to seek
  48. stream->seek(oldpos + size * (count / size));
  49. }
  50. return count / size;
  51. }
  52. static std::size_t impl_write(SDL_RWops* context, const void *ptr, size_t size, size_t num)
  53. {
  54. // writing is not supported
  55. return 0;
  56. }
  57. static int impl_close(SDL_RWops* context)
  58. {
  59. if (context == nullptr)
  60. return 0;
  61. delete get_stream(context);
  62. SDL_FreeRW(context);
  63. return 0;
  64. }
  65. SDL_RWops* MakeSDLRWops(std::unique_ptr<CInputStream> in)
  66. {
  67. SDL_RWops* result = SDL_AllocRW();
  68. if (!result)
  69. return nullptr;
  70. result->size = &impl_size;
  71. result->seek = &impl_seek;
  72. result->read = &impl_read;
  73. result->write = &impl_write;
  74. result->close = &impl_close;
  75. result->type = SDL_RWOPS_UNKNOWN;
  76. result->hidden.unknown.data1 = in.release();
  77. return result;
  78. }