#ifndef _IOSTREAM_INCLUDED
#define _IOSTREAM_INCLUDED
#include <cstdio>
#include <string>
namespace std
{
  class istream
  {
  public:
    istream() {}
    virtual ~istream() {}
    virtual istream& operator>>(string& s)=0;
    virtual operator bool() const=0;
    virtual int getc()=0;
    virtual unsigned tellg()=0;
    virtual istream& seekg(unsigned off,ios::seek_dir dir)=0;
    virtual istream& getline(char* s, unsigned n, char delim)=0;
  };
  class ifstream : public istream
  {
    FILE* f;
  public:
    void open(const char* s, /*ios::open_mode*/int mode=ios::in)
    {f=fopen(s,(mode&ios::binary)?"rb":"r");}
    ifstream():f(NULL){}
    ifstream(const char* s, /*ios::open_mode*/int mode=ios::in)
    {open(s,mode);}
    ~ifstream() {if (f) fclose(f);}
    bool fail() const {return f==NULL?true:ferror(f)||feof(f);}
    operator bool() const {return !fail();}
    bool eof() const {return f==NULL?false:feof(f);}
    virtual istream& seekg(unsigned off,ios::seek_dir dir)
    {fseek(f,off,dir);return *this;}
    ifstream& read(char* s, unsigned n)
    {if (fread(s,1,n,f)!=n) f->_flag|=0200;return *this;}
    virtual unsigned tellg() {return ftell(f);}
    ifstream& getline(char* s, unsigned n)
    {fgets(s,n,f);unsigned m=strlen(s);
     if(m&&s[m-1]=='\n')s[m-1]=0;else f->_flag|=0200;return *this;}
    istream& operator>>(string& s)
    {char res[512];fscanf(f,"%s",res);s=res;return *this;}
    virtual istream& getline(char* s, unsigned n, char delim)
    {
      int c;
      unsigned pos=0;
      for (;pos<n-1;)
      {
        c=fgetc(f);
        if (c==EOF) break;
        if (c==delim) break;
        s[pos++]=c;
      }
      s[pos]=0;
      return *this;
    }
    int getc(void)
    { return fgetc(f); }
  };
  inline istream& getline(istream& is, string& str, char delim='\n')
  {
    str.erase();
    while (is)
    {
      int c = is.getc();
      if (c == EOF || c == delim)
        break;
      str += c;
    }
    return is;
  }
  class istringstream : public istream
  {
    string s;
    unsigned pos;
  public:
    istringstream(const char* str):s(str),pos(0) {}
    istringstream(const string& str):s(str.c_str()),pos(0) {}
    istringstream& operator>>(int& n)
    {int x;sscanf(s.c_str()+pos,"%d%n",&n,&x);pos+=x;return *this;}
    istream& operator>>(string& s)
    {int x;char res[512];sscanf(s.c_str()+pos,"%s%n",res,&x);pos+=x;
    s=res;return *this;}
    virtual operator bool() const {return s.c_str()[pos]!=0;}
    virtual int getc()
    {
      char c=s.c_str()[pos];
      if (c==0)
        return EOF;
      pos++;
      return c;
    }
    virtual unsigned tellg() {return pos;}
    virtual istream& seekg(unsigned off,ios::seek_dir dir)
    {
      unsigned sz=s.size();
      switch (dir)
      {
        case ios::beg: pos=off;break;
        case ios::cur: pos+=off;break;
        case ios::end: pos=sz-off;break;
      }
      if (pos>sz) pos=sz;
      return *this;
    }
    virtual istream& getline(char* str, unsigned n, char delim)
    {
      int c;
      unsigned p=0;
      for (;p<n-1;)
      {
        c=s[pos++];
        if (c==0) {pos--;break;}
        if (c==delim) break;
        str[p++]=c;
      }
      str[p]=0;
      return *this;
    }
  };
}
#endif
