1 /*
2  *	HT Editor
3  *	stream.h
4  *
5  *	Copyright (C) 1999-2002 Stefan Weyergraf (stefan@weyergraf.de)
6  *
7  *	This program is free software; you can redistribute it and/or modify
8  *	it under the terms of the GNU General Public License version 2 as
9  *	published by the Free Software Foundation.
10  *
11  *	This program is distributed in the hope that it will be useful,
12  *	but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *	GNU General Public License for more details.
15  *
16  *	You should have received a copy of the GNU General Public License
17  *	along with this program; if not, write to the Free Software
18  *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 
21 #ifndef __STREAM_H__
22 #define __STREAM_H__
23 
24 #include <stdarg.h>
25 #include <stdio.h>
26 
27 #include "data.h"
28 #include "str.h"
29 #include "io/file.h"
30 
31 class String;
32 
33 /**
34  *	A stream.
35  */
36 class Stream {
37 private:
38 	IOAccessMode mAccessMode;
39 protected:
40 		void			checkAccess(IOAccessMode mask);
41 public:
42 					Stream();
~Stream()43 	virtual				~Stream() {};
44 	/* new */
45 	virtual	FileOfs			copyAllTo(Stream *stream);
46 	virtual	FileOfs			copyTo(Stream *stream, FileOfs count);
47 	virtual	IOAccessMode		getAccessMode() const;
48 	virtual	String &		getDesc(String &result) const;
49 	virtual	uint			read(void *buf, uint size);
50 		void			readx(void *buf, uint size);
51 	virtual	int			setAccessMode(IOAccessMode mode);
52 		void			setAccessModex(IOAccessMode mode);
53 	virtual	uint			write(const void *buf, uint size);
54 		void			writex(const void *buf, uint size);
55 
56 		char *			readstrz();
57 		bool			readStringz(String &s);
58 		void			writestrz(const char *str);
59 
60 		char *			readstrp();
61 		void			writestrp(const char *str);
62 
63 		char *			readstrw();
64 		void			writestrw( const char *str);
65 
66 		char *			readstrl();
67 		void			writestrl(const char *str);
68 		void *			readmeml(uint32 &len);
69 		void			writememl(void *mem, uint32 len);
70 };
71 
72 /**
73  *	A stream, layering a stream.
74  */
75 class StreamLayer: public Stream {
76 protected:
77 	Stream *mStream;
78 	bool mOwnStream;
79 
80 public:
81 
82 					StreamLayer(Stream *stream, bool own_stream);
83 	virtual				~StreamLayer();
84 	/* extends Stream */
85 	virtual IOAccessMode		getAccessMode() const;
86 	virtual String &		getDesc(String &result) const;
87 	virtual uint			read(void *buf, uint size);
88 	virtual int			setAccessMode(IOAccessMode mode);
89 	virtual uint			write(const void *buf, uint size);
90 	/* new */
91 		Stream *		getLayered() const;
92 	virtual	void			setLayered(Stream *newLayered, bool ownNewLayered);
93 };
94 
95 
96 #define	OS_FMT_DEC		0
97 #define	OS_FMT_HEX		1
98 
99 class GetObject;
100 
101 /**
102  *	A stream-layer, storing/loading |Object|s.
103  */
104 class ObjectStream: public StreamLayer {
105 public:
106 				ObjectStream(Stream *stream, bool own_stream);
107 	/* new */
108 	virtual void		getBinary(void *buf, uint size, const char *desc) = 0;
109 	virtual bool		getBool(const char *desc) = 0;
110 	virtual uint64		getInt(uint size, const char *desc) = 0;
111 	virtual Object *	getObjectInternal(const char *name, ObjectID id = OBJID_INVALID) = 0;
112 		GetObject	getObject(const char *name, ObjectID id = OBJID_INVALID);
113 	virtual char *		getString(const char *desc) = 0;
114 	virtual byte *		getLenString(int &length, const char *desc) = 0;
115 
116 	virtual void		putBinary(const void *mem, uint size, const char *desc) = 0;
117 	virtual void		putBool(bool b, const char *desc) = 0;
118 	virtual void		putComment(const char *comment) = 0;
119 	virtual void		putCommentf(const char *comment_format, ...);
120 	virtual void		putInt(uint64 i, uint size, const char *desc, uint int_fmt_hint = OS_FMT_DEC) = 0;
121 	virtual void		putObject(const Object *object, const char *name, ObjectID id = OBJID_INVALID) = 0;
122 	virtual void		putSeparator() = 0;
123 	virtual void		putString(const char *string, const char *desc) = 0;
124 	virtual void		putLenString(const byte *string, int length, const char *desc) = 0;
125 
126 	virtual void		corrupt() = 0;
127 };
128 
129 class GetObject {
130 private:
131 	friend GetObject ObjectStream::getObject(const char *name, ObjectID id);
132 
133 	ObjectStream &mO;
134 	const char *mName;
135 	ObjectID mId;
136 
137 	GetObject(ObjectStream &o, const char *name, ObjectID id = OBJID_INVALID)
mO(o)138 		: mO(o), mName(name), mId(id)
139 	{
140 	}
141 
142 	GetObject operator=(const GetObject &); // not implemented
143 
144 public:
145 	template <typename T> operator T* () const
146 	{
147 		return static_cast<T*>(mO.getObjectInternal(mName, mId));
148 	}
149 };
150 
getObject(const char * name,ObjectID id)151 inline GetObject ObjectStream::getObject(const char *name, ObjectID id)
152 {
153 	return GetObject(*this, name, id);
154 }
155 
156 #define PUTX_BINARY(st, d, size, dstr)	(st).putBinary(d, size, dstr)
157 #define PUTX_BOOL(st, d, dstr)		(st).putBool(d, dstr)
158 #define PUTX_INT(st, d, size, dstr)	(st).putInt(d, size, dstr)
159 #define PUTX_INTD(st, d, size, dstr)	(st).putInt(d, size, dstr, OS_FMT_DEC)
160 #define PUTX_INTX(st, d, size, dstr)	(st).putInt(d, size, dstr, OS_FMT_HEX)
161 #define PUTX_INT8(st, d, dstr)		(st).putInt(d, 1, dstr)
162 #define PUTX_INT8D(st, d, dstr)		(st).putInt(d, 1, dstr, OS_FMT_DEC)
163 #define PUTX_INT8X(st, d, dstr)		(st).putInt(d, 1, dstr, OS_FMT_HEX)
164 #define PUTX_INT16(st, d, dstr)		(st).putInt(d, 2, dstr)
165 #define PUTX_INT16D(st, d, dstr)	(st).putInt(d, 2, dstr, OS_FMT_DEC)
166 #define PUTX_INT16X(st, d, dstr)	(st).putInt(d, 2, dstr, OS_FMT_HEX)
167 #define PUTX_INT32(st, d, dstr)		(st).putInt(d, 4, dstr)
168 #define PUTX_INT32D(st, d, dstr)	(st).putInt(d, 4, dstr, OS_FMT_DEC)
169 #define PUTX_INT32X(st, d, dstr)	(st).putInt(d, 4, dstr, OS_FMT_HEX)
170 #define PUTX_INT64(st, d, dstr)		(st).putInt(d, 8, dstr)
171 #define PUTX_INT64D(st, d, dstr)	(st).putInt(d, 8, dstr, OS_FMT_DEC)
172 #define PUTX_INT64X(st, d, dstr)	(st).putInt(d, 8, dstr, OS_FMT_HEX)
173 #define PUTX_OBJECT(st, d, dstr)	(st).putObject(d, dstr)
174 #define PUTX_STRING(st, d, dstr)	(st).putString(d, dstr)
175 #define PUTX_LSTRING(st, d, len, dstr)	(st).putLenString(d, len, dstr)
176 
177 #define PUT_BINARY(st, d, size)		PUTX_BINARY(st, d, size, #d)
178 #define PUT_BOOL(st, d)			PUTX_BOOL(st, d, #d)
179 #define PUT_INT(st, d, size)		PUTX_INT(st, d, size, #d)
180 #define PUT_INTD(st, d, size)		PUTX_INTD(st, d, size, #d)
181 #define PUT_INTX(st, d, size)		PUTX_INTX(st, d, size, #d)
182 #define PUT_INT8(st, d)			PUTX_INT8(st, d, #d)
183 #define PUT_INT8D(st, d)		PUTX_INT8D(st, d, #d)
184 #define PUT_INT8X(st, d)		PUTX_INT8X(st, d, #d)
185 #define PUT_INT16(st, d)		PUTX_INT16(st, d, #d)
186 #define PUT_INT16D(st, d)		PUTX_INT16D(st, d, #d)
187 #define PUT_INT16X(st, d)		PUTX_INT16X(st, d, #d)
188 #define PUT_INT32(st, d)		PUTX_INT32(st, d, #d)
189 #define PUT_INT32D(st, d)		PUTX_INT32D(st, d, #d)
190 #define PUT_INT32X(st, d)		PUTX_INT32X(st, d, #d)
191 #define PUT_INT64(st, d)		PUTX_INT64(st, d, #d)
192 #define PUT_INT64D(st, d)		PUTX_INT64D(st, d, #d)
193 #define PUT_INT64X(st, d)		PUTX_INT64X(st, d, #d)
194 #define PUT_OBJECT(st, d)		PUTX_OBJECT(st, d, #d)
195 #define PUT_STRING(st, d)		PUTX_STRING(st, d, #d)
196 #define PUT_LSTRING(st, d, len)		PUTX_LSTRING(st, d, len, #d)
197 
198 #define GETX_BINARY(st, d, size, dstr)	(st).getBinary(d, size, dstr)
199 #define GETX_BOOL(st, dstr)		(st).getBool(dstr)
200 #define GETX_INT(st, size, dstr)	(st).getInt(size, dstr)
201 #define GETX_INTD(st, size, dstr)       GETX_INT(st, size, dstr)
202 #define GETX_INTX(st, size, dstr)       GETX_INT(st, size, dstr)
203 #define GETX_INT8(st, dstr)		(st).getInt(1, dstr)
204 #define GETX_INT8D(st, dstr)		GETX_INT8(st, dstr)
205 #define GETX_INT8X(st, dstr)		GETX_INT8(st, dstr)
206 #define GETX_INT16(st, dstr)		(st).getInt(2, dstr)
207 #define GETX_INT16D(st, dstr)		GETX_INT16(st, dstr)
208 #define GETX_INT16X(st, dstr)		GETX_INT16(st, dstr)
209 #define GETX_INT32(st, dstr)		(st).getInt(4, dstr)
210 #define GETX_INT32D(st, dstr)		GETX_INT32(st, dstr)
211 #define GETX_INT32X(st, dstr)		GETX_INT32(st, dstr)
212 #define GETX_INT64(st, dstr)		(st).getInt(8, dstr)
213 #define GETX_INT64D(st, dstr)		GETX_INT64(st, dstr)
214 #define GETX_INT64X(st, dstr)		GETX_INT64(st, dstr)
215 #define GETX_STRING(st, dstr)		(st).getString(dstr)
216 #define GETX_LSTRING(st, size, dstr)	(st).getLenString(size, dstr)
217 #define GETX_OBJECT(st, dstr)		(st).getObject(dstr)
218 
219 #define GET_BINARY(st, d, size)		GETX_BINARY(st, d, size, #d)
220 #define GET_BOOL(st, d)			d=GETX_BOOL(st, #d)
221 #define GET_INT(st, d, size)		d=GETX_INT(st, size, #d)
222 #define GET_INTD(st, d, size)		d=GET_INT(st, d, size)
223 #define GET_INTX(st, d, size)		d=GET_INT(st, d, size)
224 #define GET_INT8(st, d)			d=GETX_INT8(st, #d)
225 #define GET_INT8D(st, d)		d=GETX_INT8D(st, #d)
226 #define GET_INT8X(st, d)		d=GETX_INT8X(st, #d)
227 #define GET_INT16(st, d)		d=GETX_INT16(st, #d)
228 #define GET_INT16D(st, d)		d=GETX_INT16D(st, #d)
229 #define GET_INT16X(st, d)		d=GETX_INT16X(st, #d)
230 #define GET_INT32(st, d)		d=GETX_INT32(st, #d)
231 #define GET_INT32D(st, d)		d=GETX_INT32D(st, #d)
232 #define GET_INT32X(st, d)		d=GETX_INT32X(st, #d)
233 #define GET_INT64(st, d)		d=GETX_INT64(st, #d)
234 #define GET_INT64D(st, d)		d=GETX_INT64D(st, #d)
235 #define GET_INT64X(st, d)		d=GETX_INT64X(st, #d)
236 #define GET_STRING(st, d)		d=GETX_STRING(st, #d)
237 #define GET_LSTRING(st, d, size)	d=GETX_LSTRING(st, size, #d)
238 #define GET_OBJECT(st, d)		d=GETX_OBJECT(st, #d)
239 
240 /**
241  *	A object-stream-layer.
242  */
243 class ObjectStreamLayer: public ObjectStream {
244 protected:
245 	ObjectStream	*mObjStream;
246 public:
247 				ObjectStreamLayer(ObjectStream *aObjStream, bool own_ostream);
248 	/* extends ObjectStream */
249 	virtual void		getBinary(void *buf, uint size, const char *desc);
250 	virtual bool		getBool(const char *desc);
251 	virtual uint64		getInt(uint size, const char *desc);
252 	virtual Object *	getObjectInternal(const char *name, ObjectID id = OBJID_INVALID);
253 	virtual char *		getString(const char *desc);
254 	virtual byte *		getLenString(int &length, const char *desc);
255 
256 	virtual void		putBinary(const void *mem, uint size, const char *desc);
257 	virtual void		putBool(bool b, const char *desc);
258 	virtual void		putComment(const char *comment);
259 	virtual void		putInt(uint64 i, uint size, const char *desc, uint int_fmt_hint = OS_FMT_DEC);
260 	virtual void		putObject(const Object *object, const char *name, ObjectID id = OBJID_INVALID);
261 	virtual void		putSeparator();
262 	virtual void		putString(const char *string, const char *desc);
263 	virtual void		putLenString(const byte *string, int length, const char *desc);
264 };
265 
266 /* cntl cmd */
267 #define FCNTL_MODS_INVD			0x00000001
268 #define FCNTL_MODS_FLUSH		0x00000002
269 #define FCNTL_MODS_CLEAR_DIRTY_RANGE	0x00000003	// const FileOfs offset, const FileOfs range
270 #define FCNTL_MODS_IS_DIRTY		0x00000004	// const FileOfs offset, const FileOfs range, bool &isdirty
271 #define FCNTL_CACHE_INVD		0x00000005
272 #define FCNTL_FLUSH_STAT		0x00000006
273 #define FCNTL_GET_RELOC			0x00000007	// bool &enabled
274 #define FCNTL_SET_RELOC			0x00000008	// bool enable
275 #define FCNTL_GET_FD			0x00000009	// int &fd
276 
277 // Return a "modification count" that changes, every time the file state
278 // ( content, size, pstat ) changes.
279 // While identical mod-counts imply identical file states,
280 // different mod-counts do not necessarily imply different file states !
281 #define FCNTL_GET_MOD_COUNT		0x00000009	// int &mcount
282 
283 #define IS_DIRTY_SINGLEBIT		0x80000000
284 
285 /**
286  *	A file.
287  */
288 class File: public Stream {
289 protected:
290 	int mcount;
291 public:
292 		File();
293 	/* new */
294 		int			cntl(uint cmd, ...);
295 	virtual void			cut(FileOfs size);
296 	virtual void			extend(FileOfs newsize);
297 	virtual String &		getFilename(String &result) const;
298 	virtual FileOfs			getSize() const;
299 	virtual void			insert(const void *buf, FileOfs size);
300 	virtual void			pstat(pstat_t &s) const;
301 	virtual void			seek(FileOfs offset);
302 	virtual FileOfs			tell() const;
303 	virtual void			truncate(FileOfs newsize);
304 	virtual int			vcntl(uint cmd, va_list vargs);
305 
306 		void			move(FileOfs src, FileOfs dest, FileOfs size);
307 		char *			fgetstrz();
308 		String &		fgetstrz(String &result);
309 };
310 
311 /**
312  *	A file, layering a file.
313  */
314 class FileLayer: public File {
315 protected:
316 	File *mFile;
317 	bool mOwnFile;
318 public:
319 					FileLayer(File *file, bool own_file);
320 	virtual 			~FileLayer();
321 	/* extends File */
322 	virtual void			cut(FileOfs size);
323 	virtual void			extend(FileOfs newsize);
324 	virtual IOAccessMode		getAccessMode() const;
325 	virtual String &		getDesc(String &result) const;
326 	virtual String &		getFilename(String &result) const;
327 	virtual FileOfs			getSize() const;
328 	virtual void			insert(const void *buf, FileOfs size);
329 	virtual void			pstat(pstat_t &s) const;
330 	virtual uint			read(void *buf, uint size);
331 	virtual void			seek(FileOfs offset);
332 	virtual int			setAccessMode(IOAccessMode mode);
333 	virtual FileOfs			tell() const;
334 	virtual void			truncate(FileOfs newsize);
335 	virtual int			vcntl(uint cmd, va_list vargs);
336 	virtual uint			write(const void *buf, uint size);
337 	/* new */
338 		File *			getLayered() const;
339 	virtual	void			setLayered(File *newLayered, bool ownNewLayered);
340 };
341 
342 /**
343  *	A local file (file descriptor [fd]).
344  */
345 class LocalFileFD: public File {
346 protected:
347 	String		mFilename;
348 	FileOpenMode	mOpenMode;
349 
350 	int fd;
351 	bool own_fd;
352 
353 	FileOfs offset;
354 
355 		int		setAccessModeInternal(IOAccessMode mode);
356 public:
357 
358 				LocalFileFD(const String &aFilename, IOAccessMode mode, FileOpenMode aOpenMode);
359 				LocalFileFD(int fd, bool own_fd, IOAccessMode mode);
360 	virtual 		~LocalFileFD();
361 	/* extends File */
362 	virtual String &	getDesc(String &result) const;
363 	virtual String &	getFilename(String &result) const;
364 	virtual FileOfs		getSize() const;
365 	virtual uint		read(void *buf, uint size);
366 	virtual void		seek(FileOfs offset);
367 	virtual int		setAccessMode(IOAccessMode mode);
368 	virtual FileOfs 	tell() const;
369 	virtual void		truncate(FileOfs newsize);
370 	virtual int		vcntl(uint cmd, va_list vargs);
371 	virtual uint		write(const void *buf, uint size);
372 };
373 
374 /**
375  *	A local file (file stream [FILE*]).
376  */
377 class LocalFile: public File {
378 protected:
379 	String		mFilename;
380 	FileOpenMode	mOpenMode;
381 
382 	SYS_FILE *	file;
383 	bool		own_file;
384 
385 	FileOfs		offset;
386 
387 		int		setAccessModeInternal(IOAccessMode mode);
388 public:
389 				LocalFile(const String &aFilename, IOAccessMode mode, FileOpenMode aOpenMode);
390 				LocalFile(SYS_FILE *file, bool own_file, IOAccessMode mode);
391 	virtual			~LocalFile();
392 	/* extends File */
393 	virtual String &	getDesc(String &result) const;
394 	virtual String &	getFilename(String &result) const;
395 	virtual FileOfs		getSize() const;
396 	virtual void		pstat(pstat_t &s) const;
397 	virtual uint		read(void *buf, uint size);
398 	virtual void		seek(FileOfs offset);
399 	virtual int		setAccessMode(IOAccessMode mode);
400 	virtual FileOfs 	tell() const;
401 	virtual void		truncate(FileOfs newsize);
402 	virtual int		vcntl(uint cmd, va_list vargs);
403 	virtual uint		write(const void *buf, uint size);
404 };
405 
406 /**
407  *	A temporary file.
408  */
409 class TempFile: public LocalFile {
410 public:
411 				TempFile(IOAccessMode mode);
412 	/* extends File */
413 	virtual String &	getDesc(String &result) const;
414 	virtual void		pstat(pstat_t &s) const;
415 };
416 
417 /**
418  *	A fixed-size, read-only file, mapping a area of memory.
419  */
420 class ConstMemMapFile: public File {
421 protected:
422 	FileOfs ofs, pos;
423 	uint size;
424 	const void *buf;
425 public:
426 				ConstMemMapFile(const void *buf, uint size, FileOfs ofs=0);
427 	/* extends File */
428 	virtual String &	getDesc(String &result) const;
429 	virtual FileOfs	getSize() const;
430 	virtual uint		read(void *buf, uint size);
431 	virtual void		seek(FileOfs offset);
432 	virtual FileOfs 	tell() const;
433 };
434 
435 /**
436  *	A fixed-size file, mapping a area of memory.
437  */
438 class MemMapFile: public ConstMemMapFile {
439 public:
440 				MemMapFile(void *buf, uint size, FileOfs ofs=0);
441 	/* extends Stream */
442 	virtual uint		write(const void *buf, uint size);
443 };
444 
445 /**
446  *	A (read-only) file with zero-content.
447  */
448 class NullFile: public File {
449 public:
450 				NullFile();
451 	/* extends File */
452 	virtual void		extend(FileOfs newsize);
453 	virtual String &	getDesc(String &result) const;
454 	virtual FileOfs	getSize() const;
455 	virtual void		pstat(pstat_t &s) const;
456 	virtual uint		read(void *buf, uint size);
457 	virtual void		seek(FileOfs offset);
458 	virtual int		setAccessMode(IOAccessMode mode);
459 	virtual FileOfs 	tell() const;
460 	virtual void		truncate(FileOfs newsize);
461 	virtual uint		write(const void *buf, uint size);
462 };
463 
464 /**
465  *	A file, existing only in memory.
466  */
467 class MemoryFile: public File {
468 protected:
469 	FileOfs ofs;
470 	FileOfs pos;
471 	uint bufsize, dsize, ibufsize;
472 	byte *buf;
473 
474 	virtual	uint		extendBufSize(uint bufsize);
475 	virtual	uint		shrinkBufSize(uint bufsize);
476 		void		extendBuf();
477 		void		shrinkBuf();
478 		void		resizeBuf(uint newsize);
479 public:
480 				MemoryFile(FileOfs ofs = 0, uint size = 0, IOAccessMode mode = IOAM_READ | IOAM_WRITE);
481 	virtual 		~MemoryFile();
482 	/* extends File */
483 	virtual void		extend(FileOfs newsize);
484 	virtual IOAccessMode	getAccessMode() const;
485 	virtual String &	getDesc(String &result) const;
486 	virtual FileOfs		getSize() const;
487 	virtual void		pstat(pstat_t &s) const;
488 	virtual uint		read(void *buf, uint size);
489 	virtual void		seek(FileOfs offset);
490 	virtual int		setAccessMode(IOAccessMode mode);
491 	virtual FileOfs 	tell() const;
492 	virtual void		truncate(FileOfs newsize);
493 	virtual uint		write(const void *buf, uint size);
494 	/* new */
495 		byte *		getBufPtr() const;
496 };
497 
498 /**
499  *	A file layer, representing a cropped version of a file
500  */
501 class CroppedFile: public FileLayer {
502 protected:
503 	FileOfs mCropStart;
504 	bool	mHasCropSize;
505 	FileOfs mCropSize;
506 public:
507 				// crop [start; start+size-1]
508 				CroppedFile(File *file, bool own_file, FileOfs aCropStart, FileOfs aCropSize);
509 				// no size, just start
510 				CroppedFile(File *file, bool own_file, FileOfs aCropStart);
511 	/* extends FileLayer */
512 	virtual void		extend(FileOfs newsize);
513 	virtual String &	getDesc(String &result) const;
514 	virtual FileOfs		getSize() const;
515 	virtual void		pstat(pstat_t &s) const;
516 	virtual uint		read(void *buf, uint size);
517 	virtual void		seek(FileOfs offset);
518 	virtual FileOfs 	tell() const;
519 	virtual void		truncate(FileOfs newsize);
520 	virtual uint		write(const void *buf, uint size);
521 };
522 
523 
524 #endif /* __STREAM_H__ */
525