📄 fileo.cpp
字号:
///////////////////////////////////////////////////////////////////////////////
// $Header: /shorthand/src/fileo.cpp 3 1/09/03 7:14p Arm $
//-----------------------------------------------------------------------------
// Project: ShortHand interpreter
// Author: Andrei Remenchuk <andrei@remenchuk.com>
//-----------------------------------------------------------------------------
// fileo.cpp: ShortHand FILE object
///////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <errno.h>
#ifdef WIN32
#include <io.h>
#include <fcntl.h>
#endif
#include "fileo.h"
#include "except.h"
#include "value.h"
#include "module.h"
ShhFile::ShhFile(ShhModule& module, const YYLTYPE& location)
: ShhObject(module, "File", location)
{
m_file = NULL;
}
ShhFile::~ShhFile()
{
if (m_file != NULL) fclose(m_file);
}
void ShhFile::constructor(ShhValueList* args)
{
if (args == NULL || args->size() == 0 || !args->get(0)->isString())
throw new ShhObjectException("File object constructor requires file name as first argument");
args->get(0)->toString(m_name);
if (args->size() > 1)
{
args->get(1)->toString(m_mode);
}
else
{
m_mode = "r";
}
// assign read-only properties
setProperty("name", m_module.scratch().strdup(m_name));
setProperty("mode", m_module.scratch().strdup(m_mode));
m_file = ::fopen(m_name, m_mode);
if (m_file == NULL)
{
const char* msg = m_module.scratch().strdup(strerror(errno));
ShhValue tmp(msg);
setProperty("error", tmp);
}
#ifdef WIN32
if (m_file != NULL)
::_setmode(_fileno(m_file), _O_BINARY);
#endif
}
bool ShhFile::hasMethod(const char* name)
{
if (stricmp(name, "read") == 0) return true;
else if (stricmp(name, "write") == 0) return true;
else if (stricmp(name, "close") == 0) return true;
else if (stricmp(name, "eof") == 0) return true;
else if (stricmp(name, "rewind") == 0) return true;
else if (stricmp(name, "error") == 0) return true;
else return false;
}
ShhValue ShhFile::executeMethod(const char* name, ShhValueList* args)
{
ShhValue result;
int argc = args ? args->size() : 0;
if (stricmp(name, "read") == 0)
{
/**
* read specified number of bytes or entire file
*/
int size;
if (argc >= 1) size = args->get(0)->toInt();
else size = 0;
if (size < 0)
throw new ShhObjectException(6103, "read() method requires first argument positive or zero");
if (m_file == NULL)
throw new ShhObjectException(6104, "file is not opened");
string acc;
char buffer[1024];
int total_count = 0;
while(true)
{
int bytes_to_read = 1024;
if (size > 0 && size - total_count < 1024) bytes_to_read = size - total_count;
int count = fread(buffer, 1, bytes_to_read, m_file);
if (count == 0) break;
acc.append(buffer, count);
total_count += count;
if (size > 0 && total_count >= size) break;
}
if (ferror(m_file))
{
m_last_error = strerror(errno);
setProperty("ERROR", m_module.scratch().strdup(m_last_error));
}
else
{
m_last_error = "";
setProperty("ERROR", "");
}
result = m_module.scratch().strdup(acc);
}
else if (stricmp(name, "eof") == 0)
{
if (m_file == NULL)
throw new ShhObjectException(6104, "file is not opened");
result = feof(m_file);
}
else if (stricmp(name, "rewind") == 0)
{
if (m_file == NULL)
throw new ShhObjectException(6104, "file is not opened");
fseek(m_file, 0, SEEK_SET);
}
else if (stricmp(name, "readln") == 0)
{
// read one line
if (m_file == NULL)
throw new ShhObjectException(6104, "file is not opened");
string acc;
char buffer[1024];
int count;
bool got_line = false;
while((count = fread(buffer, 1, 1024, m_file)) > 0)
{
long pos = ftell(m_file) - count;
for(int i=0;i<count;i++)
{
if (buffer[i] == '\n')
{
if (i+1 < count) fseek(m_file, pos+i+1, SEEK_SET);
if (i > 0) acc.append(buffer, i);
got_line = true;
break;
}
}
if (got_line) break;
acc.append(buffer, count);
}
acc.chop("\r\n");
result = m_module.scratch().strdup(acc);
if (ferror(m_file))
{
m_last_error = strerror(errno);
setProperty("ERROR", m_module.scratch().strdup(m_last_error));
}
else
{
m_last_error = "";
setProperty("ERROR", "");
}
result = m_module.scratch().strdup(acc);
}
else if (stricmp(name, "write") == 0)
{
if (argc < 1)
throw new ShhObjectException(6102, "write() method requires argument");
if (m_file == NULL)
throw new ShhObjectException(6104, "file is not opened");
string data;
args->get(0)->toString(data);
int size;
if (argc >= 2)
size = args->get(1)->toInt();
else
size = data.length();
if (size < 0)
throw new ShhObjectException(6101, "read() method requires positive second argument");
if (size > 0)
{
result = ::fwrite(data.cstr(), 1, size, m_file);
}
else
result = 0;
if (ferror(m_file))
{
m_last_error = strerror(errno);
setProperty("ERROR", m_module.scratch().strdup(m_last_error));
}
else
{
m_last_error = "";
setProperty("ERROR", "");
}
}
else if (stricmp(name, "close") == 0)
{
if (m_file != NULL)
{
::fclose(m_file);
m_file = NULL;
}
}
else if (stricmp(name, "error") == 0)
{
result = getProperty("error");
}
return result;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -