///////////////////////////////////////////////////////////////////////////////
// //
// This file is part of ModelBlocks. Copyright 2009, ModelBlocks developers. //
// //
// ModelBlocks is free software: you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation, either version 3 of the License, or //
// (at your option) any later version. //
// //
// ModelBlocks is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with ModelBlocks. If not, see . //
// //
// ModelBlocks developers designate this particular file as subject to //
// the "Moses" exception as provided by ModelBlocks developers in //
// the LICENSE file that accompanies this code. //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef _NL_STREAM__
#define _NL_STREAM__
#include "nl-string.h"
////////////////////////////////////////////////////////////////////////////////
class IStreamSource {
private:
// Data members...
String sBuff; // string buffer, to allow re-reading in disjunctions
unsigned int iAvail; // index of where string buffer begins; subtract from indices in IStream to get buffer index
FILE* pfSrc; // file pointer
public:
IStreamSource ( FILE* pf ) : sBuff(256), iAvail(0), pfSrc(pf) { }
IStreamSource ( const char* psz ) : sBuff(psz), iAvail(0), pfSrc() { }
char* c_array ( ) { return sBuff.c_array(); }
char get ( unsigned int i ) { assert(i-iAvail<((unsigned int)(-1))/2); // NOTE: PROBLEM IF ANY ISTREAM FALLS BEHIND BY MORE THAN MAXINT CHARACTERS!
int c=0; while(i-iAvail>=sBuff.size()-1){sBuff.add()=((c=getc(pfSrc))==EOF)?'\0':c;} return sBuff.get(i-iAvail); }
char& set ( unsigned int i ) { assert(i-iAvail<((unsigned int)(-1))/2); // NOTE: PROBLEM IF ANY ISTREAM FALLS BEHIND BY MORE THAN MAXINT CHARACTERS!
int c=0; while(i-iAvail>=sBuff.size()-1){sBuff.add()=((c=getc(pfSrc))==EOF)?'\0':c;} return sBuff.set(i-iAvail); }
FILE* getFile ( ) { return pfSrc; }
// Output method...
friend ostream& operator<< ( ostream& os, const IStreamSource& iss ) { return os<<"'"<iAvail to get index in psrc->sBuff
char get ( unsigned int i ) { return psrc->get(i); }
char& set ( unsigned int i ) { return psrc->set(i); }
char* c_array ( unsigned int i=0 ) { return &psrc->set(i); }
public:
IStream ( ) : psrc(NULL), iIndex(0) { }
IStream ( IStreamSource& src, unsigned int i=0 ) : psrc(&src), iIndex(i) { }
IStream ( const IStream& is, unsigned int i ) : psrc(is.psrc), iIndex(i) { }
// Specification methods...
IStream& operator= ( const IStream& is ) { psrc=is.psrc; iIndex=is.iIndex; return *this; }
// Extraction methods...
bool operator== ( const IStream& is ) const { return (psrc==is.psrc && iIndex==is.iIndex); }
bool operator!= ( const IStream& is ) const { return (psrc!=is.psrc || iIndex!=is.iIndex); }
IStreamSource* getSource() { return psrc; }
// Output method...
friend ostream& operator<< ( ostream& os, const IStream& is ) { return os<> ( IStream is, char& c ) {
// Propagate fail...
if (IStream()==is) return IStream();
c=is.get(is.iIndex);
return ('\0'==c) ? IStream() : IStream(is,is.iIndex+1);
}
// Match string delimiter...
friend IStream operator>> ( IStream is, const char* psDlm ) {
// Propagate fail...
if (IStream()==is) { return IStream(); }
unsigned int i;
// Read in characters until fail or match delimiter...
for (i=0; is.get(i+is.iIndex)!='\0' && psDlm[i]!='\0'; i++)
if (is.get(i+is.iIndex)!=psDlm[i]) return IStream();
return (psDlm[i]=='\0') ? IStream(is,i+is.iIndex) : IStream();
}
// Match anything else followed by zero-terminated string delimiter...
template friend pair operator>> ( IStream is, X& x ) { return pair(is,&x); }
template friend IStream operator>> ( pair is_x, const char* psDlm ) {
IStream& is = is_x.first;
X& x = *is_x.second;
// Propagate fail...
if (IStream()==is) { return IStream(); }
unsigned int d = strlen(psDlm);
// Read in characters until fail or match delimiter...
for (unsigned int i=is.iIndex; is.get(i)!='\0'; i++) {
// Try to match delimiter ending at current point in stream...
if ( i-is.iIndex+1>=d ) {
unsigned int j;
for (j=0; ji="<> ( pair is_x, const char* psDlm ) {
IStream& is = is_x.first;
int& x = *is_x.second;
// Propagate fail...
if (IStream()==is) return IStream();
unsigned int d = strlen(psDlm);
// Read in characters until fail or match delimiter...
for (unsigned int i=is.iIndex; is.get(i)!='\0'; i++) {
// Try to match delimiter ending at current point in stream...
if ( i+1>=is.iIndex+d ) {
unsigned int j;
for (j=0; j> ( pair is_x, const char* psDlm ) {
IStream& is = is_x.first;
unsigned int& x = *is_x.second;
// Propagate fail...
if (IStream()==is) return IStream();
unsigned int d = strlen(psDlm);
// Read in characters until fail or match delimiter...
for (unsigned int i=is.iIndex; is.get(i)!='\0'; i++) {
// Try to match delimiter ending at current point in stream...
if ( i+1>=is.iIndex+d ) {
unsigned int j;
for (j=0; j> ( pair is_x, const char* psDlm ) {
IStream& is = is_x.first;
float& x = *is_x.second;
// Propagate fail...
if (IStream()==is) return IStream();
unsigned int d = strlen(psDlm);
// Read in characters until fail or match delimiter...
for (unsigned int i=is.iIndex; is.get(i)!='\0'; i++) {
// Try to match delimiter ending at current point in stream...
if ( i+1>=is.iIndex+d ) {
unsigned int j;
for (j=0; j> ( pair is_x, const char* psDlm ) {
IStream& is = is_x.first;
double& x = *is_x.second;
// Propagate fail...
if (IStream()==is) return IStream();
unsigned int d = strlen(psDlm);
// Read in characters until fail or match delimiter...
for (unsigned int i=is.iIndex; is.get(i)!='\0'; i++) {
// Try to match delimiter ending at current point in stream...
if ( i+1>=is.iIndex+d ) {
unsigned int j;
for (j=0; j> ( pair is_x, const char* psDlm ) {
IStream& is = is_x.first;
// Propagate fail...
if (IStream()==is) return IStream();
unsigned int d = strlen(psDlm);
// Read in characters until fail or match delimiter...
for (unsigned int i=is.iIndex; is.get(i)!='\0'; i++) {
// Try to match delimiter ending at current point in stream...
if ( i+1>=is.iIndex+d ) {
unsigned int j;
for (j=0; j