1 #ifndef _INCLUDED_MEDIA_HPP_
2 #define _INCLUDED_MEDIA_HPP_
3 
4 #include <stdio.h>
5 #include <limits.h>
6 #include <string.h>
7 
8 // type names that do not conflcit with anything else
9 typedef signed char S8;
10 typedef unsigned char U8;
11 typedef signed short int S16;
12 typedef unsigned short int U16;
13 typedef signed int S32;
14 typedef unsigned int U32;
15 
16 class MediaMedium
17 {
18 	protected:
19 		// standard constructor
MediaMedium()20 		MediaMedium() :
21 			m_fError(0),
22 			m_nDefBufSize(1024),
23 			m_pWriteBuffer(NULL),
24 			m_pReadBuffer(NULL),
25 			m_nReadBufPos(0),
26 			m_nWriteBufPos(0),
27 			m_nBufSize(0),
28 			m_nBufLenUsed(0),
29 			m_nRefCnt(1)
30 			{}
31 
~MediaMedium()32 		virtual ~MediaMedium() {}
33 
34 	public:
35 		// allow reference counting
AddRef()36 		unsigned AddRef() { return ++m_nRefCnt; }
Release()37 		unsigned Release() { if (0==(--m_nRefCnt)) { delete this; return 0;} else return m_nRefCnt; }
38 
39 		enum
40 		{
41 			// error code flags
42 			 MME_VEOFMET   = 0x00000001 // virtual end of file met
43 			,MME_EOFMET    = 0x00000002 // actual end of file met
44 			,MME_OPENFAIL  = 0x00000004 // failed to open medium
45 			,MME_CLOSEFAIL = 0x00000008 // failed to close medium
46 			,MME_UNAVAIL   = 0x00000010 // requested operation was not available
47 			,MME_IOERROR   = 0x00000020 // read/write operation failed
48 		};
49 		unsigned m_fError;
50 
51 		unsigned m_nDefBufSize; // default read or write buffer sizes for buffering small objects
52 
53 		// flush read/write buffers. You should call this function after the last read or write operation on the object
54 		// alternatively, derived (implementation) classes close methods should call this
Flush()55 		void Flush()
56 		{
57 			if (m_pReadBuffer)
58 			{
59 				unsigned nBufStartPos = DoGetPos();
60 				CloseReadBuffer(m_nReadBufPos > m_nBufLenUsed ? m_nReadBufPos : m_nBufLenUsed);
61 				DoSetPos(nBufStartPos + m_nReadBufPos);
62 				m_pReadBuffer = NULL;
63 				m_nReadBufPos = 0;
64 			}
65 			else if (m_pWriteBuffer)
66 			{
67 				unsigned nBufStartPos = DoGetPos();
68 				CloseWriteBuffer(m_nWriteBufPos > m_nBufLenUsed ? m_nWriteBufPos : m_nBufLenUsed);
69 				DoSetPos(nBufStartPos + m_nWriteBufPos);
70 				m_pWriteBuffer = NULL;
71 				m_nWriteBufPos = 0;
72 			}
73 			m_nBufSize = 0;
74 			m_nBufLenUsed = 0;
75 		}
76 
77 		// use this to write a block of raw data
WriteBlock(void const * pData,unsigned nSize)78 		void WriteBlock(void const * pData, unsigned nSize)
79 		{
80 			Flush();
81 			DoWriteBlock(pData,nSize);
82 		}
83 
84 		// this may be faster, but will only work if the block size no more than the default buffer size
WriteBufferedBlock(void const * pData,unsigned nSize)85 		void WriteBufferedBlock(void const * pData, unsigned nSize)
86 		{
87 			if (m_nWriteBufPos + nSize <= m_nBufSize)
88 			{
89 				memcpy(static_cast<char *>(m_pWriteBuffer) + m_nWriteBufPos/sizeof(char), pData, nSize);
90 				m_nWriteBufPos += nSize;
91 			}
92 			else
93 			{
94 				Flush();
95 				m_pWriteBuffer = GetWriteBuffer(&m_nBufSize,m_nDefBufSize);
96 				if (nSize <= m_nBufSize)
97 				{
98 					memcpy(m_pWriteBuffer, pData, nSize);
99 					m_nWriteBufPos = nSize;
100 				}
101 				else
102 				{
103 					m_fError |= MME_VEOFMET;
104 				}
105 			}
106 		}
107 
108 		// use this to read a block of raw data
ReadBlock(void * pData,unsigned nSize)109 		void ReadBlock(void * pData, unsigned nSize)
110 		{
111 			Flush();
112 			DoReadBlock(pData,nSize);
113 		}
114 
115 		// this may be faster, but will only work if the block size no more than the default buffer size
ReadBufferedBlock(void * pData,unsigned nSize)116 		void ReadBufferedBlock(void * pData, unsigned nSize)
117 		{
118 			if (m_nReadBufPos + nSize <= m_nBufSize)
119 			{
120 				memcpy(pData, static_cast<char const *>(m_pReadBuffer) + m_nReadBufPos/sizeof(char), nSize);
121 				m_nReadBufPos += nSize;
122 			}
123 			else
124 			{
125 				Flush();
126 				m_pReadBuffer = GetReadBuffer(&m_nBufSize,m_nDefBufSize);
127 				if (nSize <= m_nBufSize)
128 				{
129 					memcpy(pData, m_pReadBuffer, nSize);
130 					m_nReadBufPos = nSize;
131 				}
132 				else
133 				{
134 					m_fError |= MME_VEOFMET;
135 				}
136 			}
137 		}
138 
139 		// move the 'file' pointer nOffset bytes
140 		// this will not necessarily cause buffers to be flushed
141 		// if the pointer can be moved within the current buffer,
142 		// some of the buffer may be left uninitialized, and no
143 		// error will occur, which otherwise might (particularly
144 		// if the object has write access)
MovePos(signed nOffset)145 		void MovePos(signed nOffset)
146 		{
147 			if (m_pReadBuffer)
148 			{
149 				if (nOffset>0 && m_nReadBufPos+nOffset<=m_nBufSize)
150 				{
151 					m_nReadBufPos+=nOffset;
152 					return;
153 				}
154 				else if (nOffset<=0 && m_nReadBufPos>=static_cast<unsigned>(-nOffset))
155 				{
156 					if (m_nBufLenUsed < m_nReadBufPos) m_nBufLenUsed = m_nReadBufPos;
157 					m_nReadBufPos+=nOffset;
158 					return;
159 				}
160 			}
161 			else if (m_pWriteBuffer)
162 			{
163 				if (nOffset>0 && m_nWriteBufPos+nOffset<=m_nBufSize)
164 				{
165 					m_nWriteBufPos+=nOffset;
166 					return;
167 				}
168 				else if (nOffset<=0 && m_nWriteBufPos>=static_cast<unsigned>(-nOffset))
169 				{
170 					if (m_nBufLenUsed < m_nWriteBufPos) m_nBufLenUsed = m_nWriteBufPos;
171 					m_nWriteBufPos+=nOffset;
172 					return;
173 				}
174 			}
175 			// else
176 			Flush();
177 			DoSetPos(DoGetPos()+nOffset);
178 		}
179 
180 		// set the 'file' pointer
181 		// you would normally only pass values which have been
182 		// previously returned by a call to GetPos
183 		// note that this will not necessarily cause buffers to be flushed
184 		// if the pointer can be moved within the current buffer,
185 		// some of the buffer may be left uninitialized, and no
186 		// error will occur, which otherwise might (particularly
187 		// if the object has write access)
SetPos(unsigned nPos)188 		void SetPos(unsigned nPos)
189 		{
190 			unsigned nNewBufPos = nPos - DoGetPos();
191 			if (nNewBufPos <= m_nBufSize)
192 			{
193 				if (m_pReadBuffer)
194 				{
195 					if (m_nBufLenUsed < m_nReadBufPos) m_nBufLenUsed = m_nReadBufPos;
196 					m_nReadBufPos = nNewBufPos;
197 				}
198 				else // pWriteBuffer
199 				{
200 					if (m_nBufLenUsed < m_nWriteBufPos) m_nBufLenUsed = m_nWriteBufPos;
201 					m_nWriteBufPos = nNewBufPos;
202 				}
203 			}
204 			else
205 			{
206 				Flush();
207 				DoSetPos(nPos);
208 			}
209 		}
210 
211 		// get the 'file' pointer. The returned value
212 		// can be used in a call to SetPos
GetPos()213 		unsigned GetPos()
214 		{
215 			return DoGetPos()+m_nReadBufPos+m_nWriteBufPos;
216 		}
217 
218 		virtual unsigned GetRemainingSize();
219 
220 	private:
221 		void * m_pWriteBuffer;
222 		void const * m_pReadBuffer;
223 		unsigned m_nReadBufPos;
224 		unsigned m_nWriteBufPos;
225 		unsigned m_nBufSize;
226 		unsigned m_nBufLenUsed;
227 
228 		unsigned m_nRefCnt;
229 
230 	protected:
231 
232 		// the non-pure functions default implementation sets the unavailable error flag
233 
234 		// it is safe to assume that these four functions will be called in a logical order
235 		// and that only one buffer (read or write) will be required at once
236 
237 		// this two functions may return NULL only if *pSize is set to zero
238 		// *pSize should otherwise be set to the actual size of the buffer returned
239 
240 		// get a pointer to memory where data can be written to directly
241 		virtual void * GetWriteBuffer(unsigned * pSize, unsigned nDesiredSize);
242 
243 		// get a pointer to memory where data can be read from directly
244 		virtual void const * GetReadBuffer(unsigned * pSize, unsigned nDesiredSize);
245 
246 		// close the buffer 'allocated' above and assume nPosOffset bytes were transferred
247 		// and that the 'file' pointer should be positioned at the end of the transferred data
248 		virtual void CloseWriteBuffer(unsigned nPosOffset);
249 		virtual void CloseReadBuffer(unsigned nPosOffset);
250 
251 		// transfer a block of data
252 		// it is safe to assume that no buffer will be open
253 		virtual void DoWriteBlock(void const * pData, unsigned nSize);
254 		virtual void DoReadBlock(void * pData, unsigned nSize);
255 
256 		// if a buffer is open, should return pos at start of buffer
257 		virtual unsigned DoGetPos() = 0;
258 
259 		// it is safe to assume that no buffer will be open
260 		virtual void DoSetPos(unsigned nPos) = 0;
261 
262 	friend class MediaSection;
263 
264 	friend void MediaRead(MediaMedium * pThis, S8 * p);
265 	friend void MediaRead(MediaMedium * pThis, U8 * p);
266 	friend void MediaRead(MediaMedium * pThis, S16 * p);
267 	friend void MediaRead(MediaMedium * pThis, U16 * p);
268 	friend void MediaRead(MediaMedium * pThis, S32 * p);
269 	friend void MediaRead(MediaMedium * pThis, U32 * p);
270 };
271 
272 // use this to read in simple data types
273 // note especially that if the size of TYPE is greater than the
274 // default buffer size, then the operation will fail
275 // and the virtual end of file error flag will be set
276 // - use ReadBlock instead
MediaRead(MediaMedium * pThis,S8 * p)277 inline void MediaRead(MediaMedium * pThis, S8 * p)
278 {
279 	if (pThis->m_nReadBufPos + sizeof(S8) <= pThis->m_nBufSize)
280 	{
281 		*p = static_cast<S8 const *>(pThis->m_pReadBuffer)[pThis->m_nReadBufPos];
282 		pThis->m_nReadBufPos += sizeof(S8);
283 	}
284 	else
285 	{
286 		pThis->Flush();
287 		pThis->m_pReadBuffer = pThis->GetReadBuffer(&pThis->m_nBufSize,pThis->m_nDefBufSize);
288 		if (sizeof(S8) <= pThis->m_nBufSize)
289 		{
290 			*p = *static_cast<S8 const *>(pThis->m_pReadBuffer);
291 			pThis->m_nReadBufPos = sizeof(S8);
292 		}
293 		else
294 		{
295 			pThis->m_fError |= MediaMedium::MME_VEOFMET;
296 		}
297 	}
298 }
299 
MediaRead(MediaMedium * pThis,U8 * p)300 inline void MediaRead(MediaMedium * pThis, U8 * p)
301 {
302 	if (pThis->m_nReadBufPos + sizeof(U8) <= pThis->m_nBufSize)
303 	{
304 		*p = static_cast<U8 const *>(pThis->m_pReadBuffer)[pThis->m_nReadBufPos];
305 		pThis->m_nReadBufPos += sizeof(U8);
306 	}
307 	else
308 	{
309 		pThis->Flush();
310 		pThis->m_pReadBuffer = pThis->GetReadBuffer(&pThis->m_nBufSize,pThis->m_nDefBufSize);
311 		if (sizeof(U8) <= pThis->m_nBufSize)
312 		{
313 			*p = *static_cast<U8 const *>(pThis->m_pReadBuffer);
314 			pThis->m_nReadBufPos = sizeof(U8);
315 		}
316 		else
317 		{
318 			pThis->m_fError |= MediaMedium::MME_VEOFMET;
319 		}
320 	}
321 }
322 
MediaRead(MediaMedium * pThis,S16 * p)323 inline void MediaRead(MediaMedium * pThis, S16 * p)
324 {
325 	S8 b0, b1;
326 	::MediaRead(pThis, &b0);
327 	::MediaRead(pThis, &b1);
328 	*p = (b0 << 0) | (b1 << 8);
329 }
330 
MediaRead(MediaMedium * pThis,U16 * p)331 inline void MediaRead(MediaMedium * pThis, U16 * p)
332 {
333 	U8 b0, b1;
334 	::MediaRead(pThis, &b0);
335 	::MediaRead(pThis, &b1);
336 	*p = (b0 << 0) | (b1 << 8);
337 }
338 
MediaRead(MediaMedium * pThis,S32 * p)339 inline void MediaRead(MediaMedium * pThis, S32 * p)
340 {
341 	S8 b0, b1, b2, b3;
342 	::MediaRead(pThis, &b0);
343 	::MediaRead(pThis, &b1);
344 	::MediaRead(pThis, &b2);
345 	::MediaRead(pThis, &b3);
346 	*p = (b0 << 0) | (b1 << 8) | (b2 << 16) | (b3 << 24);
347 }
348 
MediaRead(MediaMedium * pThis,U32 * p)349 inline void MediaRead(MediaMedium * pThis, U32 * p)
350 {
351 	U8 b0, b1, b2, b3;
352 	::MediaRead(pThis, &b0);
353 	::MediaRead(pThis, &b1);
354 	::MediaRead(pThis, &b2);
355 	::MediaRead(pThis, &b3);
356 	*p = (b0 << 0) | (b1 << 8) | (b2 << 16) | (b3 << 24);
357 }
358 
359 #ifdef _MEDIA_WIN_TARGET
360 
361 class MediaWinFileMedium : public MediaMedium
362 {
363 	public:
MediaWinFileMedium()364 		MediaWinFileMedium() : m_hFile(INVALID_HANDLE_VALUE), m_nReadBufLen(0) {}
365 
Attach(HANDLE hFile)366 		void Attach(HANDLE hFile)
367 		{
368 			m_hFile = hFile;
369 		}
Detach()370 		void Detach()
371 		{
372 			Flush();
373 			m_hFile = INVALID_HANDLE_VALUE;
374 		}
375 
Open(char * pszFileName,DWORD dwDesiredAccess)376 		void Open(char *pszFileName, DWORD dwDesiredAccess)
377 		{
378 			DWORD dwShareMode;
379 			DWORD dwCreationDistribution;
380 			switch (dwDesiredAccess & (GENERIC_READ|GENERIC_WRITE))
381 			{
382 				case 0:
383 					dwShareMode = FILE_SHARE_READ|FILE_SHARE_WRITE;
384 					dwCreationDistribution = OPEN_EXISTING;
385 					break;
386 				case GENERIC_READ:
387 					dwShareMode = FILE_SHARE_READ;
388 					dwCreationDistribution = OPEN_EXISTING;
389 					break;
390 				case GENERIC_WRITE:
391 					dwShareMode = 0;
392 					dwCreationDistribution = CREATE_ALWAYS;
393 					break;
394 				default: // GENERIC_WRITE|GENERIC_READ
395 					dwCreationDistribution = OPEN_ALWAYS;
396 					dwShareMode = 0;
397 			}
398 			m_hFile = CreateFile
399 			(
400 				pszFileName,
401 				dwDesiredAccess,
402 				dwShareMode,
403 				0,
404 				dwCreationDistribution,
405 				FILE_ATTRIBUTE_NORMAL,
406 				0
407 			);
408 			if (INVALID_HANDLE_VALUE == m_hFile)
409 				m_fError |= MME_OPENFAIL;
410 		}
Close()411 		void Close()
412 		{
413 			if (INVALID_HANDLE_VALUE == m_hFile)
414 				m_fError |= MME_CLOSEFAIL;
415 			else
416 			{
417 				Flush();
418 				if (!CloseHandle(m_hFile))
419 					m_fError |= MME_CLOSEFAIL;
420 				else
421 					m_hFile = INVALID_HANDLE_VALUE;
422 			}
423 		}
424 
~MediaWinFileMedium()425 		~MediaWinFileMedium()
426 		{
427 			// should already be closed...
428 			Close();
429 		}
430 
431 		virtual unsigned GetRemainingSize();
432 
433 	private:
434 		HANDLE m_hFile;
435 
436 		char * m_pBuffer;
437 		unsigned m_nReadBufLen;
438 
439 	protected:
440 
441 		// get a pointer to memory where data can be written to directly
442 		virtual void * GetWriteBuffer(unsigned * pSize, unsigned nDesiredSize);
443 
444 		// get a pointer to memory where data can be read from directly
445 		virtual void const * GetReadBuffer(unsigned * pSize, unsigned nDesiredSize);
446 
447 		// close the buffer allocated above and assume nPosOffset were transferred
448 		virtual void CloseWriteBuffer(unsigned nPosOffset);
449 		virtual void CloseReadBuffer(unsigned nPosOffset);
450 
451 		// transfer a block of data: the buffer should be closed
452 		virtual void DoWriteBlock(void const * pData, unsigned nSize);
453 		virtual void DoReadBlock(void * pData, unsigned nSize);
454 
455 		// if a buffer is open, should return pos at start of buffer
456 		virtual unsigned DoGetPos();
457 
458 		// requires that no buffer is oben
459 		virtual void DoSetPos(unsigned nPos);
460 };
461 
462 #endif // _MEDIA_WIN_TARGET
463 
464 class MediaStdFileMedium : public MediaMedium
465 {
466 	public:
MediaStdFileMedium()467 		MediaStdFileMedium() : m_pFile(NULL), m_nReadBufLen(0) {}
468 
Attach(FILE * pFile)469 		void Attach(FILE * pFile)
470 		{
471 			m_pFile = pFile;
472 		}
Detach()473 		void Detach()
474 		{
475 			Flush();
476 			m_pFile = NULL;
477 		}
478 
Open(char const * pszFileName,char const * pszOpenMode)479 		void Open(char const * pszFileName, char const * pszOpenMode)
480 		{
481 			if (pszOpenMode[0] != 'r' || pszOpenMode[1] != 'b') {
482 				fprintf(stderr, "Open(%s, %s)\n", pszFileName, pszOpenMode);
483 				m_fError |= MME_OPENFAIL;
484 				return;
485 			}
486 			m_pFile = OpenGameFile(pszFileName, FILEMODE_READONLY, FILETYPE_PERM);
487 			if (!m_pFile)
488 				m_fError |= MME_OPENFAIL;
489 		}
Close()490 		void Close()
491 		{
492 			if (!m_pFile)
493 				m_fError |= MME_CLOSEFAIL;
494 			else
495 			{
496 				Flush();
497 				if (fclose(m_pFile))
498 					m_fError |= MME_CLOSEFAIL;
499 				else
500 					m_pFile = NULL;
501 			}
502 		}
503 
~MediaStdFileMedium()504 		~MediaStdFileMedium()
505 		{
506 			// should already be closed...
507 			Close();
508 		}
509 
510 		virtual unsigned GetRemainingSize();
511 
512 	private:
513 		FILE * m_pFile;
514 
515 		char * m_pBuffer;
516 		unsigned m_nReadBufLen;
517 
518 	protected:
519 
520 		// get a pointer to memory where data can be written to directly
521 		virtual void * GetWriteBuffer(unsigned * pSize, unsigned nDesiredSize);
522 
523 		// get a pointer to memory where data can be read from directly
524 		virtual void const * GetReadBuffer(unsigned * pSize, unsigned nDesiredSize);
525 
526 		// close the buffer allocated above and assume nPosOffset were transferred
527 		virtual void CloseWriteBuffer(unsigned nPosOffset);
528 		virtual void CloseReadBuffer(unsigned nPosOffset);
529 
530 		// transfer a block of data: the buffer should be closed
531 		virtual void DoWriteBlock(void const * pData, unsigned nSize);
532 		virtual void DoReadBlock(void * pData, unsigned nSize);
533 
534 		// if a buffer is open, should return pos at start of buffer
535 		virtual unsigned DoGetPos();
536 
537 		// requires that no buffer is oben
538 		virtual void DoSetPos(unsigned nPos);
539 };
540 
541 class MediaMemoryReadMedium : public MediaMedium
542 {
543 	public:
MediaMemoryReadMedium()544 		MediaMemoryReadMedium() : m_pMem(NULL) {}
545 
Open(void const * p)546 		void Open(void const * p)
547 		{
548 			m_pMem = p;
549 			m_nOffset = 0;
550 		}
551 
Close()552 		void Close()
553 		{
554 			if (m_pMem)
555 			{
556 				Flush();
557 				m_pMem = NULL;
558 			}
559 			else
560 				m_fError |= MME_CLOSEFAIL;
561 		}
562 
563 	private:
564 		void const * m_pMem;
565 
566 	protected:
567 		unsigned m_nOffset;
568 
569 		// get a pointer to memory where data can be read from directly
570 		virtual void const * GetReadBuffer(unsigned * pSize, unsigned nDesiredSize);
571 
572 		// close the buffer allocated above and assume nPosOffset were transferred
573 		virtual void CloseReadBuffer(unsigned nPosOffset);
574 
575 		// transfer a block of data: the buffer should be closed
576 		virtual void DoReadBlock(void * pData, unsigned nSize);
577 
578 		// if a buffer is open, should return pos at start of buffer
579 		virtual unsigned DoGetPos();
580 
581 		// requires that no buffer is oben
582 		virtual void DoSetPos(unsigned nPos);
583 };
584 
585 class MediaMemoryMedium : public MediaMemoryReadMedium
586 {
587 	public:
MediaMemoryMedium()588 		MediaMemoryMedium() : m_pMem(NULL) {}
589 
Open(void * p)590 		void Open(void * p)
591 		{
592 			m_pMem = p;
593 			MediaMemoryReadMedium::Open(p);
594 		}
595 
Close()596 		void Close()
597 		{
598 			MediaMemoryReadMedium::Close();
599 			m_pMem = NULL;
600 		}
601 
602 	private:
603 		void * m_pMem;
604 
605 	protected:
606 
607 		// get a pointer to memory where data can be written to directly
608 		virtual void * GetWriteBuffer(unsigned * pSize, unsigned nDesiredSize);
609 
610 		// close the buffer allocated above and assume nPosOffset were transferred
611 		virtual void CloseWriteBuffer(unsigned nPosOffset);
612 
613 		// transfer a block of data: the buffer should be closed
614 		virtual void DoWriteBlock(void const * pData, unsigned nSize);
615 };
616 
617 
618 class MediaSection : public MediaMedium
619 {
620 	public:
MediaSection()621 		MediaSection() : m_pMedium(NULL) {}
622 
Open(MediaMedium * pMedium,unsigned nMaxSize=UINT_MAX)623 		void Open(MediaMedium * pMedium, unsigned nMaxSize = UINT_MAX)
624 		{
625 			m_pMedium = pMedium;
626 			m_nMaxSize = nMaxSize;
627 			m_nPos = 0;
628 			m_nUsedPos = 0;
629 		}
Close()630 		void Close()
631 		{
632 			if (m_pMedium)
633 				Flush();
634 			if (m_nPos > m_nUsedPos) m_nUsedPos = m_nPos;
635 			m_pMedium = NULL;
636 		}
GetUsedSize() const637 		unsigned GetUsedSize() const
638 		{
639 			return (m_nPos > m_nUsedPos) ? m_nPos : m_nUsedPos;
640 		}
641 
642 		virtual unsigned GetRemainingSize();
643 
644 	private:
645 		MediaMedium * m_pMedium;
646 		unsigned m_nMaxSize;
647 		unsigned m_nPos;
648 		unsigned m_nUsedPos;
649 
650 	protected:
651 		// get a pointer to memory where data can be written to directly
652 		virtual void * GetWriteBuffer(unsigned * pSize, unsigned nDesiredSize);
653 
654 		// get a pointer to memory where data can be read from directly
655 		virtual void const * GetReadBuffer(unsigned * pSize, unsigned nDesiredSize);
656 
657 		// close the buffer allocated above and assume nPosOffset were transferred
658 		virtual void CloseWriteBuffer(unsigned nPosOffset);
659 		virtual void CloseReadBuffer(unsigned nPosOffset);
660 
661 		// transfer a block of data: the buffer should be closed
662 		virtual void DoWriteBlock(void const * pData, unsigned nSize);
663 		virtual void DoReadBlock(void * pData, unsigned nSize);
664 
665 		// if a buffer is open, should return pos at start of buffer
666 		virtual unsigned DoGetPos();
667 
668 		// requires that no buffer is oben
669 		virtual void DoSetPos(unsigned nPos);
670 };
671 
672 
673 #endif
674