archivelib.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. /*
  2. Copyright (C) 2001-2006, William Joseph.
  3. All Rights Reserved.
  4. This file is part of GtkRadiant.
  5. GtkRadiant is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. GtkRadiant 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. You should have received a copy of the GNU General Public License
  14. along with GtkRadiant; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. */
  17. #if !defined (INCLUDED_ARCHIVELIB_H)
  18. #define INCLUDED_ARCHIVELIB_H
  19. #include "debugging/debugging.h"
  20. #include "iarchive.h"
  21. #include "stream/filestream.h"
  22. #include "stream/textfilestream.h"
  23. #include "memory/allocator.h"
  24. #include "string/string.h"
  25. /// \brief A single-byte-reader wrapper around an InputStream.
  26. /// Optimised for reading one byte at a time.
  27. /// Uses a buffer to reduce the number of times the wrapped stream must be read.
  28. template<typename InputStreamType, int SIZE = 1024>
  29. class SingleByteInputStream
  30. {
  31. typedef typename InputStreamType::byte_type byte_type;
  32. static const int BUFFERSIZE = SIZE;
  33. InputStreamType& m_inputStream;
  34. byte_type m_buffer[BUFFERSIZE];
  35. byte_type* m_cur;
  36. byte_type* m_end;
  37. public:
  38. SingleByteInputStream(InputStreamType& inputStream) : m_inputStream(inputStream), m_cur(m_buffer + BUFFERSIZE), m_end(m_cur)
  39. {
  40. }
  41. bool readByte(byte_type& b)
  42. {
  43. if(m_cur == m_end)
  44. {
  45. if(m_end != m_buffer + BUFFERSIZE)
  46. {
  47. return false;
  48. }
  49. m_end = m_buffer + m_inputStream.read(m_buffer, BUFFERSIZE);
  50. m_cur = m_buffer;
  51. if(m_end == m_buffer)
  52. {
  53. return false;
  54. }
  55. }
  56. b = *m_cur++;
  57. return true;
  58. }
  59. };
  60. /// \brief A binary-to-text wrapper around an InputStream.
  61. /// Converts CRLF or LFCR line-endings to LF line-endings.
  62. template<typename BinaryInputStreamType>
  63. class BinaryToTextInputStream : public TextInputStream
  64. {
  65. SingleByteInputStream<BinaryInputStreamType> m_inputStream;
  66. public:
  67. BinaryToTextInputStream(BinaryInputStreamType& inputStream) : m_inputStream(inputStream)
  68. {
  69. }
  70. std::size_t read(char* buffer, std::size_t length)
  71. {
  72. char* p = buffer;
  73. for(;;)
  74. {
  75. if(length != 0 && m_inputStream.readByte(*reinterpret_cast<typename BinaryInputStreamType::byte_type*>(p)))
  76. {
  77. if(*p != '\r')
  78. {
  79. ++p;
  80. --length;
  81. }
  82. }
  83. else
  84. {
  85. return p - buffer;
  86. }
  87. }
  88. }
  89. };
  90. /// \brief An ArchiveFile which is stored uncompressed as part of a larger archive file.
  91. class StoredArchiveFile : public ArchiveFile
  92. {
  93. CopiedString m_name;
  94. FileInputStream m_filestream;
  95. SubFileInputStream m_substream;
  96. FileInputStream::size_type m_size;
  97. public:
  98. typedef FileInputStream::size_type size_type;
  99. typedef FileInputStream::position_type position_type;
  100. StoredArchiveFile(const char* name, const char* archiveName, position_type position, size_type stream_size, size_type file_size)
  101. : m_name(name), m_filestream(archiveName), m_substream(m_filestream, position, stream_size), m_size(file_size)
  102. {
  103. }
  104. static StoredArchiveFile* create(const char* name, const char* archiveName, position_type position, size_type stream_size, size_type file_size)
  105. {
  106. return New<StoredArchiveFile>().scalar(name, archiveName, position, stream_size, file_size);
  107. }
  108. void release()
  109. {
  110. Delete<StoredArchiveFile>().scalar(this);
  111. }
  112. size_type size() const
  113. {
  114. return m_size;
  115. }
  116. const char* getName() const
  117. {
  118. return m_name.c_str();
  119. }
  120. InputStream& getInputStream()
  121. {
  122. return m_substream;
  123. }
  124. };
  125. /// \brief An ArchiveTextFile which is stored uncompressed as part of a larger archive file.
  126. class StoredArchiveTextFile : public ArchiveTextFile
  127. {
  128. CopiedString m_name;
  129. FileInputStream m_filestream;
  130. SubFileInputStream m_substream;
  131. BinaryToTextInputStream<SubFileInputStream> m_textStream;
  132. public:
  133. typedef FileInputStream::size_type size_type;
  134. typedef FileInputStream::position_type position_type;
  135. StoredArchiveTextFile(const char* name, const char* archiveName, position_type position, size_type stream_size)
  136. : m_name(name), m_filestream(archiveName), m_substream(m_filestream, position, stream_size), m_textStream(m_substream)
  137. {
  138. }
  139. static StoredArchiveTextFile* create(const char* name, const char* archiveName, position_type position, size_type stream_size)
  140. {
  141. return New<StoredArchiveTextFile>().scalar(name, archiveName, position, stream_size);
  142. }
  143. void release()
  144. {
  145. Delete<StoredArchiveTextFile>().scalar(this);
  146. }
  147. const char* getName() const
  148. {
  149. return m_name.c_str();
  150. }
  151. TextInputStream& getInputStream()
  152. {
  153. return m_textStream;
  154. }
  155. };
  156. /// \brief An ArchiveFile which is stored as a single file on disk.
  157. class DirectoryArchiveFile : public ArchiveFile
  158. {
  159. CopiedString m_name;
  160. FileInputStream m_istream;
  161. FileInputStream::size_type m_size;
  162. public:
  163. typedef FileInputStream::size_type size_type;
  164. DirectoryArchiveFile(const char* name, const char* filename)
  165. : m_name(name), m_istream(filename)
  166. {
  167. if(!failed())
  168. {
  169. m_istream.seek(0, FileInputStream::end);
  170. m_size = m_istream.tell();
  171. m_istream.seek(0);
  172. }
  173. else
  174. {
  175. m_size = 0;
  176. }
  177. }
  178. bool failed() const
  179. {
  180. return m_istream.failed();
  181. }
  182. void release()
  183. {
  184. delete this;
  185. }
  186. size_type size() const
  187. {
  188. return m_size;
  189. }
  190. const char* getName() const
  191. {
  192. return m_name.c_str();
  193. }
  194. InputStream& getInputStream()
  195. {
  196. return m_istream;
  197. }
  198. };
  199. /// \brief An ArchiveTextFile which is stored as a single file on disk.
  200. class DirectoryArchiveTextFile : public ArchiveTextFile
  201. {
  202. CopiedString m_name;
  203. TextFileInputStream m_inputStream;
  204. public:
  205. DirectoryArchiveTextFile(const char* name, const char* filename)
  206. : m_name(name), m_inputStream(filename)
  207. {
  208. }
  209. bool failed() const
  210. {
  211. return m_inputStream.failed();
  212. }
  213. void release()
  214. {
  215. delete this;
  216. }
  217. const char* getName() const
  218. {
  219. return m_name.c_str();
  220. }
  221. TextInputStream& getInputStream()
  222. {
  223. return m_inputStream;
  224. }
  225. };
  226. #endif