file.cpp

来自「由一个古老的BASIC解释器改进而成, 保留了ANSI C固有的艺术美感.」· C++ 代码 · 共 950 行 · 第 1/2 页

CPP
950
字号
{
        using std::ios;

        ios::openmode mode= ios::in;
        switch (nmode)
        {
        case Input:
                mode= ios::in; break;
        case Output:
                mode= ios::out; break;
        case Append:
                mode= ios::out | ios::ate; break;
	default:
		throw ErrBlassicInternal;
        }
        fs.open (name.c_str (), mode);
        if (! fs.is_open () )
        	throw ErrFileNotFound;
}

bool BlFileRegular::eof ()
{
	int c= fs.get ();
	if (! fs || c == EOF)
		return true;
	fs.unget ();
	return false;
}

void BlFileRegular::flush ()
{
        fs << std::flush;
}

void BlFileRegular::getline (std::string & str)
{
	std::getline (fs, str);
	if (! fs)
	{
		if (fs.eof () )
			throw ErrPastEof;
		else
			throw ErrFileRead;
	}
}

std::string BlFileRegular::read (size_t n)
{
	util::auto_buffer <char> buf (n);
	fs.read (buf, n);
	if (! fs)
	{
		if (fs.eof () )
			throw ErrPastEof;
		else
			throw ErrFileRead;
	}
	return std::string (buf, n);
}

std::ostream & BlFileRegular::ofs ()
{
	return fs;
}

//***********************************************
//              BlFileRandom
//***********************************************

inline void BlFileRandom::field_chunk::getvar (char * buf) const
{
	assignvarstring (name, std::string (buf + pos, size) );
}

BlFileRandom::BlFileRandom (const std::string & name, size_t record_len) :
	BlFile (Random),
	len (record_len),
	actual (0),
	buf (record_len)
{
        using std::ios;

	fs.open (name.c_str (), ios::in | ios::out | ios::binary);
	if (! fs.is_open () )
		throw "Al cuerno con todo";
	std::fill_n (buf.begin (), len, '\0');
}

void BlFileRandom::put (size_t pos)
{
	if (pos != 0)
	{
		actual= pos - 1;
		fs.seekp (actual * len);
	}
	fs.write (buf, len);
	++actual;
}

namespace {

class GetVar {
public:
	GetVar (char * buf) : buf (buf) { }
	void operator () (const BlFileRandom::field_chunk & chunk)
	{
		chunk.getvar (buf);
	}
private:
	char * buf;
};

} // namespace

void BlFileRandom::get (size_t pos)
{
        using std::string;

	if (pos != 0)
		actual= pos - 1;
        fs.clear ();
        fs.seekg (actual * len);
	fs.read (buf, len);
	std::streamsize r= fs.gcount ();
	if (r < std::streamsize (len) )
		std::fill_n (buf.begin () + r, len - r, ' ');
	std::for_each (chunk.begin (), chunk.end (), GetVar (buf) );
	++actual;
}

namespace {

class MakeChunk {
public:
	MakeChunk (size_t len) :
		len (len),
		pos (0)
	{ }
	BlFileRandom::field_chunk operator ()
		(const BlFile::field_element & elem)
	{
		size_t size= elem.size;
		BlFileRandom::field_chunk fc;
		fc.name= elem.name;
		fc.pos= pos;
		fc.size= size;
		pos+= size;
		if (pos > len)
			throw ErrFieldOverflow;
		return fc;
	}
private:
	const size_t len;
	size_t pos;
};

} // namespace

void BlFileRandom::field (const std::vector <field_element> & elem)
{
        chunk.clear ();
	std::transform (elem.begin (), elem.end (),
		std::back_inserter (chunk), MakeChunk (len) );
}

namespace {

class name_is {
public:
	name_is (const std::string & name) : name (name)
	{ }
	bool operator () (const BlFileRandom::field_chunk & chunk)
	{
		return chunk.name == name;
	}
private:
	const std::string & name;
};

} // namespace

void BlFileRandom::assign (const std::string & name,
                const std::string & value, Align align)
{
	vchunk::iterator pe= std::find_if (chunk.begin (), chunk.end (),
		name_is (name) );
	if (pe == chunk.end () )
		return;
        char * init= buf + pe->pos;
        std::string str;
        std::string::size_type l= value.size ();
        if (align == AlignLeft)
        {
                if (l < pe->size)
                        str= value + std::string (pe->size - l, ' ');
                else
                        str= value.substr (0, pe->size);
        }
        else
        {
                if (l < pe->size)
                        str= std::string (pe->size - l, ' ') + value;
                else
                        str= value.substr (l - pe->size);
        }
        ASSERT (str.size () == pe->size);
	std::copy (str.begin (), str.end (), init);
}

//***********************************************
//              BlFilePopen
//***********************************************

BlFilePopen::BlFilePopen (const std::string & str, OpenMode nmode) :
        BlFile (nmode),
        bufpos (0),
        bufread (0)
{
        TraceFunc tr ("BlFilePopen::BlFilePopen");

        #ifdef _Windows

        std::string command;
        {
                const char * strCommand= getenv ("COMSPEC");
                if (strCommand == NULL)
                        strCommand= "C:\\COMMAND.COM";
                command= strCommand;
        }
        command+= " /C ";
        command+= str;

        HANDLE hread, hwrite;
        HANDLE hchild;
        const HANDLE haux= INVALID_HANDLE_VALUE;
        SECURITY_ATTRIBUTES sec;
        sec.nLength= sizeof sec;
        sec.lpSecurityDescriptor= NULL;
        sec.bInheritHandle= TRUE;
        if (CreatePipe (& hread, & hwrite, & sec, 0) == 0)
                throw "Al diablo";
        STARTUPINFO start;
        GetStartupInfo (& start);
        start.dwFlags= STARTF_USESTDHANDLES;
        switch (nmode)
        {
        case BlFile::Input:
                hpipe= hread;
                hchild= hwrite;
                start.hStdInput= haux;
                start.hStdOutput= hwrite;
                start.hStdError= hwrite;
                break;
        case BlFile::Output:
                hpipe= hwrite;
                hchild= hread;
                start.hStdInput= hread;
                start.hStdOutput= haux;
                start.hStdError= haux;
                break;
        default:
		cerr << "Bad file mode in popen" << endl;
		throw ErrBlassicInternal;
        }

        PROCESS_INFORMATION procinfo;
        BOOL createresult= CreateProcess (
                NULL, (char *) command.c_str (),
                NULL, NULL,
                TRUE, 0,
                NULL, NULL, & start, & procinfo);

        CloseHandle (hchild);

        if (createresult == 0)
        {
                CloseHandle (hpipe);
                throw "Cuernos";
        }
        CloseHandle (procinfo.hProcess);
        CloseHandle (procinfo.hThread);

	#else // No windows

	const char * type;
	switch (nmode)
	{
	case BlFile::Input:
		type= "r";
		break;
	case BlFile::Output:
		type= "w";
		break;
	default:
		cerr << "Bad file mode in popen" << endl;
		throw ErrBlassicInternal;
	}
	hpipe= popen (str.c_str (), type);
        if (hpipe == NULL)
                throw "Cuernos";

        #endif
}

BlFilePopen::~BlFilePopen ()
{
        TraceFunc tr ("BlFilePopen:~BlFilePopen");

	#ifdef _Windows

        CloseHandle (hpipe);

	#else

	pclose (hpipe);

	#endif
}

void BlFilePopen::readbuffer ()
{
        TraceFunc tr ("BlFilePopen::readbuffer");

	#ifdef _Windows

        DWORD bytesread= 0;
        ReadFile (hpipe, buffer, bufsize, & bytesread, NULL);

	#else

	size_t bytesread= ::read (fileno (hpipe), buffer, bufsize);
	if (bytesread == size_t (-1) )
		bytesread= 0;

	#endif

        bufread= bytesread;
        bufpos= 0;
}

char BlFilePopen::getcharfrombuffer ()
{
        if (bufpos >= bufread)
        {
                readbuffer ();
                if (bufread == 0)
                        return '\0';
        }
        return buffer [bufpos++];
}


bool BlFilePopen::eof ()
{
        TraceFunc tr ("BlFilePopen::eof");

        if (bufpos < bufread)
	        return false;
        readbuffer ();
        return bufread == 0;
}

void BlFilePopen::flush ()
{
}

void BlFilePopen::getline (std::string & str)
{
        TraceFunc tr ("BlFilePopen::getline");

        str= std::string ();
        char c;
        while ( (c= getcharfrombuffer () ) != '\r' && c != '\n' && c != '\0')
                str+= c;

        #ifdef _Windows

        if (c == '\r')
                getcharfrombuffer ();
        //Sleep (10);

        #endif
}

std::string BlFilePopen::read (size_t n)
{
	std::string str;
	for (size_t i= 0; i < n; ++i)
		str+= getcharfrombuffer ();
	return str;
}

void BlFilePopen::outstring (const std::string & str)
{
	TraceFunc tr ("BlFilePopen::outstring");

	const char * to= str.data ();
        std::string::size_type l= str.size ();

        #ifdef _Windows

        DWORD written;
        WriteFile (hpipe, to, l, & written, NULL);

	#else

	write (fileno (hpipe), to, l);

        #endif
}

void BlFilePopen::outchar (char c)
{
        #ifdef _Windows

        DWORD written;
        WriteFile (hpipe, & c, 1, & written, NULL);

	#else

	write (fileno (hpipe), & c, 1);

        #endif
}

//***********************************************
//              BlFileSocket
//***********************************************

BlFileSocket::BlFileSocket (const std::string & host, short port) :
	BlFile (OpenMode (Input | Output) ),
	socket (host, port)
{
}

BlFileSocket::~BlFileSocket ()
{
}

bool BlFileSocket::eof ()
{
	return socket.eof ();
}

void BlFileSocket::flush ()
{
}

void BlFileSocket::getline (std::string & str)
{
	str= socket.readline ();
}

std::string BlFileSocket::read (size_t n)
{
	util::auto_buffer <char> buf (n);
	int r= socket.read (buf, n);
	std::string result;
	if (r > 0)
		result.assign (buf, r);
	return result;
}

void BlFileSocket::outstring (const std::string & str)
{
	socket.write (str);
}

void BlFileSocket::outchar (char c)
{
	socket.write (& c, 1);
}

// Fin de file.cpp

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?