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

📄 mstream.cpp

📁 Shorthand是一个强大的脚本语言
💻 CPP
字号:
/////////////////////////////////////////////////////////////////////////////
// $Header: /shorthand/src/mstream.cpp 4     8/28/02 6:27a Arm $
//---------------------------------------------------------------------------
// This file is part of "libAndrix" library - a collection of classes
// and functions developed by Andrei Remenchuk.
//---------------------------------------------------------------------------
// While you may own complete copyright on the project with which you have
// received this file, the author reserves the right to use code contained
// in this very file for any purposes, including publishing and usage in
// any free or commercial software.
//
// You may re-distribute this file or re-use it in your own free or
// commercial software provided that this text is included in the file.
// If you change this file you must include clear notice stating that
// you changed this file and the date of change.
//
// This statement doesn't apply to other files that are part of the same
// package unless otherwise noted.
//---------------------------------------------------------------------------
// (c) 1998-2002 Andrei Remenchuk <andrei@remenchuk.com>
//---------------------------------------------------------------------------
// mstream.cpp - memory stream
/////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdarg.h>
#include <assert.h>
#include <string.h>
#include <ctype.h>

#if defined(WIN32)
#include <io.h>
#include <malloc.h>
#else
#include <unistd.h>
#endif

#ifdef __GNUG__
#pragma implementation "mstream.h"
#endif

#include "mstream.h"
#include "utils.h"
#include "except.h"

#ifdef WIN32
//istream cin;
//ostream cout;
//ostream cerr;
#endif



mstream::mstream(int initial_capacity) 
{
    m_size = 0;
    m_capacity = initial_capacity ? initial_capacity : 1024;
    m_buffer = (char*) xmalloc(m_capacity);
    m_position = 0;
    m_byte_order = HOST_BYTE_ORDER;
    m_last_read_count = 0;
}

void mstream::set_byte_order(short new_byte_order) 
{
    m_byte_order = new_byte_order;
}

void mstream::clear() 
{
    m_position = 0;
    m_size = 0;
    bzero(m_buffer, m_capacity);
}

int mstream::seek(int offset, int from) 
{
    int target_offset;
    switch(from) 
    {
    case MSEEK_START:   target_offset = offset; break;
    case MSEEK_CURRENT: target_offset = m_position + offset; break;
    case MSEEK_END:     target_offset = m_size - offset; break;
    default: return -1;
    }
    if (target_offset < 0 || target_offset > m_size) return -1;
    m_position = target_offset;
    return 0;
}



void* mstream::provide_window(int size)
{
   int new_size = m_position + size + 2;
   if (new_size > m_capacity)
   {
        m_capacity = (new_size/2048+1)*2048;
        m_buffer = (char*) xrealloc(m_buffer, m_capacity);
   }
   return m_buffer + m_position;
 
}


int mstream::load_from_stream(FILE* f)
{
#ifdef WIN32
    _setmode(fileno(f), _O_BINARY);
#endif
    clear();
    int block_size = 8192;
    while(true)
    {
        void* window = provide_window(block_size);
        int count = ::fread(window, 1, block_size, f);
        if (count <= 0) break;
        ((char*)window)[count] = '\0';
        m_position += count;
    }

    rewind();
    return m_size;
}



int mstream::load_from_file(const char *filename) 
{
    int e;
    int flags = O_RDONLY;

#ifdef WIN32
    flags |= O_BINARY;
#endif

    int fd = ::open(filename, flags);
    if (fd < 0) 
        throw new ShhException(1401, "Cannot open file \"%s\": %s", filename, strerror(errno));

    struct stat stinfo;
    if (fstat(fd, &stinfo) != 0) 
    { 
        e = errno; close(fd); 
        throw new ShhException(1402, "Cannot read attributes of file \"%s\": %s", filename, strerror(e));
    }
    int new_size = stinfo.st_size;
    if ((new_size+1) > m_capacity) 
    {
        m_capacity = new_size+1;
        m_buffer = (char*) xrealloc(m_buffer, m_capacity);
    }
    int n_read = ::read(fd, m_buffer, new_size); e = errno;
    close(fd);
    if (n_read < new_size)
        throw new ShhException(1403, "Read operation on file \"%s\" failed", filename);
    m_position = 0;
    m_size = new_size;
    m_buffer[m_size] = '\0';
    return 0;
}


int mstream::save_to_file(const char *filename) const
{
    int omode = O_WRONLY|O_CREAT|O_TRUNC;
#ifdef WIN32    
    omode |= O_BINARY;
#endif

    int fd = open(filename, omode, 0644);
    if (fd < 0) return errno;
    int n_write = ::write(fd, m_buffer, m_size);
    close(fd);
    if (n_write < m_size) { return -1; }
    return 0;
}

int mstream::put_zeroes(int count) 
{
    if (m_position + count > m_size) m_size = m_position + count;
    if (m_size + 1 > m_capacity) 
    {
        m_capacity = ((m_size+1)/1024+1)*1024;
        m_buffer = (char*) xrealloc(m_buffer, m_capacity);
    }
    memset(m_buffer+m_position, 0, count);
    m_position += count;
    m_buffer[m_position] = '\0';
    return count;
}


int mstream::write(const void* b, int count) 
{
    if (m_position + count > m_size) m_size = m_position + count;
    if (m_size + 1 > m_capacity) 
    {
        m_capacity = ((m_size+1)/1024+1)*1024;
        m_buffer = (char*) xrealloc(m_buffer, m_capacity);
    }
    memcpy(m_buffer+m_position, b, count);
    m_position += count;
    m_buffer[m_position] = '\0';
    return count;
}

void mstream::put_z(const char *s) 
{
   short len = strlen(s)+1; 
   put_w(len);
   write(s, len);
}

void mstream::put_lz(const char *s) 
{
   int len = strlen(s)+1; 
   put_l(len);
   write(s, len);
}

void mstream::put_b(int arg) 
{
    char x = (char) (arg & 0xff);
    write(&x, 1);
}

void mstream::put_w(int arg) 
{
    short x = (short)(arg & 0xffff);

    if (m_byte_order == HOST_BYTE_ORDER) 
    {
        write(&x, 2);
    }
    else 
    {
        char d[2]; 
        d[0] = ((char*)&x)[1]; 
        d[1] = ((char*)&x)[0];
        write(d, 2);
    }
}

void mstream::put_l(int arg) 
{
    if (m_byte_order == HOST_BYTE_ORDER) 
    {
        write(&arg, 4);
    }
    else 
    {
        char x[4]; const char* s = (const char*)&arg;
        x[0] = s[3]; x[1] = s[2]; x[2] = s[1]; x[3] = s[0];
        write(x, 4);
    }
}

void mstream::put_f(double arg) 
{
    if (m_byte_order == HOST_BYTE_ORDER) 
    {
        write(&arg, 8);
    }
    else 
    {
        char x[8]; const char* s = (const char*)&arg;
        x[0] = s[7]; x[1] = s[6]; x[2] = s[5]; x[3] = s[4];
        x[4] = s[3]; x[5] = s[2]; x[6] = s[1]; x[7] = s[0];
        write(x, 8);
    }
}


int mstream::puts(const char* s) {
    int n = strlen(s);
    return write(s, n);
}


int mstream::putq(const char* s) 
{
    const char* p = s;
    unsigned int oldpos = m_position;
    while(*p) 
    {
        switch(*p) 
        {
        case '\t': puts("\\t"); break;
        case '\n': puts("\\n"); break;
        case '\r': puts("\\r"); break;
        case '\\': puts("\\\\"); break;
        case '\"': puts("\\\""); break;
        case ' ':  put_b(' '); break;
        default: 
            if (isgraph(*p)/*isalnum(*p) || strchr(" ~`'!@#$;%^:&?*()-_[]{}+=|/", *p)*/) put_b(*p);
            else printf("\\x%02X", (unsigned char)*p);
            break;
        }
        ++p;
    }
    return m_position-oldpos;
}


int mstream::putsl(const char* s) 
{
    static const char eol = '\x0a';
    int n = strlen(s);
    write(s, n);
    write(&eol, 1);
    return n+1;
}

int mstream::printf(const char* format, ...) 
{
    assert(format);
    va_list args; va_start(args, format);

    int w = vawidth(format, &args);
    char* s = (char*) alloca(w+1);
    vsprintf(s, format, args);

    int n = strlen(s);
    n = write(s, n);
    return n;
}


int mstream::vprintf(const char* format, va_list args) 
{
    int w = vawidth(format, &args);
    char* s = (char*) alloca(w+1);
    vsprintf(s, format, args);
    int n = strlen(s);
    n = write(s, n);
    return n;
}

int mstream::gcount() const
{
    return m_last_read_count;
}

int mstream::stdread(void* b, int count)
{
    int actual_count = count;
    if (m_position + actual_count > m_size) 
    {
        actual_count = m_size - m_position;
    }
    memcpy(b, m_buffer+m_position, actual_count);
    m_position += actual_count;
    m_last_read_count = actual_count;
    return actual_count;
}


int mstream::read(void* b, int count) 
{
    int actual_count = count;
    if (m_position + actual_count > m_size) 
    {
        actual_count = m_size - m_position;
        throw new ShhException(1406, "Stream read error: expected %d bytes at offset %d, only %d are available",
            count, m_position, actual_count
        );
    }
    memcpy(b, m_buffer+m_position, actual_count);
    m_position += actual_count;
    m_last_read_count = actual_count;
    return actual_count;
}

int mstream::read_zeroes(int count)
{
    int actual_count = count;
    if (m_position + actual_count > m_size) 
    {
        actual_count = m_size - m_position;
        throw new ShhException(1406, "Stream read error: expected %d bytes at offset %d, only %d are available",
            count, m_position, actual_count
        );
    }
    // just skip it
    m_position += actual_count;
    m_last_read_count;
    return actual_count;
}


const char* mstream::read_z() 
{
    char* s; int count = read_w();
    s = (char*) m_buffer + m_position;

    if (m_position + count > m_size) 
    {
        int actual_count = m_size - m_position;
        throw new ShhException(1406, "Stream read error: expected %d bytes at offset %d, only %d are available",
            count, m_position, actual_count
        );
    } 
    else 
    {
        m_position += count;
        return s;
    }
}

const char* mstream::read_lz() 
{
    char* s; 
    int count = read_l();
    s = (char*) m_buffer + m_position;

    if (m_position + count > m_size) 
    {
        int actual_count = m_size - m_position;
        throw new ShhException(1406, "Stream read error: expected %d bytes at offset %d, only %d are available",
            count, m_position, actual_count
        );
    } 
    else 
    {
        m_position += count;
        return s;
    }
}

char mstream::read_b() 
{
    char r; read(&r, 1);
    return r;
}

short mstream::read_w() 
{
    short r;
    if (m_byte_order == HOST_BYTE_ORDER) 
    {
        read(&r, 2);
    }
    else 
    {
        char x[2]; read(x, 2); char* p = (char*)&r;
        p[0] = x[1]; p[1] = x[0];
    }
    return r;
}

int mstream::read_l() 
{

    int r;
    if (m_byte_order == HOST_BYTE_ORDER) 
        read(&r, 4);
    else 
    {
        char x[4]; 
        read(x, 4); 
        char* p = (char*)&r;
        p[0] = x[3]; 
        p[1] = x[2]; 
        p[2] = x[1]; 
        p[3] = x[0];
    }
    return r;
}

double mstream::read_f() 
{
    double r;
    if (m_byte_order == HOST_BYTE_ORDER) 
    {
        read(&r, 8);
    }
    else 
    {
        char x[8]; read(x, 8); char* p = (char*)&r;
        p[0] = x[7]; p[1] = x[6]; p[2] = x[5]; p[3] = x[4];
        p[4] = x[3]; p[5] = x[2]; p[6] = x[1]; p[7] = x[0];
    }
    return r;
}


/**
 * iterates through all lines in the string.
 */
const char* mstream::next_line(void** position)
{
    char** pos = (char**) position;
    if (*pos == NULL) *pos = m_buffer;
    if (*pos < m_buffer || (*pos - m_buffer) >= m_size) return NULL;
    if (*pos == '\0') return NULL;
    
    char* line = *pos;
    char* eol = strchr(*pos, '\n');
    if (eol != NULL) {
        *eol = '\0';
        *pos = eol + 1;
    } else {
        *pos = *pos + strlen(*pos);
    }
    return line;
}


// reports whether or not there's more data after current position
bool mstream::have_more_data() const
{
    return m_position < m_size;
}

// returns a pointer to the location in buffer at current position 
const char*  mstream::remainder() const
{
    return m_buffer + m_position;
}


bool mstream::fail() const
{
    return false;
}

bool mstream::bad() const
{
    return false;
}


mstream::~mstream() 
{
    if (m_buffer != NULL) xfree(m_buffer);
}


⌨️ 快捷键说明

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