#include <fstream>
#include <iostream>
#include <sstream>
#include <limits>

struct double_istream 
{
  std::istream &in;
  
  double_istream (std::istream &i) : in(i) {}
  
  double_istream & parse_on_fail (double &x, bool neg)
  {
    const char *exp[] = {"", "inf", "Inf", "NaN", "nan"};
    const char *e = exp[0];
    int l = 0;
    char parsed[4];
    char *c = parsed;
    if (neg) *c++ = '-';
    in.clear();
    if (!(in >> *c).good()) return *this; //If the stream is broken even before trying to read from it, it's pointless to try.
    
    switch (*c) //Switch on the first character to parse, if 'i' or 'I', set up for Infinity, else if 'n' or 'N', set up for NaN
    {
      case 'i': e = exp[l=1]; break;
      case 'I': e = exp[l=2]; break;
      case 'N': e = exp[l=3]; break;
      case 'n': e = exp[l=4]; break;
    }
    
    while (*c == *e) 
    {
      if ((e-exp[l]) == 2) break;
      ++e; 
      if (!(in >> *++c).good()) break;
    }
    
    if (in.good() && *c == *e) 
    {
      switch (l) 
      {
        case 1: case 2: x = std::numeric_limits<double>::infinity(); break;
        case 3: case 4: x = std::numeric_limits<double>::quiet_NaN(); break;
      }
      if (neg) x = -x;
      return *this;
    } 
    else if (!in.good()) 
    {
      if (!in.fail()) return *this;
      in.clear(); --c;
    }
    
    do { in.putback(*c); } while (c-- != parsed);
    in.setstate(std::ios_base::failbit);
    return *this;
  }
  
  double_istream & operator >> (double &x) {
    bool neg = false;
    char c;
    if (!in.good()) return *this;
    while (isspace(c = in.peek())) in.get();
    if (c == '-') { neg = true; }
    in >> x;
    if (! in.fail()) return *this;
    return parse_on_fail(x, neg);
  }
};

struct double_imanip 
{
  mutable std::istream *in;
  
  const double_imanip & operator >> (double &x) const 
  {
    double_istream(*in) >> x;
    return *this;
  }
  
  std::istream & operator >> (const double_imanip &) const 
  {
    return *in;
  }
};

const double_imanip & operator >> (std::istream &in, const double_imanip &dm) 
{
  dm.in = &in;
  return dm;
}

int main()
{
std::stringstream iss("1.0 -NaN inf Inf nan -inf NaN 1.2 inf");
double u, v, w, x, y, z, a, b, fail_double;
std::string fail_string;
iss >> double_imanip()
    >> u >> v >> w >> x >> y >> z >> a >> b
    >> double_imanip()
    >> fail_double;
std::cout << u << " " << v << " " << w << " "
          << x << " " << y << " " << z << " " << a << " " << b << std::endl;
if (iss.fail()) {
    iss.clear();
    iss >> fail_string;
    std::cout << fail_string << std::endl;
} else {
    std::cout << "TEST FAILED" << std::endl;
}
}