1//
2// This file is part of the aMule Project.
3//
4// Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org )
5// Copyright (c) 2002-2011 Merkur ( devs@emule-project.net / http://www.emule-project.net )
6//
7// Any parts of this program derived from the xMule, lMule or eMule project,
8// or contributed by third-party developers are copyrighted by their
9// respective authors.
10//
11// This program is free software; you can redistribute it and/or modify
12// it under the terms of the GNU General Public License as published by
13// the Free Software Foundation; either version 2 of the License, or
14// (at your option) any later version.
15//
16// This program is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19// GNU General Public License for more details.
20//
21// You should have received a copy of the GNU General Public License
22// along with this program; if not, write to the Free Software
23// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
24//
25
26#ifndef SAFEFILE_H
27#define SAFEFILE_H
28
29
30#include <wx/filename.h>			// Needed for wxFileName
31#include <common/MuleDebug.h>			// Needef for CMuleException
32#include "Tag.h"
33
34namespace Kademlia {
35	class CUInt128;
36}
37using Kademlia::CUInt128;
38class CMD4Hash;
39
40
41/**
42 * This class provides a interface for safe file IO.
43 *
44 * Basic IO operations will either succeed or throw an exception,
45 * so that failure cannot be ignored. There are currently 3 types
46 * of failures: Read past EOF, errors while reading, and errors
47 * while writing.
48 *
49 * Beyond basic IO, the interface provides functions for reading
50 * and writing a number of simple data-types. These are all written
51 * and read as little-endian in order to allow for communication
52 * across platforms.
53 *
54 * Note that when empty areas are created, for instance by seeking
55 * past the end, then writing, the value of bytes where no data was
56 * explicitly written is not specified.
57 */
58class CFileDataIO
59{
60public:
61	/**
62	 * The Destructor does nothing, but is needed to allow
63	 * for safe deletion objects via CFileDataIO pointers.
64	 */
65	virtual ~CFileDataIO();
66
67
68	/**
69	 * Must return the current position in the file.
70	 */
71	virtual uint64 GetPosition() const = 0;
72
73	/**
74	 * Must return the length of the file-object in bytes.
75	 */
76	virtual uint64 GetLength() const = 0;
77
78	/**
79	 * Returns true when the file-position is past or at the end of the file.
80	 */
81	virtual bool Eof() const;
82
83
84	/**
85	 * Changes the file position.
86	 *
87	 * Note that seeking to an negative position is an illegal operation.
88	 *
89	 * @see wxFile::Seek
90	 */
91	virtual uint64 Seek(sint64 offset, wxSeekMode from = wxFromStart) const;
92
93
94	/**
95	 * Reads 'count' bytes into 'buffer'.
96	 *
97	 * @param buffer The target buffer.
98	 * @param count The number of bytes to read.
99	 *
100	 * Note that Read will read the specified number of
101	 * bytes unless this would read past the end of the
102	 * file. In that case, a CEOFException is thrown and
103	 * the position and target buffer is left unchanged.
104	 *
105	 * However, it is also possible that the read will
106	 * fail due to IO errors (bad hardware, ect), in which
107	 * case an CIOFailureException will be thrown.
108	 */
109	virtual void Read(void* buffer, size_t count) const;
110
111	/**
112	 * Write 'count' bytes from 'buffer' into the file.
113	 *
114	 * @param buffer The source-data buffer.
115	 * @param count The number of bytes to write.
116	 *
117	 * Note that Write will throw a CIOFailureException
118	 * if it fails to write the specified number of bytes,
119	 * which can be caused by hardware failures, lack of
120	 * free space, etc.
121	 */
122	virtual void Write(const void* buffer, size_t count);
123
124
125	/**
126	 * Reads the given type from the file, stored as little-endian.
127	 *
128	 * @see CSafeFileIO::Read
129	 */
130	//@{
131	virtual uint8		ReadUInt8() const;
132	virtual uint16		ReadUInt16() const;
133	virtual uint32		ReadUInt32() const;
134	virtual uint64		ReadUInt64() const;
135	virtual CUInt128	ReadUInt128() const;
136	virtual CMD4Hash	ReadHash() const;
137	virtual float		ReadFloat() const;
138	virtual unsigned char*	ReadBsob(uint8* size) const;
139	//@}
140
141	/**
142	 * Reads a string from the file.
143	 *
144	 * @param bOptUTF8 Specifies if the string is UTF8 encoded.
145	 * @param lenBytes The number of bytes used to store the string length.
146	 * @param SafeRead Avoids throwing CEOFException, see below.
147	 * @return The resulting text-string.
148	 *
149	 * Note that when SafeRead is set to true, CSafeFileIO will crop the length
150	 * read from the lenght-field (see lenBytes), so that at most GetLength() -
151	 * GetPosition() bytes are read.
152	 *
153	 * @see CSafeFileIO::Read
154	 */
155 	virtual wxString	ReadString(bool bOptUTF8, uint8 lenBytes = 2, bool SafeRead = false) const;
156
157	/**
158	 * Reads a string from the file, where the length is specified directly.
159	 *
160	 * @param bOptUTF8 Specifies if the string is UTF8 encoded.
161	 * @param length The length of the string.
162	 * @return The resulting text-string.
163	 *
164	 * This function is typically used when the text-fields length is not stored
165	 * as an integer-field in front of the text-field.
166	 */
167	virtual wxString	ReadOnlyString(bool bOptUTF8, uint16 length) const;
168
169
170	/**
171	 * Writes a value of the given type to the file, storing it as little-endian.
172	 *
173	 * @see CSafeFileIO::Write
174	 */
175	//@{
176	virtual void WriteUInt8(uint8 value);
177	virtual void WriteUInt16(uint16 value);
178	virtual void WriteUInt32(uint32 value);
179	virtual void WriteUInt64(uint64 value);
180	virtual void WriteUInt128(const CUInt128& value);
181	virtual void WriteHash(const CMD4Hash& value);
182	virtual void WriteFloat(float value);
183	virtual void WriteBsob( const unsigned char* val, uint8 size);
184	//@}
185
186	/**
187	 * Writes a text-string to the file.
188	 *
189	 * @param str The string to be written.
190	 * @param encoding The text-ecoding, see EUtf8Str.
191	 * @param lenBytes The number of bytes used to store the string length.
192	 *
193	 * Valid values for the 'lenBytes' parameters is 0 bytes (no length field),
194	 * 2 bytes and 4 bytes.
195	 *
196	 * @see CSafeFileIO::Write
197	 */
198	virtual void WriteString(const wxString& str, EUtf8Str encoding = utf8strNone, uint8 lenBytes = 2);
199
200/* Warning: Special Kad functions, needs documentation */
201
202	CTag*		ReadTag(bool bOptACP = false) const;
203	void		ReadTagPtrList(TagPtrList* taglist, bool bOptACP = false) const;
204
205	void		WriteTag(const CTag& tag);
206	void		WriteTagPtrList(const TagPtrList& tagList);
207
208/* Special ED2Kv2 function */
209	uint64		GetIntTagValue() const;
210
211/* Some functions I added for simplicity */
212	// Very obvious
213	bool IsEmpty() { return (GetLength() == 0); }
214
215	// Appends to the end
216	void Append(const uint8* buffer, int n) { Seek(0, wxFromEnd); Write(buffer, n); }
217
218protected:
219	/**
220	 * The actual read / write function, as implemented by subclasses.
221	 *
222	 * @param buffer The buffer to read data into / write data from.
223	 * @param count The number of bytes to read / written.
224	 * @return The number of bytes read / written or -1 in case of errors.
225	 *
226	 * Note that the return value must be the actual number of bytes
227	 * read or written, with the exception that in case of errors, -1
228	 * may be returned. This is because the return value is used to
229	 * detect if the operation succeded.
230	 *
231	 * This function should not throw Either of the CSafeIOExceptions,
232	 * this is done by the CSafeFileIO::Read and the CSafeFileIO::Write
233	 * functions.
234	 */
235	//@{
236	virtual sint64 doRead(void* buffer, size_t count) const = 0;
237	virtual sint64 doWrite(const void* buffer, size_t count) = 0;
238	//@}
239
240	/**
241	 * The actual seek function, as implemented by subclasses.
242	 *
243	 * @param offset The absolute offset to seek to.
244	 * @return The resulting offset.
245	 *
246	 * This function should not throw of the CSafeIOExceptions,
247	 * this is handled by the CSafeFileIO::Seek. At the moment,
248	 * seeks that fail are considered a fatal error.
249	 */
250	virtual sint64 doSeek(sint64 offset) const = 0;
251
252private:
253	/**
254	 * Helper-function that does the actual writing of the string.
255	 *
256	 * @param str The string to be written.
257	 * @param encoding The encoding of the string.
258	 * @param lenBytes The number of bytes used to store the string length.
259	 *
260	 */
261	void WriteStringCore(const char* str, EUtf8Str encoding, uint8 lenBytes);
262};
263
264
265/**
266 * The base class of IO exceptions used by
267 * the CSafeFileIO interface and implementations
268 * of the interface.
269 */
270struct CSafeIOException : public CMuleException
271{
272	CSafeIOException(const wxString& type, const wxString& desc);
273};
274
275
276/**
277 * This exception is thrown when attempts are
278 * made at reading past the end of the file.
279 *
280 * This typically happens when a invalid packet
281 * is received that is shorter than expected and
282 * is not fatal.
283 */
284struct CEOFException : public CSafeIOException {
285	CEOFException(const wxString& desc);
286};
287
288
289/**
290 * This exception reflects a failure in performing
291 * basic IO operations read and write. It will be
292 * thrown in case a read or a write fails to read
293 * or write the specified number of bytes.
294 */
295struct CIOFailureException : public CSafeIOException {
296	CIOFailureException(const wxString& type, const wxString& desc);
297	CIOFailureException(const wxString& desc);
298};
299
300
301#endif // SAFEFILE_H
302// File_checked_for_headers
303