⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fileo.cpp

📁 Shorthand是一个强大的脚本语言
💻 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 + -