
#ifndef TINYSTL_ISTREAM
#define TINYSTL_ISTREAM

// fread/fwrite
#include <stdio.h>

// strlen
#include <memory.h>

#include <ios>
#include <streambuf>

namespace std {
  
  /* This is just the start */
  
  class basic_istream : virtual public basic_ios {
  public:
    
    basic_istream () {
    }

    basic_istream (FILE* f) {
      m_f = f;
    }
    
    basic_istream (basic_streambuf* sb) {
      // TODO: streambuf = sb;
    }
    
    virtual ~basic_istream () {
    }
    
    // TODO: implement them ...
    basic_istream& operator>> (bool& n){
      int c = get ();
      if (c == '0')
	n = false;
      else if (c == '1')
	n = true;
      else {
	putback (c);
	setstate (badbit);
      }
      return *this;
    }

    basic_istream& operator>> (short& n) {
      const char* fmt;
      if (flags() & dec)
        fmt = "%hd";
      else
        fmt = "%hx";

      if (fscanf (m_f, fmt, &n) == 0)
        setstate (badbit);
      return *this;
    }

    basic_istream& operator>> (unsigned short& n) {
      const char* fmt;
      if (flags() & dec)
        fmt = "%hd";
      else
        fmt = "%hx";
      int i;
      if (fscanf (m_f, fmt, &i) == 0)
        setstate (badbit);
      n = i;
      return *this;
    }

    basic_istream& operator>> (int& n) {
      const char* fmt;
      if (flags() & dec)
	fmt = "%d";
      else
	fmt = "%x";

      int i;
      if (fscanf (m_f, fmt, &i) == 0)
	setstate (badbit);
      n = i;
      return *this;
    }

    basic_istream& operator>> (unsigned int& n) {
      const char* fmt;
      if (flags() & dec)
	fmt = "%d";
      else
	fmt = "%x";
      
      if (fscanf (m_f, fmt, &n) == 0) {
	setstate (badbit);
      }
      return *this;
    }

    basic_istream& operator>> (long& n) {
      if (fscanf (m_f, "%ld", &n) == 0)
	setstate (badbit);
      return *this;
    }
    
    basic_istream& operator>> (unsigned long& n) {
      if (fscanf (m_f, "%lud", &n) == 0)
	setstate (badbit);
      return *this;
    }

    basic_istream& operator>> (float& f) {
      if (fscanf (m_f, "%f", &f) == 0)
	setstate (badbit);
      return *this;
    }

    basic_istream& operator>> (double& f) {
      if (fscanf (m_f, "%lf", &f) == 0)
	setstate (badbit);
      return *this;
    }

    basic_istream& operator>> (long double& f) {
      if (fscanf (m_f, "%Lf", &f) == 0)
	setstate (badbit);
      return *this;
    }

    basic_istream& operator>> (void*& p) {
      if (fscanf (m_f, "%p", &p) == 0)
	setstate (badbit);
      return *this;
    }
    
    int get () {
      int c = fgetc (m_f);
      if (c == EOF)
	setstate(eofbit|badbit);
      return c;
    }

    basic_istream& get (char& c) {
      c = get();
      return *this;
    }
    
    basic_istream& unget () {
      // TODO: implement
      return *this;
    }
    
    basic_istream& putback (char c) {
      ungetc (c, m_f);
      return *this;
    }

    basic_istream& get (char* str, streamsize count, char delim = '\n') {
      // TODO:
      return *this;
    }
    
    basic_istream& getline (char* str, streamsize count, char delim = '\n') {
      int c = get();
      for ( ; c != delim && count > 0 ; --count) {
	*str++ = c;
	c = get();
      }
      return *this;
    }
    
    // basic_istream& ignore (streamsize count, char t = eof);
    
    basic_istream& read (char* str, streamsize count) {
      int c = get();
      for ( ; !eof() && count > 0 ; --count) {
	*str++ = c;
	c = get();
      }
      return *this;
    }

    streamsize readsome (char* str, streamsize count) {
      count = fread (str, 1, count, m_f);
      // no state manipulation as in ths standard
      return count;
    }

    int peek () {
      // TODO: Really implement it ...
      int c = get ();
      putback ((char )c);
      return c;
    }
    
    // TODO
    /*
      pos_type tellg();
      seekg(offset);
      seekg(offset,ros); */
    
    
    
  protected:
    FILE* m_f;
  };
  
  typedef basic_istream istream;
}

#endif // TINYSTL_ISTREAM
