Code View

cparse / cparse-1.3.0.2 / src / cparse / Indentation.hh
// SPDX-License-Identifier: MIT
#pragma once

#include <cstdint>
#include <iosfwd>

/// \file Indentation.hh
/// \brief Step-based indentation tracker for code generators.

namespace fedem
{
  namespace parser
  {
    /// \brief A small value type that tracks a current indentation width and a
    ///        step size, and streams itself as that many spaces.
    ///
    /// `Indentation` is the code-generation side's counterpart to a text
    /// editor's indent level. `right()` and `left()` move by whole steps;
    /// `operator<<` writes the current width as spaces. It holds no stream and
    /// owns no resources — copy it freely, keep one per `Generator`.
    ///
    /// All operations are `noexcept`. `left()` saturates at zero and `right()`
    /// saturates at the maximum of `uint_fast16_t` rather than wrapping.
    ///
    /// \see https://cparse.fedem.eu/reference/indentation — reference manual page.
    /// \see Generator
    class Indentation final
    {
      public:
        /// \brief Construct with a step size; the current indentation starts at zero.
        /// \param step_size Columns per step. Defaults to #DEFAULT_STEPSIZE.
        /// \see https://cparse.fedem.eu/reference/indentation-ctor
        explicit Indentation( uint_fast16_t step_size = DEFAULT_STEPSIZE ) noexcept;

        /// \brief Destructor. Trivial — `Indentation` owns nothing.
        /// \see https://cparse.fedem.eu/reference/indentation-dtor
        ~Indentation( ) noexcept;

        /// \brief Copy constructor. Copies both the step size and the current width.
        /// \param object Instance to copy from.
        Indentation( Indentation const& object ) noexcept;

        /// \brief Copy assignment. Copies both the step size and the current width.
        /// \param object Instance to copy from.
        /// \return `*this`.
        /// \see https://cparse.fedem.eu/reference/indentation-operator-assign
        Indentation& operator=( Indentation const& object ) noexcept;

        /// \brief Decrease the indentation by whole steps, saturating at zero.
        /// \param step_size Number of steps to dedent. Defaults to 1.
        /// \see https://cparse.fedem.eu/reference/indentation-left
        void left( uint_fast16_t step_size = 1 ) noexcept;

        /// \brief Increase the indentation by whole steps, saturating at the
        ///        maximum representable width.
        /// \param step_size Number of steps to indent. Defaults to 1.
        /// \see https://cparse.fedem.eu/reference/indentation-right
        void right( uint_fast16_t step_size = 1 ) noexcept;

        /// \brief Set the number of columns one step represents.
        /// \param step_size New step size, in columns.
        /// \note Does not rescale the current width; it changes what the next
        ///       `left()` / `right()` moves by.
        /// \see https://cparse.fedem.eu/reference/indentation-set-step-size
        void setStepSize( uint_fast16_t step_size ) noexcept;

        /// \brief The number of columns one step represents.
        /// \return The current step size, in columns.
        /// \see https://cparse.fedem.eu/reference/indentation-get-step-size
        uint_fast16_t getStepSize( ) const noexcept;

        /// \brief Set the current indentation width directly.
        /// \param indent New width, in columns (not steps).
        /// \see https://cparse.fedem.eu/reference/indentation-set-indentation
        void setIndentation( uint_fast16_t indent ) noexcept;

        /// \brief The current indentation width.
        /// \return The current width, in columns.
        /// \see https://cparse.fedem.eu/reference/indentation-get-indentation
        uint_fast16_t getIndentation( ) const noexcept;

        /// \brief Set the current width back to zero and, optionally, change the
        ///        step size.
        /// \param step_size New step size. Defaults to #DEFAULT_STEPSIZE.
        /// \see https://cparse.fedem.eu/reference/indentation-reset
        void reset( uint_fast16_t step_size = DEFAULT_STEPSIZE ) noexcept;

        /// \brief Default step size used when none is supplied: two columns.
        /// \see https://cparse.fedem.eu/reference/indentation-default-stepsize
        static constexpr uint_fast16_t const DEFAULT_STEPSIZE = 2U;

      protected:
        uint_fast16_t stepSize;  ///< Columns per step.
        uint_fast16_t indent;    ///< Current indentation width, in columns.

      private:
        Indentation( Indentation&& object ) noexcept = delete;
        Indentation& operator=( Indentation&& object ) noexcept = delete;
    };

    /// \brief Write `object.getIndentation()` spaces to `stream`.
    /// \param stream Destination stream.
    /// \param object Indentation whose width is written.
    /// \return `stream`, for chaining.
    /// \see https://cparse.fedem.eu/reference/indentation-operator-shl
    std::ostream& operator<<( std::ostream& stream, Indentation const& object );
  }  // end namespace parser
}  // end namespace fedem