<commit_before>/*
	Copyright (C) 2003-2013 by Kristina Simpson <sweet.kristas@gmail.com>

	This software is provided 'as-is', without any express or implied
	warranty. In no event will the authors be held liable for any damages
	arising from the use of this software.

	Permission is granted to anyone to use this software for any purpose,
	including commercial applications, and to alter it and redistribute it
	freely, subject to the following restrictions:

	   1. The origin of this software must not be misrepresented; you must not
	   claim that you wrote the original software. If you use this software
	   in a product, an acknowledgment in the product documentation would be
	   appreciated but is not required.

	   2. Altered source versions must be plainly marked as such, and must not be
	   misrepresented as being the original software.

	   3. This notice may not be removed or altered from any source
	   distribution.
*/

#include <iomanip>

#include "Blittable.hpp"

#include "to_roman.hpp"
#include "utf8_to_codepoint.hpp"

#include "xhtml_block_box.hpp"
#include "xhtml_listitem_box.hpp"
#include "xhtml_layout_engine.hpp"

namespace xhtml
{
	using namespace css;

	namespace
	{
		const char32_t marker_disc = 0x2022;
		const char32_t marker_circle = 0x25e6;
		const char32_t marker_square = 0x25a0;
		const char32_t marker_lower_greek = 0x03b1 - 1;
		const char32_t marker_lower_greek_end = 0x03c9;
		const char32_t marker_lower_latin = 0x0061 - 1;
		const char32_t marker_lower_latin_end = 0x007a;
		const char32_t marker_upper_latin = 0x0041 - 1;
		const char32_t marker_upper_latin_end = 0x005A;
		const char32_t marker_armenian = 0x0531 - 1;
		const char32_t marker_armenian_end = 0x0556;
		const char32_t marker_georgian = 0x10d0 - 1;
		const char32_t marker_georgian_end = 0x10f6;
	}

	ListItemBox::ListItemBox(const BoxPtr& parent, const StyleNodePtr& node, const RootBoxPtr& root, int count)
		: Box(BoxId::LIST_ITEM, parent, node, root),
		  count_(count),
		  marker_(utils::codepoint_to_utf8(marker_disc))
	{
		addChild(std::make_shared<BlockBox>(parent, node, root));
	}

	std::string ListItemBox::toString() const
	{
		std::ostringstream ss;
		ss << "ListItemBox: " << getDimensions().content_ << (isFloat() ? " floating" : "");
		return ss.str();
	}

	void ListItemBox::handleLayout(LayoutEngine& eng, const Dimensions& containing)
	{
		auto lst = getStyleNode()->getListStyleType();
		switch(lst) {
			case ListStyleType::DISC: /* is the default */ break;
			case ListStyleType::CIRCLE:
				marker_ = utils::codepoint_to_utf8(marker_circle);
				break;
			case ListStyleType::SQUARE:
				marker_ = utils::codepoint_to_utf8(marker_square);
				break;
			case ListStyleType::DECIMAL: {
				std::ostringstream ss;
				ss << std::dec << count_ << ".";
				marker_ = ss.str();
				break;
			}
			case ListStyleType::DECIMAL_LEADING_ZERO: {
				std::ostringstream ss;
				ss << std::dec << std::setfill('0') << std::setw(2) << count_ << ".";
				marker_ = ss.str();
				break;
			}
			case ListStyleType::LOWER_ROMAN:
				if(count_ < 4000) {
					marker_ = to_roman(count_, true) + ".";
				}
				break;
			case ListStyleType::UPPER_ROMAN:
				if(count_ < 4000) {
					marker_ = to_roman(count_, false) + ".";
				}
				break;
			case ListStyleType::LOWER_GREEK:
				if(count_ <= (marker_lower_greek_end - marker_lower_greek + 1)) {
					marker_ = utils::codepoint_to_utf8(marker_lower_greek + count_) + ".";
				}
				break;
			case ListStyleType::LOWER_ALPHA:
			case ListStyleType::LOWER_LATIN:
				if(count_ <= (marker_lower_latin_end - marker_lower_latin + 1)) {
					marker_ = utils::codepoint_to_utf8(marker_lower_latin + count_) + ".";
				}
				break;
			case ListStyleType::UPPER_ALPHA:
			case ListStyleType::UPPER_LATIN:
				if(count_ <= (marker_upper_latin_end - marker_upper_latin + 1)) {
					marker_ = utils::codepoint_to_utf8(marker_upper_latin + count_) + ".";
				}
				break;
			case ListStyleType::ARMENIAN:
				if(count_ <= (marker_armenian_end - marker_armenian + 1)) {
					marker_ = utils::codepoint_to_utf8(marker_armenian + count_) + ".";
				}
				break;
			case ListStyleType::GEORGIAN:
				if(count_ <= (marker_georgian_end - marker_georgian + 1)) {
					marker_ = utils::codepoint_to_utf8(marker_georgian + count_) + ".";
				}
				break;
			case ListStyleType::NONE:
			default:
				marker_.clear();
				break;
		}

		FixedPoint top = getMBPTop() + containing.content_.height;
		FixedPoint left = getMBPLeft();

		if(isFloat()) {
			// XXX fixme to use a more intelligent approach than iterating every pixel!
			const FixedPoint lh = 65536;//getDimensions().content_.height;
			const FixedPoint box_w = getDimensions().content_.width;

			FixedPoint y = getMBPTop();
			FixedPoint x = getMBPLeft();

			FixedPoint y1 = y + getOffset().y;
			left = getStyleNode()->getFloat() == Float::LEFT ? eng.getXAtPosition(y1, y1 + lh) + x : eng.getX2AtPosition(y1, y1 + lh);
			FixedPoint w = eng.getWidthAtPosition(y1, y1 + lh, containing.content_.width);
			bool placed = false;
			while(!placed) {
				if(w >= box_w) {
					left = left - (getStyleNode()->getFloat() == Float::LEFT ? x : box_w);
					top = y;
					placed = true;
				} else {
					y += lh;
					y1 = y + getOffset().y;
					left = getStyleNode()->getFloat() == Float::LEFT ? eng.getXAtPosition(y1, y1 + lh) + x : eng.getX2AtPosition(y1, y1 + lh);
					w = eng.getWidthAtPosition(y1, y1 + lh, containing.content_.width);
				}
			}
		}

		setContentX(left);
		setContentY(top);

		auto& css_height = getStyleNode()->getHeight();
		if(!css_height->isAuto()) {
			FixedPoint h = css_height->getLength().compute(containing.content_.height);
			//if(h > child_height_) {
			//	/* apply overflow properties */
			//}
			setContentHeight(h);
		}

	}

	void ListItemBox::handlePreChildLayout(LayoutEngine& eng, const Dimensions& containing)
	{
		FixedPoint containing_width = containing.content_.width;

		calculateHorzMPB(containing_width);
		calculateVertMPB(containing.content_.height);

		const auto& css_width = getStyleNode()->getWidth();
		FixedPoint width = 0;
		if(!css_width->isAuto()) {
			width = css_width->getLength().compute(containing_width);
		} else {
			width = containing_width;
		}

		setContentWidth(width);
		setContentHeight(0);
	}

	void ListItemBox::handlePostChildLayout(LayoutEngine& eng, BoxPtr child)
	{
		setContentHeight(getHeight() + child->getHeight() + child->getMBPBottom());
	}

	void ListItemBox::handleRender(const KRE::SceneTreePtr& scene_tree, const point& offset) const
	{
		// XXX should figure out if there is a cleaner way of doing this.
		auto y = getLineHeight();
		auto& fnt = getStyleNode()->getFont();

		auto& img = getStyleNode()->getListStyleImage();
		if(getStyleNode()->getListStyleImage() != nullptr) {
			// There are some other calculations we should do here if there is an
			// intrinsic ration to use.
			int em = static_cast<int>(fnt->getFontSize() / 72.0f * static_cast<float>(RenderContext::get().getDPI()));
			auto tex = img->getTexture(em, em);
			if(tex != nullptr) {
				auto rend = std::make_shared<KRE::Blittable>(tex);
				rend->setCentre(KRE::Blittable::Centre::BOTTOM_LEFT);
				rend->setCentreCoords(pointf(0.0f, y / LayoutEngine::getFixedPointScaleFloat()));
				scene_tree->addObject(rend);
			}
		} else {
			auto path = fnt->getGlyphPath(marker_);
			std::vector<point> new_path;
			FixedPoint path_width = path.back().x - path.front().x + fnt->calculateCharAdvance(' ');

			for(auto& p : path) {
				new_path.emplace_back(p.x + 5 - path_width, p.y + y);
			}
			auto fontr = fnt->createRenderableFromPath(nullptr, marker_, new_path);
			fontr->setColorPointer(getStyleNode()->getColor());
			scene_tree->addObject(fontr);
		}
	}

}
<commit_msg>Experimental change to make the width requirement for positioning a floating list item require more than 1 pixel width.<commit_after>/*
	Copyright (C) 2003-2013 by Kristina Simpson <sweet.kristas@gmail.com>

	This software is provided 'as-is', without any express or implied
	warranty. In no event will the authors be held liable for any damages
	arising from the use of this software.

	Permission is granted to anyone to use this software for any purpose,
	including commercial applications, and to alter it and redistribute it
	freely, subject to the following restrictions:

	   1. The origin of this software must not be misrepresented; you must not
	   claim that you wrote the original software. If you use this software
	   in a product, an acknowledgment in the product documentation would be
	   appreciated but is not required.

	   2. Altered source versions must be plainly marked as such, and must not be
	   misrepresented as being the original software.

	   3. This notice may not be removed or altered from any source
	   distribution.
*/

#include <iomanip>

#include "Blittable.hpp"

#include "to_roman.hpp"
#include "utf8_to_codepoint.hpp"

#include "xhtml_block_box.hpp"
#include "xhtml_listitem_box.hpp"
#include "xhtml_layout_engine.hpp"

namespace xhtml
{
	using namespace css;

	namespace
	{
		const char32_t marker_disc = 0x2022;
		const char32_t marker_circle = 0x25e6;
		const char32_t marker_square = 0x25a0;
		const char32_t marker_lower_greek = 0x03b1 - 1;
		const char32_t marker_lower_greek_end = 0x03c9;
		const char32_t marker_lower_latin = 0x0061 - 1;
		const char32_t marker_lower_latin_end = 0x007a;
		const char32_t marker_upper_latin = 0x0041 - 1;
		const char32_t marker_upper_latin_end = 0x005A;
		const char32_t marker_armenian = 0x0531 - 1;
		const char32_t marker_armenian_end = 0x0556;
		const char32_t marker_georgian = 0x10d0 - 1;
		const char32_t marker_georgian_end = 0x10f6;
	}

	ListItemBox::ListItemBox(const BoxPtr& parent, const StyleNodePtr& node, const RootBoxPtr& root, int count)
		: Box(BoxId::LIST_ITEM, parent, node, root),
		  count_(count),
		  marker_(utils::codepoint_to_utf8(marker_disc))
	{
		addChild(std::make_shared<BlockBox>(parent, node, root));
	}

	std::string ListItemBox::toString() const
	{
		std::ostringstream ss;
		ss << "ListItemBox: " << getDimensions().content_ << (isFloat() ? " floating" : "");
		return ss.str();
	}

	void ListItemBox::handleLayout(LayoutEngine& eng, const Dimensions& containing)
	{
		auto lst = getStyleNode()->getListStyleType();
		switch(lst) {
			case ListStyleType::DISC: /* is the default */ break;
			case ListStyleType::CIRCLE:
				marker_ = utils::codepoint_to_utf8(marker_circle);
				break;
			case ListStyleType::SQUARE:
				marker_ = utils::codepoint_to_utf8(marker_square);
				break;
			case ListStyleType::DECIMAL: {
				std::ostringstream ss;
				ss << std::dec << count_ << ".";
				marker_ = ss.str();
				break;
			}
			case ListStyleType::DECIMAL_LEADING_ZERO: {
				std::ostringstream ss;
				ss << std::dec << std::setfill('0') << std::setw(2) << count_ << ".";
				marker_ = ss.str();
				break;
			}
			case ListStyleType::LOWER_ROMAN:
				if(count_ < 4000) {
					marker_ = to_roman(count_, true) + ".";
				}
				break;
			case ListStyleType::UPPER_ROMAN:
				if(count_ < 4000) {
					marker_ = to_roman(count_, false) + ".";
				}
				break;
			case ListStyleType::LOWER_GREEK:
				if(count_ <= (marker_lower_greek_end - marker_lower_greek + 1)) {
					marker_ = utils::codepoint_to_utf8(marker_lower_greek + count_) + ".";
				}
				break;
			case ListStyleType::LOWER_ALPHA:
			case ListStyleType::LOWER_LATIN:
				if(count_ <= (marker_lower_latin_end - marker_lower_latin + 1)) {
					marker_ = utils::codepoint_to_utf8(marker_lower_latin + count_) + ".";
				}
				break;
			case ListStyleType::UPPER_ALPHA:
			case ListStyleType::UPPER_LATIN:
				if(count_ <= (marker_upper_latin_end - marker_upper_latin + 1)) {
					marker_ = utils::codepoint_to_utf8(marker_upper_latin + count_) + ".";
				}
				break;
			case ListStyleType::ARMENIAN:
				if(count_ <= (marker_armenian_end - marker_armenian + 1)) {
					marker_ = utils::codepoint_to_utf8(marker_armenian + count_) + ".";
				}
				break;
			case ListStyleType::GEORGIAN:
				if(count_ <= (marker_georgian_end - marker_georgian + 1)) {
					marker_ = utils::codepoint_to_utf8(marker_georgian + count_) + ".";
				}
				break;
			case ListStyleType::NONE:
			default:
				marker_.clear();
				break;
		}

		FixedPoint top = getMBPTop() + containing.content_.height;
		FixedPoint left = getMBPLeft();

		if(isFloat()) {
			// XXX fixme to use a more intelligent approach than iterating every pixel!
			const FixedPoint lh = 65536;//getDimensions().content_.height;
			const FixedPoint box_w = getDimensions().content_.width;

			FixedPoint y = getMBPTop();
			FixedPoint x = getMBPLeft();

			FixedPoint y1 = y + getOffset().y;
			left = getStyleNode()->getFloat() == Float::LEFT ? eng.getXAtPosition(y1, y1 + lh) + x : eng.getX2AtPosition(y1, y1 + lh);
			FixedPoint w = eng.getWidthAtPosition(y1, y1 + lh, containing.content_.width);
			bool placed = false;
			while(!placed) {
				if((w - box_w) >= LayoutEngine::getFixedPointScale()) {
					left = left - (getStyleNode()->getFloat() == Float::LEFT ? x : box_w);
					top = y;
					placed = true;
				} else {
					y += lh;
					y1 = y + getOffset().y;
					left = getStyleNode()->getFloat() == Float::LEFT ? eng.getXAtPosition(y1, y1 + lh) + x : eng.getX2AtPosition(y1, y1 + lh);
					w = eng.getWidthAtPosition(y1, y1 + lh, containing.content_.width);
				}
			}
		}

		setContentX(left);
		setContentY(top);

		auto& css_height = getStyleNode()->getHeight();
		if(!css_height->isAuto()) {
			FixedPoint h = css_height->getLength().compute(containing.content_.height);
			//if(h > child_height_) {
			//	/* apply overflow properties */
			//}
			setContentHeight(h);
		}

	}

	void ListItemBox::handlePreChildLayout(LayoutEngine& eng, const Dimensions& containing)
	{
		FixedPoint containing_width = containing.content_.width;

		calculateHorzMPB(containing_width);
		calculateVertMPB(containing.content_.height);

		const auto& css_width = getStyleNode()->getWidth();
		FixedPoint width = 0;
		if(!css_width->isAuto()) {
			width = css_width->getLength().compute(containing_width);
		} else {
			width = containing_width;
		}

		setContentWidth(width);
		setContentHeight(0);
	}

	void ListItemBox::handlePostChildLayout(LayoutEngine& eng, BoxPtr child)
	{
		setContentHeight(getHeight() + child->getHeight() + child->getMBPBottom());
	}

	void ListItemBox::handleRender(const KRE::SceneTreePtr& scene_tree, const point& offset) const
	{
		// XXX should figure out if there is a cleaner way of doing this.
		auto y = getLineHeight();
		auto& fnt = getStyleNode()->getFont();

		auto& img = getStyleNode()->getListStyleImage();
		if(getStyleNode()->getListStyleImage() != nullptr) {
			// There are some other calculations we should do here if there is an
			// intrinsic ration to use.
			int em = static_cast<int>(fnt->getFontSize() / 72.0f * static_cast<float>(RenderContext::get().getDPI()));
			auto tex = img->getTexture(em, em);
			if(tex != nullptr) {
				auto rend = std::make_shared<KRE::Blittable>(tex);
				rend->setCentre(KRE::Blittable::Centre::BOTTOM_LEFT);
				rend->setCentreCoords(pointf(0.0f, y / LayoutEngine::getFixedPointScaleFloat()));
				scene_tree->addObject(rend);
			}
		} else {
			auto path = fnt->getGlyphPath(marker_);
			std::vector<point> new_path;
			FixedPoint path_width = path.back().x - path.front().x + fnt->calculateCharAdvance(' ');

			for(auto& p : path) {
				new_path.emplace_back(p.x + 5 - path_width, p.y + y);
			}
			auto fontr = fnt->createRenderableFromPath(nullptr, marker_, new_path);
			fontr->setColorPointer(getStyleNode()->getColor());
			scene_tree->addObject(fontr);
		}
	}

}
<|endoftext|>


<commit_before>//
//  LocalNotificationSystem.cpp
//  Chilli Source
//  Created by Scott Downie on 01/07/2011.
//
//  The MIT License (MIT)
//
//  Copyright (c) 2011 Tag Games Limited
//
//  Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.
//

#ifdef CS_TARGETPLATFORM_IOS

#include <CSBackend/Platform/iOS/Core/Notification/LocalNotificationSystem.h>

#include <CSBackend/Platform/iOS/Core/String/NSStringUtils.h>

#import <UIKit/UIKit.h>

namespace CSBackend
{
    namespace iOS
    {
        namespace
        {
            LocalNotificationSystem* g_localNotificationSystem;
            std::vector<CSCore::NotificationSPtr> g_queuedNotifications;

            //---------------------------------------------------------------
            /// Convert UILocalNotification to Notification
            ///
            /// @author Scott Downie
            ///
            /// @param Apple UILocalNotification
            /// @param [Out] Chilli Source notification
            //---------------------------------------------------------------
            CSCore::NotificationUPtr ConvertUILocalNotificationToNotification(UILocalNotification* in_uiLocal)
            {
                CSCore::NotificationUPtr notification = CSCore::NotificationUPtr(new CSCore::Notification());
                notification->m_id = (CSCore::Notification::ID)[[in_uiLocal.userInfo objectForKey:@"ID"] unsignedIntValue];
                notification->m_priority = (CSCore::Notification::Priority)[[in_uiLocal.userInfo objectForKey:@"Priority"] unsignedIntValue];

                NSDictionary* nsParams = (NSDictionary*)[in_uiLocal.userInfo objectForKey:@"Params"];
                for(id key in nsParams)
                {
                    notification->m_params.SetValue([NSStringUtils newUTF8StringWithNSString:[nsParams objectForKey:key]], [NSStringUtils newUTF8StringWithNSString:key]);
                }

                return notification;
            }
        }
        CS_DEFINE_NAMEDTYPE(LocalNotificationSystem);
        //----------------------------------------------------------
        //----------------------------------------------------------
        LocalNotificationSystem::LocalNotificationSystem()
        : m_enabled(true)
        {
        }
        //--------------------------------------------------------
        //-------------------------------------------------------
        bool LocalNotificationSystem::IsA(CSCore::InterfaceIDType in_interfaceId) const
        {
            return (CSCore::LocalNotificationSystem::InterfaceID == in_interfaceId || LocalNotificationSystem::InterfaceID == in_interfaceId);
        }
        //--------------------------------------------------
        //---------------------------------------------------
        void LocalNotificationSystem::SetEnabled(bool in_enabled)
        {
            m_enabled = in_enabled;

            if (m_enabled == false)
            {
                CancelAll();
            }
        }
        //---------------------------------------------------
        //---------------------------------------------------
        void LocalNotificationSystem::ScheduleNotificationForTime(CSCore::Notification::ID in_id, const CSCore::ParamDictionary& in_params, TimeIntervalSecs in_time, CSCore::Notification::Priority in_priority)
        {
            @autoreleasepool
            {
                if (m_enabled == true)
                {
                    //Create the notifications
                    UILocalNotification* nsNotification = [[[UILocalNotification alloc] init] autorelease];
                    nsNotification.fireDate = [NSDate dateWithTimeIntervalSince1970:(NSTimeInterval)in_time];
                    nsNotification.timeZone = [NSTimeZone defaultTimeZone];
                    nsNotification.alertAction = @"View";

                    NSString* body = [NSStringUtils newNSStringWithUTF8String:in_params.GetValue("Body")];
                    nsNotification.alertBody = body;
                    [body release];

                    if(in_params.HasKey("Sound") == true)
                    {
                        NSString* sound = [NSStringUtils newNSStringWithUTF8String:in_params.GetValue("Sound")];
                        nsNotification.soundName = sound;
                        [sound release];
                    }
                    else
                    {
                        nsNotification.soundName = UILocalNotificationDefaultSoundName;
                    }

                    nsNotification.applicationIconBadgeNumber = 1;

                    NSMutableDictionary* nsParams = [[NSMutableDictionary alloc] init];
                    for(CSCore::ParamDictionary::const_iterator it = in_params.begin(); it != in_params.end(); ++it)
                    {
                        NSString* key = [NSStringUtils newNSStringWithUTF8String:it->first];
                        NSString* value = [NSStringUtils newNSStringWithUTF8String:it->second];
                        [nsParams setObject:key forKey:value];
                        [key release];
                        [value release];
                    }

                    //Encode the type ID into the notification so we can retrieve it at the other end
                    NSDictionary* pInfo = [NSDictionary dictionaryWithObjectsAndKeys:
                                           [NSNumber numberWithUnsignedInt:(u32)in_id], @"ID",
                                           [NSNumber numberWithUnsignedInt:(u32)in_priority], @"Priority",
                                           nsParams, @"Params",
                                           nil];

                    nsNotification.userInfo = pInfo;

                    // pInfo dictionary retains the pParams dictionary on insertion so we need to release
                    [nsParams release];

                    //Schedule this baby
                    [[UIApplication sharedApplication] scheduleLocalNotification:nsNotification];
                }
            }
        }
        //--------------------------------------------------------
        //--------------------------------------------------------
        void LocalNotificationSystem::GetScheduledNotifications(std::vector<CSCore::NotificationCSPtr>& out_notifications, TimeIntervalSecs in_time, TimeIntervalSecs in_period) const
        {
            for(UILocalNotification* nsNotification in [[UIApplication sharedApplication] scheduledLocalNotifications])
			{
                TimeIntervalSecs triggerTime = (TimeIntervalSecs)[nsNotification.fireDate timeIntervalSince1970];
                s32 dwDeltaSecs = (s32)(in_time - triggerTime);

				if(std::abs(dwDeltaSecs) <= in_period)
				{
                    CSCore::NotificationSPtr notification = ConvertUILocalNotificationToNotification(nsNotification);
					out_notifications.push_back(notification);
				}
			}
        }
        //------------------------------------------------
        //------------------------------------------------
        void LocalNotificationSystem::CancelByID(CSCore::Notification::ID in_id)
        {
			for(UILocalNotification* nsNotification in [[UIApplication sharedApplication] scheduledLocalNotifications])
			{
				CSCore::Notification::ID notificationId = [[nsNotification.userInfo objectForKey:@"ID"] unsignedIntValue];

				if(notificationId == in_id)
				{
					[[UIApplication sharedApplication] cancelLocalNotification:nsNotification];
				}
			}
        }
        //------------------------------------------------
        //------------------------------------------------
        void LocalNotificationSystem::CancelAll()
        {
            [[UIApplication sharedApplication] cancelAllLocalNotifications];
        }
        //--------------------------------------------------
        //---------------------------------------------------
        CSCore::IConnectableEvent<CSCore::LocalNotificationSystem::RecievedDelegate>& LocalNotificationSystem::GetRecievedEvent()
        {
            return m_receivedEvent;
        }
        //------------------------------------------------
        //------------------------------------------------
        bool LocalNotificationSystem::ApplicationDidFinishLaunchingWithOptions(UIApplication* inpApplication, NSDictionary* inpOptions)
        {
            //Reset the badge number
            inpApplication.applicationIconBadgeNumber = 0;

            UILocalNotification* pLocalNotification = [inpOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
            if(pLocalNotification)
            {
                CSCore::NotificationSPtr notification = ConvertUILocalNotificationToNotification(pLocalNotification);
                if (g_localNotificationSystem != nullptr)
                {
                    g_localNotificationSystem->OnNotificationRecieved(notification);
                }
                else
                {
                    g_queuedNotifications.push_back(notification);
                }
                return true;
            }

            return false;
        }
        //------------------------------------------------
        //------------------------------------------------
		void LocalNotificationSystem::ApplicationDidBecomeActive(UIApplication* inpApplication)
		{
			//Reset the badge number
            inpApplication.applicationIconBadgeNumber = 0;
		}
        //------------------------------------------------
        //------------------------------------------------
        void LocalNotificationSystem::ApplicationDidReceiveLocalNotification(UIApplication* inpApplication, UILocalNotification* inpNotification)
        {
            //Reset the badge number
            inpApplication.applicationIconBadgeNumber = (inpApplication.applicationIconBadgeNumber - 1);

            CSCore::NotificationSPtr notification = ConvertUILocalNotificationToNotification(inpNotification);
            if (g_localNotificationSystem != nullptr)
            {
                g_localNotificationSystem->OnNotificationRecieved(notification);
            }
            else
            {
                g_queuedNotifications.push_back(notification);
            }
        }
        //--------------------------------------------------------
        //--------------------------------------------------------
        void LocalNotificationSystem::OnInit()
        {
            CSCore::LocalNotificationSystem::OnInit();

            CS_ASSERT(g_localNotificationSystem == nullptr, "Cannot create more than 1 Local Notification System!");
            g_localNotificationSystem = this;

            for (const CSCore::NotificationSPtr& notification : g_queuedNotifications)
            {
                OnNotificationRecieved(notification);
            }

            g_queuedNotifications.clear();
            g_queuedNotifications.shrink_to_fit();
        }
        //--------------------------------------------------------
        //--------------------------------------------------------
        void LocalNotificationSystem::OnNotificationRecieved(const CSCore::NotificationSPtr& in_notification)
        {
            m_receivedEvent.NotifyConnections(in_notification);
        }
        //--------------------------------------------------------
        //--------------------------------------------------------
        void LocalNotificationSystem::OnDestroy()
        {
            g_localNotificationSystem = nullptr;
            CSCore::LocalNotificationSystem::OnDestroy();
        }
        //----------------------------------------------------------
        //----------------------------------------------------------
        LocalNotificationSystem::~LocalNotificationSystem()
        {
            g_localNotificationSystem = nullptr;
        }
    }
}

#endif<commit_msg>Requesting UI permissions for local notifications<commit_after>//
//  LocalNotificationSystem.cpp
//  Chilli Source
//  Created by Scott Downie on 01/07/2011.
//
//  The MIT License (MIT)
//
//  Copyright (c) 2011 Tag Games Limited
//
//  Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.
//

#ifdef CS_TARGETPLATFORM_IOS

#include <CSBackend/Platform/iOS/Core/Notification/LocalNotificationSystem.h>

#include <CSBackend/Platform/iOS/Core/String/NSStringUtils.h>

#import <UIKit/UIKit.h>

namespace CSBackend
{
    namespace iOS
    {
        namespace
        {
            LocalNotificationSystem* g_localNotificationSystem;
            std::vector<CSCore::NotificationSPtr> g_queuedNotifications;

            //---------------------------------------------------------------
            /// Convert UILocalNotification to Notification
            ///
            /// @author Scott Downie
            ///
            /// @param Apple UILocalNotification
            /// @param [Out] Chilli Source notification
            //---------------------------------------------------------------
            CSCore::NotificationUPtr ConvertUILocalNotificationToNotification(UILocalNotification* in_uiLocal)
            {
                CSCore::NotificationUPtr notification = CSCore::NotificationUPtr(new CSCore::Notification());
                notification->m_id = (CSCore::Notification::ID)[[in_uiLocal.userInfo objectForKey:@"ID"] unsignedIntValue];
                notification->m_priority = (CSCore::Notification::Priority)[[in_uiLocal.userInfo objectForKey:@"Priority"] unsignedIntValue];

                NSDictionary* nsParams = (NSDictionary*)[in_uiLocal.userInfo objectForKey:@"Params"];
                for(id key in nsParams)
                {
                    notification->m_params.SetValue([NSStringUtils newUTF8StringWithNSString:[nsParams objectForKey:key]], [NSStringUtils newUTF8StringWithNSString:key]);
                }

                return notification;
            }
        }
        CS_DEFINE_NAMEDTYPE(LocalNotificationSystem);
        //----------------------------------------------------------
        //----------------------------------------------------------
        LocalNotificationSystem::LocalNotificationSystem()
        : m_enabled(true)
        {
        }
        //--------------------------------------------------------
        //-------------------------------------------------------
        bool LocalNotificationSystem::IsA(CSCore::InterfaceIDType in_interfaceId) const
        {
            return (CSCore::LocalNotificationSystem::InterfaceID == in_interfaceId || LocalNotificationSystem::InterfaceID == in_interfaceId);
        }
        //--------------------------------------------------
        //---------------------------------------------------
        void LocalNotificationSystem::SetEnabled(bool in_enabled)
        {
            m_enabled = in_enabled;

            if (m_enabled == false)
            {
                CancelAll();
            }
        }
        //---------------------------------------------------
        //---------------------------------------------------
        void LocalNotificationSystem::ScheduleNotificationForTime(CSCore::Notification::ID in_id, const CSCore::ParamDictionary& in_params, TimeIntervalSecs in_time, CSCore::Notification::Priority in_priority)
        {
            @autoreleasepool
            {
                if (m_enabled == true)
                {
                    //Create the notifications
                    UILocalNotification* nsNotification = [[[UILocalNotification alloc] init] autorelease];
                    nsNotification.fireDate = [NSDate dateWithTimeIntervalSince1970:(NSTimeInterval)in_time];
                    nsNotification.timeZone = [NSTimeZone defaultTimeZone];
                    nsNotification.alertAction = @"View";

                    NSString* body = [NSStringUtils newNSStringWithUTF8String:in_params.GetValue("Body")];
                    nsNotification.alertBody = body;
                    [body release];

                    if(in_params.HasKey("Sound") == true)
                    {
                        NSString* sound = [NSStringUtils newNSStringWithUTF8String:in_params.GetValue("Sound")];
                        nsNotification.soundName = sound;
                        [sound release];
                    }
                    else
                    {
                        nsNotification.soundName = UILocalNotificationDefaultSoundName;
                    }

                    nsNotification.applicationIconBadgeNumber = 1;

                    NSMutableDictionary* nsParams = [[NSMutableDictionary alloc] init];
                    for(CSCore::ParamDictionary::const_iterator it = in_params.begin(); it != in_params.end(); ++it)
                    {
                        NSString* key = [NSStringUtils newNSStringWithUTF8String:it->first];
                        NSString* value = [NSStringUtils newNSStringWithUTF8String:it->second];
                        [nsParams setObject:key forKey:value];
                        [key release];
                        [value release];
                    }

                    //Encode the type ID into the notification so we can retrieve it at the other end
                    NSDictionary* pInfo = [NSDictionary dictionaryWithObjectsAndKeys:
                                           [NSNumber numberWithUnsignedInt:(u32)in_id], @"ID",
                                           [NSNumber numberWithUnsignedInt:(u32)in_priority], @"Priority",
                                           nsParams, @"Params",
                                           nil];

                    nsNotification.userInfo = pInfo;

                    // pInfo dictionary retains the pParams dictionary on insertion so we need to release
                    [nsParams release];

                    //Schedule this baby
                    [[UIApplication sharedApplication] scheduleLocalNotification:nsNotification];
                }
            }
        }
        //--------------------------------------------------------
        //--------------------------------------------------------
        void LocalNotificationSystem::GetScheduledNotifications(std::vector<CSCore::NotificationCSPtr>& out_notifications, TimeIntervalSecs in_time, TimeIntervalSecs in_period) const
        {
            for(UILocalNotification* nsNotification in [[UIApplication sharedApplication] scheduledLocalNotifications])
			{
                TimeIntervalSecs triggerTime = (TimeIntervalSecs)[nsNotification.fireDate timeIntervalSince1970];
                s32 dwDeltaSecs = (s32)(in_time - triggerTime);

				if(std::abs(dwDeltaSecs) <= in_period)
				{
                    CSCore::NotificationSPtr notification = ConvertUILocalNotificationToNotification(nsNotification);
					out_notifications.push_back(notification);
				}
			}
        }
        //------------------------------------------------
        //------------------------------------------------
        void LocalNotificationSystem::CancelByID(CSCore::Notification::ID in_id)
        {
			for(UILocalNotification* nsNotification in [[UIApplication sharedApplication] scheduledLocalNotifications])
			{
				CSCore::Notification::ID notificationId = [[nsNotification.userInfo objectForKey:@"ID"] unsignedIntValue];

				if(notificationId == in_id)
				{
					[[UIApplication sharedApplication] cancelLocalNotification:nsNotification];
				}
			}
        }
        //------------------------------------------------
        //------------------------------------------------
        void LocalNotificationSystem::CancelAll()
        {
            [[UIApplication sharedApplication] cancelAllLocalNotifications];
        }
        //--------------------------------------------------
        //---------------------------------------------------
        CSCore::IConnectableEvent<CSCore::LocalNotificationSystem::RecievedDelegate>& LocalNotificationSystem::GetRecievedEvent()
        {
            return m_receivedEvent;
        }
        //------------------------------------------------
        //------------------------------------------------
        bool LocalNotificationSystem::ApplicationDidFinishLaunchingWithOptions(UIApplication* inpApplication, NSDictionary* inpOptions)
        {
            //Reset the badge number
            inpApplication.applicationIconBadgeNumber = 0;

            UILocalNotification* pLocalNotification = [inpOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
            if(pLocalNotification)
            {
                CSCore::NotificationSPtr notification = ConvertUILocalNotificationToNotification(pLocalNotification);
                if (g_localNotificationSystem != nullptr)
                {
                    g_localNotificationSystem->OnNotificationRecieved(notification);
                }
                else
                {
                    g_queuedNotifications.push_back(notification);
                }
                return true;
            }

            return false;
        }
        //------------------------------------------------
        //------------------------------------------------
		void LocalNotificationSystem::ApplicationDidBecomeActive(UIApplication* inpApplication)
		{
			//Reset the badge number
            inpApplication.applicationIconBadgeNumber = 0;
		}
        //------------------------------------------------
        //------------------------------------------------
        void LocalNotificationSystem::ApplicationDidReceiveLocalNotification(UIApplication* inpApplication, UILocalNotification* inpNotification)
        {
            //Reset the badge number
            inpApplication.applicationIconBadgeNumber = (inpApplication.applicationIconBadgeNumber - 1);

            CSCore::NotificationSPtr notification = ConvertUILocalNotificationToNotification(inpNotification);
            if (g_localNotificationSystem != nullptr)
            {
                g_localNotificationSystem->OnNotificationRecieved(notification);
            }
            else
            {
                g_queuedNotifications.push_back(notification);
            }
        }
        //--------------------------------------------------------
        //--------------------------------------------------------
        void LocalNotificationSystem::OnInit()
        {
            if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)])
            {
                //From iOS 8 we need to request permissions to display notifications, to badge the app icon and to play a sound
                UIUserNotificationSettings* notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
                [[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
            }

            CSCore::LocalNotificationSystem::OnInit();

            CS_ASSERT(g_localNotificationSystem == nullptr, "Cannot create more than 1 Local Notification System!");
            g_localNotificationSystem = this;

            for (const CSCore::NotificationSPtr& notification : g_queuedNotifications)
            {
                OnNotificationRecieved(notification);
            }

            g_queuedNotifications.clear();
            g_queuedNotifications.shrink_to_fit();
        }
        //--------------------------------------------------------
        //--------------------------------------------------------
        void LocalNotificationSystem::OnNotificationRecieved(const CSCore::NotificationSPtr& in_notification)
        {
            m_receivedEvent.NotifyConnections(in_notification);
        }
        //--------------------------------------------------------
        //--------------------------------------------------------
        void LocalNotificationSystem::OnDestroy()
        {
            g_localNotificationSystem = nullptr;
            CSCore::LocalNotificationSystem::OnDestroy();
        }
        //----------------------------------------------------------
        //----------------------------------------------------------
        LocalNotificationSystem::~LocalNotificationSystem()
        {
            g_localNotificationSystem = nullptr;
        }
    }
}

#endif<|endoftext|>


<commit_before>#ifndef STAN_MATH_GPU_OPENCL_CONTEXT_HPP
#define STAN_MATH_GPU_OPENCL_CONTEXT_HPP
#ifdef STAN_OPENCL
#define __CL_ENABLE_EXCEPTIONS

#include <stan/math/prim/arr/err/check_opencl.hpp>
#include <stan/math/prim/scal/err/domain_error.hpp>
#include <CL/cl.hpp>
#include <cmath>
#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include <vector>

#define DEVICE_FILTER CL_DEVICE_TYPE_GPU

/**
 *  @file stan/math/gpu/opencl_context.hpp
 *  @brief Initialization for OpenCL:
 *    1. find OpenCL platforms and devices available
 *    2. create context
 *    3. set up job queue
 *    4. initialize kernel groups
 */

namespace stan {
namespace math {

static int initialized_ = 0;
typedef std::map<std::string, std::string> map_string;
typedef std::map<std::string, cl::Kernel> map_kernel;
typedef std::map<std::string, bool> map_bool;
static map_string kernel_groups;
static map_string kernel_strings;
static map_kernel kernels;
static map_bool compiled_kernels;
static std::string dummy_kernel
    = "__kernel void dummy(__global const int* foo) { };";

/**
 * Initalizes the global std::map variables that
 * hold the OpenCL kernel sources, the groups to
 * which each kernel is assigned to and the
 * information about which kernel was already compiled.
 *
 */
inline void init_kernel_groups() {
  // To identify the kernel group
  kernel_groups["transpose"] = "basic_matrix";
  kernel_groups["copy"] = "basic_matrix";
  kernel_groups["zeros"] = "basic_matrix";
  kernel_groups["identity"] = "basic_matrix";
  kernel_groups["copy_triangular"] = "basic_matrix";
  kernel_groups["copy_triangular_transposed"] = "basic_matrix";
  kernel_groups["add"] = "basic_matrix";
  kernel_groups["subtract"] = "basic_matrix";
  kernel_groups["copy_submatrix"] = "basic_matrix";
  kernel_groups["scalar_mul_diagonal"] = "matrix_multiply";
  kernel_groups["scalar_mul"] = "matrix_multiply";
  kernel_groups["basic_multiply"] = "matrix_multiply";
  kernel_groups["multiply_self_transposed"] = "matrix_multiply";
  kernel_groups["lower_tri_inv_step1"] = "matrix_inverse";
  kernel_groups["lower_tri_inv_step2"] = "matrix_inverse";
  kernel_groups["lower_tri_inv_step3"] = "matrix_inverse";
  kernel_groups["cholesky_block"] = "cholesky_decomposition";
  kernel_groups["check_nan"] = "check_gpu";
  kernel_groups["check_symmetric"] = "check_gpu";
  kernel_groups["check_diagonal_zeros"] = "check_gpu";

  kernel_groups["dummy"] = "timing";

  // Kernel group strings
  // the dummy kernel is the only one not included in files
  // so it is treated before the loop that iterates
  // through  kernels to load all

  kernel_strings["timing"] = dummy_kernel;
  kernel_strings["check_gpu"] =
#include <stan/math/prim/mat/fun/kern_gpu/check_gpu.cl>  // NOLINT
      ;                                                  // NOLINT
  kernel_strings["cholesky_decomposition"] =
#include <stan/math/prim/mat/fun/kern_gpu/cholesky_decomposition.cl>  // NOLINT
      ;                                                               // NOLINT
  kernel_strings["matrix_inverse"] =
#include <stan/math/prim/mat/fun/kern_gpu/matrix_inverse.cl>  // NOLINT
      ;                                                       // NOLINT
  kernel_strings["matrix_multiply"] =
#include <stan/math/prim/mat/fun/kern_gpu/matrix_multiply.cl>  // NOLINT
      ;                                                        // NOLINT
  kernel_strings["basic_matrix"] =
#include <stan/math/prim/mat/fun/kern_gpu/basic_matrix.cl>  // NOLINT
      ;                                                     // NOLINT

  // Check if the kernels were already compiled
  compiled_kernels["basic_matrix"] = false;
  compiled_kernels["matrix_multiply"] = false;
  compiled_kernels["timing"] = false;
  compiled_kernels["matrix_inverse"] = false;
  compiled_kernels["cholesky_decomposition"] = false;
  compiled_kernels["check_gpu"] = false;
}

// TODO(Rok): select some other platform/device than 0
// TODO(Rok): option to turn profiling OFF
/**
 * The class that represents the OpenCL runtime
 *
 * The class is used to find the OpenCL supported
 * platforms/devices and initialize the OpenCL
 * context/command queue.
 *
 */
class opencl_context {
 private:
  std::string description_;
  cl::Context oclContext_;
  cl::CommandQueue oclQueue_;
  cl::Platform oclPlatform_;
  cl::Device oclDevice_;

  size_t max_workgroup_size_;

  inline void init() {
    try {
      std::vector<cl::Platform> allPlatforms;
      cl::Platform::get(&allPlatforms);
      if (allPlatforms.size() == 0) {
        domain_error("OpenCL Initialization", "[Platform]", "",
                     "No OpenCL platforms found");
      }
      oclPlatform_ = allPlatforms[0];
      std::vector<cl::Device> allDevices;
      oclPlatform_.getDevices(DEVICE_FILTER, &allDevices);
      // TODO(Steve): This should throw which platform
      if (allDevices.size() == 0) {
        domain_error("OpenCL Initialization", "[Device]", "",
                     "No OpenCL devices found on the selected platform.");
      }
      oclDevice_ = allDevices[0];
      description_ = "Device " + oclDevice_.getInfo<CL_DEVICE_NAME>()
                     + " on the platform "
                     + oclPlatform_.getInfo<CL_PLATFORM_NAME>();
      allDevices[0].getInfo<size_t>(CL_DEVICE_MAX_WORK_GROUP_SIZE,
                                    &max_workgroup_size_);
      oclContext_ = cl::Context(allDevices);
      oclQueue_ = cl::CommandQueue(oclContext_, oclDevice_,
                                   CL_QUEUE_PROFILING_ENABLE, NULL);
      init_kernel_groups();
      // Compile the dummy kernel used for timing purposes
      cl::Program::Sources source(
          1, std::make_pair(dummy_kernel.c_str(), dummy_kernel.size()));
      cl::Program program_ = cl::Program(oclContext_, source);

      try {
        program_.build(allDevices);
        kernels["dummy"] = cl::Kernel(program_, "dummy", NULL);
        compiled_kernels["timing"] = true;
      } catch (const cl::Error &e) {
        domain_error(
            "OpenCL Initialization", e.what(), e.err(),
            "\nRetrieving build log\n",
            program_.getBuildInfo<CL_PROGRAM_BUILD_LOG>(allDevices[0]).c_str());
      }
    } catch (const cl::Error &e) {
      check_ocl_error("build", e);
    }
  }

 public:
  inline std::string description() const {
    if (initialized_ == 1) {
      return description_;
    }
    return "No device selected yet.";
  }

  inline cl::Context &context() {
    if (initialized_ == 0) {
      init();
      initialized_ = 1;
    }
    return oclContext_;
  }

  inline cl::CommandQueue &queue() {
    if (initialized_ == 0) {
      init();
      initialized_ = 1;
    }
    return oclQueue_;
  }
  inline size_t maxWorkgroupSize() { return max_workgroup_size_; }
};

static opencl_context opencl_context;

/**
 * Returns the description of the OpenCL
 * platform and device that is used.
 *
 */
inline std::string get_description() { return opencl_context.description(); }

/**
 * Returns the reference to the
 * OpenCL context. If no context was created,
 * a new context is created.
 *
 */
inline cl::Context &get_context() { return opencl_context.context(); }
/**
 * Returns the reference to the active
 * OpenCL command queue. If no context
 * and queue were created,
 * a new context and queue are created and
 * the reference to the new queue is returned.
 *
 */
inline cl::CommandQueue &get_queue() { return opencl_context.queue(); }
/**
 * Returns the reference to the active
 * OpenCL command queue. If no context
 * and queue were created,
 * a new context and queue are created and
 * the reference to the new queue is returned.
 *
 */
inline int get_maximum_workgroup_size() {
  return opencl_context.maxWorkgroupSize();
}

/**
 * Compiles all the kernel in the specified group
 *
 * @param group The kernel group name
 *
 */
inline void compile_kernel_group(std::string group) {
  cl::Context &ctx = get_context();
  std::vector<cl::Device> devices = ctx.getInfo<CL_CONTEXT_DEVICES>();
  std::string kernel_source = kernel_strings[group];
  cl::Program::Sources source(
      1, std::make_pair(kernel_source.c_str(), kernel_source.size()));
  cl::Program program_ = cl::Program(ctx, source);
  try {
    char temp[100];
    int local = 32;
    int gpu_local_max = sqrt(get_maximum_workgroup_size());
    if (gpu_local_max < local)
      local = gpu_local_max;
    // parameters that have special limits are for now handled here
    // kernels with paramters will be compiled separately
    // for now we have static parameters, so this will be OK
    snprintf(temp, sizeof(temp), "-D TS=%d -D TS1=%d -D TS2=%d ", local, local,
             local);
    program_.build(devices, temp);

    cl_int err = CL_SUCCESS;
    // Iterate over the kernel list
    // and get all the kernels from this group
    for (std::map<std::string, std::string>::iterator it
         = kernel_groups.begin();
         it != kernel_groups.end(); ++it) {
      if (group.compare((it->second).c_str()) == 0) {
        kernels[(it->first).c_str()]
            = cl::Kernel(program_, (it->first).c_str(), &err);
      }
    }
  } catch (const cl::Error &e) {
    domain_error(
        "OpenCL Initialization", e.what(), e.err(), "\nRetrieving build log\n",
        program_.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devices[0]).c_str());
  }
}

/**
 * Returns the reference to the compiled kernel.
 * If the kernel has not yet been compiled,
 * the kernel group is compiled first.
 *
 * @param name The kernel name
 *
 */
inline cl::Kernel get_kernel(std::string name) {
  // Compile the kernel group and return the kernel
  if (!compiled_kernels[kernel_groups[name]]) {
    compile_kernel_group(kernel_groups[name]);
    compiled_kernels[kernel_groups[name]] = true;
  }
  return kernels[name];
}

}  // namespace math
}  // namespace stan

#endif
#endif
<commit_msg>set local from int to size_t<commit_after>#ifndef STAN_MATH_GPU_OPENCL_CONTEXT_HPP
#define STAN_MATH_GPU_OPENCL_CONTEXT_HPP
#ifdef STAN_OPENCL
#define __CL_ENABLE_EXCEPTIONS

#include <stan/math/prim/arr/err/check_opencl.hpp>
#include <stan/math/prim/scal/err/domain_error.hpp>
#include <CL/cl.hpp>
#include <cmath>
#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include <vector>

#define DEVICE_FILTER CL_DEVICE_TYPE_GPU

/**
 *  @file stan/math/gpu/opencl_context.hpp
 *  @brief Initialization for OpenCL:
 *    1. find OpenCL platforms and devices available
 *    2. create context
 *    3. set up job queue
 *    4. initialize kernel groups
 */

namespace stan {
namespace math {

static int initialized_ = 0;
typedef std::map<std::string, std::string> map_string;
typedef std::map<std::string, cl::Kernel> map_kernel;
typedef std::map<std::string, bool> map_bool;
static map_string kernel_groups;
static map_string kernel_strings;
static map_kernel kernels;
static map_bool compiled_kernels;
static std::string dummy_kernel
    = "__kernel void dummy(__global const int* foo) { };";

/**
 * Initalizes the global std::map variables that
 * hold the OpenCL kernel sources, the groups to
 * which each kernel is assigned to and the
 * information about which kernel was already compiled.
 *
 */
inline void init_kernel_groups() {
  // To identify the kernel group
  kernel_groups["transpose"] = "basic_matrix";
  kernel_groups["copy"] = "basic_matrix";
  kernel_groups["zeros"] = "basic_matrix";
  kernel_groups["identity"] = "basic_matrix";
  kernel_groups["copy_triangular"] = "basic_matrix";
  kernel_groups["copy_triangular_transposed"] = "basic_matrix";
  kernel_groups["add"] = "basic_matrix";
  kernel_groups["subtract"] = "basic_matrix";
  kernel_groups["copy_submatrix"] = "basic_matrix";
  kernel_groups["scalar_mul_diagonal"] = "matrix_multiply";
  kernel_groups["scalar_mul"] = "matrix_multiply";
  kernel_groups["basic_multiply"] = "matrix_multiply";
  kernel_groups["multiply_self_transposed"] = "matrix_multiply";
  kernel_groups["lower_tri_inv_step1"] = "matrix_inverse";
  kernel_groups["lower_tri_inv_step2"] = "matrix_inverse";
  kernel_groups["lower_tri_inv_step3"] = "matrix_inverse";
  kernel_groups["cholesky_block"] = "cholesky_decomposition";
  kernel_groups["check_nan"] = "check_gpu";
  kernel_groups["check_symmetric"] = "check_gpu";
  kernel_groups["check_diagonal_zeros"] = "check_gpu";

  kernel_groups["dummy"] = "timing";

  // Kernel group strings
  // the dummy kernel is the only one not included in files
  // so it is treated before the loop that iterates
  // through  kernels to load all

  kernel_strings["timing"] = dummy_kernel;
  kernel_strings["check_gpu"] =
#include <stan/math/prim/mat/fun/kern_gpu/check_gpu.cl>  // NOLINT
      ;                                                  // NOLINT
  kernel_strings["cholesky_decomposition"] =
#include <stan/math/prim/mat/fun/kern_gpu/cholesky_decomposition.cl>  // NOLINT
      ;                                                               // NOLINT
  kernel_strings["matrix_inverse"] =
#include <stan/math/prim/mat/fun/kern_gpu/matrix_inverse.cl>  // NOLINT
      ;                                                       // NOLINT
  kernel_strings["matrix_multiply"] =
#include <stan/math/prim/mat/fun/kern_gpu/matrix_multiply.cl>  // NOLINT
      ;                                                        // NOLINT
  kernel_strings["basic_matrix"] =
#include <stan/math/prim/mat/fun/kern_gpu/basic_matrix.cl>  // NOLINT
      ;                                                     // NOLINT

  // Check if the kernels were already compiled
  compiled_kernels["basic_matrix"] = false;
  compiled_kernels["matrix_multiply"] = false;
  compiled_kernels["timing"] = false;
  compiled_kernels["matrix_inverse"] = false;
  compiled_kernels["cholesky_decomposition"] = false;
  compiled_kernels["check_gpu"] = false;
}

// TODO(Rok): select some other platform/device than 0
// TODO(Rok): option to turn profiling OFF
/**
 * The class that represents the OpenCL runtime
 *
 * The class is used to find the OpenCL supported
 * platforms/devices and initialize the OpenCL
 * context/command queue.
 *
 */
class opencl_context {
 private:
  std::string description_;
  cl::Context oclContext_;
  cl::CommandQueue oclQueue_;
  cl::Platform oclPlatform_;
  cl::Device oclDevice_;

  size_t max_workgroup_size_;

  inline void init() {
    try {
      std::vector<cl::Platform> allPlatforms;
      cl::Platform::get(&allPlatforms);
      if (allPlatforms.size() == 0) {
        domain_error("OpenCL Initialization", "[Platform]", "",
                     "No OpenCL platforms found");
      }
      oclPlatform_ = allPlatforms[0];
      std::vector<cl::Device> allDevices;
      oclPlatform_.getDevices(DEVICE_FILTER, &allDevices);
      // TODO(Steve): This should throw which platform
      if (allDevices.size() == 0) {
        domain_error("OpenCL Initialization", "[Device]", "",
                     "No OpenCL devices found on the selected platform.");
      }
      oclDevice_ = allDevices[0];
      description_ = "Device " + oclDevice_.getInfo<CL_DEVICE_NAME>()
                     + " on the platform "
                     + oclPlatform_.getInfo<CL_PLATFORM_NAME>();
      allDevices[0].getInfo<size_t>(CL_DEVICE_MAX_WORK_GROUP_SIZE,
                                    &max_workgroup_size_);
      oclContext_ = cl::Context(allDevices);
      oclQueue_ = cl::CommandQueue(oclContext_, oclDevice_,
                                   CL_QUEUE_PROFILING_ENABLE, NULL);
      init_kernel_groups();
      // Compile the dummy kernel used for timing purposes
      cl::Program::Sources source(
          1, std::make_pair(dummy_kernel.c_str(), dummy_kernel.size()));
      cl::Program program_ = cl::Program(oclContext_, source);

      try {
        program_.build(allDevices);
        kernels["dummy"] = cl::Kernel(program_, "dummy", NULL);
        compiled_kernels["timing"] = true;
      } catch (const cl::Error &e) {
        domain_error(
            "OpenCL Initialization", e.what(), e.err(),
            "\nRetrieving build log\n",
            program_.getBuildInfo<CL_PROGRAM_BUILD_LOG>(allDevices[0]).c_str());
      }
    } catch (const cl::Error &e) {
      check_ocl_error("build", e);
    }
  }

 public:
  inline std::string description() const {
    if (initialized_ == 1) {
      return description_;
    }
    return "No device selected yet.";
  }

  inline cl::Context &context() {
    if (initialized_ == 0) {
      init();
      initialized_ = 1;
    }
    return oclContext_;
  }

  inline cl::CommandQueue &queue() {
    if (initialized_ == 0) {
      init();
      initialized_ = 1;
    }
    return oclQueue_;
  }
  inline size_t maxWorkgroupSize() { return max_workgroup_size_; }
};

static opencl_context opencl_context;

/**
 * Returns the description of the OpenCL
 * platform and device that is used.
 *
 */
inline std::string get_description() { return opencl_context.description(); }

/**
 * Returns the reference to the
 * OpenCL context. If no context was created,
 * a new context is created.
 *
 */
inline cl::Context &get_context() { return opencl_context.context(); }
/**
 * Returns the reference to the active
 * OpenCL command queue. If no context
 * and queue were created,
 * a new context and queue are created and
 * the reference to the new queue is returned.
 *
 */
inline cl::CommandQueue &get_queue() { return opencl_context.queue(); }
/**
 * Returns the reference to the active
 * OpenCL command queue. If no context
 * and queue were created,
 * a new context and queue are created and
 * the reference to the new queue is returned.
 *
 */
inline int get_maximum_workgroup_size() {
  return opencl_context.maxWorkgroupSize();
}

/**
 * Compiles all the kernel in the specified group
 *
 * @param group The kernel group name
 *
 */
inline void compile_kernel_group(std::string group) {
  cl::Context &ctx = get_context();
  std::vector<cl::Device> devices = ctx.getInfo<CL_CONTEXT_DEVICES>();
  std::string kernel_source = kernel_strings[group];
  cl::Program::Sources source(
      1, std::make_pair(kernel_source.c_str(), kernel_source.size()));
  cl::Program program_ = cl::Program(ctx, source);
  try {
    char temp[100];
    size_t local = 32;
    size_t gpu_local_max = sqrt(get_maximum_workgroup_size());
    if (gpu_local_max < local)
      local = gpu_local_max;
    // parameters that have special limits are for now handled here
    // kernels with paramters will be compiled separately
    // for now we have static parameters, so this will be OK
    snprintf(temp, sizeof(temp), "-D TS=%zu -D TS1=%zu -D TS2=%zu ", local, local,
             local);
    program_.build(devices, temp);

    cl_int err = CL_SUCCESS;
    // Iterate over the kernel list
    // and get all the kernels from this group
    for (std::map<std::string, std::string>::iterator it
         = kernel_groups.begin();
         it != kernel_groups.end(); ++it) {
      if (group.compare((it->second).c_str()) == 0) {
        kernels[(it->first).c_str()]
            = cl::Kernel(program_, (it->first).c_str(), &err);
      }
    }
  } catch (const cl::Error &e) {
    domain_error(
        "OpenCL Initialization", e.what(), e.err(), "\nRetrieving build log\n",
        program_.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devices[0]).c_str());
  }
}

/**
 * Returns the reference to the compiled kernel.
 * If the kernel has not yet been compiled,
 * the kernel group is compiled first.
 *
 * @param name The kernel name
 *
 */
inline cl::Kernel get_kernel(std::string name) {
  // Compile the kernel group and return the kernel
  if (!compiled_kernels[kernel_groups[name]]) {
    compile_kernel_group(kernel_groups[name]);
    compiled_kernels[kernel_groups[name]] = true;
  }
  return kernels[name];
}

}  // namespace math
}  // namespace stan

#endif
#endif
<|endoftext|>


<commit_before>// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/browser/api/atom_api_cookies.h"

#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/gurl_converter.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "base/time/time.h"
#include "base/values.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
#include "net/cookies/cookie_monster.h"
#include "net/cookies/cookie_store.h"
#include "net/cookies/cookie_util.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"

using content::BrowserThread;

namespace mate {

template<>
struct Converter<atom::api::Cookies::Error> {
  static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
                                   atom::api::Cookies::Error val) {
    if (val == atom::api::Cookies::SUCCESS)
      return v8::Null(isolate);
    else
      return v8::Exception::Error(StringToV8(isolate, "failed"));
  }
};

template<>
struct Converter<net::CanonicalCookie> {
  static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
                                   const net::CanonicalCookie& val) {
    mate::Dictionary dict(isolate, v8::Object::New(isolate));
    dict.Set("name", val.Name());
    dict.Set("value", val.Value());
    dict.Set("domain", val.Domain());
    dict.Set("hostOnly", net::cookie_util::DomainIsHostOnly(val.Domain()));
    dict.Set("path", val.Path());
    dict.Set("secure", val.IsSecure());
    dict.Set("httpOnly", val.IsHttpOnly());
    dict.Set("session", !val.IsPersistent());
    if (val.IsPersistent())
      dict.Set("expirationDate", val.ExpiryDate().ToDoubleT());
    return dict.GetHandle();
  }
};

}  // namespace mate

namespace atom {

namespace api {

namespace {

// Returns whether |domain| matches |filter|.
bool MatchesDomain(std::string filter, const std::string& domain) {
  // Add a leading '.' character to the filter domain if it doesn't exist.
  if (net::cookie_util::DomainIsHostOnly(filter))
    filter.insert(0, ".");

  std::string sub_domain(domain);
  // Strip any leading '.' character from the input cookie domain.
  if (!net::cookie_util::DomainIsHostOnly(sub_domain))
    sub_domain = sub_domain.substr(1);

  // Now check whether the domain argument is a subdomain of the filter domain.
  for (sub_domain.insert(0, "."); sub_domain.length() >= filter.length();) {
    if (sub_domain == filter)
      return true;
    const size_t next_dot = sub_domain.find('.', 1);  // Skip over leading dot.
    sub_domain.erase(0, next_dot);
  }
  return false;
}

// Returns whether |cookie| matches |filter|.
bool MatchesCookie(const base::DictionaryValue* filter,
                   const net::CanonicalCookie& cookie) {
  std::string str;
  bool b;
  if (filter->GetString("name", &str) && str != cookie.Name())
    return false;
  if (filter->GetString("path", &str) && str != cookie.Path())
    return false;
  if (filter->GetString("domain", &str) && !MatchesDomain(str, cookie.Domain()))
    return false;
  if (filter->GetBoolean("secure", &b) && b != cookie.IsSecure())
    return false;
  if (filter->GetBoolean("session", &b) && b != !cookie.IsPersistent())
    return false;
  return true;
}

// Helper to returns the CookieStore.
inline net::CookieStore* GetCookieStore(
    scoped_refptr<net::URLRequestContextGetter> getter) {
  return getter->GetURLRequestContext()->cookie_store();
}

// Run |callback| on UI thread.
void RunCallbackInUI(const base::Closure& callback) {
  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
}

// Remove cookies from |list| not matching |filter|, and pass it to |callback|.
void FilterCookies(scoped_ptr<base::DictionaryValue> filter,
                   const Cookies::GetCallback& callback,
                   const net::CookieList& list) {
  net::CookieList result;
  for (const auto& cookie : list) {
    if (MatchesCookie(filter.get(), cookie))
      result.push_back(cookie);
  }
  RunCallbackInUI(base::Bind(callback, Cookies::SUCCESS, result));
}

// Receives cookies matching |filter| in IO thread.
void GetCookiesOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
                    scoped_ptr<base::DictionaryValue> filter,
                    const Cookies::GetCallback& callback) {
  std::string url;
  filter->GetString("url", &url);

  auto filtered_callback =
      base::Bind(FilterCookies, base::Passed(&filter), callback);

  net::CookieMonster* monster = GetCookieStore(getter)->GetCookieMonster();
  // Empty url will match all url cookies.
  if (url.empty())
    monster->GetAllCookiesAsync(filtered_callback);
  else
    monster->GetAllCookiesForURLAsync(GURL(url), filtered_callback);
}

// Removes cookie with |url| and |name| in IO thread.
void RemoveCookieOnIOThread(scoped_refptr<net::URLRequestContextGetter> getter,
                            const GURL& url, const std::string& name,
                            const base::Closure& callback) {
  GetCookieStore(getter)->DeleteCookieAsync(
      url, name, base::Bind(RunCallbackInUI, callback));
}

// Callback of SetCookie.
void OnSetCookie(const Cookies::SetCallback& callback, bool success) {
  RunCallbackInUI(
      base::Bind(callback, success ? Cookies::SUCCESS : Cookies::FAILED));
}

// Sets cookie with |details| in IO thread.
void SetCookieOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
                   scoped_ptr<base::DictionaryValue> details,
                   const Cookies::SetCallback& callback) {
  std::string url, name, value, domain, path;
  bool secure = false;
  bool http_only = false;
  double expiration_date;
  details->GetString("url", &url);
  details->GetString("name", &name);
  details->GetString("value", &value);
  details->GetString("domain", &domain);
  details->GetString("path", &path);
  details->GetBoolean("secure", &secure);
  details->GetBoolean("httpOnly", &http_only);

  base::Time expiration_time;
  if (details->GetDouble("expirationDate", &expiration_date)) {
    expiration_time = (expiration_date == 0) ?
        base::Time::UnixEpoch() :
        base::Time::FromDoubleT(expiration_date);
  }

  GetCookieStore(getter)->GetCookieMonster()->SetCookieWithDetailsAsync(
      GURL(url), name, value, domain, path, expiration_time, secure, http_only,
      false, false, false, net::COOKIE_PRIORITY_DEFAULT,
      base::Bind(OnSetCookie, callback));
}

}  // namespace

Cookies::Cookies(v8::Isolate* isolate,
                 content::BrowserContext* browser_context)
      : request_context_getter_(browser_context->GetRequestContext()) {
  Init(isolate);
}

Cookies::~Cookies() {
}

void Cookies::Get(const base::DictionaryValue& filter,
                  const GetCallback& callback) {
  scoped_ptr<base::DictionaryValue> copied(filter.CreateDeepCopy());
  auto getter = make_scoped_refptr(request_context_getter_);
  content::BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      base::Bind(GetCookiesOnIO, getter, Passed(&copied), callback));
}

void Cookies::Remove(const GURL& url, const std::string& name,
                     const base::Closure& callback) {
  auto getter = make_scoped_refptr(request_context_getter_);
  content::BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      base::Bind(RemoveCookieOnIOThread, getter, url, name, callback));
}

void Cookies::Set(const base::DictionaryValue& details,
                  const SetCallback& callback) {
  scoped_ptr<base::DictionaryValue> copied(details.CreateDeepCopy());
  auto getter = make_scoped_refptr(request_context_getter_);
  content::BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      base::Bind(SetCookieOnIO, getter, Passed(&copied), callback));
}

// static
mate::Handle<Cookies> Cookies::Create(
    v8::Isolate* isolate,
    content::BrowserContext* browser_context) {
  return mate::CreateHandle(isolate, new Cookies(isolate, browser_context));
}

// static
void Cookies::BuildPrototype(v8::Isolate* isolate,
                             v8::Local<v8::ObjectTemplate> prototype) {
  mate::ObjectTemplateBuilder(isolate, prototype)
      .SetMethod("get", &Cookies::Get)
      .SetMethod("remove", &Cookies::Remove)
      .SetMethod("set", &Cookies::Set);
}

}  // namespace api

}  // namespace atom
<commit_msg>No more GetCookieMonster<commit_after>// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/browser/api/atom_api_cookies.h"

#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/gurl_converter.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "base/time/time.h"
#include "base/values.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
#include "net/cookies/cookie_monster.h"
#include "net/cookies/cookie_store.h"
#include "net/cookies/cookie_util.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"

using content::BrowserThread;

namespace mate {

template<>
struct Converter<atom::api::Cookies::Error> {
  static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
                                   atom::api::Cookies::Error val) {
    if (val == atom::api::Cookies::SUCCESS)
      return v8::Null(isolate);
    else
      return v8::Exception::Error(StringToV8(isolate, "failed"));
  }
};

template<>
struct Converter<net::CanonicalCookie> {
  static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
                                   const net::CanonicalCookie& val) {
    mate::Dictionary dict(isolate, v8::Object::New(isolate));
    dict.Set("name", val.Name());
    dict.Set("value", val.Value());
    dict.Set("domain", val.Domain());
    dict.Set("hostOnly", net::cookie_util::DomainIsHostOnly(val.Domain()));
    dict.Set("path", val.Path());
    dict.Set("secure", val.IsSecure());
    dict.Set("httpOnly", val.IsHttpOnly());
    dict.Set("session", !val.IsPersistent());
    if (val.IsPersistent())
      dict.Set("expirationDate", val.ExpiryDate().ToDoubleT());
    return dict.GetHandle();
  }
};

}  // namespace mate

namespace atom {

namespace api {

namespace {

// Returns whether |domain| matches |filter|.
bool MatchesDomain(std::string filter, const std::string& domain) {
  // Add a leading '.' character to the filter domain if it doesn't exist.
  if (net::cookie_util::DomainIsHostOnly(filter))
    filter.insert(0, ".");

  std::string sub_domain(domain);
  // Strip any leading '.' character from the input cookie domain.
  if (!net::cookie_util::DomainIsHostOnly(sub_domain))
    sub_domain = sub_domain.substr(1);

  // Now check whether the domain argument is a subdomain of the filter domain.
  for (sub_domain.insert(0, "."); sub_domain.length() >= filter.length();) {
    if (sub_domain == filter)
      return true;
    const size_t next_dot = sub_domain.find('.', 1);  // Skip over leading dot.
    sub_domain.erase(0, next_dot);
  }
  return false;
}

// Returns whether |cookie| matches |filter|.
bool MatchesCookie(const base::DictionaryValue* filter,
                   const net::CanonicalCookie& cookie) {
  std::string str;
  bool b;
  if (filter->GetString("name", &str) && str != cookie.Name())
    return false;
  if (filter->GetString("path", &str) && str != cookie.Path())
    return false;
  if (filter->GetString("domain", &str) && !MatchesDomain(str, cookie.Domain()))
    return false;
  if (filter->GetBoolean("secure", &b) && b != cookie.IsSecure())
    return false;
  if (filter->GetBoolean("session", &b) && b != !cookie.IsPersistent())
    return false;
  return true;
}

// Helper to returns the CookieStore.
inline net::CookieStore* GetCookieStore(
    scoped_refptr<net::URLRequestContextGetter> getter) {
  return getter->GetURLRequestContext()->cookie_store();
}

// Run |callback| on UI thread.
void RunCallbackInUI(const base::Closure& callback) {
  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
}

// Remove cookies from |list| not matching |filter|, and pass it to |callback|.
void FilterCookies(scoped_ptr<base::DictionaryValue> filter,
                   const Cookies::GetCallback& callback,
                   const net::CookieList& list) {
  net::CookieList result;
  for (const auto& cookie : list) {
    if (MatchesCookie(filter.get(), cookie))
      result.push_back(cookie);
  }
  RunCallbackInUI(base::Bind(callback, Cookies::SUCCESS, result));
}

// Receives cookies matching |filter| in IO thread.
void GetCookiesOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
                    scoped_ptr<base::DictionaryValue> filter,
                    const Cookies::GetCallback& callback) {
  std::string url;
  filter->GetString("url", &url);

  auto filtered_callback =
      base::Bind(FilterCookies, base::Passed(&filter), callback);

  // Empty url will match all url cookies.
  if (url.empty())
    GetCookieStore(getter)->GetAllCookiesAsync(filtered_callback);
  else
    GetCookieStore(getter)->GetAllCookiesForURLAsync(GURL(url), filtered_callback);
}

// Removes cookie with |url| and |name| in IO thread.
void RemoveCookieOnIOThread(scoped_refptr<net::URLRequestContextGetter> getter,
                            const GURL& url, const std::string& name,
                            const base::Closure& callback) {
  GetCookieStore(getter)->DeleteCookieAsync(
      url, name, base::Bind(RunCallbackInUI, callback));
}

// Callback of SetCookie.
void OnSetCookie(const Cookies::SetCallback& callback, bool success) {
  RunCallbackInUI(
      base::Bind(callback, success ? Cookies::SUCCESS : Cookies::FAILED));
}

// Sets cookie with |details| in IO thread.
void SetCookieOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
                   scoped_ptr<base::DictionaryValue> details,
                   const Cookies::SetCallback& callback) {
  std::string url, name, value, domain, path;
  bool secure = false;
  bool http_only = false;
  double creation_date;
  double expiration_date;
  double last_access_date;
  details->GetString("url", &url);
  details->GetString("name", &name);
  details->GetString("value", &value);
  details->GetString("domain", &domain);
  details->GetString("path", &path);
  details->GetBoolean("secure", &secure);
  details->GetBoolean("httpOnly", &http_only);

  base::Time creation_time;
  if (details->GetDouble("creationDate", &creation_date)) {
    creation_time = (creation_date == 0) ?
        base::Time::UnixEpoch() :
        base::Time::FromDoubleT(creation_date);
  }

  base::Time expiration_time;
  if (details->GetDouble("expirationDate", &expiration_date)) {
    expiration_time = (expiration_date == 0) ?
        base::Time::UnixEpoch() :
        base::Time::FromDoubleT(expiration_date);
  }

  base::Time last_access_time;
  if (details->GetDouble("lastAccessDate", &last_access_date)) {
    last_access_time = (last_access_date == 0) ?
        base::Time::UnixEpoch() :
        base::Time::FromDoubleT(last_access_date);
  }

  GetCookieStore(getter)->SetCookieWithDetailsAsync(
      GURL(url), name, value, domain, path, creation_time,
      expiration_time, last_access_time, secure, http_only,
      false, false, net::COOKIE_PRIORITY_DEFAULT,
      base::Bind(OnSetCookie, callback));
}

}  // namespace

Cookies::Cookies(v8::Isolate* isolate,
                 content::BrowserContext* browser_context)
      : request_context_getter_(browser_context->GetRequestContext()) {
  Init(isolate);
}

Cookies::~Cookies() {
}

void Cookies::Get(const base::DictionaryValue& filter,
                  const GetCallback& callback) {
  scoped_ptr<base::DictionaryValue> copied(filter.CreateDeepCopy());
  auto getter = make_scoped_refptr(request_context_getter_);
  content::BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      base::Bind(GetCookiesOnIO, getter, Passed(&copied), callback));
}

void Cookies::Remove(const GURL& url, const std::string& name,
                     const base::Closure& callback) {
  auto getter = make_scoped_refptr(request_context_getter_);
  content::BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      base::Bind(RemoveCookieOnIOThread, getter, url, name, callback));
}

void Cookies::Set(const base::DictionaryValue& details,
                  const SetCallback& callback) {
  scoped_ptr<base::DictionaryValue> copied(details.CreateDeepCopy());
  auto getter = make_scoped_refptr(request_context_getter_);
  content::BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      base::Bind(SetCookieOnIO, getter, Passed(&copied), callback));
}

// static
mate::Handle<Cookies> Cookies::Create(
    v8::Isolate* isolate,
    content::BrowserContext* browser_context) {
  return mate::CreateHandle(isolate, new Cookies(isolate, browser_context));
}

// static
void Cookies::BuildPrototype(v8::Isolate* isolate,
                             v8::Local<v8::ObjectTemplate> prototype) {
  mate::ObjectTemplateBuilder(isolate, prototype)
      .SetMethod("get", &Cookies::Get)
      .SetMethod("remove", &Cookies::Remove)
      .SetMethod("set", &Cookies::Set);
}

}  // namespace api

}  // namespace atom
<|endoftext|>


<commit_before>#include <iostream>

#include "WakeDefines.h"

#include "Logging/LogMacros.h"

#include "Engine/InputManager.h"
#include "Engine/GEngine.h"
#include "Engine/Bootstrap.h"
#include "Engine/Shader.h"

#include "World/World.h"
#include "World/StaticMeshComponent.h"

#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>

int xAxis = 0;
int yAxis = 0;

class TestActor : public Actor
{
public:
	TestActor(ActorID Id, bool StartActive)
		: Actor(Id, StartActive)
	{
	}

	virtual void Spawn() override
	{
		Actor::Spawn();

		LOG_INFO(GlobalLogger, "TestActor spawned with an id of " << GetActorID() << "!");

		ShaderProgram* Shader = new ShaderProgram(ShaderProgram::LoadProgram("assets/shaders/basic.vert", "assets/shaders/basic.frag"));
		GLint posAttrib = glGetAttribLocation(Shader->GetProgram(), "position");

		float vertices[] = {
			0.f, 0.5f, 0.f,
			0.5f, -0.5f, 0.f,
			-0.5f, -0.5f, 0.f
		};

		GLuint vbo;
		GLuint vao;

		glGenBuffers(1, &vbo);
		glBindBuffer(GL_ARRAY_BUFFER, vbo);

		glGenVertexArrays(1, &vao);
		glBindVertexArray(vao);

		glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
		glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0);
		glEnableVertexAttribArray(posAttrib);

		MeshComponent = CreateComponent<StaticMeshComponent>(true, new StaticMesh(vbo, vao, 3), Shader);
	}

	virtual void Destroy() override
	{
		Actor::Destroy();

		LOG_INFO(GlobalLogger, "TestActor is being destroyed with an id of " << GetActorID() << "!");
	}

	virtual void Tick() override
	{
		Actor::Tick();
		SetPosition(GetPosition() + glm::vec3(xAxis, yAxis, 0) * W_ENGINE.GetDeltaTime());
	}

private:
	StaticMeshComponent* MeshComponent;

};

void OnInput_New(const Input& Input)
{
	W_WORLD.SpawnActor<TestActor>();
}

void Left(const Input& Input)
{
	xAxis += Input.Mode == EInputMode::Pressed ? -1 : 1;
}

void Right(const Input& Input)
{
	xAxis += Input.Mode == EInputMode::Pressed ? 1 : -1;
}

void Up(const Input& Input)
{
	yAxis += Input.Mode == EInputMode::Pressed ? 1 : -1;
}

void Down(const Input& Input)
{
	yAxis += Input.Mode == EInputMode::Pressed ? -1 : 1;
}

void OnInput_Exit(const Input& Input)
{
	W_ENGINE.Stop();
}

void Setup()
{
	W_INPUT.Bind("Exit", INPUT_BIND(Keyboard, Pressed, Escape));
	W_INPUT.Event("Exit").Bind(&OnInput_Exit);

	/*W_INPUT.CreateBinding("Exit", INPUT_BIND(Keyboard, Pressed, Escape));
	W_INPUT.Event("Exit").Bind(&OnInput_Exit);

	W_INPUT.CreateBinding("New", INPUT_BIND(Keyboard, Pressed, Return));
	W_INPUT.Event("New").Bind(&OnInput_New);

	W_INPUT.CreateBinding("Left", INPUT_BIND(Keyboard, Pressed, Left));
	W_INPUT.CreateBinding("Left", INPUT_BIND(Keyboard, Released, Left));
	W_INPUT.CreateBinding("Right", INPUT_BIND(Keyboard, Pressed, Right));
	W_INPUT.CreateBinding("Right", INPUT_BIND(Keyboard, Released, Right));
	W_INPUT.CreateBinding("Up", INPUT_BIND(Keyboard, Pressed, Up));
	W_INPUT.CreateBinding("Up", INPUT_BIND(Keyboard, Released, Up));
	W_INPUT.CreateBinding("Down", INPUT_BIND(Keyboard, Pressed, Down));
	W_INPUT.CreateBinding("Down", INPUT_BIND(Keyboard, Released, Down));

	W_INPUT.Event("Left").Bind(&Left);
	W_INPUT.Event("Right").Bind(&Right);
	W_INPUT.Event("Up").Bind(&Up);
	W_INPUT.Event("Down").Bind(&Down);

	W_WORLD.SpawnActor<TestActor>();*/
}

void RunEngine(int ArgC, char** ArgV)
{
	BootstrapOptions Options;
	Options.DefaultLogSinks = true;
	Options.DontRunEngine = false;

	Bootstrap Engine(ArgC, ArgV, Options);
	if (!Engine.Startup())
	{
		return;
	}

	Setup();

	Engine.Run();
}

int main(int argc, char** argv)
{
	RunEngine(argc, argv);

#ifdef WAKE_EXIT_PAUSE
	std::cout << "Press return to exit..." << std::endl;
	getchar();
#endif
	return 0;
}<commit_msg>fixed up example (new input functions)<commit_after>#include <iostream>

#include "WakeDefines.h"

#include "Logging/LogMacros.h"

#include "Engine/InputManager.h"
#include "Engine/GEngine.h"
#include "Engine/Bootstrap.h"
#include "Engine/Shader.h"

#include "World/World.h"
#include "World/StaticMeshComponent.h"

#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>

int xAxis = 0;
int yAxis = 0;

class TestActor : public Actor
{
public:
	TestActor(ActorID Id, bool StartActive)
		: Actor(Id, StartActive)
	{
	}

	virtual void Spawn() override
	{
		Actor::Spawn();

		LOG_INFO(GlobalLogger, "TestActor spawned with an id of " << GetActorID() << "!");

		ShaderProgram* Shader = new ShaderProgram(ShaderProgram::LoadProgram("assets/shaders/basic.vert", "assets/shaders/basic.frag"));
		GLint posAttrib = glGetAttribLocation(Shader->GetProgram(), "position");

		float vertices[] = {
			0.f, 0.5f, 0.f,
			0.5f, -0.5f, 0.f,
			-0.5f, -0.5f, 0.f
		};

		GLuint vbo;
		GLuint vao;

		glGenBuffers(1, &vbo);
		glBindBuffer(GL_ARRAY_BUFFER, vbo);

		glGenVertexArrays(1, &vao);
		glBindVertexArray(vao);

		glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
		glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0);
		glEnableVertexAttribArray(posAttrib);

		MeshComponent = CreateComponent<StaticMeshComponent>(true, new StaticMesh(vbo, vao, 3), Shader);
	}

	virtual void Destroy() override
	{
		Actor::Destroy();

		LOG_INFO(GlobalLogger, "TestActor is being destroyed with an id of " << GetActorID() << "!");
	}

	virtual void Tick() override
	{
		Actor::Tick();
		SetPosition(GetPosition() + glm::vec3(xAxis, yAxis, 0) * W_ENGINE.GetDeltaTime());
	}

private:
	StaticMeshComponent* MeshComponent;

};

void OnInput_New(const Input& Input)
{
	W_WORLD.SpawnActor<TestActor>();
}

void Left(const Input& Input)
{
	xAxis += Input.Mode == EInputMode::Pressed ? -1 : 1;
}

void Right(const Input& Input)
{
	xAxis += Input.Mode == EInputMode::Pressed ? 1 : -1;
}

void Up(const Input& Input)
{
	yAxis += Input.Mode == EInputMode::Pressed ? 1 : -1;
}

void Down(const Input& Input)
{
	yAxis += Input.Mode == EInputMode::Pressed ? -1 : 1;
}

void OnInput_Exit(const Input& Input)
{
	W_ENGINE.Stop();
}

void Setup()
{
	W_INPUT.Bind("Exit", INPUT_BIND(Keyboard, Pressed, Escape));
	W_INPUT.Event("Exit").Bind(&OnInput_Exit);

	W_INPUT.Bind("New", INPUT_BIND(Keyboard, Pressed, Return));
	W_INPUT.Event("New").Bind(&OnInput_New);

	W_INPUT.Bind("Left", INPUT_BIND(Keyboard, Pressed, Left));
	W_INPUT.Bind("Left", INPUT_BIND(Keyboard, Released, Left));
	W_INPUT.Bind("Right", INPUT_BIND(Keyboard, Pressed, Right));
	W_INPUT.Bind("Right", INPUT_BIND(Keyboard, Released, Right));
	W_INPUT.Bind("Up", INPUT_BIND(Keyboard, Pressed, Up));
	W_INPUT.Bind("Up", INPUT_BIND(Keyboard, Released, Up));
	W_INPUT.Bind("Down", INPUT_BIND(Keyboard, Pressed, Down));
	W_INPUT.Bind("Down", INPUT_BIND(Keyboard, Released, Down));

	W_INPUT.Event("Left").Bind(&Left);
	W_INPUT.Event("Right").Bind(&Right);
	W_INPUT.Event("Up").Bind(&Up);
	W_INPUT.Event("Down").Bind(&Down);
}

void RunEngine(int ArgC, char** ArgV)
{
	BootstrapOptions Options;
	Options.DefaultLogSinks = true;
	Options.DontRunEngine = false;

	Bootstrap Engine(ArgC, ArgV, Options);
	if (!Engine.Startup())
	{
		return;
	}

	Setup();

	Engine.Run();
}

int main(int argc, char** argv)
{
	RunEngine(argc, argv);

#ifdef WAKE_EXIT_PAUSE
	std::cout << "Press return to exit..." << std::endl;
	getchar();
#endif
	return 0;
}<|endoftext|>


<commit_before>#include "halley/core/graphics/painter.h"
#include "halley/core/graphics/render_context.h"
#include "halley/core/graphics/render_target/render_target.h"
#include "halley/core/graphics/material/material.h"
#include "halley/core/graphics/material/material_definition.h"
#include "halley/core/graphics/material/material_parameter.h"

using namespace Halley;

void Painter::startRender()
{
	nDrawCalls = nTriangles = nVertices = 0;

	verticesPending = 0;
	bytesPending = 0;
	doStartRender();
}

void Painter::endRender()
{
	flush();
	doEndRender();
	camera = nullptr;
	viewPort = Rect4i(0, 0, 0, 0);
}

void Painter::flush()
{
	flushPending();
}

/*
template <typename T>
static void doMemcpyAlign(void* dstBytes, const void* srcBytes, size_t bytes)
{
	T* dst = reinterpret_cast<T*>(dstBytes);
	const T* src = reinterpret_cast<const T*>(srcBytes);
	const T* srcEnd = src + (bytes / sizeof(T));
	for (; src != srcEnd; ++src, ++dst) {
		*dst = *src;
	}
}

inline void memcpyAlign(void* dstBytes, const void* srcBytes, size_t bytes)
{
	if (bytes % sizeof(size_t) == 0) {
		// Use size_t aligned if possible
		doMemcpyAlign<size_t>(dstBytes, srcBytes, bytes);
	} else {
		// Data is always int-aligned, since numVertices % 4 == 0
		doMemcpyAlign<int>(dstBytes, srcBytes, bytes);
	}
}
*/

void Painter::drawQuads(std::shared_ptr<Material> material, size_t numVertices, void* vertexData)
{
	assert(numVertices > 0);
	assert(numVertices % 4 == 0);
	assert(vertexData != nullptr);

	if (material != materialPending) {
		if (materialPending != std::shared_ptr<Material>()) {
			flushPending();
		}
		materialPending = material;
	}

	size_t dataSize = numVertices * material->getDefinition().getVertexStride();
	size_t requiredSize = dataSize + bytesPending;
	if (vertexBuffer.size() < requiredSize) {
		vertexBuffer.resize(requiredSize * 2);
	}

	memmove(vertexBuffer.data() + bytesPending, vertexData, dataSize);

	verticesPending += numVertices;
	bytesPending += dataSize;
}

void Painter::bind(RenderContext& context)
{
	// Set render target
	auto& rt = context.getRenderTarget();
	rt.bind();

	// Set viewport
	viewPort = context.getViewPort();
	setViewPort(viewPort, viewPort != rt.getViewPort());

	// Set camera
	camera = &context.getCamera();
	camera->setViewArea(Vector2f(viewPort.getSize()));
	camera->updateProjection();
	projection = camera->getProjection();
}

void Painter::flushPending()
{
	if (verticesPending > 0) {
		executeDrawQuads(*materialPending, verticesPending, vertexBuffer.data());
	}

	// Reset
	bytesPending = 0;
	verticesPending = 0;
	materialPending.reset();
}

void Painter::executeDrawQuads(Material& material, size_t numVertices, void* vertexData)
{
	// Bind projection
	material["u_mvp"] = projection;

	// Load vertices
	setVertices(material.getDefinition(), numVertices, vertexData);

	// Go through each pass
	for (int i = 0; i < material.getDefinition().getNumPasses(); i++) {
		// Bind pass
		material.bind(i, *this);

		// Draw
		drawQuads(int(numVertices / 4));

		// Log stats
		nDrawCalls++;
		nTriangles += numVertices / 2;
		nVertices += numVertices;
	}
}
<commit_msg>Missing header for memmove()<commit_after>#include "halley/core/graphics/painter.h"
#include "halley/core/graphics/render_context.h"
#include "halley/core/graphics/render_target/render_target.h"
#include "halley/core/graphics/material/material.h"
#include "halley/core/graphics/material/material_definition.h"
#include "halley/core/graphics/material/material_parameter.h"
#include <cstring> // memmove

using namespace Halley;

void Painter::startRender()
{
	nDrawCalls = nTriangles = nVertices = 0;

	verticesPending = 0;
	bytesPending = 0;
	doStartRender();
}

void Painter::endRender()
{
	flush();
	doEndRender();
	camera = nullptr;
	viewPort = Rect4i(0, 0, 0, 0);
}

void Painter::flush()
{
	flushPending();
}

/*
template <typename T>
static void doMemcpyAlign(void* dstBytes, const void* srcBytes, size_t bytes)
{
	T* dst = reinterpret_cast<T*>(dstBytes);
	const T* src = reinterpret_cast<const T*>(srcBytes);
	const T* srcEnd = src + (bytes / sizeof(T));
	for (; src != srcEnd; ++src, ++dst) {
		*dst = *src;
	}
}

inline void memcpyAlign(void* dstBytes, const void* srcBytes, size_t bytes)
{
	if (bytes % sizeof(size_t) == 0) {
		// Use size_t aligned if possible
		doMemcpyAlign<size_t>(dstBytes, srcBytes, bytes);
	} else {
		// Data is always int-aligned, since numVertices % 4 == 0
		doMemcpyAlign<int>(dstBytes, srcBytes, bytes);
	}
}
*/

void Painter::drawQuads(std::shared_ptr<Material> material, size_t numVertices, void* vertexData)
{
	assert(numVertices > 0);
	assert(numVertices % 4 == 0);
	assert(vertexData != nullptr);

	if (material != materialPending) {
		if (materialPending != std::shared_ptr<Material>()) {
			flushPending();
		}
		materialPending = material;
	}

	size_t dataSize = numVertices * material->getDefinition().getVertexStride();
	size_t requiredSize = dataSize + bytesPending;
	if (vertexBuffer.size() < requiredSize) {
		vertexBuffer.resize(requiredSize * 2);
	}

	memmove(vertexBuffer.data() + bytesPending, vertexData, dataSize);

	verticesPending += numVertices;
	bytesPending += dataSize;
}

void Painter::bind(RenderContext& context)
{
	// Set render target
	auto& rt = context.getRenderTarget();
	rt.bind();

	// Set viewport
	viewPort = context.getViewPort();
	setViewPort(viewPort, viewPort != rt.getViewPort());

	// Set camera
	camera = &context.getCamera();
	camera->setViewArea(Vector2f(viewPort.getSize()));
	camera->updateProjection();
	projection = camera->getProjection();
}

void Painter::flushPending()
{
	if (verticesPending > 0) {
		executeDrawQuads(*materialPending, verticesPending, vertexBuffer.data());
	}

	// Reset
	bytesPending = 0;
	verticesPending = 0;
	materialPending.reset();
}

void Painter::executeDrawQuads(Material& material, size_t numVertices, void* vertexData)
{
	// Bind projection
	material["u_mvp"] = projection;

	// Load vertices
	setVertices(material.getDefinition(), numVertices, vertexData);

	// Go through each pass
	for (int i = 0; i < material.getDefinition().getNumPasses(); i++) {
		// Bind pass
		material.bind(i, *this);

		// Draw
		drawQuads(int(numVertices / 4));

		// Log stats
		nDrawCalls++;
		nTriangles += numVertices / 2;
		nVertices += numVertices;
	}
}
<|endoftext|>