physfs_sdl.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // SuperTux
  2. // Copyright (C) 2006 Matthias Braun <matze@braunis.de>
  3. //
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. #include "physfs/physfs_sdl.hpp"
  17. #include <physfs.h>
  18. #include <sstream>
  19. #include <stdexcept>
  20. #include <assert.h>
  21. #include <stdio.h>
  22. #include "physfs/util.hpp"
  23. #include "util/log.hpp"
  24. #include <iostream>
  25. namespace {
  26. Sint64 funcSize(struct SDL_RWops* context)
  27. {
  28. PHYSFS_file* file = static_cast<PHYSFS_file*>(context->hidden.unknown.data1);
  29. return PHYSFS_fileLength(file);
  30. }
  31. Sint64 funcSeek(struct SDL_RWops* context, Sint64 offset, int whence)
  32. {
  33. PHYSFS_file* file = static_cast<PHYSFS_file*>(context->hidden.unknown.data1);
  34. int res;
  35. switch (whence) {
  36. case SEEK_SET:
  37. res = PHYSFS_seek(file, offset);
  38. break;
  39. case SEEK_CUR:
  40. res = PHYSFS_seek(file, PHYSFS_tell(file) + offset);
  41. break;
  42. case SEEK_END:
  43. res = PHYSFS_seek(file, PHYSFS_fileLength(file) + offset);
  44. break;
  45. default:
  46. res = 0; // NOLINT
  47. assert(false);
  48. break;
  49. }
  50. if (res == 0) {
  51. log_warning << "Error seeking in file: " << physfsutil::get_last_error() << std::endl;
  52. return -1;
  53. }
  54. int i = static_cast<int>(PHYSFS_tell(file));
  55. return i;
  56. }
  57. size_t funcRead(struct SDL_RWops* context, void* ptr, size_t size, size_t maxnum)
  58. {
  59. PHYSFS_file* file = static_cast<PHYSFS_file*>(context->hidden.unknown.data1);
  60. PHYSFS_sint64 res = PHYSFS_readBytes(file, ptr, size * maxnum);
  61. if (res < 0)
  62. {
  63. return 0;
  64. }
  65. else
  66. {
  67. return static_cast<size_t>(res / size);
  68. }
  69. }
  70. size_t funcWrite(struct SDL_RWops* context, const void* ptr, size_t size, size_t num)
  71. {
  72. PHYSFS_file* file = static_cast<PHYSFS_file*>(context->hidden.unknown.data1);
  73. PHYSFS_sint64 res = PHYSFS_writeBytes(file, ptr, size * num);
  74. if (res < 0)
  75. {
  76. return 0;
  77. }
  78. else
  79. {
  80. return static_cast<size_t>(res / size);
  81. }
  82. }
  83. int funcClose(struct SDL_RWops* context)
  84. {
  85. PHYSFS_file* file = static_cast<PHYSFS_file*>(context->hidden.unknown.data1);
  86. PHYSFS_close(file);
  87. delete context;
  88. return 0;
  89. }
  90. } // namespace
  91. SDL_RWops* get_physfs_SDLRWops(const std::string& filename)
  92. {
  93. // check this as PHYSFS seems to be buggy and still returns a
  94. // valid pointer in this case
  95. if (filename.empty()) {
  96. throw std::runtime_error("Couldn't open file: empty filename");
  97. }
  98. PHYSFS_file* file = static_cast<PHYSFS_file*>(PHYSFS_openRead(filename.c_str()));
  99. if (!file) {
  100. std::stringstream msg;
  101. msg << "Couldn't open '" << filename << "': "
  102. << physfsutil::get_last_error();
  103. throw std::runtime_error(msg.str());
  104. }
  105. SDL_RWops* ops = new SDL_RWops;
  106. ops->size = funcSize;
  107. ops->seek = funcSeek;
  108. ops->read = funcRead;
  109. ops->write = funcWrite;
  110. ops->close = funcClose;
  111. ops->type = SDL_RWOPS_UNKNOWN;
  112. ops->hidden.unknown.data1 = file;
  113. return ops;
  114. }
  115. SDL_RWops* get_writable_physfs_SDLRWops(const std::string& filename)
  116. {
  117. // check this as PHYSFS seems to be buggy and still returns a
  118. // valid pointer in this case
  119. if (filename.empty()) {
  120. throw std::runtime_error("Couldn't open file: empty filename");
  121. }
  122. PHYSFS_file* file = static_cast<PHYSFS_file*>(PHYSFS_openWrite(filename.c_str()));
  123. if (!file) {
  124. std::stringstream msg;
  125. msg << "Couldn't open '" << filename << "' for writing: "
  126. << physfsutil::get_last_error();
  127. throw std::runtime_error(msg.str());
  128. }
  129. SDL_RWops* ops = new SDL_RWops;
  130. ops->size = funcSize;
  131. ops->seek = funcSeek;
  132. ops->read = funcRead;
  133. ops->write = funcWrite;
  134. ops->close = funcClose;
  135. ops->type = SDL_RWOPS_UNKNOWN;
  136. ops->hidden.unknown.data1 = file;
  137. return ops;
  138. }
  139. /* EOF */