<commit_before>#pragma once
#include "includes.hpp"

#define TAGLIB_STATIC
#include <taglib/fileref.h>
#include <taglib/tag.h>
#include <taglib/tpropertymap.h>

class playlist : public Component, public FileDragAndDropTarget {
    struct playlistModel : public TableListBoxModel {
		StringArray entries;
        int getNumRows() override {
            return entries.size();
        }

		// This is overloaded from TableListBoxModel, and should fill in the background of the whole row
		void paintRowBackground(Graphics& g, int rowNumber, int /*width*/, int /*height*/, bool rowIsSelected) override {
			if (rowIsSelected)
				g.fillAll(Colours::lightblue);
			else if (rowNumber % 2)
				g.fillAll(Colour(0xffeeeeee));
		}

		// This is overloaded from TableListBoxModel, and must paint any cells that aren't using custom
		// components.
		void paintCell(Graphics& g, int rowNumber, int /*columnId*/,
						int width, int height, bool /*rowIsSelected*/) override {
			g.setColour(Colours::black);
			g.setFont(height * 0.7f);
			g.drawText(entries[rowNumber], 5, 0, width, height, Justification::centredLeft, true);
			g.setColour(Colours::black.withAlpha(0.2f));
			g.fillRect(width - 1, 0, 1, height);
		}
    };

    TableListBox box;
    playlistModel model;
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(playlist);

	// TODO: system codecs?
	bool isFileSupported(const String &fname) {
		return fname.endsWith(".mp3")
			|| fname.endsWith(".wav")
			|| fname.endsWith(".wma")
			|| fname.endsWith(".flac")
			|| fname.endsWith(".ogg")
			|| fname.endsWith(".ape");
	}

public:
    playlist() : box("playlist-box", nullptr) {
		setName("playlist");
		box.setModel(&model);
		box.setMultipleSelectionEnabled(true);
		addAndMakeVisible(box);

		box.getHeader().addColumn("album", 0, 200, 50, 1000, TableHeaderComponent::defaultFlags);
		box.getHeader().addColumn("artist", 0, 200, 50, 1000, TableHeaderComponent::defaultFlags);
		box.getHeader().addColumn("title", 0, 200, 50, 1000, TableHeaderComponent::defaultFlags);
		box.setMultipleSelectionEnabled (true);
	}

    void resized() override {
		box.setBounds(getLocalBounds().reduced(0));
	}

	bool isInterestedInFileDrag(const StringArray& /*files*/) override {
		return true;
	}

	void fileDragEnter(const StringArray& /*files*/, int /*x*/, int /*y*/) override {
		repaint();
	}

	void fileDragMove (const StringArray& /*files*/, int /*x*/, int /*y*/) override {}

	void fileDragExit (const StringArray& /*files*/) override {
		repaint();
	}

	void filesDropped (const StringArray& files, int /*x*/, int /*y*/) override {
		for (auto &f : files) {
			if (isFileSupported(f)) {
				//TagLib::FileRef file(f.toRawUTF8());
				//f = (file.tag()->album() + L" | " + file.tag()->artist() + L" | " + file.tag()->title()).toCString();
			}
		}
		model.entries.addArray(files);
		box.updateContent();
		repaint();
	}

	base::string getSelectedRowString() {
		return model.entries[box.getSelectedRow()].toStdString();
	}
};
<commit_msg>+ mem model change<commit_after>#pragma once
#include "includes.hpp"

#define TAGLIB_STATIC
#include <taglib/fileref.h>
#include <taglib/tag.h>
#include <taglib/tpropertymap.h>

class playlist : public Component, public FileDragAndDropTarget {
    struct playlistModel : public TableListBoxModel {
		base::string paths;
		std::vector<size_t> paths_i;

		void init() {
			paths.clear();
			paths_i.clear();
			paths_i.push_back(0);
		}

		void addItem(const String &path) {

			//TagLib::FileRef file(f.toRawUTF8());
			//f = (file.tag()->album() + L" | " + file.tag()->artist() + L" | " + file.tag()->title()).toCString();

			paths.append(path.toStdString());
			paths_i.push_back(paths.size());
		}

		base::string getItemPath(size_t index) {
			return base::string(paths.begin() + paths_i[index],
								paths.begin() + paths_i[index + 1]);
		}

		// GUI
        int getNumRows() override {
            return paths_i.size() - 1;
        }

		// This is overloaded from TableListBoxModel, and should fill in the background of the whole row
		void paintRowBackground(Graphics& g, int rowNumber, int /*width*/, int /*height*/, bool rowIsSelected) override {
			if (rowIsSelected)
				g.fillAll(Colours::lightblue);
			else if (rowNumber % 2)
				g.fillAll(Colour(0xffeeeeee));
		}

		// This is overloaded from TableListBoxModel, and must paint any cells that aren't using custom
		// components.
		void paintCell(Graphics& g, int rowNumber, int /*columnId*/,
						int width, int height, bool /*rowIsSelected*/) override {
			g.setColour(Colours::black);
			g.setFont(height * 0.7f);
			g.drawText(getItemPath(rowNumber), 5, 0, width, height, Justification::centredLeft, true);
			g.setColour(Colours::black.withAlpha(0.2f));
			g.fillRect(width - 1, 0, 1, height);
		}
    };

    TableListBox box;
    playlistModel model;
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(playlist);

	// TODO: system codecs?
	bool isFileSupported(const String &fname) {
		return fname.endsWith(".mp3")
			|| fname.endsWith(".wav")
			|| fname.endsWith(".wma")
			|| fname.endsWith(".flac")
			|| fname.endsWith(".ogg")
			|| fname.endsWith(".ape");
	}

public:
    playlist() : box("playlist-box", nullptr) {
		model.init();
		setName("playlist");
		box.setModel(&model);
		box.setMultipleSelectionEnabled(true);
		addAndMakeVisible(box);

		box.getHeader().addColumn("album", 0, 200, 50, 1000, TableHeaderComponent::defaultFlags);
		box.getHeader().addColumn("artist", 0, 200, 50, 1000, TableHeaderComponent::defaultFlags);
		box.getHeader().addColumn("title", 0, 200, 50, 1000, TableHeaderComponent::defaultFlags);
		box.setMultipleSelectionEnabled(true);
	}

    void resized() override {
		box.setBounds(getLocalBounds().reduced(0));
	}

	bool isInterestedInFileDrag(const StringArray& /*files*/) override {
		return true;
	}

	void fileDragEnter(const StringArray& /*files*/, int /*x*/, int /*y*/) override {
		repaint();
	}

	void fileDragMove (const StringArray& /*files*/, int /*x*/, int /*y*/) override {}

	void fileDragExit (const StringArray& /*files*/) override {
		repaint();
	}

	void filesDropped (const StringArray& files, int /*x*/, int /*y*/) override {
		for (auto &f : files) {
			if (isFileSupported(f)) {
				model.addItem(f);
			}
		}
		box.updateContent();
		repaint();
	}

	base::string getSelectedRowString() {
		return model.getItemPath(box.getSelectedRow());
	}
};
<|endoftext|>


<commit_before>#ifndef BULL_CORE_MEMORY_RANGECHECK_HPP
#define BULL_CORE_MEMORY_RANGECHECK_HPP

#include <Bull/Core/Configuration/Integer.hpp>
#include <Bull/Core/Export.hpp>

namespace Bull
{
    class BULL_CORE_API RangeCheck
    {
    public:

        /*! \brief Constructor
         *
         * \param max The max value of the index
         *
         */
        explicit RangeCheck(std::size_t max);

        /*! \brief Constructor
         *
         * \param index The index
         * \param max   The max value of the index
         *
         */
        RangeCheck(std::size_t index, std::size_t max);

        /*! \brief Perform range check
         *
         * \param index The index to test
         *
         * \return This
         *
         */
        RangeCheck& apply(std::size_t index);

    private:

        std::size_t m_max;
    };
}

#endif // BULL_CORE_MEMORY_RANGECHECK_HPP
<commit_msg>[Core/RangeCheck] Remove useless header<commit_after>#ifndef BULL_CORE_MEMORY_RANGECHECK_HPP
#define BULL_CORE_MEMORY_RANGECHECK_HPP

#include <Bull/Core/Export.hpp>

namespace Bull
{
    class BULL_CORE_API RangeCheck
    {
    public:

        /*! \brief Constructor
         *
         * \param max The max value of the index
         *
         */
        explicit RangeCheck(std::size_t max);

        /*! \brief Constructor
         *
         * \param index The index
         * \param max   The max value of the index
         *
         */
        RangeCheck(std::size_t index, std::size_t max);

        /*! \brief Perform range check
         *
         * \param index The index to test
         *
         * \return This
         *
         */
        RangeCheck& apply(std::size_t index);

    private:

        std::size_t m_max;
    };
}

#endif // BULL_CORE_MEMORY_RANGECHECK_HPP
<|endoftext|>


<commit_before>#pragma once

#include <eosio/chain/wasm_interface.hpp>
#include <eosio/chain/webassembly/wavm.hpp>
#include <eosio/chain/webassembly/binaryen.hpp>
#include <eosio/chain/webassembly/runtime_interface.hpp>
#include <eosio/chain/wasm_eosio_injection.hpp>

#include "IR/Module.h"
#include "Runtime/Intrinsics.h"
#include "Platform/Platform.h"
#include "WAST/WAST.h"
#include "IR/Validate.h"

using namespace fc;
using namespace eosio::chain::webassembly;
using namespace IR;
using namespace Runtime;

namespace eosio { namespace chain {

   struct wasm_interface_impl {
      wasm_interface_impl(wasm_interface::vm_type vm) {
         if(vm == wasm_interface::vm_type::wavm)
            runtime_interface = std::make_unique<webassembly::wavm::wavm_runtime>();
         else if(vm == wasm_interface::vm_type::binaryen)
            runtime_interface = std::make_unique<webassembly::binaryen::binaryen_runtime>();
         else
            FC_THROW("wasm_interface_impl fall through");
      }

      std::vector<uint8_t> parse_initial_memory(const shared_vector<char>& code) {
         std::vector<uint8_t> mem_image;
         Module module;
         Serialization::MemoryInputStream stream((const U8*)code.data(), code.size());
         WASM::serialize(stream, module);

         for(const DataSegment& data_segment : module.dataSegments) {
            FC_ASSERT(data_segment.baseOffset.type == InitializerExpression::Type::i32_const);
            FC_ASSERT(module.memories.defs.size());
            const U32 base_offset = data_segment.baseOffset.i32;
            const Uptr memory_size = (module.memories.defs[0].type.size.min << IR::numBytesPerPageLog2);
            if(base_offset >= memory_size || base_offset + data_segment.data.size() > memory_size)
               FC_THROW_EXCEPTION(wasm_execution_error, "WASM data segment outside of valid memory range");
            if(base_offset + data_segment.data.size() > mem_image.size())
               mem_image.resize(base_offset + data_segment.data.size(), 0x00);
            memcpy(mem_image.data() + base_offset, data_segment.data.data(), data_segment.data.size());
         }

         return mem_image;
      }

      std::unique_ptr<wasm_instantiated_module_interface>& get_instantiated_module(const digest_type& code_id, const shared_vector<char>& code) {
         auto it = instantiation_cache.find(code_id);
         if(it == instantiation_cache.end()) {
            IR::Module module;
            Serialization::MemoryInputStream stream((const U8 *)code.data(), code.size());
            WASM::serialize(stream, module);

            wasm_injections::wasm_binary_injection injector(module);
            injector.inject();

            Serialization::ArrayOutputStream outstream;
            WASM::serialize(outstream, module);
            std::vector<U8> bytes = outstream.getBytes();

            it = instantiation_cache.emplace(code_id, runtime_interface->instantiate_module(code.data(), code.size(), parse_initial_memory(code))).first;
         }
         return it->second;
      }

      std::unique_ptr<wasm_runtime_interface> runtime_interface;
      map<digest_type, std::unique_ptr<wasm_instantiated_module_interface>> instantiation_cache;
   };

#define _REGISTER_INTRINSIC_EXPLICIT(CLS, METHOD, WASM_SIG, NAME, SIG)\
   _REGISTER_WAVM_INTRINSIC(CLS, METHOD, WASM_SIG, NAME, SIG)\
   _REGISTER_BINARYEN_INTRINSIC(CLS, METHOD, WASM_SIG, NAME, SIG)

#define _REGISTER_INTRINSIC4(CLS, METHOD, WASM_SIG, NAME, SIG)\
   _REGISTER_INTRINSIC_EXPLICIT(CLS, METHOD, WASM_SIG, NAME, SIG )

#define _REGISTER_INTRINSIC3(CLS, METHOD, WASM_SIG, NAME)\
   _REGISTER_INTRINSIC_EXPLICIT(CLS, METHOD, WASM_SIG, NAME, decltype(&CLS::METHOD) )

#define _REGISTER_INTRINSIC2(CLS, METHOD, WASM_SIG)\
   _REGISTER_INTRINSIC_EXPLICIT(CLS, METHOD, WASM_SIG, BOOST_PP_STRINGIZE(METHOD), decltype(&CLS::METHOD) )

#define _REGISTER_INTRINSIC1(CLS, METHOD)\
   static_assert(false, "Cannot register " BOOST_PP_STRINGIZE(CLS) ":" BOOST_PP_STRINGIZE(METHOD) " without a signature");

#define _REGISTER_INTRINSIC0(CLS, METHOD)\
   static_assert(false, "Cannot register " BOOST_PP_STRINGIZE(CLS) ":<unknown> without a method name and signature");

#define _UNWRAP_SEQ(...) __VA_ARGS__

#define _EXPAND_ARGS(CLS, INFO)\
   ( CLS, _UNWRAP_SEQ INFO )

#define _REGISTER_INTRINSIC(R, CLS, INFO)\
   BOOST_PP_CAT(BOOST_PP_OVERLOAD(_REGISTER_INTRINSIC, _UNWRAP_SEQ INFO) _EXPAND_ARGS(CLS, INFO), BOOST_PP_EMPTY())

#define REGISTER_INTRINSICS(CLS, MEMBERS)\
   BOOST_PP_SEQ_FOR_EACH(_REGISTER_INTRINSIC, CLS, _WRAPPED_SEQ(MEMBERS))

} } // eosio::chain
<commit_msg>Make sure to actually pass the injected wasm through to the new runtime objects<commit_after>#pragma once

#include <eosio/chain/wasm_interface.hpp>
#include <eosio/chain/webassembly/wavm.hpp>
#include <eosio/chain/webassembly/binaryen.hpp>
#include <eosio/chain/webassembly/runtime_interface.hpp>
#include <eosio/chain/wasm_eosio_injection.hpp>

#include "IR/Module.h"
#include "Runtime/Intrinsics.h"
#include "Platform/Platform.h"
#include "WAST/WAST.h"
#include "IR/Validate.h"

using namespace fc;
using namespace eosio::chain::webassembly;
using namespace IR;
using namespace Runtime;

namespace eosio { namespace chain {

   struct wasm_interface_impl {
      wasm_interface_impl(wasm_interface::vm_type vm) {
         if(vm == wasm_interface::vm_type::wavm)
            runtime_interface = std::make_unique<webassembly::wavm::wavm_runtime>();
         else if(vm == wasm_interface::vm_type::binaryen)
            runtime_interface = std::make_unique<webassembly::binaryen::binaryen_runtime>();
         else
            FC_THROW("wasm_interface_impl fall through");
      }

      std::vector<uint8_t> parse_initial_memory(const Module& module) {
         std::vector<uint8_t> mem_image;

         for(const DataSegment& data_segment : module.dataSegments) {
            FC_ASSERT(data_segment.baseOffset.type == InitializerExpression::Type::i32_const);
            FC_ASSERT(module.memories.defs.size());
            const U32 base_offset = data_segment.baseOffset.i32;
            const Uptr memory_size = (module.memories.defs[0].type.size.min << IR::numBytesPerPageLog2);
            if(base_offset >= memory_size || base_offset + data_segment.data.size() > memory_size)
               FC_THROW_EXCEPTION(wasm_execution_error, "WASM data segment outside of valid memory range");
            if(base_offset + data_segment.data.size() > mem_image.size())
               mem_image.resize(base_offset + data_segment.data.size(), 0x00);
            memcpy(mem_image.data() + base_offset, data_segment.data.data(), data_segment.data.size());
         }

         return mem_image;
      }

      std::unique_ptr<wasm_instantiated_module_interface>& get_instantiated_module(const digest_type& code_id, const shared_vector<char>& code) {
         auto it = instantiation_cache.find(code_id);
         if(it == instantiation_cache.end()) {
            IR::Module module;
            Serialization::MemoryInputStream stream((const U8 *)code.data(), code.size());
            WASM::serialize(stream, module);

            wasm_injections::wasm_binary_injection injector(module);
            injector.inject();

            Serialization::ArrayOutputStream outstream;
            WASM::serialize(outstream, module);
            std::vector<U8> bytes = outstream.getBytes();

            it = instantiation_cache.emplace(code_id, runtime_interface->instantiate_module((const char*)bytes.data(), bytes.size(), parse_initial_memory(module))).first;
         }
         return it->second;
      }

      std::unique_ptr<wasm_runtime_interface> runtime_interface;
      map<digest_type, std::unique_ptr<wasm_instantiated_module_interface>> instantiation_cache;
   };

#define _REGISTER_INTRINSIC_EXPLICIT(CLS, METHOD, WASM_SIG, NAME, SIG)\
   _REGISTER_WAVM_INTRINSIC(CLS, METHOD, WASM_SIG, NAME, SIG)\
   _REGISTER_BINARYEN_INTRINSIC(CLS, METHOD, WASM_SIG, NAME, SIG)

#define _REGISTER_INTRINSIC4(CLS, METHOD, WASM_SIG, NAME, SIG)\
   _REGISTER_INTRINSIC_EXPLICIT(CLS, METHOD, WASM_SIG, NAME, SIG )

#define _REGISTER_INTRINSIC3(CLS, METHOD, WASM_SIG, NAME)\
   _REGISTER_INTRINSIC_EXPLICIT(CLS, METHOD, WASM_SIG, NAME, decltype(&CLS::METHOD) )

#define _REGISTER_INTRINSIC2(CLS, METHOD, WASM_SIG)\
   _REGISTER_INTRINSIC_EXPLICIT(CLS, METHOD, WASM_SIG, BOOST_PP_STRINGIZE(METHOD), decltype(&CLS::METHOD) )

#define _REGISTER_INTRINSIC1(CLS, METHOD)\
   static_assert(false, "Cannot register " BOOST_PP_STRINGIZE(CLS) ":" BOOST_PP_STRINGIZE(METHOD) " without a signature");

#define _REGISTER_INTRINSIC0(CLS, METHOD)\
   static_assert(false, "Cannot register " BOOST_PP_STRINGIZE(CLS) ":<unknown> without a method name and signature");

#define _UNWRAP_SEQ(...) __VA_ARGS__

#define _EXPAND_ARGS(CLS, INFO)\
   ( CLS, _UNWRAP_SEQ INFO )

#define _REGISTER_INTRINSIC(R, CLS, INFO)\
   BOOST_PP_CAT(BOOST_PP_OVERLOAD(_REGISTER_INTRINSIC, _UNWRAP_SEQ INFO) _EXPAND_ARGS(CLS, INFO), BOOST_PP_EMPTY())

#define REGISTER_INTRINSICS(CLS, MEMBERS)\
   BOOST_PP_SEQ_FOR_EACH(_REGISTER_INTRINSIC, CLS, _WRAPPED_SEQ(MEMBERS))

} } // eosio::chain
<|endoftext|>


<commit_before>// Copyright (c) 2013-2020 mogemimi. Distributed under the MIT license.

#pragma once

#include "Pomdog/Basic/Export.hpp"
#include "Pomdog/Content/AssetBuilders/Builder.hpp"
#include "Pomdog/Content/AssetLoaders/AssetLoader.hpp"
#include "Pomdog/Content/AssetLoaders/AudioClipLoader.hpp"
#include "Pomdog/Content/AssetLoaders/Texture2DLoader.hpp"
#include "Pomdog/Utility/Assert.hpp"
#include "Pomdog/Utility/Errors.hpp"
#include "Pomdog/Utility/PathHelper.hpp"
#include <any>
#include <memory>
#include <string>
#include <tuple>
#include <typeindex>
#include <typeinfo>
#include <unordered_map>
#include <utility>

namespace Pomdog {

class AudioEngine;
class GraphicsDevice;

class POMDOG_EXPORT AssetManager final {
public:
    AssetManager(
        const std::string& contentDirectory,
        const std::shared_ptr<AudioEngine>& audioEngine,
        const std::shared_ptr<GraphicsDevice>& graphicsDevice);

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

    /// Loads an asset stored at the specified path in a content directory.
    template <typename T>
    [[nodiscard]] std::tuple<std::shared_ptr<T>, std::shared_ptr<Error>>
    Load(const std::string& assetName)
    {
        static_assert(std::is_object<T>::value, "");

        const std::type_index typeIndex = typeid(std::shared_ptr<T>);

        const auto filePath = GetAssetPath(assetName);

        auto key = PathHelper::ToSlash(filePath);
        if (auto iter = assets.find(key); iter != std::end(assets)) {
            auto& assetHolder = iter->second;

            if (std::type_index(assetHolder.type()) == typeIndex) {
                auto asset = std::any_cast<std::shared_ptr<T>>(assetHolder);
                return std::make_tuple(std::move(asset), nullptr);
            }

            assets.erase(iter);
        }

        Detail::AssetLoader<T> loader;
        auto [asset, err] = loader(*this, filePath);
        if (err != nullptr) {
            return std::make_tuple(nullptr, std::move(err));
        }

        static_assert(std::is_same<decltype(asset), std::shared_ptr<T>>::value);

        auto assetHolder = std::make_any<std::shared_ptr<T>>(asset);
        POMDOG_ASSERT(std::type_index(assetHolder.type()) == typeIndex);

        assets.emplace(std::move(key), std::move(assetHolder));

        return std::make_tuple(std::move(asset), nullptr);
    }

    /// Creates an asset builder.
    template <typename T, typename... Arguments>
    AssetBuilders::Builder<T> CreateBuilder(Arguments&&... arguments)
    {
        AssetBuilders::Builder<T> builder(*this,
            std::forward<Arguments>(arguments)...);
        return builder;
    }

    /// Disposes all loaded assets in this manager.
    void Unload();

    /// Gets the path to the asset directory.
    [[nodiscard]] std::string
    GetContentDirectory() const noexcept;

    /// Sets the path to the asset directory.
    void SetContentDirectory(const std::string& dir) noexcept;

    /// Gets the audio engine for creating audio resources.
    [[nodiscard]] std::shared_ptr<AudioEngine>
    GetAudioEngine() const noexcept;

    /// Gets the graphics device for creating graphics resources.
    [[nodiscard]] std::shared_ptr<GraphicsDevice>
    GetGraphicsDevice() const noexcept;

    /// Gets the full path to the asset.
    [[nodiscard]] std::string
    GetAssetPath(const std::string& assetName) const noexcept;

private:
    std::string contentDirectory;
    std::weak_ptr<AudioEngine> audioEngine;
    std::weak_ptr<GraphicsDevice> graphicsDevice;
    std::unordered_map<std::string, std::any> assets;
};

} // namespace Pomdog
<commit_msg>Minor refactor<commit_after>// Copyright (c) 2013-2020 mogemimi. Distributed under the MIT license.

#pragma once

#include "Pomdog/Basic/Export.hpp"
#include "Pomdog/Content/AssetBuilders/Builder.hpp"
#include "Pomdog/Content/AssetLoaders/AssetLoader.hpp"
#include "Pomdog/Content/AssetLoaders/AudioClipLoader.hpp"
#include "Pomdog/Content/AssetLoaders/Texture2DLoader.hpp"
#include "Pomdog/Utility/Assert.hpp"
#include "Pomdog/Utility/Errors.hpp"
#include "Pomdog/Utility/PathHelper.hpp"
#include <any>
#include <memory>
#include <string>
#include <tuple>
#include <typeindex>
#include <typeinfo>
#include <unordered_map>
#include <utility>

namespace Pomdog {

class AudioEngine;
class GraphicsDevice;

class POMDOG_EXPORT AssetManager final {
public:
    AssetManager(
        const std::string& contentDirectory,
        const std::shared_ptr<AudioEngine>& audioEngine,
        const std::shared_ptr<GraphicsDevice>& graphicsDevice);

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

    /// Loads an asset stored at the specified path in a content directory.
    template <typename T>
    [[nodiscard]] std::tuple<std::shared_ptr<T>, std::shared_ptr<Error>>
    Load(const std::string& assetName)
    {
        static_assert(std::is_object<T>::value, "");

        const std::type_index typeIndex = typeid(std::shared_ptr<T>);

        const auto filePath = GetAssetPath(assetName);

        auto key = PathHelper::ToSlash(filePath);
        if (auto iter = assets.find(key); iter != std::end(assets)) {
            auto& assetHolder = iter->second;

            if (std::type_index(assetHolder.type()) == typeIndex) {
                auto asset = std::any_cast<std::shared_ptr<T>>(assetHolder);
                return std::make_tuple(std::move(asset), nullptr);
            }

            assets.erase(iter);
        }

        Detail::AssetLoader<T> loader;
        auto [asset, err] = loader(*this, filePath);
        if (err != nullptr) {
            return std::make_tuple(nullptr, std::move(err));
        }

        static_assert(std::is_same<decltype(asset), std::shared_ptr<T>>::value);

        auto assetHolder = std::make_any<std::shared_ptr<T>>(asset);
        POMDOG_ASSERT(std::type_index(assetHolder.type()) == typeIndex);

        assets.emplace(std::move(key), std::move(assetHolder));

        return std::make_tuple(std::move(asset), nullptr);
    }

    /// Creates an asset builder.
    template <typename T, typename... Arguments>
    [[nodiscard]] AssetBuilders::Builder<T>
    CreateBuilder(Arguments&&... arguments)
    {
        AssetBuilders::Builder<T> builder(*this, std::forward<Arguments>(arguments)...);
        return builder;
    }

    /// Disposes all loaded assets in this manager.
    void Unload();

    /// Gets the path to the asset directory.
    [[nodiscard]] std::string
    GetContentDirectory() const noexcept;

    /// Sets the path to the asset directory.
    void SetContentDirectory(const std::string& dir) noexcept;

    /// Gets the audio engine for creating audio resources.
    [[nodiscard]] std::shared_ptr<AudioEngine>
    GetAudioEngine() const noexcept;

    /// Gets the graphics device for creating graphics resources.
    [[nodiscard]] std::shared_ptr<GraphicsDevice>
    GetGraphicsDevice() const noexcept;

    /// Gets the full path to the asset.
    [[nodiscard]] std::string
    GetAssetPath(const std::string& assetName) const noexcept;

private:
    std::string contentDirectory;
    std::weak_ptr<AudioEngine> audioEngine;
    std::weak_ptr<GraphicsDevice> graphicsDevice;
    std::unordered_map<std::string, std::any> assets;
};

} // namespace Pomdog
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
 */

#pragma once

#include <stdint.h>
#include <limits>
#include <uavcan/internal/util.hpp>
#include <uavcan/internal/marshalling/scalar_codec.hpp>
#include <uavcan/internal/marshalling/type_util.hpp>

namespace uavcan
{

enum Signedness { SignednessUnsigned, SignednessSigned };

template <unsigned int BitLen_, Signedness Signedness, CastMode CastMode>
class IntegerSpec
{
    enum { IsSigned = Signedness == SignednessSigned };

    struct ErrorNoSuchInteger;

public:
    enum { BitLen = BitLen_ };
    enum { MinBitLen = BitLen };
    enum { MaxBitLen = BitLen };

    typedef typename StaticIf<(BitLen <= 8),  typename StaticIf<IsSigned, int8_t,  uint8_t>::Result,
            typename StaticIf<(BitLen <= 16), typename StaticIf<IsSigned, int16_t, uint16_t>::Result,
            typename StaticIf<(BitLen <= 32), typename StaticIf<IsSigned, int32_t, uint32_t>::Result,
            typename StaticIf<(BitLen <= 64), typename StaticIf<IsSigned, int64_t, uint64_t>::Result,
                              ErrorNoSuchInteger>::Result>::Result>::Result>::Result StorageType;

private:
    typedef typename IntegerSpec<BitLen, SignednessUnsigned, CastMode>::StorageType UnsignedStorageType;

    IntegerSpec();

    struct ExactSizeLimits
    {
        static StorageType max() { return std::numeric_limits<StorageType>::max(); }
        static StorageType min() { return std::numeric_limits<StorageType>::min(); }
        static UnsignedStorageType mask() { return ~UnsignedStorageType(0); }
    };

    struct NonExactSizeLimits
    {
        static StorageType max()
        {
            return IsSigned ? ((StorageType(1) << (BitLen - 1)) - 1) : ((StorageType(1) << BitLen) - 1);
        }
        static StorageType min() { return IsSigned ? -(StorageType(1) << (BitLen - 1)) : 0; }
        static UnsignedStorageType mask() { return (UnsignedStorageType(1) << BitLen) - 1; }
    };

    enum { IsExactSize = (BitLen == 8) || (BitLen == 16) || (BitLen == 32) || (BitLen == 64) };

    typedef typename StaticIf<IsExactSize, ExactSizeLimits, NonExactSizeLimits>::Result Limits;

    static void saturate(StorageType& value)
    {
        if (value > max())
            value = max();
        else if (value <= min()) // 'Less or Equal' allows to suppress compiler warning on unsigned types
            value = min();
    }

    static void truncate(StorageType& value)
    {
        // cppcheck-suppress duplicateExpression
        value &= Limits::mask();
    }

public:
    // cppcheck-suppress duplicateExpression
    static StorageType max() { return Limits::max(); }
    // cppcheck-suppress duplicateExpression
    static StorageType min() { return Limits::min(); }

    static int encode(StorageType value, ScalarCodec& codec, TailArrayOptimizationMode)
    {
        // cppcheck-suppress duplicateExpression
        if (CastMode == CastModeSaturate)
            saturate(value);
        else
            truncate(value);
        return codec.encode<BitLen>(value);
    }

    static int decode(StorageType& out_value, ScalarCodec& codec, TailArrayOptimizationMode)
    {
        return codec.decode<BitLen>(out_value);
    }
};

template <CastMode CastMode>
class IntegerSpec<1, SignednessSigned, CastMode>;   // Invalid instantiation

}
<commit_msg>Added compile time and run time assertions for IntegerSpec<><commit_after>/*
 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
 */

#pragma once

#include <stdint.h>
#include <limits>
#include <uavcan/internal/util.hpp>
#include <uavcan/internal/marshalling/scalar_codec.hpp>
#include <uavcan/internal/marshalling/type_util.hpp>

namespace uavcan
{

enum Signedness { SignednessUnsigned, SignednessSigned };

template <unsigned int BitLen_, Signedness Signedness, CastMode CastMode>
class IntegerSpec
{
    enum { IsSigned = Signedness == SignednessSigned };

    struct ErrorNoSuchInteger;

public:
    enum { BitLen = BitLen_ };
    enum { MinBitLen = BitLen };
    enum { MaxBitLen = BitLen };

    typedef typename StaticIf<(BitLen <= 8),  typename StaticIf<IsSigned, int8_t,  uint8_t>::Result,
            typename StaticIf<(BitLen <= 16), typename StaticIf<IsSigned, int16_t, uint16_t>::Result,
            typename StaticIf<(BitLen <= 32), typename StaticIf<IsSigned, int32_t, uint32_t>::Result,
            typename StaticIf<(BitLen <= 64), typename StaticIf<IsSigned, int64_t, uint64_t>::Result,
                              ErrorNoSuchInteger>::Result>::Result>::Result>::Result StorageType;

    typedef typename IntegerSpec<BitLen, SignednessUnsigned, CastMode>::StorageType UnsignedStorageType;

private:
    IntegerSpec();

    struct LimitsImplGeneric
    {
        static StorageType max()
        {
            StaticAssert<(sizeof(uintmax_t) >= 8)>::check();
            return StorageType(IsSigned ? ((uintmax_t(1) << (BitLen - 1)) - 1) : ((uintmax_t(1) << BitLen) - 1));
        }
        static UnsignedStorageType mask()
        {
            StaticAssert<(sizeof(uintmax_t) >= 8)>::check();
            return UnsignedStorageType((uintmax_t(1) << BitLen) - 1);
        }
    };

    struct LimitsImpl64
    {
        static StorageType max() { return StorageType(IsSigned ? 0x7FFFFFFFFFFFFFFF : 0xFFFFFFFFFFFFFFFF); }
        static UnsignedStorageType mask() { return 0xFFFFFFFFFFFFFFFF; }
    };

    typedef typename StaticIf<(BitLen == 64), LimitsImpl64, LimitsImplGeneric>::Result Limits;

    static void saturate(StorageType& value)
    {
        if (value > max())
            value = max();
        else if (value <= min()) // 'Less or Equal' allows to suppress compiler warning on unsigned types
            value = min();
    }

    static void truncate(StorageType& value) { value &= mask(); }

    static void validate()
    {
        StaticAssert<(BitLen <= (sizeof(StorageType) * 8))>::check();
        assert(max() <= std::numeric_limits<StorageType>::max());
        assert(min() >= std::numeric_limits<StorageType>::min());
    }

public:
    static StorageType max() { return Limits::max(); }
    static StorageType min() { return IsSigned ? StorageType(-max() - 1) : 0; }
    static UnsignedStorageType mask() { return Limits::mask(); }

    static int encode(StorageType value, ScalarCodec& codec, TailArrayOptimizationMode)
    {
        validate();
        // cppcheck-suppress duplicateExpression
        if (CastMode == CastModeSaturate)
            saturate(value);
        else
            truncate(value);
        return codec.encode<BitLen>(value);
    }

    static int decode(StorageType& out_value, ScalarCodec& codec, TailArrayOptimizationMode)
    {
        validate();
        return codec.decode<BitLen>(out_value);
    }
};

template <CastMode CastMode>
class IntegerSpec<1, SignednessSigned, CastMode>;   // Invalid instantiation

template <Signedness Signedness, CastMode CastMode>
class IntegerSpec<0, Signedness, CastMode>;         // Invalid instantiation

}
<|endoftext|>


<commit_before>#include "apply_feature_functors.hpp"
#include "shape_view_params.hpp"
#include "visual_params.hpp"
#include "engine_context.hpp"

#include "area_shape.hpp"
#include "line_shape.hpp"
#include "text_shape.hpp"
#include "poi_symbol_shape.hpp"
#include "path_symbol_shape.hpp"
#include "circle_shape.hpp"
#include "path_text_shape.hpp"

#include "../indexer/drawing_rules.hpp"
#include "../indexer/drules_include.hpp"

#include "../drape/color.hpp"
#include "../drape/stipple_pen_resource.hpp"

#include "../graphics/defines.hpp"

#include "../std/algorithm.hpp"
#include "../std/utility.hpp"

namespace df
{

namespace
{

dp::Color ToDrapeColor(uint32_t src)
{
  return dp::Extract(src, 255 - (src >> 24));
}

void Extract(::LineDefProto const * lineRule,
             df::LineViewParams & params)
{
  float const scale = df::VisualParams::Instance().GetVisualScale();
  params.m_color = ToDrapeColor(lineRule->color());
  params.m_width = max(lineRule->width() * scale, 1.0);

  if (lineRule->has_dashdot())
  {
    DashDotProto const & dd = lineRule->dashdot();

    int const count = dd.dd_size();
    params.m_pattern.reserve(count);
    for (int i = 0; i < count; ++i)
      params.m_pattern.push_back(dd.dd(i) * scale);
  }

  switch(lineRule->cap())
  {
  case ::ROUNDCAP : params.m_cap = dp::RoundCap;
    break;
  case ::BUTTCAP  : params.m_cap = dp::ButtCap;
    break;
  case ::SQUARECAP: params.m_cap = dp::SquareCap;
    break;
  default:
    ASSERT(false, ());
  }

  switch (lineRule->join())
  {
  case ::NOJOIN    : params.m_join = dp::MiterJoin;
    break;
  case ::ROUNDJOIN : params.m_join = dp::RoundJoin;
    break;
  case ::BEVELJOIN : params.m_join = dp::BevelJoin;
    break;
  default:
    ASSERT(false, ());
  }
}

void CaptionDefProtoToFontDecl(CaptionDefProto const * capRule, df::FontDecl &params)
{
  params.m_color = ToDrapeColor(capRule->color());
  params.m_size = max(8.0, capRule->height() * df::VisualParams::Instance().GetVisualScale());

  params.m_needOutline = false;
  if (capRule->has_stroke_color())
  {
    params.m_needOutline = true;
    params.m_outlineColor = dp::Color(255, 255, 255, 255);
  }
}

m2::PointF GetCaptionOffset(CaptionDefProto const * capRule)
{
  m2::PointF offset;
  float visualScale = df::VisualParams::Instance().GetVisualScale();
  if (capRule->has_offset_x())
    offset.x = capRule->offset_x() * visualScale;

  if (capRule->has_offset_y())
    offset.y = capRule->offset_y() * visualScale;

  return offset;
}

dp::Anchor GetAnchor(CaptionDefProto const * capRule)
{
  if (capRule->has_offset_y())
  {
    if (capRule->offset_y() > 0)
      return dp::Top;
    else
      return dp::Bottom;
  }
  if (capRule->has_offset_x())
  {
    if (capRule->offset_x() > 0)
      return dp::Right;
    else
      return dp::Left;

  }

  return dp::Center;
}

} // namespace

BaseApplyFeature::BaseApplyFeature(EngineContext & context, TileKey tileKey,
                                   FeatureID const & id, CaptionDescription const & caption)
  : m_context(context)
  , m_tileKey(tileKey)
  , m_id(id)
  , m_captions(caption)
{
}

void BaseApplyFeature::ExtractCaptionParams(CaptionDefProto const * primaryProto,
                                            CaptionDefProto const * secondaryProto,
                                            double depth,
                                            TextViewParams & params) const
{
  FontDecl decl;
  CaptionDefProtoToFontDecl(primaryProto, decl);

  params.m_anchor = GetAnchor(primaryProto);
  params.m_depth = depth;
  params.m_featureID = m_id;
  params.m_primaryOffset = GetCaptionOffset(primaryProto);
  params.m_primaryText = m_captions.GetMainText();
  params.m_primaryTextFont = decl;

  if (secondaryProto)
  {
    FontDecl auxDecl;
    CaptionDefProtoToFontDecl(secondaryProto, auxDecl);

    params.m_secondaryText = m_captions.GetAuxText();
    params.m_secondaryTextFont = auxDecl;
  }
}

// ============================================= //

ApplyPointFeature::ApplyPointFeature(EngineContext & context, TileKey tileKey,
                                     FeatureID const & id, CaptionDescription const & captions)
  : TBase(context, tileKey, id, captions)
  , m_hasPoint(false)
  , m_symbolDepth(graphics::minDepth)
  , m_circleDepth(graphics::minDepth)
  , m_symbolRule(NULL)
  , m_circleRule(NULL)
{
}

void ApplyPointFeature::operator()(CoordPointT const & point)
{
  operator()(m2::PointF(point.first, point.second));
}

void ApplyPointFeature::operator()(m2::PointD const & point)
{
  m_hasPoint = true;
  m_centerPoint = point;
}

void ApplyPointFeature::ProcessRule(Stylist::rule_wrapper_t const & rule)
{
  if (m_hasPoint == false)
    return;
  drule::BaseRule const * pRule = rule.first;
  float depth = rule.second;

  bool isNode = (pRule->GetType() & drule::node) != 0;
  CaptionDefProto const * capRule = pRule->GetCaption(0);
  if (capRule && isNode)
  {
    TextViewParams params;
    ExtractCaptionParams(capRule, pRule->GetCaption(1), depth, params);
    if(!params.m_primaryText.empty() || !params.m_secondaryText.empty())
      m_context.InsertShape(m_tileKey, dp::MovePointer<MapShape>(new TextShape(m_centerPoint, params)));
  }

  SymbolRuleProto const * symRule =  pRule->GetSymbol();
  if (symRule)
  {
    m_symbolDepth = depth;
    m_symbolRule  = symRule;
  }

  CircleRuleProto const * circleRule = pRule->GetCircle();
  if (circleRule)
  {
    m_circleDepth = depth;
    m_circleRule  = circleRule;
  }
}

void ApplyPointFeature::Finish()
{
  if (m_circleRule && m_symbolRule)
  {
    // draw circledSymbol
  }
  else if (m_circleRule)
  {
    CircleViewParams params(m_id);
    params.m_depth = m_circleDepth;
    params.m_color = ToDrapeColor(m_circleRule->color());
    params.m_radius = m_circleRule->radius();

    CircleShape * shape = new CircleShape(m_centerPoint, params);
    m_context.InsertShape(m_tileKey, dp::MovePointer<MapShape>(shape));
  }
  else if (m_symbolRule)
  {
    PoiSymbolViewParams params(m_id);
    params.m_depth = m_symbolDepth;
    params.m_symbolName = m_symbolRule->name();

    PoiSymbolShape * shape = new PoiSymbolShape(m_centerPoint, params);
    m_context.InsertShape(m_tileKey, dp::MovePointer<MapShape>(shape));
  }
}

// ============================================= //

ApplyAreaFeature::ApplyAreaFeature(EngineContext & context, TileKey tileKey,
                                   FeatureID const & id, CaptionDescription const & captions)
  : TBase(context, tileKey, id, captions)
{
}

void ApplyAreaFeature::operator()(m2::PointD const & p1, m2::PointD const & p2, m2::PointD const & p3)
{
  m_triangles.push_back(p1);
  m_triangles.push_back(p2);
  m_triangles.push_back(p3);
}

void ApplyAreaFeature::ProcessRule(Stylist::rule_wrapper_t const & rule)
{
  drule::BaseRule const * pRule = rule.first;
  double const depth = rule.second;

  AreaRuleProto const * areaRule = pRule->GetArea();
  if (areaRule && !m_triangles.empty())
  {
    AreaViewParams params;
    params.m_depth = depth;
    params.m_color = ToDrapeColor(areaRule->color());

    AreaShape * shape = new AreaShape(move(m_triangles), params);
    m_context.InsertShape(m_tileKey, dp::MovePointer<MapShape>(shape));
  }
  else
    TBase::ProcessRule(rule);
}

// ============================================= //

ApplyLineFeature::ApplyLineFeature(EngineContext & context, TileKey tileKey,
                                   FeatureID const & id, CaptionDescription const & captions,
                                   double currentScaleGtoP)
  : TBase(context, tileKey, id, captions)
  , m_currentScaleGtoP(currentScaleGtoP)
{
}

void ApplyLineFeature::operator() (m2::PointD const & point)
{
  if (m_spline.IsNull())
    m_spline.Reset(new m2::Spline());

  m_spline->AddPoint(point);
}

bool ApplyLineFeature::HasGeometry() const
{
  return m_spline->IsValid();
}

void ApplyLineFeature::ProcessRule(Stylist::rule_wrapper_t const & rule)
{
  ASSERT(HasGeometry(), ());
  drule::BaseRule const * pRule = rule.first;
  float depth = rule.second;

  bool isWay = (pRule->GetType() & drule::way) != 0;
  CaptionDefProto const * pCaptionRule = pRule->GetCaption(0);
  LineDefProto const * pLineRule = pRule->GetLine();
  if (pCaptionRule == NULL && pLineRule == NULL)
    return;

  ASSERT(pCaptionRule == NULL || pLineRule == NULL, ());
  if (pCaptionRule != NULL && pCaptionRule->height() > 2 &&
      !m_captions.GetPathName().empty() && isWay)
  {
    FontDecl fontDecl;
    CaptionDefProtoToFontDecl(pCaptionRule, fontDecl);

    PathTextViewParams params;
    params.m_depth = depth;
    params.m_text = m_captions.GetPathName();
    params.m_textFont = fontDecl;
    params.m_baseGtoPScale = m_currentScaleGtoP;

    m_context.InsertShape(m_tileKey, dp::MovePointer<MapShape>(new PathTextShape(m_spline, params)));
  }

  if (pLineRule != NULL)
  {
    if (pLineRule->has_pathsym())
    {
      PathSymProto const & symRule = pLineRule->pathsym();
      PathSymbolViewParams params;
      params.m_depth = depth;
      params.m_symbolName = symRule.name();
      float const mainScale = df::VisualParams::Instance().GetVisualScale();
      params.m_offset = symRule.offset() * mainScale;
      params.m_step = symRule.step() * mainScale;
      params.m_baseGtoPScale = m_currentScaleGtoP;

      m_context.InsertShape(m_tileKey, dp::MovePointer<MapShape>(new PathSymbolShape(m_spline, params)));
    }
    else
    {
      LineViewParams params;
      Extract(pLineRule, params);
      params.m_depth = depth;
      params.m_baseGtoPScale = m_currentScaleGtoP;
      m_context.InsertShape(m_tileKey, dp::MovePointer<MapShape>(new LineShape(m_spline, params)));
    }
  }
}

void ApplyLineFeature::Finish()
{
  string const & roadNumber = m_captions.GetRoadNumber();
  if (roadNumber.empty())
    return;

  double pathPixelLength = m_spline->GetLength() * m_currentScaleGtoP;
  int const textHeight = static_cast<int>(11 * df::VisualParams::Instance().GetVisualScale());

  // I don't know why we draw by this, but it's work before and will work now
  if (pathPixelLength > (roadNumber.size() + 2) * textHeight)
  {
    // TODO in future we need to choose emptySpace according GtoP scale.
    double const emptySpace = 1000.0;
    int const count = static_cast<int>((pathPixelLength / emptySpace) + 2);
    double const splineStep = pathPixelLength / count;

    FontDecl font;
    font.m_color = dp::Color(150, 75, 0, 255);
    font.m_needOutline = true;
    font.m_outlineColor = dp::Color(255, 255, 255, 255);
    font.m_size = textHeight;

    TextViewParams viewParams;
    viewParams.m_depth = 0;
    viewParams.m_anchor = dp::Center;
    viewParams.m_featureID = FeatureID();
    viewParams.m_primaryText = roadNumber;
    viewParams.m_primaryTextFont = font;

    m2::Spline::iterator it = m_spline.CreateIterator();
    while (!it.BeginAgain())
    {
      m_context.InsertShape(m_tileKey, dp::MovePointer<MapShape>(new TextShape(it.m_pos, viewParams)));
      it.Step(splineStep);
    }
  }
}

} // namespace df
<commit_msg>Fixes after merge.<commit_after>#include "apply_feature_functors.hpp"
#include "shape_view_params.hpp"
#include "visual_params.hpp"
#include "engine_context.hpp"

#include "area_shape.hpp"
#include "line_shape.hpp"
#include "text_shape.hpp"
#include "poi_symbol_shape.hpp"
#include "path_symbol_shape.hpp"
#include "circle_shape.hpp"
#include "path_text_shape.hpp"

#include "../indexer/drawing_rules.hpp"
#include "../indexer/drules_include.hpp"

#include "../drape/color.hpp"
#include "../drape/stipple_pen_resource.hpp"

#include "../graphics/defines.hpp"

#include "../std/algorithm.hpp"
#include "../std/utility.hpp"

namespace df
{

namespace
{

dp::Color ToDrapeColor(uint32_t src)
{
  return dp::Extract(src, 255 - (src >> 24));
}

void Extract(::LineDefProto const * lineRule,
             df::LineViewParams & params)
{
  float const scale = df::VisualParams::Instance().GetVisualScale();
  params.m_color = ToDrapeColor(lineRule->color());
  params.m_width = max(lineRule->width() * scale, 1.0);

  if (lineRule->has_dashdot())
  {
    DashDotProto const & dd = lineRule->dashdot();

    int const count = dd.dd_size();
    params.m_pattern.reserve(count);
    for (int i = 0; i < count; ++i)
      params.m_pattern.push_back(dd.dd(i) * scale);
  }

  switch(lineRule->cap())
  {
  case ::ROUNDCAP : params.m_cap = dp::RoundCap;
    break;
  case ::BUTTCAP  : params.m_cap = dp::ButtCap;
    break;
  case ::SQUARECAP: params.m_cap = dp::SquareCap;
    break;
  default:
    ASSERT(false, ());
  }

  switch (lineRule->join())
  {
  case ::NOJOIN    : params.m_join = dp::MiterJoin;
    break;
  case ::ROUNDJOIN : params.m_join = dp::RoundJoin;
    break;
  case ::BEVELJOIN : params.m_join = dp::BevelJoin;
    break;
  default:
    ASSERT(false, ());
  }
}

void CaptionDefProtoToFontDecl(CaptionDefProto const * capRule, df::FontDecl &params)
{
  params.m_color = ToDrapeColor(capRule->color());
  params.m_size = max(8.0, capRule->height() * df::VisualParams::Instance().GetVisualScale());

  params.m_needOutline = false;
  if (capRule->has_stroke_color())
  {
    params.m_needOutline = true;
    params.m_outlineColor = dp::Color(255, 255, 255, 255);
  }
}

m2::PointF GetCaptionOffset(CaptionDefProto const * capRule)
{
  m2::PointF offset;
  float visualScale = df::VisualParams::Instance().GetVisualScale();
  if (capRule->has_offset_x())
    offset.x = capRule->offset_x() * visualScale;

  if (capRule->has_offset_y())
    offset.y = capRule->offset_y() * visualScale;

  return offset;
}

dp::Anchor GetAnchor(CaptionDefProto const * capRule)
{
  if (capRule->has_offset_y())
  {
    if (capRule->offset_y() > 0)
      return dp::Top;
    else
      return dp::Bottom;
  }
  if (capRule->has_offset_x())
  {
    if (capRule->offset_x() > 0)
      return dp::Right;
    else
      return dp::Left;

  }

  return dp::Center;
}

} // namespace

BaseApplyFeature::BaseApplyFeature(EngineContext & context, TileKey tileKey,
                                   FeatureID const & id, CaptionDescription const & caption)
  : m_context(context)
  , m_tileKey(tileKey)
  , m_id(id)
  , m_captions(caption)
{
}

void BaseApplyFeature::ExtractCaptionParams(CaptionDefProto const * primaryProto,
                                            CaptionDefProto const * secondaryProto,
                                            double depth,
                                            TextViewParams & params) const
{
  FontDecl decl;
  CaptionDefProtoToFontDecl(primaryProto, decl);

  params.m_anchor = GetAnchor(primaryProto);
  params.m_depth = depth;
  params.m_featureID = m_id;
  params.m_primaryOffset = GetCaptionOffset(primaryProto);
  params.m_primaryText = m_captions.GetMainText();
  params.m_primaryTextFont = decl;

  if (secondaryProto)
  {
    FontDecl auxDecl;
    CaptionDefProtoToFontDecl(secondaryProto, auxDecl);

    params.m_secondaryText = m_captions.GetAuxText();
    params.m_secondaryTextFont = auxDecl;
  }
}

// ============================================= //

ApplyPointFeature::ApplyPointFeature(EngineContext & context, TileKey tileKey,
                                     FeatureID const & id, CaptionDescription const & captions)
  : TBase(context, tileKey, id, captions)
  , m_hasPoint(false)
  , m_symbolDepth(graphics::minDepth)
  , m_circleDepth(graphics::minDepth)
  , m_symbolRule(NULL)
  , m_circleRule(NULL)
{
}

void ApplyPointFeature::operator()(m2::PointD const & point)
{
  m_hasPoint = true;
  m_centerPoint = point;
}

void ApplyPointFeature::ProcessRule(Stylist::rule_wrapper_t const & rule)
{
  if (m_hasPoint == false)
    return;
  drule::BaseRule const * pRule = rule.first;
  float depth = rule.second;

  bool isNode = (pRule->GetType() & drule::node) != 0;
  CaptionDefProto const * capRule = pRule->GetCaption(0);
  if (capRule && isNode)
  {
    TextViewParams params;
    ExtractCaptionParams(capRule, pRule->GetCaption(1), depth, params);
    if(!params.m_primaryText.empty() || !params.m_secondaryText.empty())
      m_context.InsertShape(m_tileKey, dp::MovePointer<MapShape>(new TextShape(m_centerPoint, params)));
  }

  SymbolRuleProto const * symRule =  pRule->GetSymbol();
  if (symRule)
  {
    m_symbolDepth = depth;
    m_symbolRule  = symRule;
  }

  CircleRuleProto const * circleRule = pRule->GetCircle();
  if (circleRule)
  {
    m_circleDepth = depth;
    m_circleRule  = circleRule;
  }
}

void ApplyPointFeature::Finish()
{
  if (m_circleRule && m_symbolRule)
  {
    // draw circledSymbol
  }
  else if (m_circleRule)
  {
    CircleViewParams params(m_id);
    params.m_depth = m_circleDepth;
    params.m_color = ToDrapeColor(m_circleRule->color());
    params.m_radius = m_circleRule->radius();

    CircleShape * shape = new CircleShape(m_centerPoint, params);
    m_context.InsertShape(m_tileKey, dp::MovePointer<MapShape>(shape));
  }
  else if (m_symbolRule)
  {
    PoiSymbolViewParams params(m_id);
    params.m_depth = m_symbolDepth;
    params.m_symbolName = m_symbolRule->name();

    PoiSymbolShape * shape = new PoiSymbolShape(m_centerPoint, params);
    m_context.InsertShape(m_tileKey, dp::MovePointer<MapShape>(shape));
  }
}

// ============================================= //

ApplyAreaFeature::ApplyAreaFeature(EngineContext & context, TileKey tileKey,
                                   FeatureID const & id, CaptionDescription const & captions)
  : TBase(context, tileKey, id, captions)
{
}

void ApplyAreaFeature::operator()(m2::PointD const & p1, m2::PointD const & p2, m2::PointD const & p3)
{
  m_triangles.push_back(p1);
  m_triangles.push_back(p2);
  m_triangles.push_back(p3);
}

void ApplyAreaFeature::ProcessRule(Stylist::rule_wrapper_t const & rule)
{
  drule::BaseRule const * pRule = rule.first;
  double const depth = rule.second;

  AreaRuleProto const * areaRule = pRule->GetArea();
  if (areaRule && !m_triangles.empty())
  {
    AreaViewParams params;
    params.m_depth = depth;
    params.m_color = ToDrapeColor(areaRule->color());

    AreaShape * shape = new AreaShape(move(m_triangles), params);
    m_context.InsertShape(m_tileKey, dp::MovePointer<MapShape>(shape));
  }
  else
    TBase::ProcessRule(rule);
}

// ============================================= //

ApplyLineFeature::ApplyLineFeature(EngineContext & context, TileKey tileKey,
                                   FeatureID const & id, CaptionDescription const & captions,
                                   double currentScaleGtoP)
  : TBase(context, tileKey, id, captions)
  , m_currentScaleGtoP(currentScaleGtoP)
{
}

void ApplyLineFeature::operator() (m2::PointD const & point)
{
  if (m_spline.IsNull())
    m_spline.Reset(new m2::Spline());

  m_spline->AddPoint(point);
}

bool ApplyLineFeature::HasGeometry() const
{
  return m_spline->IsValid();
}

void ApplyLineFeature::ProcessRule(Stylist::rule_wrapper_t const & rule)
{
  ASSERT(HasGeometry(), ());
  drule::BaseRule const * pRule = rule.first;
  float depth = rule.second;

  bool isWay = (pRule->GetType() & drule::way) != 0;
  CaptionDefProto const * pCaptionRule = pRule->GetCaption(0);
  LineDefProto const * pLineRule = pRule->GetLine();
  if (pCaptionRule == NULL && pLineRule == NULL)
    return;

  ASSERT(pCaptionRule == NULL || pLineRule == NULL, ());
  if (pCaptionRule != NULL && pCaptionRule->height() > 2 &&
      !m_captions.GetPathName().empty() && isWay)
  {
    FontDecl fontDecl;
    CaptionDefProtoToFontDecl(pCaptionRule, fontDecl);

    PathTextViewParams params;
    params.m_depth = depth;
    params.m_text = m_captions.GetPathName();
    params.m_textFont = fontDecl;
    params.m_baseGtoPScale = m_currentScaleGtoP;

    m_context.InsertShape(m_tileKey, dp::MovePointer<MapShape>(new PathTextShape(m_spline, params)));
  }

  if (pLineRule != NULL)
  {
    if (pLineRule->has_pathsym())
    {
      PathSymProto const & symRule = pLineRule->pathsym();
      PathSymbolViewParams params;
      params.m_depth = depth;
      params.m_symbolName = symRule.name();
      float const mainScale = df::VisualParams::Instance().GetVisualScale();
      params.m_offset = symRule.offset() * mainScale;
      params.m_step = symRule.step() * mainScale;
      params.m_baseGtoPScale = m_currentScaleGtoP;

      m_context.InsertShape(m_tileKey, dp::MovePointer<MapShape>(new PathSymbolShape(m_spline, params)));
    }
    else
    {
      LineViewParams params;
      Extract(pLineRule, params);
      params.m_depth = depth;
      params.m_baseGtoPScale = m_currentScaleGtoP;
      m_context.InsertShape(m_tileKey, dp::MovePointer<MapShape>(new LineShape(m_spline, params)));
    }
  }
}

void ApplyLineFeature::Finish()
{
  string const & roadNumber = m_captions.GetRoadNumber();
  if (roadNumber.empty())
    return;

  double pathPixelLength = m_spline->GetLength() * m_currentScaleGtoP;
  int const textHeight = static_cast<int>(11 * df::VisualParams::Instance().GetVisualScale());

  // I don't know why we draw by this, but it's work before and will work now
  if (pathPixelLength > (roadNumber.size() + 2) * textHeight)
  {
    // TODO in future we need to choose emptySpace according GtoP scale.
    double const emptySpace = 1000.0;
    int const count = static_cast<int>((pathPixelLength / emptySpace) + 2);
    double const splineStep = pathPixelLength / count;

    FontDecl font;
    font.m_color = dp::Color(150, 75, 0, 255);
    font.m_needOutline = true;
    font.m_outlineColor = dp::Color(255, 255, 255, 255);
    font.m_size = textHeight;

    TextViewParams viewParams;
    viewParams.m_depth = 0;
    viewParams.m_anchor = dp::Center;
    viewParams.m_featureID = FeatureID();
    viewParams.m_primaryText = roadNumber;
    viewParams.m_primaryTextFont = font;

    m2::Spline::iterator it = m_spline.CreateIterator();
    while (!it.BeginAgain())
    {
      m_context.InsertShape(m_tileKey, dp::MovePointer<MapShape>(new TextShape(it.m_pos, viewParams)));
      it.Step(splineStep);
    }
  }
}

} // namespace df
<|endoftext|>


<commit_before>
/*

                        /~` _  _ _|_. _     _ |_ | _
                        \_,(_)| | | || ||_|(_||_)|(/_

                    https://github.com/Naios/continuable
                                   v2.0.0

  Copyright(c) 2015 - 2017 Denis Blank <denis.blank at outlook dot com>

  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 CONTINUABLE_DETAIL_EXPECTED_HPP_INCLUDED__
#define CONTINUABLE_DETAIL_EXPECTED_HPP_INCLUDED__

#include <cassert>
#include <memory>
#include <type_traits>
#include <utility>

#include <continuable/continuable-api.hpp>
#include <continuable/detail/types.hpp>
#include <continuable/detail/util.hpp>

namespace cti {
namespace detail {
namespace util {
namespace detail {
enum class slot_t { empty, value, error };

template <typename T>
using storage_of_t = //
    std::aligned_storage_t<(sizeof(types::error_type) > sizeof(T)
                                ? sizeof(types::error_type)
                                : sizeof(T))>;

template <typename Base>
struct expected_move_base {
  constexpr expected_move_base() = default;

  expected_move_base(expected_move_base const&) = default;
  explicit expected_move_base(expected_move_base&& right) {
    Base& me = *static_cast<Base*>(this);
    Base& other = *static_cast<Base*>(&right);
    assert(!other.is_empty());

#ifndef _NDEBUG
    me.set(slot_t::empty);
#endif

    other.visit([&](auto&& value) {
      // ...
      me.init(std::move(value));
    });
    me.set(other.get());
    other.destroy();
  }
  expected_move_base& operator=(expected_move_base const&) = default;
  expected_move_base& operator=(expected_move_base&& right) {
    Base& me = *static_cast<Base*>(this);
    Base& other = *static_cast<Base*>(&right);
    assert(!other.is_empty());

    me.weak_destroy();

    other.visit([&](auto&& value) {
      // ...
      me.init(std::move(value));
    });
    me.set(other.get());
    other.destroy();
    return *this;
  }
};
template <typename Base, bool IsCopyable /*= true*/>
struct expected_copy_base : expected_move_base<Base> {
  constexpr expected_copy_base() = default;

  expected_copy_base(expected_copy_base&&) = default;
  explicit expected_copy_base(expected_copy_base const& right)
  // TODO noexcept(Base::is_nothrow_move_constructible)
  {
    Base& me = *static_cast<Base*>(this);
    Base const& other = *static_cast<Base const*>(&right);
    assert(!other->is_empty());

#ifndef _NDEBUG
    me.set(slot_t::empty);
#endif

    other.visit([&](auto&& value) {
      // ...
      me.init(std::move(value));
    });
    me.set(other.get());
  }
  expected_copy_base& operator=(expected_copy_base&&) = default;
  expected_copy_base& operator=(expected_copy_base const& right)
  // TODO  noexcept(Base::is_nothrow_move_constructible)
  {
    Base& me = *static_cast<Base*>(this);
    Base const& other = *static_cast<Base const*>(&right);
    assert(!other.is_empty());

    me.weak_destroy();

    other.visit([&](auto&& value) {
      // ...
      me.init(std::move(value));
    });
    me.set(other.get());
    return *this;
  }
};
template <typename Base /*, bool IsCopyable = false*/>
struct expected_copy_base<Base, false> : expected_move_base<Base> {
  constexpr expected_copy_base() = default;

  expected_copy_base(expected_copy_base const&) = default;
  explicit expected_copy_base(expected_copy_base&& right) = delete;
  expected_copy_base& operator=(expected_copy_base const&) = default;
  expected_copy_base& operator=(expected_copy_base&& right) = delete;
};
} // namespace detail

/// A class similar to the one in the expected proposal,
/// however it is capable of carrying an exception_ptr if
/// exceptions are used.
template <typename T>
class expected
    : detail::expected_copy_base<
          expected<T>, std::is_copy_constructible<types::error_type>::value &&
                           std::is_copy_constructible<T>::value> {

  template <typename>
  friend class expected;
  template <typename>
  friend struct detail::expected_move_base;
  template <typename, bool>
  friend struct detail::expected_copy_base;

  detail::storage_of_t<T> storage_;
  detail::slot_t slot_;

  template <typename V>
  expected(V&& value, detail::slot_t const slot) {
    using type = std::decay_t<decltype(value)>;
    new (&storage_) type(std::forward<V>(value));
    set(slot);
  }

public:
  constexpr expected() : slot_(detail::slot_t::empty) {
  }

  expected(expected const&) = default;
  expected(expected&&) = default;
  expected& operator=(expected const&) = default;
  expected& operator=(expected&&) = default;

  explicit expected(T value) //
      : expected(std::move(value), detail::slot_t::value) {
  }
  explicit expected(types::error_type error) //
      : expected(std::move(error), detail::slot_t::error) {
  }

  expected& operator=(T value) {
    set_value(std::move(value));
    return *this;
  }
  expected& operator=(types::error_type error) {
    set_error(std::move(error));
    return *this;
  }

  bool is_value() const noexcept {
    assert(!is_empty());
    return is(detail::slot_t::value);
  }
  bool is_exception() const noexcept {
    assert(!is_empty());
    return is(detail::slot_t::error);
  }

  explicit constexpr operator bool() const noexcept {
    return is_value();
  }

  void set_value(T value) {
    weak_destroy();
    init(std::move(value));
    set(detail::slot_t::value);
  }
  void set_error(types::error_type error) {
    weak_destroy();
    init(std::move(error));
    set(detail::slot_t::error);
  }

  T& get_value() noexcept {
    assert(is_value());
    return cast<T>();
  }
  T const& get_value() const noexcept {
    assert(is_value());
    return cast<T>();
  }
  T& get_exception() noexcept {
    assert(is_exception());
    return cast<types::error_type>();
  }
  T const& get_exception() const noexcept {
    assert(is_exception());
    return cast<types::error_type>();
  }

  T& operator*() noexcept {
    return get_value();
  }
  T const& operator*() const noexcept {
    return get_value();
  }

private:
  template <typename V>
  void visit(V&& visitor) {
    switch (slot_) {
      case detail::slot_t::value:
        return std::forward<V>(visitor)(cast<T>());
      case detail::slot_t::error:
        return std::forward<V>(visitor)(cast<types::error_type>());
      default:
        // We don't visit when there is no value
        break;
    }
  }
  template <typename V>
  void visit(V&& visitor) const {
    switch (slot_) {
      case detail::slot_t::value:
        return std::forward<V>(visitor)(cast<T>());
      case detail::slot_t::error:
        return std::forward<V>(visitor)(cast<types::error_type>());
      default:
        // We don't visit when there is no value
        break;
    }
  }

  bool is_empty() const noexcept {
    return is(detail::slot_t::empty);
  }

  template <typename V>
  V& cast() noexcept {
    assert(!is_empty());
    return *reinterpret_cast<V*>(&storage_);
  }
  template <typename V>
  V const& cast() const noexcept {
    assert(!is_empty());
    return *reinterpret_cast<V const*>(&storage_);
  }

  template <typename V>
  void init(V&& value) {
    assert(is_empty());
    using type = std::decay_t<decltype(value)>;
    auto storage = &storage_;
    new (storage) type(std::forward<V>(value));
  }
  void destroy() {
    weak_destroy();

#ifdef NDEBUG
    set(detail::slot_t::empty);
#endif
  }
  void weak_destroy() {
    visit([&](auto&& value) {
      using type = std::decay_t<decltype(value)>;
      value.~type();
    });

#ifndef NDEBUG
    set(detail::slot_t::empty);
#endif
  }
  detail::slot_t get() const noexcept {
    return slot_;
  }
  bool is(detail::slot_t const slot) const noexcept {
    return get() == slot;
  }
  void set(detail::slot_t const slot) {
    slot_ = slot;
  }
};
} // namespace util
} // namespace detail
} // namespace cti

#endif // CONTINUABLE_DETAIL_EXPECTED_HPP_INCLUDED__
<commit_msg>build fix<commit_after>
/*

                        /~` _  _ _|_. _     _ |_ | _
                        \_,(_)| | | || ||_|(_||_)|(/_

                    https://github.com/Naios/continuable
                                   v2.0.0

  Copyright(c) 2015 - 2017 Denis Blank <denis.blank at outlook dot com>

  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 CONTINUABLE_DETAIL_EXPECTED_HPP_INCLUDED__
#define CONTINUABLE_DETAIL_EXPECTED_HPP_INCLUDED__

#include <cassert>
#include <memory>
#include <type_traits>
#include <utility>

#include <continuable/continuable-api.hpp>
#include <continuable/detail/types.hpp>
#include <continuable/detail/util.hpp>

namespace cti {
namespace detail {
namespace util {
namespace detail {
enum class slot_t { empty, value, error };

template <typename T>
using storage_of_t = //
    std::aligned_storage_t<(sizeof(types::error_type) > sizeof(T)
                                ? sizeof(types::error_type)
                                : sizeof(T))>;

template <typename Base>
struct expected_move_base {
  constexpr expected_move_base() = default;

  expected_move_base(expected_move_base const&) = default;
  explicit expected_move_base(expected_move_base&& right) {
    Base& me = *static_cast<Base*>(this);
    Base& other = *static_cast<Base*>(&right);
    assert(!other.is_empty());

#ifndef _NDEBUG
    me.set(slot_t::empty);
#endif

    other.visit([&](auto&& value) {
      // ...
      me.init(std::move(value));
    });
    me.set(other.get());
    other.destroy();
  }
  expected_move_base& operator=(expected_move_base const&) = default;
  expected_move_base& operator=(expected_move_base&& right) {
    Base& me = *static_cast<Base*>(this);
    Base& other = *static_cast<Base*>(&right);
    assert(!other.is_empty());

    me.weak_destroy();

    other.visit([&](auto&& value) {
      // ...
      me.init(std::move(value));
    });
    me.set(other.get());
    other.destroy();
    return *this;
  }
};
template <typename Base, bool IsCopyable /*= true*/>
struct expected_copy_base : expected_move_base<Base> {
  constexpr expected_copy_base() = default;

  expected_copy_base(expected_copy_base&&) = default;
  explicit expected_copy_base(expected_copy_base const& right)
  // TODO noexcept(Base::is_nothrow_move_constructible)
  {
    Base& me = *static_cast<Base*>(this);
    Base const& other = *static_cast<Base const*>(&right);
    assert(!other.is_empty());

#ifndef _NDEBUG
    me.set(slot_t::empty);
#endif

    other.visit([&](auto&& value) {
      // ...
      me.init(std::move(value));
    });
    me.set(other.get());
  }
  expected_copy_base& operator=(expected_copy_base&&) = default;
  expected_copy_base& operator=(expected_copy_base const& right)
  // TODO  noexcept(Base::is_nothrow_move_constructible)
  {
    Base& me = *static_cast<Base*>(this);
    Base const& other = *static_cast<Base const*>(&right);
    assert(!other.is_empty());

    me.weak_destroy();

    other.visit([&](auto&& value) {
      // ...
      me.init(std::move(value));
    });
    me.set(other.get());
    return *this;
  }
};
template <typename Base /*, bool IsCopyable = false*/>
struct expected_copy_base<Base, false> : expected_move_base<Base> {
  constexpr expected_copy_base() = default;

  expected_copy_base(expected_copy_base const&) = default;
  explicit expected_copy_base(expected_copy_base&& right) = delete;
  expected_copy_base& operator=(expected_copy_base const&) = default;
  expected_copy_base& operator=(expected_copy_base&& right) = delete;
};
} // namespace detail

/// A class similar to the one in the expected proposal,
/// however it is capable of carrying an exception_ptr if
/// exceptions are used.
template <typename T>
class expected
    : detail::expected_copy_base<
          expected<T>, std::is_copy_constructible<types::error_type>::value &&
                           std::is_copy_constructible<T>::value> {

  template <typename>
  friend class expected;
  template <typename>
  friend struct detail::expected_move_base;
  template <typename, bool>
  friend struct detail::expected_copy_base;

  detail::storage_of_t<T> storage_;
  detail::slot_t slot_;

  template <typename V>
  expected(V&& value, detail::slot_t const slot) {
    using type = std::decay_t<decltype(value)>;
    new (&storage_) type(std::forward<V>(value));
    set(slot);
  }

public:
  constexpr expected() : slot_(detail::slot_t::empty) {
  }

  expected(expected const&) = default;
  expected(expected&&) = default;
  expected& operator=(expected const&) = default;
  expected& operator=(expected&&) = default;

  explicit expected(T value) //
      : expected(std::move(value), detail::slot_t::value) {
  }
  explicit expected(types::error_type error) //
      : expected(std::move(error), detail::slot_t::error) {
  }

  expected& operator=(T value) {
    set_value(std::move(value));
    return *this;
  }
  expected& operator=(types::error_type error) {
    set_error(std::move(error));
    return *this;
  }

  bool is_value() const noexcept {
    assert(!is_empty());
    return is(detail::slot_t::value);
  }
  bool is_exception() const noexcept {
    assert(!is_empty());
    return is(detail::slot_t::error);
  }

  explicit constexpr operator bool() const noexcept {
    return is_value();
  }

  void set_value(T value) {
    weak_destroy();
    init(std::move(value));
    set(detail::slot_t::value);
  }
  void set_error(types::error_type error) {
    weak_destroy();
    init(std::move(error));
    set(detail::slot_t::error);
  }

  T& get_value() noexcept {
    assert(is_value());
    return cast<T>();
  }
  T const& get_value() const noexcept {
    assert(is_value());
    return cast<T>();
  }
  T& get_exception() noexcept {
    assert(is_exception());
    return cast<types::error_type>();
  }
  T const& get_exception() const noexcept {
    assert(is_exception());
    return cast<types::error_type>();
  }

  T& operator*() noexcept {
    return get_value();
  }
  T const& operator*() const noexcept {
    return get_value();
  }

private:
  template <typename V>
  void visit(V&& visitor) {
    switch (slot_) {
      case detail::slot_t::value:
        return std::forward<V>(visitor)(cast<T>());
      case detail::slot_t::error:
        return std::forward<V>(visitor)(cast<types::error_type>());
      default:
        // We don't visit when there is no value
        break;
    }
  }
  template <typename V>
  void visit(V&& visitor) const {
    switch (slot_) {
      case detail::slot_t::value:
        return std::forward<V>(visitor)(cast<T>());
      case detail::slot_t::error:
        return std::forward<V>(visitor)(cast<types::error_type>());
      default:
        // We don't visit when there is no value
        break;
    }
  }

  bool is_empty() const noexcept {
    return is(detail::slot_t::empty);
  }

  template <typename V>
  V& cast() noexcept {
    assert(!is_empty());
    return *reinterpret_cast<V*>(&storage_);
  }
  template <typename V>
  V const& cast() const noexcept {
    assert(!is_empty());
    return *reinterpret_cast<V const*>(&storage_);
  }

  template <typename V>
  void init(V&& value) {
    assert(is_empty());
    using type = std::decay_t<decltype(value)>;
    auto storage = &storage_;
    new (storage) type(std::forward<V>(value));
  }
  void destroy() {
    weak_destroy();

#ifdef NDEBUG
    set(detail::slot_t::empty);
#endif
  }
  void weak_destroy() {
    visit([&](auto&& value) {
      using type = std::decay_t<decltype(value)>;
      value.~type();
    });

#ifndef NDEBUG
    set(detail::slot_t::empty);
#endif
  }
  detail::slot_t get() const noexcept {
    return slot_;
  }
  bool is(detail::slot_t const slot) const noexcept {
    return get() == slot;
  }
  void set(detail::slot_t const slot) {
    slot_ = slot;
  }
};
} // namespace util
} // namespace detail
} // namespace cti

#endif // CONTINUABLE_DETAIL_EXPECTED_HPP_INCLUDED__
<|endoftext|>


<commit_before>#include <sstream>
#include <iostream>
#include <set>

#include "contexts_corpus.hh"
#include "gzstream.hh"
#include "contexts_lexer.h"

#include <boost/tuple/tuple.hpp>

using namespace std;

//////////////////////////////////////////////////
// ContextsCorpus
//////////////////////////////////////////////////

void read_callback(const ContextsLexer::PhraseContextsType& new_contexts, void* extra) {
  assert(new_contexts.contexts.size() == new_contexts.counts.size());

  boost::tuple<ContextsCorpus*, BackoffGenerator*, map<string,int>* >* extra_pair
    = static_cast< boost::tuple<ContextsCorpus*, BackoffGenerator*, map<string,int>* >* >(extra);

  ContextsCorpus* corpus_ptr = extra_pair->get<0>();
  BackoffGenerator* backoff_gen = extra_pair->get<1>();
  map<string,int>* counts = extra_pair->get<2>();

  Document* doc(new Document());

  //cout << "READ: " << new_contexts.phrase << "\t";
  for (int i=0; i < new_contexts.contexts.size(); ++i) {
    int cache_word_count = corpus_ptr->m_dict.max();
    string context_str = corpus_ptr->m_dict.toString(new_contexts.contexts[i]);

    // filter out singleton contexts
    if (!counts->empty()) {
      map<string,int>::const_iterator find_it = counts->find(context_str);
      if (find_it == counts->end() || find_it->second == 1)
        continue;
    }

    WordID id = corpus_ptr->m_dict.Convert(context_str);
    if (cache_word_count != corpus_ptr->m_dict.max()) {
      corpus_ptr->m_backoff->terms_at_level(0)++;
      corpus_ptr->m_num_types++;
    }

    int count = new_contexts.counts[i];
    for (int j=0; j<count; ++j)
      doc->push_back(id);
    corpus_ptr->m_num_terms += count;

    // generate the backoff map
    if (backoff_gen) {
      int order = 1;
      WordID backoff_id = id;
      ContextsLexer::Context backedoff_context = new_contexts.contexts[i];
      while (true) {
        if (!corpus_ptr->m_backoff->has_backoff(backoff_id)) {
          //cerr << "Backing off from " << corpus_ptr->m_dict.Convert(backoff_id) << " to ";
          backedoff_context = (*backoff_gen)(backedoff_context);

          if (backedoff_context.empty()) {
            //cerr << "Nothing." << endl;
            (*corpus_ptr->m_backoff)[backoff_id] = -1;
            break;
          }

          if (++order > corpus_ptr->m_backoff->order())
            corpus_ptr->m_backoff->order(order);

          int cache_word_count = corpus_ptr->m_dict.max();
          int new_backoff_id = corpus_ptr->m_dict.Convert(backedoff_context);
          if (cache_word_count != corpus_ptr->m_dict.max())
            corpus_ptr->m_backoff->terms_at_level(order-1)++;

          //cerr << corpus_ptr->m_dict.Convert(new_backoff_id) << " ." << endl;

          backoff_id = ((*corpus_ptr->m_backoff)[backoff_id] = new_backoff_id);
        }
        else break;
      }
    }
    //cout << context_str << " (" << id << ") ||| C=" << count << " ||| ";
  }
  //cout << endl;

  if (!doc->empty()) {
    corpus_ptr->m_documents.push_back(doc);
    corpus_ptr->m_keys.push_back(new_contexts.phrase);
  }
}

void filter_callback(const ContextsLexer::PhraseContextsType& new_contexts, void* extra) {
  assert(new_contexts.contexts.size() == new_contexts.counts.size());

  map<string,int>* context_counts = (static_cast<map<string,int>*>(extra));

  for (int i=0; i < new_contexts.contexts.size(); ++i) {
    int count = new_contexts.counts[i];
    pair<map<string,int>::iterator,bool> result
      = context_counts->insert(make_pair(Dict::toString(new_contexts.contexts[i]),count));
    if (!result.second)
      result.first->second += count;
  }
}

unsigned ContextsCorpus::read_contexts(const string &filename,
                                       BackoffGenerator* backoff_gen_ptr,
                                       bool filter_singeltons) {
  map<string,int> counts;
  if (filter_singeltons) {
    cerr << "--- Filtering singleton contexts ---" << endl;
    igzstream in(filename.c_str());
    ContextsLexer::ReadContexts(&in, filter_callback, &counts);
  }

  m_num_terms = 0;
  m_num_types = 0;

  igzstream in(filename.c_str());
  boost::tuple<ContextsCorpus*, BackoffGenerator*, map<string,int>* > extra_pair(this,backoff_gen_ptr,&counts);
  ContextsLexer::ReadContexts(&in, read_callback, &extra_pair);

  //m_num_types = m_dict.max();

  cerr << "Read backoff with order " << m_backoff->order() << "\n";
  for (int o=0; o<m_backoff->order(); o++)
    cerr << "  Terms at " << o << " = " << m_backoff->terms_at_level(o) << endl;
  cerr << endl;

  return m_documents.size();
}
<commit_msg>Added singleton filter.<commit_after>#include <sstream>
#include <iostream>
#include <set>

#include "contexts_corpus.hh"
#include "gzstream.hh"
#include "contexts_lexer.h"

#include <boost/tuple/tuple.hpp>

using namespace std;

//////////////////////////////////////////////////
// ContextsCorpus
//////////////////////////////////////////////////

void read_callback(const ContextsLexer::PhraseContextsType& new_contexts, void* extra) {
  assert(new_contexts.contexts.size() == new_contexts.counts.size());

  boost::tuple<ContextsCorpus*, BackoffGenerator*, map<string,int>* >* extra_pair
    = static_cast< boost::tuple<ContextsCorpus*, BackoffGenerator*, map<string,int>* >* >(extra);

  ContextsCorpus* corpus_ptr = extra_pair->get<0>();
  BackoffGenerator* backoff_gen = extra_pair->get<1>();
  map<string,int>* counts = extra_pair->get<2>();

  Document* doc(new Document());

  //cout << "READ: " << new_contexts.phrase << "\t";
  for (int i=0; i < new_contexts.contexts.size(); ++i) {
    int cache_word_count = corpus_ptr->m_dict.max();
    string context_str = corpus_ptr->m_dict.toString(new_contexts.contexts[i]);

    // filter out singleton contexts
    if (!counts->empty()) {
      map<string,int>::const_iterator find_it = counts->find(context_str);
      if (find_it == counts->end() || find_it->second < 5)
        continue;
    }

    WordID id = corpus_ptr->m_dict.Convert(context_str);
    if (cache_word_count != corpus_ptr->m_dict.max()) {
      corpus_ptr->m_backoff->terms_at_level(0)++;
      corpus_ptr->m_num_types++;
    }

    int count = new_contexts.counts[i];
    for (int j=0; j<count; ++j)
      doc->push_back(id);
    corpus_ptr->m_num_terms += count;

    // generate the backoff map
    if (backoff_gen) {
      int order = 1;
      WordID backoff_id = id;
      ContextsLexer::Context backedoff_context = new_contexts.contexts[i];
      while (true) {
        if (!corpus_ptr->m_backoff->has_backoff(backoff_id)) {
          //cerr << "Backing off from " << corpus_ptr->m_dict.Convert(backoff_id) << " to ";
          backedoff_context = (*backoff_gen)(backedoff_context);

          if (backedoff_context.empty()) {
            //cerr << "Nothing." << endl;
            (*corpus_ptr->m_backoff)[backoff_id] = -1;
            break;
          }

          if (++order > corpus_ptr->m_backoff->order())
            corpus_ptr->m_backoff->order(order);

          int cache_word_count = corpus_ptr->m_dict.max();
          int new_backoff_id = corpus_ptr->m_dict.Convert(backedoff_context);
          if (cache_word_count != corpus_ptr->m_dict.max())
            corpus_ptr->m_backoff->terms_at_level(order-1)++;

          //cerr << corpus_ptr->m_dict.Convert(new_backoff_id) << " ." << endl;

          backoff_id = ((*corpus_ptr->m_backoff)[backoff_id] = new_backoff_id);
        }
        else break;
      }
    }
    //cout << context_str << " (" << id << ") ||| C=" << count << " ||| ";
  }
  //cout << endl;

  if (!doc->empty()) {
    corpus_ptr->m_documents.push_back(doc);
    corpus_ptr->m_keys.push_back(new_contexts.phrase);
  }
}

void filter_callback(const ContextsLexer::PhraseContextsType& new_contexts, void* extra) {
  assert(new_contexts.contexts.size() == new_contexts.counts.size());

  map<string,int>* context_counts = (static_cast<map<string,int>*>(extra));

  for (int i=0; i < new_contexts.contexts.size(); ++i) {
    int count = new_contexts.counts[i];
    pair<map<string,int>::iterator,bool> result
      = context_counts->insert(make_pair(Dict::toString(new_contexts.contexts[i]),count));
    if (!result.second)
      result.first->second += count;
  }
}

unsigned ContextsCorpus::read_contexts(const string &filename,
                                       BackoffGenerator* backoff_gen_ptr,
                                       bool filter_singeltons) {
  map<string,int> counts;
  if (filter_singeltons) {
    cerr << "--- Filtering singleton contexts ---" << endl;
    igzstream in(filename.c_str());
    ContextsLexer::ReadContexts(&in, filter_callback, &counts);
  }

  m_num_terms = 0;
  m_num_types = 0;

  igzstream in(filename.c_str());
  boost::tuple<ContextsCorpus*, BackoffGenerator*, map<string,int>* > extra_pair(this,backoff_gen_ptr,&counts);
  ContextsLexer::ReadContexts(&in, read_callback, &extra_pair);

  //m_num_types = m_dict.max();

  cerr << "Read backoff with order " << m_backoff->order() << "\n";
  for (int o=0; o<m_backoff->order(); o++)
    cerr << "  Terms at " << o << " = " << m_backoff->terms_at_level(o) << endl;
  cerr << endl;

  return m_documents.size();
}
<|endoftext|>


<commit_before>#include "blackhole/detail/procname.hpp"

#include <cstring>

#include "blackhole/cpp17/string_view.hpp"

#ifdef __linux__
#   include <sys/types.h>
#elif __APPLE__
#   include <libproc.h>
#endif

#include <unistd.h>

namespace blackhole {
inline namespace v1 {
namespace detail {

namespace {

auto procname(pid_t pid) -> cpp17::string_view {
#ifdef __linux__
    return cpp17::string_view(program_invocation_short_name, ::strlen(program_invocation_short_name));
#elif __APPLE__
    static char path[PROC_PIDPATHINFO_MAXSIZE];

    if (::proc_name(pid, path, sizeof(path)) > 0) {
        return cpp17::string_view(path, ::strlen(path));
    } else {
        const auto nwritten = ::snprintf(path, sizeof(path), "%d", pid);
        return cpp17::string_view(path, static_cast<std::size_t>(nwritten));
    }
#endif
}

}  // namespace

auto procname() -> cpp17::string_view {
    static const cpp17::string_view name = procname(::getpid());
    return name;
}

}  // namespace detail
}  // namespace v1
}  // namespace blackhole
<commit_msg>style(): use proper include order<commit_after>#include "blackhole/detail/procname.hpp"

#ifdef __linux__
#   include <sys/types.h>
#elif __APPLE__
#   include <libproc.h>
#endif

#include <unistd.h>

#include <cstring>

#include "blackhole/cpp17/string_view.hpp"

namespace blackhole {
inline namespace v1 {
namespace detail {

namespace {

auto procname(pid_t pid) -> cpp17::string_view {
#ifdef __linux__
    return cpp17::string_view(program_invocation_short_name, ::strlen(program_invocation_short_name));
#elif __APPLE__
    static char path[PROC_PIDPATHINFO_MAXSIZE];

    if (::proc_name(pid, path, sizeof(path)) > 0) {
        return cpp17::string_view(path, ::strlen(path));
    } else {
        const auto nwritten = ::snprintf(path, sizeof(path), "%d", pid);
        return cpp17::string_view(path, static_cast<std::size_t>(nwritten));
    }
#endif
}

}  // namespace

auto procname() -> cpp17::string_view {
    static const cpp17::string_view name = procname(::getpid());
    return name;
}

}  // namespace detail
}  // namespace v1
}  // namespace blackhole
<|endoftext|>


<commit_before>/*
 * FixedContextCategory.hh
 *
 * Copyright 2001, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
 * Copyright 2001, Bastiaan Bakker. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#ifndef _LOG4CPP_FIXEDCONTEXTCATEGORY_HH
#define _LOG4CPP_FIXEDCONTEXTCATEGORY_HH

#include "log4cpp/Category.hh"

namespace log4cpp {

    class FixedContextCategory : public Category {

        /**
         * This Category subclass replaces the NDC field in LoggingEvents with
         * a fixed context string. All handling of Appenders, etc. is delgated
         * to the 'normal' Category with the same name. Its intended use is
         * for object instances that serve a single client: they contruct a
         * FixedContextCategory with the client identifier as context.
         * Unlike with regular Category instances one has to explicitly create
         * FixedContextCategory instances using the constructor. This also
         * implies one has to take cake of destruction of the instance as well.
         * @since 0.2.4
         **/
        public:

        /**
         * Constructor
         * @param name the fully qualified name of this Categories delegate
         * Category.
         * @param context the context to fill the NDC field of LoggingEvents
         * with.
         * @param priority the priority for this Category. Defaults to
         * Priority::NOTSET
         **/
        FixedContextCategory(const std::string& name,
                             const std::string& context);

        /**
         * Destructor for Category.
         **/
        virtual ~FixedContextCategory();

        /**
         * Set the context string used as NDC.
         * @param context the context string
         **/
        virtual void setContext(const string& context);

        /**
         * Return the context string used as NDC.
         * @return the context string.
         **/
        virtual std::string getContext() const;

        /**
         * Returns the assigned Priority, if any, for this Category.
         * @return Priority - the assigned Priority, can be Priority::NOTSET
         **/
        virtual Priority::Value getPriority() const;

        /**
         * Starting from this Category, search the category hierarchy for a
         * set priority and return it. Otherwise, return the priority
         *  of the root category.
         *
         *
The Category class is designed so that this method executes as
         * quickly as possible.
         **/
        virtual Priority::Value getChainedPriority() const;

        /**
         * Sets an Appender for this Category.
         * This method passes ownership from the caller to the Category.
         * @param appender The Appender this category has to log to.
         **/
        virtual void setAppender(Appender* appender);

        /**
         * Sets an Appender for this Category.
         * This method does not pass ownership from the caller to the Category.
         * @param appender The Appender this category has to log to.
         **/
        virtual void setAppender(Appender& appender);

        /**
         * Returns the Appender for this Category, or NULL if no Appender has
         * been set.
         * @returns The Appender.
         **/
        virtual Appender* getAppender() const;

        /**
         * Removes all appenders set for this Category. Currently a Category
         * can have only one appender, but this may change in the future.
         **/
        virtual void removeAllAppenders();

        /**
         * Returns true if the Category owns the Appender. In that case the
         * Category destructor will delete the Appender.
         **/
        virtual bool ownsAppender() const;

        /**
         * Call the appenders in the hierarchy starting at
         *  this.  If no appenders could be found, emit a
         * warning.
         *
         *
This method always calls all the appenders inherited form the
         * hierracy circumventing any evaluation of whether to log or not to
         * log the particular log request.
         *
         * @param LoggingEvent the event to log.
         **/
        virtual void callAppenders(const LoggingEvent& event);

        /**
         * Set the additivity flag for this Category instance.
         **/
        virtual void setAdditivity(bool additivity);

        /**
         * Returns the additivity flag for this Category instance.
         **/
        virtual bool getAdditivity() const;

       protected:

         /**
         * Unconditionally log a message with the specified priority.
         * @param priority The priority of this log message.
         * @param message string to write in the log file
         **/
        virtual void _logUnconditionally2(Priority::Value priority,
                                          const std::string& message);

        private:

        /**
         * The delegate category of this FixedContextCategory.
         **/
        Category& _delegate;

        /** The context of this FixedContextCategory. */
         std::string _context;

    };

}
#endif // _LOG4CPP_FIXEDCONTEXTCATEGORY_HH
<commit_msg>Moved the class description to the correct place.<commit_after>/*
 * FixedContextCategory.hh
 *
 * Copyright 2001, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
 * Copyright 2001, Bastiaan Bakker. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#ifndef _LOG4CPP_FIXEDCONTEXTCATEGORY_HH
#define _LOG4CPP_FIXEDCONTEXTCATEGORY_HH

#include "log4cpp/Category.hh"

namespace log4cpp {

    /**
     * This Category subclass replaces the NDC field in LoggingEvents with
     * a fixed context string. All handling of Appenders, etc. is delgated
     * to the 'normal' Category with the same name. Its intended use is
     * for object instances that serve a single client: they contruct a
     * FixedContextCategory with the client identifier as context.
     * Unlike with regular Category instances one has to explicitly create
     * FixedContextCategory instances using the constructor. This also
     * implies one has to take cake of destruction of the instance as well.
     * @since 0.2.4
     **/
    class FixedContextCategory : public Category {

        public:

        /**
         * Constructor
         * @param name the fully qualified name of this Categories delegate
         * Category.
         * @param context the context to fill the NDC field of LoggingEvents
         * with.
         * @param priority the priority for this Category. Defaults to
         * Priority::NOTSET
         **/
        FixedContextCategory(const std::string& name,
                             const std::string& context);

        /**
         * Destructor for Category.
         **/
        virtual ~FixedContextCategory();

        /**
         * Set the context string used as NDC.
         * @param context the context string
         **/
        virtual void setContext(const string& context);

        /**
         * Return the context string used as NDC.
         * @return the context string.
         **/
        virtual std::string getContext() const;

        /**
         * Returns the assigned Priority, if any, for this Category.
         * @return Priority - the assigned Priority, can be Priority::NOTSET
         **/
        virtual Priority::Value getPriority() const;

        /**
         * Starting from this Category, search the category hierarchy for a
         * set priority and return it. Otherwise, return the priority
         *  of the root category.
         *
         *
The Category class is designed so that this method executes as
         * quickly as possible.
         **/
        virtual Priority::Value getChainedPriority() const;

        /**
         * Sets an Appender for this Category.
         * This method passes ownership from the caller to the Category.
         * @param appender The Appender this category has to log to.
         **/
        virtual void setAppender(Appender* appender);

        /**
         * Sets an Appender for this Category.
         * This method does not pass ownership from the caller to the Category.
         * @param appender The Appender this category has to log to.
         **/
        virtual void setAppender(Appender& appender);

        /**
         * Returns the Appender for this Category, or NULL if no Appender has
         * been set.
         * @returns The Appender.
         **/
        virtual Appender* getAppender() const;

        /**
         * Removes all appenders set for this Category. Currently a Category
         * can have only one appender, but this may change in the future.
         **/
        virtual void removeAllAppenders();

        /**
         * Returns true if the Category owns the Appender. In that case the
         * Category destructor will delete the Appender.
         **/
        virtual bool ownsAppender() const;

        /**
         * Call the appenders in the hierarchy starting at
         *  this.  If no appenders could be found, emit a
         * warning.
         *
         *
This method always calls all the appenders inherited form the
         * hierracy circumventing any evaluation of whether to log or not to
         * log the particular log request.
         *
         * @param LoggingEvent the event to log.
         **/
        virtual void callAppenders(const LoggingEvent& event);

        /**
         * Set the additivity flag for this Category instance.
         **/
        virtual void setAdditivity(bool additivity);

        /**
         * Returns the additivity flag for this Category instance.
         **/
        virtual bool getAdditivity() const;

       protected:

         /**
         * Unconditionally log a message with the specified priority.
         * @param priority The priority of this log message.
         * @param message string to write in the log file
         **/
        virtual void _logUnconditionally2(Priority::Value priority,
                                          const std::string& message);

        private:

        /**
         * The delegate category of this FixedContextCategory.
         **/
        Category& _delegate;

        /** The context of this FixedContextCategory. */
         std::string _context;

    };

}
#endif // _LOG4CPP_FIXEDCONTEXTCATEGORY_HH
<|endoftext|>