physfsrwops.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. * This code provides a glue layer between PhysicsFS and Simple Directmedia
  3. * Layer's (SDL) RWops i/o abstraction.
  4. *
  5. * License: this code is public domain. I make no warranty that it is useful,
  6. * correct, harmless, or environmentally safe.
  7. *
  8. * This particular file may be used however you like, including copying it
  9. * verbatim into a closed-source project, exploiting it commercially, and
  10. * removing any trace of my name from the source (although I hope you won't
  11. * do that). I welcome enhancements and corrections to this file, but I do
  12. * not require you to send me patches if you make changes.
  13. *
  14. * Unless otherwise stated, the rest of PhysicsFS falls under the GNU Lesser
  15. * General Public License: http://www.gnu.org/licenses/lgpl.txt
  16. *
  17. * SDL falls under the LGPL, too. You can get SDL at http://www.libsdl.org/
  18. *
  19. * This file was written by Ryan C. Gordon. (icculus@clutteredmind.org).
  20. */
  21. #include <stdio.h> /* used for SEEK_SET, SEEK_CUR, SEEK_END ... */
  22. #include "physfsrwops.h"
  23. static int physfsrwops_seek(SDL_RWops *rw, int offset, int whence)
  24. {
  25. PHYSFS_file *handle = (PHYSFS_file *) rw->hidden.unknown.data1;
  26. int pos = 0;
  27. if (whence == SEEK_SET)
  28. {
  29. pos = offset;
  30. } /* if */
  31. else if (whence == SEEK_CUR)
  32. {
  33. int current = PHYSFS_tell(handle);
  34. if (current == -1)
  35. {
  36. SDL_SetError("Can't find position in file: %s",
  37. PHYSFS_getLastError());
  38. return(-1);
  39. } /* if */
  40. if (offset == 0) /* this is a "tell" call. We're done. */
  41. return(offset);
  42. pos = current + offset;
  43. } /* else if */
  44. else if (whence == SEEK_END)
  45. {
  46. int len = PHYSFS_fileLength(handle);
  47. if (len == -1)
  48. {
  49. SDL_SetError("Can't find end of file: %s", PHYSFS_getLastError());
  50. return(-1);
  51. } /* if */
  52. pos = len + offset;
  53. } /* else if */
  54. else
  55. {
  56. SDL_SetError("Invalid 'whence' parameter.");
  57. return(-1);
  58. } /* else */
  59. if (!PHYSFS_seek(handle, pos))
  60. {
  61. SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
  62. return(-1);
  63. } /* if */
  64. return(pos);
  65. } /* physfsrwops_seek */
  66. static int physfsrwops_read(SDL_RWops *rw, void *ptr, int size, int maxnum)
  67. {
  68. PHYSFS_file *handle = (PHYSFS_file *) rw->hidden.unknown.data1;
  69. int rc = PHYSFS_read(handle, ptr, size, maxnum);
  70. if (rc != maxnum)
  71. {
  72. if (!PHYSFS_eof(handle)) /* not EOF? Must be an error. */
  73. SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
  74. } /* if */
  75. return(rc);
  76. } /* physfsrwops_read */
  77. static int physfsrwops_write(SDL_RWops *rw, const void *ptr, int size, int num)
  78. {
  79. PHYSFS_file *handle = (PHYSFS_file *) rw->hidden.unknown.data1;
  80. int rc = PHYSFS_write(handle, ptr, size, num);
  81. if (rc != num)
  82. SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
  83. return(rc);
  84. } /* physfsrwops_write */
  85. static int physfsrwops_close(SDL_RWops *rw)
  86. {
  87. PHYSFS_file *handle = (PHYSFS_file *) rw->hidden.unknown.data1;
  88. if (!PHYSFS_close(handle))
  89. {
  90. SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
  91. return(-1);
  92. } /* if */
  93. SDL_FreeRW(rw);
  94. return(0);
  95. } /* physfsrwops_close */
  96. static SDL_RWops *create_rwops(PHYSFS_file *handle)
  97. {
  98. SDL_RWops *retval = NULL;
  99. if (handle == NULL)
  100. SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
  101. else
  102. {
  103. retval = SDL_AllocRW();
  104. if (retval != NULL)
  105. {
  106. retval->seek = physfsrwops_seek;
  107. retval->read = physfsrwops_read;
  108. retval->write = physfsrwops_write;
  109. retval->close = physfsrwops_close;
  110. retval->hidden.unknown.data1 = handle;
  111. } /* if */
  112. } /* else */
  113. return(retval);
  114. } /* create_rwops */
  115. SDL_RWops *PHYSFSRWOPS_makeRWops(PHYSFS_file *handle)
  116. {
  117. SDL_RWops *retval = NULL;
  118. if (handle == NULL)
  119. SDL_SetError("NULL pointer passed to PHYSFSRWOPS_makeRWops().");
  120. else
  121. retval = create_rwops(handle);
  122. return(retval);
  123. } /* PHYSFSRWOPS_makeRWops */
  124. SDL_RWops *PHYSFSRWOPS_openRead(const char *fname)
  125. {
  126. return(create_rwops(PHYSFS_openRead(fname)));
  127. } /* PHYSFSRWOPS_openRead */
  128. SDL_RWops *PHYSFSRWOPS_openWrite(const char *fname)
  129. {
  130. return(create_rwops(PHYSFS_openWrite(fname)));
  131. } /* PHYSFSRWOPS_openWrite */
  132. SDL_RWops *PHYSFSRWOPS_openAppend(const char *fname)
  133. {
  134. return(create_rwops(PHYSFS_openAppend(fname)));
  135. } /* PHYSFSRWOPS_openAppend */
  136. /* end of physfsrwops.c ... */