// include all the streams headers and <string>, to
// ensure they are compatible.
#include <string>
#include <ios>
#include <iomanip>
#include <iostream>
#include <fstream>
#include <sstream>
#ifdef _MSC_VER
#  include "vcl_msvc_warnings.h"
#endif

// This appears to do nothing, and it doesn't compile on MSVC with some weird error
//      'flux' : illegal member initialization: 'fstream' is not a base or member
#ifndef _MSC_VER
struct flux : public std::fstream
{
  // check that bitwise OR of {openmode}s works.
  flux(std::ios::openmode mode = std::ios::in | std::ios::binary)
    : std::fstream("/tmp/flux", mode)
  {}
};
#endif

int
test_iostream_main(int /*argc*/, char * /*argv*/[])
{
  std::cout << std::string("hello, vcl") << std::endl
            << std::oct << 01000 << std::endl
            << std::hex << 0x1000 << std::endl
            << std::dec << 1000 << std::endl
            << std::endl;

  // I/O formatting
  std::cin.flags(std::ios::skipws | std::ios::boolalpha);
  std::cout.unsetf(std::ios::dec);
  const std::ios::fmtflags flgs =
    std::cout.setf(std::ios::uppercase | std::ios::showbase | std::ios::showpos | std::ios::showpoint);
  std::cout.setf(std::ios::oct, std::ios::basefield);
  std::cout.setf(std::ios::scientific, std::ios::floatfield);
  std::cout.setf(std::ios::left, std::ios::adjustfield);
  std::cout << "Scientific, precision=2, width=20, pad_right : [";
  std::cout.precision(2);
  std::cout.width(20);
  std::cout.fill('x');
  // Note that precision() only applies to the next numeric or string entry!
  std::cout << 27182.81828 << "] oct " << 10 << std::endl;
  std::cout.flags(std::ios::showbase | std::ios::showpoint);
  std::cout.setf(std::ios::hex, std::ios::basefield);
  std::cout.setf(std::ios::fixed, std::ios::floatfield);
  std::cout.setf(std::ios::right, std::ios::adjustfield);
  std::cout << "Fixed,      precision=2, width=20, pad_left  : [";
  std::cout.width(20);
  std::cout << 27182.81828 << "] hex " << 10 << std::endl;
  std::cout.flags(flgs); // restore
  std::cout.setf(std::ios::showpos);
  std::cout.setf((std::ios::fmtflags)0, std::ios::floatfield);
  std::cout.setf(std::ios::internal, std::ios::adjustfield);
  std::cout << "Default,    precision=2, width=20, pad_intern: [";
  std::cout.precision(2);
  std::cout.width(20);
  std::cout << 27182.81828 << "] dec " << 10 << std::endl << std::endl;

  // Now the same output, using manipulators from <iomanip> :
  if (false)
    std::cin >> std::ws >> std::boolalpha;
  std::cout << std::resetiosflags(std::ios::dec) << std::uppercase << std::showbase << std::showpos << std::showpoint
            << std::oct << std::scientific << std::left << "Scientific, precision=2, width=20, pad_right : ["
            << std::setprecision(2) << std::setw(20) << std::setfill('x') << 27182.81828 << "] oct " << 10 << std::endl
            << std::nouppercase << std::noshowpos << std::hex << std::fixed << std::right
            << "Fixed,      precision=2, width=20, pad_left  : [" << std::setw(20) << 27182.81828 << "] hex " << 10
            << std::endl
            << std::noshowbase << std::showpos << std::noshowpoint
            << std::resetiosflags(std::ios::fixed | std::ios::scientific)
            << std::resetiosflags(std::ios::right | std::ios::left) << std::dec << std::internal
            << "Default,    precision=2, width=20, pad_intern: [" << std::setprecision(2) << std::setw(20)
            << 27182.81828 << "] dec " << 10 << std::endl
            << std::endl;

  std::streampos a = std::cin.tellg();
  std::streampos b = std::cout.tellp();
  a = b;
  b = a; // quell warning about unused vars. compilers are sooo gullible.

  std::streambuf * ptr = nullptr;
  if (ptr) // quell warning.
    ++ptr;

  std::streamsize size = 3141;
  ++size; // quell warning.

  if (false)
  {
    int x = 0;
    std::cin >> x; // read from stdin [27.3.1.2]
    std::cout << "cout goes to stdout [27.3.1.3]" << std::endl;
    std::cerr << "cerr goes to stderr [27.3.1.4]" << std::endl;
    std::clog << "clog goes to stderr [27.3.1.5]" << std::endl;
  }

  if (false)
  {
    std::ofstream f("dont_worry_this_file_is_not_created",
                    std::ios::in | std::ios::out | std::ios::ate | std::ios::app | std::ios::trunc | std::ios::binary);

    f.write("hello, file", 11);
    f.seekp(10);
    f.seekp(-2, std::ios::cur);
    f.seekp(1, std::ios::beg);
    f.seekp(-1, std::ios::end);
    f.close();
  }

  if (false)
  {
    signed char sc = 0;
    std::cin >> sc;

    bool bb = false;
    std::cin >> bb;
  }

  const std::stringstream s(std::ios::in | std::ios::out | std::ios::binary);

  return !s;
}
