<commit_before>/*************************************************************************
*    UrBackup - Client/Server backup system
*    Copyright (C) 2011  Martin Raiber
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/

#ifndef CLIENT_ONLY

#include "action_header.h"
#include "../os_functions.h"

std::string constructFilter(const std::vector<int> &clientid, std::string key);

ACTION_IMPL(logs)
{
	Helper helper(tid, &GET, &PARAMS);
	JSON::Object ret;
	SUser *session=helper.getSession();
	if(session!=NULL && session->id==-1) return;
	std::wstring filter=GET[L"filter"];
	std::wstring s_logid=GET[L"logid"];
	int logid=watoi(s_logid);
	std::string rights=helper.getRights("logs");
	std::vector<int> clientid;
	if(rights!="all" && rights!="none" )
	{
		std::vector<std::string> s_clientid;
		Tokenize(rights, s_clientid, ",");
		for(size_t i=0;i<s_clientid.size();++i)
		{
			clientid.push_back(atoi(s_clientid[i].c_str()));
		}
	}
	if(clientid.size()>0 && filter.empty() )
	{
		for(size_t i=0;i<clientid.size();++i)
		{
			filter+=convert(clientid[i]);
			if(i+1<clientid.size())
				filter+=L",";
		}
	}
	std::vector<int> v_filter;
	if(!filter.empty())
	{
		std::vector<std::wstring> s_filter;
		Tokenize(filter, s_filter, L",");
		for(size_t i=0;i<s_filter.size();++i)
		{
			v_filter.push_back(watoi(s_filter[i]));
		}
	}
	if(session!=NULL && rights!="none")
	{
		IDatabase *db=helper.getDatabase();
		std::string qstr="SELECT c.id AS id, c.name AS name FROM clients c WHERE ";
		if(!clientid.empty()) qstr+=constructFilter(clientid, "c.id")+" AND ";
		qstr+=" EXISTS (SELECT * FROM logs l WHERE l.clientid=c.id)";

		IQuery *q_clients=db->Prepare(qstr);
		db_results res=q_clients->Read();
		q_clients->Reset();
		JSON::Array clients;
		for(size_t i=0;i<res.size();++i)
		{
			JSON::Object obj;
			obj.set("id", watoi(res[i][L"id"]));
			obj.set("name", res[i][L"name"]);
			clients.add(obj);
		}
		ret.set("clients", clients);
		ret.set("filter", filter);
		if(s_logid.empty())
		{
			std::wstring s_ll=GET[L"ll"];
			int ll=2;
			if(!s_ll.empty())
			{
				ll=watoi(s_ll);
			}
			std::string bed;
			if(ll==2)
			{
				bed="l.errors>0";
			}
			else if(ll==1)
			{
				bed="(l.warnings>0 OR l.errors>0)";
			}
			qstr="SELECT l.id AS id, c.name AS name, strftime('"+helper.getTimeFormatString()+"', l.created, 'localtime') AS time, l.errors AS errors, l.warnings AS warnings, l.image AS image, l.incremental AS incremental FROM logs l INNER JOIN clients c ON l.clientid=c.id";

			if(!v_filter.empty())
			{
				qstr+=" WHERE "+constructFilter(v_filter, "l.clientid");
				if(!bed.empty())
				{
					qstr+=" AND "+bed;
				}
			}
			else if(!bed.empty()) qstr+=" WHERE "+bed;

			qstr+=" ORDER BY l.created DESC LIMIT 50";
			IQuery *q=db->Prepare(qstr);
			res=q->Read();
			q->Reset();
			JSON::Array logs;
			for(size_t i=0;i<res.size();++i)
			{
				JSON::Object obj;
				obj.set("name", res[i][L"name"]);
				obj.set("id", watoi(res[i][L"id"]));
				obj.set("time", res[i][L"time"]);
				obj.set("errors", watoi(res[i][L"errors"]));
				obj.set("warnings", watoi(res[i][L"warnings"]));
				obj.set("image", watoi(res[i][L"image"]));
				obj.set("incremental", watoi(res[i][L"incremental"]));
				logs.add(obj);
			}
			ret.set("logs", logs);
			ret.set("ll", ll);

			if(GET.find(L"report_mail")!=GET.end())
			{
				IQuery *q=db->Prepare("UPDATE settings_db.si_users SET report_mail=?, report_loglevel=? WHERE id=?");
				q->Bind(GET[L"report_mail"]);
				q->Bind(watoi(GET[L"report_loglevel"]));
				q->Bind(session->id);
				q->Write();
				q->Reset();
			}

			if(GET.find(L"report_mail")!=GET.end())
			{
				IQuery *q=db->Prepare("UPDATE settings_db.si_users SET report_mail=?, report_loglevel=?, report_sendonly=? WHERE id=?");
				q->Bind(GET[L"report_mail"]);
				q->Bind(watoi(GET[L"report_loglevel"]));
				q->Bind(watoi(GET[L"report_sendonly"]));
				q->Bind(session->id);
				q->Write();
				ret.set("saved_ok", true);
			}

			IQuery *mq=db->Prepare("SELECT report_mail, report_loglevel, report_sendonly FROM settings_db.si_users WHERE id=? AND report_mail IS NOT NULL");
			mq->Bind(session->id);
			res=mq->Read();
			mq->Reset();

			if(!res.empty())
			{
				ret.set("report_mail", res[0][L"report_mail"]);
				ret.set("report_loglevel", watoi(res[0][L"report_loglevel"]));
				ret.set("report_sendonly", watoi(res[0][L"report_sendonly"]));
			}
			else
			{
				ret.set("report_mail", "");
				ret.set("report_sendonly", "");
				ret.set("report_loglevel", "");
			}
		}
		else
		{
			IQuery *q=db->Prepare("SELECT l.clientid AS clientid, l.logdata AS logdata, strftime('"+helper.getTimeFormatString()+"', l.created, 'localtime') AS time, c.name AS name FROM logs l INNER JOIN clients c ON l.clientid=c.id WHERE l.id=?");
			q->Bind(logid);
			db_results res=q->Read();
			q->Reset();

			if(!res.empty())
			{
				bool ok=true;
				if(!clientid.empty())
				{
					ok=false;
					int t_clientid=watoi(res[0][L"clientid"]);
					for(size_t i=0;i<clientid.size();++i)
					{
						if(clientid[i]==t_clientid)
						{
							ok=true;
							break;
						}
					}
				}

				if(ok)
				{
					JSON::Object log;
					log.set("data", res[0][L"logdata"]);
					log.set("time", res[0][L"time"]);
					log.set("clientname", res[0][L"name"]);
					ret.set("log", log);
				}
			}
		}
	}
	else
	{
		ret.set("error", 1);
	}

	helper.Write(ret.get(false));
}

#endif //CLIENT_ONLY<commit_msg>Optimized query<commit_after>/*************************************************************************
*    UrBackup - Client/Server backup system
*    Copyright (C) 2011  Martin Raiber
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/

#ifndef CLIENT_ONLY

#include "action_header.h"
#include "../os_functions.h"

std::string constructFilter(const std::vector<int> &clientid, std::string key);

ACTION_IMPL(logs)
{
	Helper helper(tid, &GET, &PARAMS);
	JSON::Object ret;
	SUser *session=helper.getSession();
	if(session!=NULL && session->id==-1) return;
	std::wstring filter=GET[L"filter"];
	std::wstring s_logid=GET[L"logid"];
	int logid=watoi(s_logid);
	std::string rights=helper.getRights("logs");
	std::vector<int> clientid;
	if(rights!="all" && rights!="none" )
	{
		std::vector<std::string> s_clientid;
		Tokenize(rights, s_clientid, ",");
		for(size_t i=0;i<s_clientid.size();++i)
		{
			clientid.push_back(atoi(s_clientid[i].c_str()));
		}
	}
	if(clientid.size()>0 && filter.empty() )
	{
		for(size_t i=0;i<clientid.size();++i)
		{
			filter+=convert(clientid[i]);
			if(i+1<clientid.size())
				filter+=L",";
		}
	}
	std::vector<int> v_filter;
	if(!filter.empty())
	{
		std::vector<std::wstring> s_filter;
		Tokenize(filter, s_filter, L",");
		for(size_t i=0;i<s_filter.size();++i)
		{
			v_filter.push_back(watoi(s_filter[i]));
		}
	}
	if(session!=NULL && rights!="none")
	{
		IDatabase *db=helper.getDatabase();
		std::string qstr="SELECT c.id AS id, c.name AS name FROM clients c WHERE ";
		if(!clientid.empty()) qstr+=constructFilter(clientid, "c.id")+" AND ";
		qstr+=" EXISTS (SELECT id FROM logs l WHERE l.clientid=c.id LIMIT 1)";

		IQuery *q_clients=db->Prepare(qstr);
		db_results res=q_clients->Read();
		q_clients->Reset();
		JSON::Array clients;
		for(size_t i=0;i<res.size();++i)
		{
			JSON::Object obj;
			obj.set("id", watoi(res[i][L"id"]));
			obj.set("name", res[i][L"name"]);
			clients.add(obj);
		}
		ret.set("clients", clients);
		ret.set("filter", filter);
		if(s_logid.empty())
		{
			std::wstring s_ll=GET[L"ll"];
			int ll=2;
			if(!s_ll.empty())
			{
				ll=watoi(s_ll);
			}
			std::string bed;
			if(ll==2)
			{
				bed="l.errors>0";
			}
			else if(ll==1)
			{
				bed="(l.warnings>0 OR l.errors>0)";
			}
			qstr="SELECT l.id AS id, c.name AS name, strftime('"+helper.getTimeFormatString()+"', l.created, 'localtime') AS time, l.errors AS errors, l.warnings AS warnings, l.image AS image, l.incremental AS incremental FROM logs l INNER JOIN clients c ON l.clientid=c.id";

			if(!v_filter.empty())
			{
				qstr+=" WHERE "+constructFilter(v_filter, "l.clientid");
				if(!bed.empty())
				{
					qstr+=" AND "+bed;
				}
			}
			else if(!bed.empty()) qstr+=" WHERE "+bed;

			qstr+=" ORDER BY l.created DESC LIMIT 50";
			IQuery *q=db->Prepare(qstr);
			res=q->Read();
			q->Reset();
			JSON::Array logs;
			for(size_t i=0;i<res.size();++i)
			{
				JSON::Object obj;
				obj.set("name", res[i][L"name"]);
				obj.set("id", watoi(res[i][L"id"]));
				obj.set("time", res[i][L"time"]);
				obj.set("errors", watoi(res[i][L"errors"]));
				obj.set("warnings", watoi(res[i][L"warnings"]));
				obj.set("image", watoi(res[i][L"image"]));
				obj.set("incremental", watoi(res[i][L"incremental"]));
				logs.add(obj);
			}
			ret.set("logs", logs);
			ret.set("ll", ll);

			if(GET.find(L"report_mail")!=GET.end())
			{
				IQuery *q=db->Prepare("UPDATE settings_db.si_users SET report_mail=?, report_loglevel=? WHERE id=?");
				q->Bind(GET[L"report_mail"]);
				q->Bind(watoi(GET[L"report_loglevel"]));
				q->Bind(session->id);
				q->Write();
				q->Reset();
			}

			if(GET.find(L"report_mail")!=GET.end())
			{
				IQuery *q=db->Prepare("UPDATE settings_db.si_users SET report_mail=?, report_loglevel=?, report_sendonly=? WHERE id=?");
				q->Bind(GET[L"report_mail"]);
				q->Bind(watoi(GET[L"report_loglevel"]));
				q->Bind(watoi(GET[L"report_sendonly"]));
				q->Bind(session->id);
				q->Write();
				ret.set("saved_ok", true);
			}

			IQuery *mq=db->Prepare("SELECT report_mail, report_loglevel, report_sendonly FROM settings_db.si_users WHERE id=? AND report_mail IS NOT NULL");
			mq->Bind(session->id);
			res=mq->Read();
			mq->Reset();

			if(!res.empty())
			{
				ret.set("report_mail", res[0][L"report_mail"]);
				ret.set("report_loglevel", watoi(res[0][L"report_loglevel"]));
				ret.set("report_sendonly", watoi(res[0][L"report_sendonly"]));
			}
			else
			{
				ret.set("report_mail", "");
				ret.set("report_sendonly", "");
				ret.set("report_loglevel", "");
			}
		}
		else
		{
			IQuery *q=db->Prepare("SELECT l.clientid AS clientid, l.logdata AS logdata, strftime('"+helper.getTimeFormatString()+"', l.created, 'localtime') AS time, c.name AS name FROM logs l INNER JOIN clients c ON l.clientid=c.id WHERE l.id=?");
			q->Bind(logid);
			db_results res=q->Read();
			q->Reset();

			if(!res.empty())
			{
				bool ok=true;
				if(!clientid.empty())
				{
					ok=false;
					int t_clientid=watoi(res[0][L"clientid"]);
					for(size_t i=0;i<clientid.size();++i)
					{
						if(clientid[i]==t_clientid)
						{
							ok=true;
							break;
						}
					}
				}

				if(ok)
				{
					JSON::Object log;
					log.set("data", res[0][L"logdata"]);
					log.set("time", res[0][L"time"]);
					log.set("clientname", res[0][L"name"]);
					ret.set("log", log);
				}
			}
		}
	}
	else
	{
		ret.set("error", 1);
	}

	helper.Write(ret.get(false));
}

#endif //CLIENT_ONLY<|endoftext|>


<commit_before>/*******************************************************
 * Copyright (c) 2015, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#include <cstdio>
#include <arrayfire.h>
#include <cstdlib>

using namespace af;

static void harris_demo(bool console)
{
    // Load image
    array img = loadImage(ASSETS_DIR"/examples/images/square.png", false);

    // Calculate image gradients
    array ix, iy;
    grad(ix, iy, img);

    // Compute second-order derivatives
    array ixx = ix * ix;
    array ixy = ix * iy;
    array iyy = iy * iy;

    // Compute a Gaussian kernel with standard deviation of 1.0 and length of 5 pixels
    // These values can be changed to use a smaller or larger window
    array gauss_filt = gaussianKernel(5, 5, 1.0, 1.0);

    // Filter second-order derivatives with Gaussian kernel computed previously
    ixx = convolve(ixx, gauss_filt);
    ixy = convolve(ixy, gauss_filt);
    iyy = convolve(iyy, gauss_filt);

    // Calculate trace
    array tr = ixx + iyy;
    // Calculate determinant
    array det = ixx * iyy - ixy * ixy;

    // Calculate Harris response
    array response = det - 0.04f * (tr * tr);

    // Gets maximum response for each 3x3 neighborhood
    //array max_resp = maxfilt(response, 3, 3);
    array mask = constant(1,3,3);
    array max_resp = dilate(response, mask);

    // Discard responses that are not greater than threshold
    array corners = response > 1e5f;
    corners = corners * response;

    // Discard responses that are not equal to maximum neighborhood response,
    // scale them to original response value
    corners = (corners == max_resp) * corners;

    // Find corner indexes in the image as 1D indexes
    array idx = where(corners);

    // Calculate 2D corner indexes
    array corners_x = idx / corners.dims()[0];
    array corners_y = idx % corners.dims()[0];

    const int good_corners = corners_x.dims()[0];
    std::cout << "Corners found: " << good_corners << std::endl << std::endl;

    af_print(corners_x);
    af_print(corners_y);
}

int main(int argc, char** argv)
{
    int device = argc > 1 ? atoi(argv[1]) : 0;
    bool console = argc > 2 ? argv[2][0] == '-' : false;

    try {
        af::setDevice(device);
        af::info();
        std::cout << "** ArrayFire Harris Corner Detector Demo **" << std::endl << std::endl;
        harris_demo(console);

    } catch (af::exception& ae) {
        std::cout << ae.what() << std::endl;
        throw;
    }

    if (!console) {
        printf("hit [enter]...");
        getchar();
    }
    return 0;
}
<commit_msg>Modified harris example to use graphics when appropriate<commit_after>/*******************************************************
 * Copyright (c) 2015, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#include <cstdio>
#include <arrayfire.h>
#include <cstdlib>

using namespace af;

static void harris_demo(bool console)
{
    af::Window wnd("Harris Corner Detector");

    // Load image
    array img_color;
    if (console)
        img_color = loadImage(ASSETS_DIR "/examples/images/square.png", true);
    else
        img_color = loadImage(ASSETS_DIR "/examples/images/lena.ppm", true);
    // Convert the image from RGB to gray-scale
    array img = colorSpace(img_color, AF_GRAY, AF_RGB);
    // For visualization in ArrayFire, color images must be in the [0.0f-1.0f] interval
    img_color /= 255.f;

    // Calculate image gradients
    array ix, iy;
    grad(ix, iy, img);

    // Compute second-order derivatives
    array ixx = ix * ix;
    array ixy = ix * iy;
    array iyy = iy * iy;

    // Compute a Gaussian kernel with standard deviation of 1.0 and length of 5 pixels
    // These values can be changed to use a smaller or larger window
    array gauss_filt = gaussianKernel(5, 5, 1.0, 1.0);

    // Filter second-order derivatives with Gaussian kernel computed previously
    ixx = convolve(ixx, gauss_filt);
    ixy = convolve(ixy, gauss_filt);
    iyy = convolve(iyy, gauss_filt);

    // Calculate trace
    array tr = ixx + iyy;
    // Calculate determinant
    array det = ixx * iyy - ixy * ixy;

    // Calculate Harris response
    array response = det - 0.04f * (tr * tr);

    // Gets maximum response for each 3x3 neighborhood
    //array max_resp = maxfilt(response, 3, 3);
    array mask = constant(1,3,3);
    array max_resp = dilate(response, mask);

    // Discard responses that are not greater than threshold
    array corners = response > 1e5f;
    corners = corners * response;

    // Discard responses that are not equal to maximum neighborhood response,
    // scale them to original response value
    corners = (corners == max_resp) * corners;

    // Gets host pointer to response data
    float* h_corners = corners.host<float>();

    unsigned good_corners = 0;

    // Draw draw_len x draw_len crosshairs where the corners are
    const int draw_len = 3;
    for (int y = draw_len; y < img_color.dims(0) - draw_len; y++) {
        for (int x = draw_len; x < img_color.dims(1) - draw_len; x++) {
            // Only draws crosshair if is a corner
            if (h_corners[x * corners.dims(0) + y] > 1e5f) {
                // Draw horizontal line of (draw_len * 2 + 1) pixels centered on the corner
                // Set only the first channel to 1 (green lines)
                img_color(y, seq(x-draw_len, x+draw_len), 0) = 0.f;
                img_color(y, seq(x-draw_len, x+draw_len), 1) = 1.f;
                img_color(y, seq(x-draw_len, x+draw_len), 2) = 0.f;

                // Draw vertical line of (draw_len * 2 + 1) pixels centered on  the corner
                // Set only the first channel to 1 (green lines)
                img_color(seq(y-draw_len, y+draw_len), x, 0) = 0.f;
                img_color(seq(y-draw_len, y+draw_len), x, 1) = 1.f;
                img_color(seq(y-draw_len, y+draw_len), x, 2) = 0.f;

                good_corners++;
            }
        }
    }

    printf("Corners found: %u\n", good_corners);

    if (!console) {
        // Previews color image with green crosshairs
        while(!wnd.close())
            wnd.image(img_color);
    } else {
        // Find corner indexes in the image as 1D indexes
        array idx = where(corners);

        // Calculate 2D corner indexes
        array corners_x = idx / corners.dims()[0];
        array corners_y = idx % corners.dims()[0];

        const int good_corners = corners_x.dims()[0];
        std::cout << "Corners found: " << good_corners << std::endl << std::endl;

        af_print(corners_x);
        af_print(corners_y);
    }
}

int main(int argc, char** argv)
{
    int device = argc > 1 ? atoi(argv[1]) : 0;
    bool console = argc > 2 ? argv[2][0] == '-' : false;

    try {
        af::setDevice(device);
        af::info();
        std::cout << "** ArrayFire Harris Corner Detector Demo **" << std::endl << std::endl;
        harris_demo(console);

    } catch (af::exception& ae) {
        std::cout << ae.what() << std::endl;
        throw;
    }

    return 0;
}
<|endoftext|>


<commit_before>#include <allegro5/allegro.h>

#include <sstream>
#include <vector>

#include "creature.h"
#include "game_context.h"

GameContext::GameContext():
    display(new Display()),
    dungeon(new Dungeon()),
    queue(al_create_event_queue()),
    clock_time(0)
{
    al_register_event_source(
        queue, al_get_keyboard_event_source()
    );
    al_register_event_source(
        queue, al_get_display_event_source(display->display)
    );

    int free_pos_x;
    int free_pos_y;
    while (1)
    {
        int rand_x = rand() % dungeon->get_width();
        int rand_y = rand() % dungeon->get_height();

        if (dungeon->entity_at_index(rand_x, rand_y).is_passable())
        {
            free_pos_x = rand_x;
            free_pos_y = rand_y;

            break;
        }
    }

    creatures.push_back(
        new Creature(
            '@', true, true, true, free_pos_x, free_pos_y, 50, 10
        )
    );
}

Creature* GameContext::creature_at_index(int x, int y)
{
    for (auto it = creatures.cbegin(); it != creatures.cend(); it++)
    {
        if ((*it)->get_x() == x && (*it)->get_y() == y)
        {
            return *it;
        }
    }

    return NULL;
}

void GameContext::kill_creature_at_index(int x, int y) {
    for (auto it = creatures.begin(); it != creatures.end(); it++) {
        if ((*it)->get_x() == x && (*it)->get_y() == y) {
            creatures.erase(it);

            break;
        }
    }
}

void GameContext::conduct_melee_attack(Creature* source, Creature* target) {
    auto damage = source->get_strength();

    target->take_damage(damage);

    if (target->get_health() <= 0) {
        kill_creature_at_index(target->get_x(), target->get_y());
    }
}

void GameContext::process_movement(int x, int y, Creature* creature)
{
    if (auto target = creature_at_index(x, y))
    {
        // Swap positions with the friendly creature
        if (target->is_friendly())
        {
            target->set_x(creature->get_x());
            target->set_y(creature->get_y());
            creature->set_x(x);
            creature->set_y(y);
        }
        else
        {
            conduct_melee_attack(creature, target);
        }
    }
    else if (dungeon->entity_at_index(x, y).is_passable())
    {
        creature->set_x(x);
        creature->set_y(y);
    }
}

bool GameContext::take_input(Creature* controllable)
{
    ALLEGRO_EVENT event;

    do {
        al_wait_for_event(queue, &event);
    } while(
        event.type != ALLEGRO_EVENT_DISPLAY_CLOSE &&
        event.type != ALLEGRO_EVENT_KEY_CHAR
    );

    if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
    {
        return true;
    }

    int cur_x = controllable->get_x();
    int cur_y = controllable->get_y();

    if (event.type == ALLEGRO_EVENT_KEY_CHAR)
    {
        std::ostringstream stream;
        stream << "The key " << event.keyboard.keycode << " was pressed!";

        event_messages.push_back(stream.str());

        switch (event.keyboard.keycode)
        {
        case ALLEGRO_KEY_LEFT:
            process_movement(cur_x - 1, cur_y, controllable);
            break;
        case ALLEGRO_KEY_RIGHT:
            process_movement(cur_x + 1, cur_y, controllable);
            break;
        case ALLEGRO_KEY_UP:
            process_movement(cur_x, cur_y - 1, controllable);
            break;
        case ALLEGRO_KEY_DOWN:
            process_movement(cur_x, cur_y + 1, controllable);
            break;
        case ALLEGRO_KEY_PAD_1:
            process_movement(cur_x - 1, cur_y + 1, controllable);
            break;
        case ALLEGRO_KEY_PAD_2:
            process_movement(cur_x, cur_y + 1, controllable);
            break;
        case ALLEGRO_KEY_PAD_3:
            process_movement(cur_x + 1, cur_y + 1, controllable);
            break;
        case ALLEGRO_KEY_PAD_4:
            process_movement(cur_x - 1, cur_y, controllable);
            break;
        case ALLEGRO_KEY_PAD_6:
            process_movement(cur_x + 1, cur_y, controllable);
            break;
        case ALLEGRO_KEY_PAD_7:
            process_movement(cur_x - 1, cur_y - 1, controllable);
            break;
        case ALLEGRO_KEY_PAD_8:
            process_movement(cur_x, cur_y - 1, controllable);
            break;
        case ALLEGRO_KEY_PAD_9:
            process_movement(cur_x + 1, cur_y - 1, controllable);
            break;
        }

        if (
            event.keyboard.keycode == ALLEGRO_KEY_ESCAPE ||
            event.keyboard.unichar == 'q'
        ) {
            return true;
        }
    }

    return false;
}

void GameContext::game_loop()
{
    Creature* player;
    if (!(player = get_player()))
    {
        return;
    }

    creatures.push_back(
        new Creature(
            'g', false, false, false, player->get_x() + 2, player->get_y() - 2,
            100, 10
        )
    );

    // This only needs to happen once, until window resizing is supported. Just
    // drawing this once only works because we take advantage of our grid-based
    // tile drawing and don't ever actually clear the screen
    display->draw_borders();

    while (1)
    {
        for (auto it = creatures.begin(); it != creatures.end(); it++)
        {
            if (!(*it)->is_turn(clock_time))
            {
                continue;
            }

            if (!(*it)->is_controllable())
            {
                continue;
            }

            display->draw_dungeon(
                (*it)->get_x(), (*it)->get_y(),
                dungeon, creatures.cbegin(), creatures.cend()
            );

            display->draw_event_messages(event_messages);

            display->update_screen();

            bool exit_request = take_input(*it);

            if (exit_request)
            {
                goto BREAK_GAME_LOOP;
            }
        }

        clock_time += 5;
    }

BREAK_GAME_LOOP:

    return;
}

Creature* GameContext::get_player()
{
    for (auto it = creatures.begin(); it != creatures.end(); it++)
    {
        if ((*it)->is_player())
        {
            return *it;
        }
    }

    return NULL;
}

GameContext::~GameContext()
{
    delete display;
    delete dungeon;

    for (auto it = creatures.begin(); it != creatures.end(); it++)
    {
        delete *it;
    }

    al_destroy_event_queue(queue);
}
<commit_msg>Restore drawing the beautiful borders on each game loop<commit_after>#include <allegro5/allegro.h>

#include <sstream>
#include <vector>

#include "creature.h"
#include "game_context.h"

GameContext::GameContext():
    display(new Display()),
    dungeon(new Dungeon()),
    queue(al_create_event_queue()),
    clock_time(0)
{
    al_register_event_source(
        queue, al_get_keyboard_event_source()
    );
    al_register_event_source(
        queue, al_get_display_event_source(display->display)
    );

    int free_pos_x;
    int free_pos_y;
    while (1)
    {
        int rand_x = rand() % dungeon->get_width();
        int rand_y = rand() % dungeon->get_height();

        if (dungeon->entity_at_index(rand_x, rand_y).is_passable())
        {
            free_pos_x = rand_x;
            free_pos_y = rand_y;

            break;
        }
    }

    creatures.push_back(
        new Creature(
            '@', true, true, true, free_pos_x, free_pos_y, 50, 10
        )
    );
}

Creature* GameContext::creature_at_index(int x, int y)
{
    for (auto it = creatures.cbegin(); it != creatures.cend(); it++)
    {
        if ((*it)->get_x() == x && (*it)->get_y() == y)
        {
            return *it;
        }
    }

    return NULL;
}

void GameContext::kill_creature_at_index(int x, int y) {
    for (auto it = creatures.begin(); it != creatures.end(); it++) {
        if ((*it)->get_x() == x && (*it)->get_y() == y) {
            creatures.erase(it);

            break;
        }
    }
}

void GameContext::conduct_melee_attack(Creature* source, Creature* target) {
    auto damage = source->get_strength();

    target->take_damage(damage);

    if (target->get_health() <= 0) {
        kill_creature_at_index(target->get_x(), target->get_y());
    }
}

void GameContext::process_movement(int x, int y, Creature* creature)
{
    if (auto target = creature_at_index(x, y))
    {
        // Swap positions with the friendly creature
        if (target->is_friendly())
        {
            target->set_x(creature->get_x());
            target->set_y(creature->get_y());
            creature->set_x(x);
            creature->set_y(y);
        }
        else
        {
            conduct_melee_attack(creature, target);
        }
    }
    else if (dungeon->entity_at_index(x, y).is_passable())
    {
        creature->set_x(x);
        creature->set_y(y);
    }
}

bool GameContext::take_input(Creature* controllable)
{
    ALLEGRO_EVENT event;

    do {
        al_wait_for_event(queue, &event);
    } while(
        event.type != ALLEGRO_EVENT_DISPLAY_CLOSE &&
        event.type != ALLEGRO_EVENT_KEY_CHAR
    );

    if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
    {
        return true;
    }

    int cur_x = controllable->get_x();
    int cur_y = controllable->get_y();

    if (event.type == ALLEGRO_EVENT_KEY_CHAR)
    {
        std::ostringstream stream;
        stream << "The key " << event.keyboard.keycode << " was pressed!";

        event_messages.push_back(stream.str());

        switch (event.keyboard.keycode)
        {
        case ALLEGRO_KEY_LEFT:
            process_movement(cur_x - 1, cur_y, controllable);
            break;
        case ALLEGRO_KEY_RIGHT:
            process_movement(cur_x + 1, cur_y, controllable);
            break;
        case ALLEGRO_KEY_UP:
            process_movement(cur_x, cur_y - 1, controllable);
            break;
        case ALLEGRO_KEY_DOWN:
            process_movement(cur_x, cur_y + 1, controllable);
            break;
        case ALLEGRO_KEY_PAD_1:
            process_movement(cur_x - 1, cur_y + 1, controllable);
            break;
        case ALLEGRO_KEY_PAD_2:
            process_movement(cur_x, cur_y + 1, controllable);
            break;
        case ALLEGRO_KEY_PAD_3:
            process_movement(cur_x + 1, cur_y + 1, controllable);
            break;
        case ALLEGRO_KEY_PAD_4:
            process_movement(cur_x - 1, cur_y, controllable);
            break;
        case ALLEGRO_KEY_PAD_6:
            process_movement(cur_x + 1, cur_y, controllable);
            break;
        case ALLEGRO_KEY_PAD_7:
            process_movement(cur_x - 1, cur_y - 1, controllable);
            break;
        case ALLEGRO_KEY_PAD_8:
            process_movement(cur_x, cur_y - 1, controllable);
            break;
        case ALLEGRO_KEY_PAD_9:
            process_movement(cur_x + 1, cur_y - 1, controllable);
            break;
        }

        if (
            event.keyboard.keycode == ALLEGRO_KEY_ESCAPE ||
            event.keyboard.unichar == 'q'
        ) {
            return true;
        }
    }

    return false;
}

void GameContext::game_loop()
{
    Creature* player;
    if (!(player = get_player()))
    {
        return;
    }

    creatures.push_back(
        new Creature(
            'g', false, false, false, player->get_x() + 2, player->get_y() - 2,
            100, 10
        )
    );

    while (1)
    {
        for (auto it = creatures.begin(); it != creatures.end(); it++)
        {
            if (!(*it)->is_turn(clock_time))
            {
                continue;
            }

            if (!(*it)->is_controllable())
            {
                continue;
            }

            display->draw_dungeon(
                (*it)->get_x(), (*it)->get_y(),
                dungeon, creatures.cbegin(), creatures.cend()
            );

            display->draw_event_messages(event_messages);

            display->draw_borders();

            display->update_screen();

            bool exit_request = take_input(*it);

            if (exit_request)
            {
                goto BREAK_GAME_LOOP;
            }
        }

        clock_time += 5;
    }

BREAK_GAME_LOOP:

    return;
}

Creature* GameContext::get_player()
{
    for (auto it = creatures.begin(); it != creatures.end(); it++)
    {
        if ((*it)->is_player())
        {
            return *it;
        }
    }

    return NULL;
}

GameContext::~GameContext()
{
    delete display;
    delete dungeon;

    for (auto it = creatures.begin(); it != creatures.end(); it++)
    {
        delete *it;
    }

    al_destroy_event_queue(queue);
}
<|endoftext|>


<commit_before>// Time:  O(logn * nlogx * logx) = O(1)
// Space: O(nlogx) = O(1)

// Iterative solution.
class Solution {
public:
    /**
     * @param x the base number
     * @param n the power number
     * @return the result
     */
    double myPow(double x, int n) {
        double result = 1;
        long long abs_n = abs(static_cast<long long>(n));
        while (abs_n > 0) {
            if (abs_n & 1) {
                result *= x;
            }
            abs_n >>= 1;
            x *= x;
        }
        return n < 0 ? 1 / result : result;
    }
};

// Time:  O(logn * nlogx * logx) = O(1)
// Space: O(nlogx) = O(1)
// Recursive solution.
class Solution2 {
public:
    /**
     * @param x the base number
     * @param n the power number
     * @return the resultult
     */
    double myPow(double x, int n) {
        if (n < 0 && n != -n) {
            return 1.0 / myPow(x, -n);
        }
        if (n == 0) {
            return 1;
        }
        double v = myPow(x, n / 2);
        if (n % 2 == 0) {
            return v * v;
        } else {
            return v * v * x;
        }
    }
};
<commit_msg>Update powx-n.cpp<commit_after>// Time:  O(logn)
// Space: O(1)

// Iterative solution.
class Solution {
public:
    /**
     * @param x the base number
     * @param n the power number
     * @return the result
     */
    double myPow(double x, int n) {
        double result = 1;
        long long abs_n = abs(static_cast<long long>(n));
        while (abs_n > 0) {
            if (abs_n & 1) {
                result *= x;
            }
            abs_n >>= 1;
            x *= x;
        }
        return n < 0 ? 1 / result : result;
    }
};

// Time:  O(logn)
// Space: O(logn)
// Recursive solution.
class Solution2 {
public:
    /**
     * @param x the base number
     * @param n the power number
     * @return the resultult
     */
    double myPow(double x, int n) {
        if (n < 0 && n != -n) {
            return 1.0 / myPow(x, -n);
        }
        if (n == 0) {
            return 1;
        }
        double v = myPow(x, n / 2);
        if (n % 2 == 0) {
            return v * v;
        } else {
            return v * v * x;
        }
    }
};
<|endoftext|>


<commit_before><commit_msg>switched to C++ style arrays<commit_after><|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 * Point Cloud Library (PCL) - www.pointclouds.org
 * Copyright (c) 2009-2012, Willow Garage, Inc.
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 * * Neither the name of Willow Garage, Inc. nor the names of its
 *   contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <pcl/common/time.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>

#include <pcl/io/pcd_io.h>
#include <pcl/pcl_macros.h>

#include <pcl/console/print.h>
#include <pcl/console/parse.h>

#include <pcl/outofcore/outofcore.h>
#include <pcl/outofcore/outofcore_impl.h>

// todo: Read clouds as PointCloud2 so we don't need to define PointT explicitly.
//       This also requires our octree to take PointCloud2 as an input.
typedef pcl::PointXYZRGBA PointT;

using namespace pcl;
using namespace pcl::outofcore;

using pcl::console::parse_argument;
using pcl::console::parse_file_extension_argument;
using pcl::console::find_switch;
using pcl::console::print_error;
using pcl::console::print_warn;
using pcl::console::print_info;

#include <boost/foreach.hpp>

typedef octree_base<octree_disk_container<PointT> , PointT> octree_disk;

const int OCTREE_DEPTH (0);
const int OCTREE_RESOLUTION (1);

PointCloud<PointT>::Ptr
getCloudFromFile (boost::filesystem::path pcd_path)
{
  // Read PCD file
  PointCloud<PointT>::Ptr cloud (new PointCloud<PointT> ());

  print_info ("Reading: %s ", pcd_path.c_str ());

  if (io::loadPCDFile<PointT> (pcd_path.string (), *cloud) == -1) //* load the file
  {
    PCL_ERROR ("Couldn't read file\n");
    exit (-1);
  }

  print_info ("(%d)\n", (cloud->width * cloud->height));
  return cloud;
}

int
outofcoreProcess (std::vector<boost::filesystem::path> pcd_paths, boost::filesystem::path root_dir,
                  int depth, double resolution, int build_octree_with, bool gen_lod, bool overwrite)
{
  // Bounding box min/max pts
  PointT min_pt, max_pt;

  // Iterate over all pcd files resizing min/max
  for (size_t i = 0; i < pcd_paths.size (); i++)
  {

    // Get cloud
    PointCloud<PointT>::Ptr cloud = getCloudFromFile (pcd_paths[i]);

    PointT tmp_min_pt, tmp_max_pt;

    if (i == 0)
    {
      // Get initial min/max
      getMinMax3D (*cloud, min_pt, max_pt);
    }
    else
    {
      getMinMax3D (*cloud, tmp_min_pt, tmp_max_pt);

      // Resize new min
      if (tmp_min_pt.x < min_pt.x)
        min_pt.x = tmp_min_pt.x;
      if (tmp_min_pt.y < min_pt.y)
        min_pt.y = tmp_min_pt.y;
      if (tmp_min_pt.z < min_pt.z)
        min_pt.z = tmp_min_pt.z;

      // Resize new max
      if (tmp_max_pt.x > max_pt.x)
        max_pt.x = tmp_max_pt.x;
      if (tmp_max_pt.y > max_pt.y)
        max_pt.y = tmp_max_pt.y;
      if (tmp_max_pt.z > max_pt.z)
        max_pt.z = tmp_max_pt.z;
    }
  }

  std::cout << "Bounds: " << min_pt << " - " << max_pt << std::endl;

  // The bounding box of the root node of the out-of-core octree must be specified
  const double bounding_box_min[3] = {min_pt.x, min_pt.y, min_pt.z};
  const double bounding_box_max[3] = {max_pt.x, max_pt.y, max_pt.z};

//arbitrarily large bounding box
//  const double bounding_box_min[3] = { -1e8, -1e8, -1e8 };
//  const double bounding_box_max[3] = { 1e8, 1e8, 1e8 };

  //specify the directory and the root node's meta data file with a
  //".oct_idx" extension (currently it must be this extension)
  boost::filesystem::path octree_path_on_disk (root_dir / "tree.oct_idx");

  print_info ("Writing: %s\n", octree_path_on_disk.c_str ());
  //make sure there isn't an octree there already
  if (boost::filesystem::exists (octree_path_on_disk))
  {
    if (overwrite)
    {
      boost::filesystem::remove_all (root_dir);
    }
    else
    {
      PCL_ERROR ("There's already an octree in the default location. Check the tree directory\n");
      return (-1);
    }
  }

  octree_disk *outofcore_octree;

  //create the out-of-core data structure (typedef'd above)
  if (build_octree_with == OCTREE_DEPTH)
  {
    outofcore_octree = new octree_disk (depth, bounding_box_min, bounding_box_max, octree_path_on_disk, "ECEF");
  }
  else
  {
    outofcore_octree = new octree_disk (bounding_box_min, bounding_box_max, resolution, octree_path_on_disk, "ECEF");
  }

  uint64_t total_pts = 0;

  // Iterate over all pcd files adding points to the octree
  for (size_t i = 0; i < pcd_paths.size (); i++)
  {

    PointCloud<PointT>::Ptr cloud = getCloudFromFile (pcd_paths[i]);

    uint64_t pts = 0;

    //load the points into the outofcore octree
    if (gen_lod)
    {
      print_info ("  Generating LODs\n");
      pts = outofcore_octree->addPointCloud_and_genLOD (cloud);
    }
    else
    {
      pts = outofcore_octree->addPointCloud (cloud);
    }
    print_info ("Successfully added %lu points\n",pts);
    assert ( pts == cloud->points.size () );

    total_pts += pts;
  }

  print_info ("Added a total of %lu from %d clouds\n",total_pts, pcd_paths.size ());

  double x, y;
  outofcore_octree->getBinDimension (x, y);

  print_info ("  Depth: %i\n", outofcore_octree->getDepth ());
  print_info ("  Resolution: [%f, %f]\n", x, y);

  //free outofcore data structure; the destructor forces buffer flush to disk
  delete outofcore_octree;

  return 0;
}

void
printHelp (int, char **argv)
{
  print_info ("This program is used to process pcd fiels into an outofcore data structure viewable by the");
  print_info ("pcl_outofcore_viewer\n\n");
  print_info ("%s <options> <input>.pcd <output_tree_dir>\n", argv[0]);
  print_info ("\n");
  print_info ("Options:\n");
  print_info ("\t -depth <resolution>           \t Octree depth\n");
  print_info ("\t -resolution <resolution>      \t Octree resolution\n");
  print_info ("\t -gen_lod                      \t Generate octree LODs\n");
  print_info ("\t -overwrite                    \t Overwrite existing octree\n");
  print_info ("\t -h                            \t Display help\n");
  print_info ("\n");
}

int
main (int argc, char* argv[])
{
  // Check for help (-h) flag
  if (argc > 1)
  {
    if (find_switch (argc, argv, "-h"))
    {
      printHelp (argc, argv);
      return (-1);
    }
  }

  // If no arguments specified
  if (argc - 1 < 1)
  {
    printHelp (argc, argv);
    return (-1);
  }

  // Defaults
  int depth = 4;
  double resolution = .1;
  bool gen_lod = false;
  bool overwrite = false;
  int build_octree_with = OCTREE_DEPTH;

  // If both depth and resolution specified
  if (find_switch (argc, argv, "-depth") && find_switch (argc, argv, "-resolution"))
  {
    PCL_ERROR ("Both -depth and -resolution specified, please specify one (Mutually exclusive)\n");
  }
  // Just resolution specified (Update how we build the tree)
  else if (find_switch (argc, argv, "-resolution"))
  {
    build_octree_with = OCTREE_RESOLUTION;
  }

  // Parse options
  parse_argument (argc, argv, "-depth", depth);
  parse_argument (argc, argv, "-resolution", resolution);
  gen_lod = find_switch (argc, argv, "-gen_lod");
  overwrite = find_switch (argc, argv, "-overwrite");

  // Parse non-option arguments for pcd files
  std::vector<int> file_arg_indices = parse_file_extension_argument (argc, argv, ".pcd");

  std::vector<boost::filesystem::path> pcd_paths;
  for (size_t i = 0; i < file_arg_indices.size (); i++)
  {
    boost::filesystem::path pcd_path (argv[file_arg_indices[i]]);
    if (!boost::filesystem::exists (pcd_path))
    {
      PCL_WARN ("File %s doesn't exist", pcd_path.string ().c_str ());
      continue;
    }
    pcd_paths.push_back (pcd_path);

  }

  // Check if we should process any files
  if (pcd_paths.size () < 1)
  {
    PCL_ERROR ("No .pcd files specified\n");
    return -1;
  }

  // Get root directory
  boost::filesystem::path root_dir (argv[argc - 1]);

  // Check if a root directory was specified, use directory of pcd file
  if (root_dir.extension () == ".pcd")
    root_dir = root_dir.parent_path () / "tree";

  return outofcoreProcess (pcd_paths, root_dir, depth, resolution, build_octree_with, gen_lod, overwrite);
}
<commit_msg>keep the default point type XYZ in outofcore_process for now<commit_after>/*
 * Software License Agreement (BSD License)
 *
 * Point Cloud Library (PCL) - www.pointclouds.org
 * Copyright (c) 2009-2012, Willow Garage, Inc.
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 * * Neither the name of Willow Garage, Inc. nor the names of its
 *   contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <pcl/common/time.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>

#include <pcl/io/pcd_io.h>
#include <pcl/pcl_macros.h>

#include <pcl/console/print.h>
#include <pcl/console/parse.h>

#include <pcl/outofcore/outofcore.h>
#include <pcl/outofcore/outofcore_impl.h>

// todo: Read clouds as PointCloud2 so we don't need to define PointT explicitly.
//       This also requires our octree to take PointCloud2 as an input.
typedef pcl::PointXYZ PointT;

using namespace pcl;
using namespace pcl::outofcore;

using pcl::console::parse_argument;
using pcl::console::parse_file_extension_argument;
using pcl::console::find_switch;
using pcl::console::print_error;
using pcl::console::print_warn;
using pcl::console::print_info;

#include <boost/foreach.hpp>

typedef octree_base<octree_disk_container<PointT> , PointT> octree_disk;

const int OCTREE_DEPTH (0);
const int OCTREE_RESOLUTION (1);

PointCloud<PointT>::Ptr
getCloudFromFile (boost::filesystem::path pcd_path)
{
  // Read PCD file
  PointCloud<PointT>::Ptr cloud (new PointCloud<PointT> ());

  print_info ("Reading: %s ", pcd_path.c_str ());

  if (io::loadPCDFile<PointT> (pcd_path.string (), *cloud) == -1) //* load the file
  {
    PCL_ERROR ("Couldn't read file\n");
    exit (-1);
  }

  print_info ("(%d)\n", (cloud->width * cloud->height));
  return cloud;
}

int
outofcoreProcess (std::vector<boost::filesystem::path> pcd_paths, boost::filesystem::path root_dir,
                  int depth, double resolution, int build_octree_with, bool gen_lod, bool overwrite)
{
  // Bounding box min/max pts
  PointT min_pt, max_pt;

  // Iterate over all pcd files resizing min/max
  for (size_t i = 0; i < pcd_paths.size (); i++)
  {

    // Get cloud
    PointCloud<PointT>::Ptr cloud = getCloudFromFile (pcd_paths[i]);

    PointT tmp_min_pt, tmp_max_pt;

    if (i == 0)
    {
      // Get initial min/max
      getMinMax3D (*cloud, min_pt, max_pt);
    }
    else
    {
      getMinMax3D (*cloud, tmp_min_pt, tmp_max_pt);

      // Resize new min
      if (tmp_min_pt.x < min_pt.x)
        min_pt.x = tmp_min_pt.x;
      if (tmp_min_pt.y < min_pt.y)
        min_pt.y = tmp_min_pt.y;
      if (tmp_min_pt.z < min_pt.z)
        min_pt.z = tmp_min_pt.z;

      // Resize new max
      if (tmp_max_pt.x > max_pt.x)
        max_pt.x = tmp_max_pt.x;
      if (tmp_max_pt.y > max_pt.y)
        max_pt.y = tmp_max_pt.y;
      if (tmp_max_pt.z > max_pt.z)
        max_pt.z = tmp_max_pt.z;
    }
  }

  std::cout << "Bounds: " << min_pt << " - " << max_pt << std::endl;

  // The bounding box of the root node of the out-of-core octree must be specified
  const double bounding_box_min[3] = {min_pt.x, min_pt.y, min_pt.z};
  const double bounding_box_max[3] = {max_pt.x, max_pt.y, max_pt.z};

//arbitrarily large bounding box
//  const double bounding_box_min[3] = { -1e8, -1e8, -1e8 };
//  const double bounding_box_max[3] = { 1e8, 1e8, 1e8 };

  //specify the directory and the root node's meta data file with a
  //".oct_idx" extension (currently it must be this extension)
  boost::filesystem::path octree_path_on_disk (root_dir / "tree.oct_idx");

  print_info ("Writing: %s\n", octree_path_on_disk.c_str ());
  //make sure there isn't an octree there already
  if (boost::filesystem::exists (octree_path_on_disk))
  {
    if (overwrite)
    {
      boost::filesystem::remove_all (root_dir);
    }
    else
    {
      PCL_ERROR ("There's already an octree in the default location. Check the tree directory\n");
      return (-1);
    }
  }

  octree_disk *outofcore_octree;

  //create the out-of-core data structure (typedef'd above)
  if (build_octree_with == OCTREE_DEPTH)
  {
    outofcore_octree = new octree_disk (depth, bounding_box_min, bounding_box_max, octree_path_on_disk, "ECEF");
  }
  else
  {
    outofcore_octree = new octree_disk (bounding_box_min, bounding_box_max, resolution, octree_path_on_disk, "ECEF");
  }

  uint64_t total_pts = 0;

  // Iterate over all pcd files adding points to the octree
  for (size_t i = 0; i < pcd_paths.size (); i++)
  {

    PointCloud<PointT>::Ptr cloud = getCloudFromFile (pcd_paths[i]);

    uint64_t pts = 0;

    //load the points into the outofcore octree
    if (gen_lod)
    {
      print_info ("  Generating LODs\n");
      pts = outofcore_octree->addPointCloud_and_genLOD (cloud);
    }
    else
    {
      pts = outofcore_octree->addPointCloud (cloud);
    }
    print_info ("Successfully added %lu points\n",pts);
    assert ( pts == cloud->points.size () );

    total_pts += pts;
  }

  print_info ("Added a total of %lu from %d clouds\n",total_pts, pcd_paths.size ());

  double x, y;
  outofcore_octree->getBinDimension (x, y);

  print_info ("  Depth: %i\n", outofcore_octree->getDepth ());
  print_info ("  Resolution: [%f, %f]\n", x, y);

  //free outofcore data structure; the destructor forces buffer flush to disk
  delete outofcore_octree;

  return 0;
}

void
printHelp (int, char **argv)
{
  print_info ("This program is used to process pcd fiels into an outofcore data structure viewable by the");
  print_info ("pcl_outofcore_viewer\n\n");
  print_info ("%s <options> <input>.pcd <output_tree_dir>\n", argv[0]);
  print_info ("\n");
  print_info ("Options:\n");
  print_info ("\t -depth <resolution>           \t Octree depth\n");
  print_info ("\t -resolution <resolution>      \t Octree resolution\n");
  print_info ("\t -gen_lod                      \t Generate octree LODs\n");
  print_info ("\t -overwrite                    \t Overwrite existing octree\n");
  print_info ("\t -h                            \t Display help\n");
  print_info ("\n");
}

int
main (int argc, char* argv[])
{
  // Check for help (-h) flag
  if (argc > 1)
  {
    if (find_switch (argc, argv, "-h"))
    {
      printHelp (argc, argv);
      return (-1);
    }
  }

  // If no arguments specified
  if (argc - 1 < 1)
  {
    printHelp (argc, argv);
    return (-1);
  }

  // Defaults
  int depth = 4;
  double resolution = .1;
  bool gen_lod = false;
  bool overwrite = false;
  int build_octree_with = OCTREE_DEPTH;

  // If both depth and resolution specified
  if (find_switch (argc, argv, "-depth") && find_switch (argc, argv, "-resolution"))
  {
    PCL_ERROR ("Both -depth and -resolution specified, please specify one (Mutually exclusive)\n");
  }
  // Just resolution specified (Update how we build the tree)
  else if (find_switch (argc, argv, "-resolution"))
  {
    build_octree_with = OCTREE_RESOLUTION;
  }

  // Parse options
  parse_argument (argc, argv, "-depth", depth);
  parse_argument (argc, argv, "-resolution", resolution);
  gen_lod = find_switch (argc, argv, "-gen_lod");
  overwrite = find_switch (argc, argv, "-overwrite");

  // Parse non-option arguments for pcd files
  std::vector<int> file_arg_indices = parse_file_extension_argument (argc, argv, ".pcd");

  std::vector<boost::filesystem::path> pcd_paths;
  for (size_t i = 0; i < file_arg_indices.size (); i++)
  {
    boost::filesystem::path pcd_path (argv[file_arg_indices[i]]);
    if (!boost::filesystem::exists (pcd_path))
    {
      PCL_WARN ("File %s doesn't exist", pcd_path.string ().c_str ());
      continue;
    }
    pcd_paths.push_back (pcd_path);

  }

  // Check if we should process any files
  if (pcd_paths.size () < 1)
  {
    PCL_ERROR ("No .pcd files specified\n");
    return -1;
  }

  // Get root directory
  boost::filesystem::path root_dir (argv[argc - 1]);

  // Check if a root directory was specified, use directory of pcd file
  if (root_dir.extension () == ".pcd")
    root_dir = root_dir.parent_path () / "tree";

  return outofcoreProcess (pcd_paths, root_dir, depth, resolution, build_octree_with, gen_lod, overwrite);
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB)
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "kdsysinfo.h"

#include <QLibrary>
#include <QStringList>

#include <qt_windows.h>
#include <psapi.h>
#include <tlhelp32.h>
#include <winternl.h>

QRUNINFO_NAMEPASE_BEGIN

const int KDSYSINFO_PROCESS_QUERY_LIMITED_INFORMATION = 0x1000;

typedef NTSTATUS ( * NtQueryInformationProcessPtr)(HANDLE ,PROCESSINFOCLASS ,PVOID ,ULONG ,PULONG );

quint64  RunInfo::installedMemory()
{
    MEMORYSTATUSEX status;
    status.dwLength = sizeof(status);
    GlobalMemoryStatusEx(&status);
    return quint64(status.ullTotalPhys);
}

struct EnumWindowsProcParam
{
    QList<ProcessInfo> processes;
    QList<quint32> seenIDs;
};

typedef BOOL (WINAPI *QueryFullProcessImageNamePtr)(HANDLE, DWORD, char *, PDWORD);
typedef DWORD (WINAPI *GetProcessImageFileNamePtr)(HANDLE, char *, DWORD);

QList<ProcessInfo>  RunInfo::runningProcesses()
{
    EnumWindowsProcParam param;
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (!snapshot)
        return param.processes;

    QStringList deviceList;
    const DWORD bufferSize = 1024;
    char buffer[bufferSize + 1] = { 0 };
    if (QSysInfo::windowsVersion() <= QSysInfo::WV_5_2) {
        const DWORD size = GetLogicalDriveStringsA(bufferSize, buffer);
        deviceList = QString::fromLatin1(buffer, size).split(QLatin1Char(char(0)), QString::SkipEmptyParts);
    }

    QLibrary kernel32(QLatin1String("Kernel32.dll"));
    kernel32.load();
    QueryFullProcessImageNamePtr pQueryFullProcessImageNamePtr = (QueryFullProcessImageNamePtr) kernel32
        .resolve("QueryFullProcessImageNameA");

    QLibrary psapi(QLatin1String("Psapi.dll"));
    psapi.load();
    GetProcessImageFileNamePtr pGetProcessImageFileNamePtr = (GetProcessImageFileNamePtr) psapi
        .resolve("GetProcessImageFileNameA");

    PROCESSENTRY32 processStruct;
    processStruct.dwSize = sizeof(PROCESSENTRY32);
    bool foundProcess = Process32First(snapshot, &processStruct);
    while (foundProcess) {
        HANDLE procHandle = OpenProcess(QSysInfo::windowsVersion() > QSysInfo::WV_5_2
            ? KDSYSINFO_PROCESS_QUERY_LIMITED_INFORMATION : PROCESS_QUERY_INFORMATION, false, processStruct
                .th32ProcessID);

        bool succ = false;
        QString executablePath;
        DWORD bufferSize = 1024;

        if (QSysInfo::windowsVersion() > QSysInfo::WV_5_2) {
            succ = pQueryFullProcessImageNamePtr(procHandle, 0, buffer, &bufferSize);
            executablePath = QString::fromLatin1(buffer);
        } else if (pGetProcessImageFileNamePtr) {
            succ = pGetProcessImageFileNamePtr(procHandle, buffer, bufferSize);
            executablePath = QString::fromLatin1(buffer);
            for (int i = 0; i < deviceList.count(); ++i) {
                executablePath.replace(QString::fromLatin1( "\\Device\\HarddiskVolume%1\\" ).arg(i + 1),
                    deviceList.at(i));
            }
        }

        if (succ) {
            const quint32 pid = processStruct.th32ProcessID;
            param.seenIDs.append(pid);
            ProcessInfo info;
            info.id = pid;
            info.name = executablePath;
            param.processes.append(info);
        }

        CloseHandle(procHandle);
        foundProcess = Process32Next(snapshot, &processStruct);

    }
    if (snapshot)
        CloseHandle(snapshot);

    kernel32.unload();
    return param.processes;
}

quint32 RunInfo::currentProcessId()
{
    DWORD id = GetCurrentProcessId();
    return  id;
}

quint32 RunInfo::parentProcessId()
{
    DWORD id = static_cast<DWORD>(-1);
    auto lib = LoadLibrary(L"Ntdll.dll");

    if(lib){
     NtQueryInformationProcessPtr ProcPtr = reinterpret_cast<NtQueryInformationProcessPtr>(GetProcAddress(lib, "NtQueryInformationProcess"));
     if(ProcPtr){
        HANDLE handle =  GetCurrentProcess();
        PROCESS_BASIC_INFORMATION info;
        auto status = ProcPtr(handle,ProcessBasicInformation,&info,sizeof (PROCESS_BASIC_INFORMATION),nullptr);
        if (!status)
            id = info.InheritedFromUniqueProcessId;
     }
    }
    return id;
}

QRUNINFO_NAMEPASE_END
<commit_msg>default value<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB)
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "kdsysinfo.h"

#include <QLibrary>
#include <QStringList>

#include <qt_windows.h>
#include <psapi.h>
#include <tlhelp32.h>
#include <winternl.h>

QRUNINFO_NAMEPASE_BEGIN

const int KDSYSINFO_PROCESS_QUERY_LIMITED_INFORMATION = 0x1000;

typedef NTSTATUS ( * NtQueryInformationProcessPtr)(HANDLE ,PROCESSINFOCLASS ,PVOID ,ULONG ,PULONG );

quint64  RunInfo::installedMemory()
{
    MEMORYSTATUSEX status;
    status.dwLength = sizeof(status);
    GlobalMemoryStatusEx(&status);
    return quint64(status.ullTotalPhys);
}

struct EnumWindowsProcParam
{
    QList<ProcessInfo> processes;
    QList<quint32> seenIDs;
};

typedef BOOL (WINAPI *QueryFullProcessImageNamePtr)(HANDLE, DWORD, char *, PDWORD);
typedef DWORD (WINAPI *GetProcessImageFileNamePtr)(HANDLE, char *, DWORD);

QList<ProcessInfo>  RunInfo::runningProcesses()
{
    EnumWindowsProcParam param;
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (!snapshot)
        return param.processes;

    QStringList deviceList;
    const DWORD bufferSize = 1024;
    char buffer[bufferSize + 1] = { 0 };
    if (QSysInfo::windowsVersion() <= QSysInfo::WV_5_2) {
        const DWORD size = GetLogicalDriveStringsA(bufferSize, buffer);
        deviceList = QString::fromLatin1(buffer, size).split(QLatin1Char(char(0)), QString::SkipEmptyParts);
    }

    QLibrary kernel32(QLatin1String("Kernel32.dll"));
    kernel32.load();
    QueryFullProcessImageNamePtr pQueryFullProcessImageNamePtr = (QueryFullProcessImageNamePtr) kernel32
        .resolve("QueryFullProcessImageNameA");

    QLibrary psapi(QLatin1String("Psapi.dll"));
    psapi.load();
    GetProcessImageFileNamePtr pGetProcessImageFileNamePtr = (GetProcessImageFileNamePtr) psapi
        .resolve("GetProcessImageFileNameA");

    PROCESSENTRY32 processStruct;
    processStruct.dwSize = sizeof(PROCESSENTRY32);
    bool foundProcess = Process32First(snapshot, &processStruct);
    while (foundProcess) {
        HANDLE procHandle = OpenProcess(QSysInfo::windowsVersion() > QSysInfo::WV_5_2
            ? KDSYSINFO_PROCESS_QUERY_LIMITED_INFORMATION : PROCESS_QUERY_INFORMATION, false, processStruct
                .th32ProcessID);

        bool succ = false;
        QString executablePath;
        DWORD bufferSize = 1024;

        if (QSysInfo::windowsVersion() > QSysInfo::WV_5_2) {
            succ = pQueryFullProcessImageNamePtr(procHandle, 0, buffer, &bufferSize);
            executablePath = QString::fromLatin1(buffer);
        } else if (pGetProcessImageFileNamePtr) {
            succ = pGetProcessImageFileNamePtr(procHandle, buffer, bufferSize);
            executablePath = QString::fromLatin1(buffer);
            for (int i = 0; i < deviceList.count(); ++i) {
                executablePath.replace(QString::fromLatin1( "\\Device\\HarddiskVolume%1\\" ).arg(i + 1),
                    deviceList.at(i));
            }
        }

        if (succ) {
            const quint32 pid = processStruct.th32ProcessID;
            param.seenIDs.append(pid);
            ProcessInfo info;
            info.id = pid;
            info.name = executablePath;
            param.processes.append(info);
        }

        CloseHandle(procHandle);
        foundProcess = Process32Next(snapshot, &processStruct);

    }
    if (snapshot)
        CloseHandle(snapshot);

    kernel32.unload();
    return param.processes;
}

quint32 RunInfo::currentProcessId()
{
    DWORD id = GetCurrentProcessId();
    return  id;
}

quint32 RunInfo::parentProcessId()
{
    DWORD id = static_cast<DWORD>(0);
    auto lib = LoadLibrary(L"Ntdll.dll");

    if(lib){
     NtQueryInformationProcessPtr ProcPtr = reinterpret_cast<NtQueryInformationProcessPtr>(GetProcAddress(lib, "NtQueryInformationProcess"));
     if(ProcPtr){
        HANDLE handle =  GetCurrentProcess();
        PROCESS_BASIC_INFORMATION info;
        auto status = ProcPtr(handle,ProcessBasicInformation,&info,sizeof (PROCESS_BASIC_INFORMATION),nullptr);
        if (!status)
            id = info.InheritedFromUniqueProcessId;
     }
    }
    return id;
}

QRUNINFO_NAMEPASE_END
<|endoftext|>


<commit_before>/*
 * $Id$
 *
 * Copyright(C) 1998-2004 Satoshi Nakamura
 * All rights reserved.
 *
 */

#include <qmprotocoldriver.h>

#include <qsassert.h>
#include <qsstl.h>
#include <qsstring.h>

#include <algorithm>
#include <vector>

#pragma warning(disable:4786)

using namespace qm;
using namespace qs;

namespace qm {
struct ProtocolFactoryImpl;
}

/****************************************************************************
 *
 * ProtocolDriver
 *
 */

qm::ProtocolDriver::~ProtocolDriver()
{
}

/****************************************************************************
 *
 * ProtocolFactoryImpl
 *
 */

struct qm::ProtocolFactoryImpl
{
	typedef std::vector<std::pair<const WCHAR*, ProtocolFactory*> > FactoryList;

	static FactoryList::iterator getIterator(const WCHAR* pwszName);

	static FactoryList listFactory__;
	static std::auto_ptr<PasswordCallback> pPasswordCallback_;
};

qm::ProtocolFactoryImpl::FactoryList qm::ProtocolFactoryImpl::listFactory__;
std::auto_ptr<PasswordCallback> qm::ProtocolFactoryImpl::pPasswordCallback_;

ProtocolFactoryImpl::FactoryList::iterator qm::ProtocolFactoryImpl::getIterator(const WCHAR* pwszName)
{
	return std::find_if(listFactory__.begin(), listFactory__.end(),
		std::bind2nd(
			binary_compose_f_gx_hy(
				string_equal<WCHAR>(),
				std::select1st<FactoryList::value_type>(),
				std::identity<const WCHAR*>()),
			pwszName));
}

/****************************************************************************
 *
 * ProtocolFactory
 *
 */

qm::ProtocolFactory::ProtocolFactory()
{
}

qm::ProtocolFactory::~ProtocolFactory()
{
}

std::auto_ptr<ProtocolDriver> qm::ProtocolFactory::getDriver(Account* pAccount,
															 const Security* pSecurity)
{
	const WCHAR* pwszName = pAccount->getType(Account::HOST_RECEIVE);
	ProtocolFactoryImpl::FactoryList::iterator it =
		ProtocolFactoryImpl::getIterator(pwszName);
	if (it == ProtocolFactoryImpl::listFactory__.end())
		return std::auto_ptr<ProtocolDriver>(0);

	return (*it).second->createDriver(pAccount,
		ProtocolFactoryImpl::pPasswordCallback_.get(), pSecurity);
}

void qm::ProtocolFactory::setPasswordCallback(std::auto_ptr<PasswordCallback> pPasswordCallback)
{
	ProtocolFactoryImpl::pPasswordCallback_ = pPasswordCallback;
}

void qm::ProtocolFactory::registerFactory(const WCHAR* pwszName,
										  ProtocolFactory* pFactory)
{
	assert(pwszName);
	assert(pFactory);

	ProtocolFactoryImpl::listFactory__.push_back(std::make_pair(pwszName, pFactory));
}

void qm::ProtocolFactory::unregisterFactory(const WCHAR* pwszName)
{
	assert(pwszName);

	ProtocolFactoryImpl::FactoryList::iterator it =
		ProtocolFactoryImpl::getIterator(pwszName);
	if (it != ProtocolFactoryImpl::listFactory__.end())
		ProtocolFactoryImpl::listFactory__.erase(it);
}
<commit_msg>Supress warning.<commit_after>/*
 * $Id$
 *
 * Copyright(C) 1998-2004 Satoshi Nakamura
 * All rights reserved.
 *
 */

#include <qmprotocoldriver.h>
#include <qmsession.h>

#include <qsassert.h>
#include <qsstl.h>
#include <qsstring.h>

#include <algorithm>
#include <vector>

#pragma warning(disable:4786)

using namespace qm;
using namespace qs;

namespace qm {
struct ProtocolFactoryImpl;
}

/****************************************************************************
 *
 * ProtocolDriver
 *
 */

qm::ProtocolDriver::~ProtocolDriver()
{
}

/****************************************************************************
 *
 * ProtocolFactoryImpl
 *
 */

struct qm::ProtocolFactoryImpl
{
	typedef std::vector<std::pair<const WCHAR*, ProtocolFactory*> > FactoryList;

	static FactoryList::iterator getIterator(const WCHAR* pwszName);

	static FactoryList listFactory__;
	static std::auto_ptr<PasswordCallback> pPasswordCallback_;
};

qm::ProtocolFactoryImpl::FactoryList qm::ProtocolFactoryImpl::listFactory__;
std::auto_ptr<PasswordCallback> qm::ProtocolFactoryImpl::pPasswordCallback_;

ProtocolFactoryImpl::FactoryList::iterator qm::ProtocolFactoryImpl::getIterator(const WCHAR* pwszName)
{
	return std::find_if(listFactory__.begin(), listFactory__.end(),
		std::bind2nd(
			binary_compose_f_gx_hy(
				string_equal<WCHAR>(),
				std::select1st<FactoryList::value_type>(),
				std::identity<const WCHAR*>()),
			pwszName));
}

/****************************************************************************
 *
 * ProtocolFactory
 *
 */

qm::ProtocolFactory::ProtocolFactory()
{
}

qm::ProtocolFactory::~ProtocolFactory()
{
}

std::auto_ptr<ProtocolDriver> qm::ProtocolFactory::getDriver(Account* pAccount,
															 const Security* pSecurity)
{
	const WCHAR* pwszName = pAccount->getType(Account::HOST_RECEIVE);
	ProtocolFactoryImpl::FactoryList::iterator it =
		ProtocolFactoryImpl::getIterator(pwszName);
	if (it == ProtocolFactoryImpl::listFactory__.end())
		return std::auto_ptr<ProtocolDriver>(0);

	return (*it).second->createDriver(pAccount,
		ProtocolFactoryImpl::pPasswordCallback_.get(), pSecurity);
}

void qm::ProtocolFactory::setPasswordCallback(std::auto_ptr<PasswordCallback> pPasswordCallback)
{
	ProtocolFactoryImpl::pPasswordCallback_ = pPasswordCallback;
}

void qm::ProtocolFactory::registerFactory(const WCHAR* pwszName,
										  ProtocolFactory* pFactory)
{
	assert(pwszName);
	assert(pFactory);

	ProtocolFactoryImpl::listFactory__.push_back(std::make_pair(pwszName, pFactory));
}

void qm::ProtocolFactory::unregisterFactory(const WCHAR* pwszName)
{
	assert(pwszName);

	ProtocolFactoryImpl::FactoryList::iterator it =
		ProtocolFactoryImpl::getIterator(pwszName);
	if (it != ProtocolFactoryImpl::listFactory__.end())
		ProtocolFactoryImpl::listFactory__.erase(it);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <cstdint>
#include <cstring>

#include <ffi.h>
#include <dlfcn.h>

struct Value {
  ffi_type *type;
  union {
    uint8_t u8;
    uint16_t u16;
    uint32_t u32;
    uint64_t u64;
    int8_t s8;
    int16_t s16;
    int32_t s32;
    int64_t s64;
    float f;
    double d;
    void *ptr;
  } value;
};

std::ostream &operator<<(std::ostream &out, const Value &v) {
  if (v.type == &ffi_type_uint8) {
    out << v.value.u8;
  } else if (v.type == &ffi_type_uint16) {
    out << v.value.u16;
  } else if (v.type == &ffi_type_uint32) {
    out << v.value.u32;
  } else if (v.type == &ffi_type_uint64) {
    out << v.value.u64;
  } else if (v.type == &ffi_type_sint8) {
    out << v.value.s8;
  } else if (v.type == &ffi_type_sint16) {
    out << v.value.s16;
  } else if (v.type == &ffi_type_sint32) {
    out << v.value.s32;
  } else if (v.type == &ffi_type_sint64) {
    out << v.value.s64;
  } else if (v.type == &ffi_type_float) {
    out << v.value.f;
  } else if (v.type == &ffi_type_double) {
    out << v.value.d;
  } else if (v.type == &ffi_type_pointer) {
    out << v.value.ptr;
  }
  out << "\n$";
  return out;
}

class FFIStack {
 public:
  void push(uint8_t v) {
    stack_.push_back(Value{&ffi_type_uint8, {.u8 = v}});
  }
  void push(uint16_t v) {
    stack_.push_back(Value{&ffi_type_uint16, {.u16 = v}});
  }
  void push(uint32_t v) {
    stack_.push_back(Value{&ffi_type_uint32, {.u32 = v}});
  }
  void push(uint64_t v) {
    stack_.push_back(Value{&ffi_type_uint64, {.u64 = v}});
  }
  void push(int8_t v) {
    stack_.push_back(Value{&ffi_type_sint8, {.s8 = v}});
  }
  void push(int16_t v) {
    stack_.push_back(Value{&ffi_type_sint16, {.s16 = v}});
  }
  void push(int32_t v) {
    stack_.push_back(Value{&ffi_type_sint32, {.s32 = v}});
  }
  void push(int64_t v) {
    stack_.push_back(Value{&ffi_type_sint64, {.s64 = v}});
  }
  void push(double v) {
    stack_.push_back(Value{&ffi_type_double, {.d = v}});
  }
  void push(float v) {
    stack_.push_back(Value{&ffi_type_float, {.f = v}});
  }
  void push(void *v) {
    stack_.push_back(Value{&ffi_type_pointer, {.ptr = v}});
  }
  void push(Value &v) { stack_.push_back(v); }

  Value pop() {
    Value v = stack_.back();
    stack_.pop_back();
    return v;
  }

  Value peek() { return stack_.back(); }

  Value &operator[](int i) { return stack_[stack_.size() - i - 1]; }

  void dup() {
    stack_.push_back(stack_.back());
  }

  size_t size() {
    return stack_.size();
  }

 private:
  std::vector<Value> stack_;
};

class Machine {
 public:
  Machine(std::ostream &out) : out_{out} {};
  ~Machine() {
    for (auto &i : cifs_) {
      delete i->arg_types;
      delete i;
    }
    for (auto &i : libs_) {
      dlclose(i);
    }
  };

  FFIStack stack;

  void pop() { out_ << stack.pop(); }

  void peek() { out_ << stack.peek(); }

  void dlopen() {
    const char *name = static_cast<const char *>(stack.pop().value.ptr);
    void *handle = ::dlopen(name, RTLD_LAZY);
    stack.push(handle);
    libs_.push_back(handle);
  }

  void dlsym() {
    const char *name = static_cast<const char *>(stack.pop().value.ptr);
    void *handle = stack.pop().value.ptr;
    void *ptr = ::dlsym(handle, name);
    stack.push(ptr);
  }

  void cif() {
    ffi_cif *cif = new ffi_cif;
    uint32_t nargs = stack.pop().value.u32;
    ffi_type *rtype = stack.pop().type;
    ffi_type **types = new ffi_type*[nargs];
    for (uint32_t i = 0; i < nargs; i++) {
      types[i] = stack.pop().type;
    }
    ffi_prep_cif(cif, FFI_DEFAULT_ABI, nargs, rtype, types);
    stack.push(cif);
    cifs_.push_back(cif);
  }

  void call() {
    void (*function)() = reinterpret_cast<void (*)()>(stack.pop().value.ptr);
    ffi_cif *cif = static_cast<ffi_cif *>(stack.pop().value.ptr);
    int nargs = cif->nargs;
    void *args[nargs];
    Value result {cif->rtype, {0}};
    for (int i = 0; i < nargs; i++) {
      args[i] = &stack[i].value;
    }
    ffi_call(cif, function, &result.value, args);
    for (int i = 0; i < nargs; i++) {
      stack.pop();
    }
    stack.push(result);
  }

  void strlen() {
    char *str = static_cast<char *>(stack.peek().value.ptr);
    uint32_t size = std::strlen(str);
    stack.push(size);
  }

  void dump() {
    uint32_t size = stack.pop().value.u32;
    char *data = static_cast<char *>(stack.peek().value.ptr);
    out_.write(data, size);
  }

  void free() { delete static_cast<char *>(stack.pop().value.ptr); }

  void size() {
    uint32_t size = stack.size();
    stack.push(size);
  }

 private:
  std::ostream &out_;
  std::vector<ffi_cif *> cifs_;
  std::vector<void *> libs_;
};

class Reader {
 public:
  Reader(Machine &vm, std::istream &in) : vm_{vm}, in_{in} {};

  void read_uint8() {
    uint8_t i;
    in_ >> i;
    vm_.stack.push(i);
  }
  void read_uint16() {
    uint16_t i;
    in_ >> i;
    vm_.stack.push(i);
  }
  void read_uint32() {
    uint32_t i;
    in_ >> i;
    vm_.stack.push(i);
  }
  void read_uint64() {
    uint64_t i;
    in_ >> i;
    vm_.stack.push(i);
  }

  void read_sint8() {
    int8_t i;
    in_ >> i;
    vm_.stack.push(i);
  }
  void read_sint16() {
    int16_t i;
    in_ >> i;
    vm_.stack.push(i);
  }
  void read_sint32() {
    int32_t i;
    in_ >> i;
    vm_.stack.push(i);
  }
  void read_sint64() {
    int64_t i;
    in_ >> i;
    vm_.stack.push(i);
  }

  void read_float() {
    float f;
    in_ >> f;
    vm_.stack.push(f);
  }
  void read_double() {
    double d;
    in_ >> d;
    vm_.stack.push(d);
  }

  void read_pointer() {
    void *ptr = nullptr;
    in_ >> ptr;
    vm_.stack.push(ptr);
  }

  void read(uint32_t size) {
    char *buffer = new char[size];
    in_.read(buffer, size);
    vm_.stack.push(buffer);
  }

 private:
  Machine &vm_;
  std::istream &in_;
};

int main() {
  Machine vm{std::cout};
  Reader reader{vm, std::cin};

  while (!std::cin.eof()) {
    int command = std::cin.get();
    switch (command) {
      /* push signed integer */
      case 'i' + 0: /* i */
        reader.read_sint8();
        break;
      case 'i' + 1: /* j */
        reader.read_sint16();
        break;
      case 'i' + 2: /* k */
        reader.read_sint32();
        break;
      case 'i' + 3: /* l */
        reader.read_sint64();
        break;

      /* push unsigned integer */
      case 'u' + 0: /* u */
        reader.read_uint8();
        break;
      case 'u' + 1: /* v */
        reader.read_uint16();
        break;
      case 'u' + 2: /* w */
        reader.read_uint32();
        break;
      case 'u' + 3: /* x */
        reader.read_uint64();
        break;

      /* push float */
      case 'f':
        reader.read_float();
        break;
      case 'd':
        reader.read_double();
        break;

      /* push pointer */
      case 'p':
        reader.read_pointer();
        break;

      /* peek */
      case 'e':
        vm.peek();
        break;

      /* pop */
      case 'o':
        vm.pop();
        break;

      /* call */
      case 'c':
        vm.call();
        break;

      /* call */
      case 'C':
        vm.cif();
        break;

      /* "malloc" */
      case 'M':
        reader.read(vm.stack.pop().value.u32);
        break;

      /* free */
      case 'F':
        vm.free();
        break;

      /* push NULL */
      case 'N':
        vm.stack.push(nullptr);
        break;

      /* dl calls */
      case 'O':
        vm.dlopen();
        break;
      case 'S':
        vm.dlsym();
        break;

      /* strlen */
      case 'L':
        vm.strlen();
        break;

      /* dump */
      case 'D':
        vm.dump();
        break;

      /* duplicate top value */
      case '!':
        vm.stack.dup();
        break;

      /* get stack size */
      case '?':
        vm.size();
        break;

      /* no-op */
      case ' ':
      case -1:
        break;

      default:
        std::cerr << "invalid op: " << static_cast<char>(command) << std::endl;
        break;
    }
    std::cout.flush();
  }

  std::cout << std::endl;
  return 0;
}
<commit_msg>Fix dlopen and whitespace issue.<commit_after>#include <iostream>
#include <vector>
#include <cstdint>
#include <cstring>

#include <ffi.h>
#include <dlfcn.h>

struct Value {
  ffi_type *type;
  union {
    uint8_t u8;
    uint16_t u16;
    uint32_t u32;
    uint64_t u64;
    int8_t s8;
    int16_t s16;
    int32_t s32;
    int64_t s64;
    float f;
    double d;
    void *ptr;
  } value;
};

std::ostream &operator<<(std::ostream &out, const Value &v) {
  if (v.type == &ffi_type_uint8) {
    out << v.value.u8;
  } else if (v.type == &ffi_type_uint16) {
    out << v.value.u16;
  } else if (v.type == &ffi_type_uint32) {
    out << v.value.u32;
  } else if (v.type == &ffi_type_uint64) {
    out << v.value.u64;
  } else if (v.type == &ffi_type_sint8) {
    out << v.value.s8;
  } else if (v.type == &ffi_type_sint16) {
    out << v.value.s16;
  } else if (v.type == &ffi_type_sint32) {
    out << v.value.s32;
  } else if (v.type == &ffi_type_sint64) {
    out << v.value.s64;
  } else if (v.type == &ffi_type_float) {
    out << v.value.f;
  } else if (v.type == &ffi_type_double) {
    out << v.value.d;
  } else if (v.type == &ffi_type_pointer) {
    out << v.value.ptr;
  }
  out << "\n$";
  return out;
}

class FFIStack {
 public:
  void push(uint8_t v) {
    stack_.push_back(Value{&ffi_type_uint8, {.u8 = v}});
  }
  void push(uint16_t v) {
    stack_.push_back(Value{&ffi_type_uint16, {.u16 = v}});
  }
  void push(uint32_t v) {
    stack_.push_back(Value{&ffi_type_uint32, {.u32 = v}});
  }
  void push(uint64_t v) {
    stack_.push_back(Value{&ffi_type_uint64, {.u64 = v}});
  }
  void push(int8_t v) {
    stack_.push_back(Value{&ffi_type_sint8, {.s8 = v}});
  }
  void push(int16_t v) {
    stack_.push_back(Value{&ffi_type_sint16, {.s16 = v}});
  }
  void push(int32_t v) {
    stack_.push_back(Value{&ffi_type_sint32, {.s32 = v}});
  }
  void push(int64_t v) {
    stack_.push_back(Value{&ffi_type_sint64, {.s64 = v}});
  }
  void push(double v) {
    stack_.push_back(Value{&ffi_type_double, {.d = v}});
  }
  void push(float v) {
    stack_.push_back(Value{&ffi_type_float, {.f = v}});
  }
  void push(void *v) {
    stack_.push_back(Value{&ffi_type_pointer, {.ptr = v}});
  }
  void push(Value &v) { stack_.push_back(v); }

  Value pop() {
    Value v = stack_.back();
    stack_.pop_back();
    return v;
  }

  Value peek() { return stack_.back(); }

  Value &operator[](int i) { return stack_[stack_.size() - i - 1]; }

  void dup() {
    stack_.push_back(stack_.back());
  }

  size_t size() {
    return stack_.size();
  }

 private:
  std::vector<Value> stack_;
};

class Machine {
 public:
  Machine(std::ostream &out) : out_{out} {};
  ~Machine() {
    for (auto &i : cifs_) {
      delete i->arg_types;
      delete i;
    }
    for (auto &i : libs_) {
      if (i) dlclose(i);
    }
  };

  FFIStack stack;

  void pop() { out_ << stack.pop(); }

  void peek() { out_ << stack.peek(); }

  void dlopen() {
    const char *name = static_cast<const char *>(stack.pop().value.ptr);
    void *handle = ::dlopen(name, RTLD_LAZY);
    stack.push(handle);
    libs_.push_back(handle);
  }

  void dlsym() {
    const char *name = static_cast<const char *>(stack.pop().value.ptr);
    void *handle = stack.pop().value.ptr;
    void *ptr = ::dlsym(handle, name);
    stack.push(ptr);
  }

  void cif() {
    ffi_cif *cif = new ffi_cif;
    uint32_t nargs = stack.pop().value.u32;
    ffi_type *rtype = stack.pop().type;
    ffi_type **types = new ffi_type*[nargs];
    for (uint32_t i = 0; i < nargs; i++) {
      types[i] = stack.pop().type;
    }
    ffi_prep_cif(cif, FFI_DEFAULT_ABI, nargs, rtype, types);
    stack.push(cif);
    cifs_.push_back(cif);
  }

  void call() {
    void (*function)() = reinterpret_cast<void (*)()>(stack.pop().value.ptr);
    ffi_cif *cif = static_cast<ffi_cif *>(stack.pop().value.ptr);
    int nargs = cif->nargs;
    void *args[nargs];
    Value result {cif->rtype, {0}};
    for (int i = 0; i < nargs; i++) {
      args[i] = &stack[i].value;
    }
    ffi_call(cif, function, &result.value, args);
    for (int i = 0; i < nargs; i++) {
      stack.pop();
    }
    stack.push(result);
  }

  void strlen() {
    char *str = static_cast<char *>(stack.peek().value.ptr);
    uint32_t size = std::strlen(str);
    stack.push(size);
  }

  void dump() {
    uint32_t size = stack.pop().value.u32;
    char *data = static_cast<char *>(stack.peek().value.ptr);
    out_.write(data, size);
  }

  void free() { delete static_cast<char *>(stack.pop().value.ptr); }

  void size() {
    uint32_t size = stack.size();
    stack.push(size);
  }

 private:
  std::ostream &out_;
  std::vector<ffi_cif *> cifs_;
  std::vector<void *> libs_;
};

class Reader {
 public:
  Reader(Machine &vm, std::istream &in) : vm_{vm}, in_{in} {};

  void read_uint8() {
    uint8_t i;
    in_ >> i;
    vm_.stack.push(i);
  }
  void read_uint16() {
    uint16_t i;
    in_ >> i;
    vm_.stack.push(i);
  }
  void read_uint32() {
    uint32_t i;
    in_ >> i;
    vm_.stack.push(i);
  }
  void read_uint64() {
    uint64_t i;
    in_ >> i;
    vm_.stack.push(i);
  }

  void read_sint8() {
    int8_t i;
    in_ >> i;
    vm_.stack.push(i);
  }
  void read_sint16() {
    int16_t i;
    in_ >> i;
    vm_.stack.push(i);
  }
  void read_sint32() {
    int32_t i;
    in_ >> i;
    vm_.stack.push(i);
  }
  void read_sint64() {
    int64_t i;
    in_ >> i;
    vm_.stack.push(i);
  }

  void read_float() {
    float f;
    in_ >> f;
    vm_.stack.push(f);
  }
  void read_double() {
    double d;
    in_ >> d;
    vm_.stack.push(d);
  }

  void read_pointer() {
    void *ptr = nullptr;
    in_ >> ptr;
    vm_.stack.push(ptr);
  }

  void read(uint32_t size) {
    char *buffer = new char[size];
    in_.read(buffer, size);
    vm_.stack.push(buffer);
  }

 private:
  Machine &vm_;
  std::istream &in_;
};

int main() {
  Machine vm{std::cout};
  Reader reader{vm, std::cin};

  while (!std::cin.eof()) {
    int command = std::cin.get();
    switch (command) {
      /* push signed integer */
      case 'i' + 0: /* i */
        reader.read_sint8();
        break;
      case 'i' + 1: /* j */
        reader.read_sint16();
        break;
      case 'i' + 2: /* k */
        reader.read_sint32();
        break;
      case 'i' + 3: /* l */
        reader.read_sint64();
        break;

      /* push unsigned integer */
      case 'u' + 0: /* u */
        reader.read_uint8();
        break;
      case 'u' + 1: /* v */
        reader.read_uint16();
        break;
      case 'u' + 2: /* w */
        reader.read_uint32();
        break;
      case 'u' + 3: /* x */
        reader.read_uint64();
        break;

      /* push float */
      case 'f':
        reader.read_float();
        break;
      case 'd':
        reader.read_double();
        break;

      /* push pointer */
      case 'p':
        reader.read_pointer();
        break;

      /* peek */
      case 'e':
        vm.peek();
        break;

      /* pop */
      case 'o':
        vm.pop();
        break;

      /* call */
      case 'c':
        vm.call();
        break;

      /* call */
      case 'C':
        vm.cif();
        break;

      /* "malloc" */
      case 'M':
        reader.read(vm.stack.pop().value.u32);
        break;

      /* free */
      case 'F':
        vm.free();
        break;

      /* push NULL */
      case 'N':
        vm.stack.push(nullptr);
        break;

      /* dl calls */
      case 'O':
        vm.dlopen();
        break;
      case 'S':
        vm.dlsym();
        break;

      /* strlen */
      case 'L':
        vm.strlen();
        break;

      /* dump */
      case 'D':
        vm.dump();
        break;

      /* duplicate top value */
      case '!':
        vm.stack.dup();
        break;

      /* get stack size */
      case '?':
        vm.size();
        break;

      /* no-op */
      case ' ':
      case '\n':
      case '\r':
      case -1:
        break;

      default:
        std::cerr << "invalid op: " << static_cast<char>(command) << std::endl;
        break;
    }
    std::cout.flush();
  }

  std::cout << std::endl;
  return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm.h"
#include "SkCanvas.h"
#include "SkGraphics.h"
#include "SkTypeface.h"

// GM to stress the GPU font cache

const char* gFamilyNames[] = {
    "sans-serif", "serif", "monospace"
};

const SkTypeface::Style gStyles[] = {
    SkTypeface::kNormal, SkTypeface::kItalic
};

const int gTextSizes[] = {
    12, 14, 16, 18, 20, 22, 24, 26, 28, 30
};

#define TYPEFACE_COUNT (SK_ARRAY_COUNT(gFamilyNames)*SK_ARRAY_COUNT(gStyles))

static SkScalar draw_string(SkCanvas* canvas, const SkString& text, SkScalar x,
                           SkScalar y, const SkPaint& paint) {
    canvas->drawText(text.c_str(), text.size(), x, y, paint);
    return x + paint.measureText(text.c_str(), text.size());
}

class FontCacheGM : public skiagm::GM {
public:
    FontCacheGM() {
        fName.set("fontcache");
    }

    virtual ~FontCacheGM() {
        for (size_t i = 0; i < TYPEFACE_COUNT; ++i) {
            SkSafeUnref(fTypefaces[i]);
        }
    }

protected:
    virtual SkString onShortName() SK_OVERRIDE {
        return fName;
    }

    virtual SkISize onISize() SK_OVERRIDE {
        return SkISize::Make(640, 320);
    }

    virtual void onOnceBeforeDraw() SK_OVERRIDE {
        int typefaceCount = 0;
        for (size_t i = 0; i < SK_ARRAY_COUNT(gFamilyNames); ++i) {
            for (size_t j = 0; j < SK_ARRAY_COUNT(gStyles); ++j) {
                fTypefaces[typefaceCount++] = SkTypeface::CreateFromName(gFamilyNames[i],
                                                                          gStyles[j]);
            }
        }
    }

    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
        SkScalar y = 32;
        SkPaint paint;
        paint.setAntiAlias(true);
        paint.setLCDRenderText(true);
        paint.setSubpixelText(true);

        SkString text("Ham");

        // draw some initial text to partially fill the GPU cache
        for (size_t i = 0; i < 2; ++i) {
            paint.setTypeface(fTypefaces[i]);
            SkScalar x = 20;

            for (size_t j = 0; j < SK_ARRAY_COUNT(gTextSizes); ++j) {
                paint.setTextSize(gTextSizes[j]);
                x = draw_string(canvas, text, x, y, paint) + 19;
            }
            y += 32;
        }

        // force a flush
        canvas->flush();

        // draw again, and more to overflow the cache
        for (size_t i = 0; i < TYPEFACE_COUNT; ++i) {
            paint.setTypeface(fTypefaces[i]);
            SkScalar x = 20;

            for (size_t j = 0; j < SK_ARRAY_COUNT(gTextSizes); ++j) {
                paint.setTextSize(gTextSizes[j]);
                x = draw_string(canvas, text, x, y, paint) + 19;
            }
            y += 32;
        }

    }

    virtual uint32_t onGetFlags() const SK_OVERRIDE {
        // this GM is meant only for the GPU
        return kGPUOnly_Flag;
    }

private:
    SkTypeface* fTypefaces[TYPEFACE_COUNT];
    SkString fName;
    typedef GM INHERITED;
};

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

DEF_GM( return SkNEW(FontCacheGM); )

<commit_msg>Fix font cache GM on Windows<commit_after>/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm.h"
#include "SkCanvas.h"
#include "SkGraphics.h"
#include "SkTypeface.h"

// GM to stress the GPU font cache

const char* gFamilyNames[] = {
    "sans-serif", "serif", "monospace"
};

const SkTypeface::Style gStyles[] = {
    SkTypeface::kNormal, SkTypeface::kItalic
};

const SkScalar gTextSizes[] = {
    12, 14, 16, 18, 20, 22, 24, 26, 28, 30
};

#define TYPEFACE_COUNT (SK_ARRAY_COUNT(gFamilyNames)*SK_ARRAY_COUNT(gStyles))

static SkScalar draw_string(SkCanvas* canvas, const SkString& text, SkScalar x,
                           SkScalar y, const SkPaint& paint) {
    canvas->drawText(text.c_str(), text.size(), x, y, paint);
    return x + paint.measureText(text.c_str(), text.size());
}

class FontCacheGM : public skiagm::GM {
public:
    FontCacheGM() {
        fName.set("fontcache");
    }

    virtual ~FontCacheGM() {
        for (size_t i = 0; i < TYPEFACE_COUNT; ++i) {
            SkSafeUnref(fTypefaces[i]);
        }
    }

protected:
    virtual SkString onShortName() SK_OVERRIDE {
        return fName;
    }

    virtual SkISize onISize() SK_OVERRIDE {
        return SkISize::Make(640, 320);
    }

    virtual void onOnceBeforeDraw() SK_OVERRIDE {
        int typefaceCount = 0;
        for (size_t i = 0; i < SK_ARRAY_COUNT(gFamilyNames); ++i) {
            for (size_t j = 0; j < SK_ARRAY_COUNT(gStyles); ++j) {
                fTypefaces[typefaceCount++] = SkTypeface::CreateFromName(gFamilyNames[i],
                                                                          gStyles[j]);
            }
        }
    }

    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
        SkScalar y = 32;
        SkPaint paint;
        paint.setAntiAlias(true);
        paint.setLCDRenderText(true);
        paint.setSubpixelText(true);

        SkString text("Ham");

        // draw some initial text to partially fill the GPU cache
        for (size_t i = 0; i < 2; ++i) {
            paint.setTypeface(fTypefaces[i]);
            SkScalar x = 20;

            for (size_t j = 0; j < SK_ARRAY_COUNT(gTextSizes); ++j) {
                paint.setTextSize(gTextSizes[j]);
                x = draw_string(canvas, text, x, y, paint) + 19;
            }
            y += 32;
        }

        // force a flush
        canvas->flush();

        // draw again, and more to overflow the cache
        for (size_t i = 0; i < TYPEFACE_COUNT; ++i) {
            paint.setTypeface(fTypefaces[i]);
            SkScalar x = 20;

            for (size_t j = 0; j < SK_ARRAY_COUNT(gTextSizes); ++j) {
                paint.setTextSize(gTextSizes[j]);
                x = draw_string(canvas, text, x, y, paint) + 19;
            }
            y += 32;
        }

    }

    virtual uint32_t onGetFlags() const SK_OVERRIDE {
        // this GM is meant only for the GPU
        return kGPUOnly_Flag;
    }

private:
    SkTypeface* fTypefaces[TYPEFACE_COUNT];
    SkString fName;
    typedef GM INHERITED;
};

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

DEF_GM( return SkNEW(FontCacheGM); )

<|endoftext|>