[[Page010]]

* 入力streamの分離 [#w8a8178e]

このページの必要全ファイルは &ref("myapp11.tgz");.

入力streamと contents 処理を分離する。そのため、CMyReader class を導入する。また、先頭の一定量を見て、contentsの自動分類を行う。この分類はcontents処理の前に行う必要がある。またstreamによっては先頭に戻ることは不可能である場合もあるので、最初のreadの前に一定量bufferingして分類をしておく必要がある。

 // myreader.h
 #ifndef MYREADER_H_INCLUDED
 #define MYREADER_H_INCLUDED
 
 namespace mylib
 {
 class CMyReader
 {
 public:
 	virtual ~CMyReader();
 	virtual bool Read(unsigned char* buffer, size_t maxread, size_t& nread);
 	virtual int GetOctet();
 	const unsigned char* Buffer() const;
 	size_t Filled() const;
 public:
 	static const int MY_EOF = (-1);
 	static const int MY_BUFSIZE = 1024;
 
 protected:
 	CMyReader();
 	virtual bool Fill(unsigned char* buffer, size_t maxread, size_t& nread);
 
 protected:
 	bool m_bEofDetected;
 	size_t m_nFilled;
 	size_t m_nRead;
 	unsigned char m_bBuffer[MY_BUFSIZE];
 };
 
 }	// namespace mylib
 #endif	// MYREADER_H_INCLUDED

Buffering してある場合、buffer の残量と read の size が必ずしも一致するわけではないので論理が結構面倒である。そこで、派生 class では open/close 関係の他 Fill() のみ実装すれば済むようにしておく。

 // myreader.cpp
 
 #include <windows.h>
 #include "myreader.h"
 
 namespace mylib
 {
 
 CMyReader::CMyReader()
 {
 	m_bEofDetected = false;
 	m_nFilled = 0;
 	m_nRead = 0;
 }
 
 CMyReader::~CMyReader()
 {
 }
 
 bool
 CMyReader::Fill(unsigned char* buffer, size_t maxread, size_t& nread)
 {
 	nread = 0;
 	return false;
 }
 
 bool
 CMyReader::Read(unsigned char* buffer, size_t maxread, size_t& nread)
 {
 	bool result = false;
 
 	if(m_nFilled >= (m_nRead + maxread))
 	{
 		for(size_t n = 0; n < maxread; n++)
 			buffer[n] = m_bBuffer[m_nRead++];
 		nread = maxread;
 		result = true;
 	}
 	else
 	{
 		size_t k = 0;
 		for(size_t n = m_nRead; n < m_nFilled; n++)
 			buffer[k++] = m_bBuffer[n];
 		m_nRead = m_nFilled = 0;
 		if(m_bEofDetected)
 		{
 			nread = k;
 			return true;
 		}
 		m_nRead = m_nFilled = 0;
 		result = Fill(&buffer[k], (maxread - k), nread);
 		if(nread == 0)
 			m_bEofDetected = true;
 		nread = nread + k;
 	}
 	return result;
 }
 
 int
 CMyReader::GetOctet()
 {
 	if(m_nRead >= m_nFilled)
 	{
 		m_nFilled = m_nRead = 0;
 		if(m_bEofDetected)
 			return MY_EOF;
 		if(!Fill(m_bBuffer, MY_BUFSIZE, m_nFilled))
 			return MY_EOF;
 		if(m_nFilled == 0)
 		{
 			m_bEofDetected = true;
 			return MY_EOF;
 		}
 	}
 	int c = (int)m_bBuffer[m_nRead++] & 255;
 	return c;
 } 
 
 const unsigned char*
 CMyReader::Buffer() const
 {
 	return m_bBuffer;
 }
 
 size_t
 CMyReader::Filled() const
 {
 	return m_nFilled;
 }
 
 }	//namespace mylib

** CMyFileReader class の導入 [#e99cce10]
いままでの file を読む部分を CMyFileReader class とする。
いままでの file を読む部分を CMyReader から派生させた CMyFileReader class とする。上記に述べたように CMyReader で buffering は処理するので、必要なのは open/close 
 // myfilerd.h
 #ifndef MYFILERD_H_INCLUDED
 #define MYFILERD_H_INCLUDED
 
 #include "myreader.h"
 
 namespace mylib
 {
 
 class CMyFileReader : public CMyReader
 {
 public:
 	CMyFileReader(const TCHAR* szName);
 	virtual ~CMyFileReader();
 
 protected:
 	virtual bool Fill(unsigned char* buffer, size_t maxread, size_t& nread);
 
 private:
 	HANDLE m_hFile;
 };
 
 }	// namespace mylib
 #endif	// MYFILERD_H_INCLUDED


 // myfilerd.cpp
 #include <windows.h>
 #include "myfilerd.h"
 
 namespace mylib
 {
 CMyFileReader::CMyFileReader(const TCHAR* szName)
 {
 	m_hFile = ::CreateFile(szName, GENERIC_READ, FILE_SHARE_READ, 0,
 		OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
 	if(m_hFile == INVALID_HANDLE_VALUE)
 		return;
 	Fill(m_bBuffer, MY_BUFSIZE, m_nFilled);
 }
 
 CMyFileReader::~CMyFileReader()
 {
 	if(m_hFile != INVALID_HANDLE_VALUE)
 		::CloseHandle(m_hFile);
 }
 
 bool
 CMyFileReader::Fill(unsigned char* buffer, size_t maxread, size_t& nread)
 {
 	DWORD dwRead = 0;
 	if(!::ReadFile(m_hFile, buffer, maxread, &dwRead, 0))
 	{
 		nread = 0;
 		return false;
 	}
 	nread = (size_t)dwRead;
 	return true;
 }
 
 }	// namespace mylib

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS