// 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