File.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /**
  2. * Copyright (c) 2006-2012 LOVE Development Team
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute it
  10. * freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented; you must not
  13. * claim that you wrote the original software. If you use this software
  14. * in a product, an acknowledgment in the product documentation would be
  15. * appreciated but is not required.
  16. * 2. Altered source versions must be plainly marked as such, and must not be
  17. * misrepresented as being the original software.
  18. * 3. This notice may not be removed or altered from any source distribution.
  19. **/
  20. #include "File.h"
  21. // STD
  22. #include <cstring>
  23. // LOVE
  24. #include "Filesystem.h"
  25. #include "filesystem/FileData.h"
  26. namespace love
  27. {
  28. namespace filesystem
  29. {
  30. namespace physfs
  31. {
  32. extern bool hack_setupWriteDirectory();
  33. File::File(std::string filename)
  34. : filename(filename)
  35. , file(0)
  36. , mode(filesystem::File::CLOSED)
  37. {
  38. }
  39. File::~File()
  40. {
  41. if (mode != CLOSED)
  42. close();
  43. }
  44. bool File::open(Mode mode)
  45. {
  46. if (mode == CLOSED)
  47. return true;
  48. // File must exist if read mode.
  49. if ((mode == READ) && !PHYSFS_exists(filename.c_str()))
  50. throw love::Exception("Could not open file %s. Does not exist.", filename.c_str());
  51. // Check whether the write directory is set.
  52. if ((mode == APPEND || mode == WRITE) && (PHYSFS_getWriteDir() == 0) && !hack_setupWriteDirectory())
  53. throw love::Exception("Could not set write directory.");
  54. // File already open?
  55. if (file != 0)
  56. return false;
  57. this->mode = mode;
  58. switch (mode)
  59. {
  60. case READ:
  61. file = PHYSFS_openRead(filename.c_str());
  62. break;
  63. case APPEND:
  64. file = PHYSFS_openAppend(filename.c_str());
  65. break;
  66. case WRITE:
  67. file = PHYSFS_openWrite(filename.c_str());
  68. break;
  69. default:
  70. break;
  71. }
  72. return (file != 0);
  73. }
  74. bool File::close()
  75. {
  76. if (!PHYSFS_close(file))
  77. return false;
  78. mode = CLOSED;
  79. file = 0;
  80. return true;
  81. }
  82. int64 File::getSize()
  83. {
  84. // If the file is closed, open it to
  85. // check the size.
  86. if (file == 0)
  87. {
  88. open(READ);
  89. int64 size = (int64)PHYSFS_fileLength(file);
  90. close();
  91. return size;
  92. }
  93. return (int64)PHYSFS_fileLength(file);
  94. }
  95. FileData *File::read(int64 size)
  96. {
  97. bool isOpen = (file != 0);
  98. if (!isOpen && !open(READ))
  99. throw love::Exception("Could not read file %s.", filename.c_str());
  100. int64 max = (int64)PHYSFS_fileLength(file);
  101. size = (size == ALL) ? max : size;
  102. size = (size > max) ? max : size;
  103. FileData *fileData = new FileData(size, getFilename());
  104. read(fileData->getData(), size);
  105. if (!isOpen)
  106. close();
  107. return fileData;
  108. }
  109. int64 File::read(void *dst, int64 size)
  110. {
  111. bool isOpen = (file != 0);
  112. if (!isOpen)
  113. open(READ);
  114. int64 max = (int64)PHYSFS_fileLength(file);
  115. size = (size == ALL) ? max : size;
  116. size = (size > max) ? max : size;
  117. // Sadly, we'll have to clamp to 32 bits here
  118. size = (size > LOVE_UINT32_MAX) ? LOVE_UINT32_MAX : size;
  119. int64 read = (int64)PHYSFS_read(file, dst, 1, (int) size);
  120. if (!isOpen)
  121. close();
  122. return read;
  123. }
  124. bool File::write(const void *data, int64 size)
  125. {
  126. if (file == 0)
  127. throw love::Exception("Could not write to file. File not open.");
  128. // Another clamp, for the time being.
  129. size = (size > LOVE_UINT32_MAX) ? LOVE_UINT32_MAX : size;
  130. // Try to write.
  131. int64 written = static_cast<int64>(PHYSFS_write(file, data, 1, (int) size));
  132. // Check that correct amount of data was written.
  133. if (written != size)
  134. return false;
  135. return true;
  136. }
  137. bool File::write(const Data *data, int64 size)
  138. {
  139. return write(data->getData(), (size == ALL) ? data->getSize() : size);
  140. }
  141. #ifdef LOVE_WINDOWS
  142. // MSVC doesn't like the 'this' keyword
  143. // well, we'll use 'that'.
  144. // It zigs, we zag.
  145. inline bool test_eof(File *that, PHYSFS_File *)
  146. {
  147. int64 pos = that->tell();
  148. int64 size = that->getSize();
  149. return pos == -1 || size == -1 || pos >= size;
  150. }
  151. #else
  152. inline bool test_eof(File *, PHYSFS_File *file)
  153. {
  154. return PHYSFS_eof(file);
  155. }
  156. #endif
  157. bool File::eof()
  158. {
  159. if (file == 0 || test_eof(this, file))
  160. return true;
  161. return false;
  162. }
  163. int64 File::tell()
  164. {
  165. if (file == 0)
  166. return -1;
  167. return (int64)PHYSFS_tell(file);
  168. }
  169. bool File::seek(uint64 pos)
  170. {
  171. if (file == 0)
  172. return false;
  173. if (!PHYSFS_seek(file, (PHYSFS_uint64)pos))
  174. return false;
  175. return true;
  176. }
  177. std::string File::getFilename() const
  178. {
  179. return filename;
  180. }
  181. std::string File::getExtension() const
  182. {
  183. std::string::size_type idx = filename.rfind('.');
  184. if (idx != std::string::npos)
  185. return filename.substr(idx+1);
  186. else
  187. return std::string();
  188. }
  189. filesystem::File::Mode File::getMode()
  190. {
  191. return mode;
  192. }
  193. } // physfs
  194. } // filesystem
  195. } // love