Code View

fson / source / fson-1.1.0.0 / libs / internal / sdk / fson / Array.hh
// SPDX-License-Identifier: MIT
#pragma once

#include <cstddef>
#include <memory>
#include <optional>
#include <vector>

#include "Comment.hh"
#include "Value.hh"

namespace fedem
{
  namespace fson
  {
    // ─────────────────────────────────────────────────────────────────────
    // Element
    //
    // One slot of an array, carrying its trivia:
    //   leading  : comments before the element
    //   trailing : end-of-line comment after the element / its comma
    // Move-only; duplicate with clone().
    // ─────────────────────────────────────────────────────────────────────
    class Element final
    {
      public:
        explicit Element( std::unique_ptr< Value > value );

        Element( Element&& other ) noexcept = default;
        Element& operator=( Element&& other ) noexcept = default;

        Element clone( ) const;

        Value&       getValue( )       noexcept;
        Value const& getValue( ) const noexcept;
        void setValue( std::unique_ptr< Value > value );

        CommentList&       getLeadingComments( )       noexcept;
        CommentList const& getLeadingComments( ) const noexcept;

        std::optional< Comment >&       getTrailingComment( )       noexcept;
        std::optional< Comment > const& getTrailingComment( ) const noexcept;

      private:
        CommentList               leading;
        std::unique_ptr< Value >  value;
        std::optional< Comment >  trailing;

        Element( Element const& ) = delete;
        Element& operator=( Element const& ) = delete;
    };

    // ─────────────────────────────────────────────────────────────────────
    // Array (docs/notation/00020-array.rrd)
    //
    // Ordered sequence of elements. Comments that appear before the
    // closing ']' without a following element are kept as dangling trivia.
    // ─────────────────────────────────────────────────────────────────────
    class Array final : public Value
    {
      public:
        Array( ) = default;

        Type getType( ) const noexcept override;
        std::unique_ptr< Value > clone( ) const override;

        Array*       asArray( )       noexcept override;
        Array const* asArray( ) const noexcept override;

        std::size_t size ( ) const noexcept;
        bool        empty( ) const noexcept;

        // Throws std::out_of_range on invalid index.
        Value&       at( std::size_t index );
        Value const& at( std::size_t index ) const;

        Element&       getElement( std::size_t index );
        Element const& getElement( std::size_t index ) const;

        // Returns a reference to the freshly stored value.
        Value& append( std::unique_ptr< Value > value );
        Value& insert( std::size_t index, std::unique_ptr< Value > value );

        void erase( std::size_t index );
        void clear( ) noexcept;

        CommentList&       getDanglingComments( )       noexcept;
        CommentList const& getDanglingComments( ) const noexcept;

      private:
        std::vector< Element >  elements;
        CommentList             dangling;
    };

    inline Value::Type Array::getType( ) const noexcept
    {
      return Type::Array;
    }

    inline Array* Array::asArray( ) noexcept
    {
      return this;
    }

    inline Array const* Array::asArray( ) const noexcept
    {
      return this;
    }

    inline std::size_t Array::size( ) const noexcept
    {
      return elements.size( );
    }

    inline bool Array::empty( ) const noexcept
    {
      return elements.empty( );
    }

    inline CommentList& Array::getDanglingComments( ) noexcept
    {
      return dangling;
    }

    inline CommentList const& Array::getDanglingComments( ) const noexcept
    {
      return dangling;
    }
  }  // end namespace fson
}  // end namespace fedem