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 + -
显示快捷键?