<commit_before>/************************************************************************************
**
* @copyright (c) 2013-2100, ChengDu Duyer Technology Co., LTD. All Right Reserved.
*
*************************************************************************************/
/**
* @file     g_dfs_server.cpp
* @version
* @brief
* @author   duye
* @date     2014-09-24
* @note
*
*  1. 2014-09-24 duye Created this file
*
*/

#include <g_dfs_server.h>
#include <g_logger.h>

static const GInt8* LOG_PREFIX = "dfs.server.startup";

namespace gdfs {

DfsServer::DfsServer() : gcom::HostServer() {}

DfsServer::DfsServer(const std::string& dfs_cfg_file_path) : gcom::HostServer(), m_dfsCfgFilePath(dfs_cfg_file_path) {}

DfsServer::~DfsServer()
{
    gcom::ServerFactory::intance().destroyServer(m_httpServer);
    gcom::ServerFactory::intance().destroyServer(m_ftpServer);
    gcom::ServerFactory::intance().destroyServer(m_cliServer);
}

GResult DfsServer::start()
{
    G_LOG_IN();

    if (getServerState() == HOST_SERVER_WORK)
    {
        return G_YES;
    }

    if (m_dfsCfgFilePath.empty())
    {
        m_dfsCfgFilePath = DEF_DFS_CFG_FILE_PATH;
    }

    IS_NO_R(m_cfgMgr.load(m_dfsCfgFilePath));

    // init all service
    m_httpServer = gcom::ServerFactory::intance().createServer(HTTP_SERVER);
    m_ftpServer = gcom::ServerFactory::intance().createServer(FTP_SERVER);
    m_cliServer = gcom::ServerFactory::intance().createServer(CLI_SERVER);

    // start routine() thread
    this->startTask();

    // set server state is work
    m_serverState = HOST_SERVER_WORK;

    G_LOG_OUT();

    return G_YES;
}

GResult DfsServer::stop()
{
    G_LOG_IN();

    m_httpServer->stop();
    m_ftpServer->stop();
    m_cliServer->stop();

    G_LOG_OUT();

    return G_NO;
}

DfsServerState DfsServer::routine()
{
    G_LOG_IN();

    m_httpServer->start();
    m_ftpServer->start();
    m_cliServer->start();

    for (;;)
    {
        // startup all server
        gcom::NetworkServerMonitor::keepServer(m_httpServer);
        gcom::NetworkServerMonitor::keepServer(m_ftpServer);
        gcom::NetworkServerMonitor::keepServer(m_cliServer);

        gsys::System::sleep(5);
    }

    G_LOG_OUT();

    return G_YES;
}

}
<commit_msg>Update g_dfs_server.cpp<commit_after>/************************************************************************************
**
* @copyright (c) 2013-2100, ChengDu Duyer Technology Co., LTD. All Right Reserved.
*
*************************************************************************************/
/**
* @file     g_dfs_server.cpp
* @version
* @brief
* @author   duye
* @date     2014-09-24
* @note
*
*  1. 2014-09-24 duye Created this file
*
*/

#include <g_dfs_server.h>
#include <g_logger.h>

static const GInt8* LOG_PREFIX = "dfs.server.startup";

namespace gdfs {

DfsServer::DfsServer() : gcom::HostServer() {}

DfsServer::DfsServer(const std::string& dfs_cfg_file_path) : gcom::HostServer(), m_dfsCfgFilePath(dfs_cfg_file_path) {}

DfsServer::~DfsServer()
{
    G_LOG_IN();
    gcom::ServerFactory::intance().destroyServer(m_httpServer);
    gcom::ServerFactory::intance().destroyServer(m_ftpServer);
    gcom::ServerFactory::intance().destroyServer(m_cliServer);
    G_LOG_OUT();
}

GResult DfsServer::start()
{
    G_LOG_IN();

    if (getServerState() == HOST_SERVER_WORK)
    {
        return G_YES;
    }

    if (m_dfsCfgFilePath.empty())
    {
        m_dfsCfgFilePath = DEF_DFS_CFG_FILE_PATH;
    }

    IS_NO_R(m_cfgMgr.load(m_dfsCfgFilePath));

    // init all service
    m_httpServer = gcom::ServerFactory::intance().createServer(HTTP_SERVER);
    m_ftpServer = gcom::ServerFactory::intance().createServer(FTP_SERVER);
    m_cliServer = gcom::ServerFactory::intance().createServer(CLI_SERVER);

    // startup all service
    m_httpServer->start();
    m_ftpServer->start();
    m_cliServer->start();

    // start routine() thread
    this->startTask();

    // set server state is work
    m_serverState = HOST_SERVER_WORK;

    G_LOG_OUT();

    return G_YES;
}

GResult DfsServer::stop()
{
    G_LOG_IN();

    m_httpServer->stop();
    m_ftpServer->stop();
    m_cliServer->stop();

    G_LOG_OUT();

    return G_NO;
}

DfsServerState DfsServer::routine()
{
    G_LOG_IN();

    for (;;)
    {
        // keep all service is running
        gcom::NetworkServerMonitor::keepServer(m_httpServer);
        gcom::NetworkServerMonitor::keepServer(m_ftpServer);
        gcom::NetworkServerMonitor::keepServer(m_cliServer);

        gsys::System::sleep(5);
    }

    G_LOG_OUT();

    return G_YES;
}

}
<|endoftext|>


<commit_before>/*!
  @file PDBReader.hpp
  @brief definition of a class that reads pdb atom.

  read pdb file and store the information as std::vector of shared_ptr of PDBAtom

  @author Toru Niina (niina.toru.68u@gmail.com)
  @date 2016-06-10 13:00
  @copyright Toru Niina 2016 on MIT License
*/

#ifndef COFFEE_MILL_PDB_READER
#define COFFEE_MILL_PDB_READER
#include "PDBChain.hpp"
#include <fstream>
#include <sstream>

namespace mill
{

//! PDBReader class
/*!
 * read atoms in pdb file until "ENDMDL" or "END".
 * and then parse the PDBAtoms into vector of PDBChains.
 * for movie file, parse only one model at once. you can specify the model
 * by model index.
 */
template<typename vectorT>
class PDBReader
{
  public:

    using vector_type  = vectorT;
    using atom_type    = PDBAtom<vector_type>;
    using residue_type = PDBResidue<vector_type>;
    using chain_type   = PDBChain<vector_type>;

  public:

    PDBReader() = default;
    ~PDBReader() = default;

    std::vector<chain_type> parse(const std::vector<atom_type>& atoms);

    std::vector<atom_type> read(const std::string& fname);
    std::vector<atom_type> read(const std::string& fname, const std::size_t model_idx);
    std::vector<atom_type> read(std::basic_istream<char>& fname);
    std::vector<atom_type> read(std::basic_istream<char>& fname, const std::size_t model_idx);
};

template<typename vectorT>
std::vector<typename PDBReader<vectorT>::atom_type>
PDBReader<vectorT>::read(const std::string& fname)
{
    std::ifstream ifs(fname);
    if(not ifs.good()) throw std::runtime_error("file open error: " + fname);
    const auto data = this->read(ifs);
    ifs.close();
    return data;
}

template<typename vectorT>
std::vector<typename PDBReader<vectorT>::atom_type>
PDBReader<vectorT>::read(const std::string& fname, const std::size_t model_idx)
{
    std::ifstream ifs(fname);
    if(not ifs.good()) throw std::runtime_error("file open error: " + fname);
    const auto data = this->read(ifs, model_idx);
    ifs.close();
    return data;
}

template<typename vectorT>
std::vector<typename PDBReader<vectorT>::atom_type>
PDBReader<vectorT>::read(std::basic_istream<char>& ifs, const std::size_t model_idx)
{
    while(not ifs.eof())
    {
        std::string line;
        std::getline(ifs, line);
        if(line.empty()) continue;
        if(line.substr(0, 5) == "MODEL")
        {
            std::size_t index;
            std::istringstream iss(line);
            std::string model;
            iss >> model >> index;
            if(index == model_idx) break;
        }
    }
    if(ifs.eof())
        throw std::invalid_argument("no model #" + std::to_string(model_idx));
    return this->read(ifs);
}

template<typename vectorT>
std::vector<typename PDBReader<vectorT>::atom_type>
PDBReader<vectorT>::read(std::basic_istream<char>& ifs)
{
    std::vector<atom_type> atoms;
    while(not ifs.eof())
    {
        std::string line;
        std::getline(ifs, line);
        if(line.empty()) continue;
        if(line.substr(0, 3) == "END") break; // which is better ENDMDL or END?

        atom_type atom;
        if(line >> atom) atoms.emplace_back(std::move(atom));
    }
    return atoms;
}

template<typename vectorT>
std::vector<typename PDBReader<vectorT>::chain_type>
PDBReader<vectorT>::parse(const std::vector<atom_type>& atoms)
{
    std::vector<residue_type> residues;
    residue_type tmp_residue;
    int current_residue_id = std::numeric_limits<int>::min();
    for(auto iter = atoms.cbegin(); iter != atoms.cend(); ++iter)
    {
        if(iter->residue_id != current_residue_id)
        {
            if(not tmp_residue.empty())
                residues.push_back(tmp_residue);
            tmp_residue->clear();
            current_residue_id = iter->residue_id;
        }
        tmp_residue.push_back(*iter);
    }
    if(not tmp_residue.empty()) residues.push_back(tmp_residue);

    std::vector<chain_type> chains;
    chain_type tmp_chain;
    std::string current_chain_id = "";
    for(auto iter = residues.begin(); iter != residues.end(); ++iter)
    {
        if(iter->chain_id != current_chain_id)
        {
            if(not tmp_chain.empty()) chains.push_back(tmp_chain);
            tmp_chain.clear();
            current_chain_id = iter->chain_id();
        }
        tmp_chain.push_back(*iter);
    }
    if(not tmp_chain.empty()) chains.push_back(tmp_chain);

    return chains;
}

} // mill

#endif//COFFEE_MILL_PURE_PDB_READER
<commit_msg>add const to member function of PDBReader<commit_after>/*!
  @file PDBReader.hpp
  @brief pdb reader.

  read pdb atoms from input stream and parse atoms as chains.

  @author Toru Niina (niina.toru.68u@gmail.com)
  @date 2016-06-10 13:00
  @copyright Toru Niina 2016 on MIT License
*/

#ifndef COFFEE_MILL_PDB_READER
#define COFFEE_MILL_PDB_READER
#include "PDBChain.hpp"
#include <fstream>
#include <sstream>

namespace mill
{

//! PDBReader class
/*!
 * read atoms in pdb file until "ENDMDL" or "END".
 * and then parse the PDBAtoms into vector of PDBChains.
 * for movie file, parse only one model at once. you can specify the model
 * by model index.
 */
template<typename vectorT>
class PDBReader
{
  public:

    using vector_type  = vectorT;
    using atom_type    = PDBAtom<vector_type>;
    using residue_type = PDBResidue<vector_type>;
    using chain_type   = PDBChain<vector_type>;

  public:

    PDBReader() = default;
    ~PDBReader() = default;

    std::vector<chain_type> parse(const std::vector<atom_type>& atoms) const;

    std::vector<atom_type> read(const std::string& fname) const;
    std::vector<atom_type> read(const std::string& fname, const std::size_t model_idx) const;
    std::vector<atom_type> read(std::basic_istream<char>& fname) const;
    std::vector<atom_type> read(std::basic_istream<char>& fname, const std::size_t model_idx) const;
};

template<typename vectorT>
std::vector<typename PDBReader<vectorT>::atom_type>
PDBReader<vectorT>::read(const std::string& fname) const
{
    std::ifstream ifs(fname);
    if(not ifs.good()) throw std::runtime_error("file open error: " + fname);
    const auto data = this->read(ifs);
    ifs.close();
    return data;
}

template<typename vectorT>
std::vector<typename PDBReader<vectorT>::atom_type>
PDBReader<vectorT>::read(const std::string& fname, const std::size_t model_idx) const
{
    std::ifstream ifs(fname);
    if(not ifs.good()) throw std::runtime_error("file open error: " + fname);
    const auto data = this->read(ifs, model_idx);
    ifs.close();
    return data;
}

template<typename vectorT>
std::vector<typename PDBReader<vectorT>::atom_type>
PDBReader<vectorT>::read(std::basic_istream<char>& ifs, const std::size_t model_idx) const
{
    while(not ifs.eof())
    {
        std::string line;
        std::getline(ifs, line);
        if(line.empty()) continue;
        if(line.substr(0, 5) == "MODEL")
        {
            std::size_t index;
            std::istringstream iss(line);
            std::string model;
            iss >> model >> index;
            if(index == model_idx) break;
        }
    }
    if(ifs.eof())
        throw std::invalid_argument("no model #" + std::to_string(model_idx));
    return this->read(ifs);
}

template<typename vectorT>
std::vector<typename PDBReader<vectorT>::atom_type>
PDBReader<vectorT>::read(std::basic_istream<char>& ifs) const
{
    std::vector<atom_type> atoms;
    while(not ifs.eof())
    {
        std::string line;
        std::getline(ifs, line);
        if(line.empty()) continue;
        if(line.substr(0, 3) == "END") break; // which is better ENDMDL or END?

        atom_type atom;
        if(line >> atom) atoms.emplace_back(std::move(atom));
    }
    return atoms;
}

template<typename vectorT>
std::vector<typename PDBReader<vectorT>::chain_type>
PDBReader<vectorT>::parse(const std::vector<atom_type>& atoms) const
{
    std::vector<residue_type> residues;
    residue_type tmp_residue;
    int current_residue_id = std::numeric_limits<int>::min();
    for(auto iter = atoms.cbegin(); iter != atoms.cend(); ++iter)
    {
        if(iter->residue_id != current_residue_id)
        {
            if(not tmp_residue.empty())
                residues.push_back(tmp_residue);
            tmp_residue->clear();
            current_residue_id = iter->residue_id;
        }
        tmp_residue.push_back(*iter);
    }
    if(not tmp_residue.empty()) residues.push_back(tmp_residue);

    std::vector<chain_type> chains;
    chain_type tmp_chain;
    std::string current_chain_id = "";
    for(auto iter = residues.begin(); iter != residues.end(); ++iter)
    {
        if(iter->chain_id != current_chain_id)
        {
            if(not tmp_chain.empty()) chains.push_back(tmp_chain);
            tmp_chain.clear();
            current_chain_id = iter->chain_id();
        }
        tmp_chain.push_back(*iter);
    }
    if(not tmp_chain.empty()) chains.push_back(tmp_chain);

    return chains;
}

} // mill

#endif//COFFEE_MILL_PURE_PDB_READER
<|endoftext|>


<commit_before>/*********************************************************************
* Software License Agreement (BSD License)
*
*  Copyright (c) 2008, 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 the Willow Garage 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.
*********************************************************************/

/* \author Ioan Sucan */

#include "ompl/extension/samplingbased/kinematic/extension/ik/GAIK.h"
#include <algorithm>

bool ompl::GAIK::solve(double solveTime)
{
    SpaceInformationKinematic_t                          si = dynamic_cast<SpaceInformationKinematic_t>(m_si);
    SpaceInformationKinematic::GoalRegionKinematic_t goal_r = dynamic_cast<SpaceInformationKinematic::GoalRegionKinematic_t>(si->getGoal());
    unsigned int                                        dim = si->getStateDimension();

    if (!goal_r)
    {
	m_msg.error("GAIK: Unknown type of goal (or goal undefined)");
	return false;
    }

    time_utils::Time        endTime = time_utils::Time::now() + time_utils::Duration(solveTime);

    unsigned int            maxPoolSize = m_poolSize + m_poolExpansion;
    std::vector<Individual> pool(maxPoolSize);
    IndividualSort          gs;
    bool                    solved = false;
    int                     solution = -1;

    if (m_poolSize < 1)
    {
	m_msg.error("GAIK: Pool size too small");
	return false;
    }

    for (unsigned int i = 0 ; i < maxPoolSize ; ++i)
    {
	pool[i].state = new SpaceInformationKinematic::StateKinematic(dim);
	si->sample(pool[i].state);
	if (goal_r->isSatisfied(pool[i].state, &(pool[i].distance)))
	{
	    if (si->isValid(static_cast<SpaceInformationKinematic::StateKinematic_t>(pool[i].state)))
	    {
		solved = true;
		solution = i;
	    }
	}
    }

    unsigned int generations = 1;

    std::vector<double> range(dim);
    for (unsigned int i = 0 ; i < dim ; ++i)
	range[i] = m_rho * (si->getStateComponent(i).maxValue - si->getStateComponent(i).minValue);

    while (!solved && time_utils::Time::now() < endTime)
    {
	generations++;
	std::sort(pool.begin(), pool.end(), gs);
	for (unsigned int i = 0 ; i < 5 ; ++i)
	{
	    if (si->isValid(static_cast<SpaceInformationKinematic::StateKinematic_t>(pool[i].state)))
	    {
		if (tryToSolve(pool[i].state, &(pool[i].distance)))
		{
		    solved = true;
		    solution = i;
		    break;
		}
	    }
	}
	for (unsigned int i = m_poolSize ; i < maxPoolSize ; ++i)
	{
	    si->sampleNear(pool[i].state, pool[i%m_poolSize].state, range);
	    if (goal_r->isSatisfied(pool[i].state, &(pool[i].distance)))
	    {
		if (si->isValid(static_cast<SpaceInformationKinematic::StateKinematic_t>(pool[i].state)))
		{
		    solved = true;
		    solution = i;
		    break;
		}
	    }
	}
    }

    m_msg.inform("GAIK: Ran for %u generations", generations);

    if (solved)
    {
	SpaceInformationKinematic::PathKinematic_t path = new SpaceInformationKinematic::PathKinematic(m_si);
	SpaceInformationKinematic::StateKinematic_t st = new SpaceInformationKinematic::StateKinematic(dim);
	si->copyState(st, pool[solution].state);
	path->states.push_back(st);
	goal_r->setDifference(pool[solution].distance);
	goal_r->setSolutionPath(path);
    }
    else
    {
	/* find an approximate solution */
	std::sort(pool.begin(), pool.end(), gs);
	for (unsigned int i = 0 ; i < 5 ; ++i)
	{
	    if (si->isValid(static_cast<SpaceInformationKinematic::StateKinematic_t>(pool[i].state)))
	    {
		SpaceInformationKinematic::PathKinematic_t path = new SpaceInformationKinematic::PathKinematic(m_si);
		SpaceInformationKinematic::StateKinematic_t st = new SpaceInformationKinematic::StateKinematic(dim);
		si->copyState(st, pool[i].state);
		path->states.push_back(st);
		goal_r->setDifference(pool[i].distance);
		goal_r->setSolutionPath(path, true);
		break;
	    }
	}
    }

    for (unsigned int i = 0 ; i < maxPoolSize ; ++i)
	delete pool[i].state;

    return goal_r->isAchieved();
}

bool ompl::GAIK::tryToSolve(SpaceInformationKinematic::StateKinematic_t state, double *distance)
{
    double dist = *distance;

    if (tryToSolveFact(1.01, state, distance))
	return true;

    if (dist > *distance)
    {
	dist = *distance;
	if (tryToSolveFact(1.003, state, distance))
	    return true;
    }
    else
	return false;

    if (dist > *distance)
    {
	dist = *distance;
	if (tryToSolveFact(1.001, state, distance))
	    return true;
    }

    return false;
}

bool ompl::GAIK::tryToSolveFact(double factorP, SpaceInformationKinematic::StateKinematic_t state, double *distance)
{
    SpaceInformationKinematic_t                          si = dynamic_cast<SpaceInformationKinematic_t>(m_si);
    SpaceInformationKinematic::GoalRegionKinematic_t goal_r = dynamic_cast<SpaceInformationKinematic::GoalRegionKinematic_t>(si->getGoal());
    unsigned int                                        dim = si->getStateDimension();

    double factorM = 1.0/factorP;

    bool wasSatisfied = goal_r->isSatisfied(state, distance);
    double bestDist   = *distance;

    bool change = true;

    while (change)
    {
	change = false;

	for (unsigned int i = 0 ; i < dim ; ++i)
	{
	    bool better = true;
	    while (better)
	    {
		better = false;
		double backup = state->values[i];
		state->values[i] *= factorP;
		bool isS = goal_r->isSatisfied(state, distance);
		if (wasSatisfied && !isS)
		    state->values[i] = backup;
		else
		{
		    wasSatisfied = isS;
		    if (*distance < bestDist)
		    {
			better = true;
			change = true;
			bestDist = *distance;
		    }
		    else
			state->values[i] = backup;
		}
	    }

	    better = true;
	    while (better)
	    {
		better = false;
		double backup = state->values[i];
		state->values[i] *= factorM;
		bool isS = goal_r->isSatisfied(state, distance);
		if (wasSatisfied && !isS)
		    state->values[i] = backup;
		else
		{
		    wasSatisfied = isS;
		    if (*distance < bestDist)
		    {
			better = true;
			change = true;
			bestDist = *distance;
		    }
		    else
			state->values[i] = backup;
		}
	    }
	}
    }

    *distance = bestDist;
    return wasSatisfied && si->isValid(static_cast<SpaceInformationKinematic::StateKinematic_t>(state));
}
<commit_msg><commit_after>/*********************************************************************
* Software License Agreement (BSD License)
*
*  Copyright (c) 2008, 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 the Willow Garage 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.
*********************************************************************/

/* \author Ioan Sucan */

#include "ompl/extension/samplingbased/kinematic/extension/ik/GAIK.h"
#include <algorithm>

bool ompl::GAIK::solve(double solveTime)
{
    SpaceInformationKinematic_t                          si = dynamic_cast<SpaceInformationKinematic_t>(m_si);
    SpaceInformationKinematic::GoalRegionKinematic_t goal_r = dynamic_cast<SpaceInformationKinematic::GoalRegionKinematic_t>(si->getGoal());
    unsigned int                                        dim = si->getStateDimension();

    if (!goal_r)
    {
	m_msg.error("GAIK: Unknown type of goal (or goal undefined)");
	return false;
    }

    time_utils::Time        endTime = time_utils::Time::now() + time_utils::Duration(solveTime);

    unsigned int            maxPoolSize = m_poolSize + m_poolExpansion;
    std::vector<Individual> pool(maxPoolSize);
    IndividualSort          gs;
    bool                    solved = false;
    int                     solution = -1;

    if (m_poolSize < 1)
    {
	m_msg.error("GAIK: Pool size too small");
	return false;
    }

    for (unsigned int i = 0 ; i < maxPoolSize ; ++i)
    {
	pool[i].state = new SpaceInformationKinematic::StateKinematic(dim);
	si->sample(pool[i].state);
	if (goal_r->isSatisfied(pool[i].state, &(pool[i].distance)))
	{
	    if (si->isValid(static_cast<SpaceInformationKinematic::StateKinematic_t>(pool[i].state)))
	    {
		solved = true;
		solution = i;
	    }
	}
    }

    unsigned int generations = 1;

    std::vector<double> range(dim);
    for (unsigned int i = 0 ; i < dim ; ++i)
	range[i] = m_rho * (si->getStateComponent(i).maxValue - si->getStateComponent(i).minValue);

    while (!solved && time_utils::Time::now() < endTime)
    {
	generations++;
	std::sort(pool.begin(), pool.end(), gs);

	for (unsigned int i = m_poolSize ; i < maxPoolSize ; ++i)
	{
	    si->sampleNear(pool[i].state, pool[i%m_poolSize].state, range);
	    if (goal_r->isSatisfied(pool[i].state, &(pool[i].distance)))
	    {
		if (si->isValid(static_cast<SpaceInformationKinematic::StateKinematic_t>(pool[i].state)))
		{
		    solved = true;
		    solution = i;
		    break;
		}
	    }
	}
    }

    m_msg.inform("GAIK: Ran for %u generations", generations);

    if (solved)
    {
	SpaceInformationKinematic::PathKinematic_t path = new SpaceInformationKinematic::PathKinematic(m_si);
	SpaceInformationKinematic::StateKinematic_t st = new SpaceInformationKinematic::StateKinematic(dim);
	si->copyState(st, pool[solution].state);
	path->states.push_back(st);
	goal_r->setDifference(pool[solution].distance);
	goal_r->setSolutionPath(path);

	double dist = goal_r->getDifference();
	tryToSolve(path->states[0], &dist);
	goal_r->setDifference(dist);

    }
    else
    {
	/* find an approximate solution */
	std::sort(pool.begin(), pool.end(), gs);
	for (unsigned int i = 0 ; i < 5 ; ++i)
	{
	    if (si->isValid(static_cast<SpaceInformationKinematic::StateKinematic_t>(pool[i].state)))
	    {
		SpaceInformationKinematic::PathKinematic_t path = new SpaceInformationKinematic::PathKinematic(m_si);
		SpaceInformationKinematic::StateKinematic_t st = new SpaceInformationKinematic::StateKinematic(dim);
		si->copyState(st, pool[i].state);
		path->states.push_back(st);
		goal_r->setDifference(pool[i].distance);
		goal_r->setSolutionPath(path, true);

		double dist = goal_r->getDifference();
		tryToSolve(path->states[0], &dist);
		goal_r->setDifference(dist);

		break;
	    }
	}
    }

    for (unsigned int i = 0 ; i < maxPoolSize ; ++i)
	delete pool[i].state;

    return goal_r->isAchieved();
}

bool ompl::GAIK::tryToSolve(SpaceInformationKinematic::StateKinematic_t state, double *distance)
{
    tryToSolveFact(1.1, state, distance);
    tryToSolveFact(1.01, state, distance);
    tryToSolveFact(1.001, state, distance);
    tryToSolveFact(1.0001, state, distance);
    return true;
}

bool ompl::GAIK::tryToSolveFact(double factorP, SpaceInformationKinematic::StateKinematic_t state, double *distance)
{
    SpaceInformationKinematic_t                          si = dynamic_cast<SpaceInformationKinematic_t>(m_si);
    SpaceInformationKinematic::GoalRegionKinematic_t goal_r = dynamic_cast<SpaceInformationKinematic::GoalRegionKinematic_t>(si->getGoal());
    unsigned int                                        dim = si->getStateDimension();

    double factorM = 1.0/factorP;

    bool wasSatisfied = goal_r->isSatisfied(state, distance);
    double bestDist   = *distance;

    bool change = true;

    while (change)
    {
	change = false;

	for (unsigned int i = 0 ; i < dim ; ++i)
	{
	    bool better = true;
	    while (better)
	    {
		better = false;
		double backup = state->values[i];
		state->values[i] *= factorP;
		bool isS = goal_r->isSatisfied(state, distance);
		if (wasSatisfied && !isS)
		    state->values[i] = backup;
		else
		{
		    wasSatisfied = isS;
		    if (*distance < bestDist)
		    {
			better = true;
			change = true;
			bestDist = *distance;
		    }
		    else
			state->values[i] = backup;
		}
	    }

	    better = true;
	    while (better)
	    {
		better = false;
		double backup = state->values[i];
		state->values[i] *= factorM;
		bool isS = goal_r->isSatisfied(state, distance);
		if (wasSatisfied && !isS)
		    state->values[i] = backup;
		else
		{
		    wasSatisfied = isS;
		    if (*distance < bestDist)
		    {
			better = true;
			change = true;
			bestDist = *distance;
		    }
		    else
			state->values[i] = backup;
		}
	    }
	}
    }

    *distance = bestDist;
    return wasSatisfied && si->isValid(static_cast<SpaceInformationKinematic::StateKinematic_t>(state));
}
<|endoftext|>


<commit_before>#include "core/Loader.hpp"

namespace Kvant {

static std::vector<std::string> process_material_texture(aiMaterial *mat,
                                                         aiTextureType type,
                                                         std::string typeName) {
  std::vector<std::string> textures;

  for (unsigned int t = 0; t < mat->GetTextureCount(type); t++) {
    aiString str;
    mat->GetTexture(type, t, &str);
    textures.push_back(str.C_Str());
    LOG_DEBUG << str.C_Str() << " " << type << ", " << aiTextureType_SPECULAR;
  }
  return textures;
}

static void process_mesh(RawModelData *model_data, const aiScene *scene,
                         aiMesh *mesh) {
  auto mesh_cpy = std::make_unique<Mesh>();
  std::unordered_map<Kvant::Vertex, int> vs;
  unsigned int vi = 0;

  // Store Vertex data
  for (unsigned int i = 0; i < mesh->mNumVertices; i++) {
    Vertex vert;
    vert.position = {mesh->mVertices[i].x, mesh->mVertices[i].y,
                     mesh->mVertices[i].z};
    vert.normal = {mesh->mNormals[i].x, mesh->mNormals[i].y,
                   mesh->mNormals[i].z};

    if (mesh->mTextureCoords[0]) {
      vert.uvs = {mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y};
    } else {
      vert.uvs = {0.0f, 0.0f};
    }

    mesh_cpy->vertices.push_back(vert);
  }
  // Now wak through each of the mesh's faces (a face is a mesh its triangle)
  // and retrieve the corresponding vertex indices.
  for (unsigned int m = 0; m < mesh->mNumFaces; m++) {
    auto face = mesh->mFaces[m];
    // Retrieve all indices of the face and store them in the indices vector
    for (unsigned int i = 0; i < face.mNumIndices; i++) {
      mesh_cpy->triangles.push_back(face.mIndices[i]);
    }
  }
  // push our mesh to the model
  model_data->model.meshes.push_back(std::move(mesh_cpy));

  // Try read materials
  if (mesh->mMaterialIndex < 0)
    return; // No material exists
  auto *material = scene->mMaterials[mesh->mMaterialIndex];
  // We assume a convention for sampler names in the shaders. Each diffuse
  // texture should be named as 'texture_diffuseN' where N is a sequential
  // number ranging from 1 to MAX_SAMPLER_NUMBER. Same applies to other texture
  // as the following list summarizes: Diffuse: texture_diffuseN Specular:
  // texture_specularN Normal: texture_normalN

  // diffuse
  model_data->diffuses = process_material_texture(
      material, aiTextureType_DIFFUSE, "texture_diffuse");
  // normal
  model_data->normals = process_material_texture(
      material, aiTextureType_NORMALS, "texture_normal");
  // specular
  model_data->speculars = process_material_texture(
      material, aiTextureType_SPECULAR, "texture_specular");
}

static void process_node(RawModelData *model_data, const aiScene *scene,
                         aiNode *node) {
  // Process each mesh located at the current node
  LOG_DEBUG << "Processing node " << node->mName.C_Str()
            << " with meshes = " << node->mNumMeshes
            << " children = " << node->mNumChildren;
  for (unsigned int i = 0; i < node->mNumMeshes; i++) {
    // The node object only contains indices to index the actual objects in the
    // scene. The scene contains all the data, node is just to keep stuff
    // organized (like relations between nodes).
    aiMesh *mesh = scene->mMeshes[node->mMeshes[i]];
    process_mesh(model_data, scene, mesh);
  }

  // After we've processed all of the meshes (if any) we then recursively
  // process each of the children nodes
  for (unsigned int i = 0; i < node->mNumChildren; i++) {
    process_node(model_data, scene, node->mChildren[i]);
  }
}
RawModelData read_model(const char *filename) {
  RawModelData model_data;

  using namespace Assimp;

  Assimp::Importer importer;
  const aiScene *scene =
      importer.ReadFile(filename, aiProcess_Triangulate | aiProcess_FlipUVs);
  if (!scene) {
    throw std::runtime_error("Failed to load model " + std::string(filename));
  }

  process_node(&model_data, scene, scene->mRootNode);

  model_data.model.generate_tangents();
  return model_data;
}

bool load_png_for_texture(unsigned char **img, unsigned int *width,
                          unsigned int *height, const char *filename) {
  bool success = false;
  unsigned error = lodepng_decode32_file(img, width, height, filename);
  if (error) {
    std::runtime_error("Error loading image");
  } else {
    // Flip and invert the image
    unsigned char *imagePtr = *img;
    int halfTheHeightInPixels = *height / 2;
    int heightInPixels = *height;
    // Assume RGBA for 4 components per pixel
    int numColorComponents = 4;
    // Assuming each color component is an unsigned char
    int widthInChars = *width * numColorComponents;
    unsigned char *top = NULL;
    unsigned char *bottom = NULL;
    unsigned char temp = 0;
    for (int h = 0; h < halfTheHeightInPixels; ++h) {
      top = imagePtr + h * widthInChars;
      bottom = imagePtr + (heightInPixels - h - 1) * widthInChars;
      for (int w = 0; w < widthInChars; ++w) {
        // Swap the chars around.
        temp = *top;
        *top = *bottom;
        *bottom = temp;
        ++top;
        ++bottom;
      }
    }
    success = true;
  }

  return success;
}
} // namespace Kvant
<commit_msg>Pass texture name by reference<commit_after>#include "core/Loader.hpp"

namespace Kvant {

static std::vector<std::string>
process_material_texture(aiMaterial *mat, aiTextureType type,
                         const std::string &typeName) {
  std::vector<std::string> textures;

  for (unsigned int t = 0; t < mat->GetTextureCount(type); t++) {
    aiString str;
    mat->GetTexture(type, t, &str);
    textures.push_back(str.C_Str());
    LOG_DEBUG << str.C_Str() << " " << type << ", " << aiTextureType_SPECULAR;
  }
  return textures;
}

static void process_mesh(RawModelData *model_data, const aiScene *scene,
                         aiMesh *mesh) {
  auto mesh_cpy = std::make_unique<Mesh>();
  std::unordered_map<Kvant::Vertex, int> vs;
  unsigned int vi = 0;

  // Store Vertex data
  for (unsigned int i = 0; i < mesh->mNumVertices; i++) {
    Vertex vert;
    vert.position = {mesh->mVertices[i].x, mesh->mVertices[i].y,
                     mesh->mVertices[i].z};
    vert.normal = {mesh->mNormals[i].x, mesh->mNormals[i].y,
                   mesh->mNormals[i].z};

    if (mesh->mTextureCoords[0]) {
      vert.uvs = {mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y};
    } else {
      vert.uvs = {0.0f, 0.0f};
    }

    mesh_cpy->vertices.push_back(vert);
  }
  // Now wak through each of the mesh's faces (a face is a mesh its triangle)
  // and retrieve the corresponding vertex indices.
  for (unsigned int m = 0; m < mesh->mNumFaces; m++) {
    auto face = mesh->mFaces[m];
    // Retrieve all indices of the face and store them in the indices vector
    for (unsigned int i = 0; i < face.mNumIndices; i++) {
      mesh_cpy->triangles.push_back(face.mIndices[i]);
    }
  }
  // push our mesh to the model
  model_data->model.meshes.push_back(std::move(mesh_cpy));

  // Try read materials
  if (mesh->mMaterialIndex < 0)
    return; // No material exists
  auto *material = scene->mMaterials[mesh->mMaterialIndex];
  // We assume a convention for sampler names in the shaders. Each diffuse
  // texture should be named as 'texture_diffuseN' where N is a sequential
  // number ranging from 1 to MAX_SAMPLER_NUMBER. Same applies to other texture
  // as the following list summarizes: Diffuse: texture_diffuseN Specular:
  // texture_specularN Normal: texture_normalN

  // diffuse
  model_data->diffuses = process_material_texture(
      material, aiTextureType_DIFFUSE, "texture_diffuse");
  // normal
  model_data->normals = process_material_texture(
      material, aiTextureType_NORMALS, "texture_normal");
  // specular
  model_data->speculars = process_material_texture(
      material, aiTextureType_SPECULAR, "texture_specular");
}

static void process_node(RawModelData *model_data, const aiScene *scene,
                         aiNode *node) {
  // Process each mesh located at the current node
  LOG_DEBUG << "Processing node " << node->mName.C_Str()
            << " with meshes = " << node->mNumMeshes
            << " children = " << node->mNumChildren;
  for (unsigned int i = 0; i < node->mNumMeshes; i++) {
    // The node object only contains indices to index the actual objects in the
    // scene. The scene contains all the data, node is just to keep stuff
    // organized (like relations between nodes).
    aiMesh *mesh = scene->mMeshes[node->mMeshes[i]];
    process_mesh(model_data, scene, mesh);
  }

  // After we've processed all of the meshes (if any) we then recursively
  // process each of the children nodes
  for (unsigned int i = 0; i < node->mNumChildren; i++) {
    process_node(model_data, scene, node->mChildren[i]);
  }
}
RawModelData read_model(const char *filename) {
  RawModelData model_data;

  using namespace Assimp;

  Assimp::Importer importer;
  const aiScene *scene =
      importer.ReadFile(filename, aiProcess_Triangulate | aiProcess_FlipUVs);
  if (!scene) {
    throw std::runtime_error("Failed to load model " + std::string(filename));
  }

  process_node(&model_data, scene, scene->mRootNode);

  model_data.model.generate_tangents();
  return model_data;
}

bool load_png_for_texture(unsigned char **img, unsigned int *width,
                          unsigned int *height, const char *filename) {
  bool success = false;
  unsigned error = lodepng_decode32_file(img, width, height, filename);
  if (error) {
    std::runtime_error("Error loading image");
  } else {
    // Flip and invert the image
    unsigned char *imagePtr = *img;
    int halfTheHeightInPixels = *height / 2;
    int heightInPixels = *height;
    // Assume RGBA for 4 components per pixel
    int numColorComponents = 4;
    // Assuming each color component is an unsigned char
    int widthInChars = *width * numColorComponents;
    unsigned char *top = NULL;
    unsigned char *bottom = NULL;
    unsigned char temp = 0;
    for (int h = 0; h < halfTheHeightInPixels; ++h) {
      top = imagePtr + h * widthInChars;
      bottom = imagePtr + (heightInPixels - h - 1) * widthInChars;
      for (int w = 0; w < widthInChars; ++w) {
        // Swap the chars around.
        temp = *top;
        *top = *bottom;
        *bottom = temp;
        ++top;
        ++bottom;
      }
    }
    success = true;
  }

  return success;
}
} // namespace Kvant
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2011 Apple 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:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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 "config.h"
#include "platform/scroll/ScrollbarTheme.h"

#include "RuntimeEnabledFeatures.h"
#include "platform/scroll/ScrollbarThemeClient.h"
#include "platform/scroll/ScrollbarThemeMock.h"
#include "platform/scroll/ScrollbarThemeOverlayMock.h"

namespace WebCore {

ScrollbarTheme* ScrollbarTheme::theme()
{
    if (ScrollbarTheme::mockScrollbarsEnabled()) {
        if (RuntimeEnabledFeatures::overlayScrollbarsEnabled()) {
            DEFINE_STATIC_LOCAL(ScrollbarThemeOverlayMock, overlayMockTheme, ());
            return &overlayMockTheme;
        }

        DEFINE_STATIC_LOCAL(ScrollbarThemeMock, mockTheme, ());
        return &mockTheme;
    }
    return nativeTheme();
}

bool ScrollbarTheme::gMockScrollbarsEnabled = false;

void ScrollbarTheme::setMockScrollbarsEnabled(bool flag)
{
    gMockScrollbarsEnabled = flag;
}

bool ScrollbarTheme::mockScrollbarsEnabled()
{
    return gMockScrollbarsEnabled;
}

bool ScrollbarTheme::paint(ScrollbarThemeClient* scrollbar, GraphicsContext* graphicsContext, const IntRect& damageRect)
{
    // Create the ScrollbarControlPartMask based on the damageRect
    ScrollbarControlPartMask scrollMask = NoPart;

    IntRect backButtonStartPaintRect;
    IntRect backButtonEndPaintRect;
    IntRect forwardButtonStartPaintRect;
    IntRect forwardButtonEndPaintRect;
    if (hasButtons(scrollbar)) {
        backButtonStartPaintRect = backButtonRect(scrollbar, BackButtonStartPart, true);
        if (damageRect.intersects(backButtonStartPaintRect))
            scrollMask |= BackButtonStartPart;
        backButtonEndPaintRect = backButtonRect(scrollbar, BackButtonEndPart, true);
        if (damageRect.intersects(backButtonEndPaintRect))
            scrollMask |= BackButtonEndPart;
        forwardButtonStartPaintRect = forwardButtonRect(scrollbar, ForwardButtonStartPart, true);
        if (damageRect.intersects(forwardButtonStartPaintRect))
            scrollMask |= ForwardButtonStartPart;
        forwardButtonEndPaintRect = forwardButtonRect(scrollbar, ForwardButtonEndPart, true);
        if (damageRect.intersects(forwardButtonEndPaintRect))
            scrollMask |= ForwardButtonEndPart;
    }

    IntRect startTrackRect;
    IntRect thumbRect;
    IntRect endTrackRect;
    IntRect trackPaintRect = trackRect(scrollbar, true);
    if (damageRect.intersects(trackPaintRect))
        scrollMask |= TrackBGPart;
    bool thumbPresent = hasThumb(scrollbar);
    if (thumbPresent) {
        IntRect track = trackRect(scrollbar);
        splitTrack(scrollbar, track, startTrackRect, thumbRect, endTrackRect);
        if (damageRect.intersects(thumbRect))
            scrollMask |= ThumbPart;
        if (damageRect.intersects(startTrackRect))
            scrollMask |= BackTrackPart;
        if (damageRect.intersects(endTrackRect))
            scrollMask |= ForwardTrackPart;
    }

    // Paint the scrollbar background (only used by custom CSS scrollbars).
    paintScrollbarBackground(graphicsContext, scrollbar);

    // Paint the back and forward buttons.
    if (scrollMask & BackButtonStartPart)
        paintButton(graphicsContext, scrollbar, backButtonStartPaintRect, BackButtonStartPart);
    if (scrollMask & BackButtonEndPart)
        paintButton(graphicsContext, scrollbar, backButtonEndPaintRect, BackButtonEndPart);
    if (scrollMask & ForwardButtonStartPart)
        paintButton(graphicsContext, scrollbar, forwardButtonStartPaintRect, ForwardButtonStartPart);
    if (scrollMask & ForwardButtonEndPart)
        paintButton(graphicsContext, scrollbar, forwardButtonEndPaintRect, ForwardButtonEndPart);

    if (scrollMask & TrackBGPart)
        paintTrackBackground(graphicsContext, scrollbar, trackPaintRect);

    if ((scrollMask & ForwardTrackPart) || (scrollMask & BackTrackPart)) {
        // Paint the track pieces above and below the thumb.
        if (scrollMask & BackTrackPart)
            paintTrackPiece(graphicsContext, scrollbar, startTrackRect, BackTrackPart);
        if (scrollMask & ForwardTrackPart)
            paintTrackPiece(graphicsContext, scrollbar, endTrackRect, ForwardTrackPart);

        paintTickmarks(graphicsContext, scrollbar, trackPaintRect);
    }

    // Paint the thumb.
    if (scrollMask & ThumbPart)
        paintThumb(graphicsContext, scrollbar, thumbRect);

    return true;
}

ScrollbarPart ScrollbarTheme::hitTest(ScrollbarThemeClient* scrollbar, const IntPoint& position)
{
    ScrollbarPart result = NoPart;
    if (!scrollbar->enabled())
        return result;

    IntPoint testPosition = scrollbar->convertFromContainingWindow(position);
    testPosition.move(scrollbar->x(), scrollbar->y());

    if (!scrollbar->frameRect().contains(testPosition))
        return NoPart;

    result = ScrollbarBGPart;

    IntRect track = trackRect(scrollbar);
    if (track.contains(testPosition)) {
        IntRect beforeThumbRect;
        IntRect thumbRect;
        IntRect afterThumbRect;
        splitTrack(scrollbar, track, beforeThumbRect, thumbRect, afterThumbRect);
        if (thumbRect.contains(testPosition))
            result = ThumbPart;
        else if (beforeThumbRect.contains(testPosition))
            result = BackTrackPart;
        else if (afterThumbRect.contains(testPosition))
            result = ForwardTrackPart;
        else
            result = TrackBGPart;
    } else if (backButtonRect(scrollbar, BackButtonStartPart).contains(testPosition)) {
        result = BackButtonStartPart;
    } else if (backButtonRect(scrollbar, BackButtonEndPart).contains(testPosition)) {
        result = BackButtonEndPart;
    } else if (forwardButtonRect(scrollbar, ForwardButtonStartPart).contains(testPosition)) {
        result = ForwardButtonStartPart;
    } else if (forwardButtonRect(scrollbar, ForwardButtonEndPart).contains(testPosition)) {
        result = ForwardButtonEndPart;
    }
    return result;
}

void ScrollbarTheme::invalidatePart(ScrollbarThemeClient* scrollbar, ScrollbarPart part)
{
    if (part == NoPart)
        return;

    IntRect result;
    switch (part) {
    case BackButtonStartPart:
        result = backButtonRect(scrollbar, BackButtonStartPart, true);
        break;
    case BackButtonEndPart:
        result = backButtonRect(scrollbar, BackButtonEndPart, true);
        break;
    case ForwardButtonStartPart:
        result = forwardButtonRect(scrollbar, ForwardButtonStartPart, true);
        break;
    case ForwardButtonEndPart:
        result = forwardButtonRect(scrollbar, ForwardButtonEndPart, true);
        break;
    case TrackBGPart:
        result = trackRect(scrollbar, true);
        break;
    case ScrollbarBGPart:
        result = scrollbar->frameRect();
        break;
    default: {
        IntRect beforeThumbRect, thumbRect, afterThumbRect;
        splitTrack(scrollbar, trackRect(scrollbar), beforeThumbRect, thumbRect, afterThumbRect);
        if (part == BackTrackPart)
            result = beforeThumbRect;
        else if (part == ForwardTrackPart)
            result = afterThumbRect;
        else
            result = thumbRect;
    }
    }
    result.moveBy(-scrollbar->location());
    scrollbar->invalidateRect(result);
}

void ScrollbarTheme::splitTrack(ScrollbarThemeClient* scrollbar, const IntRect& unconstrainedTrackRect, IntRect& beforeThumbRect, IntRect& thumbRect, IntRect& afterThumbRect)
{
    // This function won't even get called unless we're big enough to have some combination of these three rects where at least
    // one of them is non-empty.
    IntRect trackRect = constrainTrackRectToTrackPieces(scrollbar, unconstrainedTrackRect);
    int thumbPos = thumbPosition(scrollbar);
    if (scrollbar->orientation() == HorizontalScrollbar) {
        thumbRect = IntRect(trackRect.x() + thumbPos, trackRect.y(), thumbLength(scrollbar), scrollbar->height());
        beforeThumbRect = IntRect(trackRect.x(), trackRect.y(), thumbPos + thumbRect.width() / 2, trackRect.height());
        afterThumbRect = IntRect(trackRect.x() + beforeThumbRect.width(), trackRect.y(), trackRect.maxX() - beforeThumbRect.maxX(), trackRect.height());
    } else {
        thumbRect = IntRect(trackRect.x(), trackRect.y() + thumbPos, scrollbar->width(), thumbLength(scrollbar));
        beforeThumbRect = IntRect(trackRect.x(), trackRect.y(), trackRect.width(), thumbPos + thumbRect.height() / 2);
        afterThumbRect = IntRect(trackRect.x(), trackRect.y() + beforeThumbRect.height(), trackRect.width(), trackRect.maxY() - beforeThumbRect.maxY());
    }
}

// Returns the size represented by track taking into account scrolling past
// the end of the document.
static float usedTotalSize(ScrollbarThemeClient* scrollbar)
{
    float overhangAtStart = -scrollbar->currentPos();
    float overhangAtEnd = scrollbar->currentPos() + scrollbar->visibleSize() - scrollbar->totalSize();
    float overhang = std::max(0.0f, std::max(overhangAtStart, overhangAtEnd));
    return scrollbar->totalSize() + overhang;
}

int ScrollbarTheme::thumbPosition(ScrollbarThemeClient* scrollbar)
{
    if (scrollbar->enabled()) {
        float size = usedTotalSize(scrollbar) - scrollbar->visibleSize();
        // Avoid doing a floating point divide by zero and return 1 when usedTotalSize == visibleSize.
        if (!size)
            return 1;
        float pos = std::max(0.0f, scrollbar->currentPos()) * (trackLength(scrollbar) - thumbLength(scrollbar)) / size;
        return (pos < 1 && pos > 0) ? 1 : pos;
    }
    return 0;
}

int ScrollbarTheme::thumbLength(ScrollbarThemeClient* scrollbar)
{
    if (!scrollbar->enabled())
        return 0;

    float overhang = 0;
    if (scrollbar->currentPos() < 0)
        overhang = -scrollbar->currentPos();
    else if (scrollbar->visibleSize() + scrollbar->currentPos() > scrollbar->totalSize())
        overhang = scrollbar->currentPos() + scrollbar->visibleSize() - scrollbar->totalSize();
    float proportion = (scrollbar->visibleSize() - overhang) / usedTotalSize(scrollbar);
    int trackLen = trackLength(scrollbar);
    int length = round(proportion * trackLen);
    length = std::max(length, minimumThumbLength(scrollbar));
    if (length > trackLen)
        length = 0; // Once the thumb is below the track length, it just goes away (to make more room for the track).
    return length;
}

int ScrollbarTheme::minimumThumbLength(ScrollbarThemeClient* scrollbar)
{
    return scrollbarThickness(scrollbar->controlSize());
}

int ScrollbarTheme::trackPosition(ScrollbarThemeClient* scrollbar)
{
    IntRect constrainedTrackRect = constrainTrackRectToTrackPieces(scrollbar, trackRect(scrollbar));
    return (scrollbar->orientation() == HorizontalScrollbar) ? constrainedTrackRect.x() - scrollbar->x() : constrainedTrackRect.y() - scrollbar->y();
}

int ScrollbarTheme::trackLength(ScrollbarThemeClient* scrollbar)
{
    IntRect constrainedTrackRect = constrainTrackRectToTrackPieces(scrollbar, trackRect(scrollbar));
    return (scrollbar->orientation() == HorizontalScrollbar) ? constrainedTrackRect.width() : constrainedTrackRect.height();
}

void ScrollbarTheme::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
{
    context->fillRect(cornerRect, Color::white);
}

IntRect ScrollbarTheme::thumbRect(ScrollbarThemeClient* scrollbar)
{
    if (!hasThumb(scrollbar))
        return IntRect();

    IntRect track = trackRect(scrollbar);
    IntRect startTrackRect;
    IntRect thumbRect;
    IntRect endTrackRect;
    splitTrack(scrollbar, track, startTrackRect, thumbRect, endTrackRect);

    return thumbRect;
}

int ScrollbarTheme::thumbThickness(ScrollbarThemeClient* scrollbar)
{
    IntRect track = trackRect(scrollbar);
    return scrollbar->orientation() == HorizontalScrollbar ? track.height() : track.width();
}

void ScrollbarTheme::paintOverhangBackground(GraphicsContext* context, const IntRect& horizontalOverhangRect, const IntRect& verticalOverhangRect, const IntRect& dirtyRect)
{
    context->setFillColor(Color::white);
    if (!horizontalOverhangRect.isEmpty())
        context->fillRect(intersection(horizontalOverhangRect, dirtyRect));
    if (!verticalOverhangRect.isEmpty())
        context->fillRect(intersection(verticalOverhangRect, dirtyRect));
}

}
<commit_msg>Makes ScrollbarTheme call through to theme engine for corner (2)<commit_after>/*
 * Copyright (C) 2011 Apple 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:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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 "config.h"
#include "platform/scroll/ScrollbarTheme.h"

#include "RuntimeEnabledFeatures.h"
#include "platform/scroll/ScrollbarThemeClient.h"
#include "platform/scroll/ScrollbarThemeMock.h"
#include "platform/scroll/ScrollbarThemeOverlayMock.h"

#if !OS(MACOSX)
#include "public/platform/Platform.h"
#include "public/platform/WebRect.h"
#include "public/platform/default/WebThemeEngine.h"
#endif

namespace WebCore {

ScrollbarTheme* ScrollbarTheme::theme()
{
    if (ScrollbarTheme::mockScrollbarsEnabled()) {
        if (RuntimeEnabledFeatures::overlayScrollbarsEnabled()) {
            DEFINE_STATIC_LOCAL(ScrollbarThemeOverlayMock, overlayMockTheme, ());
            return &overlayMockTheme;
        }

        DEFINE_STATIC_LOCAL(ScrollbarThemeMock, mockTheme, ());
        return &mockTheme;
    }
    return nativeTheme();
}

bool ScrollbarTheme::gMockScrollbarsEnabled = false;

void ScrollbarTheme::setMockScrollbarsEnabled(bool flag)
{
    gMockScrollbarsEnabled = flag;
}

bool ScrollbarTheme::mockScrollbarsEnabled()
{
    return gMockScrollbarsEnabled;
}

bool ScrollbarTheme::paint(ScrollbarThemeClient* scrollbar, GraphicsContext* graphicsContext, const IntRect& damageRect)
{
    // Create the ScrollbarControlPartMask based on the damageRect
    ScrollbarControlPartMask scrollMask = NoPart;

    IntRect backButtonStartPaintRect;
    IntRect backButtonEndPaintRect;
    IntRect forwardButtonStartPaintRect;
    IntRect forwardButtonEndPaintRect;
    if (hasButtons(scrollbar)) {
        backButtonStartPaintRect = backButtonRect(scrollbar, BackButtonStartPart, true);
        if (damageRect.intersects(backButtonStartPaintRect))
            scrollMask |= BackButtonStartPart;
        backButtonEndPaintRect = backButtonRect(scrollbar, BackButtonEndPart, true);
        if (damageRect.intersects(backButtonEndPaintRect))
            scrollMask |= BackButtonEndPart;
        forwardButtonStartPaintRect = forwardButtonRect(scrollbar, ForwardButtonStartPart, true);
        if (damageRect.intersects(forwardButtonStartPaintRect))
            scrollMask |= ForwardButtonStartPart;
        forwardButtonEndPaintRect = forwardButtonRect(scrollbar, ForwardButtonEndPart, true);
        if (damageRect.intersects(forwardButtonEndPaintRect))
            scrollMask |= ForwardButtonEndPart;
    }

    IntRect startTrackRect;
    IntRect thumbRect;
    IntRect endTrackRect;
    IntRect trackPaintRect = trackRect(scrollbar, true);
    if (damageRect.intersects(trackPaintRect))
        scrollMask |= TrackBGPart;
    bool thumbPresent = hasThumb(scrollbar);
    if (thumbPresent) {
        IntRect track = trackRect(scrollbar);
        splitTrack(scrollbar, track, startTrackRect, thumbRect, endTrackRect);
        if (damageRect.intersects(thumbRect))
            scrollMask |= ThumbPart;
        if (damageRect.intersects(startTrackRect))
            scrollMask |= BackTrackPart;
        if (damageRect.intersects(endTrackRect))
            scrollMask |= ForwardTrackPart;
    }

    // Paint the scrollbar background (only used by custom CSS scrollbars).
    paintScrollbarBackground(graphicsContext, scrollbar);

    // Paint the back and forward buttons.
    if (scrollMask & BackButtonStartPart)
        paintButton(graphicsContext, scrollbar, backButtonStartPaintRect, BackButtonStartPart);
    if (scrollMask & BackButtonEndPart)
        paintButton(graphicsContext, scrollbar, backButtonEndPaintRect, BackButtonEndPart);
    if (scrollMask & ForwardButtonStartPart)
        paintButton(graphicsContext, scrollbar, forwardButtonStartPaintRect, ForwardButtonStartPart);
    if (scrollMask & ForwardButtonEndPart)
        paintButton(graphicsContext, scrollbar, forwardButtonEndPaintRect, ForwardButtonEndPart);

    if (scrollMask & TrackBGPart)
        paintTrackBackground(graphicsContext, scrollbar, trackPaintRect);

    if ((scrollMask & ForwardTrackPart) || (scrollMask & BackTrackPart)) {
        // Paint the track pieces above and below the thumb.
        if (scrollMask & BackTrackPart)
            paintTrackPiece(graphicsContext, scrollbar, startTrackRect, BackTrackPart);
        if (scrollMask & ForwardTrackPart)
            paintTrackPiece(graphicsContext, scrollbar, endTrackRect, ForwardTrackPart);

        paintTickmarks(graphicsContext, scrollbar, trackPaintRect);
    }

    // Paint the thumb.
    if (scrollMask & ThumbPart)
        paintThumb(graphicsContext, scrollbar, thumbRect);

    return true;
}

ScrollbarPart ScrollbarTheme::hitTest(ScrollbarThemeClient* scrollbar, const IntPoint& position)
{
    ScrollbarPart result = NoPart;
    if (!scrollbar->enabled())
        return result;

    IntPoint testPosition = scrollbar->convertFromContainingWindow(position);
    testPosition.move(scrollbar->x(), scrollbar->y());

    if (!scrollbar->frameRect().contains(testPosition))
        return NoPart;

    result = ScrollbarBGPart;

    IntRect track = trackRect(scrollbar);
    if (track.contains(testPosition)) {
        IntRect beforeThumbRect;
        IntRect thumbRect;
        IntRect afterThumbRect;
        splitTrack(scrollbar, track, beforeThumbRect, thumbRect, afterThumbRect);
        if (thumbRect.contains(testPosition))
            result = ThumbPart;
        else if (beforeThumbRect.contains(testPosition))
            result = BackTrackPart;
        else if (afterThumbRect.contains(testPosition))
            result = ForwardTrackPart;
        else
            result = TrackBGPart;
    } else if (backButtonRect(scrollbar, BackButtonStartPart).contains(testPosition)) {
        result = BackButtonStartPart;
    } else if (backButtonRect(scrollbar, BackButtonEndPart).contains(testPosition)) {
        result = BackButtonEndPart;
    } else if (forwardButtonRect(scrollbar, ForwardButtonStartPart).contains(testPosition)) {
        result = ForwardButtonStartPart;
    } else if (forwardButtonRect(scrollbar, ForwardButtonEndPart).contains(testPosition)) {
        result = ForwardButtonEndPart;
    }
    return result;
}

void ScrollbarTheme::invalidatePart(ScrollbarThemeClient* scrollbar, ScrollbarPart part)
{
    if (part == NoPart)
        return;

    IntRect result;
    switch (part) {
    case BackButtonStartPart:
        result = backButtonRect(scrollbar, BackButtonStartPart, true);
        break;
    case BackButtonEndPart:
        result = backButtonRect(scrollbar, BackButtonEndPart, true);
        break;
    case ForwardButtonStartPart:
        result = forwardButtonRect(scrollbar, ForwardButtonStartPart, true);
        break;
    case ForwardButtonEndPart:
        result = forwardButtonRect(scrollbar, ForwardButtonEndPart, true);
        break;
    case TrackBGPart:
        result = trackRect(scrollbar, true);
        break;
    case ScrollbarBGPart:
        result = scrollbar->frameRect();
        break;
    default: {
        IntRect beforeThumbRect, thumbRect, afterThumbRect;
        splitTrack(scrollbar, trackRect(scrollbar), beforeThumbRect, thumbRect, afterThumbRect);
        if (part == BackTrackPart)
            result = beforeThumbRect;
        else if (part == ForwardTrackPart)
            result = afterThumbRect;
        else
            result = thumbRect;
    }
    }
    result.moveBy(-scrollbar->location());
    scrollbar->invalidateRect(result);
}

void ScrollbarTheme::splitTrack(ScrollbarThemeClient* scrollbar, const IntRect& unconstrainedTrackRect, IntRect& beforeThumbRect, IntRect& thumbRect, IntRect& afterThumbRect)
{
    // This function won't even get called unless we're big enough to have some combination of these three rects where at least
    // one of them is non-empty.
    IntRect trackRect = constrainTrackRectToTrackPieces(scrollbar, unconstrainedTrackRect);
    int thumbPos = thumbPosition(scrollbar);
    if (scrollbar->orientation() == HorizontalScrollbar) {
        thumbRect = IntRect(trackRect.x() + thumbPos, trackRect.y(), thumbLength(scrollbar), scrollbar->height());
        beforeThumbRect = IntRect(trackRect.x(), trackRect.y(), thumbPos + thumbRect.width() / 2, trackRect.height());
        afterThumbRect = IntRect(trackRect.x() + beforeThumbRect.width(), trackRect.y(), trackRect.maxX() - beforeThumbRect.maxX(), trackRect.height());
    } else {
        thumbRect = IntRect(trackRect.x(), trackRect.y() + thumbPos, scrollbar->width(), thumbLength(scrollbar));
        beforeThumbRect = IntRect(trackRect.x(), trackRect.y(), trackRect.width(), thumbPos + thumbRect.height() / 2);
        afterThumbRect = IntRect(trackRect.x(), trackRect.y() + beforeThumbRect.height(), trackRect.width(), trackRect.maxY() - beforeThumbRect.maxY());
    }
}

// Returns the size represented by track taking into account scrolling past
// the end of the document.
static float usedTotalSize(ScrollbarThemeClient* scrollbar)
{
    float overhangAtStart = -scrollbar->currentPos();
    float overhangAtEnd = scrollbar->currentPos() + scrollbar->visibleSize() - scrollbar->totalSize();
    float overhang = std::max(0.0f, std::max(overhangAtStart, overhangAtEnd));
    return scrollbar->totalSize() + overhang;
}

int ScrollbarTheme::thumbPosition(ScrollbarThemeClient* scrollbar)
{
    if (scrollbar->enabled()) {
        float size = usedTotalSize(scrollbar) - scrollbar->visibleSize();
        // Avoid doing a floating point divide by zero and return 1 when usedTotalSize == visibleSize.
        if (!size)
            return 1;
        float pos = std::max(0.0f, scrollbar->currentPos()) * (trackLength(scrollbar) - thumbLength(scrollbar)) / size;
        return (pos < 1 && pos > 0) ? 1 : pos;
    }
    return 0;
}

int ScrollbarTheme::thumbLength(ScrollbarThemeClient* scrollbar)
{
    if (!scrollbar->enabled())
        return 0;

    float overhang = 0;
    if (scrollbar->currentPos() < 0)
        overhang = -scrollbar->currentPos();
    else if (scrollbar->visibleSize() + scrollbar->currentPos() > scrollbar->totalSize())
        overhang = scrollbar->currentPos() + scrollbar->visibleSize() - scrollbar->totalSize();
    float proportion = (scrollbar->visibleSize() - overhang) / usedTotalSize(scrollbar);
    int trackLen = trackLength(scrollbar);
    int length = round(proportion * trackLen);
    length = std::max(length, minimumThumbLength(scrollbar));
    if (length > trackLen)
        length = 0; // Once the thumb is below the track length, it just goes away (to make more room for the track).
    return length;
}

int ScrollbarTheme::minimumThumbLength(ScrollbarThemeClient* scrollbar)
{
    return scrollbarThickness(scrollbar->controlSize());
}

int ScrollbarTheme::trackPosition(ScrollbarThemeClient* scrollbar)
{
    IntRect constrainedTrackRect = constrainTrackRectToTrackPieces(scrollbar, trackRect(scrollbar));
    return (scrollbar->orientation() == HorizontalScrollbar) ? constrainedTrackRect.x() - scrollbar->x() : constrainedTrackRect.y() - scrollbar->y();
}

int ScrollbarTheme::trackLength(ScrollbarThemeClient* scrollbar)
{
    IntRect constrainedTrackRect = constrainTrackRectToTrackPieces(scrollbar, trackRect(scrollbar));
    return (scrollbar->orientation() == HorizontalScrollbar) ? constrainedTrackRect.width() : constrainedTrackRect.height();
}

void ScrollbarTheme::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
{
    if (cornerRect.isEmpty())
        return;

#if OS(MACOSX)
    context->fillRect(cornerRect, Color::white);
#else
    blink::Platform::current()->themeEngine()->paint(context->canvas(), blink::WebThemeEngine::PartScrollbarCorner, blink::WebThemeEngine::StateNormal, blink::WebRect(cornerRect), 0);
#endif
}

IntRect ScrollbarTheme::thumbRect(ScrollbarThemeClient* scrollbar)
{
    if (!hasThumb(scrollbar))
        return IntRect();

    IntRect track = trackRect(scrollbar);
    IntRect startTrackRect;
    IntRect thumbRect;
    IntRect endTrackRect;
    splitTrack(scrollbar, track, startTrackRect, thumbRect, endTrackRect);

    return thumbRect;
}

int ScrollbarTheme::thumbThickness(ScrollbarThemeClient* scrollbar)
{
    IntRect track = trackRect(scrollbar);
    return scrollbar->orientation() == HorizontalScrollbar ? track.height() : track.width();
}

void ScrollbarTheme::paintOverhangBackground(GraphicsContext* context, const IntRect& horizontalOverhangRect, const IntRect& verticalOverhangRect, const IntRect& dirtyRect)
{
    context->setFillColor(Color::white);
    if (!horizontalOverhangRect.isEmpty())
        context->fillRect(intersection(horizontalOverhangRect, dirtyRect));
    if (!verticalOverhangRect.isEmpty())
        context->fillRect(intersection(verticalOverhangRect, dirtyRect));
}

}
<|endoftext|>


<commit_before><commit_msg>IWorkController interface<commit_after><|endoftext|>


<commit_before><commit_msg>Improved zlib error message<commit_after><|endoftext|>


<commit_before>/*
* Copyright (c) 2003-2011 Rony Shapiro <ronys@users.sourceforge.net>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/

#include "Report.h"
#include "Util.h"
#include "core.h"
#include "StringX.h"

#include "os/dir.h"
#include "os/debug.h"
#include "os/file.h"
#include "os/utf8conv.h"

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <errno.h>

#include <sstream>
#include <fstream>

const TCHAR *CRLF = _T("\r\n");

/*
  It writes a header record and a "Start Report" record.
*/
void CReport::StartReport(LPCTSTR tcAction, const stringT &csDataBase)
{
  m_osxs.str(_T(""));

  m_tcAction = tcAction;
  m_csDataBase = csDataBase;

  stringT cs_title, sTimeStamp;
  PWSUtil::GetTimeStamp(sTimeStamp);
  Format(cs_title, IDSC_REPORT_TITLE1, tcAction, sTimeStamp.c_str());
  WriteLine();
  WriteLine(cs_title);
  Format(cs_title, IDSC_REPORT_TITLE2, csDataBase.c_str());
  WriteLine(cs_title);
  WriteLine();
  LoadAString(cs_title, IDSC_START_REPORT);
  WriteLine(cs_title);
  WriteLine();
}

static bool isFileUnicode(const stringT &fname)
{
  struct _stat statbuf;

  int status = _tstat(fname.c_str(), &statbuf);
  // Need file to exist and length at least 2 for BOM
  if (status != 0 || statbuf.st_size < 2)
    return false;

  const unsigned char BOM[] = {0xff, 0xfe};
  unsigned char buffer[] = {0x00, 0x00};

  // Check if the first 2 characters are the BOM
  // Need to use FOpen as cannot pass wchar_t filename to a std::istream
  // and cannot convert a wchar_t filename/path to char if non-Latin characters
  // present
  FILE *fn = pws_os::FOpen(fname.c_str(), _T("rb"));
  fread(buffer, 1, 2, fn);
  fclose(fn);

  return (buffer[0] == BOM[0] && buffer[1] == BOM[1]);
}

/*
  SaveToDisk creates a new file of name "<tcAction>_Report.txt" e.g. "Merge_Report.txt"
  in the same directory as the current database or appends to this file if it already exists.
*/
bool CReport::SaveToDisk()
{
  FILE *fd;

  stringT path(m_csDataBase);
  stringT drive, dir, file, ext;
  if (!pws_os::splitpath(path, drive, dir, file, ext)) {
    pws_os::IssueError(_T("StartReport: Finding path to database"));
    return false;
  }

  Format(m_cs_filename, IDSC_REPORTFILENAME,
         drive.c_str(), dir.c_str(), m_tcAction.c_str());

  if ((fd = pws_os::FOpen(m_cs_filename, _T("a+b"))) == NULL) {
    pws_os::IssueError(_T("StartReport: Opening log file"));
    return false;
  }

  // **** MOST LIKELY ACTION ****
  // If file is new/emtpy AND we are UNICODE, write BOM, as some text editors insist!

  // **** LEAST LIKELY ACTIONS as it requires the user to use both U & NU versions ****
  // Text editors really don't like files with both UNICODE and ASCII characters, so -
  // If we are UNICODE and file is not, convert file to UNICODE before appending
  // If we are not UNICODE but file is, convert file to ASCII before appending

  bool bFileIsUnicode = isFileUnicode(m_cs_filename);

#ifdef UNICODE
  const unsigned int iBOM = 0xFEFF;
  if (pws_os::fileLength(fd) == 0) {
    // File is empty - write BOM
    putwc(iBOM, fd);
  } else
    if (!bFileIsUnicode) {
      // Convert ASCII contents to UNICODE
      // Close original first
      fclose(fd);

      // Open again to read
      FILE *f_in = pws_os::FOpen(m_cs_filename, _S("rb"));

      // Open new file
      stringT cs_out = m_cs_filename + _S(".tmp");
      FILE *f_out = pws_os::FOpen(cs_out, _S("wb"));

      // Write BOM
      putwc(iBOM, f_out);

      size_t nBytesRead;
      unsigned char inbuffer[4096];
      wchar_t outwbuffer[4096];

      // Now copy
      do {
        nBytesRead = fread(inbuffer, sizeof(inbuffer), 1, f_in);

        if (nBytesRead > 0) {
          size_t len = pws_os::mbstowcs(outwbuffer, 4096, reinterpret_cast<const char *>(inbuffer), nBytesRead);
          if (len != 0)
            fwrite(outwbuffer, sizeof(outwbuffer[0])*len, 1, f_out);
        } else
          break;

      } while(nBytesRead > 0);

      // Close files
      fclose(f_in);
      fclose(f_out);

      // Swap them
      pws_os::RenameFile(cs_out, m_cs_filename);

      // Re-open file
      if ((fd = pws_os::FOpen(m_cs_filename, _S("ab"))) == NULL) {
        pws_os::IssueError(_T("StartReport: Opening log file"));
        return false;
      }
    }
#else
  if (bFileIsUnicode) {
    // Convert UNICODE contents to ASCII
    // Close original first
    fclose(fd);

    // Open again to read
    FILE *f_in = pws_os::FOpen(m_cs_filename, "rb");

    // Open new file
    stringT cs_out = m_cs_filename + _T(".tmp");
    FILE *f_out = pws_os::FOpen(cs_out, "wb");

    UINT nBytesRead;
    WCHAR inwbuffer[4096];
    unsigned char outbuffer[4096];

    // Skip over BOM
    fseek(f_in, 2, SEEK_SET);

    // Now copy
    do {
      nBytesRead = fread(inwbuffer, sizeof(inwbuffer[0])*sizeof(inwbuffer),
                         1, f_in);

      if (nBytesRead > 0) {
        size_t len = pws_os::wcstombs((char *)outbuffer, 4096,
                                      inwbuffer, nBytesRead);
        if (len != 0)
          fwrite(outbuffer, len, 1, f_out);
      } else
        break;

    } while(nBytesRead > 0);

    // Close files
    fclose(f_in);
    fclose(f_out);

    // Swap them
    pws_os::RenameFile(cs_out, m_cs_filename);

    // Re-open file
    if ((fd = pws_os::FOpen(m_cs_filename, _S("ab"))) == NULL) {
      pws_os::IssueError(_T("StartReport: Opening log file"));
      return false;
    }
  }
#endif
  StringX sx = m_osxs.rdbuf()->str();
  fwrite(reinterpret_cast<const void *>(sx.c_str()), sizeof(BYTE),
             sx.length() * sizeof(TCHAR), fd);
  fclose(fd);

  return true;
}

// Write a record with(default) or without a CRLF
void CReport::WriteLine(const stringT &cs_line, bool bCRLF)
{
  m_osxs << cs_line.c_str();
  if (bCRLF) {
    m_osxs << CRLF;
  }
}

// Write a record with (default) or without a CRLF
void CReport::WriteLine(const LPTSTR &tc_line, bool bCRLF)
{
  m_osxs << tc_line;
  if (bCRLF) {
    m_osxs << CRLF;
  }
}

// Write a new line
void CReport::WriteLine()
{
  m_osxs << CRLF;
}

//  EndReport writes a "End Report" record and closes the report file.
void CReport::EndReport()
{
  WriteLine();
  stringT cs_title;
  LoadAString(cs_title, IDSC_END_REPORT1);
  WriteLine(cs_title);
  LoadAString(cs_title, IDSC_END_REPORT2);
  WriteLine(cs_title);

  m_osxs.flush();
}
<commit_msg>Portability: rev 4211 should compile under Linux too.<commit_after>/*
* Copyright (c) 2003-2011 Rony Shapiro <ronys@users.sourceforge.net>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/

#include "Report.h"
#include "Util.h"
#include "core.h"
#include "StringX.h"

#include "os/dir.h"
#include "os/debug.h"
#include "os/file.h"
#include "os/utf8conv.h"

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

#include <sstream>
#include <fstream>

const TCHAR *CRLF = _T("\r\n");

/*
  It writes a header record and a "Start Report" record.
*/
void CReport::StartReport(LPCTSTR tcAction, const stringT &csDataBase)
{
  m_osxs.str(_T(""));

  m_tcAction = tcAction;
  m_csDataBase = csDataBase;

  stringT cs_title, sTimeStamp;
  PWSUtil::GetTimeStamp(sTimeStamp);
  Format(cs_title, IDSC_REPORT_TITLE1, tcAction, sTimeStamp.c_str());
  WriteLine();
  WriteLine(cs_title);
  Format(cs_title, IDSC_REPORT_TITLE2, csDataBase.c_str());
  WriteLine(cs_title);
  WriteLine();
  LoadAString(cs_title, IDSC_START_REPORT);
  WriteLine(cs_title);
  WriteLine();
}

static bool isFileUnicode(const stringT &fname)
{
  // Check if the first 2 characters are the BOM
  // (Need file to exist and length at least 2 for BOM)
  // Need to use FOpen as cannot pass wchar_t filename to a std::istream
  // and cannot convert a wchar_t filename/path to char if non-Latin characters
  // present
  const unsigned char BOM[] = {0xff, 0xfe};
  unsigned char buffer[] = {0x00, 0x00};
  bool retval = false;

  FILE *fn = pws_os::FOpen(fname, _T("rb"));
  if (fn == NULL)
    return false;
  if (pws_os::fileLength(fn) < 2)
    retval = false;
  else {
    fread(buffer, 1, 2, fn);
    retval = (buffer[0] == BOM[0] && buffer[1] == BOM[1]);
  }
  fclose(fn);
  return retval;
}

/*
  SaveToDisk creates a new file of name "<tcAction>_Report.txt" e.g. "Merge_Report.txt"
  in the same directory as the current database or appends to this file if it already exists.
*/
bool CReport::SaveToDisk()
{
  FILE *fd;

  stringT path(m_csDataBase);
  stringT drive, dir, file, ext;
  if (!pws_os::splitpath(path, drive, dir, file, ext)) {
    pws_os::IssueError(_T("StartReport: Finding path to database"));
    return false;
  }

  Format(m_cs_filename, IDSC_REPORTFILENAME,
         drive.c_str(), dir.c_str(), m_tcAction.c_str());

  if ((fd = pws_os::FOpen(m_cs_filename, _T("a+b"))) == NULL) {
    pws_os::IssueError(_T("StartReport: Opening log file"));
    return false;
  }

  // **** MOST LIKELY ACTION ****
  // If file is new/emtpy AND we are UNICODE, write BOM, as some text editors insist!

  // **** LEAST LIKELY ACTIONS as it requires the user to use both U & NU versions ****
  // Text editors really don't like files with both UNICODE and ASCII characters, so -
  // If we are UNICODE and file is not, convert file to UNICODE before appending
  // If we are not UNICODE but file is, convert file to ASCII before appending

  bool bFileIsUnicode = isFileUnicode(m_cs_filename);

#ifdef UNICODE
  const unsigned int iBOM = 0xFEFF;
  if (pws_os::fileLength(fd) == 0) {
    // File is empty - write BOM
    putwc(iBOM, fd);
  } else
    if (!bFileIsUnicode) {
      // Convert ASCII contents to UNICODE
      // Close original first
      fclose(fd);

      // Open again to read
      FILE *f_in = pws_os::FOpen(m_cs_filename, _S("rb"));

      // Open new file
      stringT cs_out = m_cs_filename + _S(".tmp");
      FILE *f_out = pws_os::FOpen(cs_out, _S("wb"));

      // Write BOM
      putwc(iBOM, f_out);

      size_t nBytesRead;
      unsigned char inbuffer[4096];
      wchar_t outwbuffer[4096];

      // Now copy
      do {
        nBytesRead = fread(inbuffer, sizeof(inbuffer), 1, f_in);

        if (nBytesRead > 0) {
          size_t len = pws_os::mbstowcs(outwbuffer, 4096, reinterpret_cast<const char *>(inbuffer), nBytesRead);
          if (len != 0)
            fwrite(outwbuffer, sizeof(outwbuffer[0])*len, 1, f_out);
        } else
          break;

      } while(nBytesRead > 0);

      // Close files
      fclose(f_in);
      fclose(f_out);

      // Swap them
      pws_os::RenameFile(cs_out, m_cs_filename);

      // Re-open file
      if ((fd = pws_os::FOpen(m_cs_filename, _S("ab"))) == NULL) {
        pws_os::IssueError(_T("StartReport: Opening log file"));
        return false;
      }
    }
#else
  if (bFileIsUnicode) {
    // Convert UNICODE contents to ASCII
    // Close original first
    fclose(fd);

    // Open again to read
    FILE *f_in = pws_os::FOpen(m_cs_filename, "rb");

    // Open new file
    stringT cs_out = m_cs_filename + _T(".tmp");
    FILE *f_out = pws_os::FOpen(cs_out, "wb");

    UINT nBytesRead;
    WCHAR inwbuffer[4096];
    unsigned char outbuffer[4096];

    // Skip over BOM
    fseek(f_in, 2, SEEK_SET);

    // Now copy
    do {
      nBytesRead = fread(inwbuffer, sizeof(inwbuffer[0])*sizeof(inwbuffer),
                         1, f_in);

      if (nBytesRead > 0) {
        size_t len = pws_os::wcstombs((char *)outbuffer, 4096,
                                      inwbuffer, nBytesRead);
        if (len != 0)
          fwrite(outbuffer, len, 1, f_out);
      } else
        break;

    } while(nBytesRead > 0);

    // Close files
    fclose(f_in);
    fclose(f_out);

    // Swap them
    pws_os::RenameFile(cs_out, m_cs_filename);

    // Re-open file
    if ((fd = pws_os::FOpen(m_cs_filename, _S("ab"))) == NULL) {
      pws_os::IssueError(_T("StartReport: Opening log file"));
      return false;
    }
  }
#endif
  StringX sx = m_osxs.rdbuf()->str();
  fwrite(reinterpret_cast<const void *>(sx.c_str()), sizeof(BYTE),
             sx.length() * sizeof(TCHAR), fd);
  fclose(fd);

  return true;
}

// Write a record with(default) or without a CRLF
void CReport::WriteLine(const stringT &cs_line, bool bCRLF)
{
  m_osxs << cs_line.c_str();
  if (bCRLF) {
    m_osxs << CRLF;
  }
}

// Write a record with (default) or without a CRLF
void CReport::WriteLine(const LPTSTR &tc_line, bool bCRLF)
{
  m_osxs << tc_line;
  if (bCRLF) {
    m_osxs << CRLF;
  }
}

// Write a new line
void CReport::WriteLine()
{
  m_osxs << CRLF;
}

//  EndReport writes a "End Report" record and closes the report file.
void CReport::EndReport()
{
  WriteLine();
  stringT cs_title;
  LoadAString(cs_title, IDSC_END_REPORT1);
  WriteLine(cs_title);
  LoadAString(cs_title, IDSC_END_REPORT2);
  WriteLine(cs_title);

  m_osxs.flush();
}
<|endoftext|>