/**
 * This file is part of the "libterminal" project
 *   Copyright (c) 2019-2020 Christian Parpart <christian@parpart.family>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once

#include <terminal/Color.h>
#include <terminal/RenderBuffer.h>
#include <terminal/Screen.h>

#include <terminal_renderer/BoxDrawingRenderer.h>
#include <terminal_renderer/FontDescriptions.h>
#include <terminal_renderer/RenderTarget.h>
#include <terminal_renderer/TextureAtlas.h>

#include <text_shaper/font.h>
#include <text_shaper/shaper.h>

#include <crispy/FNV.h>
#include <crispy/LRUCache.h>
#include <crispy/point.h>
#include <crispy/size.h>

#include <unicode/convert.h>
#include <unicode/run_segmenter.h>

#include <gsl/span>
#include <gsl/span_ext>

#include <functional>
#include <list>
#include <memory>
#include <unordered_map>
#include <vector>

namespace terminal::renderer
{

std::unique_ptr<text::font_locator> createFontLocator(FontLocatorEngine _engine);

struct FontKeys
{
    text::font_key regular;
    text::font_key bold;
    text::font_key italic;
    text::font_key boldItalic;
    text::font_key emoji;
};

/// Text Rendering Pipeline
class TextRenderer: public Renderable
{
  public:
    TextRenderer(GridMetrics const& gridMetrics,
                 text::shaper& textShaper,
                 FontDescriptions& fontDescriptions,
                 FontKeys const& fontKeys);

    void setRenderTarget(RenderTarget& renderTarget, DirectMappingAllocator& directMappingAllocator) override;
    void setTextureAtlas(TextureAtlas& atlas) override;

    void inspect(std::ostream& _textOutput) const override;

    void clearCache() override;

    void updateFontMetrics();

    void setPressure(bool _pressure) noexcept { pressure_ = _pressure; }

    /// Must be invoked before a new terminal frame is rendered.
    void beginFrame();

    /// Renders a given terminal's grid cell that has been
    /// transformed into a RenderCell.
    void renderCell(RenderCell const& _cell);

    /// Must be invoked when rendering the terminal's text has finished for this frame.
    void endFrame();

  private:
    void initializeDirectMapping();

    /// Puts a sequence of codepoints that belong to the same grid cell at @p _pos
    /// at the end of the currently filled line.
    void appendCellTextToClusterGroup(std::u32string const& _codepoints, TextStyle _style, RGBColor _color);

    /// Gets the text shaping result of the current text cluster group
    text::shape_result const& getOrCreateCachedGlyphPositions(crispy::StrongHash hash);
    text::shape_result createTextShapedGlyphPositions();
    text::shape_result shapeTextRun(unicode::run_segmenter::range const& _run);
    void flushTextClusterGroup();

    AtlasTileAttributes const* getOrCreateRasterizedMetadata(crispy::StrongHash const& hash,
                                                             text::glyph_key const& glyphKey,
                                                             unicode::PresentationStyle presentationStyle);

    /**
     * Creates (and rasterizes) a single glyph and returns its
     * render tile attributes required for the render step.
     */
    std::optional<TextureAtlas::TileCreateData> createSlicedRasterizedGlyph(
        atlas::TileLocation tileLocation,
        text::glyph_key const& id,
        unicode::PresentationStyle presentation,
        crispy::StrongHash const& hash);

    std::optional<TextureAtlas::TileCreateData> createRasterizedGlyph(
        atlas::TileLocation tileLocation, text::glyph_key const& id, unicode::PresentationStyle presentation);

    crispy::Point applyGlyphPositionToPen(crispy::Point pen,
                                          AtlasTileAttributes const& tileAttributes,
                                          text::glyph_position const& gpos) const noexcept;

    void renderRasterizedGlyph(crispy::Point targetSurfacePosition,
                               RGBAColor glyphColor,
                               AtlasTileAttributes const& attributes);

    // general properties
    //
    FontDescriptions& fontDescriptions_;
    FontKeys const& fonts_;

    // performance optimizations
    //
    bool pressure_ = false;

    using ShapingResultCache = crispy::StrongLRUHashtable<text::shape_result>;
    using ShapingResultCachePtr = ShapingResultCache::Ptr;

    ShapingResultCachePtr textShapingCache_;
    // TODO: make unique_ptr, get owned, export cref for other users in Renderer impl.
    text::shaper& textShaper_;

    DirectMapping _directMapping {};

    // Maps from glyph index to tile index.
    std::vector<uint32_t> _directMappedGlyphKeyToTileIndex {};

    bool isGlyphDirectMapped(text::glyph_key const& glyph) const noexcept
    {
        return _directMapping                  // Is direct mapping enabled?
               && glyph.font == fonts_.regular // Only regular font is direct-mapped for now.
               && glyph.index.value < _directMappedGlyphKeyToTileIndex.size()
               && _directMappedGlyphKeyToTileIndex[glyph.index.value] != 0;
    }

    // sub-renderer
    //
    BoxDrawingRenderer boxDrawingRenderer_;

    // work-data for the current text cluster group
    struct TextClusterGroup
    {
        // pen-start position of this text group
        crispy::Point initialPenPosition {};

        // uniform text style for this text group
        TextStyle style = TextStyle::Invalid;

        // uniform text color for this text group
        RGBColor color {};

        // codepoints within this text group with
        // uniform unicode properties (script, language, direction).
        std::vector<char32_t> codepoints;

        // cluster indices for each codepoint
        std::vector<unsigned> clusters;

        // number of grid cells processed
        int cellCount = 0; // FIXME: EA width vs actual cells

        void resetAndMovePenForward(int penIncrementInX)
        {
            codepoints.clear();
            clusters.clear();
            cellCount = 0;
            initialPenPosition.x += penIncrementInX;
        }
    };
    TextClusterGroup textClusterGroup_ {};

    bool textStartFound_ = false;
    bool forceCellGroupSplit_ = false;
};

} // namespace terminal::renderer


/* Copyright 2019-2020 Canaan Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once
#include "compiler_defs.h"
#include <cstring>
#include <gsl/gsl-lite.hpp>

BEGIN_NS_NNCASE_RUNTIME

class span_reader
{
public:
    span_reader(gsl::span<const gsl::byte> span)
        : span_(span)
    {
    }

    bool empty() const noexcept { return span_.empty(); }
    size_t avail() const noexcept { return span_.size_bytes(); }

    template <class T>
    T read()
    {
        auto value = *reinterpret_cast<const T *>(span_.data());
        advance(sizeof(T));
        return value;
    }

    template <class T>
    T read_unaligned()
    {
        alignas(T) uint8_t storage[sizeof(T)];
        std::memcpy(storage, span_.data(), sizeof(T));
        advance(sizeof(T));
        return *reinterpret_cast<const T *>(storage);
    }

    template <class T>
    void read(T &value)
    {
        value = *reinterpret_cast<const T *>(span_.data());
        advance(sizeof(T));
    }

    template <class T>
    void read_span(gsl::span<const T> &span, size_t size)
    {
        span = { reinterpret_cast<const T *>(span_.data()), size };
        advance(sizeof(T) * size);
    }

    template <class T = gsl::byte>
    gsl::span<const T> read_span(size_t size)
    {
        gsl::span<const T> span(reinterpret_cast<const T *>(span_.data()), size);
        advance(sizeof(T) * size);
        return span;
    }

    void read_avail(gsl::span<const gsl::byte> &span)
    {
        span = span_;
        span_ = {};
    }

    gsl::span<const gsl::byte> read_avail()
    {
        auto span = span_;
        span_ = {};
        return span;
    }

    gsl::span<const gsl::byte> peek_avail()
    {
        return span_;
    }

    template <class T>
    T peek()
    {
        auto value = *reinterpret_cast<const T *>(span_.data());
        return value;
    }

    template <class T>
    T peek_unaligned()
    {
        T value;
        std::memcpy(&value, span_.data(), sizeof(T));
        return value;
    }

    template <class T>
    T peek_unaligned_with_offset(size_t offset)
    {
        T value;
        std::memcpy(&value, span_.data() + offset, sizeof(T));
        return value;
    }

    template <class T>
    const T *get_ref()
    {
        auto ptr = reinterpret_cast<const T *>(span_.data());
        advance(sizeof(T));
        return ptr;
    }

    template <class T>
    void get_ref(const T *&ptr)
    {
        ptr = get_ref<T>();
    }

    void skip(size_t count)
    {
        advance(count);
    }

private:
    void advance(size_t count)
    {
        span_ = span_.subspan(count);
    }

private:
    gsl::span<const gsl::byte> span_;
};

END_NS_NNCASE_RUNTIME


#pragma once

#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
#include <GLES3/gl3platform.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <gsl/gsl>

namespace android::OpenGLHelpers
{
    constexpr GLint GetTextureUnit(GLenum texture)
    {
        return texture - GL_TEXTURE0;
    }

    GLuint CreateShaderProgram(const char* vertShaderSource, const char* fragShaderSource);

    namespace GLTransactions
    {
        inline auto MakeCurrent(EGLDisplay display, EGLSurface drawSurface, EGLSurface readSurface, EGLContext context)
        {
            EGLDisplay previousDisplay{ eglGetDisplay(EGL_DEFAULT_DISPLAY) };
            EGLSurface previousDrawSurface{ eglGetCurrentSurface(EGL_DRAW) };
            EGLSurface previousReadSurface{ eglGetCurrentSurface(EGL_READ) };
            EGLContext previousContext{ eglGetCurrentContext() };
            eglMakeCurrent(display, drawSurface, readSurface, context);
            return gsl::finally([previousDisplay, previousDrawSurface, previousReadSurface, previousContext]() { eglMakeCurrent(previousDisplay, previousDrawSurface, previousReadSurface, previousContext); });
        }
    }
}


#pragma once

#include <memory>
#include <gsl/span>

#include "halley/time/halleytime.h"
#include "../session/network_session.h"
#include "entity_network_remote_peer.h"
#include "halley/bytes/serialization_dictionary.h"

namespace Halley {
	class EntityFactory;
	class Resources;
	class World;
	class NetworkSession;

	class EntitySessionSharedData : public SharedData {
	public:

	};

	class EntityClientSharedData : public SharedData {
	public:
		std::optional<Rect4i> viewRect;

		void serialize(Serializer& s) const override;
		void deserialize(Deserializer& s) override;
	};

	class EntityNetworkSession : NetworkSession::IListener, NetworkSession::ISharedDataHandler {
    public:
		class IEntityNetworkSessionListener {
		public:
			virtual ~IEntityNetworkSessionListener() = default;
			virtual void onRemoteEntityCreated(EntityRef entity, NetworkSession::PeerId peerId) {}
			virtual void onPreSendDelta(EntityDataDelta& delta) {}
			virtual bool isEntityInView(EntityRef entity, const EntityClientSharedData& clientData) = 0;
		};

		EntityNetworkSession(std::shared_ptr<NetworkSession> session, Resources& resources, std::set<String> ignoreComponents, IEntityNetworkSessionListener* listener);
		~EntityNetworkSession() override;

		void setWorld(World& world);

		void sendUpdates(Time t, Rect4i viewRect, gsl::span<const std::pair<EntityId, uint8_t>> entityIds); // Takes pairs of entity id and owner peer id
		void receiveUpdates();

		World& getWorld() const;
		EntityFactory& getFactory() const;
		NetworkSession& getSession() const;
		bool hasWorld() const;

		const EntityFactory::SerializationOptions& getEntitySerializationOptions() const;
		const EntityDataDelta::Options& getEntityDeltaOptions() const;
		const SerializerOptions& getByteSerializationOptions() const;

		Time getMinSendInterval() const;

		void onRemoteEntityCreated(EntityRef entity, NetworkSession::PeerId peerId);
		void onPreSendDelta(EntityDataDelta& delta);

		bool isReadyToStart() const;
		bool isEntityInView(EntityRef entity, const EntityClientSharedData& clientData) const;

		std::vector<Rect4i> getRemoteViewPorts() const;

	protected:
		void onStartSession(NetworkSession::PeerId myPeerId) override;
		void onPeerConnected(NetworkSession::PeerId peerId) override;
		void onPeerDisconnected(NetworkSession::PeerId peerId) override;
		std::unique_ptr<SharedData> makeSessionSharedData() override;
		std::unique_ptr<SharedData> makePeerSharedData() override;

	private:
		struct QueuedPacket {
			NetworkSession::PeerId fromPeerId;
			EntityNetworkHeaderType type;
			InboundNetworkPacket packet;
		};

		Resources& resources;
		std::shared_ptr<EntityFactory> factory;
		IEntityNetworkSessionListener* listener = nullptr;

		EntityFactory::SerializationOptions entitySerializationOptions;
		EntityDataDelta::Options deltaOptions;
		SerializerOptions byteSerializationOptions;
		SerializationDictionary serializationDictionary;

		std::shared_ptr<NetworkSession> session;
		std::vector<EntityNetworkRemotePeer> peers;

		std::vector<QueuedPacket> queuedPackets;

		bool readyToStart = false;

		void onReceiveEntityUpdate(NetworkSession::PeerId fromPeerId, EntityNetworkHeaderType type, InboundNetworkPacket packet);
		void onReceiveReady(NetworkSession::PeerId fromPeerId);

		void setupDictionary();
	};
}


#pragma once

#include <d3d11.h>
#include <gsl\gsl>
#include "Rectangle.h"

namespace Library
{
	class TextureHelper final
	{
	public:
		static Point GetTextureSize(gsl::not_null<ID3D11Texture2D*> texture);
		static Rectangle GetTextureBounds(gsl::not_null<ID3D11Texture2D*> texture);
		static std::uint32_t BitsPerPixel(const DXGI_FORMAT format);

		TextureHelper() = delete;
		TextureHelper(const TextureHelper&) = delete;
		TextureHelper& operator=(const TextureHelper&) = delete;
		TextureHelper(TextureHelper&&) = delete;
		TextureHelper& operator=(TextureHelper&&) = delete;
		~TextureHelper() = default;
	};
}


#ifndef EV3PLOTTER_MESSAGEQUEUE_H
#define EV3PLOTTER_MESSAGEQUEUE_H

#include <gsl/span>
#include <memory>
#include <string_view>
#include <type_safe/flag_set.hpp>

namespace ev3plotter {

class message_queue {
  public:
    enum class option { read, write, non_blocking, remove_on_destruction, _flag_set_size };

    enum class send_result { success, failure_queue_full, failure };

    enum class receive_result { success, failure_no_messages, failure };

    message_queue(std::string_view name, std::size_t max_message_size, type_safe::flag_set<option> options);
    ~message_queue();

    send_result send(std::string_view msg);
    receive_result receive(gsl::span<char>& buffer);

    std::size_t message_size() const noexcept;

  private:
    class impl;

    std::unique_ptr<impl> impl_;
};
} // namespace ev3plotter

#endif // EV3PLOTTER_MESSAGEQUEUE_H


#if !defined(TESTUTIL_H_INCLUDED)
#define TESTUTIL_H_INCLUDED

#include "Exceptions.h"

#include <gsl/gsl>
#include <iosfwd>

// ===========================================================================
//
// Test case structs
//
// ===========================================================================

using ArgSpan = ::gsl::span<const char*const>;

struct CmdLineParseTestCase
{
	template<::std::size_t N>
	CmdLineParseTestCase(const char*const(&args)[N]) noexcept
		: m_args(::gsl::make_span(args + 1, N - 1)) {}

	ArgSpan m_args;
};

struct CmdLineParseFailTestCase : public CmdLineParseTestCase
{
	template<::std::size_t N>
	CmdLineParseFailTestCase(const char*const(&args)[N], char const* pExMsgPattern) noexcept :
		CmdLineParseTestCase(args),
		m_pExMsgPattern(pExMsgPattern)
		{}
	bool doesExMatch(CmdLineError const& ex) const;

	char const*	m_pExMsgPattern;
};

::std::ostream& operator<<(::std::ostream& ostrm, CmdLineParseTestCase const& tc);

#endif // TESTUTIL_H_INCLUDED


#ifndef ppom_57c54fa0_d309_4aad_9678_16fa29f7af42_h
#define ppom_57c54fa0_d309_4aad_9678_16fa29f7af42_h

#include <rathen\config.h>
#include <gslib\tree.h>
#include <rathen\basis.h>

__rathen_begin__

class ppom
{
public:
    typedef tree<object, _treenode_wrapper<object> > ppom_tree;
    typedef ppom_tree::iterator iterator;
    typedef ppom_tree::const_iterator const_iterator;
    //typedef ;

public:
    ppom() {}

public:
    template<class _cst>
    iterator insert(iterator i) { return _tree.insert_tail<_cst>(i); }
    template<class _cst>
    iterator birth(iterator i) { return _tree.birth_tail<_cst>(i); }

protected:
    ppom_tree       _tree;
};

__rathen_end__

#endif


#pragma once

#include <gsl\gsl>
#include "Texture.h"
#include "Rectangle.h"

namespace Library
{
	class Texture2D final : public Texture
	{
		RTTI_DECLARATIONS(Texture2D, Texture)

	public:
		Texture2D(const GLuint textureID, GLuint width, GLuint height);
		Texture2D(const Texture2D&) = default;
		Texture2D& operator=(const Texture2D&) = default;
		Texture2D(Texture2D&&) = default;
		Texture2D& operator=(Texture2D&&) = default;
		~Texture2D() = default;

		static std::shared_ptr<Texture2D> CreateTexture2D(GLuint width, GLuint height, GLint mipLevels = 1, GLenum colorFormat = GL_RGBA16F);

		GLuint Width() const;
		GLuint Height() const;
		Rectangle Bounds() const;

	private:
		GLuint mWidth;
		GLuint mHeight;
	};
}


/**
 * This file is part of the "libterminal" project
 *   Copyright (c) 2019-2020 Christian Parpart <christian@parpart.family>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once

#include <terminal/GraphicsAttributes.h>
#include <terminal/Hyperlink.h>
#include <terminal/primitives.h>

#include <crispy/BufferObject.h>
#include <crispy/Comparison.h>
#include <crispy/assert.h>

#include <gsl/span>
#include <gsl/span_ext>

#include <iterator>
#include <sstream>
#include <string>
#include <vector>

namespace terminal
{

enum class LineFlags : uint8_t
{
    None = 0x0000,
    Wrappable = 0x0001,
    Wrapped = 0x0002,
    Marked = 0x0004,
    // TODO: DoubleWidth  = 0x0010,
    // TODO: DoubleHeight = 0x0020,
};

// clang-format off
template <typename, bool> struct OptionalProperty;
template <typename T> struct OptionalProperty<T, false> {};
template <typename T> struct OptionalProperty<T, true> { T value; };
// clang-format on

/**
 * Line storage with call columns sharing the same SGR attributes.
 */
struct TrivialLineBuffer
{
    ColumnCount displayWidth;
    GraphicsAttributes textAttributes;
    GraphicsAttributes fillAttributes = textAttributes;
    HyperlinkId hyperlink {};

    ColumnCount usedColumns {};
    crispy::BufferFragment text {};

    void reset(GraphicsAttributes _attributes) noexcept
    {
        textAttributes = _attributes;
        fillAttributes = _attributes;
        hyperlink = {};
        usedColumns = {};
        text.reset();
    }
};

template <typename Cell>
using InflatedLineBuffer = std::vector<Cell>;

/// Unpacks a TrivialLineBuffer into an InflatedLineBuffer<Cell>.
template <typename Cell>
InflatedLineBuffer<Cell> inflate(TrivialLineBuffer const& input);

template <typename Cell>
using LineStorage = std::variant<TrivialLineBuffer, InflatedLineBuffer<Cell>>;

/**
 * Line<Cell> API.
 *
 * TODO: Use custom allocator for ensuring cache locality of Cells to sibling lines.
 * TODO: Make the line optimization work.
 */
template <typename Cell>
class Line
{
  public:
    Line() = default;
    Line(Line const&) = default;
    Line(Line&&) noexcept = default;
    Line& operator=(Line const&) = default;
    Line& operator=(Line&&) noexcept = default;

    using TrivialBuffer = TrivialLineBuffer;
    using InflatedBuffer = InflatedLineBuffer<Cell>;
    using Storage = LineStorage<Cell>;
    using value_type = Cell;
    using iterator = typename InflatedBuffer::iterator;
    using reverse_iterator = typename InflatedBuffer::reverse_iterator;
    using const_iterator = typename InflatedBuffer::const_iterator;

    Line(LineFlags _flags, ColumnCount _width, GraphicsAttributes _templateSGR):
        storage_ { TrivialBuffer { _width, _templateSGR } }, flags_ { static_cast<unsigned>(_flags) }
    {
    }

    Line(LineFlags _flags, InflatedBuffer _buffer):
        storage_ { std::move(_buffer) }, flags_ { static_cast<unsigned>(_flags) }
    {
    }

    void reset(LineFlags _flags, GraphicsAttributes _attributes) noexcept
    {
        flags_ = static_cast<unsigned>(_flags);
        if (isTrivialBuffer())
            trivialBuffer().reset(_attributes);
        else
            setBuffer(TrivialBuffer { size(), _attributes });
    }

    void fill(LineFlags _flags,
              GraphicsAttributes const& _attributes,
              char32_t _codepoint,
              uint8_t _width) noexcept
    {
        if (_codepoint == 0)
            reset(_flags, _attributes);
        else
        {
            flags_ = static_cast<unsigned>(_flags);
            for (Cell& cell: inflatedBuffer())
            {
                cell.reset();
                cell.write(_attributes, _codepoint, _width);
            }
        }
    }

    /// Tests if all cells are empty.
    [[nodiscard]] bool empty() const noexcept
    {
        if (isTrivialBuffer())
            return trivialBuffer().text.empty();

        for (auto const& cell: inflatedBuffer())
            if (!cell.empty())
                return false;
        return true;
    }

    /**
     * Fills this line with the given content.
     *
     * @p _start offset into this line of the first charater
     * @p _sgr graphics rendition for the line starting at @c _start until the end
     * @p _ascii the US-ASCII characters to fill with
     */
    void fill(ColumnOffset _start, GraphicsAttributes const& _sgr, std::string_view _ascii)
    {
        auto& buffer = inflatedBuffer();

        assert(unbox<size_t>(_start) + _ascii.size() <= buffer.size());

        auto constexpr ASCII_Width = 1;
        auto const* s = _ascii.data();

        Cell* i = &buffer[unbox<size_t>(_start)];
        Cell* e = i + _ascii.size();
        while (i != e)
            (i++)->write(_sgr, static_cast<char32_t>(*s++), ASCII_Width);

        auto const e2 = buffer.data() + buffer.size();
        while (i != e2)
            (i++)->reset();
    }

    [[nodiscard]] ColumnCount size() const noexcept
    {
        if (isTrivialBuffer())
            return trivialBuffer().displayWidth;
        else
            return ColumnCount::cast_from(inflatedBuffer().size());
    }

    void resize(ColumnCount _count);

    gsl::span<Cell const> trim_blank_right() const noexcept;

    gsl::span<Cell const> cells() const noexcept { return inflatedBuffer(); }

    gsl::span<Cell> useRange(ColumnOffset _start, ColumnCount _count) noexcept
    {
#if defined(__clang__) && __clang_major__ <= 11
        auto const bufferSpan = gsl::span(inflatedBuffer());
        return bufferSpan.subspan(unbox<size_t>(_start), unbox<size_t>(_count));
#else
        // Clang <= 11 cannot deal with this (e.g. FreeBSD 13 defaults to Clang 11).
        return gsl::span(inflatedBuffer()).subspan(unbox<size_t>(_start), unbox<size_t>(_count));
#endif
    }

    Cell& useCellAt(ColumnOffset _column) noexcept
    {
        Require(ColumnOffset(0) <= _column);
        Require(_column <= ColumnOffset::cast_from(size())); // Allow off-by-one for sentinel.
        return inflatedBuffer()[unbox<size_t>(_column)];
    }

    [[nodiscard]] uint8_t cellEmptyAt(ColumnOffset column) const noexcept
    {
        if (isTrivialBuffer())
        {
            Require(ColumnOffset(0) <= column);
            Require(column < ColumnOffset::cast_from(size()));
            return unbox<size_t>(column) >= trivialBuffer().text.size()
                   || trivialBuffer().text[column.as<size_t>()] == 0x20;
        }
        return inflatedBuffer().at(unbox<size_t>(column)).empty();
    }

    [[nodiscard]] uint8_t cellWithAt(ColumnOffset column) const noexcept
    {
        if (isTrivialBuffer())
        {
            Require(ColumnOffset(0) <= column);
            Require(column < ColumnOffset::cast_from(size()));
            return 1; // TODO: When trivial line is to support Unicode, this should be adapted here.
        }
        return inflatedBuffer().at(unbox<size_t>(column)).width();
    }

    [[nodiscard]] LineFlags flags() const noexcept
    {
        return static_cast<LineFlags>(flags_);
    }

    [[nodiscard]] bool marked() const noexcept
    {
        return isFlagEnabled(LineFlags::Marked);
    }
    void setMarked(bool _enable)
    {
        setFlag(LineFlags::Marked, _enable);
    }

    [[nodiscard]] bool wrapped() const noexcept
    {
        return isFlagEnabled(LineFlags::Wrapped);
    }
    void setWrapped(bool _enable)
    {
        setFlag(LineFlags::Wrapped, _enable);
    }

    [[nodiscard]] bool wrappable() const noexcept
    {
        return isFlagEnabled(LineFlags::Wrappable);
    }
    void setWrappable(bool _enable)
    {
        setFlag(LineFlags::Wrappable, _enable);
    }

    [[nodiscard]] LineFlags wrappableFlag() const noexcept
    {
        return wrappable() ? LineFlags::Wrappable : LineFlags::None;
    }
    [[nodiscard]] LineFlags wrappedFlag() const noexcept
    {
        return marked() ? LineFlags::Wrapped : LineFlags::None;
    }
    [[nodiscard]] LineFlags markedFlag() const noexcept
    {
        return marked() ? LineFlags::Marked : LineFlags::None;
    }

    [[nodiscard]] LineFlags inheritableFlags() const noexcept
    {
        auto constexpr Inheritables = unsigned(LineFlags::Wrappable) | unsigned(LineFlags::Marked);
        return static_cast<LineFlags>(flags_ & Inheritables);
    }

    void setFlag(LineFlags _flag, bool _enable) noexcept
    {
        if (_enable)
            flags_ |= static_cast<unsigned>(_flag);
        else
            flags_ &= ~static_cast<unsigned>(_flag);
    }

    [[nodiscard]] bool isFlagEnabled(LineFlags _flag) const noexcept
    {
        return (flags_ & static_cast<unsigned>(_flag)) != 0;
    }

    [[nodiscard]] InflatedBuffer reflow(ColumnCount _newColumnCount);
    [[nodiscard]] std::string toUtf8() const;
    [[nodiscard]] std::string toUtf8Trimmed() const;

    // Returns a reference to this mutable grid-line buffer.
    //
    // If this line has been stored in an optimized state, then
    // the line will be first unpacked into a vector of grid cells.
    InflatedBuffer& inflatedBuffer();
    InflatedBuffer const& inflatedBuffer() const;

    [[nodiscard]] TrivialBuffer& trivialBuffer() noexcept
    {
        return std::get<TrivialBuffer>(storage_);
    }
    [[nodiscard]] TrivialBuffer const& trivialBuffer() const noexcept
    {
        return std::get<TrivialBuffer>(storage_);
    }

    [[nodiscard]] bool isTrivialBuffer() const noexcept
    {
        return std::holds_alternative<TrivialBuffer>(storage_);
    }
    [[nodiscard]] bool isInflatedBuffer() const noexcept
    {
        return !std::holds_alternative<TrivialBuffer>(storage_);
    }

    void setBuffer(TrivialBuffer const& buffer) noexcept
    {
        storage_ = buffer;
    }
    void setBuffer(InflatedBuffer buffer)
    {
        storage_ = std::move(buffer);
    }

    void reset(GraphicsAttributes textAttributes,
               GraphicsAttributes fillAttributes,
               HyperlinkId hyperlink,
               crispy::BufferFragment text,
               ColumnCount columnsUsed)
    {
        storage_ =
            TrivialBuffer { size(), textAttributes, fillAttributes, hyperlink, columnsUsed, std::move(text) };
    }

  private:
    Storage storage_;
    unsigned flags_ = 0;
};

constexpr LineFlags operator|(LineFlags a, LineFlags b) noexcept
{
    return LineFlags(unsigned(a) | unsigned(b));
}

constexpr LineFlags operator~(LineFlags a) noexcept
{
    return LineFlags(~unsigned(a));
}

constexpr LineFlags operator&(LineFlags a, LineFlags b) noexcept
{
    return LineFlags(unsigned(a) & unsigned(b));
}

template <typename Cell>
inline typename Line<Cell>::InflatedBuffer& Line<Cell>::inflatedBuffer()
{
    if (std::holds_alternative<TrivialBuffer>(storage_))
        storage_ = inflate<Cell>(std::get<TrivialBuffer>(storage_));
    return std::get<InflatedBuffer>(storage_);
}

template <typename Cell>
inline typename Line<Cell>::InflatedBuffer const& Line<Cell>::inflatedBuffer() const
{
    return const_cast<Line<Cell>*>(this)->inflatedBuffer();
}

} // namespace terminal

namespace fmt // {{{
{
template <>
struct formatter<terminal::LineFlags>
{
    template <typename ParseContext>
    auto parse(ParseContext& ctx)
    {
        return ctx.begin();
    }
    template <typename FormatContext>
    auto format(const terminal::LineFlags _flags, FormatContext& ctx) const
    {
        static const std::array<std::pair<terminal::LineFlags, std::string_view>, 3> nameMap = {
            std::pair { terminal::LineFlags::Wrappable, std::string_view("Wrappable") },
            std::pair { terminal::LineFlags::Wrapped, std::string_view("Wrapped") },
            std::pair { terminal::LineFlags::Marked, std::string_view("Marked") },
        };
        std::string s;
        for (auto const& mapping: nameMap)
        {
            if ((mapping.first & _flags) != terminal::LineFlags::None)
            {
                if (!s.empty())
                    s += ",";
                s += mapping.second;
            }
        }
        return fmt::format_to(ctx.out(), "{}", s);
    }
};
} // namespace fmt


/* err/gsl_message.h
 *
 * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Gerard Jungman, Brian Gough
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#ifndef __GSL_MESSAGE_H__
#define __GSL_MESSAGE_H__
#include <gsl/gsl_types.h>

#undef __BEGIN_DECLS
#undef __END_DECLS
#ifdef __cplusplus
# define __BEGIN_DECLS extern "C" {
# define __END_DECLS }
#else
# define __BEGIN_DECLS /* empty */
# define __END_DECLS /* empty */
#endif

__BEGIN_DECLS

/* Provide a general messaging service for client use.  Messages can
 * be selectively turned off at compile time by defining an
 * appropriate message mask. Client code which uses the GSL_MESSAGE()
 * macro must provide a mask which is or'ed with the GSL_MESSAGE_MASK.
 *
 * The messaging service can be completely turned off
 * by defining GSL_MESSAGING_OFF.  */

void gsl_message(const char * message, const char * file, int line,
                 unsigned int mask);

#ifndef GSL_MESSAGE_MASK
#define GSL_MESSAGE_MASK 0xffffffffu /* default all messages allowed */
#endif

GSL_VAR unsigned int gsl_message_mask ;

/* Provide some symolic masks for client ease of use. */

enum {
  GSL_MESSAGE_MASK_A = 1,
  GSL_MESSAGE_MASK_B = 2,
  GSL_MESSAGE_MASK_C = 4,
  GSL_MESSAGE_MASK_D = 8,
  GSL_MESSAGE_MASK_E = 16,
  GSL_MESSAGE_MASK_F = 32,
  GSL_MESSAGE_MASK_G = 64,
  GSL_MESSAGE_MASK_H = 128
} ;

#ifdef GSL_MESSAGING_OFF        /* throw away messages */
#define GSL_MESSAGE(message, mask) do { } while(0)
#else                           /* output all messages */
#define GSL_MESSAGE(message, mask) \
       do { \
       if (mask & GSL_MESSAGE_MASK) \
         gsl_message (message, __FILE__, __LINE__, mask) ; \
       } while (0)
#endif

__END_DECLS

#endif /* __GSL_MESSAGE_H__ */


#pragma once

#include <filesystem>
#include <unordered_map>
#include <optional>
#include <variant>
#include <string>
#include <vector>
#include <gsl/gsl>
#include <DirectML.h>
#include "BucketAllocator.h"

class Model
{
public:
    // When binding a buffer to an operator it is possible to use a subregion of
    // the buffer by specifying an elementOffset, elementCount, and elementSizeInBytes.
    // Additionally, an optional format specifier dictates how to interpret the buffer
    // contents; when omitted the buffer will be interpreted using the same data type used
    // to initialize it.
    struct BufferBindingSource
    {
        std::string name;
        uint64_t elementCount;
        uint64_t elementSizeInBytes;
        uint64_t elementOffset;
        std::optional<DXGI_FORMAT> format;

        // For Append/Consume buffers only:
        std::optional<std::string> counterName;
        uint64_t counterOffsetBytes;
    };

    using Bindings = std::unordered_map<std::string, std::vector<BufferBindingSource>>;

    // RESOURCES
    // ------------------------------------------------------------------------

    struct BufferDesc
    {
        uint64_t sizeInBytes;
        std::vector<std::byte> initialValues;
        DML_TENSOR_DATA_TYPE initialValuesDataType;
        uint64_t initialValuesOffsetInBytes;
    };

    struct ResourceDesc
    {
        std::string name;
        std::variant<BufferDesc> value;
    };

    // DISPATCHABLES
    // ------------------------------------------------------------------------

    struct DmlDispatchableDesc
    {
        struct BindPoint
        {
            std::string name;
            uint32_t resourceCount;
            bool required;
        };

        struct BindPoints
        {
            std::vector<BindPoint> inputs;
            std::vector<BindPoint> outputs;
        };

        DML_OPERATOR_DESC* desc;
        BindPoints bindPoints;
        DML_EXECUTION_FLAGS executionFlags;
        Bindings initBindings;
    };

    struct HlslDispatchableDesc
    {
        enum class Compiler
        {
            DXC
        };

        std::filesystem::path sourcePath;
        Compiler compiler;
        std::vector<std::string> compilerArgs;
    };

    struct DispatchableDesc
    {
        std::string name;
        std::variant<DmlDispatchableDesc, HlslDispatchableDesc> value;
    };

    // COMMANDS
    // ------------------------------------------------------------------------

    struct DispatchCommand
    {
        std::string dispatchableName;
        Bindings bindings;
        std::array<uint32_t, 3> threadGroupCount;
    };

    struct PrintCommand
    {
        std::string resourceName;
    };

    using Command = std::variant<DispatchCommand, PrintCommand>;

    Model() = default;

    Model(
        std::vector<ResourceDesc>&& resourceDescs,
        std::vector<DispatchableDesc>&& dispatchableDescs,
        std::vector<Command>&& commands,
        BucketAllocator&& allocator);

    Model(const Model&) = delete;
    Model& operator=(const Model&) = delete;
    Model(Model&&) = default;
    Model& operator=(Model&&) = default;

    gsl::span<const ResourceDesc> GetResourceDescs() const { return m_resourceDescs; }
    gsl::span<const DispatchableDesc> GetDispatchableDescs() const { return m_dispatchableDescs; }
    gsl::span<const Command> GetCommands() const { return m_commands; }

    const ResourceDesc& GetResource(std::string_view name) const { return *m_resourceDescsByName.find(name.data())->second; }
    const DispatchableDesc& GetDispatchable(std::string_view name) const { return *m_dispatchableDescsByName.find(name.data())->second; }

private:
    std::vector<ResourceDesc> m_resourceDescs;
    std::vector<DispatchableDesc> m_dispatchableDescs;
    std::vector<Command> m_commands;
    BucketAllocator m_allocator;
    std::unordered_map<std::string, ResourceDesc*> m_resourceDescsByName;
    std::unordered_map<std::string, DispatchableDesc*> m_dispatchableDescsByName;
};


#pragma once

#include <gsl.h>
#include <ImmutableRanges.h>
#include <qobject.h>

#include <mitkBaseData.h>
#include <FaceIdentifier.h>

class QWidget;

namespace crimson
{
class QtPropertyStorage;

/*! \brief   An interface for data associated with model faces.
 *
 * This includes boundary conditions and materials.
 */
class FaceData : public mitk::BaseData
{
public:
    mitkClassMacro(FaceData, BaseData);

    /*!
     * \brief   Gets the FaceData object name.
     */
    virtual gsl::cstring_span<> getName() const = 0;

    /*!
     * \brief   Gets the list of face types (as defined by FaceIdentifer::FaceType) that the face
     *  data can be applied to.
     */
    virtual ImmutableRefRange<FaceIdentifier::FaceType> applicableFaceTypes() = 0;

    ///@{
    /*!
     * \brief   Sets the identifiers of the faces the FaceData is applied to.
     */
    virtual void setFaces(ImmutableRefRange<FaceIdentifier> faces) = 0;

    /*!
    * \brief   Gets the identifiers of the faces the FaceData is applied to.
    */
    virtual ImmutableRefRange<FaceIdentifier> getFaces() const = 0;
    ///@}

    /*!
     * \brief   Creates custom editor widget which should be added to the UI.
     */
    virtual QWidget* createCustomEditorWidget() { return nullptr; }

    /*!
     * \brief   Gets property storage for the FaceData properties.
     */
    virtual gsl::not_null<QtPropertyStorage*> getPropertyStorage() = 0;

	/*!
	* \brief  stores a pointer to C++ owned data object. For use in python-based boundary conditions that have the logic
	implemented in C++
	*/
	virtual void setDataObject(QVariantList data){};

	virtual void setDataUID(std::string dataUID){};

	virtual std::string getDataUID(){ return std::string{}; };

protected:
    FaceData() { mitk::BaseData::InitializeTimeGeometry(1); }
    virtual ~FaceData() {}

    FaceData(const Self&) = default;

    void SetRequestedRegion(const itk::DataObject*) override {}
    void SetRequestedRegionToLargestPossibleRegion() override {}
    bool RequestedRegionIsOutsideOfTheBufferedRegion() override { return true; }
    bool VerifyRequestedRegion() override { return true; }
};

} // end namespace crimson


#pragma once
#include "utility/types.h"
#include <gsl/gsl>
#include <array>

namespace cws80 {

extern std::array<gsl::span<const u8>, 11> extra_bank_data;

}  // namespace cws80


#pragma once

#include "Common.h"
#include "PEFile.h"
#include "DelayLoadedModule.h"

#include <gsl/gsl>

namespace winlogo::pe_parser {

namespace details {
/**
 * This is an input iterator for iterating over the delay-loaded modules of the delay-load
 * directory.
 */
class DelayLoadDirectoryIterator {
public:
    DelayLoadDirectoryIterator(PEFile file,
                               gsl::span<IMAGE_DELAYLOAD_DESCRIPTOR>::iterator iterator);

    bool operator==(const DelayLoadDirectoryIterator& other) const noexcept;
    bool operator!=(const DelayLoadDirectoryIterator& other) const noexcept;

    DelayLoadedModule operator*() const noexcept;
    DelayLoadDirectoryIterator& operator++() noexcept;

private:
    PEFile m_peFile;
    gsl::span<IMAGE_DELAYLOAD_DESCRIPTOR>::iterator m_current;
};

}  // namespace details

/**
 * This class represents an iterable view of a PE file's delay-loaded directory.
 */
class DelayLoadDirectory {
public:
    /**
     * Initialize the delay-load directory from its PE file.
     */
    explicit DelayLoadDirectory(PEFile peFile);

    /**
     * Get the raw import descriptors.
     */
    gsl::span<IMAGE_DELAYLOAD_DESCRIPTOR> rawDelayLoadDescriptors() const noexcept;

    // Iterators for iterating over the imported modules.

    details::DelayLoadDirectoryIterator begin() const noexcept;
    details::DelayLoadDirectoryIterator end() const noexcept;

private:
    /// The owning PE file.
    PEFile m_peFile;
    gsl::span<IMAGE_DELAYLOAD_DESCRIPTOR> m_delayLoadDescriptors;
};

}  // namespace winlogo::pe_parser


#pragma once

#include "BasicTypes.h"
#include "CharInfo.h"
#include "Distance.h"
#include "FontTypes.h"
#include "types/ND0.h"
#include "types/ND1_Node.h"
#include "types/ND1_Box.h"
#include "types/ND2_Char.h"
#include "types/ND2_Box.h"
#include "types/ND2_Rule.h"
#include "types/ND2_Glue.h"
#include "types/ND2_Kern.h"
#include "types/ND2_Penalty.h"
#include <gsl.h>
#include <list>


/**
 * @file coroutine/unix.h
 * @author github.com/luncliff (luncliff@gmail.com)
 * @copyright CC BY 4.0
 */
#ifndef COROUTINE_SYSTEM_WRAPPER_H
#define COROUTINE_SYSTEM_WRAPPER_H
#if !(defined(unix) || defined(__APPLE__) || defined(__FreeBSD__))
#error "expect UNIX platform for this file"
#endif
#include <sys/event.h> // for BSD kqueue

#include <gsl/gsl>

#include <coroutine/return.h>

/**
 * @defgroup BSD
 */

namespace coro {

/**
 * @brief RAII wrapping for kqueue file descriptor
 * @ingroup BSD
 */
class kqueue_owner final {
    int64_t kqfd;

  public:
    /**
     * @brief create a fd with `kqueue`. Throw if the function fails.
     * @see kqeueue
     * @throw system_error
     */
    kqueue_owner() noexcept(false);
    /**
     * @brief close the current kqueue file descriptor
     */
    ~kqueue_owner() noexcept;
    kqueue_owner(const kqueue_owner&) = delete;
    kqueue_owner(kqueue_owner&&) = delete;
    kqueue_owner& operator=(const kqueue_owner&) = delete;
    kqueue_owner& operator=(kqueue_owner&&) = delete;

  public:
    /**
     * @brief bind the event to kqueue
     * @param req
     * @see kevent64
     * @throw system_error
     *
     * The function is named `change` because
     * the given argument is used for 'change list' fo `kqueue64`
     */
    void change(kevent64_s& req) noexcept(false);

    /**
     * @brief fetch all events for the given kqeueue descriptor
     * @param wait_time
     * @param list
     * @return ptrdiff_t
     * @see kevent64
     * @throw system_error
     *
     * The function is named `events` because
     * the given argument is used for 'event list' fo `kqueue64`
     *
     * Timeout is not an error for this function
     */
    ptrdiff_t events(const timespec& wait_time,
                     gsl::span<kevent64_s> list) noexcept(false);

  public:
    /**
     * @brief return temporary awaitable object for given event
     * @param req input for `change` operation
     * @see change
     *
     * There is no guarantee of reusage of returned awaiter object
     * When it is awaited, and `req.udata` is null(0),
     * the value is set to `coroutine_handle<void>`
     *
     * @code
     * auto read_async(kqueue_owner& kq, uint64_t fd) -> frame_t {
     *     kevent64_s req{.ident = fd,
     *                    .filter = EVFILT_READ,
     *                    .flags = EV_ADD | EV_ENABLE | EV_ONESHOT};
     *     co_await kq.submit(req);
     *     // ...
     *     co_await kq.submit(req);
     *     // ...
     * }
     * @endcode
     */
    [[nodiscard]] auto submit(kevent64_s& req) noexcept {
        class awaiter final : public suspend_always {
            kqueue_owner& kq;
            kevent64_s& req;

          public:
            constexpr awaiter(kqueue_owner& _kq, kevent64_s& _req)
                : kq{_kq}, req{_req} {
            }

          public:
            void await_suspend(coroutine_handle<void> coro) noexcept(false) {
                if (req.udata == 0)
                    req.udata = reinterpret_cast<uint64_t>(coro.address());
                return kq.change(req);
            }
        };
        return awaiter{*this, req};
    }
};

} // namespace coro

#endif // COROUTINE_SYSTEM_WRAPPER_H


#pragma once

#include "BoundingVolume.h"
#include "Library.h"
#include "Tile.h"
#include "TileContext.h"
#include "TileID.h"
#include "TileRefine.h"
#include "TilesetOptions.h"

#include <CesiumAsync/AsyncSystem.h>
#include <CesiumAsync/IAssetAccessor.h>
#include <CesiumAsync/IAssetRequest.h>

#include <gsl/span>
#include <spdlog/fwd.h>

#include <cstddef>
#include <memory>

namespace Cesium3DTilesSelection {
/**
 * @brief The information that is passed to a {@link TileContentLoader} to
 * create a {@link TileContentLoadResult}.
 *
 * For many types of tile content, only the `pRequest` field is required. The
 * other members are used for content that can generate child tiles, like
 * external tilesets or composite tiles. These members are usually initialized
 * from
 * the corresponding members of the {@link Tile} that the content belongs to.
 */
struct CESIUM3DTILESSELECTION_API TileContentLoadInput {

  /**
   * @brief Creates a new, uninitialized instance for the given tile.
   *
   * The `asyncSystem`, `pLogger`, `pAssetAccessor` and `pRequest` will have
   * default values, and have to be initialized before this instance is passed
   * to one of the loader functions.
   *
   * @param tile The {@link Tile} that the content belongs to
   */
  TileContentLoadInput(const Tile& tile);

  /**
   * @brief Creates a new instance
   *
   * @param asyncSystem The async system to use for tile content loading.
   * @param pLogger The logger that will be used
   * @param pAssetAccessor The asset accessor to make further requests with.
   * @param pRequest The original tile request and its response.
   * @param tile The {@link Tile} that the content belongs to.
   */
  TileContentLoadInput(
      const CesiumAsync::AsyncSystem& asyncSystem,
      const std::shared_ptr<spdlog::logger>& pLogger,
      const std::shared_ptr<CesiumAsync::IAssetAccessor>& pAssetAccessor,
      const std::shared_ptr<CesiumAsync::IAssetRequest>& pRequest,
      const Tile& tile);

  /**
   * @brief Creates a new instance.
   *
   * @param asyncSystem The async system to use for tile content loading.
   * @param pLogger The logger that will be used
   * @param pAssetAccessor The asset accessor to make further requests with.
   * @param pRequest The original tile request and its response.
   * @param tileID The {@link TileID}
   * @param tileBoundingVolume The tile {@link BoundingVolume}
   * @param tileContentBoundingVolume The tile content {@link BoundingVolume}
   * @param tileRefine The {@link TileRefine} strategy
   * @param tileGeometricError The geometric error of the tile
   * @param tileTransform The tile transform
   */
  TileContentLoadInput(
      const CesiumAsync::AsyncSystem& asyncSystem,
      const std::shared_ptr<spdlog::logger>& pLogger,
      const std::shared_ptr<CesiumAsync::IAssetAccessor>& pAssetAccessor,
      const std::shared_ptr<CesiumAsync::IAssetRequest>& pRequest,
      const TileID& tileID,
      const BoundingVolume& tileBoundingVolume,
      const std::optional<BoundingVolume>& tileContentBoundingVolume,
      TileRefine tileRefine,
      double tileGeometricError,
      const glm::dmat4& tileTransform,
      const TilesetContentOptions& contentOptions);

  /**
   * @brief The async system to use for tile content loading.
   */
  CesiumAsync::AsyncSystem asyncSystem;

  /**
   * @brief The logger that receives details of loading errors and warnings.
   */
  std::shared_ptr<spdlog::logger> pLogger;

  /**
   * @brief The asset accessor to make further requests with.
   */
  std::shared_ptr<CesiumAsync::IAssetAccessor> pAssetAccessor;

  /**
   * @brief The asset request and response data for the tile.
   */
  std::shared_ptr<CesiumAsync::IAssetRequest> pRequest;

  /**
   * @brief The {@link TileID}.
   */
  TileID tileID;

  /**
   * @brief The tile {@link BoundingVolume}.
   */
  BoundingVolume tileBoundingVolume;

  /**
   * @brief Tile content {@link BoundingVolume}.
   */
  std::optional<BoundingVolume> tileContentBoundingVolume;

  /**
   * @brief The {@link TileRefine}.
   */
  TileRefine tileRefine;

  /**
   * @brief The geometric error.
   */
  double tileGeometricError;

  /**
   * @brief The tile transform
   */
  glm::dmat4 tileTransform;

  /**
   * @brief Options for parsing content and creating Gltf models.
   */
  TilesetContentOptions contentOptions;
};
} // namespace Cesium3DTilesSelection


// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

#pragma once

#define NOMINMAX

#pragma warning(disable : 6221) // Disable implicit cast warning for C++/WinRT headers (tracked by Bug 17528784: C++/WinRT headers trigger C6221 comparing e.code() to int-typed things)

// Disable factory caching in CppWinRT as the global COM pointers that are released during dll/process
// unload are not safe. Setting this makes CppWinRT just call get_activation_factory directly every time.
#define WINRT_DISABLE_FACTORY_CACHE 1

#include "targetver.h"

#include "BuildMacros.h"

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>

#include <wrl\implements.h>
#include <wrl\module.h>
#include <wrl\event.h>

#define MUX_ASSERT(X) _ASSERT(X)
#define MUX_ASSERT_MSG(X, MSG) _ASSERT_EXPR(X, MSG)
#define MUX_ASSERT_NOASSUME(X) _ASSERT(X)

#define MUX_FAIL_FAST() RaiseFailFastException(nullptr, nullptr, 0);
#define MUX_FAIL_FAST_MSG(MSG) RaiseFailFastException(nullptr, nullptr, 0);

#ifdef BUILD_WINDOWS
#include <gsl/gsl_util>
#else
#include <gsl_util.h>
#endif

// windows.ui.xaml.h accesses LoadLibrary in its inline declaration of CreateXamlUiPresenter
// Accessing LoadLibrary is not always allowed (e.g. on phone), so we need to suppress that.
// We can do so by making this define prior to including the header.
#define CREATE_XAML_UI_PRESENTER_API
#include <Windows.UI.Xaml.Hosting.ReferenceTracker.h>

#include <WindowsNumerics.h>

#include <strsafe.h>
#include <robuffer.h>

// STL
#include <vector>
#include <map>
#include <functional>

#define _USE_MATH_DEFINES
#include <math.h>

#ifdef BUILD_WINDOWS
#include <staging.h>
#include <featurestaging-xaml.h>

#undef CATCH_RETURN // See our implementation in ErrorHandling.h

#else
#define WI_IS_FEATURE_PRESENT(FeatureName) 1
#endif

#undef GetCurrentTime

#include "CppWinRTIncludes.h"


// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//

#pragma once
#pragma warning (disable : 4514 4710 4711) // inlining
#pragma warning (disable: 5045) // TODO Spectre

// #define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#pragma warning (push, 1)
#pragma warning (disable : 5039 4668 4996 26814 4548 4355 4917 4702 26400 4987 4820 4365 4623 4625 4626 5026 5027 4571 4774 26412 26461 26426 26432 26447 26472 26446 26473 26440 26429 26496 26472 26482 26486 26487 26434)
#include <gsl.h>
#pragma warning (pop) // unbalanced push in span.h
#include <windows.h>
#include <Shlobj.h>
#include <Strsafe.h>

#include <algorithm>
#include <fstream>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <memory>
#include <string>
#include <vector>
#include <array>
#include <ranges>
#include <span>

#include "Resource.h"
#pragma warning (pop)


/*
  Copyright [2017-2020] [IBM Corporation]
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
  http://www.apache.org/licenses/LICENSE-2.0
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/
#ifndef __SHARD_CONNECTION_H__
#define __SHARD_CONNECTION_H__

#ifdef __cplusplus

#include "tls_session.h"
#include "buffer_manager.h"
#include "fabric_connection_base.h"  // default to fabric transport
#include "mcas_config.h"
#include "pool_manager.h"
#include "protocol.h"
#include "protocol_ostream.h"
#include "region_manager.h"
#include "connection_state.h"

#include <api/components.h>
#include <api/fabric_itf.h>
#include <api/kvstore_itf.h>
#include <common/exceptions.h>
#include <common/logging.h>
#include <gsl/pointers>

#include <cassert>
#include <map>
#include <queue>
#include <utility> /* swap */
#include <vector>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"

namespace mcas
{
using Connection_base = Fabric_connection_base;

/**
 * Connection handler is instantiated for each "connected" client
 */
class Connection_handler
  : public Connection_base,
    public Region_manager,
    private Connection_TLS_session
{
  friend class Connection_TLS_session;
  friend struct TLS_transport;

public:
  enum {
        TICK_RESPONSE_CONTINUE        = 0,
        TICK_RESPONSE_BOOTSTRAP_SPAWN = 1,
        TICK_RESPONSE_WAIT_SECURITY   = 2,
        TICK_RESPONSE_CLOSE           = 0xFF,
  };

  enum {
        ACTION_NONE = 0,
        ACTION_RELEASE_VALUE_LOCK_EXCLUSIVE,
        ACTION_POOL_DELETE,
  };

private:
  Connection_state    _state       = Connection_state::INITIAL;
  unsigned option_DEBUG = mcas::global::debug_level;

  /* list of pre-registered memory regions; normally one region */
  std::vector<component::IKVStore::memory_handle_t> _mr_vector;

  uint64_t                            _tick_count alignas(8);
  uint64_t                            _auth_id;
  std::queue<buffer_t *>              _pending_msgs;
  std::queue<action_t>                _pending_actions;
  Pool_manager                        _pool_manager; /* instance shared across connections */

  /* Adaptor point for different transports */
  using Connection = component::IFabric_server;
  using Factory    = component::IFabric_server_factory;

  struct stats {
    uint64_t response_count;
    uint64_t recv_msg_count;
    uint64_t send_msg_count;
    uint64_t wait_send_value_misses;
    uint64_t wait_msg_recv_misses;
    uint64_t wait_respond_complete_misses;
    uint64_t last_count;
    uint64_t next_stamp;
    stats()
      : response_count(0),
        recv_msg_count(0),
        send_msg_count(0),
        wait_send_value_misses(0),
        wait_msg_recv_misses(0),
        wait_respond_complete_misses(0),
        last_count(0),
        next_stamp(0)
    {
    }
  } _stats alignas(8);

  void dump_stats()
  {
    PINF("-----------------------------------------");
    PINF("| Connection Handler Statistics         |");
    PINF("-----------------------------------------");
    PINF("Ticks                       : %lu", _tick_count);
    PINF("Open pools                  : %lu", _pool_manager.open_pool_count());
    PINF("NEW_MSG_RECV misses         : %lu", _stats.wait_msg_recv_misses);
    PINF("Recv message count          : %lu", _stats.recv_msg_count);
    PINF("Send message count          : %lu", _stats.send_msg_count);
    PINF("Response count              : %lu", _stats.response_count);
    PINF("WAIT_SEND_VALUE misses      : %lu", _stats.wait_send_value_misses);
    PINF("WAIT_RESPOND_COMPLETE misses: %lu", _stats.wait_respond_complete_misses);
    PINF("-----------------------------------------");
  }

  /**
   * Change state in FSM
   *
   * @param s
   */
  inline void set_state(Connection_state s)
  {
    if (2 < option_DEBUG) {
      const std::map<Connection_state, const char *> m{
                                          {Connection_state::INITIAL, "INITIAL"},
                                          {Connection_state::WAIT_HANDSHAKE, "WAIT_HANDSHAKE"},
                                          {Connection_state::WAIT_TLS_HANDSHAKE, "WAIT_TLS_HANDSHAKE"},
                                          {Connection_state::CLIENT_DISCONNECTED, "CLIENT_DISCONNECTED"},
                                          {Connection_state::CLOSE_CONNECTION, "CLOSE_CONNECTION"},
                                          {Connection_state::WAIT_NEW_MSG_RECV, "WAIT_NEW_MSG_RECV"}};
      PLOG("state %s -> %s", m.find(_state)->second, m.find(s)->second);
    }
    _state = s; /* we could add transition checking later */
  }

  static void static_send_callback2(void *cnxn, buffer_t *iob) noexcept
  {
    auto base = static_cast<Fabric_connection_base *>(cnxn);
    static_cast<Connection_handler *>(base)->send_callback2(iob);
  }

  void send_callback2(buffer_t *iob) noexcept
  {
    assert(iob->value_adjunct);
    if (0 < option_DEBUG) {
      PLOG("Completed send2 (value_adjunct %p)", common::p_fmt(iob->value_adjunct));
    }
    _deferred_unlock.push(iob->value_adjunct);
    send_callback(iob);
  }

  /**
   * Send handshake response
   *
   * @param start_tls Set if a TLS handshake needs to be started
   */
  void respond_to_handshake(bool start_tls);

public:

  explicit Connection_handler(unsigned debug_level,
                              gsl::not_null<Factory *> factory,
                              gsl::not_null<Connection *> connection);

  virtual ~Connection_handler();

  inline bool client_connected() { return _state != Connection_state::CLIENT_DISCONNECTED; }

  auto allocate_send() { return allocate(static_send_callback); }
  auto allocate_recv() { return allocate(static_recv_callback); }

  /**
   * Initialize security session
   *
   * @param bind_ipaddr
   * @param bind_port
   */
  void configure_security(const std::string& bind_ipaddr,
                          const unsigned bind_port,
                          const std::string& cert_file,
                          const std::string& key_file);

  /**
   * State machine transition tick.  It is really important that this tick
   * execution duration is small, so that other connections are not impacted by
   * the thread not returning to them.
   *
   */
  int tick();
  /**
   * Check for network completions
   *
   */
  Fabric_connection_base::Completion_state check_network_completions()
  {
    auto state = poll_completions();

    while (!_deferred_unlock.empty()) {
      //      void *deferred_unlock = nullptr;
      //???     std::swap(deferred_unlock, _deferred_unlock.front());
      void *deferred_unlock = _deferred_unlock.front();
      if (option_DEBUG > 2)
        PLOG("adding action for deferred unlocking value @ %p", deferred_unlock);
      add_pending_action(action_t{ACTION_RELEASE_VALUE_LOCK_EXCLUSIVE, deferred_unlock});
      _deferred_unlock.pop();
    }

    return state;
  }

  /**
   * Peek at pending message from the connection. Used when the resources
   * required to process a pending nessage may depend on the content of the
   * message.
   *
   * @param msg [out] Pointer to base protocol message
   *
   * @return Pointer to buffer holding the message or null if there are none
   */
  inline mcas::protocol::Message *peek_pending_msg() const
  {
    return _pending_msgs.empty() ? nullptr
      : static_cast<mcas::protocol::Message *>(_pending_msgs.front()->base().get());
  }

  /**
   * Discard a pending message from the connection. Used along with tick
   * (which adds pending messages) and peek (which peeks at them).
   *
   * @param msg [out] Pointer to base protocol message
   *
   * @return Pointer to buffer holding the message or null if there are none
   */
  inline buffer_t *pop_pending_msg()
  {
    assert(!_pending_msgs.empty());
    auto iob = _pending_msgs.front();
    _pending_msgs.pop();
    return iob;
  }

  /**
   * Get deferred actions
   *
   * @param action [out] Action
   *
   * @return True if action
   */
  inline bool get_pending_action(action_t &action)
  {
    if (_pending_actions.empty()) return false;

    action = _pending_actions.front();

    if (option_DEBUG > 2) PLOG("Connection_handler: popped pending action (%u, %p)", action.op, action.parm);

    _pending_actions.pop();
    return true;
  }

  template <typename MT>
  void msg_log(const unsigned level_, const MT *msg_, const char *desc_, const char *direction_)
  {
    if (level_ < Connection_base::debug_level()) {
      std::ostringstream m;
      m << *msg_;
      PLOG("%s (%s) %s", direction_, desc_, m.str().c_str());
    }
  }

  template <typename MT>
  void msg_recv_log(const MT *m, const char *desc)
  {
    msg_recv_log(1, m, desc);
  }

  template <typename MT>
  void msg_recv_log(const unsigned level, const MT *msg, const char *desc)
  {
    msg_log(level, msg, desc, "RECV");
  }

  template <typename MT>
  void msg_send_log(const MT *m, const char *desc)
  {
    msg_send_log(1, m, desc);
  }

  template <typename MT>
  void msg_send_log(const unsigned level, const MT *msg, const char *desc)
  {
    msg_log(level, msg, desc, "SEND");
  }

  /**
   * Add an action to the pending queue
   *
   * @param action Action to add
   */
  inline void add_pending_action(const action_t& action)
  {
    _pending_actions.push(action);
  }

  template <typename Msg>
  void post_send_buffer(gsl::not_null<buffer_t *> buffer, Msg *msg, const char *desc)
  {
    msg_send_log(msg, desc);
    Connection_base::post_send_buffer(buffer);
  }

  template <typename Msg>
  void post_send_buffer_with_value(gsl::not_null<buffer_t *> buffer,
                         const ::iovec &           val_iov,
                         void *                    val_desc,
                         Msg *                     msg,
                         const char *              func_name)
  {
    msg_send_log(msg, func_name);
    Connection_base::post_send_buffer2(buffer, val_iov, val_desc);
  }

  /**
   * Post a response
   *
   * @param iob IO buffer to post
   */
  template <typename Msg>
  inline void post_response_with_value(gsl::not_null<buffer_t *> iob,
                             const ::iovec &           val_iov,
                             void *                    val_desc,
                             Msg *                     msg,
                             const char *              func_name)
  {
    iob->set_completion(static_send_callback2, val_iov.iov_base);
    post_send_buffer_with_value(iob, val_iov, val_desc, msg, func_name);
    /* don't wait for this, let it be picked up in the check_completions cycle
     */

    _stats.response_count++;
  }

  /**
   * Post a response
   *
   * @param iob IO buffer to post
   */
  template <typename Msg>
  inline void post_response(gsl::not_null<buffer_t *> iob, Msg *msg, const char *desc)
  {
    post_send_buffer(iob, msg, desc);
    /* don't wait for this, let it be picked up in the check_completions cycle
     */

    _stats.response_count++;
  }

  /**
   * Set up for pending value send/recv
   *
   * @param target
   * @param target_len
   * @param region
   */
  void add_memory_handle(component::IKVStore::memory_handle_t handle) { _mr_vector.push_back(handle); }

  component::IKVStore::memory_handle_t pop_memory_handle()
  {
    if (_mr_vector.empty()) return nullptr;
    auto mr = _mr_vector.back();
    _mr_vector.pop_back();
    return mr;
  }

  inline uint64_t       auth_id() const { return _auth_id; }
  inline void           set_auth_id(uint64_t id) { _auth_id = id; }
  inline size_t         max_message_size() const { return _max_message_size; }
  inline Pool_manager & pool_manager() { return _pool_manager; }

private:
  common::Byte_buffer _tls_buffer;
};

}  // namespace mcas

#pragma GCC diagnostic pop

#endif

#endif  // __CONNECTION_HANDLER_H__


#pragma once
#include <gsl/assert>

constexpr char deathstring[] = "Expected Death";
constexpr char failed_set_terminate_deathstring[] = ".*";

// This prevents a failed call to set_terminate from failing the test suite.
constexpr const char* GetExpectedDeathString(std::terminate_handler handle)
{
    return handle ? deathstring : failed_set_terminate_deathstring;
}


// SPDX-License-Identifier: MIT
// The MIT License (MIT)
//
// Copyright (c) 2014-2018, Institute for Software & Systems Engineering
// Copyright (c) 2018-2019, Johannes Leupolz
//
// 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 PEMC_EXECUTABLE_MODEL_TEMPORARY_STATE_STORAGE_H_
#define PEMC_EXECUTABLE_MODEL_TEMPORARY_STATE_STORAGE_H_

#include <vector>
#include <gsl/span>
#include <cstdint>
#include <atomic>
#include <boost/align/aligned_allocator.hpp>

#include "pemc/basic/tsc_index.h"
#include "pemc/basic/probability.h"
#include "pemc/basic/label.h"
#include "pemc/basic/model_capacity.h"
#include "pemc/basic/raw_memory.h"
#include "pemc/formula/formula.h"

namespace pemc {

  ///   We store states in a contiguous array, indexed by a continuous variable.
  ///   The TemporaryStateStorage is not thread safe.
  class TemporaryStateStorage {
  private:

      // The length in bytes of a state vector required for the analysis model.
      int32_t modelStateVectorSize = 0;
      // Extra bytes in state vector for preStateStorage modifiers.
      int32_t preStateStorageModifierStateVectorSize = 0;
      // The length in bytes of the state vector of the analysis model with the extra bytes
      // required for the preStateStorage modifiers
      int32_t stateVectorSize = 0;

      // The number of saved states
      StateIndex savedStates = 0;
  	  // The number of states that can be cached and the number of reserved states.
      StateIndex totalCapacity;

      // the memory that contains the serialized states
      std::vector<gsl::byte> stateMemory;

      void resizeStateBuffer();

  public:
      TemporaryStateStorage(StateIndex _capacity);

      StateIndex getNumberOfSavedStates();

      gsl::span<gsl::byte> operator [](size_t idx);

      StateIndex getFreshStateIndex();

      void setStateVectorSize(int32_t _modelStateVectorSize, int32_t _preStateStorageModifierStateVectorSize);

      void clear();
  };

}

#endif  // PEMC_EXECUTABLE_MODEL_TEMPORARY_STATE_STORAGE_H_


#pragma once
#include <typeinfo>
#include <gsl/gsl_assert>
#include <algorithm>
#include "halleystring.h"
#include <halley/support/exception.h>

namespace Halley
{

	template <typename T>
	struct EnumNames {
	};

	struct UserConverter
	{
		template<typename T, typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
		static String toString(const T& v)
		{
			return EnumNames<T>()()[int(v)];
		}

		template<typename T, typename std::enable_if<!std::is_enum<T>::value, int>::type = 0>
		static String toString(const T& v)
		{
			return v.toString();
		}

		template<typename T, typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
		static T fromString(const String& str)
		{
			EnumNames<T> n;
			auto names = n();
			auto res = std::find_if(std::begin(names), std::end(names), [&](const char* v) { return str == v; });
			if (res == std::end(names)) {
				throw Exception("String \"" + str + "\" does not exist in enum \"" + typeid(T).name() + "\".", HalleyExceptions::Utils);
			}
			return T(res - std::begin(names));
		}

		template<typename T, typename std::enable_if<!std::is_enum<T>::value, int>::type = 0>
		static T fromString(const String& str)
		{
			return T(str);
		}
	};

	template <typename T>
	struct ToStringConverter {
		String operator()(const T& s) const
		{
			return UserConverter::toString(s);
		}
	};

	template <typename T>
	struct FromStringConverter {
		T operator()(const String& s) const
		{
			return UserConverter::fromString<T>(s);
		}
	};

	template<size_t N>
	struct ToStringConverter<char[N]>
	{
		String operator()(const char s[N]) const
		{
			return String(s);
		}
	};

	template<>
	struct ToStringConverter<const char*>
	{
		String operator()(const char* s) const
		{
			return String(s);
		}
	};

	template<>
	struct ToStringConverter<char*>
	{
		String operator()(const char* s) const
		{
			return String(s);
		}
	};

	template<size_t N>
	struct ToStringConverter<wchar_t[N]>
	{
		String operator()(const wchar_t s[N]) const
		{
			return String(s);
		}
	};

	template<>
	struct ToStringConverter<const wchar_t*>
	{
		String operator()(const wchar_t* s) const
		{
			return String(s);
		}
	};

	template<>
	struct ToStringConverter<wchar_t*>
	{
		String operator()(const wchar_t* s) const
		{
			return String(s);
		}
	};

	template<>
	struct ToStringConverter<std::string>
	{
		String operator()(const std::string& s) const
		{
			return String(s);
		}
	};

	template<>
	struct ToStringConverter<bool>
	{
		String operator()(bool s) const
		{
			return String(s ? "true" : "false");
		}
	};

	template<>
	struct FromStringConverter<bool>
	{
		bool operator()(const String& s) const
		{
			return s == "true";
		}
	};

	template <typename T, typename std::enable_if<std::is_floating_point<T>::value, int>::type = 0>
	String toString(T src, int precisionDigits = -1, char decimalSeparator = '.')
	{
		Expects(precisionDigits >= -1 && precisionDigits <= 20);
		std::stringstream str;
		if (precisionDigits != -1) {
			str << std::fixed << std::setprecision(precisionDigits);
		}
		str << src;

		String result;
		if (precisionDigits == -1) {
			result = String::prettyFloat(str.str());
		} else {
			result = str.str();
		}

		if (decimalSeparator != '.') {
			result = result.replaceAll(String("."), String(decimalSeparator));
		}

		return result;
	}

	template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
	String toString(T value, int base = 10, int width = 1)
	{
		Expects(base == 10 || base == 16 || base == 8);
		std::stringstream ss;
		if (base == 16) {
			ss.setf(std::ios::hex, std::ios::basefield);
		} else if (base == 8) {
			ss.setf(std::ios::oct, std::ios::basefield);
		}
		if (width > 1) {
			ss << std::setfill('0') << std::setw(width);
		}
		ss << value;
		return ss.str();
	}

	template <typename T, typename std::enable_if<!std::is_integral<T>::value && !std::is_floating_point<T>::value, int>::type = 0>
	String toString(const T& value)
	{
		return ToStringConverter<typename std::remove_cv<T>::type>()(value);
	}

	template <typename T>
	T fromString(const String& value)
	{
		return FromStringConverter<T>()(value);
	}

	template <typename T, typename std::enable_if<!std::is_same<T, String>::value, int>::type = 0>
	String operator+ (const String& lhp, const T& rhp)
	{
		return lhp + toString<typename std::remove_cv<T>::type>(rhp);
	}

	template <typename T, typename std::enable_if<!std::is_same<T, String>::value, int>::type = 0>
	String operator+ (const T& lhp, const String& rhp)
	{
		return toString<typename std::remove_cv<T>::type>(lhp) + rhp;
	}

}


/*****************************************************************\
__
/ /
/ /                     __  __
/ /______    _______    / / / / ________   __       __
/ ______  \  /_____  \  / / / / / _____  | / /      / /
/ /      | / _______| / / / / / / /____/ / / /      / /
/ /      / / / _____  / / / / / / _______/ / /      / /
/ /      / / / /____/ / / / / / / |______  / |______/ /
/_/      /_/ |________/ / / / /  \_______/  \_______  /
/_/ /_/                     / /
/ /
High Level Game Framework            /_/

---------------------------------------------------------------

Copyright (c) 2007-2011 - Rodrigo Braz Monteiro.
This file is subject to the terms of halley_license.txt.

\*****************************************************************/

#pragma once

#include "halley/text/halleystring.h"
#include "halley/file/path.h"
#include <memory>
#include <functional>
#include <halley/concurrency/future.h>
#include <gsl/gsl>
#include "metadata.h"

namespace Halley {
	enum class AssetType;

	class ResourceDataReader {
	public:
		virtual ~ResourceDataReader() {}
		virtual size_t size() const = 0;
		virtual int read(gsl::span<gsl::byte> dst) = 0;
		virtual void seek(int64_t pos, int whence) = 0;
		virtual size_t tell() const = 0;
		virtual void close() = 0;

		Bytes readAll();
	};

	class ResourceData {
	public:
		ResourceData(String path);
		virtual ~ResourceData() {}

		String getPath() const { return path; }

	private:
		String path;
	};

	class ResourceDataStatic : public ResourceData {
	public:
		ResourceDataStatic(String path);
		ResourceDataStatic(const void* data, size_t size, String path, bool owning = true);

		void set(const void* data, size_t size, bool owning = true);
		bool isLoaded() const;

		const void* getData() const;
		gsl::span<const gsl::byte> getSpan() const;
		size_t getSize() const;
		String getString() const;
		void inflate();

		static std::unique_ptr<ResourceDataStatic> loadFromFileSystem(Path path);
		void writeToFileSystem(String path) const;

	private:
		std::shared_ptr<const char> data;
		size_t size = 0;
		bool loaded;
	};

	typedef std::function<std::unique_ptr<ResourceDataReader>()> ResourceDataMakeReader;
	class ResourceDataStream : public ResourceData {
	public:
		ResourceDataStream(String path, ResourceDataMakeReader makeReader);
		std::unique_ptr<ResourceDataReader> getReader() const { return make(); }

	private:
		ResourceDataMakeReader make;
	};

	class IResourceLocator
	{
	public:
		virtual ~IResourceLocator() {}
		virtual const Metadata& getMetaData(const String& resource, AssetType type) const = 0;
		virtual std::unique_ptr<ResourceDataStatic> getStatic(const String& asset, AssetType type) = 0;
		virtual std::unique_ptr<ResourceDataStream> getStream(const String& asset, AssetType type) = 0;
	};

	enum class ResourceLoadPriority {
		Low = 0,
		Normal = 1,
		High = 2
	};

	class HalleyAPI;
	class Metadata;

	class ResourceLoader
	{
		friend class ResourceCollectionBase;

	public:
		const String& getName() const { return name; }
		ResourceLoadPriority getPriority() const { return priority; }
		const HalleyAPI& getAPI() const { return *api; }
		const Metadata& getMeta() const { return *metadata; }

		std::unique_ptr<ResourceDataStatic> getStatic();
		std::unique_ptr<ResourceDataStream> getStream();
		Future<std::unique_ptr<ResourceDataStatic>> getAsync() const;

	private:
		ResourceLoader(ResourceLoader&& loader) noexcept;
		ResourceLoader(IResourceLocator& locator, const String& name, AssetType type, ResourceLoadPriority priority, const HalleyAPI* api);
		~ResourceLoader();

		IResourceLocator& locator;
		String name;
		AssetType type;
		ResourceLoadPriority priority;
		const HalleyAPI* api;
		const Metadata* metadata;
		bool loaded = false;
	};

}


#pragma once

#include <functional>
#include <memory>
#include <vector>

#include <gsl/gsl-lite.hpp> // gsl::span

#include <QObject>

#include "HypCommands.h" // Hyperion::RECORD_LENGTH

class DeviceLink;
class Recording;

class HypReader : public QObject
{
    Q_OBJECT
public:
    explicit HypReader(std::function<void(const QString&)> msgCBck,
                       std::function<void(size_t)> finishedCBck,
                       QObject* parent = nullptr);

    void DownloadFromDevice();
    void EraseDevice();

    bool LoadFromFile(const QString& filePath);
    bool SaveToFile  (const QString& filePath);

    size_t GetNumRecordings() const; // { return m_recordings.size(); }
    const Recording& GetRecording(size_t idx) const;

    Hyperion::DeviceType GetDeviceType() const;
    int         GetFirmwareVersionX100() const;

signals:
    void SeriesEnded();
    void DownloadFinish(bool success);

private:
    void EndSeries();
    void FinishDownload(bool success);

    // These get called from DeviceLink worker thread.
    // They emit the data to be processed on UI thread.
    void MarkSeriesEnd();
    void DownloadFinished(bool success);
    void ReceiveDataChunk(const gsl::span<uint8_t>& data);

//data:
    std::function<void(const QString&)> m_msgCBck;
    std::function<void(size_t)>         m_finishedCBck;
    std::unique_ptr<DeviceLink>         m_deviceReader;

    std::vector<std::vector<uint8_t>> m_downloadedRawData;
    std::vector<Recording>            m_recordings;

public:
    static const QString BS;
};


#include <bindings.cmacros.h>
#include <gsl/gsl_version.h>

BC_GLOBALARRAY(GSL_VERSION,char)
BC_GLOBALARRAY(gsl_version,char)


// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#pragma once

#include "arcana/functional/inplace_function.h"
#include "arcana/sentry.h"

#include "affinity.h"
#include "blocking_concurrent_queue.h"

#include <gsl/gsl>
#include <vector>

namespace mira
{
    template<size_t WorkSize>
    class dispatcher
    {
    public:
        using callback_t = stdext::inplace_function<void(), WorkSize>;
        static constexpr size_t work_size = WorkSize;

        template<typename T>
        void queue(T&& work)
        {
            m_work.push(std::forward<T>(work));
        }

        affinity get_affinity() const
        {
            return m_affinity;
        }

        dispatcher(const dispatcher&) = delete;
        dispatcher& operator=(const dispatcher&) = delete;

        virtual ~dispatcher() = default;

    protected:
        dispatcher() = default;
        dispatcher& operator=(dispatcher&&) = default;
        dispatcher(dispatcher&&) = default;

        bool tick(const cancellation& token)
        {
            return internal_tick(token, false);
        }

        bool blocking_tick(const cancellation& token)
        {
            return internal_tick(token, true);
        }

        /*
        Sets the dispatcher's tick thread affinity. Once this is set the methods
        on this instance will need to be called by that thread.
        */
        void set_affinity(const affinity& aff)
        {
            m_affinity = aff;
        }

        void cancelled()
        {
            m_work.cancelled();
        }

        void clear()
        {
            m_work.clear();
        }

    private:
        bool internal_tick(const cancellation& token, bool block)
        {
            GSL_CONTRACT_CHECK("thread affinity", m_affinity.check());

            if (block)
            {
                if (!m_work.blocking_drain(m_workload, token))
                    return false;
            }
            else
            {
                if (!m_work.try_drain(m_workload, token))
                    return false;
            }

            for (auto& work : m_workload)
            {
                work();
            }

            m_workload.clear();

            return true;
        }

        blocking_concurrent_queue<callback_t> m_work;
        affinity m_affinity;
        std::vector<callback_t> m_workload;
    };

    template<size_t WorkSize>
    class manual_dispatcher : public dispatcher<WorkSize>
    {
    public:
        using dispatcher<WorkSize>::blocking_tick;
        using dispatcher<WorkSize>::cancelled;
        using dispatcher<WorkSize>::clear;
        using dispatcher<WorkSize>::set_affinity;
        using dispatcher<WorkSize>::tick;
    };

    template<size_t WorkSize>
    class background_dispatcher : public dispatcher<WorkSize>
    {
    public:
        background_dispatcher()
            : m_registration{ m_cancellation.add_listener([this] { this->cancelled(); }) }
        {
            m_thread = std::thread{ [&]() {

                // TODO: Set the affinity when usage bugs are fixed.
                constexpr bool should_set_affinity{ false };
                if (should_set_affinity)
                {
                    this->set_affinity(std::this_thread::get_id());
                }

                while (!m_cancellation.cancelled())
                {
                    this->blocking_tick(m_cancellation);
                }
            } };
        }

        void cancel()
        {
            m_cancellation.cancel();

            if (m_thread.joinable())
            {
                m_thread.join();
            }

            this->clear();
        }

        ~background_dispatcher()
        {
            cancel();
        }

    private:
        std::thread m_thread;
        cancellation_source m_cancellation;
        cancellation_source::ticket m_registration;
    };
}


/*
 * Copyright (c) 2016-2021 lymastee, All rights reserved.
 * Contact: lymastee@hotmail.com
 *
 * This file is part of the gslib project.
 *
 * 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.
 */

#pragma once

#ifndef rendersys_5fadb7a4_2c63_4b3a_8029_14043d2405e6_h
#define rendersys_5fadb7a4_2c63_4b3a_8029_14043d2405e6_h

#include <ariel/config.h>
#include <ariel/type.h>
#include <gslib/std.h>
#include <ariel/image.h>

__ariel_begin__

enum shader_type
{
    st_vertex_shader,
    st_pixel_shader,
    st_geometry_shader,
    st_hull_shader,
    st_domain_shader,
    st_tessellation_shader,
    st_compute_shader,
    /* more.. */
};

enum sampler_state_filter
{
    ssf_point,
    ssf_linear,
    ssf_anisotropic,
};

struct render_device_info
{
    uint            vendor_id;
};

class __gs_novtable rendersys abstract
{
public:
    typedef unordered_map<string, string> configs;
    typedef render_vertex_buffer vertex_buffer;
    typedef render_index_buffer index_buffer;
    typedef render_constant_buffer constant_buffer;
    typedef render_texture1d texture1d;
    typedef render_texture2d texture2d;
    typedef render_texture3d texture3d;
    typedef render_sampler_state sampler_state;
    typedef unordered_map<void*, rendersys*> rsys_map;
    config_select_type(select_render_platform, vertex_format_desc);

public:
    rendersys();
    virtual ~rendersys() {}
    virtual bool setup(uint hwnd, const configs& cfg) = 0;
    virtual void destroy() = 0;
    virtual void setup_pipeline_state() = 0;
    virtual render_blob* compile_shader_from_file(const gchar* file, const gchar* entry, const gchar* sm, render_include* inc) = 0;
    virtual render_blob* compile_shader_from_memory(const char* src, int len, const gchar* name, const gchar* entry, const gchar* sm, render_include* inc) = 0;
    virtual vertex_shader* create_vertex_shader(const void* ptr, size_t len) = 0;
    virtual pixel_shader* create_pixel_shader(const void* ptr, size_t len) = 0;
    virtual compute_shader* create_compute_shader(const void* ptr, size_t len) = 0;
    virtual geometry_shader* create_geometry_shader(const void* ptr, size_t len) = 0;
    virtual hull_shader* create_hull_shader(const void* ptr, size_t len) = 0;
    virtual domain_shader* create_domain_shader(const void* ptr, size_t len) = 0;
    virtual vertex_format* create_vertex_format(const void* ptr, size_t len, vertex_format_desc desc[], uint n) = 0;
    virtual vertex_buffer* create_vertex_buffer(uint stride, uint count, bool read, bool write, uint usage, const void* ptr = 0) = 0;
    virtual index_buffer* create_index_buffer(uint count, bool read, bool write, uint usage, const void* ptr = 0) = 0;
    virtual constant_buffer* create_constant_buffer(uint stride, bool read, bool write, const void* ptr = 0) = 0;
    virtual shader_resource_view* create_shader_resource_view(render_resource* res) = 0;    /* texture view in GL */
    virtual depth_stencil_view* create_depth_stencil_view(render_resource* res) = 0;
    virtual unordered_access_view* create_unordered_access_view(render_resource* res) = 0;
    virtual sampler_state* create_sampler_state(sampler_state_filter filter) = 0;
    virtual texture2d* create_texture2d(const image& img, uint mips, uint usage, uint bindflags, uint cpuflags, uint miscflags) = 0;
    virtual texture2d* create_texture2d(int width, int height, uint format, uint mips, uint usage, uint bindflags, uint cpuflags, uint miscflags) = 0;
    virtual void load_with_mips(texture2d* tex, const image& img) = 0;
    virtual void update_buffer(void* buf, int size, const void* ptr) = 0;
    virtual void set_vertex_format(vertex_format* vfmt) = 0;
    virtual void set_vertex_buffer(vertex_buffer* vb, uint stride, uint offset) = 0;
    virtual void set_index_buffer(index_buffer* ib, uint offset) = 0;
    virtual void begin_render() = 0;
    virtual void end_render() = 0;
    virtual void set_render_option(render_option opt, uint val) = 0;
    virtual void set_vertex_shader(vertex_shader* vs) = 0;
    virtual void set_pixel_shader(pixel_shader* ps) = 0;
    virtual void set_geometry_shader(geometry_shader* gs) = 0;
    virtual void set_viewport(const viewport& vp) = 0;
    virtual void set_constant_buffer(uint slot, constant_buffer* cb, shader_type st) = 0;
    virtual void set_sampler_state(uint slot, sampler_state* sstate, shader_type st) = 0;
    virtual void set_shader_resource(uint slot, shader_resource_view* srv, shader_type st) = 0;
    virtual void draw(uint count, uint start) = 0;
    virtual void draw_indexed(uint count, uint start, int base = 0) = 0;
    virtual void capture_screen(image& img, const rectf& rc, int buff_id) = 0;      /* before present, buff_id = 0; after present, buff_id = 1 */
    virtual void enable_alpha_blend(bool b) = 0;
    virtual void enable_depth(bool b) = 0;

public:
    static bool is_vsync_enabled(const configs& cfg);
    static bool is_full_screen(const configs& cfg);
    static bool is_MSAA_enabled(const configs& cfg);
    static uint get_MSAA_sampler_count(const configs& cfg);
    static void register_dev_index_service(void* dev, rendersys* rsys);
    static void unregister_dev_index_service(void* dev);
    static rendersys* find_by_dev(void* dev);           /* we could usually find the rendersys by its device ptr */

protected:
    render_device_info      _device_info;
    float                   _bkcr[4];

public:
    const render_device_info& get_device_info() const { return _device_info; }
    void set_background_color(const color& cr);

private:
    static rsys_map         _dev_indexing;
};

extern void release_vertex_buffer(render_vertex_buffer* buf);
extern void release_index_buffer(render_index_buffer* buf);
extern void release_constant_buffer(render_constant_buffer* buf);
extern void release_texture2d(render_texture2d* tex);

template<class res_class>
render_resource* convert_to_resource(res_class*);

template<class _pack>
inline uint pack_cb_size()
{
    uint s = sizeof(_pack);
    uint m = s % 16;
    return !m ? s : s + (16 - m);
}

__ariel_end__

#endif


/* err/stream.c
 *
 * Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman, Brian Gough
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <config.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>

#include <gsl/gsl_errno.h>
#include <gsl/gsl_message.h>

FILE * gsl_stream = NULL ;
gsl_stream_handler_t * gsl_stream_handler = NULL;

void
gsl_stream_printf (const char *label, const char *file, int line,
		   const char *reason)
{
  if (gsl_stream == NULL)
    {
      gsl_stream = stderr;
    }
  if (gsl_stream_handler)
    {
      (*gsl_stream_handler) (label, file, line, reason);
      return;
    }
  fprintf (gsl_stream, "gsl: %s:%d: %s: %s\n", file, line, label, reason);

}

gsl_stream_handler_t *
gsl_set_stream_handler (gsl_stream_handler_t * new_handler)
{
  gsl_stream_handler_t * previous_handler = gsl_stream_handler;
  gsl_stream_handler = new_handler;
  return previous_handler;
}

FILE *
gsl_set_stream (FILE * new_stream)
{
  FILE * previous_stream;
  if (gsl_stream == NULL) {
    gsl_stream = stderr;
  }
  previous_stream = gsl_stream;
  gsl_stream = new_stream;
  return previous_stream;
}