#ifndef cathlibcpp_ios_H
#define cathlibcpp_ios_H

// File:       ios.h
// Author:     (c) Miles Sabin, 1997
// Purpose:    approximation to ANSI C++ ios header

// Change log:
//  16/01/00   Corrected naming of manipulators. (by Alexander Thoukydides)


#ifndef included_ctype_H
#define included_ctype_H
#include <ctype.h>                   // for isspace()
#endif

#ifndef included_stddef_H
#define included_stddef_H
#include <stddef.h>                  // for size_t
#endif

#ifndef cathlibcpp_bool_H
#include "bool.h"
#endif

#ifndef cathlibcpp_config_H
#include "config.h"
#endif

#ifndef cathlibcpp_exception_H
#include "exception.h"
#endif

#ifndef cathlibcpp_iosfwd_H
#include "iosfwd.h"
#endif

#ifndef cathlibcpp_string_H
#include "string.h"                  // for char_traits_char
#endif

#ifndef cathlibcpp_typeinfo_H
#include "typeinfo.h"
#endif


typedef int streamoff;
typedef int streamsize;

class ios_base;
class basic_ios_char;

typedef basic_ios_char ios;


// manipulators

ios_base& boolalpha   (ios_base& str);
ios_base& noboolalpha (ios_base& str);

ios_base& showbase    (ios_base& str);
ios_base& noshowbase  (ios_base& str);

ios_base& showpoint   (ios_base& str);
ios_base& noshowpoint (ios_base& str);

ios_base& showpos     (ios_base& str);
ios_base& noshowpos   (ios_base& str);

ios_base& skipws      (ios_base& str);
ios_base& noskipws    (ios_base& str);

ios_base& uppercase   (ios_base& str);
ios_base& nouppercase (ios_base& str);


// adjustfield

ios_base& internal    (ios_base& str);
ios_base& left        (ios_base& str);
ios_base& right       (ios_base& str);


// basefield

ios_base& dec         (ios_base& str);
ios_base& hex         (ios_base& str);
ios_base& oct         (ios_base& str);


// floatfield

ios_base& fixed       (ios_base& str);
ios_base& scientific  (ios_base& str);


// ios_base

class ios_base
{
  friend class basic_istream_char_sentry;
  friend class basic_ostream_char_sentry;

  public:

    // types

    class failure : public exception
    {
      public:

        failure(char const* msg);
        ~failure();

        char const* what() const;

        RTTI_SCAFFOLDING_DECL

      private:

        char const* msg_;
    };

    enum
    {
      boolalpha   = 1<<0,
      left        = 1<<1,
      right       = 1<<2,
      internal    = 1<<3,
      dec         = 1<<4,
      oct         = 1<<5,
      hex         = 1<<6,
      scientific  = 1<<7,
      fixed       = 1<<8,
      showbase    = 1<<9,
      showpoint   = 1<<10,
      showpos     = 1<<11,
      skipws      = 1<<12,
      unitbuf     = 1<<13,
      uppercase   = 1<<14,
      adjustfield = left|right|internal,
      basefield   = dec|oct|hex,
      floatfield  = scientific|fixed
    };

    typedef int fmtflags;

    enum
    {
      goodbit     = 0,
      badbit      = 1<<0,
      eofbit      = 1<<1,
      failbit     = 1<<2,
    };

    typedef int iostate;

    enum
    {
      app         = 1<<0,
      ate         = 1<<1,
      binary      = 1<<2,
      in          = 1<<3,
      out         = 1<<4,
      trunc       = 1<<5
    };

    typedef int openmode;

    enum
    {
      beg,
      cur,
      end
    };

    typedef int seekdir;

    // init objects not needed with this implementation.
    // class Init provided for ANSI compatability.
    class Init
    {
      public:

        Init() {}
        ~Init() {}
    };

    // fmtflags state
    fmtflags flags() const;
    fmtflags flags(fmtflags fmtfl);

    fmtflags setf(fmtflags fmtfl);
    fmtflags setf(fmtflags fmtfl, fmtflags mask);
    void unsetf(fmtflags mask);

    int precision() const;
    int precision(int prec);

    int width() const;
    int width(int wide);

    // storage
    static int xalloc();
    long& iword(int index);
    void*& pword(int index);

    // destructor
    ~ios_base();   // intentionally non-virtual

    static bool sync_with_stdio(bool sync = true);

  protected:

    // constructors
    ios_base();

    void init();
    void copyfmt(ios_base const& rhs);

  private:

    static inline bool get_sync_with_stdio()
      { return sync_with_stdio_; }

    // implementation idea idea borrowed from libg++
    struct long_and_ptr
    {
      void* p;
      long i;
    };

    long_and_ptr& get_array_element(int index);

    fmtflags fmtflags_;
    int precision_;
    int width_;
    long_and_ptr* arrays_;

    static int index_;
    static bool sync_with_stdio_;
};


class basic_ostream_char;
class basic_streambuf_char;


class basic_ios_char : public ios_base
{
  public:

    // types
    typedef char_traits_char traits;

    // iostate flags
    operator void*() const;
    bool operator!() const;

    iostate rdstate() const;
    void clear(iostate state = goodbit);
    void setstate(iostate state);

    bool good() const;
    bool eof() const;
    bool fail() const;
    bool bad() const;

    iostate exceptions() const;
    void exceptions(iostate except);

    // constructor/destructor
    basic_ios_char(basic_streambuf_char* sb);
    virtual ~basic_ios_char();

    // accessors
    basic_ostream_char* tie() const;
    basic_ostream_char* tie(basic_ostream_char* tiestr);

    basic_streambuf_char* rdbuf() const;
    basic_streambuf_char* rdbuf(basic_streambuf_char* sb);

    basic_ios_char& copyfmt(basic_ios_char const& rhs);

    int fill() const;
    int fill(int ch);

  protected:

    basic_ios_char() {}

    void init(basic_streambuf_char* sb);
    void setstate_no_throw(iostate state);

  private:

    iostate iostate_;
    iostate exceptions_;
    int fill_char_;
    basic_streambuf_char* sb_;
    basic_ostream_char* tie_;
};


// Implementation of ios_base

inline ios_base::fmtflags ios_base::flags() const
  { return fmtflags_; }

inline ios_base::fmtflags ios_base::flags(fmtflags fmtfl)
  {
    int old_fmtflags = fmtflags_;
    fmtflags_ = fmtfl;
    return old_fmtflags;
  }

inline ios_base::fmtflags ios_base::setf(fmtflags fmtfl)
  {
    int old_fmtflags = fmtflags_;
    fmtflags_ |= fmtfl;
    return old_fmtflags;
  }

inline ios_base::fmtflags ios_base::setf(fmtflags fmtfl, fmtflags mask)
  {
    int old_fmtflags = fmtflags_;
    fmtflags_ = (fmtflags_&~mask)|fmtfl;
    return old_fmtflags;
  }

inline void ios_base::unsetf(fmtflags mask)
  { fmtflags_ &= ~mask; }

inline int ios_base::precision() const
  { return precision_; }

inline int ios_base::precision(int prec)
  {
    int old_precision = precision_;
    precision_ = prec;
    return old_precision;
  }

inline int ios_base::width() const
  { return width_; }

inline int ios_base::width(int wide)
  {
    int old_width = width_;
    width_ = wide;
    return old_width;
  }


// Implementation of basic_ios_char

inline ios_base::iostate basic_ios_char::rdstate() const
  { return iostate_; }

inline bool basic_ios_char::good() const
  { return rdstate() == 0; }

inline bool basic_ios_char::eof() const
  { return (rdstate()&eofbit) != 0; }

inline bool basic_ios_char::fail() const
  { return (rdstate()&(failbit|badbit)) != 0; }

inline bool basic_ios_char::bad() const
  { return (rdstate()&badbit) != 0; }

inline basic_ios_char::operator void*() const
  { return (fail() ? 0 : (void*)1); }

inline bool basic_ios_char::operator!() const
  { return fail(); }

inline ios_base::iostate basic_ios_char::exceptions() const
  { return exceptions_; }

inline basic_ostream_char* basic_ios_char::tie() const
  { return tie_; }

inline basic_streambuf_char* basic_ios_char::rdbuf() const
  { return sb_; }

inline basic_ostream_char* basic_ios_char::tie(basic_ostream_char* tiestr)
  {
    basic_ostream_char* old_tie = tie_;
    tie_ = tiestr;
    return old_tie;
  }

inline int basic_ios_char::fill() const
  { return fill_char_; }

inline int basic_ios_char::fill(int ch)
  {
    int old_fill_char = fill_char_;
    fill_char_ = ch;
    return old_fill_char;
  }

inline void basic_ios_char::setstate_no_throw(iostate state)
  { iostate_ |= state; }

#endif
