#pragma once

#define NOMINMAX

#include <iostream>
#include <vector>
#include <string>
#include <string_view>
#include <sstream>
#include <variant>
#include <codecvt>
#include <locale>
#include <filesystem>
#include <fstream>
#include <chrono>
#include <functional>
#include <numeric>

#include <wrl/client.h>
#include <wil/result.h>
#include <Windows.h>
#include <d3d12.h>
#include <dxcore.h>

#include <gsl/gsl>

#define DML_TARGET_VERSION_USE_LATEST
#include <DirectML.h>
#include <directx/d3dx12.h>
#include "DirectMLX.h"

#include <rapidjson/document.h>
#include <rapidjson/istreamwrapper.h>

#include <fmt/format.h>


#pragma once

#include <gsl\gsl>
#include <winrt\base.h>
#include <d3d11.h>
#include "DrawableGameComponent.h"
#include "BasicTessellationMaterial.h"
#include "RenderStateHelper.h"

namespace Rendering
{
	class BasicTessellationDemo final : public Library::DrawableGameComponent
	{
	public:
		BasicTessellationDemo(Library::Game& game, const std::shared_ptr<Library::Camera>& camera);
		BasicTessellationDemo(const BasicTessellationDemo&) = delete;
		BasicTessellationDemo(BasicTessellationDemo&&) = default;
		BasicTessellationDemo& operator=(const BasicTessellationDemo&) = default;
		BasicTessellationDemo& operator=(BasicTessellationDemo&&) = default;
		~BasicTessellationDemo();

		bool UseUniformTessellation() const;
		void SetUseUniformTessellation(bool useUniformTessellation);
		void ToggleUseUniformTessellation();
		bool ShowQuadTopology() const;
		void SetShowQuadTopology(bool showQuadTopology);
		void ToggleTopology();

		gsl::span<const float> EdgeFactors() const;
		void SetUniformEdgeFactors(float factor);
		void SetEdgeFactor(float factor, std::uint32_t index);
		void SetInsideFactor(float factor, std::uint32_t index);

		gsl::span<const float> InsideFactors() const;

		virtual void Initialize() override;
		virtual void Draw(const Library::GameTime& gameTime) override;

	private:
		/*void UpdateEdgeFactors();
		void UpdateInsideEdgeFactors();*/

		Library::RenderStateHelper mRenderStateHelper;
		BasicTessellationMaterial mMaterial;
		winrt::com_ptr<ID3D11Buffer> mTriVertexBuffer;
		winrt::com_ptr<ID3D11Buffer> mQuadVertexBuffer;
		bool mUpdateMaterial{ true };
		bool mUseUniformTessellation{ true };
	};
}


/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2017-Present Couchbase, Inc.
 *
 *   Use of this software is governed by the Business Source License included
 *   in the file licenses/BSL-Couchbase.txt.  As of the Change Date specified
 *   in that file, in accordance with the Business Source License, use of this
 *   software will be governed by the Apache License, Version 2.0, included in
 *   the file licenses/APL2.txt.
 */

#pragma once

#include "atomic.h"
#include "monotonic.h"

#include <memcached/types.h>
#include <gsl/gsl>

#include <functional>
#include <unordered_map>

struct DocKey;

namespace Collections {

// The reserved name of the system owned, default collection.
const char* const DefaultCollectionName = "_default";
static std::string_view DefaultCollectionIdentifier(DefaultCollectionName);

const char* const DefaultScopeName = "_default";
static std::string_view DefaultScopeIdentifier(DefaultScopeName);

// The SystemEvent keys are given some human readable tags to make disk or
// memory dumps etc... more helpful.
const char* const CollectionEventDebugTag = "_collection";
const char* const ScopeEventDebugTag = "_scope";

// Couchstore private file name for manifest data
const char CouchstoreManifest[] = "_local/collections_manifest";

// Name of file where the manifest will be kept on persistent buckets
const char* const ManifestFile = "collections.manifest";
static std::string_view ManifestFileName(ManifestFile);

// Length of the string excluding the zero terminator (i.e. strlen)
const size_t CouchstoreManifestLen = sizeof(CouchstoreManifest) - 1;

using ManifestUid = WeaklyMonotonic<uint64_t>;

// Struct/Map used in summary stat collecting (where we do vb accumulation)
struct AccumulatedStats {
    AccumulatedStats& operator+=(const AccumulatedStats& other);
    uint64_t itemCount{0};
    uint64_t diskSize{0};
    uint64_t opsStore{0};
    uint64_t opsDelete{0};
    uint64_t opsGet{0};
};
using Summary = std::unordered_map<CollectionID, AccumulatedStats>;

struct ManifestUidNetworkOrder {
    explicit ManifestUidNetworkOrder(ManifestUid uid) : uid(htonll(uid)) {
    }
    ManifestUid to_host() const {
        return ManifestUid(ntohll(uid));
    }
    ManifestUid::value_type uid;
};
static_assert(sizeof(ManifestUidNetworkOrder) == 8,
              "ManifestUidNetworkOrder must have fixed size of 8 bytes as "
              "written to disk.");

/**
 * Return a ManifestUid from a C-string.
 * A valid ManifestUid is a C-string where each character satisfies
 * std::isxdigit and can be converted to a ManifestUid by std::strtoull.
 *
 * @param uid C-string uid
 * @param len a length for validation purposes
 * @throws std::invalid_argument if uid is invalid
 */
ManifestUid makeUid(const char* uid, size_t len = 16);

/**
 * Return a ManifestUid from a std::string
 * A valid ManifestUid is a std::string where each character satisfies
 * std::isxdigit and can be converted to a ManifestUid by std::strtoull.
 *
 * @param uid std::string
 * @throws std::invalid_argument if uid is invalid
 */
static inline ManifestUid makeUid(const std::string& uid) {
    return makeUid(uid.c_str());
}

/**
 * Return a CollectionID from a C-string.
 * A valid CollectionID is a C-string where each character satisfies
 * std::isxdigit and can be converted to a CollectionID by std::strtoul.
 *
 * @param uid C-string uid
 * @throws std::invalid_argument if uid is invalid
 */
static inline CollectionID makeCollectionID(const char* uid) {
    // CollectionID is 8 characters max and smaller than a ManifestUid
    return gsl::narrow_cast<CollectionID>(makeUid(uid, 8));
}

/**
 * Return a CollectionID from a std::string
 * A valid CollectionID is a std::string where each character satisfies
 * std::isxdigit and can be converted to a CollectionID by std::strtoul
 *
 * @param uid std::string
 * @throws std::invalid_argument if uid is invalid
 */
static inline CollectionID makeCollectionID(const std::string& uid) {
    return makeCollectionID(uid.c_str());
}

/**
 * Return a ScopeID from a C-string.
 * A valid CollectionID is a std::string where each character satisfies
 * std::isxdigit and can be converted to a CollectionID by std::strtoul
 * @param uid C-string uid
 * @return std::invalid_argument if uid is invalid
 */
static inline ScopeID makeScopeID(const char* uid) {
    // ScopeId is 8 characters max and smaller than a ManifestUid
    return gsl::narrow_cast<ScopeID>(makeUid(uid, 8));
}

/**
 * Return a ScopeID from a std::string
 * A valid ScopeID is a std::string where each character satisfies
 * std::isxdigit and can be converted to a CollectionID by std::strtoul
 * @param uid std::string
 * @return std::invalid_argument if uid is invalid
 */
static inline ScopeID makeScopeID(const std::string& uid) {
    return makeScopeID(uid.c_str());
}

/**
 * The metadata of a single collection
 *
 * Default construction yields the default collection
 */
struct CollectionMetaData {
    ScopeID sid{ScopeID::Default}; // The scope that the collection belongs to
    CollectionID cid{CollectionID::Default}; // The collection's ID
    std::string name{DefaultCollectionName}; // The collection's name
    cb::ExpiryLimit maxTtl{}; // The collection's maxTTL

    bool operator==(const CollectionMetaData& other) const {
        return sid == other.sid && cid == other.cid && name == other.name &&
               maxTtl == other.maxTtl;
    }
};

/**
 * The metadata of a single scope
 *
 * Default construction yields the default scope
 */
struct ScopeMetaData {
    ScopeID sid{ScopeID::Default}; // The scope's ID
    std::string name{DefaultScopeName}; // The scope's name

    bool operator==(const ScopeMetaData& other) const {
        return sid == other.sid && name == other.name;
    }
};

/**
 * For creation of collection SystemEvents - The SystemEventFactory
 * glues the CollectionID into the event key (so create of x doesn't
 * collide with create of y). This method yields the 'keyExtra' parameter
 *
 * @param collection The value to turn into a string
 * @return the keyExtra parameter to be passed to SystemEventFactory
 */
std::string makeCollectionIdIntoString(CollectionID collection);

/**
 * For creation of collection SystemEvents - The SystemEventFactory
 * glues the CollectionID into the event key (so create of x doesn't
 * collide with create of y). This method basically reverses
 * makeCollectionIdIntoString so we can get a CollectionID from a
 * SystemEvent key
 *
 * @param key DocKey from an Item in the System namespace and is a collection
 *        event
 * @return the ID which was in the event
 */
CollectionID getCollectionIDFromKey(const DocKey& key);

/// Same as getCollectionIDFromKey but for events changing scopes
ScopeID getScopeIDFromKey(const DocKey& key);

/**
 * Callback function for processing against dropped collections in an ephemeral
 * vb, returns true if the key at seqno should be dropped
 *
 * @param DocKey the key of the item we should process
 * @param int64_t the seqno of the item
 */
using IsDroppedEphemeralCb = std::function<bool(const DocKey&, int64_t)>;

/**
 * A function for determining if a collection is visible
 */
using IsVisibleFunction =
        std::function<bool(ScopeID, std::optional<CollectionID>)>;

namespace VB {
enum class ManifestUpdateStatus {
    Success,
    // The new Manifest has a 'UID' that is < current.
    Behind,
    // The new Manifest has a 'UID' that is == current, but adds/drops
    // collections/scopes.
    EqualUidWithDifferences,
    // The new Manifest changes scopes or collections immutable properties, e.g.
    // current has {id:8, name:"c1"} and new has {id:8,name:"c2"}.
    ImmutablePropertyModified
};
std::string to_string(ManifestUpdateStatus);

/// values required by the flusher to calculate new collection statistics
struct StatsForFlush {
    uint64_t itemCount;
    size_t diskSize;
    uint64_t highSeqno;
};

// Following classes define the metadata that will be held by the Manager but
// referenced from VB::Manifest
class CollectionSharedMetaData;
class CollectionSharedMetaDataView {
public:
    CollectionSharedMetaDataView(std::string_view name,
                                 ScopeID scope,
                                 cb::ExpiryLimit maxTtl);
    CollectionSharedMetaDataView(const CollectionSharedMetaData&);
    std::string to_string() const;
    std::string_view name;
    const ScopeID scope;
    const cb::ExpiryLimit maxTtl;
};

// The type stored by the Manager SharedMetaDataTable
class CollectionSharedMetaData : public RCValue {
public:
    CollectionSharedMetaData(std::string_view name,
                             ScopeID scope,
                             cb::ExpiryLimit maxTtl);
    CollectionSharedMetaData(const CollectionSharedMetaDataView& view);
    bool operator==(const CollectionSharedMetaDataView& view) const;
    bool operator!=(const CollectionSharedMetaDataView& view) const {
        return !(*this == view);
    }
    bool operator==(const CollectionSharedMetaData& meta) const;
    bool operator!=(const CollectionSharedMetaData& meta) const {
        return !(*this == meta);
    }

    const std::string name;
    const ScopeID scope;
    const cb::ExpiryLimit maxTtl;
};
std::ostream& operator<<(std::ostream& os,
                         const CollectionSharedMetaData& meta);

class ScopeSharedMetaData;
class ScopeSharedMetaDataView {
public:
    ScopeSharedMetaDataView(const ScopeSharedMetaData&);
    ScopeSharedMetaDataView(std::string_view name) : name(name) {
    }
    std::string to_string() const;
    std::string_view name;
};

// The type stored by the Manager SharedMetaDataTable
class ScopeSharedMetaData : public RCValue {
public:
    ScopeSharedMetaData(const ScopeSharedMetaDataView& view);
    bool operator==(const ScopeSharedMetaDataView& view) const;
    bool operator!=(const ScopeSharedMetaDataView& view) const {
        return !(*this == view);
    }
    bool operator==(const ScopeSharedMetaData& meta) const;
    bool operator!=(const ScopeSharedMetaData& meta) const {
        return !(*this == meta);
    }

    const std::string name;
};
std::ostream& operator<<(std::ostream& os, const ScopeSharedMetaData& meta);

} // namespace VB

} // end namespace Collections


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

#pragma once

#include "arcana/bob/bob_helpers.h"

#include <cstdint>
#include <string>
#include <vector>

#include <cereal/cereal.hpp>
#include <cereal/types/vector.hpp>

#include <gsl/gsl>

namespace mira
{
    namespace bob
    {
        namespace v1
        {
            namespace
            {
                constexpr std::uint32_t VERSION = 1;
            }

            //
            // manifest and stream_file_header are both types found in the json
            // manifest file. This file describes in a human readable format what the bob
            // stream contains and which data it depends on.
            //
            // entry_instance is the header data of each instance of an entry stream in the
            // binary stream file (.bob).
            //

            //
            //  Describes what the binary stream file contains
            //
            class stream_file_header
            {
            public:
                //
                //  An entry describes the properties of one type of packet found in the stream
                //
                class entry
                {
                public:
                    entry()
                        : m_name{}
                        , m_type{}
                        , m_version{}
                    {}

                    entry(std::string name, ::uint32_t version)
                        : m_name{ std::move(name) }
                        , m_type{}
                        , m_version{ version }
                    {}

                    entry(std::string name, std::string type, ::uint32_t version)
                        : m_name{ std::move(name) }
                        , m_type{ std::move(type) }
                        , m_version{ version }
                    {}

                    const std::string& name() const
                    {
                        return m_name;
                    }

                    const std::string& type() const
                    {
                        return m_type;
                    }

                    std::uint32_t version() const
                    {
                        return m_version;
                    }

                    template<typename Archive>
                    void serialize(Archive& ar)
                    {
                        ar(cereal::make_nvp("Name", m_name), cereal::make_nvp("Type", m_type), cereal::make_nvp("Version", m_version));
                    }

                private:
                    std::string m_name;
                    std::string m_type;
                    std::uint32_t m_version;
                };

                stream_file_header() = default;

                explicit stream_file_header(std::vector<entry> entries)
                    : m_entries(std::move(entries))
                {}

                std::uint32_t version() const
                {
                    return VERSION;
                }

                const std::vector<entry>& entries() const
                {
                    return m_entries;
                }

                template<typename Archive>
                void serialize(Archive& ar, const std::uint32_t version)
                {
                    if (version != VERSION)
                        throw_invalid_version();

                    ar(cereal::make_nvp("Entries", m_entries));
                }

            private:
                std::vector<entry> m_entries;
            };

            class manifest
            {
            public:
                manifest() = default;

                manifest(stream_file_header header)
                    : m_stream{ std::move(header) }
                {}

                std::uint32_t version() const
                {
                    return VERSION;
                }

                const stream_file_header& stream() const
                {
                    return m_stream;
                }

                template<typename Archive>
                void serialize(Archive& ar, const std::uint32_t version)
                {
                    if (version != VERSION)
                        throw_invalid_version();

                    ar(cereal::make_nvp("Stream", m_stream));
                }

            private:
                stream_file_header m_stream;
            };

            //
            // describes an entry in the binary stream, the data for the entry
            // is contained between this block and the next.
            //
            struct entry_instance
            {
                std::int64_t Timestamp;
                std::int64_t NextBlockOffset;
                std::int32_t EntryIdx;

                template<typename Archive>
                void serialize(Archive& ar, const std::uint32_t version)
                {
                    if (version != VERSION)
                        throw_invalid_version();

                    ar(CEREAL_NVP(Timestamp), CEREAL_NVP(NextBlockOffset), CEREAL_NVP(EntryIdx));
                }
            };
        }

        using namespace v1;
    }
}

CEREAL_CLASS_VERSION(::mira::bob::v1::manifest, ::mira::bob::v1::VERSION);
CEREAL_CLASS_VERSION(::mira::bob::v1::stream_file_header, ::mira::bob::v1::VERSION);


#pragma once

#include <gsl\gsl>
#include <winrt\base.h>
#include <d3d11.h>
#include "DrawableGameComponent.h"
#include "FullScreenQuad.h"

namespace Rendering
{
	class ComputeShaderMaterial;

	class ComputeShaderDemo final : public Library::DrawableGameComponent
	{
	public:
		ComputeShaderDemo(Library::Game& game, const std::shared_ptr<Library::Camera>& camera);
		ComputeShaderDemo(const ComputeShaderDemo&) = delete;
		ComputeShaderDemo(ComputeShaderDemo&&) = default;
		ComputeShaderDemo& operator=(const ComputeShaderDemo&) = default;
		ComputeShaderDemo& operator=(ComputeShaderDemo&&) = default;
		~ComputeShaderDemo();

		bool AnimationEnabled() const;
		void SetAnimationEnabled(bool enabled);

		float BlueColor() const;
		void SetBlueColor(float blueColor);

		virtual void Initialize() override;
		virtual void Update(const Library::GameTime& gameTime) override;
		virtual void Draw(const Library::GameTime& gameTime) override;

	private:
		std::unique_ptr<ComputeShaderMaterial> mMaterial;
		Library::FullScreenQuad mFullScreenQuad;
		winrt::com_ptr<ID3D11ShaderResourceView> mColorTexture;
		bool mAnimationEnabled{ true };
	};
}


#pragma once
/*
 * (C) Copyright 2020-2021 UCAR
 *
 * This software is licensed under the terms of the Apache Licence Version 2.0
 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
 */
/*! \addtogroup ioda_cxx_variable
 *
 * @{
 * \file Has_Variables.h
 * \brief Interfaces for ioda::Has_Variables and related classes.
 */

#include <cstring>
#include <gsl/gsl-lite.hpp>
#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "ioda/Attributes/Attribute_Creator.h"
#include "ioda/Exception.h"
#include "ioda/Layout.h"
#include "ioda/Misc/Eigen_Compat.h"
#include "ioda/Misc/MergeMethods.h"
#include "ioda/Types/Type.h"
#include "ioda/Variables/FillPolicy.h"
#include "ioda/Variables/Variable.h"
#include "ioda/defs.h"

namespace ioda {
class Has_Variables;
class ObsGroup;
struct Named_Variable;
namespace detail {
class Has_Variables_Backend;
class Has_Variables_Base;
class DataLayoutPolicy;
class Group_Base;

}  // namespace detail

/// \brief A few chunking strategies for Variables
namespace chunking {
/// Convenience function for setting default chunking parameters.
inline bool Chunking_Max(const std::vector<Dimensions_t>& in, std::vector<Dimensions_t>& out) {
  out = in;
  return true;
}
}  // namespace chunking

/// \brief Used to specify Variable creation-time properties.
/// \ingroup ioda_cxx_variable
struct IODA_DL VariableCreationParameters {
private:
  std::vector<std::pair<unsigned int, Variable> > dimsToAttach_;
  std::string dimScaleName_;

public:
  /// @name Fill Value
  /// @{

  detail::FillValueData_t fillValue_;

  template <class DataType>
  VariableCreationParameters& setFillValue(DataType fill) {
    detail::assignFillValue<DataType>(fillValue_, fill);
    return *this;
  }
  inline VariableCreationParameters& unsetFillValue() {
    fillValue_.set_ = false;
    return *this;
  }

  /// @}
  /// @name Chunking and compression
  /// @{

  /// \brief Do we chunk this variable? Required for extendible / compressible Variables.
  /// \details Requires a chunking strategy.
  bool chunk = false;

  /// \brief Manually specify the chunks. Never directly use. Use getChunks(...) instead.
  std::vector<Dimensions_t> chunks;
  /// Set variable chunking strategy. Used only if chunk == true and chunks.size() == 0.
  std::function<bool(const std::vector<Dimensions_t>&, std::vector<Dimensions_t>&)>
    fChunkingStrategy = chunking::Chunking_Max;
  /// Figure out the chunking size
  /// \param cur_dims are the current dimensions
  std::vector<Dimensions_t> getChunks(const std::vector<Dimensions_t>& cur_dims) const {
    if (chunks.size()) return chunks;
    std::vector<Dimensions_t> res;
    if (fChunkingStrategy(cur_dims, res)) return res;
    throw Exception("Cannot figure out an appropriate chunking size.", ioda_Here());
  }

  bool gzip_                        = false;
  bool szip_                        = false;
  int gzip_level_                   = 6;  // 1 (fastest) - 9 (most compression)
  unsigned int szip_PixelsPerBlock_ = 16;
  unsigned int szip_options_        = 4;  // Defined as H5_SZIP_EC_OPTION_MASK in hdf5.h;

  void noCompress();
  void compressWithGZIP(int level = 6);
  void compressWithSZIP(unsigned PixelsPerBlock = 16, unsigned options = 4);

  /// @}
  /// @name General Functions
  /// @{

  /// Set any initial attributes here
  Attribute_Creator_Store atts;

  VariableCreationParameters();
  VariableCreationParameters(const VariableCreationParameters&);
  VariableCreationParameters& operator=(const VariableCreationParameters&);

  template<class DataType>
  static VariableCreationParameters defaulted() {
    VariableCreationParameters ret;
    ret.chunk = true;
    ret.compressWithGZIP();
    FillValuePolicies::applyFillValuePolicy<DataType>(FillValuePolicy::NETCDF4, ret.fillValue_);
    return ret;
  }
  template <class DataType>
  static VariableCreationParameters defaults() {
    return defaulted<DataType>();
  }

  /// Finalize routine to make sure struct members are intact (e.g. for fill values)
  detail::FillValueData_t::FillValueUnion_t finalize() const { return fillValue_.finalize(); }

  detail::python_bindings::VariableCreationFillValues<VariableCreationParameters> _py_setFillValue;

private:
  friend class detail::Has_Variables_Base;
  /// Apply the properties to a Variable (second pass; after Variable is created).
  Variable applyImmediatelyAfterVariableCreation(Variable h) const;

  /// @}
};

typedef std::vector<Variable> NewVariables_Scales_t;
/// \brief Used to specify a new variable with the collective createWithScales function.
struct IODA_DL NewVariable_Base : std::enable_shared_from_this<NewVariable_Base> {
  /// Name of the variable.
  std::string name_;
  /// Type of the new dimension. Int, char, etc. Used if a type is not passed directly.
  std::type_index dataType_;
  /// Type of the new dimension. Used if a type is passed directly.
  Type dataTypeKnown_;
  /// Dimension scales
  NewVariables_Scales_t scales_;
  /// Var creation params
  VariableCreationParameters vcp_;

  virtual ~NewVariable_Base() {}

  NewVariable_Base(const std::string& name, const Type& dataType,
                   const NewVariables_Scales_t& scales,
                   const VariableCreationParameters& params)
      : name_(name), dataType_(typeid(void)), dataTypeKnown_(dataType),
        scales_(scales),
        vcp_(params) {}

  NewVariable_Base(const std::string& name, const std::type_index& dataType,
                   const NewVariables_Scales_t& scales,
                   const VariableCreationParameters& params)
      : name_(name),
        dataType_(dataType),
        scales_(scales),
        vcp_(params) {}
};
typedef std::vector<std::shared_ptr<NewVariable_Base>> NewVariables_t;

template <class DataType>
inline std::shared_ptr<NewVariable_Base> NewVariable(
  const std::string& name, const NewVariables_Scales_t& scales,
  const VariableCreationParameters& params = VariableCreationParameters::defaulted<DataType>()) {
  return std::make_shared<NewVariable_Base>(name, typeid(DataType), scales, params);
}

inline std::shared_ptr<NewVariable_Base> NewVariable(const std::string& name,
                                                     const Type& DataType,
                                                     const NewVariables_Scales_t& scales,
                                                     const VariableCreationParameters& params
                                                     = VariableCreationParameters()) {
  return std::make_shared<NewVariable_Base>(name, DataType, scales, params);
}

namespace detail {

/// \ingroup ioda_cxx_variable
class IODA_DL Has_Variables_Base {
  // friend class Group_Base;
private:
  /// Using an opaque object to implement the backend.
  std::shared_ptr<Has_Variables_Backend> backend_;
  /// Set by ObsGroup.
  std::shared_ptr<const detail::DataLayoutPolicy> layout_;
  std::vector<ComplementaryVariableCreationParameters> complementaryVariables_;
  /// \brief FillValuePolicy helper
  /// \details Hides the template function calls, so that the headers are smaller.
  static void _py_fvp_helper(BasicTypes dataType, FillValuePolicy& fvp,
                             VariableCreationParameters& params);

  ComplementaryVariableCreationParameters createDerivedVariableParameters(
      const std::string &inputName, const std::string &outputName, size_t position);
  std::vector<std::vector<std::string>> loadComponentVariableData(
      const ComplementaryVariableCreationParameters& derivedVariableParams);

protected:
  Has_Variables_Base(std::shared_ptr<Has_Variables_Backend>,
                     std::shared_ptr<const DataLayoutPolicy> = nullptr);

public:
  virtual ~Has_Variables_Base();

  /// Set the mapping policy to determine the Layout of Variables stored under this Group.
  /// Usually only set by ObsGroup when we create / open.
  virtual void setLayout(std::shared_ptr<const detail::DataLayoutPolicy>);

  /// Query the backend and get the type provider.
  virtual Type_Provider* getTypeProvider() const;

  /// \brief Get the fill value policy used for Variables within this Group
  /// \details The backend has to be consulted for this operation. Storage of this policy is
  /// backend-dependent.
  virtual FillValuePolicy getFillValuePolicy() const;

  /// @name General Functions
  /// @{
  ///

  /// \brief Does a Variable with the specified name exist?
  /// \param name is the name of the Variable that we are looking for.
  /// \returns true if it exists.
  /// \returns false otherwise.
  virtual bool exists(const std::string& name) const;
  /// \brief Delete an Attribute with the specified name.
  /// \param attname is the name of the Variable that we are deleting.
  /// \throws ioda::Exception if no such attribute exists.
  virtual void remove(const std::string& name);
  /// \brief Open a Variable by name
  /// \param name is the name of the Variable to be opened.
  /// \returns An instance of a Variable that can be queried (with getDimensions()) and read.
  virtual Variable open(const std::string& name) const;
  /// \brief Open a Variable by name
  /// \param name is the name of the Variable to be opened.
  /// \returns An instance of a Variable that can be queried (with getDimensions()) and read.
  inline Variable operator[](const std::string& name) const { return open(name); }

  /// List all Variables under this group (one-level search).
  /// \see Group_Base::listObjects if you need to enumerate both Groups and Variables, or
  ///   if you need recursion.
  virtual std::vector<std::string> list() const;
  /// Convenience function to list all Variables under this group (one-level search).
  /// \see Group_Base::listObjects if you need to enumerate both Groups and Variables, or
  ///   if you need recursion.
  inline std::vector<std::string> operator()() const { return list(); }

  /// \brief Combines all complementary variables as specified in the mapping file, opens them,
  /// and optionally removes the originals from the ObsGroup.
  ///
  /// \p removeOriginals determines if the original complementary variables should be removed from
  /// the ObsGroup. Later functionality will ensure that the original complementary variables can
  /// be recreated on writing back to the original file.
  void stitchComplementaryVariables(bool removeOriginals = true);

  /// \brief Converts unit to SI for all eligible variables. If conversion function not defined,
  /// stores unit as attribute.
  ///
  /// Makes the conversion if the variable's unit is defined in the mapping file and the unit conversion
  /// is defined in UnitConversions.h.
  void convertVariableUnits(std::ostream &out = std::cerr);

  /// \brief Create a Variable without setting its data.
  /// \param attrname is the name of the Variable.
  /// \param dimensions is a vector representing the size of the metadata.
  ///   Each element of the vector is a dimension with a certain size.
  /// \param in_memory_datatype is the runtime description of the Attribute's data type.
  /// \returns A Variable that can be written to.
  virtual Variable create(const std::string& name, const Type& in_memory_dataType,
                          const std::vector<Dimensions_t>& dimensions     = {1},
                          const std::vector<Dimensions_t>& max_dimensions = {},
                          const VariableCreationParameters& params = VariableCreationParameters());

  /// Python compatability function
  /// \note Multiple ways to specify dimensions to match possible
  ///   Python function signatures.
  Variable _create_py(const std::string& name, BasicTypes dataType,
                             const std::vector<Dimensions_t>& cur_dimensions = {1},
                             const std::vector<Dimensions_t>& max_dimensions = {},
                             const std::vector<Variable>& dimension_scales   = {},
                             const VariableCreationParameters& params
                             = VariableCreationParameters());

  inline Variable create(const std::string& name, const Type& in_memory_dataType,
                         const ioda::Dimensions& dims,
                         const VariableCreationParameters& params = VariableCreationParameters()) {
    return create(name, in_memory_dataType, dims.dimsCur, dims.dimsMax, params);
  }

  /// \brief Create a Variable without setting its data.
  /// \tparam DataType is the type of the data. I.e. float, int32_t, uint16_t, std::string, etc.
  /// \param name is the name of the Variable.
  /// \param dimensions is a vector representing the size of the metadata. Each element of the
  ///   vector is a dimension with a certain size.
  /// \returns A Variable that can be written to.
  template <class DataType>
  Variable create(const std::string& name, const std::vector<Dimensions_t>& dimensions = {1},
                  const std::vector<Dimensions_t>& max_dimensions = {},
                  const VariableCreationParameters& params        = VariableCreationParameters::defaulted<DataType>()) {
    try {
      VariableCreationParameters params2 = params;
      FillValuePolicies::applyFillValuePolicy<DataType>(getFillValuePolicy(), params2.fillValue_);
      Type in_memory_dataType = Types::GetType<DataType>(getTypeProvider());
      auto var                = create(name, in_memory_dataType, dimensions,
        max_dimensions, params2);
      return var;
    } catch (...) {
      std::throw_with_nested(Exception(ioda_Here()));
    }
  }

  template <class DataType>
  Variable create(const std::string& name, const ioda::Dimensions& dims,
                  const VariableCreationParameters& params
                  = VariableCreationParameters::defaulted<DataType>()) {
    try {
      VariableCreationParameters params2 = params;
      FillValuePolicies::applyFillValuePolicy<DataType>(getFillValuePolicy(), params2.fillValue_);
      return create<DataType>(name, dims.dimsCur, dims.dimsMax, params2);
    } catch (...) {
      std::throw_with_nested(Exception(ioda_Here()));
    }
  }

  /// \brief Convenience function to create a Variable from certain dimension scales.
  /// \tparam DataType is the type of the data. I.e. int, int32_t, uint16_t, std::string, etc.
  /// \param name is the name of the Variable.
  /// \param dimensions is a vector representing the size of the metadata. Each element of the
  ///   vector is a dimension with a certain size.
  /// \returns A Variable that can be written to.
  template <class DataType>
  Variable createWithScales(const std::string& name,
                            const std::vector<Variable>& dimension_scales,
                            const VariableCreationParameters& params
                            = VariableCreationParameters::defaulted<DataType>()) {
    try {
      Type in_memory_dataType = Types::GetType<DataType>(getTypeProvider());

      NewVariables_t newvars{NewVariable(name, in_memory_dataType, dimension_scales, params)};
      createWithScales(newvars);
      return open(name);
    } catch (...) {
      std::throw_with_nested(Exception(ioda_Here()));
    }
  }

  /// @brief Collective function optimized to mass-construct variables and attach scales.
  /// @param newvars is a vector of the new variables to be created.
  /// @see NewVariable for the signature of the objects to add.
  void createWithScales(const NewVariables_t& newvars);

  /// @}
  /// @name Collective functions
  /// @brief These functions apply the an operation to a *set* of variables in situations where
  ///   such an operation would produce better performance results than a loop of serial
  ///   function calls.
  /// @{

  /// @brief Attach dimension scales to many Dimension Numbers in a set of Variables.
  /// @param DimensionNumber
  /// @param mapping is the scale mappings for each variable. The first part of the pair refers
  ///   to the variable that you are attaching scales to. The second part is a sequence of
  ///   scales that are attached along each dimension (indexed by the vector).
  /// @details
  /// For some backends, particularly HDF5, attaching a dimension scale to a variable is a slow
  /// procedure when you have many variables. This function batches low-level calls and avoids
  /// loops.
  virtual void attachDimensionScales(
    const std::vector<std::pair<Variable, std::vector<Variable>>>& mapping);

  /// @}
};

class IODA_DL Has_Variables_Backend : public detail::Has_Variables_Base {
protected:
  Has_Variables_Backend();

public:
  virtual ~Has_Variables_Backend();
  FillValuePolicy getFillValuePolicy() const override;
  void attachDimensionScales(
    const std::vector<std::pair<Variable, std::vector<Variable>>>& mapping) override;
};
}  // namespace detail

/// \brief This class exists inside of ioda::Group and provides the interface to manipulating
///   Variables.
/// \ingroup ioda_cxx_variable
///
/// \note It should only be constructed inside of a Group. It has no meaning elsewhere.
/// \see ioda::Variable for the class that represents individual variables.
/// \throws ioda::Exception on all exceptions.
class IODA_DL Has_Variables : public detail::Has_Variables_Base {
public:
  virtual ~Has_Variables();
  Has_Variables();
  Has_Variables(std::shared_ptr<detail::Has_Variables_Backend>,
                std::shared_ptr<const detail::DataLayoutPolicy> = nullptr);
};
}  // namespace ioda

/// @}


#pragma once
#include "halley/plugin/iasset_importer.h"
#include <yaml-cpp/node/node.h>
#include "halley/core/graphics/material/material_definition.h"
#include <gsl/span>

namespace Halley
{
	class MaterialDefinition;

	class MaterialImporter : public IAssetImporter
	{
	public:
		ImportAssetType getType() const override { return ImportAssetType::MaterialDefinition; }

		void import(const ImportingAsset& asset, IAssetCollector& collector) override;

		MaterialDefinition parseMaterial(Path basePath, gsl::span<const gsl::byte> data, IAssetCollector& collector) const;

	private:
		static void loadPass(MaterialDefinition& material, const ConfigNode& node, IAssetCollector& collector, int passN);
		static void loadUniforms(MaterialDefinition& material, const YAML::Node& topNode);
		static void loadTextures(MaterialDefinition& material, const YAML::Node& topNode);
		static void loadAttributes(MaterialDefinition& material, const YAML::Node& topNode);

		static ShaderParameterType parseParameterType(String rawType);
		static int getAttributeSize(ShaderParameterType type);

		static Bytes loadShader(const String& name, IAssetCollector& collector);
		static Bytes doLoadShader(const String& name, IAssetCollector& collector, std::set<String>& loaded);
	};
}


#ifndef _EM_IO_H_
#define _EM_IO_H_ 1

#include <petsc.h>

struct EMContext;

PetscErrorCode read_mdl(const char *, EMContext *);
PetscErrorCode read_emd(const char *, EMContext *);

PetscErrorCode save_mesh(EMContext *, const char *, int);
PetscErrorCode save_rsp(EMContext *, const char *);

#endif


/*	$Id$ */
/*
 * Copyright (c) 2014, 2015 Kristaps Dzonsons <kristaps@kcons.eu>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#include <assert.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#include <cairo.h>
#include <cairo-pdf.h>
#include <cairo-ps.h>
#include <gtk/gtk.h>
#include <gsl/gsl_multifit.h>
#include <kplot.h>

#include "extern.h"

enum	savetype {
	SAVE_PDF,
	SAVE_PS,
	SAVE_EPS
};

static int
savepng(const gchar *fname, const struct curwin *c)
{
	cairo_surface_t	*surf;
	cairo_t		*cr;
	cairo_status_t	 st;

	g_debug("%p: Saving: %s", c, fname);
	surf = cairo_image_surface_create
		(CAIRO_FORMAT_ARGB32, 600, 400);
	st = cairo_surface_status(surf);
	if (CAIRO_STATUS_SUCCESS != st) {
		g_debug("%s", cairo_status_to_string(st));
		cairo_surface_destroy(surf);
		return(0);
	}

	cr = cairo_create(surf);
	cairo_surface_destroy(surf);

	st = cairo_status(cr);
	if (CAIRO_STATUS_SUCCESS != st) {
		g_debug("%s", cairo_status_to_string(st));
		cairo_destroy(cr);
		return(0);

	}

	cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
	cairo_rectangle(cr, 0.0, 0.0, 600.0, 400.0);
	cairo_fill(cr);
	kplot_draw(c->views[c->view], 600.0, 400.0, cr);

	st = cairo_surface_write_to_png(cairo_get_target(cr), fname);

	if (CAIRO_STATUS_SUCCESS != st) {
		g_debug("%s", cairo_status_to_string(st));
		cairo_destroy(cr);
		return(0);
	}

	cairo_destroy(cr);
	return(1);
}

static int
savepdf(const gchar *fname, struct curwin *c, enum savetype type)
{
	cairo_surface_t	*surf;
	cairo_t		*cr;
	cairo_status_t	 st;
	struct kplotcfg	*cfg;
	struct kdatacfg	*datas;
	size_t		 datasz, i, j;
	int		 rc;
	double		 svtic, svaxis, svborder, svgrid, sv, svticln;
	const double	 w = 72 * 6, h = 72 * 5;

	g_debug("%p: Saving: %s", c, fname);
	switch (type) {
	case (SAVE_PDF):
		surf = cairo_pdf_surface_create(fname, w, h);
		break;
	case (SAVE_EPS):
		surf = cairo_ps_surface_create(fname, w, h);
		cairo_ps_surface_set_eps(surf, 1);
		break;
	case (SAVE_PS):
		surf = cairo_ps_surface_create(fname, w, h);
		cairo_ps_surface_set_eps(surf, 0);
		break;
	default:
		abort();
	}

	st = cairo_surface_status(surf);
	if (CAIRO_STATUS_SUCCESS != st) {
		g_debug("%s", cairo_status_to_string(st));
		cairo_surface_destroy(surf);
		return(0);
	}

	cr = cairo_create(surf);
	cairo_surface_destroy(surf);

	st = cairo_status(cr);
	if (CAIRO_STATUS_SUCCESS != st) {
		g_debug("%s", cairo_status_to_string(st));
		cairo_destroy(cr);
		return(0);

	}

	cfg = kplot_get_plotcfg(c->views[c->view]);

	svtic = cfg->ticlabelfont.sz;
	svaxis = cfg->axislabelfont.sz;
	svborder = cfg->borderline.sz;
	svgrid = cfg->gridline.sz;
	svticln = cfg->ticline.sz;
	sv = 0.0; /* Silence compiler. */

	cfg->ticlabelfont.sz = 9.0;
	cfg->axislabelfont.sz = 9.0;
	cfg->borderline.sz = 0.5;
	cfg->gridline.sz = 0.5;
	cfg->ticline.sz = 0.5;

	for (i = 0; ; i++) {
		rc = kplot_get_datacfg(c->views[c->view],
			i, &datas, &datasz);
		if (0 == rc)
			break;
		for (j = 0; j < datasz; j++) {
			sv = datas[j].line.sz;
			datas[j].line.sz = 1.0;
		}
	}

	cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
	cairo_rectangle(cr, 0.0, 0.0, w, h);
	cairo_fill(cr);
	kplot_draw(c->views[c->view], w, h, cr);
	cairo_destroy(cr);

	cfg->ticlabelfont.sz = svtic;
	cfg->axislabelfont.sz = svaxis;
	cfg->borderline.sz = svborder;
	cfg->gridline.sz = svgrid;
	cfg->ticline.sz = svticln;

	for (i = 0; ; i++) {
		rc = kplot_get_datacfg(c->views[c->view],
			i, &datas, &datasz);
		if (0 == rc)
			break;
		for (j = 0; j < datasz; j++)
			datas[j].line.sz = sv;
	}

	return(1);
}

int
save(const gchar *fname, struct curwin *cur)
{

	if (g_str_has_suffix(fname, ".pdf"))
		return(savepdf(fname, cur, SAVE_PDF));
	else if (g_str_has_suffix(fname, ".ps"))
		return(savepdf(fname, cur, SAVE_PS));
	else if (g_str_has_suffix(fname, ".eps"))
		return(savepdf(fname, cur, SAVE_EPS));
	else
		return(savepng(fname, cur));
}

int
saveconfig(const gchar *fname, const struct curwin *cur)
{
	FILE		*f;
	struct sim	*sim;
	GList		*l;

	g_debug("%p: Saving configuration: %s", cur, fname);

	if (NULL == (f = fopen(fname, "w"))) {
		g_debug("%s: %s", fname, strerror(errno));
		return(0);
	}

	for (l = cur->sims; NULL != l; l = g_list_next(l)) {
		sim = l->data;
		fprintf(f, "Name: %s\n", sim->name);
		fprintf(f, "Colour: #%.2x%.2x%.2x\n",
			(unsigned int)(cur->b->clrs[sim->colour].rgba[0] * 255),
			(unsigned int)(cur->b->clrs[sim->colour].rgba[1] * 255),
			(unsigned int)(cur->b->clrs[sim->colour].rgba[2] * 255));
		fprintf(f, "Function: %s\n", sim->func);
		fprintf(f, "Threads: %zu\n", sim->nprocs);
		fprintf(f, "Multiplier: %g(1 + %g lambda)\n",
			sim->alpha, sim->delta);
		fprintf(f, "Max generations: %zu\n", sim->stop);
		fprintf(f, "Migration: %g (%suniform)\n",
			sim->m, NULL != sim->ms ? "non-" : "");
		fprintf(f, "Incumbents: %zu, [%g,%g)\n",
			sim->dims, sim->xmin, sim->xmax);
		fprintf(f, "Rolling average window: %zu\n", sim->smoothing);
		switch (sim->maptop) {
		case (MAPTOP_RECORD):
			fprintf(f, "Map: record-based\n");
			break;
		case (MAPTOP_RAND):
			fprintf(f, "Map: random\n");
			break;
		case (MAPTOP_TORUS):
			fprintf(f, "Map: torus\n");
			break;
		default:
			abort();
		}
		switch (sim->migrant) {
		case (MAPMIGRANT_UNIFORM):
			fprintf(f, "Migration: uniform\n");
			break;
		case (MAPMIGRANT_DISTANCE):
			fprintf(f, "Migration: distance\n");
			break;
		case (MAPMIGRANT_NEAREST):
			fprintf(f, "Migration: nearest\n");
			break;
		case (MAPMIGRANT_TWONEAREST):
			fprintf(f, "Migration: two nearest\n");
			break;
		default:
			abort();
		}
		if (MAPINDEX_STRIPED == sim->mapindex)
			fprintf(f, "Mutant index case: striped\n");
		else
			fprintf(f, "Mutant index case: fixed (%zu)\n",
				sim->mapindexfix);
		if (MUTANTS_DISCRETE == sim->mutants)
			fprintf(f, "Mutants: %zu, [%g,%g)\n",
				sim->dims, sim->ymin, sim->ymax);
		else
			fprintf(f, "Mutants: N(sigma=%g), [%g,%g)\n",
				sim->mutantsigma, sim->ymin, sim->ymax);
		fprintf(f, "Islands: %zu (%zu islanders)\n",
			sim->islands, sim->totalpop);
		if (NULL != sim->pops)
			fprintf(f, "Island populations: non-uniform\n");
		else
			fprintf(f, "Island populations: %zu\n", sim->pop);
		fprintf(f, "Fit polynomial: %zu (%sweighted)\n",
			sim->fitpoly, 0 == sim->weighted ? "un" : "");

		fprintf(f, "\n");
	}

	fclose(f);
	return(1);
}


/* -----------------------------------------------------------------------------
 * Copyright 2021 Jonathan Haigh
 * SPDX-License-Identifier: MIT
 * ---------------------------------------------------------------------------*/

#ifndef SQ_INCLUDE_GUARD_system_schema_h_
#define SQ_INCLUDE_GUARD_system_schema_h_

#include "core/Primitive.h"
#include "core/typeutil.h"

#include <cstddef>
#include <gsl/gsl>
#include <optional>
#include <string_view>

namespace sq::system {

class SchemaImpl;

/**
 * Represents the schema for a primitive type.
 */
class PrimitiveTypeSchema {
public:
  constexpr explicit PrimitiveTypeSchema(std::string_view name,
                                         std::string_view doc)
      : name_{name}, doc_{doc} {}

  SQ_ND std::string_view name() const;
  SQ_ND std::string_view doc() const;

private:
  std::string_view name_;
  std::string_view doc_;
};

/**
 * Represents the schema for a parameter of field of a system object.
 */
class ParamSchema {
public:
  constexpr ParamSchema(std::string_view name, std::string_view doc,
                        std::size_t index, std::size_t type_index,
                        bool required, std::string_view default_value_str,
                        std::string_view default_value_doc)
      : name_{name}, doc_{doc}, index_{index}, type_index_{type_index},
        required_{required}, default_value_str_{default_value_str},
        default_value_doc_{default_value_doc} {}

  SQ_ND std::string_view name() const;
  SQ_ND std::string_view doc() const;
  SQ_ND std::size_t index() const;
  SQ_ND const PrimitiveTypeSchema &type() const;
  SQ_ND bool required() const;
  SQ_ND std::optional<Primitive> default_value() const;
  SQ_ND std::string_view default_value_doc() const;

private:
  std::string_view name_;
  std::string_view doc_;
  std::size_t index_;
  std::size_t type_index_;
  bool required_;
  std::string_view default_value_str_;
  std::string_view default_value_doc_;
};

class TypeSchema;

/**
 * Represents the schema for a field of a system object.
 */
class FieldSchema {
public:
  constexpr FieldSchema(std::string_view name, std::string_view doc,
                        std::size_t params_begin_index,
                        std::size_t params_end_index,
                        std::size_t return_type_index, bool return_list,
                        bool null)
      : name_{name}, doc_{doc}, params_begin_index_{params_begin_index},
        params_end_index_{params_end_index},
        return_type_index_{return_type_index},
        return_list_{return_list}, null_{null} {}

  SQ_ND std::string_view name() const;
  SQ_ND std::string_view doc() const;
  SQ_ND gsl::span<const ParamSchema> params() const;
  SQ_ND const TypeSchema &return_type() const;
  SQ_ND bool return_list() const;
  SQ_ND bool null() const;

private:
  std::string_view name_;
  std::string_view doc_;
  std::size_t params_begin_index_;
  std::size_t params_end_index_;
  std::size_t return_type_index_;
  bool return_list_;
  bool null_;
};

/**
 * Represents the schema for a system object.
 */
class TypeSchema {
public:
  constexpr TypeSchema(std::string_view name, std::string_view doc,
                       std::size_t fields_begin_index,
                       std::size_t fields_end_index)
      : name_{name}, doc_{doc}, fields_begin_index_{fields_begin_index},
        fields_end_index_{fields_end_index} {}

  SQ_ND std::string_view name() const;
  SQ_ND std::string_view doc() const;
  SQ_ND gsl::span<const FieldSchema> fields() const;

private:
  std::string_view name_;
  std::string_view doc_;
  std::size_t fields_begin_index_;
  std::size_t fields_end_index_;
};

/**
 * Represents the whole SQ schema.
 */
struct Schema {
public:
  SQ_ND gsl::span<const TypeSchema> types() const;
  SQ_ND gsl::span<const PrimitiveTypeSchema> primitive_types() const;
  SQ_ND const TypeSchema &root_type() const;
};

/**
 * Get the whole SQ schema.
 */
const Schema &schema();

} // namespace sq::system

#endif // SQ_INCLUDE_GUARD_system_schema_h_


#pragma once
#include "Ds4Color.h"
#include <gsl/span>

/**
 * \brief PoD for setting \c Ds4Device parameters like motor speed, light color, etc.
 */
struct Ds4Output
{
	uint8_t  rightMotor    = 0;
	uint8_t  leftMotor     = 0;
	Ds4Color lightColor    = {};
	uint8_t  flashOnDur    = 0;
	uint8_t  flashOffDur   = 0;
	uint8_t  volumeLeft    = 50;
	uint8_t  volumeRight   = 50;
	uint8_t  volumeMic     = 50;
	uint8_t  volumeSpeaker = 50;

	/**
	 * \brief Updates a buffer with the stored device parameters.
	 * \param buffer Buffer to update.
	 * \return \c true if changes have been made to \a buffer.
	 */
	bool update(const gsl::span<uint8_t>& buffer) const;
};


// 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_GENERIC_TRAVERSER_TRAVERSAL_TRANSITION_H_
#define PEMC_GENERIC_TRAVERSER_TRAVERSAL_TRANSITION_H_

#include <gsl/gsl_byte>
#include <cstdint>

#include "pemc/basic/tsc_index.h"
#include "pemc/basic/label.h"

namespace pemc {

  enum TraversalTransitionFlags : uint32_t {
    NoFlag,

		/// If set, the value of targetStateIndex is set and targetState is invalid.
		/// If unset, the value of targetState is set and targetStateIndex is invalid.
    IsTargetStateTransformedToIndex = 1,

    /// If set, the transition is invalid and should be ignored
    IsTransitionInvalid = 2,

    /// If set, the transition leads to the stuttering state and the state in targetState
    /// shall be ignored.
    IsToStutteringState = 4
  };

  struct TraversalTransition {
    // 4 bytes / 8 bytes
    union {
      gsl::byte* targetState;  // is set prior to adding  the state to state storage
      StateIndex targetStateIndex; // is set after having added the state to state storage
    };

    // 4 bytes
    TraversalTransitionFlags flags;

    // 4 bytes
    Label label;

    TraversalTransition()
      : targetState(nullptr), flags(TraversalTransitionFlags::NoFlag), label(Label()){
    }

    TraversalTransition(gsl::byte* _targetState, Label _label)
      : targetState(_targetState), flags(TraversalTransitionFlags::NoFlag), label(_label) {
    }
  };

  inline TraversalTransitionFlags operator|(TraversalTransitionFlags a, TraversalTransitionFlags b) {
    return static_cast<TraversalTransitionFlags>(static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
  }

  inline TraversalTransitionFlags operator|=(TraversalTransitionFlags a, const TraversalTransitionFlags b) {
    a =  static_cast<TraversalTransitionFlags>(static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
    return a;
  }

}

#endif  // PEMC_GENERIC_TRAVERSER_TRAVERSAL_TRANSITION_H_


#pragma once
#ifndef _SECURE_ATL
#define _SECURE_ATL 1
#endif
#include "framework.h"
#include <strsafe.h>

// <tas=uncomment to use Guidelines Support Library https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md">
#pragma warning (push)
#pragma warning (disable: 4003)
//#include <gsl/gsl>
//#include <gsl/gsl_algorithm> // copy
#include <gsl/gsl_assert> // Ensures/Expects
//#include <gsl/gsl_byte> // byte
#include <gsl/gsl_util> // finally()/narrow()/narrow_cast()...
//#include <gsl/multi_span> // multi_span, strided_span...
#include <gsl/pointers> // owner, not_null
//#include <gsl/span> // span
#include <gsl/string_span> // zstring, string_span, zstring_builder...
#pragma warning (pop)
// </tas>
#include "Resource.h"

// OD_OLE_SUPPORT
// Vectorization support for OLE objects on Windows can be obtained by including this module: OdOleItemHandler
// Source for this module is located in [kernel root]/Extensions/win/OleItemHandler.
// OLE support can be enabled by linking in the OdOleItemHandler module and registering "OdOleItemHandler" using the ODRX_DEFINE_STATIC_APPLICATION macro.
// For the DLL version, place the OdOleItemHandler.tx module in the same directory as the DLLs (no explicit registration required).
// Uncomment #define for support
// #define OD_OLE_SUPPORT 1
#include <OdaCommon.h>
#include <Ge/GePoint3d.h>
#include <Ge/GeVector3d.h>
#include <Ge/GeMatrix3d.h>

unsigned AFXAPI HashKey(CString& string) noexcept;

#include "SafeMath.h"

inline double MillimetersToInches(const double millimeters) {
	return millimeters / kMmPerInch;
}

inline double InchesToMillimeters(const double inches) {
	return inches * kMmPerInch;
}

// <tas="Static analysis"/>
// Compiler warnings that are off by default (https://docs.microsoft.com/en-us/cpp/preprocessor/compiler-warnings-that-are-off-by-default?view=vs-2019)
#pragma warning (default: 4165) // (level 1) 'HRESULT' is being converted to 'bool'; are you sure this is what you want ?
#pragma warning (default: 4264) // (level 1) 'virtual_function': no override available for virtual member function from base 'class'; function is hidden
#pragma warning (default: 4342) // (level 1) behavior change : 'function' called, but a member operator was called in previous versions
#pragma warning (default: 4350) // (level 1) behavior change : 'member1' called instead of 'member2'
#pragma warning (default: 4426) // (level 1) optimization flags changed after including header, may be due to #pragma optimize()
#pragma warning (default: 4472) // (level 1) 'identifier' is a native enum : add an access specifier(private / public) to declare a managed enum
#pragma warning (default: 4545) // (level 1) expression before comma evaluates to a function which is missing an argument list
#pragma warning (default: 4545) // (level 1) expression before comma evaluates to a function which is missing an argument list
#pragma warning (default: 4546) // (level 1) function call before comma missing argument list
#pragma warning (default: 4547) // (level 1) 'operator': operator before comma has no effect; expected operator with side - effect
#pragma warning (default: 4548) // (level 1) expression before comma has no effect; expected expression with side - effect
#pragma warning (default: 4549) // (level 1) 'operator1': operator before comma has no effect; did you intend 'operator2' ?
#pragma warning (default: 4555) // (level 1) expression has no effect; expected expression with side - effect
#pragma warning (default: 4577) // (level 1) 'noexcept' used with no exception handling mode specified; termination on exception is not guaranteed.Specify / EHsc
#pragma warning (default: 4587) // (level 1) 'anonymous_structure': behavior change : constructor is no longer implicitly called
#pragma warning (default: 4588) // (level 1) 'anonymous_structure' : behavior change : destructor is no longer implicitly called
#pragma warning (default: 4598) // (level 1 and level 3) '#include "header"': header number number in the precompiled header does not match current compilation at that position
#pragma warning (default: 4605) // (level 1) '/Dmacro' specified on current command line, but was not specified when precompiled header was built
#pragma warning (default: 4628) // (level 1) digraphs not supported with - Ze.Character sequence 'digraph' not interpreted as alternate token for 'char'
#pragma warning (default: 4692) // (level 1) 'function': signature of non - private member contains assembly private native type 'native_type'
#pragma warning (default: 4822) // (level 1) 'member' : local class member function does not have a body
#pragma warning (default: 4905) // (level 1) wide string literal cast to 'LPSTR'
#pragma warning (default: 4906) // (level 1) string literal cast to 'LPWSTR'
#pragma warning (default: 4917) // (level 1) 'declarator' : a GUID can only be associated with a class, interface, or namespace
#pragma warning (default: 4928) // (level 1) illegal copy - initialization; more than one user - defined conversion has been implicitly applied
#pragma warning (default: 4946) // (level 1) reinterpret_cast used between related classes : 'class1'and 'class2'
#pragma warning (default: 5026) // (level 1 and level 4) 'type' : move constructor was implicitly defined as deleted
#pragma warning (default: 5027) // (level 1 and level 4) 'type' : move assignment operator was implicitly defined as deleted
#pragma warning (default: 5036) // (level 1) varargs function pointer conversion when compiling with / hybrid : x86arm64 'type1' to 'type2'
#pragma warning (default: 4412) // (level 2) 'function': function signature contains type 'type'; C++ objects are unsafe to pass between pure code and mixed or native
#pragma warning (default: 4826) // (level 2) Conversion from 'type1' to 'type2' is sign - extended.This may cause unexpected runtime behavior.
#pragma warning (default: 4191) // (level 3) 'operator': unsafe conversion from 'type_of_expression' to 'type_required'
#pragma warning (default: 4265) // (level 3) 'class' : class has virtual functions, but destructor is not virtual
#pragma warning (default: 4287) // (level 3) 'operator' : unsigned / negative constant mismatch
#pragma warning (default: 4370) // (level 3) layout of class has changed from a previous version of the compiler due to better packing
#pragma warning (default: 4371) // (level 3) 'classname' : layout of class may have changed from a previous version of the compiler due to better packing of member 'member'
#pragma warning (default: 4444) // (level 3) top level '__unaligned' is not implemented in this context
#pragma warning (default: 4557) // (level 3) '__assume' contains effect 'effect'
#pragma warning (default: 4599) // (level 3) 'option path' : command - line argument number number does not match pre - compiled header 14.3
#pragma warning (default: 4608) // (level 3) 'union_member' has already been initialized by another union member in the initializer list, 'union_member' Perm
#pragma warning (default: 4619) // (level 3) #pragma warning : there is no warning number 'number'
#pragma warning (default: 4640) // (level 3) 'instance' : construction of local static object is not thread - safe
#pragma warning (default: 4647) // (level 3) behavior change : __is_pod(type) has different value in previous versions
#pragma warning (default: 4686) // (level 3) 'user-defined type' : possible change in behavior, change in UDT return calling convention
#pragma warning (default: 4738) // (level 3) storing 32 - bit float result in memory, possible loss of performance
#pragma warning (default: 4768) // (level 3) __declspec attributes before linkage specification are ignored
#pragma warning (default: 4786) // (level 3) 'symbol' : object name was truncated to 'number' characters in the debug information
#pragma warning (default: 5042) // (level 3) 'function' : function declarations at block scope cannot be specified 'inline' in standard C++; remove 'inline' specifier
#pragma warning (default: 4061) // (level 4) enumerator 'identifier' in a switch of enum 'enumeration' is not explicitly handled by a case label
#pragma warning (default: 4062) // (level 4) enumerator 'identifier' in a switch of enum 'enumeration' is not handled
#pragma warning (default: 4242) // (level 4) 'identifier': conversion from 'type1' to 'type2', possible loss of data
#pragma warning (default: 4254) // (level 4) 'operator' : conversion from 'type1' to 'type2', possible loss of data
#pragma warning (default: 4255) // (level 4) 'function': no function prototype given: converting '()' to '(void)'
#pragma warning (default: 4263) // (level 4) 'function' : member function does not override any base class virtual member function
#pragma warning (default: 4266) // (level 4) 'function': no override available for virtual member function from base 'type'; function is hidden
#pragma warning (default: 4289) // (level 4) nonstandard extension used : 'var' : loop control variable declared in the for - loop is used outside the for - loop scope
#pragma warning (default: 4296) // (level 4) 'operator' : expression is always false
#pragma warning (default: 4339) // (level 4) 'type' : use of undefined type detected in CLR meta - data - use of this type may lead to a runtime exception
#pragma warning (default: 4365) // (level 4) 'action' : conversion from 'type_1' to 'type_2', signed/unsigned mismatch
#pragma warning (default: 4388) // (level 4) signed / unsigned mismatch
#pragma warning (default: 4435) // (level 4) 'class1' : Object layout under / vd2 will change due to virtual base 'class2'
#pragma warning (default: 4437) // (level 4) dynamic_cast from virtual base 'class1' to 'class2' could fail in some contexts
#pragma warning (default: 4464) // (level 4) relative include path contains '..'
#pragma warning (default: 4471) // (level 4) a forward declaration of an unscoped enumeration must have an underlying type(int assumed) Perm
#pragma warning (default: 4514) // (level 4) 'function' : unreferenced inline function has been removed
#pragma warning (default: 4536) // (level 4) 'type name' : type - name exceeds meta - data limit of 'limit' characters
#pragma warning (default: 4571) // (level 4) informational : catch (...) semantics changed since Visual C++ 7.1; structured exceptions(SEH) are no longer caught
#pragma warning (default: 4574) // (level 4) 'identifier' is defined to be '0': did you mean to use '#if identifier' ?
#pragma warning (default: 4582) // (level 4) 'type' : constructor is not implicitly called
#pragma warning (default: 4583) // (level 4) 'type' : destructor is not implicitly called
#pragma warning (default: 4596) // (level 4) 'identifier' : illegal qualified name in member declaration 14.3 Perm
#pragma warning (default: 4623) // (level 4) 'derived class' : default constructor could not be generated because a base class default constructor is inaccessible
#pragma warning (default: 4625) // (level 4) 'derived class' : copy constructor could not be generated because a base class copy constructor is inaccessible
#pragma warning (default: 4626) // (level 4) 'derived class' : assignment operator could not be generated because a base class assignment operator is inaccessible
#pragma warning (default: 4643) // (level 4) Forward declaring 'identifier' in namespace std is not permitted by the C++ Standard.
#pragma warning (default: 4654) // (level 4) Code placed before include of precompiled header line will be ignored.Add code to precompiled header.
#pragma warning (default: 4668) // (level 4) 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives'
#pragma warning (default: 4682) // (level 4) 'symbol' : no directional parameter attribute specified, defaulting to[in]
#pragma warning (default: 4710) // (level 4) 'function' : function not inlined
#pragma warning (default: 4749) // (level 4) conditionally supported : offsetof applied to non - standard - layout type 'type'
#pragma warning (default: 4767) // (level 4) section name 'symbol' is longer than 8 characters and will be truncated by the linker
#pragma warning (default: 4774) // (level 4) 'string' : format string expected in argument number is not a string literal
#pragma warning (default: 4777) // (level 4) 'function' : format string 'string' requires an argument of type 'type1', but variadic argument number has type 'type2'
// <tas="requires VS 2019"/>#pragma warning (default: 4800) // (level 4) Implicit conversion from 'type' to bool.Possible information loss
#pragma warning (default: 4820) // (level 4) 'bytes' bytes padding added after construct 'member_name'
#pragma warning (default: 4837) // (level 4) trigraph detected : '??character' replaced by 'character'
#pragma warning (default: 4841) // (level 4) non - standard extension used : compound member designator used in offsetof
#pragma warning (default: 4842) // (level 4) the result of 'offsetof' applied to a type using multiple inheritance is not guaranteed to be consistent between compiler releases
#pragma warning (default: 4868) // (level 4) 'file(line_number)' compiler may not enforce left - to - right evaluation order in braced initialization list
#pragma warning (default: 4931) // (level 4) we are assuming the type library was built for number - bit pointers
#pragma warning (default: 4986) // (level 4) 'symbol' : exception specification does not match previous declaration
#pragma warning (default: 4987) // (level 4) nonstandard extension used : 'throw (...)'
#pragma warning (default: 4988) // (level 4) 'symbol' : variable declared outside class / function scope
#pragma warning (default: 5024) // (level 4) 'type' : move constructor was implicitly defined as deleted
#pragma warning (default: 5025) // (level 4) 'type' : move assignment operator was implicitly defined as deleted
#pragma warning (default: 5029) // (level 4) nonstandard extension used : alignment attributes in C++ apply to variables, data members and tag types only
#pragma warning (default: 5031) // (level 4) #pragma warning(pop) : likely mismatch, popping warning state pushed in different file
#pragma warning (default: 5032) // (level 4) detected #pragma warning(push) with no corresponding #pragma warning(pop)
#pragma warning (default: 5039) // (level 4) 'function' : pointer or reference to potentially throwing function passed to extern C function under - EHc.Undefined behavior may occur if this function throws an exception.
#pragma warning (default: 5038) // (level 4) data member 'member1' will be initialized after data member 'member2'
#pragma warning (default: 4355) // 'this' : used in base member initializer list
#pragma warning (default: 4746) // volatile access of 'expression' is subject to / volatile : <iso | ms> setting; consider using __iso_volatile_load / store intrinsic functions
#pragma warning (default: 4962) // 'function': profile - guided optimizations disabled because optimizations caused profile data to become inconsistent
#pragma warning (default: 5022) // 'type' : multiple move constructors specified
#pragma warning (default: 5023) // 'type' : multiple move assignment operators specified
#pragma warning (default: 5034) // use of intrinsic 'intrinsic' causes function function to be compiled as guest code
#pragma warning (default: 5035) // use of feature 'feature' causes function function to be compiled as guest code

// <tas="Following default warnings count many thousands. For later evaluation separately"/>
#pragma warning(disable : 5026) // (level 1 and level 4) 'type': move constructor was implicitly defined as deleted
#pragma warning (disable: 5027) // (level 1 and level 4) 'type' : move assignment operator was implicitly defined as deleted
#pragma warning (disable: 5031) // #pragma warning(pop) : likely mismatch, popping warning state pushed in different file

// <tas="Following warnings occur many times in Oda libraries"/>
#pragma warning(disable : 4619) // (level 3) there is no warning number 'number'

// <tas="Following off by default warnings (defaulted above) occur many times in Oda libraries. For later evaluation separately"/>
#pragma warning(disable : 4514) // (level 4) 'function' : unreferenced inline function has been removed
#pragma warning (disable: 4625) // (level 4) 'derived class' : copy constructor could not be generated because a base class copy constructor is inaccessible
#pragma warning (disable: 4626) // (level 4) 'derived class' : assignment operator could not be generated because a base class assignment operator is inaccessible
#pragma warning (disable: 4800) // (level 4) Implicit conversion from 'type' to bool.Possible information loss
#pragma warning (disable: 4820) // (level 4) 'bytes' bytes padding added after construct 'member_name'


#pragma once

#include "memcached/types.h"
#include "slabs.h"

#include <gsl/gsl-lite.h>
#include <atomic>
#include <cstddef>
#include <cstring>

/*
 * You should not try to aquire any of the item locks before calling these
 * functions.
 */
typedef struct _hash_item {
    struct _hash_item* next;
    struct _hash_item* prev;
    struct _hash_item* h_next; /* hash chain next */
    /**
     * The unique identifier for this item (it is guaranteed to be unique
     * per key, which means that a two different version of a document
     * cannot have the same CAS value (This is not true after a server
     * restart given that default_bucket is an in-memory bucket).
     */
    uint64_t cas;

    /** least recent access */
    rel_time_t time;

    /** When the item will expire (relative to process startup) */
    rel_time_t exptime;

    /**
     * When the current lock for the object expire. If locktime < "current
     * time" the item isn't locked anymore (timed out). If locktime >=
     * "current time" the object is locked.
     */
    rel_time_t locktime;

    /** The total size of the data (in bytes) */
    uint32_t nbytes;

    /** Flags associated with the item (in network byte order) */
    uint32_t flags;

    /**
     * The number of entities holding a reference to this item object (we
     * operate in a copy'n'write context so it is always safe for all of
     * our clients to share an existing object, but we need the refcount
     * so that we know when we can release the object.
     */
    uint16_t refcount;

    /** Intermal flags used by the engine.*/
    std::atomic<uint8_t> iflag;

    /** which slab class we're in */
    uint8_t slabs_clsid;

    /** to identify the type of the data */
    uint8_t datatype;

    // There is 3 spare bytes due to alignment
} hash_item;

/*
    The structure of the key we hash with.

    This is a combination of the bucket index and the client's key.

    To respect the memcached protocol we support keys > 250, even
    though the current frontend doesn't.

    Keys upto 128 bytes long will be carried wholly on the stack,
    larger keys go on the heap.
*/
typedef struct _hash_key_sized {
    bucket_id_t bucket_index;
    uint8_t client_key[128];
} hash_key_sized;

typedef struct _hash_key_data {
    bucket_id_t bucket_index;
    uint8_t client_key[1];
} hash_key_data;

typedef struct _hash_key_header {
    uint16_t len; /* length of the hash key (bucket_index+client) */
    hash_key_data* full_key; /* points to hash_key::key_storage or a malloc blob*/
} hash_key_header;

typedef struct _hash_key {
    hash_key_header header;
    hash_key_sized key_storage;
} hash_key;

static inline uint8_t* hash_key_get_key(const hash_key* key) {
    return (uint8_t*)key->header.full_key;
}

static inline bucket_id_t hash_key_get_bucket_index(const hash_key* key) {
    return key->header.full_key->bucket_index;
}

static inline void hash_key_set_bucket_index(hash_key* key,
                                             bucket_id_t bucket_index) {
    key->header.full_key->bucket_index = bucket_index;
}

static inline uint16_t hash_key_get_key_len(const hash_key* key) {
    return key->header.len;
}

static inline void hash_key_set_len(hash_key* key, uint16_t len) {
    key->header.len = len;
}

static inline uint8_t* hash_key_get_client_key(const hash_key* key) {
    return key->header.full_key->client_key;
}

static inline uint16_t hash_key_get_client_key_len(const hash_key* key) {
    return hash_key_get_key_len(key) -
           gsl::narrow<uint16_t>(sizeof(key->header.full_key->bucket_index));
}

static inline void hash_key_set_client_key(hash_key* key,
                                           const void* client_key,
                                           const size_t client_key_len) {
    memcpy(key->header.full_key->client_key, client_key, client_key_len);
}

/*
 * return the bytes needed to store the hash_key structure
 * in a single contiguous allocation.
 */
static inline size_t hash_key_get_alloc_size(const hash_key* key) {
    return offsetof(hash_key, key_storage) + hash_key_get_key_len(key);
}

typedef struct {
    unsigned int evicted;
    unsigned int evicted_nonzero;
    rel_time_t evicted_time;
    unsigned int outofmemory;
    unsigned int tailrepairs;
    unsigned int reclaimed;
} itemstats_t;

struct items {
   hash_item *heads[POWER_LARGEST];
   hash_item *tails[POWER_LARGEST];
   itemstats_t itemstats[POWER_LARGEST];
   unsigned int sizes[POWER_LARGEST];
   /*
    * serialise access to the items data
   */
   std::mutex lock;
};

/**
 * Allocate and initialize a new item structure
 * @param engine handle to the storage engine
 * @param key the key for the new item
 * @param nkey the number of bytes in the key
 * @param flags the flags in the new item
 * @param exptime when the object should expire
 * @param nbytes the number of bytes in the body for the item
 * @return a pointer to an item on success NULL otherwise
 */
hash_item *item_alloc(struct default_engine *engine,
                      const void *key, const size_t nkey, int flags,
                      rel_time_t exptime, int nbytes, const void *cookie,
                      uint8_t datatype);

/**
 * Get an item from the cache
 *
 * @param engine handle to the storage engine
 * @param cookie connection cookie
 * @param key the key for the item to get
 * @param nkey the number of bytes in the key
 * @param state Only return documents in this state
 * @return pointer to the item if it exists or NULL otherwise
 */
hash_item* item_get(struct default_engine* engine,
                    const void* cookie,
                    const void* key,
                    const size_t nkey,
                    const DocStateFilter state);

/**
 * Get an item from the cache using a hash_key
 *
 * @param engine handle to the storage engine
 * @param cookie connection cookie
 * @param key to lookup
 * @param state Only return documents in this state
 * @return pointer to the item if it exists or NULL otherwise
 */
hash_item* item_get(struct default_engine* engine,
                    const void* cookie,
                    const hash_key& key,
                    const DocStateFilter state);

/**
 * Get an item from the cache and acquire the lock.
 *
 * @param engine handle to the storage engine
 * @param cookie connection cookie
 * @param where to return the item (if found)
 * @param key the key for the item to get
 * @param nkey the number of bytes in the key
 * @param locktime when the item expire
 * @return ENGINE_SUCCESS for success
 */
ENGINE_ERROR_CODE item_get_locked(struct default_engine* engine,
                                  const void* cookie,
                                  hash_item** it,
                                  const void* key,
                                  const size_t nkey,
                                  rel_time_t locktime);

/**
 * Get and touch an item
 *
 * @param engine handle to the storage engine
 * @param cookie connection cookie
 * @param where to return the item (if found)
 * @param key the key for the item to get
 * @param nkey the number of bytes in the key
 * @param exptime The new expiry time
 * @return ENGINE_SUCCESS for success
 */
ENGINE_ERROR_CODE item_get_and_touch(struct default_engine* engine,
                                     const void* cookie,
                                     hash_item** it,
                                     const void* key,
                                     const size_t nkey,
                                     rel_time_t exptime);

/**
 * Unlock an item in the cache
 *
 * @param engine handle to the storage engine
 * @param cookie connection cookie
 * @param key the key for the item to unlock
 * @param nkey the number of bytes in the key
 * @param cas value for the locked value
 * @return ENGINE_SUCCESS for success
 */
ENGINE_ERROR_CODE item_unlock(struct default_engine* engine,
                              const void* cookie,
                              const void* key,
                              const size_t nkey,
                              uint64_t cas);

/**
 * Reset the item statistics
 * @param engine handle to the storage engine
 */
void item_stats_reset(struct default_engine *engine);

/**
 * Get item statitistics
 * @param engine handle to the storage engine
 * @param add_stat callback provided by the core used to
 *                 push statistics into the response
 * @param cookie cookie provided by the core to identify the client
 */
void item_stats(struct default_engine* engine,
                const AddStatFn& add_stat,
                const void* cookie);

/**
 * Get detaild item statitistics
 * @param engine handle to the storage engine
 * @param add_stat callback provided by the core used to
 *                 push statistics into the response
 * @param cookie cookie provided by the core to identify the client
 */
void item_stats_sizes(struct default_engine* engine,
                      const AddStatFn& add_stat,
                      const void* cookie);

/**
 * Flush expired items from the cache
 * @param engine handle to the storage engine
 */
void  item_flush_expired(struct default_engine *engine);

/**
 * Release our reference to the current item
 * @param engine handle to the storage engine
 * @param it the item to release
 */
void item_release(struct default_engine *engine, hash_item *it);

/**
 * Unlink the item from the hash table (make it inaccessible)
 * @param engine handle to the storage engine
 * @param it the item to unlink
 */
void item_unlink(struct default_engine *engine, hash_item *it);

/**
 * Unlink the item from the hash table (make it inaccessible),
 * but only if the CAS value in the item is the same as the
 * one in the hash table (two different connections may operate
 * on the same objects, so the cas value for the value in the
 * hashtable may be different than the items value. We need
 * to have exclusive access to the hashtable to do the actual
 * unlink)
 *
 * @param engine handle to the storage engine
 * @param it the item to unlink
 */
ENGINE_ERROR_CODE safe_item_unlink(struct default_engine *engine,
                                   hash_item *it);

/**
 * Store an item in the cache
 * @param engine handle to the storage engine
 * @param item the item to store
 * @param cas the cas value (OUT)
 * @param operation what kind of store operation is this (ADD/SET etc)
 * @param document_state the state of the document to store
 * @return ENGINE_SUCCESS on success
 *
 * @todo should we refactor this into hash_item ** and remove the cas
 *       there so that we can get it from the item instead?
 */
ENGINE_ERROR_CODE store_item(struct default_engine *engine,
                             hash_item *item,
                             uint64_t *cas,
                             ENGINE_STORE_OPERATION operation,
                             const void *cookie,
                             const DocumentState document_state);

/**
 * Run a single scrub loop for the engine.
 * @param engine handle to the storage engine
 */
void item_scrubber_main(struct default_engine *engine);

/**
 * Start the item scrubber for the engine
 * @param engine handle to the storage engine
 * @return true if the scrubber has been invoked
 */
bool item_start_scrub(struct default_engine *engine);


//
//  Author  : github.com/luncliff (luncliff@gmail.com)
//  License : CC BY 4.0
//
//  Note
//      Async I/O operation support for socket
//
#pragma once
// clang-format off
#if defined(FORCE_STATIC_LINK)
#   define _INTERFACE_
#   define _HIDDEN_
#elif defined(_MSC_VER) // MSVC or clang-cl
#   define _HIDDEN_
#   ifdef _WINDLL
#       define _INTERFACE_ __declspec(dllexport)
#   else
#       define _INTERFACE_ __declspec(dllimport)
#   endif
#elif defined(__GNUC__) || defined(__clang__)
#   define _INTERFACE_ __attribute__((visibility("default")))
#   define _HIDDEN_ __attribute__((visibility("hidden")))
#else
#   error "unexpected linking configuration"
#endif
// clang-format on

#ifndef COROUTINE_NET_IO_H
#define COROUTINE_NET_IO_H

#include <chrono>
#include <gsl/gsl>
#include <coroutine/yield.hpp>

#if __has_include(<WinSock2.h>) // use winsock
#include <WS2tcpip.h>
#include <WinSock2.h>
#include <ws2def.h>

using io_control_block = OVERLAPPED;

static constexpr bool is_winsock = true;
static constexpr bool is_netinet = false;

#elif __has_include(<netinet/in.h>) // use netinet
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <unistd.h>

// Follow the definition of Windows `OVERLAPPED`
struct io_control_block {
    uint64_t internal;      // uint32_t errc, int32_t flag
    uint64_t internal_high; // int64_t len, socklen_t addrlen
    union {
        struct {
            int32_t offset;
            int32_t offset_high;
        };
        void* ptr; // sockaddr* addr;
    };
    int64_t handle; // int64_t sd;
};

static constexpr bool is_winsock = false;
static constexpr bool is_netinet = true;

#endif // winsock || netinet

namespace coro {
using namespace std;
using namespace std::experimental;

//  1 I/O task == 1 coroutine function
using io_task_t = coroutine_handle<void>;

//  This is simply a view to storage. Be aware that it doesn't have ownership
using io_buffer_t = gsl::span<std::byte>;
static_assert(sizeof(io_buffer_t) <= sizeof(void*) * 2);

//  A struct to describe "1 I/O request" to system API
class io_work_t : public io_control_block {
  public:
    io_task_t task{};
    io_buffer_t buffer{};

  protected:
    _INTERFACE_ bool ready() const noexcept;

  public:
    // Multiple retrieving won't be a matter
    _INTERFACE_ uint32_t error() const noexcept;
};
static_assert(sizeof(io_work_t) <= 56);

//  Type to perform `sendto` I/O request
class io_send_to final : public io_work_t {
  private:
    // This function must be used through `co_await`
    _INTERFACE_ void suspend(io_task_t t) noexcept(false);
    // This function must be used through `co_await`
    // Unlike inherited `error` function, multiple invoke of this will
    // lead to malfunction.
    _INTERFACE_ int64_t resume() noexcept;

  public:
    bool await_ready() const noexcept {
        return this->ready();
    }
    void await_suspend(io_task_t t) noexcept(false) {
        return this->suspend(t);
    }
    auto await_resume() noexcept {
        return this->resume();
    }
};
static_assert(sizeof(io_send_to) == sizeof(io_work_t));

//  Type to perform `recvfrom` I/O request
class io_recv_from final : public io_work_t {
  private:
    // This function must be used through `co_await`
    _INTERFACE_ void suspend(io_task_t t) noexcept(false);
    // This function must be used through `co_await`
    // Unlike inherited `error` function, multiple invoke of this will
    // lead to malfunction.
    _INTERFACE_ int64_t resume() noexcept;

  public:
    bool await_ready() const noexcept {
        return this->ready();
    }
    void await_suspend(io_task_t t) noexcept(false) {
        return this->suspend(t);
    }
    auto await_resume() noexcept {
        return this->resume();
    }
};
static_assert(sizeof(io_recv_from) == sizeof(io_work_t));

//  Type to perform `send` I/O request
class io_send final : public io_work_t {
  private:
    // This function must be used through `co_await`
    _INTERFACE_ void suspend(io_task_t t) noexcept(false);
    // This function must be used through `co_await`
    // Unlike inherited `error` function, multiple invoke of this will
    // lead to malfunction.
    _INTERFACE_ int64_t resume() noexcept;

  public:
    bool await_ready() const noexcept {
        return this->ready();
    }
    void await_suspend(io_task_t t) noexcept(false) {
        return this->suspend(t);
    }
    auto await_resume() noexcept {
        return this->resume();
    }
};
static_assert(sizeof(io_send) == sizeof(io_work_t));

//  Type to perform `recv` I/O request
class io_recv final : public io_work_t {
  private:
    // This function must be used through `co_await`
    _INTERFACE_ void suspend(io_task_t t) noexcept(false);
    // This function must be used through `co_await`
    // Unlike inherited `error` function, multiple invoke of this will
    // lead to malfunction.
    _INTERFACE_ int64_t resume() noexcept;

  public:
    bool await_ready() const noexcept {
        return this->ready();
    }
    void await_suspend(io_task_t t) noexcept(false) {
        return this->suspend(t);
    }
    auto await_resume() noexcept {
        return this->resume();
    }
};
static_assert(sizeof(io_recv) == sizeof(io_work_t));

//  Constructs awaitable `io_send_to` object with the given parameters
[[nodiscard]] _INTERFACE_                                     //
    auto                                                      //
    send_to(uint64_t sd, const sockaddr_in& remote,           //
            io_buffer_t buf, io_work_t& work) noexcept(false) //
    -> io_send_to&;

//  Constructs awaitable `io_send_to` object with the given parameters
[[nodiscard]] _INTERFACE_                                             //
    auto                                                              //
    send_to(uint64_t sd, const sockaddr_in6& remote, io_buffer_t buf, //
            io_work_t& work) noexcept(false)                          //
    -> io_send_to&;

//  Constructs awaitable `io_recv_from` object with the given parameters
[[nodiscard]] _INTERFACE_                                        //
    auto                                                         //
    recv_from(uint64_t sd, sockaddr_in& remote, io_buffer_t buf, //
              io_work_t& work) noexcept(false)                   //
    -> io_recv_from&;

//  Constructs awaitable `io_recv_from` object with the given parameters
[[nodiscard]] _INTERFACE_                                         //
    auto                                                          //
    recv_from(uint64_t sd, sockaddr_in6& remote, io_buffer_t buf, //
              io_work_t& work) noexcept(false)                    //
    -> io_recv_from&;

//  Constructs awaitable `io_send` object with the given parameters
[[nodiscard]] _INTERFACE_                                    //
    auto                                                     //
    send_stream(uint64_t sd, io_buffer_t buf, uint32_t flag, //
                io_work_t& work) noexcept(false)             //
    -> io_send&;

//  Constructs awaitable `io_recv` object with the given parameters
[[nodiscard]] _INTERFACE_                                    //
    auto                                                     //
    recv_stream(uint64_t sd, io_buffer_t buf, uint32_t flag, //
                io_work_t& work) noexcept(false)             //
    -> io_recv&;

//  This function is for non-Windows platform.
//  Over Windows api, it always yields **nothing**.
//
//  Its caller must continue the loop without break
//  so there is no leak of the I/O events
//
//  Also, the library doesn't guarantee all coroutines(i/o tasks) will be
//  fetched at once. Therefore it is strongly recommended for user to have
//  another method to detect that watching I/O coroutines are returned.
_INTERFACE_
void wait_net_tasks(enumerable<io_task_t>& tasks,
                    chrono::nanoseconds timeout) noexcept(false);

inline auto wait_net_tasks(chrono::nanoseconds timeout) noexcept(false) {
    enumerable<io_task_t> tasks{};
    wait_net_tasks(tasks, timeout);
    return tasks;
}

//
//  Name resolution utilities
//

using zstring_host = gsl::zstring<NI_MAXHOST>;
using zstring_serv = gsl::zstring<NI_MAXSERV>;
using czstring_host = gsl::czstring<NI_MAXHOST>;
using czstring_serv = gsl::czstring<NI_MAXSERV>;

//  Combination of `getaddrinfo` functions
//  If there is an error, the enumerable is untouched
_INTERFACE_
int32_t resolve(enumerable<sockaddr>& g, const addrinfo& hint, //
                czstring_host name, czstring_serv serv) noexcept;

// construct system_error using `gai_strerror` function
_INTERFACE_
auto resolve_error(int32_t ec) noexcept -> std::system_error;

inline auto resolve(const addrinfo& hint, //
                    czstring_host name, czstring_serv serv) noexcept(false)
    -> enumerable<sockaddr> {
    enumerable<sockaddr> g{};
    if (const auto ec = resolve(g, hint, name, serv)) {
        throw resolve_error(ec);
    }
    return g;
}

//  Thin wrapper of `getnameinfo`. Parameter 'serv' can be nullptr.
_INTERFACE_
int32_t get_name(const sockaddr_in& addr, zstring_host name, zstring_serv serv,
                 int32_t flags = NI_NUMERICHOST | NI_NUMERICSERV) noexcept;
_INTERFACE_
int32_t get_name(const sockaddr_in6& addr, zstring_host name, zstring_serv serv,
                 int32_t flags = NI_NUMERICHOST | NI_NUMERICSERV) noexcept;

} // namespace coro

#endif // COROUTINE_NET_IO_H


/* -----------------------------------------------------------------------------
 * Copyright 2021 Jonathan Haigh
 * SPDX-License-Identifier: MIT
 * ---------------------------------------------------------------------------*/

#ifndef SQ_INCLUDE_GUARD_parser_FilterSpec_h_
#define SQ_INCLUDE_GUARD_parser_FilterSpec_h_

#include "core/Primitive.h"
#include "core/typeutil.h"

#include <compare>
#include <gsl/gsl>
#include <iosfwd>
#include <optional>
#include <variant>

namespace sq::parser {

/**
 * Represents the lack of a filter specification for a field access.
 */
struct NoFilterSpec {
  SQ_ND auto operator<=>(const NoFilterSpec &) const = default;
};
std::ostream &operator<<(std::ostream &os, NoFilterSpec nlfs);

/**
 * Represents access of an indexed element in a list of results for a field
 * access.
 */
struct ElementAccessSpec {
  gsl::index index_;
  SQ_ND auto operator<=>(const ElementAccessSpec &) const = default;
};
std::ostream &operator<<(std::ostream &os, ElementAccessSpec leas);

/**
 * Represents a Python-style slice of a list of results for a field access.
 */
struct SliceSpec {
  std::optional<gsl::index> start_;
  std::optional<gsl::index> stop_;
  std::optional<gsl::index> step_;
  SQ_ND auto operator<=>(const SliceSpec &) const = default;
};
std::ostream &operator<<(std::ostream &os, SliceSpec lss);

enum class ComparisonOperator {
  GreaterThanOrEqualTo,
  GreaterThan,
  LessThanOrEqualTo,
  LessThan,
  Equals
};

/**
 * Represents a comparison to determine whether to keep a field or not.
 */
struct ComparisonSpec {
  std::string member_;
  ComparisonOperator op_;
  Primitive value_;
  SQ_ND auto operator<=>(const ComparisonSpec &) const = default;
};

std::ostream &operator<<(std::ostream &os, const ComparisonOperator &op);
std::ostream &operator<<(std::ostream &os, const ComparisonSpec &cs);

using FilterSpec =
    std::variant<NoFilterSpec, ElementAccessSpec, SliceSpec, ComparisonSpec>;

} // namespace sq::parser

#endif // SQ_INCLUDE_GUARD_parser_FilterSpec_h_


#pragma once

#include <gsl/pointers>  // contains gsl::not_null

class Consultant;

class PaymentCalculator {
 public:
  double calculate() const { return {}; }

  void setConsultant(const Consultant &c) { consultant_ = &consultant_; }

  void setTaxPercentage(double tax) { taxPercentage_ = tax; }

 private:
  gsl::not_null<const Consultant *> consultant_;
  double taxPercentage_;
};


#pragma once

#include <gsl/span>

/**
* This header is mainly for shorthands when dealing with `gsl::span`s
* see the `gsl` or c++ core guidelines for more info on what a `gsl::span` is/does.
*/

namespace riner {

    template<class T, std::ptrdiff_t Extent = gsl::dynamic_extent>
    using span = gsl::span<T, Extent>;

    template<std::ptrdiff_t Extent = gsl::dynamic_extent>
    using ByteSpan = span<uint8_t, Extent>;

    template<std::ptrdiff_t Extent = gsl::dynamic_extent>
    using cByteSpan = span<const uint8_t, Extent>;
}