/** * Copyright (c) 2011-2018 Bill Greiman * This file is part of the SdFat library for SD memory cards. * * MIT License * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #ifndef ios_h #define ios_h #include "FatFile.h" /** * \file * \brief \ref ios_base and \ref ios classes */ //============================================================================== /** * \class ios_base * \brief Base class for all streams */ class ios_base { public: /** typedef for iostate bitmask */ typedef unsigned char iostate; // State flags. /** iostate for no flags */ static const iostate goodbit = 0x00; /** iostate bad bit for a nonrecoverable error. */ static const iostate badbit = 0X01; /** iostate bit for end of file reached */ static const iostate eofbit = 0x02; /** iostate fail bit for nonfatal error */ static const iostate failbit = 0X04; /** * unsigned size that can represent maximum file size. * (violates spec - should be signed) */ typedef uint32_t streamsize; /** type for absolute seek position */ typedef uint32_t pos_type; /** type for relative seek offset */ typedef int32_t off_type; /** enumerated type for the direction of relative seeks */ enum seekdir { /** seek relative to the beginning of the stream */ beg, /** seek relative to the current stream position */ cur, /** seek relative to the end of the stream */ end }; /** type for format flags */ typedef unsigned int fmtflags; /** left adjust fields */ static const fmtflags left = 0x0001; /** right adjust fields */ static const fmtflags right = 0x0002; /** fill between sign/base prefix and number */ static const fmtflags internal = 0x0004; /** base 10 flag*/ static const fmtflags dec = 0x0008; /** base 16 flag */ static const fmtflags hex = 0x0010; /** base 8 flag */ static const fmtflags oct = 0x0020; // static const fmtflags fixed = 0x0040; // static const fmtflags scientific = 0x0080; /** use strings true/false for bool */ static const fmtflags boolalpha = 0x0100; /** use prefix 0X for hex and 0 for oct */ static const fmtflags showbase = 0x0200; /** always show '.' for floating numbers */ static const fmtflags showpoint = 0x0400; /** show + sign for nonnegative numbers */ static const fmtflags showpos = 0x0800; /** skip initial white space */ static const fmtflags skipws = 0x1000; // static const fmtflags unitbuf = 0x2000; /** use uppercase letters in number representations */ static const fmtflags uppercase = 0x4000; /** mask for adjustfield */ static const fmtflags adjustfield = left | right | internal; /** mask for basefield */ static const fmtflags basefield = dec | hex | oct; // static const fmtflags floatfield = scientific | fixed; //---------------------------------------------------------------------------- /** typedef for iostream open mode */ typedef uint8_t openmode; // Openmode flags. /** seek to end before each write */ static const openmode app = 0X4; /** open and seek to end immediately after opening */ static const openmode ate = 0X8; /** perform input and output in binary mode (as opposed to text mode) */ static const openmode binary = 0X10; /** open for input */ static const openmode in = 0X20; /** open for output */ static const openmode out = 0X40; /** truncate an existing stream when opening */ static const openmode trunc = 0X80; //---------------------------------------------------------------------------- ios_base() : m_fill(' '), m_fmtflags(dec | right | skipws) , m_precision(2), m_width(0) {} /** \return fill character */ char fill() { return m_fill; } /** Set fill character * \param[in] c new fill character * \return old fill character */ char fill(char c) { char r = m_fill; m_fill = c; return r; } /** \return format flags */ fmtflags flags() const { return m_fmtflags; } /** set format flags * \param[in] fl new flag * \return old flags */ fmtflags flags(fmtflags fl) { fmtflags tmp = m_fmtflags; m_fmtflags = fl; return tmp; } /** \return precision */ int precision() const { return m_precision; } /** set precision * \param[in] n new precision * \return old precision */ int precision(unsigned int n) { int r = m_precision; m_precision = n; return r; } /** set format flags * \param[in] fl new flags to be or'ed in * \return old flags */ fmtflags setf(fmtflags fl) { fmtflags r = m_fmtflags; m_fmtflags |= fl; return r; } /** modify format flags * \param[in] mask flags to be removed * \param[in] fl flags to be set after mask bits have been cleared * \return old flags */ fmtflags setf(fmtflags fl, fmtflags mask) { fmtflags r = m_fmtflags; m_fmtflags &= ~mask; m_fmtflags |= fl; return r; } /** clear format flags * \param[in] fl flags to be cleared * \return old flags */ void unsetf(fmtflags fl) { m_fmtflags &= ~fl; } /** \return width */ unsigned width() { return m_width; } /** set width * \param[in] n new width * \return old width */ unsigned width(unsigned n) { unsigned r = m_width; m_width = n; return r; } protected: /** \return current number base */ uint8_t flagsToBase() { uint8_t f = flags() & basefield; return f == oct ? 8 : f != hex ? 10 : 16; } private: char m_fill; fmtflags m_fmtflags; unsigned char m_precision; unsigned int m_width; }; //------------------------------------------------------------------------------ /** function for boolalpha manipulator * \param[in] str The stream * \return The stream */ inline ios_base& boolalpha(ios_base& str) { str.setf(ios_base::boolalpha); return str; } /** function for dec manipulator * \param[in] str The stream * \return The stream */ inline ios_base& dec(ios_base& str) { str.setf(ios_base::dec, ios_base::basefield); return str; } /** function for hex manipulator * \param[in] str The stream * \return The stream */ inline ios_base& hex(ios_base& str) { str.setf(ios_base::hex, ios_base::basefield); return str; } /** function for internal manipulator * \param[in] str The stream * \return The stream */ inline ios_base& internal(ios_base& str) { str.setf(ios_base::internal, ios_base::adjustfield); return str; } /** function for left manipulator * \param[in] str The stream * \return The stream */ inline ios_base& left(ios_base& str) { str.setf(ios_base::left, ios_base::adjustfield); return str; } /** function for noboolalpha manipulator * \param[in] str The stream * \return The stream */ inline ios_base& noboolalpha(ios_base& str) { str.unsetf(ios_base::boolalpha); return str; } /** function for noshowbase manipulator * \param[in] str The stream * \return The stream */ inline ios_base& noshowbase(ios_base& str) { str.unsetf(ios_base::showbase); return str; } /** function for noshowpoint manipulator * \param[in] str The stream * \return The stream */ inline ios_base& noshowpoint(ios_base& str) { str.unsetf(ios_base::showpoint); return str; } /** function for noshowpos manipulator * \param[in] str The stream * \return The stream */ inline ios_base& noshowpos(ios_base& str) { str.unsetf(ios_base::showpos); return str; } /** function for noskipws manipulator * \param[in] str The stream * \return The stream */ inline ios_base& noskipws(ios_base& str) { str.unsetf(ios_base::skipws); return str; } /** function for nouppercase manipulator * \param[in] str The stream * \return The stream */ inline ios_base& nouppercase(ios_base& str) { str.unsetf(ios_base::uppercase); return str; } /** function for oct manipulator * \param[in] str The stream * \return The stream */ inline ios_base& oct(ios_base& str) { str.setf(ios_base::oct, ios_base::basefield); return str; } /** function for right manipulator * \param[in] str The stream * \return The stream */ inline ios_base& right(ios_base& str) { str.setf(ios_base::right, ios_base::adjustfield); return str; } /** function for showbase manipulator * \param[in] str The stream * \return The stream */ inline ios_base& showbase(ios_base& str) { str.setf(ios_base::showbase); return str; } /** function for showpos manipulator * \param[in] str The stream * \return The stream */ inline ios_base& showpos(ios_base& str) { str.setf(ios_base::showpos); return str; } /** function for showpoint manipulator * \param[in] str The stream * \return The stream */ inline ios_base& showpoint(ios_base& str) { str.setf(ios_base::showpoint); return str; } /** function for skipws manipulator * \param[in] str The stream * \return The stream */ inline ios_base& skipws(ios_base& str) { str.setf(ios_base::skipws); return str; } /** function for uppercase manipulator * \param[in] str The stream * \return The stream */ inline ios_base& uppercase(ios_base& str) { str.setf(ios_base::uppercase); return str; } //============================================================================== /** * \class ios * \brief Error and state information for all streams */ class ios : public ios_base { public: /** Create ios with no error flags set */ ios() : m_iostate(0) {} /** \return null pointer if fail() is true. */ operator const void*() const { return !fail() ? reinterpret_cast(this) : 0; } /** \return true if fail() else false. */ bool operator!() const { return fail(); } /** \return The iostate flags for this file. */ iostate rdstate() const { return m_iostate; } /** \return True if no iostate flags are set else false. */ bool good() const { return m_iostate == goodbit; } /** \return true if end of file has been reached else false. * * Warning: An empty file returns false before the first read. * * Moral: eof() is only useful in combination with fail(), to find out * whether EOF was the cause for failure */ bool eof() const { return m_iostate & eofbit; } /** \return true if any iostate bit other than eof are set else false. */ bool fail() const { return m_iostate & (failbit | badbit); } /** \return true if bad bit is set else false. */ bool bad() const { return m_iostate & badbit; } /** Clear iostate bits. * * \param[in] state The flags you want to set after clearing all flags. **/ void clear(iostate state = goodbit) { m_iostate = state; } /** Set iostate bits. * * \param[in] state Bitts to set. **/ void setstate(iostate state) { m_iostate |= state; } private: iostate m_iostate; }; #endif // ios_h