/* * * C++ Portable Types Library (PTypes) * Version 2.1.1 Released 27-Jun-2007 * * Copyright (C) 2001-2007 Hovik Melikyan * * http://www.melikyan.com/ptypes/ * */ #include #include #include #ifdef WIN32 # include #else # include #endif #include "pstreams.h" PTYPES_BEGIN instm::instm(int ibufsize): iobase(ibufsize) { } instm::~instm() { } int instm::classid() { return CLASS_INSTM; } int instm::dorawread(char* buf, int count) { if (handle == invhandle) return -1; #ifdef WIN32 unsigned long ret; if (!ReadFile(HANDLE(handle), buf, count, &ret, nil)) #else int ret; if ((ret = ::read(handle, buf, count)) < 0) #endif { int e = uerrno(); if (e == EPIPE) ret = 0; else error(e, "Couldn't read"); } return ret; } int instm::rawread(char* buf, int count) { requireactive(); try { int ret = dorawread(buf, count); if (ret <= 0) { ret = 0; eof = true; chstat(IO_EOF); } else { abspos += ret; chstat(IO_READING); } return ret; } catch (estream*) { eof = true; chstat(IO_EOF); throw; } } large instm::tellx() { return abspos - bufend + bufpos; } void instm::bufvalidate() { requirebuf(); bufclear(); bufend = rawread(bufdata, bufsize); } large instm::seekx(large newpos, ioseekmode mode) { if (bufdata != 0 && mode != IO_END) { if (mode == IO_CURRENT) { newpos += tellx(); mode = IO_BEGIN; } // see if it is possible to seek within the buffer large newbufpos = newpos - (abspos - bufend); if (newbufpos >= 0 && newbufpos <= bufend) { bufpos = (int)newbufpos; eof = false; return tellx(); } } // if IO_END or if not possible to seek within the buffer return iobase::seekx(newpos, mode); } bool instm::get_eof() { if (!eof && bufdata != 0 && bufpos >= bufend) bufvalidate(); return eof; } int instm::get_dataavail() { get_eof(); return bufend - bufpos; } char instm::preview() { if (!eof && bufpos >= bufend) bufvalidate(); if (eof) return eofchar; return bufdata[bufpos]; } void instm::putback() { requireactive(); if (bufpos == 0) fatal(CRIT_FIRST + 14, "putback() failed"); bufpos--; eof = false; } bool instm::get_eol() { char c = preview(); return (eof || c == 10 || c == 13); } void instm::skipeol() { switch (preview()) { case 10: get(); break; case 13: get(); if (preview() == 10) get(); break; } } char instm::get() { char ret = preview(); if (!eof) bufpos++; return ret; } string instm::token(const cset& chars, int limit) { requirebuf(); string ret; while (!get_eof()) { char* b = bufdata + bufpos; char* e = bufdata + bufend; char* p = b; while (p < e && (*p & chars)) p++; int n = p - b; limit -= n; if (limit < 0) { bufpos += n + limit; error(ERANGE, "Token too long"); } concat(ret, b, n); bufpos += n; if (p < e) break; } return ret; } string instm::token(const cset& chars) { return token(chars, INT_MAX); } static cset linechars = cset("*") - cset("~0a~0d"); string instm::line(int limit) { string ret = token(linechars, limit); skipeol(); return ret; } string instm::line() { string ret = token(linechars, INT_MAX); skipeol(); return ret; } int instm::token(const cset& chars, char* buf, int count) { requirebuf(); int ret = 0; while (count > 0 && !get_eof()) { char* b = bufdata + bufpos; char* e = b + imin(count, bufend - bufpos); char* p = b; while (p < e && (*p & chars)) p++; int n = p - b; memcpy(buf, b, n); buf += n; ret += n; count -= n; bufpos += n; if (p < e) break; } return ret; } int instm::line(char* buf, int size, bool eateol) { int ret = token(linechars, buf, size); if (eateol) skipeol(); return ret; } int instm::read(void* buf, int count) { int ret = 0; if (bufdata == 0) ret = rawread(pchar(buf), count); else { while (count > 0 && !get_eof()) { int n = imin(count, bufend - bufpos); memcpy(buf, bufdata + bufpos, n); buf = pchar(buf) + n; ret += n; count -= n; bufpos += n; } } return ret; } int instm::skip(int count) { int ret = 0; requirebuf(); while (count > 0 && !get_eof()) { int n = imin(count, bufend - bufpos); ret += n; count -= n; bufpos += n; } return ret; } int instm::skiptoken(const cset& chars) { int ret = 0; requirebuf(); while (!get_eof()) { char* b = bufdata + bufpos; char* e = bufdata + bufend; char* p = b; while (p < e && (*p & chars)) p++; int n = p - b; bufpos += n; ret += n; if (p < e) break; } return ret; } void instm::skipline(bool eateol) { if (!get_eol()) skiptoken(linechars); if (eateol) skipeol(); } PTYPES_END