📄 mstream.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 + -