Page010

入力streamの分離

このページの必要全ファイルは filemyapp11.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 の導入

いままでの 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

添付ファイル: filemyapp11.tgz 12094件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2007-08-28 (火) 11:26:55 (63d)