FileSubStream.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*
  2. Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
  3. Permission is hereby granted, free of charge, to any person
  4. obtaining a copy of this software and associated documentation
  5. files (the "Software"), to deal in the Software without
  6. restriction, including without limitation the rights to use,
  7. copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. copies of the Software, and to permit persons to whom the
  9. Software is furnished to do so, subject to the following
  10. conditions:
  11. The above copyright notice and this permission notice shall be
  12. included in all copies or substantial portions of the Software.
  13. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  14. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  15. OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  16. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  17. HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  18. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20. OTHER DEALINGS IN THE SOFTWARE.
  21. */
  22. #include "FileSubStream.h"
  23. #include "Types.h"
  24. #include "Log.h"
  25. namespace crown
  26. {
  27. FileSubStream::FileSubStream(StreamOpenMode openMode, const Str& filename, size_t position, size_t length) :
  28. Stream(openMode), mFile(0),
  29. mSubPosition(position), mSubLength(length)
  30. {
  31. //Takes ownership
  32. if (openMode != SOM_READ)
  33. Log::E("FileSubStream accepts only SOM_READ as openMode.");
  34. mFile = File::Open(filename.c_str(), FOM_READ);
  35. size_t fileSize = mFile->GetSize();
  36. if (position >= fileSize || position + length >= fileSize)
  37. throw ArgumentException("Position and length parameters define a file subsection outside the file dimensions");
  38. fseek(mFile->GetHandle(), position, SEEK_SET);
  39. }
  40. FileSubStream::~FileSubStream()
  41. {
  42. delete mFile;
  43. mFile = 0;
  44. }
  45. uint8_t FileSubStream::ReadByte()
  46. {
  47. CheckValid();
  48. uint8_t buffer;
  49. bool error = false;
  50. if (EndOfStream())
  51. error = true;
  52. else
  53. error = fread(&buffer, 1, 1, mFile->GetHandle()) != 1;
  54. if (error)
  55. {
  56. Log::E("Could not read from file.");
  57. throw FileIOException("Could not read from file.");
  58. }
  59. return buffer;
  60. }
  61. void FileSubStream::ReadDataBlock(void* buffer, size_t size)
  62. {
  63. CheckValid();
  64. bool error = false;
  65. if (GetPosition() + size > GetSize())
  66. error = true;
  67. else
  68. error = fread(buffer, size, 1, mFile->GetHandle()) != 1;
  69. if (error)
  70. {
  71. Log::E("Could not read from file.");
  72. throw FileIOException("Could not read from file.");
  73. }
  74. }
  75. bool FileSubStream::CopyTo(Stream* stream, size_t size)
  76. {
  77. CheckValid();
  78. if (stream == 0)
  79. {
  80. return false;
  81. }
  82. if (GetPosition() + size > GetSize())
  83. {
  84. Log::E("The given size goes beyond the end of file.");
  85. return false;
  86. }
  87. const int chunksize = 1024*1024;
  88. char* buff = new char[chunksize];
  89. size_t totReadBytes = 0;
  90. while (size == 0 || totReadBytes < size)
  91. {
  92. int readBytes;
  93. readBytes = fread(buff, 1, chunksize, mFile->GetHandle());
  94. if (readBytes < chunksize)
  95. {
  96. bool returnVal;
  97. if (feof(mFile->GetHandle()))
  98. {
  99. if (readBytes != 0)
  100. {
  101. stream->WriteDataBlock(buff, readBytes);
  102. }
  103. returnVal = true;
  104. }
  105. else
  106. {
  107. returnVal = false;
  108. }
  109. delete[] buff;
  110. return returnVal;
  111. }
  112. stream->WriteDataBlock(buff, readBytes);
  113. totReadBytes += readBytes;
  114. }
  115. delete [] buff;
  116. return true;
  117. }
  118. bool FileSubStream::EndOfStream() const
  119. {
  120. return GetPosition() - mSubPosition == mSubLength;
  121. }
  122. void FileSubStream::WriteByte(uint8_t /*val*/)
  123. {
  124. Log::E("Write operation on FileSubStream not supported.");
  125. throw FileIOException("Write operation on FileSubStream not supported.");
  126. }
  127. void FileSubStream::WriteDataBlock(const void* /*buffer*/, size_t /*size*/)
  128. {
  129. Log::E("Write operation on FileSubStream not supported.");
  130. throw FileIOException("Write operation on FileSubStream not supported.");
  131. }
  132. void FileSubStream::Flush()
  133. {
  134. CheckValid();
  135. fflush(mFile->GetHandle());
  136. }
  137. void FileSubStream::Seek(int newPos, SeekMode mode)
  138. {
  139. CheckValid();
  140. //flush(); <<<---?
  141. //TODO: Add a check on file boundaries
  142. fseek(mFile->GetHandle(), newPos + mSubPosition, (mode==SM_SeekFromBegin)?SEEK_SET:(mode==SM_SeekFromCurrent)?SEEK_CUR:SEEK_END);
  143. }
  144. size_t FileSubStream::GetPosition() const
  145. {
  146. CheckValid();
  147. return ftell(mFile->GetHandle()) - mSubPosition;
  148. }
  149. size_t FileSubStream::GetSize() const
  150. {
  151. return mSubLength;
  152. }
  153. bool FileSubStream::CanRead() const
  154. {
  155. CheckValid();
  156. return Stream::CanRead();
  157. }
  158. bool FileSubStream::CanWrite() const
  159. {
  160. return false;
  161. }
  162. bool FileSubStream::CanSeek() const
  163. {
  164. return true;
  165. }
  166. }