<commit_before>
// Copyright 2015 XLGAMES Inc.
//
// Distributed under the MIT License (See
// accompanying file "LICENSE" or the website
// http://www.opensource.org/licenses/mit-license.php)

#include "XLELayerUtils.h"
#include "../../Tools/ToolsRig/VisualisationUtils.h"
#include "../../Tools/EntityInterface/EntityInterface.h"
#include "../../Tools/GuiLayer/MarshalString.h"
#include "../../Tools/GuiLayer/NativeEngineDevice.h"
#include "../../RenderCore/Techniques/TechniqueUtils.h"
#include "../../Math/Transformations.h"
#include "../../ConsoleRig/LogStartup.h"
#include "../../ConsoleRig/GlobalServices.h"

using namespace Sce::Atf;
using namespace Sce::Atf::Applications;

namespace XLEBridgeUtils
{
    public interface class INativeDocumentAdapter
    {
    public:
        property EntityInterface::DocumentId NativeDocumentId { EntityInterface::DocumentId get(); }
    };

    GUILayer::CameraDescWrapper^ Utils::AsCameraDesc(Sce::Atf::Rendering::Camera^ camera)
    {
        ToolsRig::VisCameraSettings visCam;
        visCam._position = AsFloat3(camera->WorldEye);
        visCam._focus = AsFloat3(camera->WorldLookAtPoint);
        visCam._verticalFieldOfView = camera->YFov * 180.f / gPI;
        visCam._nearClip = camera->NearZ;
        visCam._farClip = camera->FarZ;
        return gcnew GUILayer::CameraDescWrapper(visCam);
    }

    GUILayer::IntersectionTestContextWrapper^
        Utils::CreateIntersectionTestContext(
            GUILayer::EngineDevice^ engineDevice,
            GUILayer::TechniqueContextWrapper^ techniqueContext,
            Sce::Atf::Rendering::Camera^ camera,
            unsigned viewportWidth, unsigned viewportHeight)
    {
        return GUILayer::EditorInterfaceUtils::CreateIntersectionTestContext(
            engineDevice, techniqueContext,
            AsCameraDesc(camera), viewportWidth, viewportHeight);
    }

    Sce::Atf::VectorMath::Matrix4F^ Utils::MakeFrustumMatrix(
        Sce::Atf::Rendering::Camera^ camera,
        System::Drawing::RectangleF rectangle,
        System::Drawing::Size viewportSize)
    {
            //  Given a camera and rectangle, calculate a
            //  frustum matrix that will represents that area.
        System::Drawing::RectangleF fRect(
            rectangle.Left / float(viewportSize.Width), rectangle.Top / float(viewportSize.Height),
            rectangle.Width / float(viewportSize.Width), rectangle.Height / float(viewportSize.Height));

            // skew XY in the projection matrix to suit the rectangle
        float sx = 1.f / (fRect.Width);
        float sy = 1.f / (fRect.Height);
        float tx = -(2.f * .5f * (fRect.Left + fRect.Right) - 1.f) * sx;
        float ty = -(-2.f * .5f * (fRect.Top + fRect.Bottom) + 1.f) * sy;

        Float4x4 rectangleAdj = MakeFloat4x4(
            sx, 0.f, 0.f,  tx,
            0.f,  sy, 0.f,  ty,
            0.f, 0.f, 1.f, 0.f,
            0.f, 0.f, 0.f, 1.f);

        std::unique_ptr<Float4x4> worldToProjPtr;
        worldToProjPtr.reset((Float4x4*)GUILayer::EditorInterfaceUtils::CalculateWorldToProjection(
            AsCameraDesc(camera), viewportSize.Width / float(viewportSize.Height)));

        auto worldToProj = Combine(*worldToProjPtr, rectangleAdj);

            // note -- forcing a transpose here!
        return gcnew Sce::Atf::VectorMath::Matrix4F(
            worldToProj(0,0), worldToProj(1,0), worldToProj(2,0), worldToProj(3,0),
            worldToProj(0,1), worldToProj(1,1), worldToProj(2,1), worldToProj(3,1),
            worldToProj(0,2), worldToProj(1,2), worldToProj(2,2), worldToProj(3,2),
            worldToProj(0,3), worldToProj(1,3), worldToProj(2,3), worldToProj(3,3));
    }

    DomChangeInspector::DomChangeInspector(IContextRegistry^ contextRegistry)
            : m_contextRegistry(contextRegistry)
    {
        m_observableContext = nullptr;
        contextRegistry->ActiveContextChanged +=
            gcnew EventHandler(this, &DomChangeInspector::ContextRegistry_ActiveContextChanged);
    }

    void DomChangeInspector::ContextRegistry_ActiveContextChanged(System::Object^ sender, EventArgs^ e)
    {
        using namespace LevelEditorCore;
        IGameContext^ game = m_contextRegistry->GetActiveContext<IGameContext^>();
        auto observableContext = Sce::Atf::Adaptation::Adapters::As<IObservableContext^>(game);
        if (m_observableContext == observableContext) return;
        if (m_observableContext != nullptr) {
            m_observableContext->ItemInserted -= gcnew EventHandler<ItemInsertedEventArgs<System::Object^>^>(this, &DomChangeInspector::m_observableContext_ItemInserted);
            m_observableContext->ItemRemoved -= gcnew EventHandler<ItemRemovedEventArgs<System::Object^>^>(this, &DomChangeInspector::m_observableContext_ItemRemoved);
            m_observableContext->ItemChanged -= gcnew EventHandler<Sce::Atf::ItemChangedEventArgs<System::Object^>^>(this, &DomChangeInspector::m_observableContext_ItemChanged);
            m_observableContext->Reloaded -= gcnew EventHandler(this, &DomChangeInspector::m_observableContext_Reloaded);
        }
        m_observableContext = observableContext;

        if (m_observableContext != nullptr) {
            m_observableContext->ItemInserted += gcnew EventHandler<ItemInsertedEventArgs<System::Object^>^>(this, &DomChangeInspector::m_observableContext_ItemInserted);
            m_observableContext->ItemRemoved += gcnew EventHandler<ItemRemovedEventArgs<System::Object^>^>(this, &DomChangeInspector::m_observableContext_ItemRemoved);
            m_observableContext->ItemChanged += gcnew EventHandler<Sce::Atf::ItemChangedEventArgs<System::Object^>^>(this, &DomChangeInspector::m_observableContext_ItemChanged);
            m_observableContext->Reloaded += gcnew EventHandler(this, &DomChangeInspector::m_observableContext_Reloaded);
        }
        OnActiveContextChanged(sender);
    }

///////////////////////////////////////////////////////////////////////////////////////////////////

    namespace Internal
    {
        static Sce::Atf::OutputMessageType AsOutputMessageType(ConsoleRig::LogLevel level)
        {
            switch (level) {
            default:
            case ConsoleRig::LogLevel::Fatal:
            case ConsoleRig::LogLevel::Error: return Sce::Atf::OutputMessageType::Error;
            case ConsoleRig::LogLevel::Warning: return Sce::Atf::OutputMessageType::Warning;
            case ConsoleRig::LogLevel::Info:
            case ConsoleRig::LogLevel::Verbose: return Sce::Atf::OutputMessageType::Info;
            }
        }

        class LoggingRedirectHelper : public ConsoleRig::LogCallback
        {
        public:
            virtual void OnDispatch(ConsoleRig::LogLevel level, const std::string& str)
            {
                if (!str.empty()) {
                    auto s = clix::marshalString<clix::E_UTF8>(str);
                        // we must append a new line if one isn't already there!
                        // this falls in line with the behaviour of easylogging++,
                        // which will automatically add a new line at the end of each
                        // message.
                    if (!s->EndsWith(System::Environment::NewLine))
                        s += System::Environment::NewLine;
                    Sce::Atf::Outputs::Write(AsOutputMessageType(level), s);
                }
            }

            LoggingRedirectHelper() {}
            ~LoggingRedirectHelper() {}
        };
    }

    LoggingRedirect::LoggingRedirect()
    {
        _helper = std::make_shared<Internal::LoggingRedirectHelper>();
        _helper->Enable();
    }

    LoggingRedirect::~LoggingRedirect() {}
    LoggingRedirect::!LoggingRedirect() {}

    static ConsoleRig::AttachRef<ConsoleRig::GlobalServices> s_attachRef;

    void Utils::AttachLibrary(GUILayer::EngineDevice^ device)
    {
        if (!s_attachRef) {
            s_attachRef = device->GetNative().GetGlobalServices()->Attach();
        }
    }

    void Utils::DetachLibrary()
    {
        s_attachRef.Detach();
    }

}

<commit_msg>Delayed logging to level editor window - this prevents a problem where windows messages (like WM_PAINT) were being handled in the middle of a logging dispatch operation - it prevents a problem that was resulting in a call to std::abort() sometimes<commit_after>
// Copyright 2015 XLGAMES Inc.
//
// Distributed under the MIT License (See
// accompanying file "LICENSE" or the website
// http://www.opensource.org/licenses/mit-license.php)

#include "XLELayerUtils.h"
#include "../../Tools/ToolsRig/VisualisationUtils.h"
#include "../../Tools/EntityInterface/EntityInterface.h"
#include "../../Tools/GuiLayer/MarshalString.h"
#include "../../Tools/GuiLayer/NativeEngineDevice.h"
#include "../../RenderCore/Techniques/TechniqueUtils.h"
#include "../../Math/Transformations.h"
#include "../../ConsoleRig/LogStartup.h"
#include "../../ConsoleRig/GlobalServices.h"

using namespace Sce::Atf;
using namespace Sce::Atf::Applications;

namespace XLEBridgeUtils
{
    public interface class INativeDocumentAdapter
    {
    public:
        property EntityInterface::DocumentId NativeDocumentId { EntityInterface::DocumentId get(); }
    };

    GUILayer::CameraDescWrapper^ Utils::AsCameraDesc(Sce::Atf::Rendering::Camera^ camera)
    {
        ToolsRig::VisCameraSettings visCam;
        visCam._position = AsFloat3(camera->WorldEye);
        visCam._focus = AsFloat3(camera->WorldLookAtPoint);
        visCam._verticalFieldOfView = camera->YFov * 180.f / gPI;
        visCam._nearClip = camera->NearZ;
        visCam._farClip = camera->FarZ;
        return gcnew GUILayer::CameraDescWrapper(visCam);
    }

    GUILayer::IntersectionTestContextWrapper^
        Utils::CreateIntersectionTestContext(
            GUILayer::EngineDevice^ engineDevice,
            GUILayer::TechniqueContextWrapper^ techniqueContext,
            Sce::Atf::Rendering::Camera^ camera,
            unsigned viewportWidth, unsigned viewportHeight)
    {
        return GUILayer::EditorInterfaceUtils::CreateIntersectionTestContext(
            engineDevice, techniqueContext,
            AsCameraDesc(camera), viewportWidth, viewportHeight);
    }

    Sce::Atf::VectorMath::Matrix4F^ Utils::MakeFrustumMatrix(
        Sce::Atf::Rendering::Camera^ camera,
        System::Drawing::RectangleF rectangle,
        System::Drawing::Size viewportSize)
    {
            //  Given a camera and rectangle, calculate a
            //  frustum matrix that will represents that area.
        System::Drawing::RectangleF fRect(
            rectangle.Left / float(viewportSize.Width), rectangle.Top / float(viewportSize.Height),
            rectangle.Width / float(viewportSize.Width), rectangle.Height / float(viewportSize.Height));

            // skew XY in the projection matrix to suit the rectangle
        float sx = 1.f / (fRect.Width);
        float sy = 1.f / (fRect.Height);
        float tx = -(2.f * .5f * (fRect.Left + fRect.Right) - 1.f) * sx;
        float ty = -(-2.f * .5f * (fRect.Top + fRect.Bottom) + 1.f) * sy;

        Float4x4 rectangleAdj = MakeFloat4x4(
            sx, 0.f, 0.f,  tx,
            0.f,  sy, 0.f,  ty,
            0.f, 0.f, 1.f, 0.f,
            0.f, 0.f, 0.f, 1.f);

        std::unique_ptr<Float4x4> worldToProjPtr;
        worldToProjPtr.reset((Float4x4*)GUILayer::EditorInterfaceUtils::CalculateWorldToProjection(
            AsCameraDesc(camera), viewportSize.Width / float(viewportSize.Height)));

        auto worldToProj = Combine(*worldToProjPtr, rectangleAdj);

            // note -- forcing a transpose here!
        return gcnew Sce::Atf::VectorMath::Matrix4F(
            worldToProj(0,0), worldToProj(1,0), worldToProj(2,0), worldToProj(3,0),
            worldToProj(0,1), worldToProj(1,1), worldToProj(2,1), worldToProj(3,1),
            worldToProj(0,2), worldToProj(1,2), worldToProj(2,2), worldToProj(3,2),
            worldToProj(0,3), worldToProj(1,3), worldToProj(2,3), worldToProj(3,3));
    }

    DomChangeInspector::DomChangeInspector(IContextRegistry^ contextRegistry)
            : m_contextRegistry(contextRegistry)
    {
        m_observableContext = nullptr;
        contextRegistry->ActiveContextChanged +=
            gcnew EventHandler(this, &DomChangeInspector::ContextRegistry_ActiveContextChanged);
    }

    void DomChangeInspector::ContextRegistry_ActiveContextChanged(System::Object^ sender, EventArgs^ e)
    {
        using namespace LevelEditorCore;
        IGameContext^ game = m_contextRegistry->GetActiveContext<IGameContext^>();
        auto observableContext = Sce::Atf::Adaptation::Adapters::As<IObservableContext^>(game);
        if (m_observableContext == observableContext) return;
        if (m_observableContext != nullptr) {
            m_observableContext->ItemInserted -= gcnew EventHandler<ItemInsertedEventArgs<System::Object^>^>(this, &DomChangeInspector::m_observableContext_ItemInserted);
            m_observableContext->ItemRemoved -= gcnew EventHandler<ItemRemovedEventArgs<System::Object^>^>(this, &DomChangeInspector::m_observableContext_ItemRemoved);
            m_observableContext->ItemChanged -= gcnew EventHandler<Sce::Atf::ItemChangedEventArgs<System::Object^>^>(this, &DomChangeInspector::m_observableContext_ItemChanged);
            m_observableContext->Reloaded -= gcnew EventHandler(this, &DomChangeInspector::m_observableContext_Reloaded);
        }
        m_observableContext = observableContext;

        if (m_observableContext != nullptr) {
            m_observableContext->ItemInserted += gcnew EventHandler<ItemInsertedEventArgs<System::Object^>^>(this, &DomChangeInspector::m_observableContext_ItemInserted);
            m_observableContext->ItemRemoved += gcnew EventHandler<ItemRemovedEventArgs<System::Object^>^>(this, &DomChangeInspector::m_observableContext_ItemRemoved);
            m_observableContext->ItemChanged += gcnew EventHandler<Sce::Atf::ItemChangedEventArgs<System::Object^>^>(this, &DomChangeInspector::m_observableContext_ItemChanged);
            m_observableContext->Reloaded += gcnew EventHandler(this, &DomChangeInspector::m_observableContext_Reloaded);
        }
        OnActiveContextChanged(sender);
    }

///////////////////////////////////////////////////////////////////////////////////////////////////

    namespace Internal
    {
        static Sce::Atf::OutputMessageType AsOutputMessageType(ConsoleRig::LogLevel level)
        {
            switch (level) {
            default:
            case ConsoleRig::LogLevel::Fatal:
            case ConsoleRig::LogLevel::Error: return Sce::Atf::OutputMessageType::Error;
            case ConsoleRig::LogLevel::Warning: return Sce::Atf::OutputMessageType::Warning;
            case ConsoleRig::LogLevel::Info:
            case ConsoleRig::LogLevel::Verbose: return Sce::Atf::OutputMessageType::Info;
            }
        }

        ref class LoggingRedirectDelegate
        {
        public:
            static void Callback(Object^ obj)
            {
                LoggingRedirectDelegate^ del = (LoggingRedirectDelegate^)obj;
                Sce::Atf::Outputs::Write(del->Type, del->Msg);
            }

            property System::String^ Msg;
            property Sce::Atf::OutputMessageType Type;
        };

        class LoggingRedirectHelper : public ConsoleRig::LogCallback
        {
        public:
            virtual void OnDispatch(ConsoleRig::LogLevel level, const std::string& str)
            {
                    // Note -- it is not safe to handle this message immediately
                    //  Calling Sce::Atf::Outputs::Write can invoke a windows events (such as WM_PAINT)
                    //  This is a problem because we can enter this function at any time.
                    //  If we are currently in the middle of one paint operation, this can effectively
                    //  cause us to paint recursively.
                    //
                    //  But there's another worse issue. This thread will currently have the logging mutex
                    //  locked. So if any paint or other operations cause a log operation, then the logging
                    //  system will attempt a recursive lock on it's mutex -- which results in an exception
                    //  and ends up causing a call to std::abort()
                    //
                    // We have to delay handling the message by invoking a delegate in the main message loop.
                    // However; note that this could cause the log messages to end up in the wrong order
                    // (if we are getting log messages from different sources)

                if (!str.empty()) {
                    auto s = clix::marshalString<clix::E_UTF8>(str);
                        // We must append a new line if one isn't already there!
                        // this falls in line with the behaviour of easylogging++,
                        // which will automatically add a new line at the end of each
                        // message.
                    if (!s->EndsWith(System::Environment::NewLine))
                        s += System::Environment::NewLine;

                    LoggingRedirectDelegate^ del = gcnew LoggingRedirectDelegate;
                    del->Msg = s;
                    del->Type = AsOutputMessageType(level);
                    _context->Post(
                        gcnew System::Threading::SendOrPostCallback(&LoggingRedirectDelegate::Callback),
                        del);
                }
            }

            LoggingRedirectHelper()
            {
                    // note -- expecting to be called from the main thread.
                _context = System::Threading::SynchronizationContext::Current;
            }

            ~LoggingRedirectHelper() {}

        protected:
            gcroot<System::Threading::SynchronizationContext^> _context;
        };
    }

    LoggingRedirect::LoggingRedirect()
    {
        _helper = std::make_shared<Internal::LoggingRedirectHelper>();
        _helper->Enable();
    }

    LoggingRedirect::~LoggingRedirect() {}
    LoggingRedirect::!LoggingRedirect() {}

    static ConsoleRig::AttachRef<ConsoleRig::GlobalServices> s_attachRef;

    void Utils::AttachLibrary(GUILayer::EngineDevice^ device)
    {
        if (!s_attachRef) {
            s_attachRef = device->GetNative().GetGlobalServices()->Attach();
        }
    }

    void Utils::DetachLibrary()
    {
        s_attachRef.Detach();
    }

}

<|endoftext|>


<commit_before>#include "TTExtensionLoader.h"
#include "TTFoundation.h"
#include "TTEnvironment.h"
#include <vector>
#include <string>

// The organization here is as follows :
// 1. TTLoadExtensions is called and selects the paths
//    where the extensions should be searched, in order.
//    As soon as extensions are found in a folder, the search stops.
// 2. Platforms are defined as classes :
//     - UnixCommon contains generic data for Unix-like systems
//     - OS X, Linux, Android, Windows are the available platforms.
// 3. Each platform has a specific way to list what's in a folder :
//    The relevant method is Platform::loadClassesFromFolder
// 4. The algorithm to load a file is generic : loadClass. The
//    platform provides the algorithm with functions to get a handle.

using namespace std;
using StringVector = vector<string>;

// Utility compile-time functions to work with string constants.
// Except on windows, where constexpr will only be in VS2015 (hopefully...)
// This would allow to shrink this file size by a small half.
#if !defined(TT_PLATFORM_WIN)
template <typename T, size_t n>
constexpr size_t array_length(const T (&)[n])
{ return n; }

template <typename T>
constexpr size_t string_length(T&& t)
{ return array_length(forward<T&&>(t)) - 1; }

template<typename T>
constexpr bool string_empty(T&& t)
{ return string_length(forward<T&&>(t)) == 0; }
#endif

template<typename OS>
// Returns true if the filename (ex. : AudioEngine.ttdylib)
// is a correct extension filename for the platform we're in.
bool isExtensionFilename(const string& filename)
{
	auto res = mismatch(begin(OS::extensionPrefix),
						end(OS::extensionPrefix),
						begin(filename));

	if (string_empty(OS::extensionPrefix) || res.first == (end(OS::extensionPrefix)))
	{
		if(filename.length() >= string_length(OS::extensionSuffix))
		{
			return (0 == filename.compare(
							filename.length() - string_length(OS::extensionSuffix),
							string_length(OS::extensionSuffix),
							OS::extensionSuffix));
		}
	}

	return false;
}

template<typename OS>
// Gets the extension name from the file name.
// ex. : libWebSocket.so on Android -> WebSocket
string filenameToExtensionName(string name)
{
	// Remove the prefix
	if(!string_empty(OS::extensionPrefix))
		name.erase(begin(name),
				   begin(name) + string_length(OS::extensionPrefix));

	// Remove the suffix
	if(!string_empty(OS::extensionSuffix))
		name.erase(end(name) - string_length(OS::extensionSuffix),
				   end(name));

	return name;
}

template<typename OS, typename Loader, typename GetProc>
// A generic way to load classes.
// Loader  : a callable object that takes a filename of a shared object,
//           and returns a handle.
// GetProc : a callable object that takes a handle and a function name,
//           and returns a pointer to the function.
bool loadClass(const string& filename,
			   const string& folder,
			   Loader&& handle_fun,
			   GetProc&& getproc_fun)
{
	// Check if the file is a Jamoma extension
	if(!isExtensionFilename<OS>(filename))
		return false;

	// Get a handle
	void *handle = handle_fun((folder + "/" + filename).c_str());
	if (!handle)
	{
		TTLogMessage("Error when trying to get an handle on %s.\n", filename.c_str());
		return false;
	}

	// Load the Jamoma extension
	string initFun = "TTLoadJamomaExtension_" + filenameToExtensionName<OS>(filename);
	auto initializer = reinterpret_cast<TTExtensionInitializationMethod>(getproc_fun(handle, initFun.c_str()));
	if (initializer)
	{
		auto err = initializer();
		if(err != kTTErrNone)
		{
			TTLogMessage("Error when initializing extension %s.\n", filename.c_str());
			return false;
		}
		return true;
	}
	return false;
}

// Here is the platform-specific code.
// It is organized in the following fashion :
//
//  * Each platform has an extension prefix (e.g. "lib", required on Android) and suffix (e.g. ".ttdylib").
//  * Platforms have these paths defined (they will be evaluated in this order) :
//   * A computed relative path (the path of the JamomaFoundation shared object)
//	 * Built-in relative paths (e.g. in an app bundle on OS X)
//	 * Built-in absolute paths (standard paths, e.g. "/usr/local/jamoma"...
//	   and a compiled-in absolute path (to allow package maintainers to add their own paths)
//   * Common code for Unix-like platforms is abstracted in UnixCommon.
#if defined(TT_PLATFORM_MAC) || defined(TT_PLATFORM_LINUX)
#include <dlfcn.h>
#include <dirent.h>

// This class contains informations that are applicable to
// UNIX-like systems (i.e. they respect the Filesystem Hierarchy Standard
// and load shared objects using dlopen / dlsym).
class UnixCommon
{
	public:
		static StringVector builtinAbsolutePaths()
		{
			return {
#if defined(JAMOMA_EXTENSIONS_INSTALL_PREFIX)
				JAMOMA_EXTENSIONS_INSTALL_PREFIX,
#endif
				"/usr/lib/jamoma",
				"/usr/local/lib/jamoma",
				"/usr/jamoma/lib",
				"/usr/jamoma/extensions",
				"/usr/local/jamoma/lib",
				"/usr/local/jamoma/extensions"
			};
		}

		template<typename OS>
		// Try to load extensions. Returns "true" only if at least one extension was loaded.
		static bool loadClassesFromFolder(const string& folder)
		{
			DIR* dirp = opendir(folder.c_str());
			if(!dirp)
				return false;

			dirent* dp{};
			int count = 0; // Number of extensions loaded.
			while ((dp = readdir(dirp)))
			{
				if(loadClass<OS>(dp->d_name,
								 folder,
								[] (const char * file)
								{ return dlopen(file, RTLD_LAZY); },
								[] (void* handle, const char * fun)
								{ return dlsym(handle, fun); }))
				{
					++count;
				}
			}

			closedir(dirp);

			if(count > 0)
			{
				TTFoundationBinaryPath = folder.c_str();
				return true;
			}

			return false;
		}

		// Returns the path of the extensions
		// relative to the folder of the JamomaFoundation library
		// the application uses.
		static string computedRelativePath()
		{
			Dl_info		info;
			char		mainBundleStr[4096];

			// Use the path of JamomaFoundation
			if (dladdr((const void*)TTLoadExtensions, &info))
			{
				char *c = 0;

				TTLogMessage("computedRelativePath(): %s\n", info.dli_fname);

				strncpy(mainBundleStr, info.dli_fname, 4096);
				c = strrchr(mainBundleStr, '/');
				if (c)
					*c = 0; // chop the "/JamomaFoundation.dylib/so off of the path
			}

			return mainBundleStr;
		}
};
#endif

#if defined(TT_PLATFORM_MAC)
class OSXSpecific
{
	public:
		static constexpr const char extensionPrefix[]{""};
		static constexpr const char extensionSuffix[]{".ttdylib"};

		static string computedRelativePath()
		{ return UnixCommon::computedRelativePath(); }

		static StringVector builtinRelativePaths()
		{ return {"../Frameworks/jamoma/extensions"}; }

		static StringVector builtinAbsolutePaths()
		{ return UnixCommon::builtinAbsolutePaths(); }

		static bool loadClassesFromFolder(const string& folderName)
		{ return UnixCommon::loadClassesFromFolder<OSXSpecific>(folderName); }
};
using OperatingSystem = OSXSpecific;
#endif
// TODO iOS & Static loading.

#if defined(TT_PLATFORM_LINUX) && defined(__ANDROID_API__)
#include <unistd.h>
#include <iostream>

class AndroidSpecific
{
	public:
		static constexpr const char extensionPrefix[]{"lib"};
		static constexpr const char extensionSuffix[]{".so"};

		static string computedRelativePath()
		{
			string s{"/proc/" + string{getpid()} + "/cmdline"};
			ifstream input{s.c_str()};
			string line;
			getline(input, line);
			return string{"/data/data/"} + line + string{"/lib"};
		}

		static StringVector builtinRelativePaths()
		{ return {}; }

		static StringVector builtinAbsolutePaths()
		{ return {}; }

		static bool loadClassesFromFolder(const string& folderName)
		{ return UnixCommon::loadClassesFromFolder<AndroidSpecific>(folderName); }
};
using OperatingSystem = AndroidSpecific;
#endif

#if defined(TT_PLATFORM_LINUX)
class LinuxSpecific
{
	public:
		static constexpr const char extensionPrefix[]{""};
		static constexpr const char extensionSuffix[]{".ttso"};

		static string computedRelativePath()
		{ return UnixCommon::computedRelativePath(); }

		static StringVector builtinRelativePaths()
		{ return {"./extensions"}; }

		static StringVector builtinAbsolutePaths()
		{ return UnixCommon::builtinAbsolutePaths(); }

		static bool loadClassesFromFolder(const string& folderName)
		{ return UnixCommon::loadClassesFromFolder<LinuxSpecific>(folderName); }
};
using OperatingSystem = LinuxSpecific;
#endif

#if defined(TT_PLATFORM_WIN)
#include <ShlObj.h>

class WinSpecific
{
	public:
		static const char* extensionPrefix;
		static const char* extensionSuffix;

		static string computedRelativePath();
		static StringVector builtinRelativePaths();
		static StringVector builtinAbsolutePaths();
		static bool loadClassesFromFolder(const string& folder);
};

// Specializations since windows does not support constexpr yet.
template<>
string filenameToExtensionName<WinSpecific>(string name)
{
	name.erase(end(name) - strlen(WinSpecific::extensionSuffix), end(name));
	return name;
}

template<>
bool isExtensionFilename<WinSpecific>(const string& filename)
{
	auto suffix_len = strlen(WinSpecific::extensionSuffix);
	if(filename.length() >= suffix_len)
	{
		return (0 == filename.compare(
						filename.length() - suffix_len,
						suffix_len,
						WinSpecific::extensionSuffix));
	}

	return false;
}

string WinSpecific::computedRelativePath()
{
	TTString	fullpath{};
	char		temppath[4096];
	LONG		lRes;

	LPCSTR moduleName = "JamomaFoundation.dll";
	HMODULE	hmodule = GetModuleHandle(moduleName);
	// get the path
	GetModuleFileName(hmodule, (LPSTR)temppath, 4096);

	if (!FAILED(hmodule) && temppath[0])
	{
		fullpath = temppath;

		// get support folder path
		fullpath = fullpath.substr(0, fullpath.length() - (strlen(moduleName) + 1));
		lRes = SHCreateDirectory(NULL, (LPCWSTR)fullpath.c_str());
	}

	return fullpath.c_str();
}

StringVector WinSpecific::builtinRelativePaths()
{
	return {"./extensions"};
}

StringVector WinSpecific::builtinAbsolutePaths()
{
	return {
#if defined(JAMOMA_EXTENSIONS_INSTALL_PREFIX)
		JAMOMA_EXTENSIONS_INSTALL_PREFIX,
#endif
		"c:\\Program Files (x86)\\Jamoma\\extensions"
	};
}

bool WinSpecific::loadClassesFromFolder(const string& folder)
{
	auto windowsPathSpec = folder
							+ "/*"
							+ string{WinSpecific::extensionSuffix};
	WIN32_FIND_DATA FindFileData;
	HANDLE hFind = FindFirstFile(windowsPathSpec.c_str(), &FindFileData);

	int count = 0; // Number of extensions loaded.
	if (hFind == INVALID_HANDLE_VALUE)
		return false;

	do {
		if(loadClass<WinSpecific>(
						 FindFileData.cFileName,
						 folder,
						[] (const char * file)
						{ return LoadLibrary(file); },
						[] (void* handle, const char * fun)
						{ return GetProcAddress((HMODULE) handle, fun); }))
		{
			++count;
		}

	} while (FindNextFile(hFind, &FindFileData));
	FindClose(hFind);

	if(count > 0)
	{
		TTFoundationBinaryPath = folder.c_str();
		return true;
	}

	return false;
}

using OperatingSystem = WinSpecific;
#endif

// Because these members are static they have to be allocated in this compilation unit.
#if defined(TT_PLATFORM_WIN)
const char* OperatingSystem::extensionPrefix{""};
const char* OperatingSystem::extensionSuffix{".ttdll"};
#else
constexpr const char OperatingSystem::extensionPrefix[array_length(OperatingSystem::extensionPrefix)];
constexpr const char OperatingSystem::extensionSuffix[array_length(OperatingSystem::extensionSuffix)];
#endif

template<typename OS>
// Try to load Jamoma classes from a vector of paths.
// This will return on the first successful folder.
bool loadClassesFromPaths(StringVector&& v)
{
	return find_if(begin(v), end(v), [] (const string& path)
			{ return OS::loadClassesFromFolder(path); }) != end(v);
}

template<typename OS>
// Try to load Jamoma classes from a path computed at runtime.
bool loadClassesFromComputedPaths()
{
	auto computedPath = OperatingSystem::computedRelativePath();
	return (!computedPath.empty()
			&& OperatingSystem::loadClassesFromFolder(computedPath));
}

template<typename OS>
// Try to load Jamoma classes from the paths built-in for the
// platform.
bool loadClassesFromBuiltinPaths()
{
	return loadClassesFromPaths<OS>(OS::builtinRelativePaths()) ||
		   loadClassesFromPaths<OS>(OS::builtinAbsolutePaths());
}

void TTLoadExtensions(const char* pathToBinaries, bool loadFromOtherPaths)
{
	if(!pathToBinaries)
	{
		if(!loadClassesFromComputedPaths<OperatingSystem>() && loadFromOtherPaths)
		{
			loadClassesFromBuiltinPaths<OperatingSystem>();
		}
	}
	else
	{
		if(!OperatingSystem::loadClassesFromFolder(pathToBinaries) && loadFromOtherPaths)
		{
			if(!loadClassesFromComputedPaths<OperatingSystem>())
			{
				loadClassesFromBuiltinPaths<OperatingSystem>();
			}
		}
	}

	if(TTFoundationBinaryPath == "")
	{
		TTLogMessage("Warning: no classes were loaded.");
	}
}
<commit_msg>Fixes code style of TTExtensionLoader<commit_after>#include "TTExtensionLoader.h"
#include "TTFoundation.h"
#include "TTEnvironment.h"
#include <vector>
#include <string>

// The organization here is as follows :
// 1. TTLoadExtensions is called and selects the paths
//    where the extensions should be searched, in order.
//    As soon as extensions are found in a folder, the search stops.
// 2. Platforms are defined as classes :
//     - TTUnixCommon contains generic data for Unix-like systems
//     - OS X, Linux, Android, Windows are the available platforms.
// 3. Each platform has a specific way to list what's in a folder :
//    The relevant method is TTPlatform::TTLoadExtensionsFromFolder
// 4. The algorithm to load a file is generic : TTLoadExtension. The
//    platform provides the algorithm with functions to get a handle.

using namespace std;
using TTStringVector = vector<string>;

// Utility compile-time functions to work with string constants.
// Except on windows, where constexpr will only be in VS2015 (hopefully...)
// This would allow to shrink this file size by a small half.
#if !defined(TT_PLATFORM_WIN)
template <typename T, size_t n>
constexpr size_t array_length(const T (&)[n])
{ return n; }

template <typename T>
constexpr size_t string_length(T&& t)
{ return array_length(forward<T&&>(t)) - 1; }

template<typename T>
constexpr bool string_empty(T&& t)
{ return string_length(forward<T&&>(t)) == 0; }
#endif

template<typename OS>
// Returns true if the filename (ex. : AudioEngine.ttdylib)
// is a correct extension filename for the platform we're in.
bool TTIsExtensionFilename(const string& filename)
{
	auto res = mismatch(begin(OS::extensionPrefix),
						end(OS::extensionPrefix),
						begin(filename));

	if (string_empty(OS::extensionPrefix) || res.first == (end(OS::extensionPrefix)))
	{
		if(filename.length() >= string_length(OS::extensionSuffix))
		{
			return (0 == filename.compare(
							filename.length() - string_length(OS::extensionSuffix),
							string_length(OS::extensionSuffix),
							OS::extensionSuffix));
		}
	}

	return false;
}

template<typename OS>
// Gets the extension name from the file name.
// ex. : libWebSocket.so on Android -> WebSocket
string TTFilenameToExtensionName(string name)
{
	// Remove the prefix
	if(!string_empty(OS::extensionPrefix))
		name.erase(begin(name),
				   begin(name) + string_length(OS::extensionPrefix));

	// Remove the suffix
	if(!string_empty(OS::extensionSuffix))
		name.erase(end(name) - string_length(OS::extensionSuffix),
				   end(name));

	return name;
}

template<typename OS, typename Loader, typename GetProc>
// A generic way to load classes.
// Loader  : a callable object that takes a filename of a shared object,
//           and returns a handle.
// GetProc : a callable object that takes a handle and a function name,
//           and returns a pointer to the function.
bool TTLoadExtension(const string& filename,
			   const string& folder,
			   Loader&& handle_fun,
			   GetProc&& getproc_fun)
{
	// Check if the file is a Jamoma extension
	if(!TTIsExtensionFilename<OS>(filename))
		return false;

	// Get a handle
	void *handle = handle_fun((folder + "/" + filename).c_str());
	if (!handle)
	{
		TTLogMessage("Error when trying to get an handle on %s.\n", filename.c_str());
		return false;
	}

	// Load the Jamoma extension
	string initFun = "TTLoadJamomaExtension_" + TTFilenameToExtensionName<OS>(filename);
	auto initializer = reinterpret_cast<TTExtensionInitializationMethod>(getproc_fun(handle, initFun.c_str()));
	if (initializer)
	{
		auto err = initializer();
		if(err != kTTErrNone)
		{
			TTLogMessage("Error when initializing extension %s.\n", filename.c_str());
			return false;
		}
		return true;
	}
	return false;
}

// Here is the platform-specific code.
// It is organized in the following fashion :
//
//  * Each platform has an extension prefix (e.g. "lib", required on Android) and suffix (e.g. ".ttdylib").
//  * Platforms have these paths defined (they will be evaluated in this order) :
//   * A computed relative path (the path of the JamomaFoundation shared object)
//	 * Built-in relative paths (e.g. in an app bundle on OS X)
//	 * Built-in absolute paths (standard paths, e.g. "/usr/local/jamoma"...
//	   and a compiled-in absolute path (to allow package maintainers to add their own paths)
//   * Common code for Unix-like platforms is abstracted in TTUnixCommon.
#if defined(TT_PLATFORM_MAC) || defined(TT_PLATFORM_LINUX)
#include <dlfcn.h>
#include <dirent.h>

// This class contains informations that are applicable to
// UNIX-like systems (i.e. they respect the Filesystem Hierarchy Standard
// and load shared objects using dlopen / dlsym).
class TTUnixCommon
{
	public:
		static TTStringVector builtinAbsolutePaths()
		{
			return {
#if defined(JAMOMA_EXTENSIONS_INSTALL_PREFIX)
				JAMOMA_EXTENSIONS_INSTALL_PREFIX,
#endif
				"/usr/lib/jamoma",
				"/usr/local/lib/jamoma",
				"/usr/jamoma/lib",
				"/usr/jamoma/extensions",
				"/usr/local/jamoma/lib",
				"/usr/local/jamoma/extensions"
			};
		}

		template<typename OS>
		// Try to load extensions. Returns "true" only if at least one extension was loaded.
		static bool TTLoadExtensionsFromFolder(const string& folder)
		{
			DIR* dirp = opendir(folder.c_str());
			if(!dirp)
				return false;

			dirent* dp{};
			int count = 0; // Number of extensions loaded.
			while ((dp = readdir(dirp)))
			{
				if(TTLoadExtension<OS>(dp->d_name,
								 folder,
								[] (const char * file)
								{ return dlopen(file, RTLD_LAZY); },
								[] (void* handle, const char * fun)
								{ return dlsym(handle, fun); }))
				{
					++count;
				}
			}

			closedir(dirp);

			if(count > 0)
			{
				TTFoundationBinaryPath = folder.c_str();
				return true;
			}

			return false;
		}

		// Returns the path of the extensions
		// relative to the folder of the JamomaFoundation library
		// the application uses.
		static string computedRelativePath()
		{
			Dl_info		info;
			char		mainBundleStr[4096];

			// Use the path of JamomaFoundation
			if (dladdr((const void*)TTLoadExtensions, &info))
			{
				char *c = 0;

				TTLogMessage("computedRelativePath(): %s\n", info.dli_fname);

				strncpy(mainBundleStr, info.dli_fname, 4096);
				c = strrchr(mainBundleStr, '/');
				if (c)
					*c = 0; // chop the "/JamomaFoundation.dylib/so off of the path
			}

			return mainBundleStr;
		}
};
#endif

#if defined(TT_PLATFORM_MAC)
class TTOSXSpecific
{
	public:
		static constexpr const char extensionPrefix[]{""};
		static constexpr const char extensionSuffix[]{".ttdylib"};

		static string computedRelativePath()
		{ return TTUnixCommon::computedRelativePath(); }

		static TTStringVector builtinRelativePaths()
		{ return {"../Frameworks/jamoma/extensions"}; }

		static TTStringVector builtinAbsolutePaths()
		{ return TTUnixCommon::builtinAbsolutePaths(); }

		static bool TTLoadExtensionsFromFolder(const string& folderName)
		{ return TTUnixCommon::TTLoadExtensionsFromFolder<TTOSXSpecific>(folderName); }
};
using TTOperatingSystem = TTOSXSpecific;
#endif
// TODO iOS & Static loading.

#if defined(TT_PLATFORM_LINUX) && defined(__ANDROID_API__)
#include <unistd.h>
#include <iostream>

class TTAndroidSpecific
{
	public:
		static constexpr const char extensionPrefix[]{"lib"};
		static constexpr const char extensionSuffix[]{".so"};

		static string computedRelativePath()
		{
			string s{"/proc/" + string{getpid()} + "/cmdline"};
			ifstream input{s.c_str()};
			string line;
			getline(input, line);
			return string{"/data/data/"} + line + string{"/lib"};
		}

		static TTStringVector builtinRelativePaths()
		{ return {}; }

		static TTStringVector builtinAbsolutePaths()
		{ return {}; }

		static bool TTLoadExtensionsFromFolder(const string& folderName)
		{ return TTUnixCommon::TTLoadExtensionsFromFolder<TTAndroidSpecific>(folderName); }
};
using TTOperatingSystem = TTAndroidSpecific;
#endif

#if defined(TT_PLATFORM_LINUX)
class TTLinuxSpecific
{
	public:
		static constexpr const char extensionPrefix[]{""};
		static constexpr const char extensionSuffix[]{".ttso"};

		static string computedRelativePath()
		{ return TTUnixCommon::computedRelativePath(); }

		static TTStringVector builtinRelativePaths()
		{ return {"./extensions"}; }

		static TTStringVector builtinAbsolutePaths()
		{ return TTUnixCommon::builtinAbsolutePaths(); }

		static bool TTLoadExtensionsFromFolder(const string& folderName)
		{ return TTUnixCommon::TTLoadExtensionsFromFolder<TTLinuxSpecific>(folderName); }
};
using TTOperatingSystem = TTLinuxSpecific;
#endif

#if defined(TT_PLATFORM_WIN)
#include <ShlObj.h>

class TTWinSpecific
{
	public:
		static const char* extensionPrefix;
		static const char* extensionSuffix;

		static string computedRelativePath();
		static TTStringVector builtinRelativePaths();
		static TTStringVector builtinAbsolutePaths();
		static bool TTLoadExtensionsFromFolder(const string& folder);
};

// Specializations since windows does not support constexpr yet.
template<>
string TTFilenameToExtensionName<TTWinSpecific>(string name)
{
	name.erase(end(name) - strlen(TTWinSpecific::extensionSuffix), end(name));
	return name;
}

template<>
bool TTIsExtensionFilename<TTWinSpecific>(const string& filename)
{
	auto suffix_len = strlen(TTWinSpecific::extensionSuffix);
	if(filename.length() >= suffix_len)
	{
		return (0 == filename.compare(
						filename.length() - suffix_len,
						suffix_len,
						TTWinSpecific::extensionSuffix));
	}

	return false;
}

string TTWinSpecific::computedRelativePath()
{
	TTString	fullpath{};
	char		temppath[4096];
	LONG		lRes;

	LPCSTR moduleName = "JamomaFoundation.dll";
	HMODULE	hmodule = GetModuleHandle(moduleName);
	// get the path
	GetModuleFileName(hmodule, (LPSTR)temppath, 4096);

	if (!FAILED(hmodule) && temppath[0])
	{
		fullpath = temppath;

		// get support folder path
		fullpath = fullpath.substr(0, fullpath.length() - (strlen(moduleName) + 1));
		lRes = SHCreateDirectory(NULL, (LPCWSTR)fullpath.c_str());
	}

	return fullpath.c_str();
}

TTStringVector TTWinSpecific::builtinRelativePaths()
{
	return {"./extensions"};
}

TTStringVector TTWinSpecific::builtinAbsolutePaths()
{
	return {
#if defined(JAMOMA_EXTENSIONS_INSTALL_PREFIX)
		JAMOMA_EXTENSIONS_INSTALL_PREFIX,
#endif
		"c:\\Program Files (x86)\\Jamoma\\extensions"
	};
}

bool TTWinSpecific::TTLoadExtensionsFromFolder(const string& folder)
{
	auto windowsPathSpec = folder
							+ "/*"
							+ string{TTWinSpecific::extensionSuffix};
	WIN32_FIND_DATA FindFileData;
	HANDLE hFind = FindFirstFile(windowsPathSpec.c_str(), &FindFileData);

	int count = 0; // Number of extensions loaded.
	if (hFind == INVALID_HANDLE_VALUE)
		return false;

	do {
		if(TTLoadExtension<TTWinSpecific>(
						 FindFileData.cFileName,
						 folder,
						[] (const char * file)
						{ return LoadLibrary(file); },
						[] (void* handle, const char * fun)
						{ return GetProcAddress((HMODULE) handle, fun); }))
		{
			++count;
		}

	} while (FindNextFile(hFind, &FindFileData));
	FindClose(hFind);

	if(count > 0)
	{
		TTFoundationBinaryPath = folder.c_str();
		return true;
	}

	return false;
}

using TTOperatingSystem = TTWinSpecific;
#endif

// Because these members are static they have to be allocated in this compilation unit.
#if defined(TT_PLATFORM_WIN)
const char* TTOperatingSystem::extensionPrefix{""};
const char* TTOperatingSystem::extensionSuffix{".ttdll"};
#else
constexpr const char TTOperatingSystem::extensionPrefix[array_length(TTOperatingSystem::extensionPrefix)];
constexpr const char TTOperatingSystem::extensionSuffix[array_length(TTOperatingSystem::extensionSuffix)];
#endif

template<typename OS>
// Try to load Jamoma classes from a vector of paths.
// This will return on the first successful folder.
bool TTLoadExtensionsFromPaths(TTStringVector&& v)
{
	return find_if(begin(v), end(v), [] (const string& path)
			{ return OS::TTLoadExtensionsFromFolder(path); }) != end(v);
}

template<typename OS>
// Try to load Jamoma classes from a path computed at runtime.
bool TTLoadExtensionsFromComputedPaths()
{
	auto computedPath = TTOperatingSystem::computedRelativePath();
	return (!computedPath.empty()
			&& TTOperatingSystem::TTLoadExtensionsFromFolder(computedPath));
}

template<typename OS>
// Try to load Jamoma classes from the paths built-in for the
// platform.
bool TTLoadExtensionsFromBuiltinPaths()
{
	return TTLoadExtensionsFromPaths<OS>(OS::builtinRelativePaths()) ||
		   TTLoadExtensionsFromPaths<OS>(OS::builtinAbsolutePaths());
}

void TTLoadExtensions(const char* pathToBinaries, bool loadFromOtherPaths)
{
	if(!pathToBinaries)
	{
		if(!TTLoadExtensionsFromComputedPaths<TTOperatingSystem>() && loadFromOtherPaths)
		{
			TTLoadExtensionsFromBuiltinPaths<TTOperatingSystem>();
		}
	}
	else
	{
		if(!TTOperatingSystem::TTLoadExtensionsFromFolder(pathToBinaries) && loadFromOtherPaths)
		{
			if(!TTLoadExtensionsFromComputedPaths<TTOperatingSystem>())
			{
				TTLoadExtensionsFromBuiltinPaths<TTOperatingSystem>();
			}
		}
	}

	if(TTFoundationBinaryPath == "")
	{
		TTLogMessage("Warning: no classes were loaded.");
	}
}
<|endoftext|>


<commit_before>#include <QPainter>
#include <QTimer>

#include "CommentLib.h"

#include "AssassinWar.h"
#include "MapLoader.h"

AssassinWar::AssassinWar(QWidget *parent, Qt::WFlags flags)
    : QMainWindow(parent, flags),
      m_pRepaintTimer(NULL)
{
    ui.setupUi(this);

    MapLoader mapLoader;
    QWidget* pMapWidget =  mapLoader.LoadMap("./map/map1.ui");
    mapLoader.LoadMapTerrain(*pMapWidget);

    m_pRepaintTimer = new QTimer(this);
    connect(m_pRepaintTimer, SIGNAL(timeout()), this, SLOT(repaint()));
    m_pRepaintTimer->start(250);
}

AssassinWar::~AssassinWar()
{
    m_pRepaintTimer->stop();
}

void AssassinWar::paintEvent(QPaintEvent *PaintEvent)
{
    static float a = 0.0f;

    if(60 < a)
    {
        a = 0.0f;
    }

    QPainter painter(this);
    painter.drawLine(++a, 0.0, 15.0, 25.0);// drawing code
}<commit_msg>Signed-off-by: flymianmian <flymianmian@163.com><commit_after>#include <QPainter>
#include <QTimer>

#include "CommentLib.h"

#include "AssassinWar.h"
#include "MapLoader.h"

AssassinWar::AssassinWar(QWidget *parent, Qt::WFlags flags)
    : QMainWindow(parent, flags),
      m_pRepaintTimer(NULL)
{
    ui.setupUi(this);

    MapLoader mapLoader;
    QWidget* pMapWidget =  mapLoader.LoadMap("./map/map1.ui");
    mapLoader.LoadMapTerrain(*pMapWidget);

    showFullScreen();

    ui.mainToolBar->hide();

    m_pRepaintTimer = new QTimer(this);
    connect(m_pRepaintTimer, SIGNAL(timeout()), this, SLOT(repaint()));
    m_pRepaintTimer->start(240);
}

AssassinWar::~AssassinWar()
{
    m_pRepaintTimer->stop();
}

void AssassinWar::paintEvent(QPaintEvent *PaintEvent)
{
    static float a = 0.0f;

    if(60 < a)
    {
        a = 0.0f;
    }

    QPainter painter(this);
    painter.drawLine(++a, 0.0, 15.0, 25.0);// drawing code
}<|endoftext|>


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

/*! \file reduce.inl
 *  \brief Inline file for reduce.h
 */

#pragma once

// do not attempt to compile this file with any other compiler
#ifdef __CUDACC__

// to configure launch parameters
#include <thrust/experimental/arch.h>

#include <thrust/detail/raw_buffer.h>
#include <thrust/detail/device/cuda/block/reduce.h>

namespace thrust
{
namespace detail
{
namespace device
{
namespace cuda
{

/*
 * Reduce a vector of n elements using binary_op()
 *
 * The order of reduction is not defined, so binary_op() should
 * be a commutative (and associative) operator such as
 * (integer) addition.  Since floating point operations
 * do not completely satisfy these criteria, the result is
 * generally not the same as a consecutive reduction of
 * the elements.
 *
 * Uses the same pattern as reduce6() in the CUDA SDK
 *
 */

template<typename InputIterator,
         typename OutputType,
         typename BinaryFunction>
  __global__ void
  reduce_n_kernel(InputIterator input,
                  const unsigned int n,
                  OutputType * block_results,
                  BinaryFunction binary_op)
{
    extern __shared__ OutputType sdata[];

    // perform first level of reduction,
    // write per-block results to global memory for second level reduction

    const unsigned int grid_size = blockDim.x * gridDim.x;
    unsigned int i = blockDim.x * blockIdx.x + threadIdx.x;

    // local (per-thread) sum
    OutputType sum;

    // initialize local sum
    if (i < n)
    {
        sum = thrust::detail::device::dereference(input, i);
        i += grid_size;
    }

    // update sum
    while (i < n)
    {
        sum = binary_op(sum, thrust::detail::device::dereference(input, i));
        i += grid_size;
    }

    // copy local sum to shared memory
    sdata[threadIdx.x] = sum;  __syncthreads();

    // compute reduction across block
    block::reduce_n(sdata, min(n, blockDim.x), binary_op);

    // write result for this block to global mem
    if (threadIdx.x == 0)
        block_results[blockIdx.x] = sdata[threadIdx.x];

} // end reduce_n_kernel()

template<typename InputIterator,
         typename SizeType,
         typename OutputType,
         typename BinaryFunction>
  OutputType reduce_n(InputIterator first,
                      SizeType n,
                      OutputType init,
                      BinaryFunction binary_op)
{
    // handle zero length array case first
    if( n == 0 )
        return init;

    // determine launch parameters
    const size_t block_size = thrust::experimental::arch::max_blocksize_with_highest_occupancy(reduce_n_kernel<InputIterator, OutputType, BinaryFunction>, sizeof(OutputType));
    const size_t smem_size  = block_size * sizeof(OutputType);
    const size_t max_blocks = thrust::experimental::arch::max_active_blocks(reduce_n_kernel<InputIterator, OutputType, BinaryFunction>, block_size, smem_size);
    const size_t num_blocks = std::min(max_blocks, std::max((size_t) 1, n / block_size));

    // allocate storage for per-block results
    thrust::detail::raw_device_buffer<OutputType> temp(num_blocks + 1);

    // set first element of temp array to init
    temp[0] = init;

    // reduce input to per-block sums
    reduce_n_kernel<<<num_blocks, block_size, smem_size>>>(first, n, raw_pointer_cast(&temp[1]), binary_op);

    // reduce per-block sums together with init
    reduce_n_kernel<<<         1, block_size, smem_size>>>(raw_pointer_cast(&temp[0]), num_blocks + 1, raw_pointer_cast(&temp[0]), binary_op);

    return temp[0];
} // end reduce_n()

} // end namespace cuda
} // end namespace device
} // end namespace detail
} // end namespace thrust

#endif // __CUDACC__

<commit_msg>cuda::reduce() now works for partially used blocks<commit_after>/*
 *  Copyright 2008-2009 NVIDIA Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/*! \file reduce.inl
 *  \brief Inline file for reduce.h
 */

// do not attempt to compile this file with any other compiler
#ifdef __CUDACC__

// to configure launch parameters
#include <thrust/experimental/arch.h>

#include <thrust/detail/raw_buffer.h>
#include <thrust/detail/device/cuda/block/reduce.h>

namespace thrust
{
namespace detail
{
namespace device
{
namespace cuda
{

/*
 * Reduce a vector of n elements using binary_op()
 *
 * The order of reduction is not defined, so binary_op() should
 * be a commutative (and associative) operator such as
 * (integer) addition.  Since floating point operations
 * do not completely satisfy these criteria, the result is
 * generally not the same as a consecutive reduction of
 * the elements.
 *
 * Uses the same pattern as reduce6() in the CUDA SDK
 *
 */

template<typename InputIterator,
         typename OutputType,
         typename BinaryFunction>
  __global__ void
  reduce_n_kernel(InputIterator input,
                  const unsigned int n,
                  OutputType * block_results,
                  BinaryFunction binary_op)
{
    extern __shared__ OutputType sdata[];

    // perform first level of reduction,
    // write per-block results to global memory for second level reduction

    const unsigned int grid_size = blockDim.x * gridDim.x;
    unsigned int i = blockDim.x * blockIdx.x + threadIdx.x;

    // local (per-thread) sum
    OutputType sum;

    // initialize local sum
    if (i < n)
    {
        sum = thrust::detail::device::dereference(input, i);
        i += grid_size;
    }

    // accumulate local sum
    while (i < n)
    {
        sum = binary_op(sum, thrust::detail::device::dereference(input, i));
        i += grid_size;
    }

    // copy local sum to shared memory
    sdata[threadIdx.x] = sum;  __syncthreads();

    // compute reduction across block
    block::reduce_n(sdata, min(n - blockDim.x * blockIdx.x, blockDim.x), binary_op);

    // write result for this block to global mem
    if (threadIdx.x == 0)
        block_results[blockIdx.x] = sdata[threadIdx.x];

} // end reduce_n_kernel()

template<typename InputIterator,
         typename SizeType,
         typename OutputType,
         typename BinaryFunction>
  OutputType reduce_n(InputIterator first,
                      SizeType n,
                      OutputType init,
                      BinaryFunction binary_op)
{
    // handle zero length array case first
    if( n == 0 )
        return init;

    // determine launch parameters
    const size_t block_size = thrust::experimental::arch::max_blocksize_with_highest_occupancy(reduce_n_kernel<InputIterator, OutputType, BinaryFunction>, sizeof(OutputType));
    const size_t smem_size  = block_size * sizeof(OutputType);
    const size_t max_blocks = thrust::experimental::arch::max_active_blocks(reduce_n_kernel<InputIterator, OutputType, BinaryFunction>, block_size, smem_size);
    const size_t num_blocks = std::min(max_blocks, (n + block_size - 1) / block_size);

    // allocate storage for per-block results
    thrust::detail::raw_device_buffer<OutputType> temp(num_blocks + 1);

    // set first element of temp array to init
    temp[0] = init;

    // reduce input to per-block sums
    reduce_n_kernel<<<num_blocks, block_size, smem_size>>>(first, n, raw_pointer_cast(&temp[1]), binary_op);

    // reduce per-block sums together with init
    reduce_n_kernel<<<         1, block_size, smem_size>>>(raw_pointer_cast(&temp[0]), num_blocks + 1, raw_pointer_cast(&temp[0]), binary_op);

    return temp[0];
} // end reduce_n()

} // end namespace cuda
} // end namespace device
} // end namespace detail
} // end namespace thrust

#endif // __CUDACC__

<|endoftext|>


<commit_before>/*//////////////////////////////////////////////////////////////////
////       SKIRT -- an advanced radiative transfer code         ////
////       © Astronomical Observatory, Ghent University         ////
//////////////////////////////////////////////////////////////////*/

#include <cmath>
#include <fstream>
#include "FatalError.hpp"
#include "FilePaths.hpp"
#include "ISRF.hpp"
#include "Log.hpp"
#include "NR.hpp"
#include "PlanckFunction.hpp"
#include "WavelengthGrid.hpp"

using namespace std;

////////////////////////////////////////////////////////////////////

Array ISRF::mathis(SimulationItem* simitem)
{
    WavelengthGrid* lambdagrid = simitem->find<WavelengthGrid>();
    int Nlambda = lambdagrid->Nlambda();

    const double Wv[] = {1e-14,1e-13,4e-13};
    const double Tv[] = {7500.0,4000.0,3000.0};
    const double lambda912 = 912e-10;
    const double lambda110 = 110e-9;
    const double lambda134 = 134e-9;
    const double lambda246 = 246e-9;
    const Array& lambdav = lambdagrid->lambdav();
    int ell912 = NR::locate_clip(lambdav,lambda912);
    int ell110 = NR::locate_clip(lambdav,lambda110);
    int ell134 = NR::locate_clip(lambdav,lambda134);
    int ell246 = NR::locate_clip(lambdav,lambda246);

    Array Jv(Nlambda);
    for (int ell=ell912+1; ell<=ell110; ell++)
        Jv[ell] = 38.57 * pow(lambdav[ell]*1e6,3.4172);
    for (int ell=ell110+1; ell<=ell134; ell++)
        Jv[ell] = 2.045e-2;
    for (int ell=ell134+1; ell<=ell246; ell++)
        Jv[ell] = 7.115e-4 * pow(lambdav[ell]*1e6,-1.6678);
    for (int ell=0; ell<=ell246; ell++)
        Jv[ell] *= 1e3;     // conversion from erg/cm2/s/micron to W/m3
    for (int i=0; i<3; i++)
    {
        PlanckFunction B(Tv[i]);
        for (int ell=ell246+1; ell<Nlambda; ell++)
            Jv[ell] += 4*M_PI* Wv[i] * B(lambdav[ell]);
    }
    Jv /= (4*M_PI);
    return Jv;
}

////////////////////////////////////////////////////////////////////

Array ISRF::kruegel(SimulationItem* simitem)
{
    // Read the data from the file into local vectors lambdav[k] and Jv[k]
    const int Nlambda = 435;
    QString filename = FilePaths::resource("ISRF/ISRF-Kruegel.dat");
    ifstream file(filename.toLocal8Bit().constData());
    if (! file.is_open()) throw FATALERROR("Could not open the data file " + filename);
    simitem->find<Log>()->info("Reading ISRF data from file " + filename + "...");
    Array lambdav(Nlambda);
    Array Jv(Nlambda);
    for (int k = 0; k<Nlambda; k++)
    {
        file >> lambdav[k] >> Jv[k];
    }
    file.close();
    simitem->find<Log>()->info("File " + filename + " closed.");

    // resample on the simulation's wavelength grid
    WavelengthGrid* lambdagrid = simitem->find<WavelengthGrid>();
    return NR::resample<NR::interpolate_loglog>(lambdagrid->lambdav(), lambdav, Jv);
}

////////////////////////////////////////////////////////////////////
<commit_msg>adjust Mathis ISRF to SHG benchmark parametrization<commit_after>/*//////////////////////////////////////////////////////////////////
////       SKIRT -- an advanced radiative transfer code         ////
////       © Astronomical Observatory, Ghent University         ////
//////////////////////////////////////////////////////////////////*/

#include <cmath>
#include <fstream>
#include "FatalError.hpp"
#include "FilePaths.hpp"
#include "ISRF.hpp"
#include "Log.hpp"
#include "NR.hpp"
#include "PlanckFunction.hpp"
#include "WavelengthGrid.hpp"

using namespace std;

////////////////////////////////////////////////////////////////////

Array ISRF::mathis(SimulationItem* simitem)
{
    WavelengthGrid* lambdagrid = simitem->find<WavelengthGrid>();
    const Array& lambdav = lambdagrid->lambdav();
    int Nlambda = lambdagrid->Nlambda();
    int ellA = NR::locate_clip(lambdav, 0.0912e-6);
    int ellB = NR::locate_clip(lambdav, 0.110e-6);
    int ellC = NR::locate_clip(lambdav, 0.134e-6);
    int ellD = NR::locate_clip(lambdav, 0.250e-6);

    const double Wv[] = {1e-14,1e-13,4e-13};
    const double Tv[] = {7500,4000,3000};

    Array Jv(Nlambda);
    for (int ell=ellA+1; ell<=ellB; ell++)
        Jv[ell] = 3069. * pow(lambdav[ell]*1e6,3.4172);
    for (int ell=ellB+1; ell<=ellC; ell++)
        Jv[ell] = 1.627;
    for (int ell=ellC+1; ell<=ellD; ell++)
        Jv[ell] = 0.0566 * pow(lambdav[ell]*1e6,-1.6678);
    for (int i=0; i<3; i++)
    {
        PlanckFunction B(Tv[i]);
        for (int ell=ellD+1; ell<Nlambda; ell++)
            Jv[ell] += Wv[i] * B(lambdav[ell]);
    }
    return Jv;
}

////////////////////////////////////////////////////////////////////

Array ISRF::kruegel(SimulationItem* simitem)
{
    // Read the data from the file into local vectors lambdav[k] and Jv[k]
    const int Nlambda = 435;
    QString filename = FilePaths::resource("ISRF/ISRF-Kruegel.dat");
    ifstream file(filename.toLocal8Bit().constData());
    if (! file.is_open()) throw FATALERROR("Could not open the data file " + filename);
    simitem->find<Log>()->info("Reading ISRF data from file " + filename + "...");
    Array lambdav(Nlambda);
    Array Jv(Nlambda);
    for (int k = 0; k<Nlambda; k++)
    {
        file >> lambdav[k] >> Jv[k];
    }
    file.close();
    simitem->find<Log>()->info("File " + filename + " closed.");

    // resample on the simulation's wavelength grid
    WavelengthGrid* lambdagrid = simitem->find<WavelengthGrid>();
    return NR::resample<NR::interpolate_loglog>(lambdagrid->lambdav(), lambdav, Jv);
}

////////////////////////////////////////////////////////////////////
<|endoftext|>


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

#include <uv.h>
#include <algorithm>
#include <iterator>
#include "event.h"
#include "eventqueue.h"

EventQueue::EventQueue() {
  _async = new uv_async_t;
  uv_async_init(uv_default_loop(), _async,
                reinterpret_cast<uv_async_cb>(EventQueue::AsyncCallback));

  _async->data = this;
  uv_mutex_init(&_async_lock);
}

EventQueue::~EventQueue() {
  uv_mutex_destroy(&_async_lock);
}

void EventQueue::AsyncCallback(uv_async_t *handle, int status) {
  EventQueue *self = reinterpret_cast<EventQueue*>(handle->data);

  if (!self) {
    return;
  }

  self->Flush();
}

void EventQueue::HandleEvent(Event *event) {
  event->Handle();
  delete event;
}

void EventQueue::PushEvent(Event *event) {
  uv_mutex_lock(&_async_lock);

  _queue.push_back(event);

  uv_mutex_unlock(&_async_lock);
  uv_async_send(this->_async);
}

void EventQueue::Flush() {
  std::vector<Event*> eventList;

  uv_mutex_lock(&_async_lock);

  if (_queue.empty()) {
    uv_mutex_unlock(&_async_lock);
    return;
  }

  std::copy(_queue.begin(), _queue.end(), std::back_inserter(eventList));
  _queue.clear();

  uv_mutex_unlock(&_async_lock);
  std::for_each(eventList.begin(), eventList.end(), EventQueue::HandleEvent);
  eventList.clear();
}
<commit_msg>EventQueue: Delete async handle during destruction<commit_after>/*
 * Copyright (c) 2017 Axel Isouard <axel@isouard.fr>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <uv.h>
#include <algorithm>
#include <iterator>
#include "event.h"
#include "eventqueue.h"

EventQueue::EventQueue() {
  _async = new uv_async_t;
  uv_async_init(uv_default_loop(), _async,
                reinterpret_cast<uv_async_cb>(EventQueue::AsyncCallback));

  _async->data = this;
  uv_mutex_init(&_async_lock);
}

EventQueue::~EventQueue() {
  uv_mutex_destroy(&_async_lock);
  delete _async;
}

void EventQueue::AsyncCallback(uv_async_t *handle, int status) {
  EventQueue *self = reinterpret_cast<EventQueue*>(handle->data);

  if (!self) {
    return;
  }

  self->Flush();
}

void EventQueue::HandleEvent(Event *event) {
  event->Handle();
  delete event;
}

void EventQueue::PushEvent(Event *event) {
  uv_mutex_lock(&_async_lock);

  _queue.push_back(event);

  uv_mutex_unlock(&_async_lock);
  uv_async_send(this->_async);
}

void EventQueue::Flush() {
  std::vector<Event*> eventList;

  uv_mutex_lock(&_async_lock);

  if (_queue.empty()) {
    uv_mutex_unlock(&_async_lock);
    return;
  }

  std::copy(_queue.begin(), _queue.end(), std::back_inserter(eventList));
  _queue.clear();

  uv_mutex_unlock(&_async_lock);
  std::for_each(eventList.begin(), eventList.end(), EventQueue::HandleEvent);
  eventList.clear();
}
<|endoftext|>


<commit_before>//===------------------------ exception.cpp -------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <stdlib.h>

#include "exception"

#if __APPLE__
  #include <cxxabi.h>

  using namespace __cxxabiv1;
  #define HAVE_DEPENDENT_EH_ABI 1
  #ifndef _LIBCPPABI_VERSION
    using namespace __cxxabiapple;
    // On Darwin, there are two STL shared libraries and a lower level ABI
    // shared libray.  The globals holding the current terminate handler and
    // current unexpected handler are in the ABI library.
    #define __terminate_handler  __cxxabiapple::__cxa_terminate_handler
    #define __unexpected_handler __cxxabiapple::__cxa_unexpected_handler
  #endif  // _LIBCPPABI_VERSION
#elif defined(LIBCXXRT)
  #include <cxxabi.h>
  using namespace __cxxabiv1;
  #define HAVE_DEPENDENT_EH_ABI 1
#else  // __APPLE__
  static std::terminate_handler  __terminate_handler;
  static std::unexpected_handler __unexpected_handler;
#endif  // __APPLE__

namespace std
{

#if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION)

// libcxxrt provides implementations of these functions itself.
unexpected_handler
set_unexpected(unexpected_handler func) _NOEXCEPT
{
    return __sync_lock_test_and_set(&__unexpected_handler, func);
}

unexpected_handler
get_unexpected() _NOEXCEPT
{
    return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0);
}

_ATTRIBUTE(noreturn)
void
unexpected()
{
    (*get_unexpected())();
    // unexpected handler should not return
    terminate();
}

terminate_handler
set_terminate(terminate_handler func) _NOEXCEPT
{
    return __sync_lock_test_and_set(&__terminate_handler, func);
}

terminate_handler
get_terminate() _NOEXCEPT
{
    return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0);
}

_ATTRIBUTE(noreturn)
void
terminate() _NOEXCEPT
{
#ifndef _LIBCPP_NO_EXCEPTIONS
    try
    {
#endif  // _LIBCPP_NO_EXCEPTIONS
        (*get_terminate())();
        // handler should not return
        ::abort ();
#ifndef _LIBCPP_NO_EXCEPTIONS
    }
    catch (...)
    {
        // handler should not throw exception
        ::abort ();
    }
#endif  // _LIBCPP_NO_EXCEPTIONS
}
#endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION)

#ifndef LIBCXXRT
bool uncaught_exception() _NOEXCEPT
{
#if __APPLE__
    // on Darwin, there is a helper function so __cxa_get_globals is private
    return __cxa_uncaught_exception();
#elif LIBCXXRT
    __cxa_eh_globals * globals = __cxa_get_globals();
    return (globals->uncaughtExceptions != 0);
#else  // __APPLE__
    #warning uncaught_exception not yet implemented
    ::abort();
#endif  // __APPLE__
}

#ifndef _LIBCPPABI_VERSION

exception::~exception() _NOEXCEPT
{
}

const char* exception::what() const _NOEXCEPT
{
  return "std::exception";
}

#endif  // _LIBCPPABI_VERSION
#endif //LIBCXXRT
#ifndef _LIBCPPABI_VERSION

bad_exception::~bad_exception() _NOEXCEPT
{
}

const char* bad_exception::what() const _NOEXCEPT
{
  return "std::bad_exception";
}

#endif

exception_ptr::~exception_ptr() _NOEXCEPT
{
#if HAVE_DEPENDENT_EH_ABI
    __cxa_decrement_exception_refcount(__ptr_);
#else
    #warning exception_ptr not yet implemented
    ::abort();
#endif  // __APPLE__
}

exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
    : __ptr_(other.__ptr_)
{
#if HAVE_DEPENDENT_EH_ABI
    __cxa_increment_exception_refcount(__ptr_);
#else
    #warning exception_ptr not yet implemented
    ::abort();
#endif  // __APPLE__
}

exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
{
#if HAVE_DEPENDENT_EH_ABI
    if (__ptr_ != other.__ptr_)
    {
        __cxa_increment_exception_refcount(other.__ptr_);
        __cxa_decrement_exception_refcount(__ptr_);
        __ptr_ = other.__ptr_;
    }
    return *this;
#else  // __APPLE__
    #warning exception_ptr not yet implemented
    ::abort();
#endif  // __APPLE__
}

nested_exception::nested_exception() _NOEXCEPT
    : __ptr_(current_exception())
{
}

nested_exception::~nested_exception() _NOEXCEPT
{
}

_ATTRIBUTE(noreturn)
void
nested_exception::rethrow_nested() const
{
    if (__ptr_ == nullptr)
        terminate();
    rethrow_exception(__ptr_);
}

exception_ptr current_exception() _NOEXCEPT
{
#if HAVE_DEPENDENT_EH_ABI
    // be nicer if there was a constructor that took a ptr, then
    // this whole function would be just:
    //    return exception_ptr(__cxa_current_primary_exception());
    exception_ptr ptr;
    ptr.__ptr_ = __cxa_current_primary_exception();
    return ptr;
#else  // __APPLE__
    #warning exception_ptr not yet implemented
    ::abort();
#endif  // __APPLE__
}

_ATTRIBUTE(noreturn)
void rethrow_exception(exception_ptr p)
{
#if HAVE_DEPENDENT_EH_ABI
    __cxa_rethrow_primary_exception(p.__ptr_);
    // if p.__ptr_ is NULL, above returns so we terminate
    terminate();
#else  // __APPLE__
    #warning exception_ptr not yet implemented
    ::abort();
#endif  // __APPLE__
}
} // std
<commit_msg>Teach libc++ to check for libc++abi and use its features if they're available.<commit_after>//===------------------------ exception.cpp -------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <stdlib.h>

#include "exception"

#ifndef __has_include
#define __has_include(inc) 0
#endif

#if __APPLE__
  #include <cxxabi.h>

  using namespace __cxxabiv1;
  #define HAVE_DEPENDENT_EH_ABI 1
  #ifndef _LIBCPPABI_VERSION
    using namespace __cxxabiapple;
    // On Darwin, there are two STL shared libraries and a lower level ABI
    // shared libray.  The globals holding the current terminate handler and
    // current unexpected handler are in the ABI library.
    #define __terminate_handler  __cxxabiapple::__cxa_terminate_handler
    #define __unexpected_handler __cxxabiapple::__cxa_unexpected_handler
  #endif  // _LIBCPPABI_VERSION
#elif defined(LIBCXXRT) || __has_include(<cxxabi.h>)
  #include <cxxabi.h>
  using namespace __cxxabiv1;
  #if defined(LIBCXXRT) || defined(_LIBCPPABI_VERSION)
    #define HAVE_DEPENDENT_EH_ABI 1
  #endif
#else  // __has_include(<cxxabi.h>)
  static std::terminate_handler  __terminate_handler;
  static std::unexpected_handler __unexpected_handler;
#endif // __has_include(<cxxabi.h>)

namespace std
{

#if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION)

// libcxxrt provides implementations of these functions itself.
unexpected_handler
set_unexpected(unexpected_handler func) _NOEXCEPT
{
    return __sync_lock_test_and_set(&__unexpected_handler, func);
}

unexpected_handler
get_unexpected() _NOEXCEPT
{
    return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0);
}

_ATTRIBUTE(noreturn)
void
unexpected()
{
    (*get_unexpected())();
    // unexpected handler should not return
    terminate();
}

terminate_handler
set_terminate(terminate_handler func) _NOEXCEPT
{
    return __sync_lock_test_and_set(&__terminate_handler, func);
}

terminate_handler
get_terminate() _NOEXCEPT
{
    return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0);
}

_ATTRIBUTE(noreturn)
void
terminate() _NOEXCEPT
{
#ifndef _LIBCPP_NO_EXCEPTIONS
    try
    {
#endif  // _LIBCPP_NO_EXCEPTIONS
        (*get_terminate())();
        // handler should not return
        ::abort ();
#ifndef _LIBCPP_NO_EXCEPTIONS
    }
    catch (...)
    {
        // handler should not throw exception
        ::abort ();
    }
#endif  // _LIBCPP_NO_EXCEPTIONS
}
#endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION)

#ifndef LIBCXXRT
bool uncaught_exception() _NOEXCEPT
{
#if __APPLE__ || defined(_LIBCPPABI_VERSION)
    // on Darwin, there is a helper function so __cxa_get_globals is private
    return __cxa_uncaught_exception();
#else  // __APPLE__
    #warning uncaught_exception not yet implemented
    ::abort();
#endif  // __APPLE__
}

#ifndef _LIBCPPABI_VERSION

exception::~exception() _NOEXCEPT
{
}

const char* exception::what() const _NOEXCEPT
{
  return "std::exception";
}

#endif  // _LIBCPPABI_VERSION
#endif //LIBCXXRT
#ifndef _LIBCPPABI_VERSION

bad_exception::~bad_exception() _NOEXCEPT
{
}

const char* bad_exception::what() const _NOEXCEPT
{
  return "std::bad_exception";
}

#endif

exception_ptr::~exception_ptr() _NOEXCEPT
{
#if HAVE_DEPENDENT_EH_ABI
    __cxa_decrement_exception_refcount(__ptr_);
#else
    #warning exception_ptr not yet implemented
    ::abort();
#endif  // __APPLE__
}

exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
    : __ptr_(other.__ptr_)
{
#if HAVE_DEPENDENT_EH_ABI
    __cxa_increment_exception_refcount(__ptr_);
#else
    #warning exception_ptr not yet implemented
    ::abort();
#endif  // __APPLE__
}

exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
{
#if HAVE_DEPENDENT_EH_ABI
    if (__ptr_ != other.__ptr_)
    {
        __cxa_increment_exception_refcount(other.__ptr_);
        __cxa_decrement_exception_refcount(__ptr_);
        __ptr_ = other.__ptr_;
    }
    return *this;
#else  // __APPLE__
    #warning exception_ptr not yet implemented
    ::abort();
#endif  // __APPLE__
}

nested_exception::nested_exception() _NOEXCEPT
    : __ptr_(current_exception())
{
}

nested_exception::~nested_exception() _NOEXCEPT
{
}

_ATTRIBUTE(noreturn)
void
nested_exception::rethrow_nested() const
{
    if (__ptr_ == nullptr)
        terminate();
    rethrow_exception(__ptr_);
}

exception_ptr current_exception() _NOEXCEPT
{
#if HAVE_DEPENDENT_EH_ABI
    // be nicer if there was a constructor that took a ptr, then
    // this whole function would be just:
    //    return exception_ptr(__cxa_current_primary_exception());
    exception_ptr ptr;
    ptr.__ptr_ = __cxa_current_primary_exception();
    return ptr;
#else  // __APPLE__
    #warning exception_ptr not yet implemented
    ::abort();
#endif  // __APPLE__
}

_ATTRIBUTE(noreturn)
void rethrow_exception(exception_ptr p)
{
#if HAVE_DEPENDENT_EH_ABI
    __cxa_rethrow_primary_exception(p.__ptr_);
    // if p.__ptr_ is NULL, above returns so we terminate
    terminate();
#else  // __APPLE__
    #warning exception_ptr not yet implemented
    ::abort();
#endif  // __APPLE__
}
} // std
<|endoftext|>


<commit_before>/* Please refer to license.txt */

#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <dirent.h>

#include "file.hpp"

#include "../error/error.hpp"

#include "../string/string.hpp"

#include "../internal_header.hpp"

namespace mfile
{

FileManager::FileManager()
{
}

FileManager::~FileManager()
{
}

void FileManager::exportFile(std::string filepath, std::string output_data, bool overwrite) //Export a file.
{
	FILE *file = nullptr; //The file.

	if (overwrite) file = fopen(filepath.c_str(), "w+"); //Open the file for writing, overwriting whatever currently exists, if anything.
	else file = fopen(filepath.c_str(), "a"); //Open the file for writing. Do not overwrite, append.

	if (!file) //Error checking.
	{
		//cout << "Failed to open file: \"" << filepath << "\".\n"; //Let the user know there was an error.
		//cout << "Attempting to create folder...\n"; //Let the user know we're trying to create the directory.

		//TODO: This portiong needs to be put into a "make_directories_until()" function.

		//TODO: This needs to be adjusted to recursively make the missing folders.

		bool start_saving = false; //Start saving the characters from the string?
		std::string folderpath = ""; //The folderpath.
		std::string temp_string = ""; //Folderpath is initially read into this, backwards. Used for ordering it correctly.
		for (int i = filepath.length() - 1; i >= 0; --i) //Loop through and extract the folderpath
		{
			if (!start_saving && (filepath[i] == '\\' || filepath[i] == '/')) //If not already saving the characters...Check if it's a / or \ character.
			{
				start_saving = true; //Yay, end of filename found, now we can extract the folderpath.
			}
			if (start_saving) //Ok, it is saving the characters.
			{
				temp_string += filepath[i]; //Save the character.
			}
		}
		for (int i = temp_string.length() - 1; i >= 0; --i) //Now reverse the order of characters so that the folderpath is no longer backwards.
		{
			folderpath += temp_string[i]; //Save the character.
		}

		try
		{
			mkDir("./" + folderpath); //Create the folder. With error checking.
		}
		catch (...)
		{
			std::string *filename = new std::string; //The filename.
			*filename = mstring::toString(__FILE__); //Convert the char* that is filename to a string.
			std::string *message = new std::string;
			*message = "Failed to create directory: \"";
			*message += folderpath;
			*message += "\".";
			merror::Error *error = generateError(merror::FUNCTION_FAILURE, message, merror::SEVERITY_IGNORE, __LINE__, filename);
			throw error;
		}

		if (overwrite) file = fopen(filepath.c_str(), "w+"); //Open the file for writing, overwriting any currently existing file.
		else file = fopen(filepath.c_str(), "a"); //Open the file for writing. Do not overwrite, append.

		if (!file) //Error checking.
		{
			std::string *filename = new std::string; //The filename.
			*filename = mstring::toString(__FILE__); //Convert the char* that is filename to a string.
			std::string *message = new std::string;
			*message = "Failed to create file.";
			merror::Error *error = generateError(merror::FUNCTION_FAILURE, message, merror::SEVERITY_IGNORE, __LINE__, filename);
			throw error; //Failure.
		}

		//TODO: End portion that needs being put into a "make_directories_until()" function.
	}

	fprintf(file, output_data.c_str());  //Write out the string.

	fclose(file); //Close the file.
} //FileManager::exportFile()

void FileManager::mkDir(std::string path) //Create a directory at the specified location.
{
	#if OS == OS_WINDOWS //If the operating system is windows.
		if (mkdir(path.c_str()) == -1) //Create the directory.
		{
			//throw strerror(errno); //Throw an error. //TODO: Refine the error to use the error module.
			std::string *error_message = new std::string; //The error message.
			*error_message = mstring::toString(strerror(errno)); //Convert the char* that is strerror to a string.
			std::string *filename = new std::string; //The filename.
			*filename = mstring::toString(__FILE__); //Convert the char* that is filename to a string.
			merror::Error *error = generateError(merror::FUNCTION_FAILURE, error_message, merror::SEVERITY_IGNORE, __LINE__, filename);
			throw error;
		}
	#else //OS is not windows.
		if (mkdir(path.c_str(), 0777) == -1)//creating a directory
		{
			//throw strerror(errno); //Throw an error. //TODO: Refine the error to use the error module.
			std::string *error_message = new std::string; //The error message.
			*error_message = mstring::toString(strerror(errno)); //Convert the char* that is strerror to a string.
			std::string *filename = new std::string; //The filename.
			*filename = mstring::toString(__FILE__); //Convert the char* that is filename to a string.
			merror::Error *error = generateError(merror::FUNCTION_FAILURE, error_message, merror::SEVERITY_IGNORE, __LINE__, filename);
			throw error;
		}
	#endif
}

bool FileManager::directoryExists(std::string path) //Checks if specified directory exists.
{
	//This function could probably be done better with a call to an external library's superoptimised directory_exists() function.
	//But, until such a time that we have such a library, this will be used.

	//TODO: This portion probably can be put into an external function.

	//This portion of code determines the path to the directory the directory we're looking for is in.

	bool start_saving = false; //Start saving the characters from the string?
	std::string folderpath = ""; //The folderpath.
	std::string temp_string = ""; //Folderpath is initially read into this, backwards. Used for ordering it correctly.
	std::string directory_name_reverse = ""; //The name of the folder it's looking for. Reversed. This is used because the path is read backwards and everything after the slash is chopped off, thus determining the directory we're looking for's name.
	std::string directory_name = ""; //The name of the folder it's looking for.
	for (int i = path.length() - 1; i >= 0; --i) //Loop through and extract the folderpath. Pretty much the folder the folder is in.
	{
		if (!start_saving && (path[i] == '\\' || path[i] == '/')) //If not already saving the characters...Check if it's a / or \ character.
		{
			start_saving = true; //Yay, end of filename found, now we can extract the folderpath.
			directory_name_reverse += path[i];
		}
		else if (start_saving) //Ok, it is saving the characters.
		{
			temp_string += path[i]; //Save the character.
		}
	}
	for (int i = temp_string.length() - 1; i >= 0; --i) //Now reverse the order of characters so that the folderpath is no longer backwards.
	{
		folderpath += temp_string[i]; //Save the character.
	}
	for (int i = directory_name_reverse.length() - 1;  i >= 0; --i)
	{
		if (directory_name_reverse[i] != '\\' && directory_name_reverse[i] != '/') directory_name += directory_name_reverse[i];
	}
	//TODO: End portion that can be put in external function.

	//This portion of code looks at all the contents in the directory of the directory we're checking the existence of, and looks to see if the directory exists.
	//If it does, then return true. Else return false.

	std::vector<std::string> folders; //Stores all the folder names it finds.

	getFolders(folderpath, folders); //Grabs all the folders in the folder containing the folder which we're checking the existence of.

	if (folders.size() == 0)
	{
		return false; //If it found nothing...The directory definitely does not exist!
	}

	for (unsigned int i = 0; i < folders.size(); ++i)
	{
		if (folders[i] == directory_name) return true; //Yes, directory exists.
	}

	return false; //Default case: does not exist.
} //FileManager::directoryExists()

void FileManager::seperatePathFromFilename(std::string &path_with_filename, std::string &path)
{
	//Loop from the back, find the /, chop off everything.

	int count = 0;
	std::string input(path_with_filename);
	std::cout << "Starting with: " << input << "\n";
	std::string::iterator i = input.end();
	bool done = false;
	while (!done)
	{
		//If it found where the filepath ends...
		if ((*i) != '\\')
		{
			--i; //Keep going.
			input.pop_back(); //Delete the last character.
			count++;
		}
		else
		{
			done = true;
		}
	}

	path = input;
}

void FileManager::getFolders(std::string path, std::vector<std::string> &folders) //Get all the folders in a directory.
{
	#if OS == OS_WINDOWS
		struct stat s; //Required for the Windows version of the code
	#endif

	DIR *dir ; //Open the bases folder.

	if ((dir = opendir(path.c_str())) == nullptr) //Open directory. With error checking.
	{
		std::string *filename = new std::string; //The filename.
		*filename = mstring::toString(__FILE__); //Convert the char* that is filename to a string.
		std::string *message = new std::string;
		*message = "Failed to open directory.";
		merror::Error *error = generateError(merror::FUNCTION_FAILURE, message, merror::SEVERITY_IGNORE, __LINE__, filename);
		throw error;
	}

	struct dirent *entry = readdir(dir); //The current directory entry

	while (entry != NULL) //Loop through all the folders (and files) in this directory.
	{
		#if OS == OS_WINDOWS

			//TODO: Test this to see if it works in Windows.

			stat(entry->d_name, &s);
			if (s.st_mode & S_IFDIR)
			{
				if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) //Make sure it's not the current directory, or the one containing this directory!
				{
					folders.push_back(entry->d_name);
				}
			}

			entry = readdir(dir); //Load in the next entry.

		#else

			if (entry->d_type == DT_DIR) //If the entry type is a folder.
			{
				if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) //Make sure it's not the current directory, or the one containing this directory!
				{
					folders.push_back(entry->d_name);
				}
			}

		#endif
	}

	closedir(dir);
} //FileManager::getFolders()

} //namespace mfile
<commit_msg>Done testing, fixed the seperatePathFromFilename function (it should be fixed anyway.<commit_after>/* Please refer to license.txt */

#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <dirent.h>

#include "file.hpp"

#include "../error/error.hpp"

#include "../string/string.hpp"

#include "../internal_header.hpp"

namespace mfile
{

FileManager::FileManager()
{
}

FileManager::~FileManager()
{
}

void FileManager::exportFile(std::string filepath, std::string output_data, bool overwrite) //Export a file.
{
	FILE *file = nullptr; //The file.

	if (overwrite) file = fopen(filepath.c_str(), "w+"); //Open the file for writing, overwriting whatever currently exists, if anything.
	else file = fopen(filepath.c_str(), "a"); //Open the file for writing. Do not overwrite, append.

	if (!file) //Error checking.
	{
		//cout << "Failed to open file: \"" << filepath << "\".\n"; //Let the user know there was an error.
		//cout << "Attempting to create folder...\n"; //Let the user know we're trying to create the directory.

		//TODO: This portiong needs to be put into a "make_directories_until()" function.

		//TODO: This needs to be adjusted to recursively make the missing folders.

		bool start_saving = false; //Start saving the characters from the string?
		std::string folderpath = ""; //The folderpath.
		std::string temp_string = ""; //Folderpath is initially read into this, backwards. Used for ordering it correctly.
		for (int i = filepath.length() - 1; i >= 0; --i) //Loop through and extract the folderpath
		{
			if (!start_saving && (filepath[i] == '\\' || filepath[i] == '/')) //If not already saving the characters...Check if it's a / or \ character.
			{
				start_saving = true; //Yay, end of filename found, now we can extract the folderpath.
			}
			if (start_saving) //Ok, it is saving the characters.
			{
				temp_string += filepath[i]; //Save the character.
			}
		}
		for (int i = temp_string.length() - 1; i >= 0; --i) //Now reverse the order of characters so that the folderpath is no longer backwards.
		{
			folderpath += temp_string[i]; //Save the character.
		}

		try
		{
			mkDir("./" + folderpath); //Create the folder. With error checking.
		}
		catch (...)
		{
			std::string *filename = new std::string; //The filename.
			*filename = mstring::toString(__FILE__); //Convert the char* that is filename to a string.
			std::string *message = new std::string;
			*message = "Failed to create directory: \"";
			*message += folderpath;
			*message += "\".";
			merror::Error *error = generateError(merror::FUNCTION_FAILURE, message, merror::SEVERITY_IGNORE, __LINE__, filename);
			throw error;
		}

		if (overwrite) file = fopen(filepath.c_str(), "w+"); //Open the file for writing, overwriting any currently existing file.
		else file = fopen(filepath.c_str(), "a"); //Open the file for writing. Do not overwrite, append.

		if (!file) //Error checking.
		{
			std::string *filename = new std::string; //The filename.
			*filename = mstring::toString(__FILE__); //Convert the char* that is filename to a string.
			std::string *message = new std::string;
			*message = "Failed to create file.";
			merror::Error *error = generateError(merror::FUNCTION_FAILURE, message, merror::SEVERITY_IGNORE, __LINE__, filename);
			throw error; //Failure.
		}

		//TODO: End portion that needs being put into a "make_directories_until()" function.
	}

	fprintf(file, output_data.c_str());  //Write out the string.

	fclose(file); //Close the file.
} //FileManager::exportFile()

void FileManager::mkDir(std::string path) //Create a directory at the specified location.
{
	#if OS == OS_WINDOWS //If the operating system is windows.
		if (mkdir(path.c_str()) == -1) //Create the directory.
		{
			//throw strerror(errno); //Throw an error. //TODO: Refine the error to use the error module.
			std::string *error_message = new std::string; //The error message.
			*error_message = mstring::toString(strerror(errno)); //Convert the char* that is strerror to a string.
			std::string *filename = new std::string; //The filename.
			*filename = mstring::toString(__FILE__); //Convert the char* that is filename to a string.
			merror::Error *error = generateError(merror::FUNCTION_FAILURE, error_message, merror::SEVERITY_IGNORE, __LINE__, filename);
			throw error;
		}
	#else //OS is not windows.
		if (mkdir(path.c_str(), 0777) == -1)//creating a directory
		{
			//throw strerror(errno); //Throw an error. //TODO: Refine the error to use the error module.
			std::string *error_message = new std::string; //The error message.
			*error_message = mstring::toString(strerror(errno)); //Convert the char* that is strerror to a string.
			std::string *filename = new std::string; //The filename.
			*filename = mstring::toString(__FILE__); //Convert the char* that is filename to a string.
			merror::Error *error = generateError(merror::FUNCTION_FAILURE, error_message, merror::SEVERITY_IGNORE, __LINE__, filename);
			throw error;
		}
	#endif
}

bool FileManager::directoryExists(std::string path) //Checks if specified directory exists.
{
	//This function could probably be done better with a call to an external library's superoptimised directory_exists() function.
	//But, until such a time that we have such a library, this will be used.

	//TODO: This portion probably can be put into an external function.

	//This portion of code determines the path to the directory the directory we're looking for is in.

	bool start_saving = false; //Start saving the characters from the string?
	std::string folderpath = ""; //The folderpath.
	std::string temp_string = ""; //Folderpath is initially read into this, backwards. Used for ordering it correctly.
	std::string directory_name_reverse = ""; //The name of the folder it's looking for. Reversed. This is used because the path is read backwards and everything after the slash is chopped off, thus determining the directory we're looking for's name.
	std::string directory_name = ""; //The name of the folder it's looking for.
	for (int i = path.length() - 1; i >= 0; --i) //Loop through and extract the folderpath. Pretty much the folder the folder is in.
	{
		if (!start_saving && (path[i] == '\\' || path[i] == '/')) //If not already saving the characters...Check if it's a / or \ character.
		{
			start_saving = true; //Yay, end of filename found, now we can extract the folderpath.
			directory_name_reverse += path[i];
		}
		else if (start_saving) //Ok, it is saving the characters.
		{
			temp_string += path[i]; //Save the character.
		}
	}
	for (int i = temp_string.length() - 1; i >= 0; --i) //Now reverse the order of characters so that the folderpath is no longer backwards.
	{
		folderpath += temp_string[i]; //Save the character.
	}
	for (int i = directory_name_reverse.length() - 1;  i >= 0; --i)
	{
		if (directory_name_reverse[i] != '\\' && directory_name_reverse[i] != '/') directory_name += directory_name_reverse[i];
	}
	//TODO: End portion that can be put in external function.

	//This portion of code looks at all the contents in the directory of the directory we're checking the existence of, and looks to see if the directory exists.
	//If it does, then return true. Else return false.

	std::vector<std::string> folders; //Stores all the folder names it finds.

	getFolders(folderpath, folders); //Grabs all the folders in the folder containing the folder which we're checking the existence of.

	if (folders.size() == 0)
	{
		return false; //If it found nothing...The directory definitely does not exist!
	}

	for (unsigned int i = 0; i < folders.size(); ++i)
	{
		if (folders[i] == directory_name) return true; //Yes, directory exists.
	}

	return false; //Default case: does not exist.
} //FileManager::directoryExists()

void FileManager::seperatePathFromFilename(std::string &path_with_filename, std::string &path)
{
	//Loop from the back, find the /, chop off everything.

	std::string input(path_with_filename);
	std::string::iterator i = input.end();
	bool done = false;
	while (!done)
	{
		//If it found where the filepath ends...
		if ((*i) != '/')
		{
			--i; //Keep going.
			input.pop_back(); //Delete the last character.
		}
		else
		{
			done = true;
		}
	}

	path = input;
}

void FileManager::getFolders(std::string path, std::vector<std::string> &folders) //Get all the folders in a directory.
{
	#if OS == OS_WINDOWS
		struct stat s; //Required for the Windows version of the code
	#endif

	DIR *dir ; //Open the bases folder.

	if ((dir = opendir(path.c_str())) == nullptr) //Open directory. With error checking.
	{
		std::string *filename = new std::string; //The filename.
		*filename = mstring::toString(__FILE__); //Convert the char* that is filename to a string.
		std::string *message = new std::string;
		*message = "Failed to open directory.";
		merror::Error *error = generateError(merror::FUNCTION_FAILURE, message, merror::SEVERITY_IGNORE, __LINE__, filename);
		throw error;
	}

	struct dirent *entry = readdir(dir); //The current directory entry

	while (entry != NULL) //Loop through all the folders (and files) in this directory.
	{
		#if OS == OS_WINDOWS

			//TODO: Test this to see if it works in Windows.

			stat(entry->d_name, &s);
			if (s.st_mode & S_IFDIR)
			{
				if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) //Make sure it's not the current directory, or the one containing this directory!
				{
					folders.push_back(entry->d_name);
				}
			}

			entry = readdir(dir); //Load in the next entry.

		#else

			if (entry->d_type == DT_DIR) //If the entry type is a folder.
			{
				if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) //Make sure it's not the current directory, or the one containing this directory!
				{
					folders.push_back(entry->d_name);
				}
			}

		#endif
	}

	closedir(dir);
} //FileManager::getFolders()

} //namespace mfile
<|endoftext|>