<commit_before>#pragma once

#include <iostream>
#include <fstream>
#include <cstring>
#include <vector>
#include <queue>

using namespace std;

class const_string
{
	const char* _M_str;
public:
	explicit const_string(const char* _str): _M_str(_str){}
	~const_string(){}

	const char* str() const
	{return this->_M_str;}

	bool operator==(const const_string& _cstr)
	{return this==&_cstr;}

	bool operator!=(const const_string& _cstr)
	{return this!=&_cstr;}

	template<class ostream_type>
	friend ostream_type& operator<<(ostream_type& os, const const_string& _cstr)
	{return os << _cstr._M_str;}

	operator const char*() const
	{return this->_M_str;}
};

namespace span
{
	const const_string
	preprocessor(""),
	comment(""),
	string(""),
	character(""),
	special_character(""),
	number(""),
	keyword(""),
	type(""),
	function(""),
	operators(""),
	true_false(""),
	end("");
}

// main.cpp
extern const bool is_name[], is_true_name[];

inline string safe_character(char _c)
{
	if(_c=='<') return "&lt";
	if(_c=='>') return "&gt";
	if(_c=='&') return "&amp";
	return string(&_c, 1);
}

inline string safe_string(const string& str)
{
	string ret;
	for(string::const_iterator i=str.begin(); i!=str.end(); ++i)
		ret+=safe_character(*i);
return ret;
}

// coloring.cpp
namespace coloring
{
	void init();
	string synax_highlight(const string& code);
	void color_code(const string& code, ostream& output);
}

// aho.cpp
class aho
{
	class class_trie
	{
	public:
		struct node
		{
			int E[256], fail, long_sh_pat, pattern_id; // fail pointer, max shorter pattern, pattern id
			bool is_pattern; // is pattern end in this vertex
			unsigned char character; // this node character
			node(unsigned char letter=0): is_pattern(false), character(letter)
			{
				for(int i=0; i<256; ++i)
					E[i]=0;
			}
			~node(){}
		};

		vector<node> graph;

		class_trie(): graph(1) // add root
		{
			this->graph.front().fail=this->graph.front().long_sh_pat=0; // max shorter pattern isn't exist
		}

		void swap(class_trie& _t)
		{
			this->graph.swap(_t.graph);
		}

		int add_word(const string& word, int id);
		void add_fails(); // and the longest shorter patterns, based on BFS algorithm
	} trie;

	vector<vector<unsigned>* > fin; // finding patterns

public:
	vector<vector<unsigned>* >::size_type size()
	{return this->fin.size();}

	vector<unsigned>& operator[](vector<vector<unsigned>* >::size_type n)
	{return *this->fin[n];}

	const vector<unsigned>& operator[](vector<vector<unsigned>* >::size_type n) const
	{return *this->fin[n];}

	void swap(aho& _a)
	{
		this->trie.swap(_a.trie);
		this->fin.swap(_a.fin);
	}

	void find(const vector<string>& patterns, const string& text);
};

class special_aho
{
	class class_trie
	{
	public:
		struct node
		{
			int E[256], fail, long_sh_pat, pattern_id; // fail pointer, max shorter pattern, pattern id
			bool is_pattern; // is pattern end in this vertex
			// unsigned char color; // highlight color
			unsigned char character; // this node character
			node(unsigned char letter=0): is_pattern(false), character(letter)
			{
				for(int i=0; i<256; ++i)
					E[i]=0;
			}
			~node(){}
		};

		vector<node> graph;

		class_trie(): graph(1) // add root
		{
			this->graph.front().fail=this->graph.front().long_sh_pat=0; // max shorter pattern isn't exist
		}

		void swap(class_trie& _t)
		{
			this->graph.swap(_t.graph);
		}

		int add_word(const string& word, int id);
		void add_fails(); // and the longest shorter patterns, based on BFS algorithm
	} trie;

	vector<pair<string, const_string> > patterns;
	vector<int> fin; // finding patterns

public:
	vector<int>::size_type size()
	{return this->fin.size();}

	int& operator[](vector<int>::size_type n)
	{return this->fin[n];}

	const int& operator[](vector<int>::size_type n) const
	{return this->fin[n];}

	void swap(special_aho& _a)
	{
		this->trie.swap(_a.trie);
		this->fin.swap(_a.fin);
	}

	const pair<string, const_string>& pattern(vector<pair<string, const_string> >::size_type n) const
	{return this->patterns[n];}

	void set_patterns(const vector<pair<string, const_string> >& new_patterns);

	void find(const string& text);
};<commit_msg>Removed potential bug<commit_after>#pragma once

#include <iostream>
#include <fstream>
#include <cstring>
#include <vector>
#include <queue>

using namespace std;

class const_string
{
	char* _M_str;
public:
	explicit const_string(const char* _str): _M_str(new char[strlen(_str)+1])
	{
		memcpy(this->_M_str, _str, strlen(_str)+1);
	}
	~const_string(){}

	const char* str() const
	{return this->_M_str;}

	bool operator==(const const_string& _cstr)
	{return this==&_cstr;}

	bool operator!=(const const_string& _cstr)
	{return this!=&_cstr;}

	template<class ostream_type>
	friend ostream_type& operator<<(ostream_type& os, const const_string& _cstr)
	{return os << _cstr._M_str;}

	operator const char*() const
	{return this->_M_str;}
};

namespace span
{
	const const_string
	preprocessor(""),
	comment(""),
	string(""),
	character(""),
	special_character(""),
	number(""),
	keyword(""),
	type(""),
	function(""),
	operators(""),
	true_false(""),
	end("");
}

// main.cpp
extern const bool is_name[], is_true_name[];

inline string safe_character(char _c)
{
	if(_c=='<') return "&lt";
	if(_c=='>') return "&gt";
	if(_c=='&') return "&amp";
	return string(&_c, 1);
}

inline string safe_string(const string& str)
{
	string ret;
	for(string::const_iterator i=str.begin(); i!=str.end(); ++i)
		ret+=safe_character(*i);
return ret;
}

// coloring.cpp
namespace coloring
{
	void init();
	string synax_highlight(const string& code);
	void color_code(const string& code, ostream& output);
}

// aho.cpp
class aho
{
	class class_trie
	{
	public:
		struct node
		{
			int E[256], fail, long_sh_pat, pattern_id; // fail pointer, max shorter pattern, pattern id
			bool is_pattern; // is pattern end in this vertex
			unsigned char character; // this node character
			node(unsigned char letter=0): is_pattern(false), character(letter)
			{
				for(int i=0; i<256; ++i)
					E[i]=0;
			}
			~node(){}
		};

		vector<node> graph;

		class_trie(): graph(1) // add root
		{
			this->graph.front().fail=this->graph.front().long_sh_pat=0; // max shorter pattern isn't exist
		}

		void swap(class_trie& _t)
		{
			this->graph.swap(_t.graph);
		}

		int add_word(const string& word, int id);
		void add_fails(); // and the longest shorter patterns, based on BFS algorithm
	} trie;

	vector<vector<unsigned>* > fin; // finding patterns

public:
	vector<vector<unsigned>* >::size_type size()
	{return this->fin.size();}

	vector<unsigned>& operator[](vector<vector<unsigned>* >::size_type n)
	{return *this->fin[n];}

	const vector<unsigned>& operator[](vector<vector<unsigned>* >::size_type n) const
	{return *this->fin[n];}

	void swap(aho& _a)
	{
		this->trie.swap(_a.trie);
		this->fin.swap(_a.fin);
	}

	void find(const vector<string>& patterns, const string& text);
};

class special_aho
{
	class class_trie
	{
	public:
		struct node
		{
			int E[256], fail, long_sh_pat, pattern_id; // fail pointer, max shorter pattern, pattern id
			bool is_pattern; // is pattern end in this vertex
			// unsigned char color; // highlight color
			unsigned char character; // this node character
			node(unsigned char letter=0): is_pattern(false), character(letter)
			{
				for(int i=0; i<256; ++i)
					E[i]=0;
			}
			~node(){}
		};

		vector<node> graph;

		class_trie(): graph(1) // add root
		{
			this->graph.front().fail=this->graph.front().long_sh_pat=0; // max shorter pattern isn't exist
		}

		void swap(class_trie& _t)
		{
			this->graph.swap(_t.graph);
		}

		int add_word(const string& word, int id);
		void add_fails(); // and the longest shorter patterns, based on BFS algorithm
	} trie;

	vector<pair<string, const_string> > patterns;
	vector<int> fin; // finding patterns

public:
	vector<int>::size_type size()
	{return this->fin.size();}

	int& operator[](vector<int>::size_type n)
	{return this->fin[n];}

	const int& operator[](vector<int>::size_type n) const
	{return this->fin[n];}

	void swap(special_aho& _a)
	{
		this->trie.swap(_a.trie);
		this->fin.swap(_a.fin);
	}

	const pair<string, const_string>& pattern(vector<pair<string, const_string> >::size_type n) const
	{return this->patterns[n];}

	void set_patterns(const vector<pair<string, const_string> >& new_patterns);

	void find(const string& text);
};<|endoftext|>


<commit_before>// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/

#ifndef TAOCPP_PEGTL_INCLUDE_INTERNAL_DUSELTRONIK_HPP
#define TAOCPP_PEGTL_INCLUDE_INTERNAL_DUSELTRONIK_HPP

#include "../apply_mode.hpp"
#include "../config.hpp"
#include "../rewind_mode.hpp"

#include "dusel_mode.hpp"

namespace tao
{
   namespace TAOCPP_PEGTL_NAMESPACE
   {
      namespace internal
      {
         template< typename Rule,
                   apply_mode A,
                   rewind_mode M,
                   template< typename... > class Action,
                   template< typename... > class Control,
                   dusel_mode = dusel_mode::NOTHING >
         struct duseltronik;

         template< typename Rule,
                   apply_mode A,
                   rewind_mode M,
                   template< typename... > class Action,
                   template< typename... > class Control >
         struct duseltronik< Rule, A, M, Action, Control, dusel_mode::NOTHING >
         {
            template< typename Input, typename... States >
            static auto match( Input& in, States&&... st ) -> decltype( Rule::template match< A, M, Action, Control >( in, st... ), true )
            {
               return Rule::template match< A, M, Action, Control >( in, st... );
            }

            // NOTE: The additional "int = 0" is a work-around for missing expression SFINAE in VS2015.

            template< typename Input, typename... States, int = 0 >
            static auto match( Input& in, States&&... ) -> decltype( Rule::match( in ), true )
            {
               return Rule::match( in );
            }
         };

         template< typename Rule,
                   apply_mode A,
                   rewind_mode M,
                   template< typename... > class Action,
                   template< typename... > class Control >
         struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL >
         {
            template< typename Input, typename... States >
            static bool match( Input& in, States&&... st )
            {
               Control< Rule >::start( const_cast< const Input& >( in ), st... );

               if( duseltronik< Rule, A, M, Action, Control, dusel_mode::NOTHING >::match( in, st... ) ) {
                  Control< Rule >::success( const_cast< const Input& >( in ), st... );
                  return true;
               }
               Control< Rule >::failure( const_cast< const Input& >( in ), st... );
               return false;
            }
         };

         template< typename Rule,
                   apply_mode A,
                   rewind_mode M,
                   template< typename... > class Action,
                   template< typename... > class Control >
         struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL_AND_APPLY_VOID >
         {
            template< typename Input, typename... States >
            static bool match( Input& in, States&&... st )
            {
               auto m = in.template mark< rewind_mode::REQUIRED >();

               if( duseltronik< Rule, A, rewind_mode::ACTIVE, Action, Control, dusel_mode::CONTROL >::match( in, st... ) ) {
                  Control< Rule >::template apply< Action >( m.iterator(), const_cast< const Input& >( in ), st... );
                  return m( true );
               }
               return false;
            }
         };

         template< typename Rule,
                   apply_mode A,
                   rewind_mode M,
                   template< typename... > class Action,
                   template< typename... > class Control >
         struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL_AND_APPLY0_VOID >
         {
            template< typename Input, typename... States >
            static bool match( Input& in, States&&... st )
            {
               if( duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL >::match( in, st... ) ) {
                  Control< Rule >::template apply0< Action >( const_cast< const Input& >( in ), st... );
                  return true;
               }
               return false;
            }
         };

         template< typename Rule,
                   apply_mode A,
                   rewind_mode M,
                   template< typename... > class Action,
                   template< typename... > class Control >
         struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL_AND_APPLY_BOOL >
         {
            template< typename Input, typename... States >
            static bool match( Input& in, States&&... st )
            {
               auto m = in.template mark< rewind_mode::REQUIRED >();

               if( duseltronik< Rule, A, rewind_mode::ACTIVE, Action, Control, dusel_mode::CONTROL >::match( in, st... ) ) {
                  return m( Control< Rule >::template apply< Action >( m.iterator(), const_cast< const Input& >( in ), st... ) );
               }
               return false;
            }
         };

         template< typename Rule,
                   apply_mode A,
                   rewind_mode M,
                   template< typename... > class Action,
                   template< typename... > class Control >
         struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL_AND_APPLY0_BOOL >
         {
            template< typename Input, typename... States >
            static bool match( Input& in, States&&... st )
            {
               auto m = in.template mark< rewind_mode::REQUIRED >();

               if( duseltronik< Rule, A, rewind_mode::ACTIVE, Action, Control, dusel_mode::CONTROL >::match( in, st... ) ) {
                  return m( Control< Rule >::template apply0< Action >( const_cast< const Input& >( in ), st... ) );
               }
               return false;
            }
         };

      }  // namespace internal

   }  // namespace TAOCPP_PEGTL_NAMESPACE

}  // namespace tao

#endif
<commit_msg>Fix order.<commit_after>// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/

#ifndef TAOCPP_PEGTL_INCLUDE_INTERNAL_DUSELTRONIK_HPP
#define TAOCPP_PEGTL_INCLUDE_INTERNAL_DUSELTRONIK_HPP

#include "../apply_mode.hpp"
#include "../config.hpp"
#include "../rewind_mode.hpp"

#include "dusel_mode.hpp"

namespace tao
{
   namespace TAOCPP_PEGTL_NAMESPACE
   {
      namespace internal
      {
         template< typename Rule,
                   apply_mode A,
                   rewind_mode M,
                   template< typename... > class Action,
                   template< typename... > class Control,
                   dusel_mode = dusel_mode::NOTHING >
         struct duseltronik;

         template< typename Rule,
                   apply_mode A,
                   rewind_mode M,
                   template< typename... > class Action,
                   template< typename... > class Control >
         struct duseltronik< Rule, A, M, Action, Control, dusel_mode::NOTHING >
         {
            template< typename Input, typename... States >
            static auto match( Input& in, States&&... st ) -> decltype( Rule::template match< A, M, Action, Control >( in, st... ), true )
            {
               return Rule::template match< A, M, Action, Control >( in, st... );
            }

            // NOTE: The additional "int = 0" is a work-around for missing expression SFINAE in VS2015.

            template< typename Input, typename... States, int = 0 >
            static auto match( Input& in, States&&... ) -> decltype( Rule::match( in ), true )
            {
               return Rule::match( in );
            }
         };

         template< typename Rule,
                   apply_mode A,
                   rewind_mode M,
                   template< typename... > class Action,
                   template< typename... > class Control >
         struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL >
         {
            template< typename Input, typename... States >
            static bool match( Input& in, States&&... st )
            {
               Control< Rule >::start( const_cast< const Input& >( in ), st... );

               if( duseltronik< Rule, A, M, Action, Control, dusel_mode::NOTHING >::match( in, st... ) ) {
                  Control< Rule >::success( const_cast< const Input& >( in ), st... );
                  return true;
               }
               Control< Rule >::failure( const_cast< const Input& >( in ), st... );
               return false;
            }
         };

         template< typename Rule,
                   apply_mode A,
                   rewind_mode M,
                   template< typename... > class Action,
                   template< typename... > class Control >
         struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL_AND_APPLY_VOID >
         {
            template< typename Input, typename... States >
            static bool match( Input& in, States&&... st )
            {
               auto m = in.template mark< rewind_mode::REQUIRED >();

               if( duseltronik< Rule, A, rewind_mode::ACTIVE, Action, Control, dusel_mode::CONTROL >::match( in, st... ) ) {
                  Control< Rule >::template apply< Action >( m.iterator(), const_cast< const Input& >( in ), st... );
                  return m( true );
               }
               return false;
            }
         };

         template< typename Rule,
                   apply_mode A,
                   rewind_mode M,
                   template< typename... > class Action,
                   template< typename... > class Control >
         struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL_AND_APPLY_BOOL >
         {
            template< typename Input, typename... States >
            static bool match( Input& in, States&&... st )
            {
               auto m = in.template mark< rewind_mode::REQUIRED >();

               if( duseltronik< Rule, A, rewind_mode::ACTIVE, Action, Control, dusel_mode::CONTROL >::match( in, st... ) ) {
                  return m( Control< Rule >::template apply< Action >( m.iterator(), const_cast< const Input& >( in ), st... ) );
               }
               return false;
            }
         };

         template< typename Rule,
                   apply_mode A,
                   rewind_mode M,
                   template< typename... > class Action,
                   template< typename... > class Control >
         struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL_AND_APPLY0_VOID >
         {
            template< typename Input, typename... States >
            static bool match( Input& in, States&&... st )
            {
               if( duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL >::match( in, st... ) ) {
                  Control< Rule >::template apply0< Action >( const_cast< const Input& >( in ), st... );
                  return true;
               }
               return false;
            }
         };

         template< typename Rule,
                   apply_mode A,
                   rewind_mode M,
                   template< typename... > class Action,
                   template< typename... > class Control >
         struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL_AND_APPLY0_BOOL >
         {
            template< typename Input, typename... States >
            static bool match( Input& in, States&&... st )
            {
               auto m = in.template mark< rewind_mode::REQUIRED >();

               if( duseltronik< Rule, A, rewind_mode::ACTIVE, Action, Control, dusel_mode::CONTROL >::match( in, st... ) ) {
                  return m( Control< Rule >::template apply0< Action >( const_cast< const Input& >( in ), st... ) );
               }
               return false;
            }
         };

      }  // namespace internal

   }  // namespace TAOCPP_PEGTL_NAMESPACE

}  // namespace tao

#endif
<|endoftext|>


<commit_before>/*
 * AscEmu Framework based on ArcEmu MMORPG Server
 * Copyright (C) 2014-2015 AscEmu Team <http://www.ascemu.org/>
 * Copyright (C) 2008-2012 ArcEmu Team <http://www.ArcEmu.org/>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "ConfigEnv.h"
ConfigMgr Config;

//#define _CONFIG_DEBUG

ConfigFile::ConfigFile()
{ }

ConfigFile::~ConfigFile()
{ }

void remove_spaces(std::string & str)
{
    while (str.size() && (*str.begin() == ' ' || *str.begin() == '\t'))
        str.erase(str.begin());
}

void remove_all_spaces(std::string & str)
{
    std::string::size_type off = str.find(" ");
    while (off != std::string::npos)
    {
        str.erase(off, 1);
        off = str.find(" ");
    }

    off = str.find("\t");
    while (off != std::string::npos)
    {
        str.erase(off, 1);
        off = str.find("\t");
    }
}

bool is_comment(std::string & str, bool* in_multiline_quote)
{
    std::string stemp = str;
    remove_spaces(stemp);
    if (stemp.length() == 0)
        return false;

    if (stemp[0] == '/')
    {
        if (stemp.length() < 2)
            return false;

        if (stemp[1] == '*')
        {
            *in_multiline_quote = true;
            return true;
        }
        else if (stemp[2] == '/')
        {
            return true;
        }
    }

    if (stemp[0] == '#')
        return true;

    return false;
}

void apply_setting(std::string & str, ConfigSetting & setting)
{
    setting.AsString = str;
    setting.AsInt = atoi(str.c_str());
    setting.AsBool = (setting.AsInt > 0);
    setting.AsFloat = (float)atof(str.c_str());

    // check for verbal yes/no answers
    if (str.length() > 1)
    {
        // this might be a yes/no?
        if (str.size() >= 3 && !strnicmp("yes", str.c_str(), 3))
        {
            setting.AsBool = true;
            setting.AsInt = 1;
        }
        else if (str.size() >= 2 && !strnicmp("no", str.c_str(), 2))
        {
            setting.AsBool = false;
            setting.AsInt = 0;
        }
    }
}

uint32 ahash(const char* str)
{
    register size_t len = strlen(str);
    register uint32 ret = 0;
    register size_t i = 0;
    for (; i < len; ++i)
        ret += 5 * ret + (tolower(str[i]));

    //printf("%s : %u\n", str, ret);
    return ret;
}

uint32 ahash(std::string & str)
{
    return ahash(str.c_str());
}

bool ConfigFile::SetSource(const char* file, bool ignorecase)
{
    // wipe any existing settings
    m_settings.clear();

    // open the file
    if (file != 0)
    {
        //the right mode in Windows is "rb" since '\n' is saved as 0x0D,0x0A but fopen(file,"r") reads these 2 chars
        //as only 1 char, so ftell(f) returns a higher value than the required by fread() to the file to buf.
#ifdef WIN32
        FILE* f = fopen(file, "rb");
#else
        FILE* f = fopen(file, "r");
#endif
        char* buf;
        int length;

        if (!f)
        {
            sLog.outError("Could not open %s.", file);
            return false;
        }

        // get the length of the file
        fseek(f, 0, SEEK_END);
        length = ftell(f);
        if (length < 0)
            return false;

        buf = new char[length + 1];
        fseek(f, 0, SEEK_SET);

        // read the file
        if (fread(buf, length, 1, f) != 1)
        {
            sLog.outError("Could not read %s.", file);
            // delete buf and close the file before returning
            delete[] buf;
            fclose(f);
            return false;
        }
        buf[length] = '\0';
        std::string buffer = std::string(buf);
        delete[] buf;

        // close the file, it is no longer needed
        fclose(f);

        // let's parse it
        std::string line;
        std::string::size_type end;
        std::string::size_type offset;
        bool in_multiline_comment = false;
        bool in_multiline_quote = false;
        bool in_block = false;
        std::string current_setting = "";
        std::string current_variable = "";
        std::string current_block = "";
        ConfigBlock current_block_map;
        ConfigSetting current_setting_struct;

        // oh god this is awful
        try
        {
            for (;;)
            {
                // grab a line
                end = buffer.find(EOL);
                if (end == std::string::npos)
                {
                    if (buffer.size() == 0)
                        break;
                    line = buffer;
                    buffer.clear();
                    goto parse;
                }

                line = buffer.substr(0, end);
                buffer.erase(0, end + EOL_SIZE);
                goto parse;

            parse:
                if (!line.size())
                    continue;

                // are we a comment?
                if (!in_multiline_comment && is_comment(line, &in_multiline_comment))
                {
                    // our line is a comment
                    if (!in_multiline_comment)
                    {
                        // the entire line is a comment, skip it
                        continue;
                    }
                }

                // handle our cases
                if (in_multiline_comment)
                {
                    // we need to find a "*/".
                    offset = line.find("*/", 0);

                    // skip this entire line, eh?
                    if (offset == std::string::npos)
                        continue;

                    // remove up to the end of the comment block
                    line.erase(0, offset + 2);
                    in_multiline_comment = false;
                }

                if (in_block)
                {
                    // handle settings across multiple lines
                    if (in_multiline_quote)
                    {
                        // attempt to find the end of the quote block
                        offset = line.find("\"");

                        if (offset == std::string::npos)
                        {
                            // append the whole line to the quote
                            current_setting += line;
                            current_setting += "\n";
                            continue;
                        }

                        // only append part of the line to the setting
                        current_setting.append(line.c_str(), offset + 1);
                        line.erase(0, offset + 1);

                        // append the setting to the config block
                        if (current_block == "" || current_variable == "")
                        {
                            sLog.outError("Quote without variable.");
                            return false;
                        }

                        // apply the setting
                        apply_setting(current_setting, current_setting_struct);

                        // the setting is done, append it to the current block
                        current_block_map[ahash(current_variable)] = current_setting_struct;
#ifdef _CONFIG_DEBUG
                        sLog.outDebug("Block: '%s', Setting: '%s', Value: '%s'", current_block.c_str(), current_variable.c_str(), current_setting_struct.AsString.c_str());
#endif
                        // no longer doing this setting, or in a quote
                        current_setting = "";
                        current_variable = "";
                        in_multiline_quote = false;
                    }

                    // remove any leading spaces
                    remove_spaces(line);

                    if (!line.size())
                        continue;

                    // our target is a *setting*. look for an '=' sign, this is our seperator
                    offset = line.find("=");
                    if (offset != std::string::npos)
                    {
                        ASSERT(current_variable == "");
                        current_variable = line.substr(0, offset);

                        // remove any spaces from the end of the setting
                        remove_all_spaces(current_variable);

                        // remove the directive *and* the = from the line
                        line.erase(0, offset + 1);
                    }

                    // look for the opening quote. this signifies the start of a setting
                    offset = line.find("\"");
                    if (offset != std::string::npos)
                    {
                        ASSERT(current_setting == "");
                        ASSERT(current_variable != "");

                        // try and find the ending quote
                        end = line.find("\"", offset + 1);
                        if (end != std::string::npos)
                        {
                            // the closing quote is on the same line, oh goody
                            current_setting = line.substr(offset + 1, end - offset - 1);

                            // erase up to the end
                            line.erase(0, end + 1);

                            // apply the setting
                            apply_setting(current_setting, current_setting_struct);

                            // the setting is done, append it to the current block
                            current_block_map[ahash(current_variable)] = current_setting_struct;

#ifdef _CONFIG_DEBUG
                            sLog.outDebug("Block: '%s', Setting: '%s', Value: '%s'", current_block.c_str(), current_variable.c_str(), current_setting_struct.AsString.c_str());
#endif
                            // no longer doing this setting, or in a quote
                            current_setting = "";
                            current_variable = "";
                            in_multiline_quote = false;

                            // attempt to grab more settings from the same line
                            goto parse;
                        }
                        else
                        {
                            // the closing quote is not on the same line. means we'll try and find it on the next
                            current_setting.append(line.c_str(), offset);

                            // skip to the next line. (after setting our condition first, of course :P
                            in_multiline_quote = true;
                            continue;
                        }
                    }

                    // are we at the end of the block yet?
                    offset = line.find(">");
                    if (offset != std::string::npos)
                    {
                        line.erase(0, offset + 1);

                        // freeeee!
                        in_block = false;

                        // assign this block to the main "big" map
                        m_settings[ahash(current_block)] = current_block_map;

                        // erase all data for this so it doesn't seep through
                        current_block_map.clear();
                        current_setting = "";
                        current_variable = "";
                        current_block = "";
                    }
                }
                else
                {
                    // we're not in a block. look for the start of one
                    offset = line.find("<");

                    if (offset != std::string::npos)
                    {
                        in_block = true;

                        // whee, a block! let's cut the string and re-parse
                        line.erase(0, offset + 1);

                        // find the name of the block first, though
                        offset = line.find(" ");
                        if (offset != std::string::npos)
                        {
                            current_block = line.substr(0, offset);
                            line.erase(0, offset + 1);
                        }
                        else
                        {
                            sLog.outError("Block without name.");
                            return false;
                        }

                        // skip back
                        goto parse;
                    }
                }
            }

        }
        catch (...)
        {
            sLog.outError("Exception in config parsing.");
            return false;
        }

        // handle any errors
        if (in_block)
        {
            sLog.outError("Unterminated block.");
            return false;
        }

        if (in_multiline_comment)
        {
            sLog.outError("Unterminated comment.");
            return false;
        }

        if (in_multiline_quote)
        {
            sLog.outError("Unterminated quote.");
            return false;
        }

        return true;
    }

    return false;
}

ConfigSetting* ConfigFile::GetSetting(const char* Block, const char* Setting)
{
    uint32 block_hash = ahash(Block);
    uint32 setting_hash = ahash(Setting);

    // find it in the big map
    std::map<uint32, ConfigBlock>::iterator itr = m_settings.find(block_hash);
    if (itr != m_settings.end())
    {
        ConfigBlock::iterator it2 = itr->second.find(setting_hash);
        if (it2 != itr->second.end())
            return &(it2->second);

        return 0;
    }

    return 0;
}

bool ConfigFile::GetString(const char* block, const char* name, std::string* value)
{
    ConfigSetting* Setting = GetSetting(block, name);
    if (Setting == 0)
        return false;

    *value = Setting->AsString;
    return true;
}

std::string ConfigFile::GetStringDefault(const char* block, const char* name, const char* def)
{
    std::string ret;
    return GetString(block, name, &ret) ? ret : def;
}

bool ConfigFile::GetBool(const char* block, const char* name, bool* value)
{
    ConfigSetting* Setting = GetSetting(block, name);
    if (Setting == 0)
        return false;

    *value = Setting->AsBool;
    return true;
}

bool ConfigFile::GetBoolDefault(const char* block, const char* name, const bool def /* = false */)
{
    bool val;
    return GetBool(block, name, &val) ? val : def;
}

bool ConfigFile::GetInt(const char* block, const char* name, int* value)
{
    ConfigSetting* Setting = GetSetting(block, name);
    if (Setting == 0)
        return false;

    *value = Setting->AsInt;
    return true;
}

bool ConfigFile::GetFloat(const char* block, const char* name, float* value)
{
    ConfigSetting* Setting = GetSetting(block, name);
    if (Setting == 0)
        return false;

    *value = Setting->AsFloat;
    return true;
}

int ConfigFile::GetIntDefault(const char* block, const char* name, const int def)
{
    int val;
    return GetInt(block, name, &val) ? val : def;
}

float ConfigFile::GetFloatDefault(const char* block, const char* name, const float def)
{
    float val;
    return (GetFloat(block, name, &val) ? val : def);
}

int ConfigFile::GetIntVA(const char* block, int def, const char* name, ...)
{
    va_list ap;
    va_start(ap, name);
    char str[150];
    vsnprintf(str, 150, name, ap);
    va_end(ap);
    int val;
    return GetInt(str, block, &val) ? val : def;
}

float ConfigFile::GetFloatVA(const char* block, float def, const char* name, ...)
{
    va_list ap;
    va_start(ap, name);
    char str[150];
    vsnprintf(str, 150, name, ap);
    va_end(ap);
    float val;
    return GetFloat(str, block, &val) ? val : def;
}

std::string ConfigFile::GetStringVA(const char* block, const char* def, const char* name, ...)
{
    va_list ap;
    va_start(ap, name);
    char str[150];
    vsnprintf(str, 150, name, ap);
    va_end(ap);

    return GetStringDefault(str, block, def);
}

bool ConfigFile::GetString(const char* block, char* buffer, const char* name, const char* def, uint32 len)
{
    std::string val = GetStringDefault(block, name, def);
    size_t blen = val.length();
    if (blen > len)
        blen = len;

    memcpy(buffer, val.c_str(), blen);
    buffer[blen] = 0;

    return true;
}

<commit_msg>Attemp to resolve CID53179<commit_after>/*
 * AscEmu Framework based on ArcEmu MMORPG Server
 * Copyright (C) 2014-2015 AscEmu Team <http://www.ascemu.org/>
 * Copyright (C) 2008-2012 ArcEmu Team <http://www.ArcEmu.org/>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "ConfigEnv.h"
ConfigMgr Config;

//#define _CONFIG_DEBUG

ConfigFile::ConfigFile()
{ }

ConfigFile::~ConfigFile()
{ }

void remove_spaces(std::string & str)
{
    while (str.size() && (*str.begin() == ' ' || *str.begin() == '\t'))
        str.erase(str.begin());
}

void remove_all_spaces(std::string & str)
{
    std::string::size_type off = str.find(" ");
    while (off != std::string::npos)
    {
        str.erase(off, 1);
        off = str.find(" ");
    }

    off = str.find("\t");
    while (off != std::string::npos)
    {
        str.erase(off, 1);
        off = str.find("\t");
    }
}

bool is_comment(std::string & str, bool* in_multiline_quote)
{
    std::string stemp = str;
    remove_spaces(stemp);
    if (stemp.length() == 0)
        return false;

    if (stemp[0] == '/')
    {
        if (stemp.length() < 2)
            return false;

        if (stemp[1] == '*')
        {
            *in_multiline_quote = true;
            return true;
        }
        else if (stemp[2] == '/')
        {
            return true;
        }
    }

    if (stemp[0] == '#')
        return true;

    return false;
}

void apply_setting(std::string & str, ConfigSetting & setting)
{
    setting.AsString = str;
    setting.AsInt = atoi(str.c_str());
    setting.AsBool = (setting.AsInt > 0);
    setting.AsFloat = (float)atof(str.c_str());

    // check for verbal yes/no answers
    if (str.length() > 1)
    {
        // this might be a yes/no?
        if (str.size() >= 3 && !strnicmp("yes", str.c_str(), 3))
        {
            setting.AsBool = true;
            setting.AsInt = 1;
        }
        else if (str.size() >= 2 && !strnicmp("no", str.c_str(), 2))
        {
            setting.AsBool = false;
            setting.AsInt = 0;
        }
    }
}

uint32 ahash(const char* str)
{
    register size_t len = strlen(str);
    register uint32 ret = 0;
    register size_t i = 0;
    for (; i < len; ++i)
        ret += 5 * ret + (tolower(str[i]));

    //printf("%s : %u\n", str, ret);
    return ret;
}

uint32 ahash(std::string & str)
{
    return ahash(str.c_str());
}

bool ConfigFile::SetSource(const char* file, bool ignorecase)
{
    // wipe any existing settings
    m_settings.clear();

    // open the file
    if (file != 0)
    {
        //the right mode in Windows is "rb" since '\n' is saved as 0x0D,0x0A but fopen(file,"r") reads these 2 chars
        //as only 1 char, so ftell(f) returns a higher value than the required by fread() to the file to buf.
#ifdef WIN32
        FILE* f = fopen(file, "rb");
#else
        FILE* f = fopen(file, "r");
#endif
        char* buf;
        uint32 length;

        if (!f)
        {
            sLog.outError("Could not open %s.", file);
            return false;
        }

        // get the length of the file
        fseek(f, 0, SEEK_END);

        if (ftell(f) <= 0)
            return false;
        else
            length = ftell(f);

        buf = new char[length + 1];
        fseek(f, 0, SEEK_SET);

        // read the file
        if (fread(buf, length, 1, f) != 1)
        {
            sLog.outError("Could not read %s.", file);
            // delete buf and close the file before returning
            delete[] buf;
            fclose(f);
            return false;
        }
        buf[length] = '\0';
        std::string buffer = std::string(buf);
        delete[] buf;

        // close the file, it is no longer needed
        fclose(f);

        // let's parse it
        std::string line;
        std::string::size_type end;
        std::string::size_type offset;
        bool in_multiline_comment = false;
        bool in_multiline_quote = false;
        bool in_block = false;
        std::string current_setting = "";
        std::string current_variable = "";
        std::string current_block = "";
        ConfigBlock current_block_map;
        ConfigSetting current_setting_struct;

        // oh god this is awful
        try
        {
            for (;;)
            {
                // grab a line
                end = buffer.find(EOL);
                if (end == std::string::npos)
                {
                    if (buffer.size() == 0)
                        break;
                    line = buffer;
                    buffer.clear();
                    goto parse;
                }

                line = buffer.substr(0, end);
                buffer.erase(0, end + EOL_SIZE);
                goto parse;

            parse:
                if (!line.size())
                    continue;

                // are we a comment?
                if (!in_multiline_comment && is_comment(line, &in_multiline_comment))
                {
                    // our line is a comment
                    if (!in_multiline_comment)
                    {
                        // the entire line is a comment, skip it
                        continue;
                    }
                }

                // handle our cases
                if (in_multiline_comment)
                {
                    // we need to find a "*/".
                    offset = line.find("*/", 0);

                    // skip this entire line, eh?
                    if (offset == std::string::npos)
                        continue;

                    // remove up to the end of the comment block
                    line.erase(0, offset + 2);
                    in_multiline_comment = false;
                }

                if (in_block)
                {
                    // handle settings across multiple lines
                    if (in_multiline_quote)
                    {
                        // attempt to find the end of the quote block
                        offset = line.find("\"");

                        if (offset == std::string::npos)
                        {
                            // append the whole line to the quote
                            current_setting += line;
                            current_setting += "\n";
                            continue;
                        }

                        // only append part of the line to the setting
                        current_setting.append(line.c_str(), offset + 1);
                        line.erase(0, offset + 1);

                        // append the setting to the config block
                        if (current_block == "" || current_variable == "")
                        {
                            sLog.outError("Quote without variable.");
                            return false;
                        }

                        // apply the setting
                        apply_setting(current_setting, current_setting_struct);

                        // the setting is done, append it to the current block
                        current_block_map[ahash(current_variable)] = current_setting_struct;
#ifdef _CONFIG_DEBUG
                        sLog.outDebug("Block: '%s', Setting: '%s', Value: '%s'", current_block.c_str(), current_variable.c_str(), current_setting_struct.AsString.c_str());
#endif
                        // no longer doing this setting, or in a quote
                        current_setting = "";
                        current_variable = "";
                        in_multiline_quote = false;
                    }

                    // remove any leading spaces
                    remove_spaces(line);

                    if (!line.size())
                        continue;

                    // our target is a *setting*. look for an '=' sign, this is our seperator
                    offset = line.find("=");
                    if (offset != std::string::npos)
                    {
                        ASSERT(current_variable == "");
                        current_variable = line.substr(0, offset);

                        // remove any spaces from the end of the setting
                        remove_all_spaces(current_variable);

                        // remove the directive *and* the = from the line
                        line.erase(0, offset + 1);
                    }

                    // look for the opening quote. this signifies the start of a setting
                    offset = line.find("\"");
                    if (offset != std::string::npos)
                    {
                        ASSERT(current_setting == "");
                        ASSERT(current_variable != "");

                        // try and find the ending quote
                        end = line.find("\"", offset + 1);
                        if (end != std::string::npos)
                        {
                            // the closing quote is on the same line, oh goody
                            current_setting = line.substr(offset + 1, end - offset - 1);

                            // erase up to the end
                            line.erase(0, end + 1);

                            // apply the setting
                            apply_setting(current_setting, current_setting_struct);

                            // the setting is done, append it to the current block
                            current_block_map[ahash(current_variable)] = current_setting_struct;

#ifdef _CONFIG_DEBUG
                            sLog.outDebug("Block: '%s', Setting: '%s', Value: '%s'", current_block.c_str(), current_variable.c_str(), current_setting_struct.AsString.c_str());
#endif
                            // no longer doing this setting, or in a quote
                            current_setting = "";
                            current_variable = "";
                            in_multiline_quote = false;

                            // attempt to grab more settings from the same line
                            goto parse;
                        }
                        else
                        {
                            // the closing quote is not on the same line. means we'll try and find it on the next
                            current_setting.append(line.c_str(), offset);

                            // skip to the next line. (after setting our condition first, of course :P
                            in_multiline_quote = true;
                            continue;
                        }
                    }

                    // are we at the end of the block yet?
                    offset = line.find(">");
                    if (offset != std::string::npos)
                    {
                        line.erase(0, offset + 1);

                        // freeeee!
                        in_block = false;

                        // assign this block to the main "big" map
                        m_settings[ahash(current_block)] = current_block_map;

                        // erase all data for this so it doesn't seep through
                        current_block_map.clear();
                        current_setting = "";
                        current_variable = "";
                        current_block = "";
                    }
                }
                else
                {
                    // we're not in a block. look for the start of one
                    offset = line.find("<");

                    if (offset != std::string::npos)
                    {
                        in_block = true;

                        // whee, a block! let's cut the string and re-parse
                        line.erase(0, offset + 1);

                        // find the name of the block first, though
                        offset = line.find(" ");
                        if (offset != std::string::npos)
                        {
                            current_block = line.substr(0, offset);
                            line.erase(0, offset + 1);
                        }
                        else
                        {
                            sLog.outError("Block without name.");
                            return false;
                        }

                        // skip back
                        goto parse;
                    }
                }
            }

        }
        catch (...)
        {
            sLog.outError("Exception in config parsing.");
            return false;
        }

        // handle any errors
        if (in_block)
        {
            sLog.outError("Unterminated block.");
            return false;
        }

        if (in_multiline_comment)
        {
            sLog.outError("Unterminated comment.");
            return false;
        }

        if (in_multiline_quote)
        {
            sLog.outError("Unterminated quote.");
            return false;
        }

        return true;
    }

    return false;
}

ConfigSetting* ConfigFile::GetSetting(const char* Block, const char* Setting)
{
    uint32 block_hash = ahash(Block);
    uint32 setting_hash = ahash(Setting);

    // find it in the big map
    std::map<uint32, ConfigBlock>::iterator itr = m_settings.find(block_hash);
    if (itr != m_settings.end())
    {
        ConfigBlock::iterator it2 = itr->second.find(setting_hash);
        if (it2 != itr->second.end())
            return &(it2->second);

        return 0;
    }

    return 0;
}

bool ConfigFile::GetString(const char* block, const char* name, std::string* value)
{
    ConfigSetting* Setting = GetSetting(block, name);
    if (Setting == 0)
        return false;

    *value = Setting->AsString;
    return true;
}

std::string ConfigFile::GetStringDefault(const char* block, const char* name, const char* def)
{
    std::string ret;
    return GetString(block, name, &ret) ? ret : def;
}

bool ConfigFile::GetBool(const char* block, const char* name, bool* value)
{
    ConfigSetting* Setting = GetSetting(block, name);
    if (Setting == 0)
        return false;

    *value = Setting->AsBool;
    return true;
}

bool ConfigFile::GetBoolDefault(const char* block, const char* name, const bool def /* = false */)
{
    bool val;
    return GetBool(block, name, &val) ? val : def;
}

bool ConfigFile::GetInt(const char* block, const char* name, int* value)
{
    ConfigSetting* Setting = GetSetting(block, name);
    if (Setting == 0)
        return false;

    *value = Setting->AsInt;
    return true;
}

bool ConfigFile::GetFloat(const char* block, const char* name, float* value)
{
    ConfigSetting* Setting = GetSetting(block, name);
    if (Setting == 0)
        return false;

    *value = Setting->AsFloat;
    return true;
}

int ConfigFile::GetIntDefault(const char* block, const char* name, const int def)
{
    int val;
    return GetInt(block, name, &val) ? val : def;
}

float ConfigFile::GetFloatDefault(const char* block, const char* name, const float def)
{
    float val;
    return (GetFloat(block, name, &val) ? val : def);
}

int ConfigFile::GetIntVA(const char* block, int def, const char* name, ...)
{
    va_list ap;
    va_start(ap, name);
    char str[150];
    vsnprintf(str, 150, name, ap);
    va_end(ap);
    int val;
    return GetInt(str, block, &val) ? val : def;
}

float ConfigFile::GetFloatVA(const char* block, float def, const char* name, ...)
{
    va_list ap;
    va_start(ap, name);
    char str[150];
    vsnprintf(str, 150, name, ap);
    va_end(ap);
    float val;
    return GetFloat(str, block, &val) ? val : def;
}

std::string ConfigFile::GetStringVA(const char* block, const char* def, const char* name, ...)
{
    va_list ap;
    va_start(ap, name);
    char str[150];
    vsnprintf(str, 150, name, ap);
    va_end(ap);

    return GetStringDefault(str, block, def);
}

bool ConfigFile::GetString(const char* block, char* buffer, const char* name, const char* def, uint32 len)
{
    std::string val = GetStringDefault(block, name, def);
    size_t blen = val.length();
    if (blen > len)
        blen = len;

    memcpy(buffer, val.c_str(), blen);
    buffer[blen] = 0;

    return true;
}

<|endoftext|>


<commit_before>#include "json-to-value.hh"

#include <cstring>

namespace nix {

static void skipWhitespace(const char * & s)
{
    while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') s++;
}

static string parseJSONString(const char * & s)
{
    string res;
    if (*s++ != '"') throw JSONParseError("expected JSON string");
    while (*s != '"') {
        if (!*s) throw JSONParseError("got end-of-string in JSON string");
        if (*s == '\\') {
            s++;
            if (*s == '"') res += '"';
            else if (*s == '\\') res += '\\';
            else if (*s == '/') res += '/';
            else if (*s == '/') res += '/';
            else if (*s == 'b') res += '\b';
            else if (*s == 'f') res += '\f';
            else if (*s == 'n') res += '\n';
            else if (*s == 'r') res += '\r';
            else if (*s == 't') res += '\t';
            else if (*s == 'u') throw JSONParseError("\\u characters in JSON strings are currently not supported");
            else throw JSONParseError("invalid escaped character in JSON string");
            s++;
        } else
            res += *s++;
    }
    s++;
    return res;
}

static void parseJSON(EvalState & state, const char * & s, Value & v)
{
    skipWhitespace(s);

    if (!*s) throw JSONParseError("expected JSON value");

    if (*s == '[') {
        s++;
        ValueVector values;
        values.reserve(128);
        skipWhitespace(s);
        while (1) {
            if (values.empty() && *s == ']') break;
            Value * v2 = state.allocValue();
            parseJSON(state, s, *v2);
            values.push_back(v2);
            skipWhitespace(s);
            if (*s == ']') break;
            if (*s != ',') throw JSONParseError("expected ',' or ']' after JSON array element");
            s++;
        }
        s++;
        state.mkList(v, values.size());
        for (size_t n = 0; n < values.size(); ++n)
            v.listElems()[n] = values[n];
    }

    else if (*s == '{') {
        s++;
        ValueMap attrs;
        while (1) {
            skipWhitespace(s);
            if (attrs.empty() && *s == '}') break;
            string name = parseJSONString(s);
            skipWhitespace(s);
            if (*s != ':') throw JSONParseError("expected ':' in JSON object");
            s++;
            Value * v2 = state.allocValue();
            parseJSON(state, s, *v2);
            attrs[state.symbols.create(name)] = v2;
            skipWhitespace(s);
            if (*s == '}') break;
            if (*s != ',') throw JSONParseError("expected ',' or '}' after JSON member");
            s++;
        }
        state.mkAttrs(v, attrs.size());
        for (auto & i : attrs)
            v.attrs->push_back(Attr(i.first, i.second));
        v.attrs->sort();
        s++;
    }

    else if (*s == '"') {
        mkString(v, parseJSONString(s));
    }

    else if (isdigit(*s) || *s == '-' || *s == '.' ) {
        // Buffer into a string first, then use built-in C++ conversions
        std::string tmp_number;
        ValueType number_type = tInt;

        while (isdigit(*s) || *s == '-' || *s == '.' || *s == 'e' || *s == 'E') {
            if (*s == '.' || *s == 'e' || *s == 'E')
                number_type = tFloat;
            tmp_number += *s++;
        }

        try {
            if (number_type == tFloat)
                mkFloat(v, stod(tmp_number));
            else
                mkInt(v, stoi(tmp_number));
        } catch (std::invalid_argument e) {
            throw JSONParseError("invalid JSON number");
        } catch (std::out_of_range e) {
            throw JSONParseError("out-of-range JSON number");
        }
    }

    else if (strncmp(s, "true", 4) == 0) {
        s += 4;
        mkBool(v, true);
    }

    else if (strncmp(s, "false", 5) == 0) {
        s += 5;
        mkBool(v, false);
    }

    else if (strncmp(s, "null", 4) == 0) {
        s += 4;
        mkNull(v);
    }

    else throw JSONParseError("unrecognised JSON value");
}

void parseJSON(EvalState & state, const string & s_, Value & v)
{
    const char * s = s_.c_str();
    parseJSON(state, s, v);
    skipWhitespace(s);
    if (*s) throw JSONParseError(format("expected end-of-string while parsing JSON value: %1%") % s);
}

}
<commit_msg>json-to-value: Use strtol instead of strtoi<commit_after>#include "json-to-value.hh"

#include <cstring>

namespace nix {

static void skipWhitespace(const char * & s)
{
    while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') s++;
}

static string parseJSONString(const char * & s)
{
    string res;
    if (*s++ != '"') throw JSONParseError("expected JSON string");
    while (*s != '"') {
        if (!*s) throw JSONParseError("got end-of-string in JSON string");
        if (*s == '\\') {
            s++;
            if (*s == '"') res += '"';
            else if (*s == '\\') res += '\\';
            else if (*s == '/') res += '/';
            else if (*s == '/') res += '/';
            else if (*s == 'b') res += '\b';
            else if (*s == 'f') res += '\f';
            else if (*s == 'n') res += '\n';
            else if (*s == 'r') res += '\r';
            else if (*s == 't') res += '\t';
            else if (*s == 'u') throw JSONParseError("\\u characters in JSON strings are currently not supported");
            else throw JSONParseError("invalid escaped character in JSON string");
            s++;
        } else
            res += *s++;
    }
    s++;
    return res;
}

static void parseJSON(EvalState & state, const char * & s, Value & v)
{
    skipWhitespace(s);

    if (!*s) throw JSONParseError("expected JSON value");

    if (*s == '[') {
        s++;
        ValueVector values;
        values.reserve(128);
        skipWhitespace(s);
        while (1) {
            if (values.empty() && *s == ']') break;
            Value * v2 = state.allocValue();
            parseJSON(state, s, *v2);
            values.push_back(v2);
            skipWhitespace(s);
            if (*s == ']') break;
            if (*s != ',') throw JSONParseError("expected ',' or ']' after JSON array element");
            s++;
        }
        s++;
        state.mkList(v, values.size());
        for (size_t n = 0; n < values.size(); ++n)
            v.listElems()[n] = values[n];
    }

    else if (*s == '{') {
        s++;
        ValueMap attrs;
        while (1) {
            skipWhitespace(s);
            if (attrs.empty() && *s == '}') break;
            string name = parseJSONString(s);
            skipWhitespace(s);
            if (*s != ':') throw JSONParseError("expected ':' in JSON object");
            s++;
            Value * v2 = state.allocValue();
            parseJSON(state, s, *v2);
            attrs[state.symbols.create(name)] = v2;
            skipWhitespace(s);
            if (*s == '}') break;
            if (*s != ',') throw JSONParseError("expected ',' or '}' after JSON member");
            s++;
        }
        state.mkAttrs(v, attrs.size());
        for (auto & i : attrs)
            v.attrs->push_back(Attr(i.first, i.second));
        v.attrs->sort();
        s++;
    }

    else if (*s == '"') {
        mkString(v, parseJSONString(s));
    }

    else if (isdigit(*s) || *s == '-' || *s == '.' ) {
        // Buffer into a string first, then use built-in C++ conversions
        std::string tmp_number;
        ValueType number_type = tInt;

        while (isdigit(*s) || *s == '-' || *s == '.' || *s == 'e' || *s == 'E') {
            if (*s == '.' || *s == 'e' || *s == 'E')
                number_type = tFloat;
            tmp_number += *s++;
        }

        try {
            if (number_type == tFloat)
                mkFloat(v, stod(tmp_number));
            else
                mkInt(v, stol(tmp_number));
        } catch (std::invalid_argument e) {
            throw JSONParseError("invalid JSON number");
        } catch (std::out_of_range e) {
            throw JSONParseError("out-of-range JSON number");
        }
    }

    else if (strncmp(s, "true", 4) == 0) {
        s += 4;
        mkBool(v, true);
    }

    else if (strncmp(s, "false", 5) == 0) {
        s += 5;
        mkBool(v, false);
    }

    else if (strncmp(s, "null", 4) == 0) {
        s += 4;
        mkNull(v);
    }

    else throw JSONParseError("unrecognised JSON value");
}

void parseJSON(EvalState & state, const string & s_, Value & v)
{
    const char * s = s_.c_str();
    parseJSON(state, s, v);
    skipWhitespace(s);
    if (*s) throw JSONParseError(format("expected end-of-string while parsing JSON value: %1%") % s);
}

}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/renderer/render_widget_fullscreen_pepper.h"

#include <vector>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
#include "content/common/gpu/client/gpu_channel_host.h"
#include "content/common/view_messages.h"
#include "content/public/common/content_switches.h"
#include "content/renderer/gpu/render_widget_compositor.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/render_thread_impl.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/public/platform/WebCanvas.h"
#include "third_party/WebKit/public/platform/WebCursorInfo.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
#include "third_party/WebKit/public/platform/WebLayer.h"
#include "third_party/WebKit/public/platform/WebSize.h"
#include "third_party/WebKit/public/web/WebWidget.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gl/gpu_preference.h"

using blink::WebCanvas;
using blink::WebCompositionUnderline;
using blink::WebCursorInfo;
using blink::WebGestureEvent;
using blink::WebInputEvent;
using blink::WebMouseEvent;
using blink::WebMouseWheelEvent;
using blink::WebPoint;
using blink::WebRect;
using blink::WebSize;
using blink::WebString;
using blink::WebTextDirection;
using blink::WebTextInputType;
using blink::WebVector;
using blink::WebWidget;
using blink::WGC3Dintptr;

namespace content {

namespace {

class FullscreenMouseLockDispatcher : public MouseLockDispatcher {
 public:
  explicit FullscreenMouseLockDispatcher(RenderWidgetFullscreenPepper* widget);
  ~FullscreenMouseLockDispatcher() override;

 private:
  // MouseLockDispatcher implementation.
  void SendLockMouseRequest(bool unlocked_by_target) override;
  void SendUnlockMouseRequest() override;

  RenderWidgetFullscreenPepper* widget_;

  DISALLOW_COPY_AND_ASSIGN(FullscreenMouseLockDispatcher);
};

WebMouseEvent WebMouseEventFromGestureEvent(const WebGestureEvent& gesture) {
  WebMouseEvent mouse;

  switch (gesture.type) {
    case WebInputEvent::GestureScrollBegin:
      mouse.type = WebInputEvent::MouseDown;
      break;

    case WebInputEvent::GestureScrollUpdate:
      mouse.type = WebInputEvent::MouseMove;
      break;

    case WebInputEvent::GestureFlingStart:
      if (gesture.sourceDevice == blink::WebGestureDeviceTouchscreen) {
        // A scroll gesture on the touchscreen may end with a GestureScrollEnd
        // when there is no velocity, or a GestureFlingStart when it has a
        // velocity. In both cases, it should end the drag that was initiated by
        // the GestureScrollBegin (and subsequent GestureScrollUpdate) events.
        mouse.type = WebInputEvent::MouseUp;
        break;
      } else {
        return mouse;
      }
    case WebInputEvent::GestureScrollEnd:
      mouse.type = WebInputEvent::MouseUp;
      break;

    default:
      break;
  }

  if (mouse.type == WebInputEvent::Undefined)
    return mouse;

  mouse.timeStampSeconds = gesture.timeStampSeconds;
  mouse.modifiers = gesture.modifiers | WebInputEvent::LeftButtonDown;
  mouse.button = WebMouseEvent::ButtonLeft;
  mouse.clickCount = (mouse.type == WebInputEvent::MouseDown ||
                      mouse.type == WebInputEvent::MouseUp);

  mouse.x = gesture.x;
  mouse.y = gesture.y;
  mouse.windowX = gesture.globalX;
  mouse.windowY = gesture.globalY;
  mouse.globalX = gesture.globalX;
  mouse.globalY = gesture.globalY;

  return mouse;
}

FullscreenMouseLockDispatcher::FullscreenMouseLockDispatcher(
    RenderWidgetFullscreenPepper* widget) : widget_(widget) {
}

FullscreenMouseLockDispatcher::~FullscreenMouseLockDispatcher() {
}

void FullscreenMouseLockDispatcher::SendLockMouseRequest(
    bool unlocked_by_target) {
  widget_->Send(new ViewHostMsg_LockMouse(widget_->routing_id(), false,
                                          unlocked_by_target, true));
}

void FullscreenMouseLockDispatcher::SendUnlockMouseRequest() {
  widget_->Send(new ViewHostMsg_UnlockMouse(widget_->routing_id()));
}

// WebWidget that simply wraps the pepper plugin.
// TODO(piman): figure out IME and implement setComposition and friends if
// necessary.
class PepperWidget : public WebWidget {
 public:
  explicit PepperWidget(RenderWidgetFullscreenPepper* widget)
      : widget_(widget) {
  }

  virtual ~PepperWidget() {}

  // WebWidget API
  virtual void close() {
    delete this;
  }

  virtual WebSize size() {
    return size_;
  }

  virtual void resize(const WebSize& size) {
    if (!widget_->plugin())
      return;

    size_ = size;
    WebRect plugin_rect(0, 0, size_.width, size_.height);
    widget_->plugin()->ViewChanged(plugin_rect, plugin_rect, plugin_rect,
                                   std::vector<gfx::Rect>());
    widget_->Invalidate();
  }

  virtual void themeChanged() {
    NOTIMPLEMENTED();
  }

  virtual bool handleInputEvent(const WebInputEvent& event) {
    if (!widget_->plugin())
      return false;

    // This cursor info is ignored, we always set the cursor directly from
    // RenderWidgetFullscreenPepper::DidChangeCursor.
    WebCursorInfo cursor;

    // Pepper plugins do not accept gesture events. So do not send the gesture
    // events directly to the plugin. Instead, try to convert them to equivalent
    // mouse events, and then send to the plugin.
    if (WebInputEvent::isGestureEventType(event.type)) {
      bool result = false;
      const WebGestureEvent* gesture_event =
          static_cast<const WebGestureEvent*>(&event);
      switch (event.type) {
        case WebInputEvent::GestureTap: {
          WebMouseEvent mouse;

          mouse.timeStampSeconds = gesture_event->timeStampSeconds;
          mouse.type = WebInputEvent::MouseMove;
          mouse.modifiers = gesture_event->modifiers;

          mouse.x = gesture_event->x;
          mouse.y = gesture_event->y;
          mouse.windowX = gesture_event->globalX;
          mouse.windowY = gesture_event->globalY;
          mouse.globalX = gesture_event->globalX;
          mouse.globalY = gesture_event->globalY;
          mouse.movementX = 0;
          mouse.movementY = 0;
          result |= widget_->plugin()->HandleInputEvent(mouse, &cursor);

          mouse.type = WebInputEvent::MouseDown;
          mouse.button = WebMouseEvent::ButtonLeft;
          mouse.clickCount = gesture_event->data.tap.tapCount;
          result |= widget_->plugin()->HandleInputEvent(mouse, &cursor);

          mouse.type = WebInputEvent::MouseUp;
          result |= widget_->plugin()->HandleInputEvent(mouse, &cursor);
          break;
        }

        default: {
          WebMouseEvent mouse = WebMouseEventFromGestureEvent(*gesture_event);
          if (mouse.type != WebInputEvent::Undefined)
            result |= widget_->plugin()->HandleInputEvent(mouse, &cursor);
          break;
        }
      }
      return result;
    }

    bool result = widget_->plugin()->HandleInputEvent(event, &cursor);

    // For normal web pages, WebViewImpl does input event translations and
    // generates context menu events. Since we don't have a WebView, we need to
    // do the necessary translation ourselves.
    if (WebInputEvent::isMouseEventType(event.type)) {
      const WebMouseEvent& mouse_event =
          reinterpret_cast<const WebMouseEvent&>(event);
      bool send_context_menu_event = false;
      // On Mac/Linux, we handle it on mouse down.
      // On Windows, we handle it on mouse up.
#if defined(OS_WIN)
      send_context_menu_event =
          mouse_event.type == WebInputEvent::MouseUp &&
          mouse_event.button == WebMouseEvent::ButtonRight;
#elif defined(OS_MACOSX)
      send_context_menu_event =
          mouse_event.type == WebInputEvent::MouseDown &&
          (mouse_event.button == WebMouseEvent::ButtonRight ||
           (mouse_event.button == WebMouseEvent::ButtonLeft &&
            mouse_event.modifiers & WebMouseEvent::ControlKey));
#else
      send_context_menu_event =
          mouse_event.type == WebInputEvent::MouseDown &&
          mouse_event.button == WebMouseEvent::ButtonRight;
#endif
      if (send_context_menu_event) {
        WebMouseEvent context_menu_event(mouse_event);
        context_menu_event.type = WebInputEvent::ContextMenu;
        widget_->plugin()->HandleInputEvent(context_menu_event, &cursor);
      }
    }
    return result;
  }

 private:
  RenderWidgetFullscreenPepper* widget_;
  WebSize size_;

  DISALLOW_COPY_AND_ASSIGN(PepperWidget);
};

}  // anonymous namespace

// static
RenderWidgetFullscreenPepper* RenderWidgetFullscreenPepper::Create(
    int32 opener_id,
    CompositorDependencies* compositor_deps,
    PepperPluginInstanceImpl* plugin,
    const GURL& active_url,
    const blink::WebScreenInfo& screen_info) {
  DCHECK_NE(MSG_ROUTING_NONE, opener_id);
  scoped_refptr<RenderWidgetFullscreenPepper> widget(
      new RenderWidgetFullscreenPepper(plugin, active_url, screen_info));
  widget->Init(opener_id, compositor_deps);
  widget->AddRef();
  return widget.get();
}

RenderWidgetFullscreenPepper::RenderWidgetFullscreenPepper(
    PepperPluginInstanceImpl* plugin,
    const GURL& active_url,
    const blink::WebScreenInfo& screen_info)
    : RenderWidgetFullscreen(screen_info),
      active_url_(active_url),
      plugin_(plugin),
      layer_(NULL),
      mouse_lock_dispatcher_(new FullscreenMouseLockDispatcher(
          this)) {
}

RenderWidgetFullscreenPepper::~RenderWidgetFullscreenPepper() {
}

void RenderWidgetFullscreenPepper::Invalidate() {
  InvalidateRect(gfx::Rect(size_.width(), size_.height()));
}

void RenderWidgetFullscreenPepper::InvalidateRect(const blink::WebRect& rect) {
  didInvalidateRect(rect);
}

void RenderWidgetFullscreenPepper::ScrollRect(
    int dx, int dy, const blink::WebRect& rect) {
}

void RenderWidgetFullscreenPepper::Destroy() {
  // This function is called by the plugin instance as it's going away, so reset
  // plugin_ to NULL to avoid calling into a dangling pointer e.g. on Close().
  plugin_ = NULL;

  // After calling Destroy(), the plugin instance assumes that the layer is not
  // used by us anymore, so it may destroy the layer before this object goes
  // away.
  SetLayer(NULL);

  Send(new ViewHostMsg_Close(routing_id_));
  Release();
}

void RenderWidgetFullscreenPepper::DidChangeCursor(
    const blink::WebCursorInfo& cursor) {
  didChangeCursor(cursor);
}

void RenderWidgetFullscreenPepper::SetLayer(blink::WebLayer* layer) {
  layer_ = layer;
  if (!layer_) {
    if (compositor_)
      compositor_->clearRootLayer();
    return;
  }
  if (!layerTreeView())
    initializeLayerTreeView();
  layer_->setBounds(blink::WebSize(size()));
  layer_->setDrawsContent(true);
  compositor_->setDeviceScaleFactor(device_scale_factor_);
  compositor_->setRootLayer(*layer_);
}

bool RenderWidgetFullscreenPepper::OnMessageReceived(const IPC::Message& msg) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(RenderWidgetFullscreenPepper, msg)
    IPC_MESSAGE_FORWARD(ViewMsg_LockMouse_ACK,
                        mouse_lock_dispatcher_.get(),
                        MouseLockDispatcher::OnLockMouseACK)
    IPC_MESSAGE_FORWARD(ViewMsg_MouseLockLost,
                        mouse_lock_dispatcher_.get(),
                        MouseLockDispatcher::OnMouseLockLost)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  if (handled)
    return true;

  return RenderWidgetFullscreen::OnMessageReceived(msg);
}

void RenderWidgetFullscreenPepper::DidInitiatePaint() {
  if (plugin_)
    plugin_->ViewInitiatedPaint();
}

void RenderWidgetFullscreenPepper::DidFlushPaint() {
}

void RenderWidgetFullscreenPepper::Close() {
  // If the fullscreen window is closed (e.g. user pressed escape), reset to
  // normal mode.
  if (plugin_)
    plugin_->FlashSetFullscreen(false, false);

  // Call Close on the base class to destroy the WebWidget instance.
  RenderWidget::Close();
}

void RenderWidgetFullscreenPepper::OnResize(
    const ViewMsg_Resize_Params& params) {
  if (layer_)
    layer_->setBounds(blink::WebSize(params.new_size));
  RenderWidget::OnResize(params);
}

WebWidget* RenderWidgetFullscreenPepper::CreateWebWidget() {
  return new PepperWidget(this);
}

GURL RenderWidgetFullscreenPepper::GetURLForGraphicsContext3D() {
  return active_url_;
}

void RenderWidgetFullscreenPepper::SetDeviceScaleFactor(
    float device_scale_factor) {
  RenderWidget::SetDeviceScaleFactor(device_scale_factor);
  if (compositor_)
    compositor_->setDeviceScaleFactor(device_scale_factor);
}

}  // namespace content
<commit_msg>Make WebMouseEvent.windowX equal to WebMouseEvent.x. Same for y.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/renderer/render_widget_fullscreen_pepper.h"

#include <vector>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
#include "content/common/gpu/client/gpu_channel_host.h"
#include "content/common/view_messages.h"
#include "content/public/common/content_switches.h"
#include "content/renderer/gpu/render_widget_compositor.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/render_thread_impl.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/public/platform/WebCanvas.h"
#include "third_party/WebKit/public/platform/WebCursorInfo.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
#include "third_party/WebKit/public/platform/WebLayer.h"
#include "third_party/WebKit/public/platform/WebSize.h"
#include "third_party/WebKit/public/web/WebWidget.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gl/gpu_preference.h"

using blink::WebCanvas;
using blink::WebCompositionUnderline;
using blink::WebCursorInfo;
using blink::WebGestureEvent;
using blink::WebInputEvent;
using blink::WebMouseEvent;
using blink::WebMouseWheelEvent;
using blink::WebPoint;
using blink::WebRect;
using blink::WebSize;
using blink::WebString;
using blink::WebTextDirection;
using blink::WebTextInputType;
using blink::WebVector;
using blink::WebWidget;
using blink::WGC3Dintptr;

namespace content {

namespace {

class FullscreenMouseLockDispatcher : public MouseLockDispatcher {
 public:
  explicit FullscreenMouseLockDispatcher(RenderWidgetFullscreenPepper* widget);
  ~FullscreenMouseLockDispatcher() override;

 private:
  // MouseLockDispatcher implementation.
  void SendLockMouseRequest(bool unlocked_by_target) override;
  void SendUnlockMouseRequest() override;

  RenderWidgetFullscreenPepper* widget_;

  DISALLOW_COPY_AND_ASSIGN(FullscreenMouseLockDispatcher);
};

WebMouseEvent WebMouseEventFromGestureEvent(const WebGestureEvent& gesture) {
  WebMouseEvent mouse;

  switch (gesture.type) {
    case WebInputEvent::GestureScrollBegin:
      mouse.type = WebInputEvent::MouseDown;
      break;

    case WebInputEvent::GestureScrollUpdate:
      mouse.type = WebInputEvent::MouseMove;
      break;

    case WebInputEvent::GestureFlingStart:
      if (gesture.sourceDevice == blink::WebGestureDeviceTouchscreen) {
        // A scroll gesture on the touchscreen may end with a GestureScrollEnd
        // when there is no velocity, or a GestureFlingStart when it has a
        // velocity. In both cases, it should end the drag that was initiated by
        // the GestureScrollBegin (and subsequent GestureScrollUpdate) events.
        mouse.type = WebInputEvent::MouseUp;
        break;
      } else {
        return mouse;
      }
    case WebInputEvent::GestureScrollEnd:
      mouse.type = WebInputEvent::MouseUp;
      break;

    default:
      break;
  }

  if (mouse.type == WebInputEvent::Undefined)
    return mouse;

  mouse.timeStampSeconds = gesture.timeStampSeconds;
  mouse.modifiers = gesture.modifiers | WebInputEvent::LeftButtonDown;
  mouse.button = WebMouseEvent::ButtonLeft;
  mouse.clickCount = (mouse.type == WebInputEvent::MouseDown ||
                      mouse.type == WebInputEvent::MouseUp);

  mouse.x = gesture.x;
  mouse.y = gesture.y;
  mouse.windowX = gesture.x;
  mouse.windowY = gesture.y;
  mouse.globalX = gesture.globalX;
  mouse.globalY = gesture.globalY;

  return mouse;
}

FullscreenMouseLockDispatcher::FullscreenMouseLockDispatcher(
    RenderWidgetFullscreenPepper* widget) : widget_(widget) {
}

FullscreenMouseLockDispatcher::~FullscreenMouseLockDispatcher() {
}

void FullscreenMouseLockDispatcher::SendLockMouseRequest(
    bool unlocked_by_target) {
  widget_->Send(new ViewHostMsg_LockMouse(widget_->routing_id(), false,
                                          unlocked_by_target, true));
}

void FullscreenMouseLockDispatcher::SendUnlockMouseRequest() {
  widget_->Send(new ViewHostMsg_UnlockMouse(widget_->routing_id()));
}

// WebWidget that simply wraps the pepper plugin.
// TODO(piman): figure out IME and implement setComposition and friends if
// necessary.
class PepperWidget : public WebWidget {
 public:
  explicit PepperWidget(RenderWidgetFullscreenPepper* widget)
      : widget_(widget) {
  }

  virtual ~PepperWidget() {}

  // WebWidget API
  virtual void close() {
    delete this;
  }

  virtual WebSize size() {
    return size_;
  }

  virtual void resize(const WebSize& size) {
    if (!widget_->plugin())
      return;

    size_ = size;
    WebRect plugin_rect(0, 0, size_.width, size_.height);
    widget_->plugin()->ViewChanged(plugin_rect, plugin_rect, plugin_rect,
                                   std::vector<gfx::Rect>());
    widget_->Invalidate();
  }

  virtual void themeChanged() {
    NOTIMPLEMENTED();
  }

  virtual bool handleInputEvent(const WebInputEvent& event) {
    if (!widget_->plugin())
      return false;

    // This cursor info is ignored, we always set the cursor directly from
    // RenderWidgetFullscreenPepper::DidChangeCursor.
    WebCursorInfo cursor;

    // Pepper plugins do not accept gesture events. So do not send the gesture
    // events directly to the plugin. Instead, try to convert them to equivalent
    // mouse events, and then send to the plugin.
    if (WebInputEvent::isGestureEventType(event.type)) {
      bool result = false;
      const WebGestureEvent* gesture_event =
          static_cast<const WebGestureEvent*>(&event);
      switch (event.type) {
        case WebInputEvent::GestureTap: {
          WebMouseEvent mouse;

          mouse.timeStampSeconds = gesture_event->timeStampSeconds;
          mouse.type = WebInputEvent::MouseMove;
          mouse.modifiers = gesture_event->modifiers;

          mouse.x = gesture_event->x;
          mouse.y = gesture_event->y;
          mouse.windowX = gesture_event->x;
          mouse.windowY = gesture_event->y;
          mouse.globalX = gesture_event->globalX;
          mouse.globalY = gesture_event->globalY;
          mouse.movementX = 0;
          mouse.movementY = 0;
          result |= widget_->plugin()->HandleInputEvent(mouse, &cursor);

          mouse.type = WebInputEvent::MouseDown;
          mouse.button = WebMouseEvent::ButtonLeft;
          mouse.clickCount = gesture_event->data.tap.tapCount;
          result |= widget_->plugin()->HandleInputEvent(mouse, &cursor);

          mouse.type = WebInputEvent::MouseUp;
          result |= widget_->plugin()->HandleInputEvent(mouse, &cursor);
          break;
        }

        default: {
          WebMouseEvent mouse = WebMouseEventFromGestureEvent(*gesture_event);
          if (mouse.type != WebInputEvent::Undefined)
            result |= widget_->plugin()->HandleInputEvent(mouse, &cursor);
          break;
        }
      }
      return result;
    }

    bool result = widget_->plugin()->HandleInputEvent(event, &cursor);

    // For normal web pages, WebViewImpl does input event translations and
    // generates context menu events. Since we don't have a WebView, we need to
    // do the necessary translation ourselves.
    if (WebInputEvent::isMouseEventType(event.type)) {
      const WebMouseEvent& mouse_event =
          reinterpret_cast<const WebMouseEvent&>(event);
      bool send_context_menu_event = false;
      // On Mac/Linux, we handle it on mouse down.
      // On Windows, we handle it on mouse up.
#if defined(OS_WIN)
      send_context_menu_event =
          mouse_event.type == WebInputEvent::MouseUp &&
          mouse_event.button == WebMouseEvent::ButtonRight;
#elif defined(OS_MACOSX)
      send_context_menu_event =
          mouse_event.type == WebInputEvent::MouseDown &&
          (mouse_event.button == WebMouseEvent::ButtonRight ||
           (mouse_event.button == WebMouseEvent::ButtonLeft &&
            mouse_event.modifiers & WebMouseEvent::ControlKey));
#else
      send_context_menu_event =
          mouse_event.type == WebInputEvent::MouseDown &&
          mouse_event.button == WebMouseEvent::ButtonRight;
#endif
      if (send_context_menu_event) {
        WebMouseEvent context_menu_event(mouse_event);
        context_menu_event.type = WebInputEvent::ContextMenu;
        widget_->plugin()->HandleInputEvent(context_menu_event, &cursor);
      }
    }
    return result;
  }

 private:
  RenderWidgetFullscreenPepper* widget_;
  WebSize size_;

  DISALLOW_COPY_AND_ASSIGN(PepperWidget);
};

}  // anonymous namespace

// static
RenderWidgetFullscreenPepper* RenderWidgetFullscreenPepper::Create(
    int32 opener_id,
    CompositorDependencies* compositor_deps,
    PepperPluginInstanceImpl* plugin,
    const GURL& active_url,
    const blink::WebScreenInfo& screen_info) {
  DCHECK_NE(MSG_ROUTING_NONE, opener_id);
  scoped_refptr<RenderWidgetFullscreenPepper> widget(
      new RenderWidgetFullscreenPepper(plugin, active_url, screen_info));
  widget->Init(opener_id, compositor_deps);
  widget->AddRef();
  return widget.get();
}

RenderWidgetFullscreenPepper::RenderWidgetFullscreenPepper(
    PepperPluginInstanceImpl* plugin,
    const GURL& active_url,
    const blink::WebScreenInfo& screen_info)
    : RenderWidgetFullscreen(screen_info),
      active_url_(active_url),
      plugin_(plugin),
      layer_(NULL),
      mouse_lock_dispatcher_(new FullscreenMouseLockDispatcher(
          this)) {
}

RenderWidgetFullscreenPepper::~RenderWidgetFullscreenPepper() {
}

void RenderWidgetFullscreenPepper::Invalidate() {
  InvalidateRect(gfx::Rect(size_.width(), size_.height()));
}

void RenderWidgetFullscreenPepper::InvalidateRect(const blink::WebRect& rect) {
  didInvalidateRect(rect);
}

void RenderWidgetFullscreenPepper::ScrollRect(
    int dx, int dy, const blink::WebRect& rect) {
}

void RenderWidgetFullscreenPepper::Destroy() {
  // This function is called by the plugin instance as it's going away, so reset
  // plugin_ to NULL to avoid calling into a dangling pointer e.g. on Close().
  plugin_ = NULL;

  // After calling Destroy(), the plugin instance assumes that the layer is not
  // used by us anymore, so it may destroy the layer before this object goes
  // away.
  SetLayer(NULL);

  Send(new ViewHostMsg_Close(routing_id_));
  Release();
}

void RenderWidgetFullscreenPepper::DidChangeCursor(
    const blink::WebCursorInfo& cursor) {
  didChangeCursor(cursor);
}

void RenderWidgetFullscreenPepper::SetLayer(blink::WebLayer* layer) {
  layer_ = layer;
  if (!layer_) {
    if (compositor_)
      compositor_->clearRootLayer();
    return;
  }
  if (!layerTreeView())
    initializeLayerTreeView();
  layer_->setBounds(blink::WebSize(size()));
  layer_->setDrawsContent(true);
  compositor_->setDeviceScaleFactor(device_scale_factor_);
  compositor_->setRootLayer(*layer_);
}

bool RenderWidgetFullscreenPepper::OnMessageReceived(const IPC::Message& msg) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(RenderWidgetFullscreenPepper, msg)
    IPC_MESSAGE_FORWARD(ViewMsg_LockMouse_ACK,
                        mouse_lock_dispatcher_.get(),
                        MouseLockDispatcher::OnLockMouseACK)
    IPC_MESSAGE_FORWARD(ViewMsg_MouseLockLost,
                        mouse_lock_dispatcher_.get(),
                        MouseLockDispatcher::OnMouseLockLost)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  if (handled)
    return true;

  return RenderWidgetFullscreen::OnMessageReceived(msg);
}

void RenderWidgetFullscreenPepper::DidInitiatePaint() {
  if (plugin_)
    plugin_->ViewInitiatedPaint();
}

void RenderWidgetFullscreenPepper::DidFlushPaint() {
}

void RenderWidgetFullscreenPepper::Close() {
  // If the fullscreen window is closed (e.g. user pressed escape), reset to
  // normal mode.
  if (plugin_)
    plugin_->FlashSetFullscreen(false, false);

  // Call Close on the base class to destroy the WebWidget instance.
  RenderWidget::Close();
}

void RenderWidgetFullscreenPepper::OnResize(
    const ViewMsg_Resize_Params& params) {
  if (layer_)
    layer_->setBounds(blink::WebSize(params.new_size));
  RenderWidget::OnResize(params);
}

WebWidget* RenderWidgetFullscreenPepper::CreateWebWidget() {
  return new PepperWidget(this);
}

GURL RenderWidgetFullscreenPepper::GetURLForGraphicsContext3D() {
  return active_url_;
}

void RenderWidgetFullscreenPepper::SetDeviceScaleFactor(
    float device_scale_factor) {
  RenderWidget::SetDeviceScaleFactor(device_scale_factor);
  if (compositor_)
    compositor_->setDeviceScaleFactor(device_scale_factor);
}

}  // namespace content
<|endoftext|>