<commit_before>/**
 * \file
 * \brief Implementation of RCC-related functions for STM32F1
 *
 * \author Copyright (C) 2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "distortos/chip/STM32F1-RCC.hpp"

#include "distortos/chip/STM32F1-RCC-bits.h"

#include "distortos/chip/CMSIS-proxy.h"

#include <array>

#include <cerrno>

namespace distortos
{

namespace chip
{

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| local functions
+---------------------------------------------------------------------------------------------------------------------*/

/**
 * \brief Configures PREDIV1 or PREDIV2 division factor.
 *
 * \param [in] prediv2 selects whether PREDIV1 (false) or PREDIV2 (true) will be configured
 * \param [in] prediv is the PREDIV1 or PREDIV2 division factor, [minPrediv; maxPrediv]
 *
 * \return 0 on success, error code otherwise:
 * - EINVAL - \a prediv value is invalid;
 */

int configurePrediv(const bool prediv2, const uint8_t prediv)
{
	if (prediv < minPrediv || prediv > maxPrediv)
		return EINVAL;

#if defined(CONFIG_CHIP_STM32F100)
	static_cast<void>(prediv2);	// suppress warning
	RCC->CFGR2 = (RCC->CFGR2 & ~RCC_CFGR2_PREDIV1) | (prediv << RCC_CFGR2_PREDIV1_bit);
#elif defined(CONFIG_CHIP_STM32F105) || defined(CONFIG_CHIP_STM32F107)
	RCC->CFGR2 = (RCC->CFGR2 & ~(prediv2 == true ? RCC_CFGR2_PREDIV2 : RCC_CFGR2_PREDIV1)) |
			(prediv << (prediv2 == true ? RCC_CFGR2_PREDIV2_bit : RCC_CFGR2_PREDIV1_bit));
#else	// !defined(CONFIG_CHIP_STM32F100) && !defined(CONFIG_CHIP_STM32F105) && !defined(CONFIG_CHIP_STM32F107)
	static_cast<void>(prediv2);	// suppress warning
	RCC_CFGR_PLLXTPRE_bb = prediv == 2;
#endif	// !defined(CONFIG_CHIP_STM32F100) && !defined(CONFIG_CHIP_STM32F105) && !defined(CONFIG_CHIP_STM32F107)
	return 0;
}

#if defined(CONFIG_CHIP_STM32F105) || defined(CONFIG_CHIP_STM32F107)

/**
 * \brief Enables PLL2 or PLL3.
 *
 * Enables PLL2 or PLL3 using selected parameters and waits until it is stable.
 *
 * \warning Before changing configuration of PLL2 make sure that it is not used in any way (as source of main PLL).
 * Before changing configuration of PLL3 make sure that it is not used in any way (as source of peripheral clocks).
 *
 * \param [in] pll3 selects whether PLL2 (false) or PLL3 (true) will be configured
 * \param [in] pll23Mul is the PLL2MUL value for PLL2 or PLL3MUL value for PLL3, [minPll23Mul; maxPll23Mul] and
 * {pll23Mul16, pll23Mul20}
 *
 * \return 0 on success, error code otherwise:
 * - EINVAL - \a pll23Mul value is invalid;
 */

int enablePll23(const bool pll3, const uint8_t pll23Mul)
{
	if ((pll23Mul < minPll23Mul || pll23Mul > maxPll23Mul) && pll23Mul != pll23Mul16 && pll23Mul != pll23Mul20)
		return EINVAL;

	const auto convertedPll23Mul = pll23Mul - 2 <= 0xf ? pll23Mul - 2 : 0xf;
	RCC->CFGR2 = (RCC->CFGR2 & ~(pll3 == true ? RCC_CFGR2_PLL3MUL : RCC_CFGR2_PLL2MUL)) |
			(convertedPll23Mul << (pll3 == true ? RCC_CFGR2_PLL3MUL_bit : RCC_CFGR2_PLL2MUL_bit));
	(pll3 == true ? RCC_CR_PLL3ON_bb : RCC_CR_PLL2ON_bb) = 1;
	while ((pll3 == true ? RCC_CR_PLL3RDY_bb : RCC_CR_PLL2RDY_bb) == 0);	// wait until PLL is stable
	return 0;
}

#endif	// defined(CONFIG_CHIP_STM32F105) || defined(CONFIG_CHIP_STM32F107)

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+
| global functions
+---------------------------------------------------------------------------------------------------------------------*/

int configureAhbClockDivider(const uint16_t hpre)
{
	static const std::pair<decltype(hpre), decltype(RCC_CFGR_HPRE_DIV1)> associations[]
	{
		{hpreDiv1, RCC_CFGR_HPRE_DIV1},
		{hpreDiv2, RCC_CFGR_HPRE_DIV2},
		{hpreDiv4, RCC_CFGR_HPRE_DIV4},
		{hpreDiv8, RCC_CFGR_HPRE_DIV8},
		{hpreDiv16, RCC_CFGR_HPRE_DIV16},
		{hpreDiv64, RCC_CFGR_HPRE_DIV64},
		{hpreDiv128, RCC_CFGR_HPRE_DIV128},
		{hpreDiv256, RCC_CFGR_HPRE_DIV256},
		{hpreDiv512, RCC_CFGR_HPRE_DIV512},
	};

	for (auto& association : associations)
		if (association.first == hpre)
		{
			RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_HPRE) | association.second;
			return 0;
		}

	return EINVAL;
}

int configureApbClockDivider(const bool ppre2, const uint8_t ppre)
{
	static const std::pair<decltype(ppre), std::array<decltype(RCC_CFGR_PPRE1_DIV1), 2>> associations[]
	{
		{ppreDiv1, {RCC_CFGR_PPRE1_DIV1, RCC_CFGR_PPRE2_DIV1}},
		{ppreDiv2, {RCC_CFGR_PPRE1_DIV2, RCC_CFGR_PPRE2_DIV2}},
		{ppreDiv4, {RCC_CFGR_PPRE1_DIV4, RCC_CFGR_PPRE2_DIV4}},
		{ppreDiv8, {RCC_CFGR_PPRE1_DIV8, RCC_CFGR_PPRE2_DIV8}},
		{ppreDiv16, {RCC_CFGR_PPRE1_DIV16, RCC_CFGR_PPRE2_DIV16}},
	};

	for (auto& association : associations)
		if (association.first == ppre)
		{
			static const decltype(RCC_CFGR_PPRE1) masks[] {RCC_CFGR_PPRE1, RCC_CFGR_PPRE2};
			RCC->CFGR = (RCC->CFGR & ~masks[ppre2]) | association.second[ppre2];
			return 0;
		}

	return EINVAL;
}

int configurePrediv1(const uint8_t prediv1)
{
	return configurePrediv(false, prediv1);
}

#if defined(CONFIG_CHIP_STM32F105) || defined(CONFIG_CHIP_STM32F107)

void configurePrediv1ClockSource(const bool pll2)
{
	RCC_CFGR2_PREDIV1SRC_bb = pll2;
}

int configurePrediv2(const uint8_t prediv2)
{
	return configurePrediv(true, prediv2);
}

#endif	// defined(CONFIG_CHIP_STM32F105) || defined(CONFIG_CHIP_STM32F107)

void enableHse(const bool bypass)
{
	RCC_CR_HSEBYP_bb = bypass;
	RCC_CR_HSEON_bb = 1;
	while (RCC_CR_HSERDY_bb == 0);	// wait until HSE oscillator is stable
}

int enablePll(const bool prediv1, const uint8_t pllmul)
{
#if defined(CONFIG_CHIP_STM32F105) || defined(CONFIG_CHIP_STM32F107)

	if ((pllmul < minPllmul || pllmul > maxPllmul) && pllmul != pllmul6_5)
		return EINVAL;

#else	// !defined(CONFIG_CHIP_STM32F105) && !defined(CONFIG_CHIP_STM32F107)

	if (pllmul < minPllmul || pllmul > maxPllmul)
		return EINVAL;

#endif	// !defined(CONFIG_CHIP_STM32F105) && !defined(CONFIG_CHIP_STM32F107)

	RCC->CFGR = (RCC->CFGR & ~(RCC_CFGR_PLLMULL | RCC_CFGR_PLLSRC)) | ((pllmul - 2) << RCC_CFGR_PLLMUL_bit) |
			(prediv1 << RCC_CFGR_PLLSRC_bit);
	RCC_CR_PLLON_bb = 1;
	while (RCC_CR_PLLRDY_bb == 0);	// wait until PLL is stable
	return 0;
}

#if defined(CONFIG_CHIP_STM32F105) || defined(CONFIG_CHIP_STM32F107)

int enablePll2(const uint8_t pll2Mul)
{
	return enablePll23(false, pll2Mul);
}

int enablePll3(const uint8_t pll3Mul)
{
	return enablePll23(true, pll3Mul);
}

#endif	// defined(CONFIG_CHIP_STM32F105) || defined(CONFIG_CHIP_STM32F107)

void disableHse()
{
	RCC_CR_HSEON_bb = 0;
}

void disablePll()
{
	RCC_CR_PLLON_bb = 0;
}

#if defined(CONFIG_CHIP_STM32F105) || defined(CONFIG_CHIP_STM32F107)

void disablePll2()
{
	RCC_CR_PLL2ON_bb = 0;
}

void disablePll3()
{
	RCC_CR_PLL3ON_bb = 0;
}

#endif	// defined(CONFIG_CHIP_STM32F105) || defined(CONFIG_CHIP_STM32F107)

void switchSystemClock(const SystemClockSource source)
{
	const auto sourceValue = static_cast<uint32_t>(source);
	RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_SW) | (sourceValue << RCC_CFGR_SW_bit);
	while ((RCC->CFGR & RCC_CFGR_SWS) != sourceValue << RCC_CFGR_SWS_bit);
}

}	// namespace chip

}	// namespace distortos
<commit_msg>Fix PREDIVx configuration for STM32F1<commit_after>/**
 * \file
 * \brief Implementation of RCC-related functions for STM32F1
 *
 * \author Copyright (C) 2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "distortos/chip/STM32F1-RCC.hpp"

#include "distortos/chip/STM32F1-RCC-bits.h"

#include "distortos/chip/CMSIS-proxy.h"

#include <array>

#include <cerrno>

namespace distortos
{

namespace chip
{

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| local functions
+---------------------------------------------------------------------------------------------------------------------*/

/**
 * \brief Configures PREDIV1 or PREDIV2 division factor.
 *
 * \param [in] prediv2 selects whether PREDIV1 (false) or PREDIV2 (true) will be configured
 * \param [in] prediv is the PREDIV1 or PREDIV2 division factor, [minPrediv; maxPrediv]
 *
 * \return 0 on success, error code otherwise:
 * - EINVAL - \a prediv value is invalid;
 */

int configurePrediv(const bool prediv2, const uint8_t prediv)
{
	if (prediv < minPrediv || prediv > maxPrediv)
		return EINVAL;

#if defined(CONFIG_CHIP_STM32F100)
	static_cast<void>(prediv2);	// suppress warning
	RCC->CFGR2 = (RCC->CFGR2 & ~RCC_CFGR2_PREDIV1) | ((prediv - 1) << RCC_CFGR2_PREDIV1_bit);
#elif defined(CONFIG_CHIP_STM32F105) || defined(CONFIG_CHIP_STM32F107)
	RCC->CFGR2 = (RCC->CFGR2 & ~(prediv2 == true ? RCC_CFGR2_PREDIV2 : RCC_CFGR2_PREDIV1)) |
			((prediv - 1) << (prediv2 == true ? RCC_CFGR2_PREDIV2_bit : RCC_CFGR2_PREDIV1_bit));
#else	// !defined(CONFIG_CHIP_STM32F100) && !defined(CONFIG_CHIP_STM32F105) && !defined(CONFIG_CHIP_STM32F107)
	static_cast<void>(prediv2);	// suppress warning
	RCC_CFGR_PLLXTPRE_bb = prediv == 2;
#endif	// !defined(CONFIG_CHIP_STM32F100) && !defined(CONFIG_CHIP_STM32F105) && !defined(CONFIG_CHIP_STM32F107)
	return 0;
}

#if defined(CONFIG_CHIP_STM32F105) || defined(CONFIG_CHIP_STM32F107)

/**
 * \brief Enables PLL2 or PLL3.
 *
 * Enables PLL2 or PLL3 using selected parameters and waits until it is stable.
 *
 * \warning Before changing configuration of PLL2 make sure that it is not used in any way (as source of main PLL).
 * Before changing configuration of PLL3 make sure that it is not used in any way (as source of peripheral clocks).
 *
 * \param [in] pll3 selects whether PLL2 (false) or PLL3 (true) will be configured
 * \param [in] pll23Mul is the PLL2MUL value for PLL2 or PLL3MUL value for PLL3, [minPll23Mul; maxPll23Mul] and
 * {pll23Mul16, pll23Mul20}
 *
 * \return 0 on success, error code otherwise:
 * - EINVAL - \a pll23Mul value is invalid;
 */

int enablePll23(const bool pll3, const uint8_t pll23Mul)
{
	if ((pll23Mul < minPll23Mul || pll23Mul > maxPll23Mul) && pll23Mul != pll23Mul16 && pll23Mul != pll23Mul20)
		return EINVAL;

	const auto convertedPll23Mul = pll23Mul - 2 <= 0xf ? pll23Mul - 2 : 0xf;
	RCC->CFGR2 = (RCC->CFGR2 & ~(pll3 == true ? RCC_CFGR2_PLL3MUL : RCC_CFGR2_PLL2MUL)) |
			(convertedPll23Mul << (pll3 == true ? RCC_CFGR2_PLL3MUL_bit : RCC_CFGR2_PLL2MUL_bit));
	(pll3 == true ? RCC_CR_PLL3ON_bb : RCC_CR_PLL2ON_bb) = 1;
	while ((pll3 == true ? RCC_CR_PLL3RDY_bb : RCC_CR_PLL2RDY_bb) == 0);	// wait until PLL is stable
	return 0;
}

#endif	// defined(CONFIG_CHIP_STM32F105) || defined(CONFIG_CHIP_STM32F107)

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+
| global functions
+---------------------------------------------------------------------------------------------------------------------*/

int configureAhbClockDivider(const uint16_t hpre)
{
	static const std::pair<decltype(hpre), decltype(RCC_CFGR_HPRE_DIV1)> associations[]
	{
		{hpreDiv1, RCC_CFGR_HPRE_DIV1},
		{hpreDiv2, RCC_CFGR_HPRE_DIV2},
		{hpreDiv4, RCC_CFGR_HPRE_DIV4},
		{hpreDiv8, RCC_CFGR_HPRE_DIV8},
		{hpreDiv16, RCC_CFGR_HPRE_DIV16},
		{hpreDiv64, RCC_CFGR_HPRE_DIV64},
		{hpreDiv128, RCC_CFGR_HPRE_DIV128},
		{hpreDiv256, RCC_CFGR_HPRE_DIV256},
		{hpreDiv512, RCC_CFGR_HPRE_DIV512},
	};

	for (auto& association : associations)
		if (association.first == hpre)
		{
			RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_HPRE) | association.second;
			return 0;
		}

	return EINVAL;
}

int configureApbClockDivider(const bool ppre2, const uint8_t ppre)
{
	static const std::pair<decltype(ppre), std::array<decltype(RCC_CFGR_PPRE1_DIV1), 2>> associations[]
	{
		{ppreDiv1, {RCC_CFGR_PPRE1_DIV1, RCC_CFGR_PPRE2_DIV1}},
		{ppreDiv2, {RCC_CFGR_PPRE1_DIV2, RCC_CFGR_PPRE2_DIV2}},
		{ppreDiv4, {RCC_CFGR_PPRE1_DIV4, RCC_CFGR_PPRE2_DIV4}},
		{ppreDiv8, {RCC_CFGR_PPRE1_DIV8, RCC_CFGR_PPRE2_DIV8}},
		{ppreDiv16, {RCC_CFGR_PPRE1_DIV16, RCC_CFGR_PPRE2_DIV16}},
	};

	for (auto& association : associations)
		if (association.first == ppre)
		{
			static const decltype(RCC_CFGR_PPRE1) masks[] {RCC_CFGR_PPRE1, RCC_CFGR_PPRE2};
			RCC->CFGR = (RCC->CFGR & ~masks[ppre2]) | association.second[ppre2];
			return 0;
		}

	return EINVAL;
}

int configurePrediv1(const uint8_t prediv1)
{
	return configurePrediv(false, prediv1);
}

#if defined(CONFIG_CHIP_STM32F105) || defined(CONFIG_CHIP_STM32F107)

void configurePrediv1ClockSource(const bool pll2)
{
	RCC_CFGR2_PREDIV1SRC_bb = pll2;
}

int configurePrediv2(const uint8_t prediv2)
{
	return configurePrediv(true, prediv2);
}

#endif	// defined(CONFIG_CHIP_STM32F105) || defined(CONFIG_CHIP_STM32F107)

void enableHse(const bool bypass)
{
	RCC_CR_HSEBYP_bb = bypass;
	RCC_CR_HSEON_bb = 1;
	while (RCC_CR_HSERDY_bb == 0);	// wait until HSE oscillator is stable
}

int enablePll(const bool prediv1, const uint8_t pllmul)
{
#if defined(CONFIG_CHIP_STM32F105) || defined(CONFIG_CHIP_STM32F107)

	if ((pllmul < minPllmul || pllmul > maxPllmul) && pllmul != pllmul6_5)
		return EINVAL;

#else	// !defined(CONFIG_CHIP_STM32F105) && !defined(CONFIG_CHIP_STM32F107)

	if (pllmul < minPllmul || pllmul > maxPllmul)
		return EINVAL;

#endif	// !defined(CONFIG_CHIP_STM32F105) && !defined(CONFIG_CHIP_STM32F107)

	RCC->CFGR = (RCC->CFGR & ~(RCC_CFGR_PLLMULL | RCC_CFGR_PLLSRC)) | ((pllmul - 2) << RCC_CFGR_PLLMUL_bit) |
			(prediv1 << RCC_CFGR_PLLSRC_bit);
	RCC_CR_PLLON_bb = 1;
	while (RCC_CR_PLLRDY_bb == 0);	// wait until PLL is stable
	return 0;
}

#if defined(CONFIG_CHIP_STM32F105) || defined(CONFIG_CHIP_STM32F107)

int enablePll2(const uint8_t pll2Mul)
{
	return enablePll23(false, pll2Mul);
}

int enablePll3(const uint8_t pll3Mul)
{
	return enablePll23(true, pll3Mul);
}

#endif	// defined(CONFIG_CHIP_STM32F105) || defined(CONFIG_CHIP_STM32F107)

void disableHse()
{
	RCC_CR_HSEON_bb = 0;
}

void disablePll()
{
	RCC_CR_PLLON_bb = 0;
}

#if defined(CONFIG_CHIP_STM32F105) || defined(CONFIG_CHIP_STM32F107)

void disablePll2()
{
	RCC_CR_PLL2ON_bb = 0;
}

void disablePll3()
{
	RCC_CR_PLL3ON_bb = 0;
}

#endif	// defined(CONFIG_CHIP_STM32F105) || defined(CONFIG_CHIP_STM32F107)

void switchSystemClock(const SystemClockSource source)
{
	const auto sourceValue = static_cast<uint32_t>(source);
	RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_SW) | (sourceValue << RCC_CFGR_SW_bit);
	while ((RCC->CFGR & RCC_CFGR_SWS) != sourceValue << RCC_CFGR_SWS_bit);
}

}	// namespace chip

}	// namespace distortos
<|endoftext|>


<commit_before>#include "tour_processor.h"
#include "b5m_types.h"
#include "b5m_helper.h"
#include "scd_doc_processor.h"
#include <boost/algorithm/string.hpp>
#include <glog/logging.h>
#include <common/ScdParser.h>
#include <document-manager/ScdDocument.h>
#include <assert.h>

//#define TOUR_DEBUG

using namespace sf1r;

TourProcessor::TourProcessor()
{
}

TourProcessor::~TourProcessor()
{
}

bool TourProcessor::Generate(const std::string& scd_path, const std::string& mdb_instance)
{
	//scan all the *.scd
    m_ = mdb_instance;
    ScdDocProcessor::ProcessorType p = boost::bind(&TourProcessor::Insert_, this, _1);
    int thread_num = 1;
    ScdDocProcessor sd_processor(p, thread_num);
    sd_processor.AddInput(scd_path);
    sd_processor.Process();
    Finish_();
	return true;
}

void TourProcessor::Insert_(ScdDocument& doc)
{
	std::string sdays;
	std::string price;
	BufferValueItem value;
    doc.getString(SCD_FROM_CITY, value.from);
    doc.getString(SCD_TO_CITY, value.to);
	doc.getString(SCD_PRICE,price);
    doc.getString(SCD_TIME_PLAN, sdays);
    value.days = ParseDays_(sdays);
    value.doc = doc;
    value.price = 0.0;
    try {
        value.price = boost::lexical_cast<double>(price);
    }
    catch(std::exception& ex)
    {
        std::cerr<<"parse tour price error for "<< price<<std::endl;
    }
    value.bcluster = true;
    if(value.days.second==0||value.price==0.0||value.from.empty()||value.to.empty()) value.bcluster = false;

	//generate union key by to_city
	UnionBufferKey union_key;
	GenerateUnionKey(union_key,value.from,value.to);
	//BufferKey key(value.from, value.to);
    boost::unique_lock<boost::mutex> lock(mutex_);
    buffer_[union_key].push_back(value);
}

std::pair<uint32_t, uint32_t> TourProcessor::ParseDays_(const std::string& sdays) const
{
    //find "天" Ps:4-7天/8天
    std::pair<uint32_t, uint32_t> r(0,0);
	size_t pos = sdays.find("天");
	if(pos == std::string::npos)
	{
		pos = sdays.length();
	}

	std::string tmp_days = sdays.substr(0,pos);
	//find '-'
	pos = tmp_days.find('-');
	if(pos == std::string::npos)
	{
		r.first = atoi(tmp_days.c_str());
		r.second = r.first;
	}
	else
	{
		int min_days = atoi(tmp_days.substr(0,pos).c_str());
		int max_days = atoi(tmp_days.substr(pos+1).c_str());
		r.first = min_days;
		r.second = max_days;
	}
	return r;
}

void TourProcessor::GenerateUnionKey(UnionBufferKey& union_key,
									 const std::string& from_city,
									 const std::string& to_city)const
{
	std::vector<std::string> union_to_city;
	boost::split(union_to_city,to_city,boost::is_any_of("，"));

	if(union_to_city.size() == 0)
	{
		union_key.push_back(std::make_pair(from_city,""));
		return;
	}

	for(size_t i = 0;i<union_to_city.size();i++)
	{
		//ps:from city:上海  to city：上海，马累，马尔代夫
		//so we should remove key pair(上海，上海)
		if(union_to_city[i].empty()) continue;
		if(union_to_city.size() >= 2)
		{
			if(from_city == union_to_city[i]) continue;
		}
		union_key.push_back(std::make_pair(from_city,union_to_city[i]));
	}

	if(union_key.size()==0)
	{
		union_key.push_back(std::make_pair(from_city,from_city));
	}

	//sort key vector
	std::sort(union_key.union_key_.begin(),union_key.union_key_.end());
}

void TourProcessor::Finish_()
{
    LOG(INFO)<<"buffer size "<<buffer_.size()<<std::endl;
    std::string odir = m_+"/b5mo";
    std::string pdir = m_+"/b5mp";
    boost::filesystem::create_directories(odir);
    boost::filesystem::create_directories(pdir);
    ScdWriter owriter(odir, UPDATE_SCD);
    ScdWriter pwriter(pdir, UPDATE_SCD);
    for(Buffer::iterator it = buffer_.begin();it!=buffer_.end();++it)
    {
        const UnionBufferKey& key = it->first;
        BufferValue& value = it->second;
#ifdef TOUR_DEBUG
	    LOG(INFO) << "1---->processing:";
		for(size_t i = 0; i<key.size();i++)
		{
			LOG(INFO) << key[i].first << "," << key[i].second << "	";
		}
		LOG(INFO) << value.size() << std::endl;
#endif
        std::sort(value.begin(), value.end());
        std::vector<Group> groups;
        for(uint32_t i=0;i<value.size();i++)
        {
            const BufferValueItem& vi = value[i];
#ifdef TOUR_DEBUG
            LOG(INFO)<<"find value item "<<vi.from<<","<<vi.to<<",["<<vi.days.first<<","<<vi.days.second<<"],"<<vi.price<<","<<vi.bcluster<<std::endl;
#endif
            Group* find_group = NULL;
            for(uint32_t j=0;j<groups.size();j++)
            {
                Group& g = groups[j];
                if(!g.front().bcluster) continue;
                //compare vi with g;
                std::pair<uint32_t, uint32_t> g_mindays = g.front().days;
                if(vi.days.first>g_mindays.second&&vi.days.first-g_mindays.second>1) continue;
                //if(vi.days-g_mindays>1) continue;
                //double avg_price = 0.0;
                //for(uint32_t k=0;k<g.size();k++)
                //{
                //    avg_price += g[k].price;
                //}
                //avg_price/=g.size();
                //double p_ratio = std::max(vi.price, avg_price)/std::min(vi.price, avg_price);
                //if(p_ratio>1.5) continue;
                find_group = &g;
            }

            if(find_group==NULL)
            {
                Group g;
                g.push_back(vi);
                groups.push_back(g);
#ifdef TOUR_DEBUG
                LOG(INFO)<<"create new group"<<std::endl;
#endif
            }
            else
            {
                find_group->push_back(vi);
            }
        }
        for(uint32_t i=0;i<groups.size();i++)
        {
            Group& g = groups[i];
            std::string pid;
            g.front().doc.getString("DOCID", pid);
            for(uint32_t j=0;j<g.size();j++)
            {
                BufferValueItem& vi = g[j];
                vi.doc.property("uuid") = str_to_propstr(pid);
                owriter.Append(vi.doc);
            }
            Document pdoc;
            GenP_(g, pdoc);
            pwriter.Append(pdoc);
        }
    }
    owriter.Close();
    pwriter.Close();
}

void TourProcessor::GenP_(Group& g, Document& doc) const
{
	assert(g.size() >= 1);
	doc = g[0].doc;
	doc.eraseProperty("uuid");
	std::string price;
	std::string p_docid;
    Set source_set;
	double min_price = g[0].price;
	double max_price = g[0].price;
	//get first doc uuid as pid
	g[0].doc.getString(SCD_UUID,p_docid);
	//set docid default use first docid
	doc.property(SCD_DOC_ID) = str_to_propstr(p_docid);
	for(std::size_t i=0;i<g.size();i++)
	{
		ScdDocument& doc_ref = g[i].doc;
		//get source list
        std::string source;
		doc_ref.getString(SCD_SOURCE,source);
		if(!source.empty()) source_set.insert(source);
		//get price range
		min_price = std::min(min_price,g[i].price);
		max_price = std::max(max_price,g[i].price);
		//maybe some other rules TODO........
	}

	//generate p <source>
    std::string source;
	for(Set::const_iterator it = source_set.begin();it!=source_set.end();++it)
	{
	    if(!source.empty()) source+=",";
		source += *it;
	}
	doc.property(SCD_SOURCE)=str_to_propstr(source);

	//generate p <price>
	std::stringstream ss;
	if(min_price < max_price)
	{
		ss << min_price << '-'<< max_price;
	}
	else
	{
		assert(min_price == max_price);
		ss << min_price;
	}
	ss >> price;
	doc.property(SCD_PRICE) = str_to_propstr(price);
	doc.property("itemcount") = (int64_t)(g.size());
	//may have other attribute to set property todo......
	//
	//
}
<commit_msg>fix bug:split() generate messy code<commit_after>#include "tour_processor.h"
#include "b5m_types.h"
#include "b5m_helper.h"
#include "scd_doc_processor.h"
#include <boost/algorithm/string.hpp>
#include <glog/logging.h>
#include <common/ScdParser.h>
#include <document-manager/ScdDocument.h>
#include <assert.h>

//#define TOUR_DEBUG

using namespace sf1r;

TourProcessor::TourProcessor()
{
}

TourProcessor::~TourProcessor()
{
}

bool TourProcessor::Generate(const std::string& scd_path, const std::string& mdb_instance)
{
	//scan all the *.scd
    m_ = mdb_instance;
    ScdDocProcessor::ProcessorType p = boost::bind(&TourProcessor::Insert_, this, _1);
    int thread_num = 1;
    ScdDocProcessor sd_processor(p, thread_num);
    sd_processor.AddInput(scd_path);
    sd_processor.Process();
    Finish_();
	return true;
}

void TourProcessor::Insert_(ScdDocument& doc)
{
	std::string sdays;
	std::string price;
	BufferValueItem value;
    doc.getString(SCD_FROM_CITY, value.from);
    doc.getString(SCD_TO_CITY, value.to);
	doc.getString(SCD_PRICE,price);
    doc.getString(SCD_TIME_PLAN, sdays);
    value.days = ParseDays_(sdays);
    value.doc = doc;
    value.price = 0.0;
    try {
        value.price = boost::lexical_cast<double>(price);
    }
    catch(std::exception& ex)
    {
        std::cerr<<"parse tour price error for "<< price<<std::endl;
    }
    value.bcluster = true;
    if(value.days.second==0||value.price==0.0||value.from.empty()||value.to.empty()) value.bcluster = false;

	//generate union key by to_city
	UnionBufferKey union_key;
	GenerateUnionKey(union_key,value.from,value.to);
	//BufferKey key(value.from, value.to);
    boost::unique_lock<boost::mutex> lock(mutex_);
    buffer_[union_key].push_back(value);
}

std::pair<uint32_t, uint32_t> TourProcessor::ParseDays_(const std::string& sdays) const
{
    //find "天" Ps:4-7天/8天
    std::pair<uint32_t, uint32_t> r(0,0);
	size_t pos = sdays.find("天");
	if(pos == std::string::npos)
	{
		pos = sdays.length();
	}

	std::string tmp_days = sdays.substr(0,pos);
	//find '-'
	pos = tmp_days.find('-');
	if(pos == std::string::npos)
	{
		r.first = atoi(tmp_days.c_str());
		r.second = r.first;
	}
	else
	{
		int min_days = atoi(tmp_days.substr(0,pos).c_str());
		int max_days = atoi(tmp_days.substr(pos+1).c_str());
		r.first = min_days;
		r.second = max_days;
	}
	return r;
}

void TourProcessor::GenerateUnionKey(UnionBufferKey& union_key,
									 const std::string& from_city,
									 const std::string& to_city)const
{
	std::vector<std::string> union_to_city;
	boost::split(union_to_city,to_city,boost::is_any_of(","));

	if(union_to_city.size() == 0)
	{
		union_key.push_back(std::make_pair(from_city,""));
		return;
	}

	for(size_t i = 0;i<union_to_city.size();i++)
	{
		//ps:from city:上海  to city：上海，马累，马尔代夫
		//so we should remove key pair(上海，上海)
		if(union_to_city[i].empty()) continue;
		if(union_to_city.size() >= 2)
		{
			if(from_city == union_to_city[i]) continue;
		}
		union_key.push_back(std::make_pair(from_city,union_to_city[i]));
	}

	if(union_key.size()==0)
	{
		union_key.push_back(std::make_pair(from_city,from_city));
	}

	//sort key vector
	std::sort(union_key.union_key_.begin(),union_key.union_key_.end());
}

void TourProcessor::Finish_()
{
    LOG(INFO)<<"buffer size "<<buffer_.size()<<std::endl;
    std::string odir = m_+"/b5mo";
    std::string pdir = m_+"/b5mp";
    boost::filesystem::create_directories(odir);
    boost::filesystem::create_directories(pdir);
	ScdWriter owriter(odir, UPDATE_SCD);
    ScdWriter pwriter(pdir, UPDATE_SCD);
    for(Buffer::iterator it = buffer_.begin();it!=buffer_.end();++it)
    {
        const UnionBufferKey& key = it->first;
        BufferValue& value = it->second;
#ifdef TOUR_DEBUG
		LOG(INFO) << "1---->processing:";
		for(size_t i = 0; i<key.union_key_.size();i++)
		{
			LOG(INFO) << key.union_key_[i].first << "," << key.union_key_[i].second << "	";
		}
		LOG(INFO) << "aggregate count:" << value.size();
#endif
        std::sort(value.begin(), value.end());
        std::vector<Group> groups;
        for(uint32_t i=0;i<value.size();i++)
        {
            const BufferValueItem& vi = value[i];
#ifdef TOUR_DEBUG
            LOG(INFO)<<"find value item "<<vi.from<<","<<vi.to<<",["<<vi.days.first<<","<<vi.days.second<<"],"<<vi.price<<","<<vi.bcluster<<std::endl;
#endif
            Group* find_group = NULL;
            for(uint32_t j=0;j<groups.size();j++)
            {
                Group& g = groups[j];
                if(!g.front().bcluster) continue;
                //compare vi with g;
                std::pair<uint32_t, uint32_t> g_mindays = g.front().days;
                if(vi.days.first>g_mindays.second&&vi.days.first-g_mindays.second>1) continue;
                //if(vi.days-g_mindays>1) continue;
                //double avg_price = 0.0;
                //for(uint32_t k=0;k<g.size();k++)
                //{
                //    avg_price += g[k].price;
                //}
                //avg_price/=g.size();
                //double p_ratio = std::max(vi.price, avg_price)/std::min(vi.price, avg_price);
                //if(p_ratio>1.5) continue;
                find_group = &g;
            }

            if(find_group==NULL)
            {
                Group g;
                g.push_back(vi);
                groups.push_back(g);
#ifdef TOUR_DEBUG
                LOG(INFO)<<"create new group"<<std::endl;
#endif
            }
            else
            {
                find_group->push_back(vi);
            }
        }
        for(uint32_t i=0;i<groups.size();i++)
        {
            Group& g = groups[i];
            std::string pid;
            g.front().doc.getString("DOCID", pid);
            for(uint32_t j=0;j<g.size();j++)
            {
                BufferValueItem& vi = g[j];
                vi.doc.property("uuid") = str_to_propstr(pid);
                owriter.Append(vi.doc);
            }
            Document pdoc;
            GenP_(g, pdoc);
            pwriter.Append(pdoc);
        }
    }
    owriter.Close();
    pwriter.Close();
}

void TourProcessor::GenP_(Group& g, Document& doc) const
{
	assert(g.size() >= 1);
	doc = g[0].doc;
	doc.eraseProperty("uuid");
	std::string price;
	std::string p_docid;
    Set source_set;
	double min_price = g[0].price;
	double max_price = g[0].price;
	//get first doc uuid as pid
	g[0].doc.getString(SCD_UUID,p_docid);
	//set docid default use first docid
	doc.property(SCD_DOC_ID) = str_to_propstr(p_docid);
	for(std::size_t i=0;i<g.size();i++)
	{
		ScdDocument& doc_ref = g[i].doc;
		//get source list
        std::string source;
		doc_ref.getString(SCD_SOURCE,source);
		if(!source.empty()) source_set.insert(source);
		//get price range
		min_price = std::min(min_price,g[i].price);
		max_price = std::max(max_price,g[i].price);
		//maybe some other rules TODO........
	}

	//generate p <source>
    std::string source;
	for(Set::const_iterator it = source_set.begin();it!=source_set.end();++it)
	{
	    if(!source.empty()) source+=",";
		source += *it;
	}
	doc.property(SCD_SOURCE)=str_to_propstr(source);

	//generate p <price>
	std::stringstream ss;
	if(min_price < max_price)
	{
		ss << min_price << '-'<< max_price;
	}
	else
	{
		assert(min_price == max_price);
		ss << min_price;
	}
	ss >> price;
	doc.property(SCD_PRICE) = str_to_propstr(price);
	doc.property("itemcount") = (int64_t)(g.size());
	//may have other attribute to set property todo......
	//
	//
}
<|endoftext|>


<commit_before>//
// PROJECT:         Aspia Remote Desktop
// FILE:            host/host_session_file_transfer.cc
// LICENSE:         Mozilla Public License Version 2.0
// PROGRAMMERS:     Dmitry Chapyshev (dmitry@aspia.ru)
//

#include "host/host_session_file_transfer.h"
#include "base/files/file_helpers.h"
#include "base/files/file_util.h"
#include "ipc/pipe_channel_proxy.h"
#include "protocol/message_serialization.h"
#include "protocol/filesystem.h"
#include "proto/auth_session.pb.h"

namespace aspia {

void HostSessionFileTransfer::Run(const std::wstring& channel_id)
{
    status_dialog_ = std::make_unique<FileStatusDialog>();

    ipc_channel_ = PipeChannel::CreateClient(channel_id);
    if (ipc_channel_)
    {
        ipc_channel_proxy_ = ipc_channel_->pipe_channel_proxy();

        uint32_t user_data = GetCurrentProcessId();

        PipeChannel::DisconnectHandler disconnect_handler =
            std::bind(&HostSessionFileTransfer::OnIpcChannelDisconnect, this);

        if (ipc_channel_->Connect(user_data, std::move(disconnect_handler)))
        {
            OnIpcChannelConnect(user_data);
            status_dialog_->WaitForClose();
        }

        ipc_channel_.reset();
    }

    status_dialog_.reset();
}

void HostSessionFileTransfer::OnIpcChannelConnect(uint32_t user_data)
{
    // The server sends the session type in user_data.
    proto::SessionType session_type =
        static_cast<proto::SessionType>(user_data);

    if (session_type != proto::SESSION_TYPE_FILE_TRANSFER)
    {
        LOG(FATAL) << "Invalid session type passed: " << session_type;
        return;
    }

    status_dialog_->OnSessionStarted();

    ipc_channel_proxy_->Receive(std::bind(
        &HostSessionFileTransfer::OnIpcChannelMessage, this, std::placeholders::_1));
}

void HostSessionFileTransfer::OnIpcChannelDisconnect()
{
    status_dialog_->OnSessionTerminated();
}

void HostSessionFileTransfer::OnIpcChannelMessage(const IOBuffer& buffer)
{
    proto::file_transfer::ClientToHost message;

    if (!ParseMessage(buffer, message))
    {
        ipc_channel_proxy_->Disconnect();
        return;
    }

    if (message.has_drive_list_request())
    {
        ReadDriveListRequest();
    }
    else if (message.has_file_list_request())
    {
        ReadFileListRequest(message.file_list_request());
    }
    else if (message.has_directory_size_request())
    {
        ReadDirectorySizeRequest(message.directory_size_request());
    }
    else if (message.has_create_directory_request())
    {
        ReadCreateDirectoryRequest(message.create_directory_request());
    }
    else if (message.has_rename_request())
    {
        ReadRenameRequest(message.rename_request());
    }
    else if (message.has_remove_request())
    {
        ReadRemoveRequest(message.remove_request());
    }
    else if (message.has_file_upload_request())
    {
        ReadFileUploadRequest(message.file_upload_request());
    }
    else if (message.has_file_packet())
    {
        if (!ReadFilePacket(message.file_packet()))
            ipc_channel_proxy_->Disconnect();
    }
    else if (message.has_file_download_request())
    {
        ReadFileDownloadRequest(message.file_download_request());
    }
    else if (message.has_file_packet_request())
    {
        if (!ReadFilePacketRequest())
            ipc_channel_proxy_->Disconnect();
    }
    else
    {
        LOG(ERROR) << "Unknown message from client";
        ipc_channel_proxy_->Disconnect();
    }
}

void HostSessionFileTransfer::SendReply(const proto::file_transfer::HostToClient& reply)
{
    ipc_channel_proxy_->Send(
        SerializeMessage<IOBuffer>(reply),
        std::bind(&HostSessionFileTransfer::OnReplySended, this));
}

void HostSessionFileTransfer::OnReplySended()
{
    // Receive next request.
    ipc_channel_proxy_->Receive(std::bind(
        &HostSessionFileTransfer::OnIpcChannelMessage, this, std::placeholders::_1));
}

void HostSessionFileTransfer::ReadDriveListRequest()
{
    proto::file_transfer::HostToClient reply;
    reply.set_status(ExecuteDriveListRequest(reply.mutable_drive_list()));

    if (reply.status() == proto::REQUEST_STATUS_SUCCESS)
    {
        status_dialog_->OnDriveListRequest();
    }

    SendReply(reply);
}

void HostSessionFileTransfer::ReadFileListRequest(const proto::FileListRequest& request)
{
    proto::file_transfer::HostToClient reply;

    FilePath path = std::experimental::filesystem::u8path(request.path());

    reply.set_status(ExecuteFileListRequest(path, reply.mutable_file_list()));

    if (reply.status() == proto::REQUEST_STATUS_SUCCESS)
    {
        status_dialog_->OnFileListRequest(path);
    }

    SendReply(reply);
}

void HostSessionFileTransfer::ReadCreateDirectoryRequest(
    const proto::CreateDirectoryRequest& request)
{
    proto::file_transfer::HostToClient reply;

    FilePath path = std::experimental::filesystem::u8path(request.path());

    reply.set_status(ExecuteCreateDirectoryRequest(path));

    if (reply.status() == proto::REQUEST_STATUS_SUCCESS)
    {
        status_dialog_->OnCreateDirectoryRequest(path);
    }

    SendReply(reply);
}

void HostSessionFileTransfer::ReadDirectorySizeRequest(const proto::DirectorySizeRequest& request)
{
    proto::file_transfer::HostToClient reply;

    FilePath path = std::experimental::filesystem::u8path(request.path());

    uint64_t directory_size = 0;

    reply.set_status(ExecuteDirectorySizeRequest(path, directory_size));
    reply.mutable_directory_size()->set_size(directory_size);

    SendReply(reply);
}

void HostSessionFileTransfer::ReadRenameRequest(const proto::RenameRequest& request)
{
    proto::file_transfer::HostToClient reply;

    FilePath old_name = std::experimental::filesystem::u8path(request.old_name());
    FilePath new_name = std::experimental::filesystem::u8path(request.new_name());

    reply.set_status(ExecuteRenameRequest(old_name, new_name));

    if (reply.status() == proto::REQUEST_STATUS_SUCCESS)
    {
        status_dialog_->OnRenameRequest(old_name, new_name);
    }

    SendReply(reply);
}

void HostSessionFileTransfer::ReadRemoveRequest(const proto::RemoveRequest& request)
{
    proto::file_transfer::HostToClient reply;

    FilePath path = std::experimental::filesystem::u8path(request.path());

    reply.set_status(ExecuteRemoveRequest(path));

    if (reply.status() == proto::REQUEST_STATUS_SUCCESS)
    {
        status_dialog_->OnRemoveRequest(path);
    }

    SendReply(reply);
}

void HostSessionFileTransfer::ReadFileUploadRequest(const proto::FileUploadRequest& request)
{
    proto::file_transfer::HostToClient reply;

    FilePath file_path = std::experimental::filesystem::u8path(request.file_path());

    do
    {
        if (!IsValidPathName(file_path))
        {
            reply.set_status(proto::REQUEST_STATUS_INVALID_PATH_NAME);
            break;
        }

        if (!request.overwrite())
        {
            if (PathExists(file_path))
            {
                reply.set_status(proto::REQUEST_STATUS_PATH_ALREADY_EXISTS);
                break;
            }
        }

        file_depacketizer_ = FileDepacketizer::Create(file_path, request.overwrite());
        if (!file_depacketizer_)
        {
            reply.set_status(proto::REQUEST_STATUS_FILE_CREATE_ERROR);
            break;
        }

        reply.set_status(proto::REQUEST_STATUS_SUCCESS);
    }
    while (false);

    if (reply.status() == proto::REQUEST_STATUS_SUCCESS)
    {
        status_dialog_->OnFileUploadRequest(file_path);
    }

    SendReply(reply);
}

bool HostSessionFileTransfer::ReadFilePacket(const proto::FilePacket& file_packet)
{
    if (!file_depacketizer_)
    {
        LOG(ERROR) << "Unexpected file packet";
        return false;
    }

    proto::file_transfer::HostToClient reply;

    if (!file_depacketizer_->ReadNextPacket(file_packet))
    {
        reply.set_status(proto::REQUEST_STATUS_FILE_WRITE_ERROR);
    }
    else
    {
        reply.set_status(proto::REQUEST_STATUS_SUCCESS);
    }

    if (file_packet.flags() & proto::FilePacket::LAST_PACKET)
    {
        file_depacketizer_.reset();
    }

    SendReply(reply);
    return true;
}

void HostSessionFileTransfer::ReadFileDownloadRequest(const proto::FileDownloadRequest& request)
{
    proto::file_transfer::HostToClient reply;

    FilePath file_path = std::experimental::filesystem::u8path(request.file_path());

    if (!IsValidPathName(file_path))
    {
        reply.set_status(proto::REQUEST_STATUS_INVALID_PATH_NAME);
    }
    else
    {
        file_packetizer_ = FilePacketizer::Create(file_path);
        if (!file_packetizer_)
        {
            reply.set_status(proto::REQUEST_STATUS_FILE_OPEN_ERROR);
        }
        else
        {
            reply.set_status(proto::REQUEST_STATUS_SUCCESS);
        }
    }

    SendReply(reply);
}

bool HostSessionFileTransfer::ReadFilePacketRequest()
{
    if (!file_packetizer_)
    {
        LOG(ERROR) << "Unexpected download data request";
        return false;
    }

    proto::file_transfer::HostToClient reply;

    std::unique_ptr<proto::FilePacket> packet = file_packetizer_->CreateNextPacket();
    if (!packet)
    {
        reply.set_status(proto::REQUEST_STATUS_FILE_READ_ERROR);
    }
    else
    {
        if (packet->flags() & proto::FilePacket::LAST_PACKET)
        {
            file_packetizer_.reset();
        }

        reply.set_status(proto::REQUEST_STATUS_SUCCESS);
        reply.set_allocated_file_packet(packet.release());
    }

    SendReply(reply);
    return true;
}

} // namespace aspia
<commit_msg>- Using Process class to get process id.<commit_after>//
// PROJECT:         Aspia Remote Desktop
// FILE:            host/host_session_file_transfer.cc
// LICENSE:         Mozilla Public License Version 2.0
// PROGRAMMERS:     Dmitry Chapyshev (dmitry@aspia.ru)
//

#include "host/host_session_file_transfer.h"
#include "base/files/file_helpers.h"
#include "base/files/file_util.h"
#include "base/process/process.h"
#include "ipc/pipe_channel_proxy.h"
#include "protocol/message_serialization.h"
#include "protocol/filesystem.h"
#include "proto/auth_session.pb.h"

namespace aspia {

void HostSessionFileTransfer::Run(const std::wstring& channel_id)
{
    status_dialog_ = std::make_unique<FileStatusDialog>();

    ipc_channel_ = PipeChannel::CreateClient(channel_id);
    if (ipc_channel_)
    {
        ipc_channel_proxy_ = ipc_channel_->pipe_channel_proxy();

        uint32_t user_data = Process::Current().Pid();

        PipeChannel::DisconnectHandler disconnect_handler =
            std::bind(&HostSessionFileTransfer::OnIpcChannelDisconnect, this);

        if (ipc_channel_->Connect(user_data, std::move(disconnect_handler)))
        {
            OnIpcChannelConnect(user_data);
            status_dialog_->WaitForClose();
        }

        ipc_channel_.reset();
    }

    status_dialog_.reset();
}

void HostSessionFileTransfer::OnIpcChannelConnect(uint32_t user_data)
{
    // The server sends the session type in user_data.
    proto::SessionType session_type =
        static_cast<proto::SessionType>(user_data);

    if (session_type != proto::SESSION_TYPE_FILE_TRANSFER)
    {
        LOG(FATAL) << "Invalid session type passed: " << session_type;
        return;
    }

    status_dialog_->OnSessionStarted();

    ipc_channel_proxy_->Receive(std::bind(
        &HostSessionFileTransfer::OnIpcChannelMessage, this, std::placeholders::_1));
}

void HostSessionFileTransfer::OnIpcChannelDisconnect()
{
    status_dialog_->OnSessionTerminated();
}

void HostSessionFileTransfer::OnIpcChannelMessage(const IOBuffer& buffer)
{
    proto::file_transfer::ClientToHost message;

    if (!ParseMessage(buffer, message))
    {
        ipc_channel_proxy_->Disconnect();
        return;
    }

    if (message.has_drive_list_request())
    {
        ReadDriveListRequest();
    }
    else if (message.has_file_list_request())
    {
        ReadFileListRequest(message.file_list_request());
    }
    else if (message.has_directory_size_request())
    {
        ReadDirectorySizeRequest(message.directory_size_request());
    }
    else if (message.has_create_directory_request())
    {
        ReadCreateDirectoryRequest(message.create_directory_request());
    }
    else if (message.has_rename_request())
    {
        ReadRenameRequest(message.rename_request());
    }
    else if (message.has_remove_request())
    {
        ReadRemoveRequest(message.remove_request());
    }
    else if (message.has_file_upload_request())
    {
        ReadFileUploadRequest(message.file_upload_request());
    }
    else if (message.has_file_packet())
    {
        if (!ReadFilePacket(message.file_packet()))
            ipc_channel_proxy_->Disconnect();
    }
    else if (message.has_file_download_request())
    {
        ReadFileDownloadRequest(message.file_download_request());
    }
    else if (message.has_file_packet_request())
    {
        if (!ReadFilePacketRequest())
            ipc_channel_proxy_->Disconnect();
    }
    else
    {
        LOG(ERROR) << "Unknown message from client";
        ipc_channel_proxy_->Disconnect();
    }
}

void HostSessionFileTransfer::SendReply(const proto::file_transfer::HostToClient& reply)
{
    ipc_channel_proxy_->Send(
        SerializeMessage<IOBuffer>(reply),
        std::bind(&HostSessionFileTransfer::OnReplySended, this));
}

void HostSessionFileTransfer::OnReplySended()
{
    // Receive next request.
    ipc_channel_proxy_->Receive(std::bind(
        &HostSessionFileTransfer::OnIpcChannelMessage, this, std::placeholders::_1));
}

void HostSessionFileTransfer::ReadDriveListRequest()
{
    proto::file_transfer::HostToClient reply;
    reply.set_status(ExecuteDriveListRequest(reply.mutable_drive_list()));

    if (reply.status() == proto::REQUEST_STATUS_SUCCESS)
    {
        status_dialog_->OnDriveListRequest();
    }

    SendReply(reply);
}

void HostSessionFileTransfer::ReadFileListRequest(const proto::FileListRequest& request)
{
    proto::file_transfer::HostToClient reply;

    FilePath path = std::experimental::filesystem::u8path(request.path());

    reply.set_status(ExecuteFileListRequest(path, reply.mutable_file_list()));

    if (reply.status() == proto::REQUEST_STATUS_SUCCESS)
    {
        status_dialog_->OnFileListRequest(path);
    }

    SendReply(reply);
}

void HostSessionFileTransfer::ReadCreateDirectoryRequest(
    const proto::CreateDirectoryRequest& request)
{
    proto::file_transfer::HostToClient reply;

    FilePath path = std::experimental::filesystem::u8path(request.path());

    reply.set_status(ExecuteCreateDirectoryRequest(path));

    if (reply.status() == proto::REQUEST_STATUS_SUCCESS)
    {
        status_dialog_->OnCreateDirectoryRequest(path);
    }

    SendReply(reply);
}

void HostSessionFileTransfer::ReadDirectorySizeRequest(const proto::DirectorySizeRequest& request)
{
    proto::file_transfer::HostToClient reply;

    FilePath path = std::experimental::filesystem::u8path(request.path());

    uint64_t directory_size = 0;

    reply.set_status(ExecuteDirectorySizeRequest(path, directory_size));
    reply.mutable_directory_size()->set_size(directory_size);

    SendReply(reply);
}

void HostSessionFileTransfer::ReadRenameRequest(const proto::RenameRequest& request)
{
    proto::file_transfer::HostToClient reply;

    FilePath old_name = std::experimental::filesystem::u8path(request.old_name());
    FilePath new_name = std::experimental::filesystem::u8path(request.new_name());

    reply.set_status(ExecuteRenameRequest(old_name, new_name));

    if (reply.status() == proto::REQUEST_STATUS_SUCCESS)
    {
        status_dialog_->OnRenameRequest(old_name, new_name);
    }

    SendReply(reply);
}

void HostSessionFileTransfer::ReadRemoveRequest(const proto::RemoveRequest& request)
{
    proto::file_transfer::HostToClient reply;

    FilePath path = std::experimental::filesystem::u8path(request.path());

    reply.set_status(ExecuteRemoveRequest(path));

    if (reply.status() == proto::REQUEST_STATUS_SUCCESS)
    {
        status_dialog_->OnRemoveRequest(path);
    }

    SendReply(reply);
}

void HostSessionFileTransfer::ReadFileUploadRequest(const proto::FileUploadRequest& request)
{
    proto::file_transfer::HostToClient reply;

    FilePath file_path = std::experimental::filesystem::u8path(request.file_path());

    do
    {
        if (!IsValidPathName(file_path))
        {
            reply.set_status(proto::REQUEST_STATUS_INVALID_PATH_NAME);
            break;
        }

        if (!request.overwrite())
        {
            if (PathExists(file_path))
            {
                reply.set_status(proto::REQUEST_STATUS_PATH_ALREADY_EXISTS);
                break;
            }
        }

        file_depacketizer_ = FileDepacketizer::Create(file_path, request.overwrite());
        if (!file_depacketizer_)
        {
            reply.set_status(proto::REQUEST_STATUS_FILE_CREATE_ERROR);
            break;
        }

        reply.set_status(proto::REQUEST_STATUS_SUCCESS);
    }
    while (false);

    if (reply.status() == proto::REQUEST_STATUS_SUCCESS)
    {
        status_dialog_->OnFileUploadRequest(file_path);
    }

    SendReply(reply);
}

bool HostSessionFileTransfer::ReadFilePacket(const proto::FilePacket& file_packet)
{
    if (!file_depacketizer_)
    {
        LOG(ERROR) << "Unexpected file packet";
        return false;
    }

    proto::file_transfer::HostToClient reply;

    if (!file_depacketizer_->ReadNextPacket(file_packet))
    {
        reply.set_status(proto::REQUEST_STATUS_FILE_WRITE_ERROR);
    }
    else
    {
        reply.set_status(proto::REQUEST_STATUS_SUCCESS);
    }

    if (file_packet.flags() & proto::FilePacket::LAST_PACKET)
    {
        file_depacketizer_.reset();
    }

    SendReply(reply);
    return true;
}

void HostSessionFileTransfer::ReadFileDownloadRequest(const proto::FileDownloadRequest& request)
{
    proto::file_transfer::HostToClient reply;

    FilePath file_path = std::experimental::filesystem::u8path(request.file_path());

    if (!IsValidPathName(file_path))
    {
        reply.set_status(proto::REQUEST_STATUS_INVALID_PATH_NAME);
    }
    else
    {
        file_packetizer_ = FilePacketizer::Create(file_path);
        if (!file_packetizer_)
        {
            reply.set_status(proto::REQUEST_STATUS_FILE_OPEN_ERROR);
        }
        else
        {
            reply.set_status(proto::REQUEST_STATUS_SUCCESS);
        }
    }

    SendReply(reply);
}

bool HostSessionFileTransfer::ReadFilePacketRequest()
{
    if (!file_packetizer_)
    {
        LOG(ERROR) << "Unexpected download data request";
        return false;
    }

    proto::file_transfer::HostToClient reply;

    std::unique_ptr<proto::FilePacket> packet = file_packetizer_->CreateNextPacket();
    if (!packet)
    {
        reply.set_status(proto::REQUEST_STATUS_FILE_READ_ERROR);
    }
    else
    {
        if (packet->flags() & proto::FilePacket::LAST_PACKET)
        {
            file_packetizer_.reset();
        }

        reply.set_status(proto::REQUEST_STATUS_SUCCESS);
        reply.set_allocated_file_packet(packet.release());
    }

    SendReply(reply);
    return true;
}

} // namespace aspia
<|endoftext|>


<commit_before>// Copyright (c) 2016, Joseph Mirabel
// Authors: Joseph Mirabel (joseph.mirabel@laas.fr)
//
// This file is part of hpp-pinocchio.
// hpp-pinocchio is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation, either version
// 3 of the License, or (at your option) any later version.
//
// hpp-pinocchio is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Lesser Public License for more details.  You should have
// received a copy of the GNU Lesser General Public License along with
// hpp-pinocchio. If not, see <http://www.gnu.org/licenses/>.

#include <hpp/pinocchio/urdf/util.hh>

#include <urdf_parser/urdf_parser.h>

#include <hpp/fcl/mesh_loader/loader.h>

#include <pinocchio/parsers/utils.hpp>
#include <pinocchio/parsers/urdf.hpp>
#include <pinocchio/multibody/geometry.hpp>
#include <pinocchio/algorithm/geometry.hpp>
#include <pinocchio/parsers/srdf.hpp>

#include <hpp/util/debug.hh>

#include <hpp/pinocchio/joint.hh>
#include <hpp/pinocchio/joint-collection.hh>
#include <hpp/pinocchio/device.hh>
#include <hpp/pinocchio/humanoid-robot.hh>

namespace hpp {
  namespace pinocchio {
    namespace urdf {
      namespace {
#ifdef HPP_DEBUG
        const bool verbose = true;
#else
        const bool verbose = false;
#endif

        JointPtr_t findSpecialJoint (const HumanoidRobotPtr_t& robot, const std::string& linkName)
        {
          return robot->getJointByBodyName (linkName);
        }

        void setSpecialJoints (const HumanoidRobotPtr_t& robot, std::string prefix)
        {
          if (!prefix.empty() && *prefix.rbegin() != '/') prefix += "/";
          try {
            robot->waist (robot->getJointByName(prefix + "root_joint"));
          } catch (const std::exception&) {
            hppDout (notice, "No waist joint found");
          }
          try {
            robot->chest (findSpecialJoint (robot, prefix + "chest"));
          } catch (const std::exception&) {
            hppDout (notice, "No chest joint found");
          }
          try {
            robot->leftWrist (findSpecialJoint (robot, prefix + "l_wrist"));
          } catch (const std::exception&) {
            hppDout (notice, "No left wrist joint found");
          }
          try {
            robot->rightWrist (findSpecialJoint (robot, prefix + "r_wrist"));
          } catch (const std::exception&) {
            hppDout (notice, "No right wrist joint found");
          }
          try {
            robot->leftAnkle (findSpecialJoint (robot, prefix + "l_ankle"));
          } catch (const std::exception&) {
            hppDout (notice, "No left ankle joint found");
          }
          try {
            robot->rightAnkle (findSpecialJoint (robot, prefix + "r_ankle"));
          } catch (const std::exception&) {
            hppDout (notice, "No right ankle joint found");
          }
          try {
            robot->gazeJoint (findSpecialJoint (robot, prefix + "gaze"));
          } catch (const std::exception&) {
            hppDout (notice, "No gaze joint found");
          }
        }

        void fillGaze (const HumanoidRobotPtr_t robot)
        {
          vector3_t dir, origin;
          // Gaze direction is defined by the gaze joint local
          // orientation.
          dir[0] = 1;
          dir[1] = 0;
          dir[2] = 0;
          // Gaze position should is defined by the gaze joint local
          // origin.
          origin[0] = 0;
          origin[1] = 0;
          origin[2] = 0;
          robot->gaze (dir, origin);
        }

        JointModelVariant buildJoint (const std::string& type)
        {
          if (type == "freeflyer")          return JointCollection::JointModelFreeFlyer();
          else if (type == "planar")        return JointCollection::JointModelPlanar();
          else if (type == "prismatic_x")   return JointCollection::JointModelPX();
          else if (type == "prismatic_y")   return JointCollection::JointModelPY();
          else if (type == "translation3d") return JointCollection::JointModelTranslation();
          else                          throw  std::invalid_argument
            ("Root joint type \"" + type + "\" is currently not available.");
        }

        void setPrefix (const std::string& prefix,
            Model& model, GeomModel& geomModel,
            const JointIndex& idFirstJoint,
            const FrameIndex& idFirstFrame)
        {
          for (JointIndex i = idFirstJoint; i < model.joints.size(); ++i) {
            model.names[i] = prefix + model.names[i];
          }
          for (FrameIndex i = idFirstFrame; i < model.frames.size(); ++i) {
            ::pinocchio::Frame& f = model.frames[i];
            f.name = prefix + f.name;
          }
          BOOST_FOREACH(::pinocchio::GeometryObject& go, geomModel.geometryObjects) {
            go.name = prefix + go.name;
          }
        }

        void setRootJointBounds(Model& model,
            const JointIndex& rtIdx,
            const std::string& rootType)
        {
          value_type b = std::numeric_limits<value_type>::infinity();
          if (rootType == "freeflyer") {
            const std::size_t idx = model.joints[rtIdx].idx_q();
            model.upperPositionLimit.segment<3>(idx).setConstant(+b);
            model.lowerPositionLimit.segment<3>(idx).setConstant(-b);
            // Quaternion bounds
            b = 1.01;
            const size_type quat_idx = idx + 3;
            model.upperPositionLimit.segment<4>(quat_idx).setConstant(+b);
            model.lowerPositionLimit.segment<4>(quat_idx).setConstant(-b);
          } else if (rootType == "planar") {
            const std::size_t idx = model.joints[rtIdx].idx_q();
            model.upperPositionLimit.segment<2>(idx).setConstant(+b);
            model.lowerPositionLimit.segment<2>(idx).setConstant(-b);
            // Unit complex bounds
            b = 1.01;
            const size_type cplx_idx = idx + 2;
            model.upperPositionLimit.segment<2>(cplx_idx).setConstant(+b);
            model.lowerPositionLimit.segment<2>(cplx_idx).setConstant(-b);
          }
        }

        std::string makeModelPath (const std::string& package,
                                   const std::string& type,
                                   const std::string& modelName,
                                   const std::string& suffix = "")
        {
          std::stringstream ss;
          ss << "package://" << package << "/" << type << "/" << modelName << suffix << "." << type;
          return ss.str();
        }

        template <bool XmlString>
        void _removeCollisionPairs (
            const Model& model,
            GeomModel& geomModel,
            const std::string& srdf,
            bool verbose)
        {
          ::pinocchio::srdf::removeCollisionPairsFromXML
            (model, geomModel, srdf, verbose);
        }

        template <>
        void _removeCollisionPairs<false> (
            const Model& model,
            GeomModel& geomModel,
            const std::string& srdf,
            bool verbose)
        {
          ::pinocchio::srdf::removeCollisionPairs
            (model, geomModel, srdf, verbose);
        }

        template <bool srdfAsXmlString>
        void _loadModel (const DevicePtr_t& robot,
                        const JointIndex&  baseJoint,
                        std::string prefix,
                        const std::string& rootType,
                        const ::urdf::ModelInterfaceSharedPtr urdfTree,
                        const std::istream& urdfStream,
                        const std::string& srdf)
        {
          if (!urdfTree)
            throw std::invalid_argument ("Failed to parse URDF. Use check_urdf command to know what's wrong.");
          if (baseJoint != 0)
            throw std::invalid_argument ("Only appending robots at the world is supported.");

          Model& model = robot->model();
          const JointIndex idFirstJoint = model.joints.size();
          const FrameIndex idFirstFrame = model.frames.size();
          if (rootType == "anchor")
            ::pinocchio::urdf::buildModel(urdfTree, model, verbose);
          else
            ::pinocchio::urdf::buildModel(urdfTree, buildJoint(rootType), model, verbose);
          robot->createData();

          hppDout (notice, "Finished parsing URDF file.");

          GeomModel geomModel;

          std::vector<std::string> baseDirs = ::pinocchio::rosPaths();
          fcl::MeshLoaderPtr loader (new fcl::CachedMeshLoader);
          ::pinocchio::urdf::buildGeom(model, urdfStream, ::pinocchio::COLLISION, geomModel, baseDirs, loader);
          geomModel.addAllCollisionPairs();

          if (!srdf.empty()) {
            _removeCollisionPairs<srdfAsXmlString>
              (model, geomModel, srdf, verbose);
            if(!srdfAsXmlString)
              se3::srdf::getNeutralConfigurationFromSrdf(model,srdf);
            else{
              hppDout(warning,"Neutral configuration won't be extracted from SRDF string.");
              //TODO : A method getNeutralConfigurationFromSrdfString must be added in Pinocchio,
              // similarly to removeCollisionPairsFromSrdf / removeCollisionPairsFromSrdfString
            }
          }

          if (!prefix.empty()) {
            if (*prefix.rbegin() != '/') prefix += "/";
            setPrefix(prefix, model, geomModel, idFirstJoint, idFirstFrame);
          }

          // Update root joint bounds
          assert((rootType == "anchor")
              || (model.names[idFirstJoint] == prefix + "root_joint"));
          setRootJointBounds(model, idFirstJoint, rootType);

          ::pinocchio::appendGeometryModel(robot->geomModel(), geomModel);
          robot->createGeomData();

          hppDout (notice, "Finished parsing SRDF file.");
        }

      }

      void loadRobotModel (const DevicePtr_t& robot,
			   const std::string& rootJointType,
			   const std::string& package,
			   const std::string& modelName,
			   const std::string& urdfSuffix,
                           const std::string& srdfSuffix)
      {
        loadModel (robot, 0, "", rootJointType,
            makeModelPath(package, "urdf", modelName, urdfSuffix),
            makeModelPath(package, "srdf", modelName, srdfSuffix));
      }

      void loadRobotModel (const DevicePtr_t& robot,
                           const JointIndex&  baseJoint,
			   const std::string& prefix,
			   const std::string& rootJointType,
			   const std::string& package,
			   const std::string& modelName,
			   const std::string& urdfSuffix,
                           const std::string& srdfSuffix)
      {
        loadModel (robot, baseJoint,
            (prefix.empty() ? "" : prefix + "/"),
            rootJointType,
            makeModelPath(package, "urdf", modelName, urdfSuffix),
            makeModelPath(package, "srdf", modelName, srdfSuffix));
      }

      void setupHumanoidRobot (const HumanoidRobotPtr_t& robot,
          const std::string& prefix)
      {
	// Look for special joints and attach them to the model.
	setSpecialJoints (robot, prefix);
	// Fill gaze position and direction.
	fillGaze (robot);
      }

      void loadUrdfModel (const DevicePtr_t& robot,
                          const JointIndex&  baseJoint,
                          const std::string& prefix,
			  const std::string& rootJointType,
			  const std::string& package,
			  const std::string& filename)
      {
        loadModel (robot, baseJoint,
            (prefix.empty() ? "" : prefix + "/"),
            rootJointType,
            makeModelPath(package, "urdf", filename), "");
      }

      void loadUrdfModel (const DevicePtr_t& robot,
			  const std::string& rootType,
			  const std::string& package,
			  const std::string& filename)
      {
        loadModel (robot, 0, "", rootType,
            makeModelPath(package, "urdf", filename), "");
      }

        void loadModel (const DevicePtr_t& robot,
                        const JointIndex&  baseJoint,
                        const std::string& prefix,
                        const std::string& rootType,
                        const std::string& urdfPath,
                        const std::string& srdfPath)
        {
          std::vector<std::string> baseDirs = ::pinocchio::rosPaths();

          std::string urdfFileName = ::pinocchio::retrieveResourcePath(urdfPath, baseDirs);
          if (urdfFileName == "") {
            throw std::invalid_argument (std::string ("Unable to retrieve ") +
                urdfPath);
          }

          std::string srdfFileName;
          if (!srdfPath.empty()) {
            srdfFileName = ::pinocchio::retrieveResourcePath(srdfPath, baseDirs);
            if (srdfFileName == "") {
              throw std::invalid_argument (std::string ("Unable to retrieve ") +
                  srdfPath);
            }
          }

          ::urdf::ModelInterfaceSharedPtr urdfTree = ::urdf::parseURDFFile(urdfFileName);
          std::ifstream urdfStream (urdfFileName.c_str());
          _loadModel <false> (robot, baseJoint, prefix, rootType,
              urdfTree, urdfStream, srdfFileName);
        }

        void loadModelFromString (const DevicePtr_t& robot,
                                  const JointIndex&  baseJoint,
                                  const std::string& prefix,
                                  const std::string& rootType,
                                  const std::string& urdfString,
                                  const std::string& srdfString)
        {
          ::urdf::ModelInterfaceSharedPtr urdfTree = ::urdf::parseURDF(urdfString);
          std::istringstream urdfStream (urdfString);
          _loadModel <true> (robot, baseJoint, prefix, rootType,
              urdfTree, urdfStream, srdfString);
        }
    } // end of namespace urdf.
  } // end of namespace pinocchio.
} // end of namespace  hpp.
<commit_msg>Update to Pinocchio v2<commit_after>// Copyright (c) 2016, Joseph Mirabel
// Authors: Joseph Mirabel (joseph.mirabel@laas.fr)
//
// This file is part of hpp-pinocchio.
// hpp-pinocchio is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation, either version
// 3 of the License, or (at your option) any later version.
//
// hpp-pinocchio is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Lesser Public License for more details.  You should have
// received a copy of the GNU Lesser General Public License along with
// hpp-pinocchio. If not, see <http://www.gnu.org/licenses/>.

#include <hpp/pinocchio/urdf/util.hh>

#include <urdf_parser/urdf_parser.h>

#include <hpp/fcl/mesh_loader/loader.h>

#include <pinocchio/parsers/utils.hpp>
#include <pinocchio/parsers/urdf.hpp>
#include <pinocchio/multibody/geometry.hpp>
#include <pinocchio/algorithm/geometry.hpp>
#include <pinocchio/parsers/srdf.hpp>

#include <hpp/util/debug.hh>

#include <hpp/pinocchio/joint.hh>
#include <hpp/pinocchio/joint-collection.hh>
#include <hpp/pinocchio/device.hh>
#include <hpp/pinocchio/humanoid-robot.hh>

namespace hpp {
  namespace pinocchio {
    namespace urdf {
      namespace {
#ifdef HPP_DEBUG
        const bool verbose = true;
#else
        const bool verbose = false;
#endif

        JointPtr_t findSpecialJoint (const HumanoidRobotPtr_t& robot, const std::string& linkName)
        {
          return robot->getJointByBodyName (linkName);
        }

        void setSpecialJoints (const HumanoidRobotPtr_t& robot, std::string prefix)
        {
          if (!prefix.empty() && *prefix.rbegin() != '/') prefix += "/";
          try {
            robot->waist (robot->getJointByName(prefix + "root_joint"));
          } catch (const std::exception&) {
            hppDout (notice, "No waist joint found");
          }
          try {
            robot->chest (findSpecialJoint (robot, prefix + "chest"));
          } catch (const std::exception&) {
            hppDout (notice, "No chest joint found");
          }
          try {
            robot->leftWrist (findSpecialJoint (robot, prefix + "l_wrist"));
          } catch (const std::exception&) {
            hppDout (notice, "No left wrist joint found");
          }
          try {
            robot->rightWrist (findSpecialJoint (robot, prefix + "r_wrist"));
          } catch (const std::exception&) {
            hppDout (notice, "No right wrist joint found");
          }
          try {
            robot->leftAnkle (findSpecialJoint (robot, prefix + "l_ankle"));
          } catch (const std::exception&) {
            hppDout (notice, "No left ankle joint found");
          }
          try {
            robot->rightAnkle (findSpecialJoint (robot, prefix + "r_ankle"));
          } catch (const std::exception&) {
            hppDout (notice, "No right ankle joint found");
          }
          try {
            robot->gazeJoint (findSpecialJoint (robot, prefix + "gaze"));
          } catch (const std::exception&) {
            hppDout (notice, "No gaze joint found");
          }
        }

        void fillGaze (const HumanoidRobotPtr_t robot)
        {
          vector3_t dir, origin;
          // Gaze direction is defined by the gaze joint local
          // orientation.
          dir[0] = 1;
          dir[1] = 0;
          dir[2] = 0;
          // Gaze position should is defined by the gaze joint local
          // origin.
          origin[0] = 0;
          origin[1] = 0;
          origin[2] = 0;
          robot->gaze (dir, origin);
        }

        JointModelVariant buildJoint (const std::string& type)
        {
          if (type == "freeflyer")          return JointCollection::JointModelFreeFlyer();
          else if (type == "planar")        return JointCollection::JointModelPlanar();
          else if (type == "prismatic_x")   return JointCollection::JointModelPX();
          else if (type == "prismatic_y")   return JointCollection::JointModelPY();
          else if (type == "translation3d") return JointCollection::JointModelTranslation();
          else                          throw  std::invalid_argument
            ("Root joint type \"" + type + "\" is currently not available.");
        }

        void setPrefix (const std::string& prefix,
            Model& model, GeomModel& geomModel,
            const JointIndex& idFirstJoint,
            const FrameIndex& idFirstFrame)
        {
          for (JointIndex i = idFirstJoint; i < model.joints.size(); ++i) {
            model.names[i] = prefix + model.names[i];
          }
          for (FrameIndex i = idFirstFrame; i < model.frames.size(); ++i) {
            ::pinocchio::Frame& f = model.frames[i];
            f.name = prefix + f.name;
          }
          BOOST_FOREACH(::pinocchio::GeometryObject& go, geomModel.geometryObjects) {
            go.name = prefix + go.name;
          }
        }

        void setRootJointBounds(Model& model,
            const JointIndex& rtIdx,
            const std::string& rootType)
        {
          value_type b = std::numeric_limits<value_type>::infinity();
          if (rootType == "freeflyer") {
            const std::size_t idx = model.joints[rtIdx].idx_q();
            model.upperPositionLimit.segment<3>(idx).setConstant(+b);
            model.lowerPositionLimit.segment<3>(idx).setConstant(-b);
            // Quaternion bounds
            b = 1.01;
            const size_type quat_idx = idx + 3;
            model.upperPositionLimit.segment<4>(quat_idx).setConstant(+b);
            model.lowerPositionLimit.segment<4>(quat_idx).setConstant(-b);
          } else if (rootType == "planar") {
            const std::size_t idx = model.joints[rtIdx].idx_q();
            model.upperPositionLimit.segment<2>(idx).setConstant(+b);
            model.lowerPositionLimit.segment<2>(idx).setConstant(-b);
            // Unit complex bounds
            b = 1.01;
            const size_type cplx_idx = idx + 2;
            model.upperPositionLimit.segment<2>(cplx_idx).setConstant(+b);
            model.lowerPositionLimit.segment<2>(cplx_idx).setConstant(-b);
          }
        }

        std::string makeModelPath (const std::string& package,
                                   const std::string& type,
                                   const std::string& modelName,
                                   const std::string& suffix = "")
        {
          std::stringstream ss;
          ss << "package://" << package << "/" << type << "/" << modelName << suffix << "." << type;
          return ss.str();
        }

        template <bool XmlString>
        void _removeCollisionPairs (
            const Model& model,
            GeomModel& geomModel,
            const std::string& srdf,
            bool verbose)
        {
          ::pinocchio::srdf::removeCollisionPairsFromXML
            (model, geomModel, srdf, verbose);
        }

        template <>
        void _removeCollisionPairs<false> (
            const Model& model,
            GeomModel& geomModel,
            const std::string& srdf,
            bool verbose)
        {
          ::pinocchio::srdf::removeCollisionPairs
            (model, geomModel, srdf, verbose);
        }

        template <bool srdfAsXmlString>
        void _loadModel (const DevicePtr_t& robot,
                        const JointIndex&  baseJoint,
                        std::string prefix,
                        const std::string& rootType,
                        const ::urdf::ModelInterfaceSharedPtr urdfTree,
                        const std::istream& urdfStream,
                        const std::string& srdf)
        {
          if (!urdfTree)
            throw std::invalid_argument ("Failed to parse URDF. Use check_urdf command to know what's wrong.");
          if (baseJoint != 0)
            throw std::invalid_argument ("Only appending robots at the world is supported.");

          Model& model = robot->model();
          const JointIndex idFirstJoint = model.joints.size();
          const FrameIndex idFirstFrame = model.frames.size();
          if (rootType == "anchor")
            ::pinocchio::urdf::buildModel(urdfTree, model, verbose);
          else
            ::pinocchio::urdf::buildModel(urdfTree, buildJoint(rootType), model, verbose);
          robot->createData();

          hppDout (notice, "Finished parsing URDF file.");

          GeomModel geomModel;

          std::vector<std::string> baseDirs = ::pinocchio::rosPaths();
          fcl::MeshLoaderPtr loader (new fcl::CachedMeshLoader);
          ::pinocchio::urdf::buildGeom(model, urdfStream, ::pinocchio::COLLISION, geomModel, baseDirs, loader);
          geomModel.addAllCollisionPairs();

          if (!srdf.empty()) {
            _removeCollisionPairs<srdfAsXmlString>
              (model, geomModel, srdf, verbose);
            if(!srdfAsXmlString)
              ::pinocchio::srdf::getNeutralConfiguration(model,srdf);
            else{
              hppDout(warning,"Neutral configuration won't be extracted from SRDF string.");
              //TODO : A method getNeutralConfigurationFromSrdfString must be added in Pinocchio,
              // similarly to removeCollisionPairsFromSrdf / removeCollisionPairsFromSrdfString
            }
          }

          if (!prefix.empty()) {
            if (*prefix.rbegin() != '/') prefix += "/";
            setPrefix(prefix, model, geomModel, idFirstJoint, idFirstFrame);
          }

          // Update root joint bounds
          assert((rootType == "anchor")
              || (model.names[idFirstJoint] == prefix + "root_joint"));
          setRootJointBounds(model, idFirstJoint, rootType);

          ::pinocchio::appendGeometryModel(robot->geomModel(), geomModel);
          robot->createGeomData();

          hppDout (notice, "Finished parsing SRDF file.");
        }

      }

      void loadRobotModel (const DevicePtr_t& robot,
			   const std::string& rootJointType,
			   const std::string& package,
			   const std::string& modelName,
			   const std::string& urdfSuffix,
                           const std::string& srdfSuffix)
      {
        loadModel (robot, 0, "", rootJointType,
            makeModelPath(package, "urdf", modelName, urdfSuffix),
            makeModelPath(package, "srdf", modelName, srdfSuffix));
      }

      void loadRobotModel (const DevicePtr_t& robot,
                           const JointIndex&  baseJoint,
			   const std::string& prefix,
			   const std::string& rootJointType,
			   const std::string& package,
			   const std::string& modelName,
			   const std::string& urdfSuffix,
                           const std::string& srdfSuffix)
      {
        loadModel (robot, baseJoint,
            (prefix.empty() ? "" : prefix + "/"),
            rootJointType,
            makeModelPath(package, "urdf", modelName, urdfSuffix),
            makeModelPath(package, "srdf", modelName, srdfSuffix));
      }

      void setupHumanoidRobot (const HumanoidRobotPtr_t& robot,
          const std::string& prefix)
      {
	// Look for special joints and attach them to the model.
	setSpecialJoints (robot, prefix);
	// Fill gaze position and direction.
	fillGaze (robot);
      }

      void loadUrdfModel (const DevicePtr_t& robot,
                          const JointIndex&  baseJoint,
                          const std::string& prefix,
			  const std::string& rootJointType,
			  const std::string& package,
			  const std::string& filename)
      {
        loadModel (robot, baseJoint,
            (prefix.empty() ? "" : prefix + "/"),
            rootJointType,
            makeModelPath(package, "urdf", filename), "");
      }

      void loadUrdfModel (const DevicePtr_t& robot,
			  const std::string& rootType,
			  const std::string& package,
			  const std::string& filename)
      {
        loadModel (robot, 0, "", rootType,
            makeModelPath(package, "urdf", filename), "");
      }

        void loadModel (const DevicePtr_t& robot,
                        const JointIndex&  baseJoint,
                        const std::string& prefix,
                        const std::string& rootType,
                        const std::string& urdfPath,
                        const std::string& srdfPath)
        {
          std::vector<std::string> baseDirs = ::pinocchio::rosPaths();

          std::string urdfFileName = ::pinocchio::retrieveResourcePath(urdfPath, baseDirs);
          if (urdfFileName == "") {
            throw std::invalid_argument (std::string ("Unable to retrieve ") +
                urdfPath);
          }

          std::string srdfFileName;
          if (!srdfPath.empty()) {
            srdfFileName = ::pinocchio::retrieveResourcePath(srdfPath, baseDirs);
            if (srdfFileName == "") {
              throw std::invalid_argument (std::string ("Unable to retrieve ") +
                  srdfPath);
            }
          }

          ::urdf::ModelInterfaceSharedPtr urdfTree = ::urdf::parseURDFFile(urdfFileName);
          std::ifstream urdfStream (urdfFileName.c_str());
          _loadModel <false> (robot, baseJoint, prefix, rootType,
              urdfTree, urdfStream, srdfFileName);
        }

        void loadModelFromString (const DevicePtr_t& robot,
                                  const JointIndex&  baseJoint,
                                  const std::string& prefix,
                                  const std::string& rootType,
                                  const std::string& urdfString,
                                  const std::string& srdfString)
        {
          ::urdf::ModelInterfaceSharedPtr urdfTree = ::urdf::parseURDF(urdfString);
          std::istringstream urdfStream (urdfString);
          _loadModel <true> (robot, baseJoint, prefix, rootType,
              urdfTree, urdfStream, srdfString);
        }
    } // end of namespace urdf.
  } // end of namespace pinocchio.
} // end of namespace  hpp.
<|endoftext|>


<commit_before>#include "util.h"

#include "function_traits.h"

#include "catch.h"

#include <limits>
#include <regex>

TEST_CASE("PrettyPrintNumBytes") {
  using T = function_traits<decltype(PrettyPrintNumBytes)>::argument<0>::type;
  constexpr T K = 1 << 10, M = 1 << 20, G = 1 << 30;

  // show exact numbers up to 1 KiB
  REQUIRE(PrettyPrintNumBytes(0) == "0 B");
  REQUIRE(PrettyPrintNumBytes(1) == "1 B");
  REQUIRE(PrettyPrintNumBytes(2) == "2 B");
  REQUIRE(PrettyPrintNumBytes(K - 1) == "1023 B");
  REQUIRE(PrettyPrintNumBytes(K    ) == "1 KiB");
  REQUIRE(PrettyPrintNumBytes(K + 1) == "1 KiB");

  // round up to 2 KiB starting at 1.5 KiB
  REQUIRE(PrettyPrintNumBytes(K + 511) == "1 KiB");
  REQUIRE(PrettyPrintNumBytes(K + 512) == "2 KiB");
  REQUIRE(PrettyPrintNumBytes(K + 513) == "2 KiB");

  // round up to 3 KiB starting at 2.5 KiB
  REQUIRE(PrettyPrintNumBytes(2*K + 511) == "2 KiB");
  REQUIRE(PrettyPrintNumBytes(2*K + 512) == "3 KiB");
  REQUIRE(PrettyPrintNumBytes(2*K + 513) == "3 KiB");

  // round up to 1 MiB starting at 1023.5 KiB
  REQUIRE(PrettyPrintNumBytes(M - 513) == "1023 KiB");
  REQUIRE(PrettyPrintNumBytes(M - 512) == "1 MiB");
  REQUIRE(PrettyPrintNumBytes(M - 511) == "1 MiB");

  // round up to 2 MiB starting at 1.5 MiB
  REQUIRE(PrettyPrintNumBytes(M + 512*K - 1) == "1 MiB");
  REQUIRE(PrettyPrintNumBytes(M + 512*K    ) == "2 MiB");
  REQUIRE(PrettyPrintNumBytes(M + 512*K + 1) == "2 MiB");

  // round up to 3 MiB starting at 2.5 MiB
  REQUIRE(PrettyPrintNumBytes(2*M + 512*K - 1) == "2 MiB");
  REQUIRE(PrettyPrintNumBytes(2*M + 512*K    ) == "3 MiB");
  REQUIRE(PrettyPrintNumBytes(2*M + 512*K + 1) == "3 MiB");

  // round up to 1 GiB starting at 1023.5 MiB
  REQUIRE(PrettyPrintNumBytes(G - 512*K - 1) == "1023 MiB");
  REQUIRE(PrettyPrintNumBytes(G - 512*K    ) == "1 GiB");
  REQUIRE(PrettyPrintNumBytes(G - 512*K + 1) == "1 GiB");

  constexpr T Max = std::numeric_limits<T>::max();
  REQUIRE(std::regex_match(PrettyPrintNumBytes(Max), std::regex("\\d+ EiB")));
}
<commit_msg>don't assume ULLONG_MAX is > 2^60<commit_after>#include "util.h"

#include "function_traits.h"

#include "catch.h"

#include <limits>
#include <regex>

TEST_CASE("PrettyPrintNumBytes") {
  using T = function_traits<decltype(PrettyPrintNumBytes)>::argument<0>::type;
  constexpr T K = 1 << 10, M = 1 << 20, G = 1 << 30;

  // show exact numbers up to 1 KiB
  REQUIRE(PrettyPrintNumBytes(0) == "0 B");
  REQUIRE(PrettyPrintNumBytes(1) == "1 B");
  REQUIRE(PrettyPrintNumBytes(2) == "2 B");
  REQUIRE(PrettyPrintNumBytes(K - 1) == "1023 B");
  REQUIRE(PrettyPrintNumBytes(K    ) == "1 KiB");
  REQUIRE(PrettyPrintNumBytes(K + 1) == "1 KiB");

  // round up to 2 KiB starting at 1.5 KiB
  REQUIRE(PrettyPrintNumBytes(K + 511) == "1 KiB");
  REQUIRE(PrettyPrintNumBytes(K + 512) == "2 KiB");
  REQUIRE(PrettyPrintNumBytes(K + 513) == "2 KiB");

  // round up to 3 KiB starting at 2.5 KiB
  REQUIRE(PrettyPrintNumBytes(2*K + 511) == "2 KiB");
  REQUIRE(PrettyPrintNumBytes(2*K + 512) == "3 KiB");
  REQUIRE(PrettyPrintNumBytes(2*K + 513) == "3 KiB");

  // round up to 1 MiB starting at 1023.5 KiB
  REQUIRE(PrettyPrintNumBytes(M - 513) == "1023 KiB");
  REQUIRE(PrettyPrintNumBytes(M - 512) == "1 MiB");
  REQUIRE(PrettyPrintNumBytes(M - 511) == "1 MiB");

  // round up to 2 MiB starting at 1.5 MiB
  REQUIRE(PrettyPrintNumBytes(M + 512*K - 1) == "1 MiB");
  REQUIRE(PrettyPrintNumBytes(M + 512*K    ) == "2 MiB");
  REQUIRE(PrettyPrintNumBytes(M + 512*K + 1) == "2 MiB");

  // round up to 3 MiB starting at 2.5 MiB
  REQUIRE(PrettyPrintNumBytes(2*M + 512*K - 1) == "2 MiB");
  REQUIRE(PrettyPrintNumBytes(2*M + 512*K    ) == "3 MiB");
  REQUIRE(PrettyPrintNumBytes(2*M + 512*K + 1) == "3 MiB");

  // round up to 1 GiB starting at 1023.5 MiB
  REQUIRE(PrettyPrintNumBytes(G - 512*K - 1) == "1023 MiB");
  REQUIRE(PrettyPrintNumBytes(G - 512*K    ) == "1 GiB");
  REQUIRE(PrettyPrintNumBytes(G - 512*K + 1) == "1 GiB");

  constexpr T Max = std::numeric_limits<T>::max();
  REQUIRE(std::regex_match(PrettyPrintNumBytes(Max), std::regex("\\d+ [A-Z]iB")));
}
<|endoftext|>


<commit_before>/**********************************************************************
 * $Id$
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************
 * $Log$
 * Revision 1.12  2004/05/05 13:08:01  strk
 * Leaks fixed, explicit allocations/deallocations reduced.
 *
 * Revision 1.11  2004/05/05 10:54:48  strk
 * Removed some private static heap explicit allocation, less cleanup done by
 * the unloader.
 *
 * Revision 1.10  2004/05/03 22:56:44  strk
 * leaks fixed, exception specification omitted.
 *
 * Revision 1.9  2004/05/03 17:15:38  strk
 * leaks on exception fixed.
 *
 * Revision 1.8  2004/05/03 10:43:43  strk
 * Exception specification considered harmful - left as comment.
 *
 * Revision 1.7  2004/04/30 09:15:28  strk
 * Enlarged exception specifications to allow for AssertionFailedException.
 * Added missing initializers.
 *
 * Revision 1.6  2004/04/23 00:02:18  strk
 * const-correctness changes
 *
 * Revision 1.5  2004/04/20 10:58:04  strk
 * More memory leaks removed.
 *
 * Revision 1.4  2004/04/19 15:14:46  strk
 * Added missing virtual destructor in SpatialIndex class.
 * Memory leaks fixes. Const and throw specifications added.
 *
 * Revision 1.3  2004/04/19 12:51:01  strk
 * Memory leaks fixes. Throw specifications added.
 *
 * Revision 1.2  2004/04/14 08:38:52  strk
 * BufferBuilder constructor missed to initialize workingPrecisionModel
 *
 * Revision 1.1  2004/04/10 08:40:01  ybychkov
 * "operation/buffer" upgraded to JTS 1.4
 *
 *
 **********************************************************************/

#include "../../headers/opBuffer.h"

namespace geos {

/**
* Compute the change in depth as an edge is crossed from R to L
*/
int BufferBuilder::depthDelta(Label *label) {
	int lLoc=label->getLocation(0, Position::LEFT);
	int rLoc=label->getLocation(0, Position::RIGHT);
	if (lLoc== Location::INTERIOR && rLoc== Location::EXTERIOR)
		return 1;
	else if (lLoc== Location::EXTERIOR && rLoc== Location::INTERIOR)
		return -1;
	return 0;
}

CGAlgorithms BufferBuilder::cga=RobustCGAlgorithms();

/**
* Creates a new BufferBuilder
*/
BufferBuilder::BufferBuilder() {
	workingPrecisionModel=NULL;
	graph=new PlanarGraph(new OverlayNodeFactory());
	quadrantSegments=OffsetCurveBuilder::DEFAULT_QUADRANT_SEGMENTS;
	endCapStyle=BufferOp::CAP_ROUND;
	edgeList=new EdgeList();
}

BufferBuilder::~BufferBuilder() {
	delete edgeList;
	delete graph;
}

/**
* Sets the number of segments used to approximate a angle fillet
*
* @param quadrantSegments the number of segments in a fillet for a quadrant
*/
void BufferBuilder::setQuadrantSegments(int nQuadrantSegments){
	quadrantSegments=nQuadrantSegments;
}

/**
* Sets the precision model to use during the curve computation and noding,
* if it is different to the precision model of the Geometry->
* If the precision model is less than the precision of the Geometry precision model,
* the Geometry must have previously been rounded to that precision->
*
* @param pm the precision model to use
*/
void BufferBuilder::setWorkingPrecisionModel(PrecisionModel *pm){
	workingPrecisionModel=pm;
}

void BufferBuilder::setEndCapStyle(int nEndCapStyle){
	endCapStyle=nEndCapStyle;
}

Geometry*
BufferBuilder::buffer(Geometry *g, double distance)
	// throw(GEOSException *)
{
	const PrecisionModel *precisionModel=workingPrecisionModel;
	if (precisionModel==NULL)
		precisionModel=g->getPrecisionModel();

	// factory must be the same as the one used by the input
	geomFact=g->getFactory();
	OffsetCurveBuilder curveBuilder=OffsetCurveBuilder(precisionModel, quadrantSegments);
	curveBuilder.setEndCapStyle(endCapStyle);
	OffsetCurveSetBuilder curveSetBuilder=OffsetCurveSetBuilder(g, distance, &curveBuilder);
	vector<SegmentString*> *bufferSegStrList=curveSetBuilder.getCurves();
	// short-circuit test
	if ((int)bufferSegStrList->size()<=0) {
		Geometry *emptyGeom=geomFact->createGeometryCollection(new vector<Geometry*>());
		return emptyGeom;
	}

	computeNodedEdges(bufferSegStrList, precisionModel);

	Geometry* resultGeom=NULL;
	vector<Geometry*> *resultPolyList=NULL;
	vector<BufferSubgraph*> *subgraphList=NULL;
	try {
		graph->addEdges(edgeList->getEdges());
		subgraphList=createSubgraphs(graph);
		PolygonBuilder polyBuilder=PolygonBuilder(geomFact,&cga);
		buildSubgraphs(subgraphList, &polyBuilder);
		resultPolyList=polyBuilder.getPolygons();
		resultGeom=geomFact->buildGeometry(resultPolyList);
	} catch (GEOSException *exc) {
		for (int i=0; i<subgraphList->size(); i++)
			delete (*subgraphList)[i];
		delete subgraphList;
		delete resultPolyList;
		throw;
	}
	for (int i=0; i<subgraphList->size(); i++)
		delete (*subgraphList)[i];
	delete subgraphList;
	delete resultPolyList;
	return resultGeom;
}

void
BufferBuilder::computeNodedEdges(vector<SegmentString*> *bufferSegStrList, const PrecisionModel *precisionModel)
	// throw(GEOSException *)
{
	//BufferCurveGraphNoder noder=new BufferCurveGraphNoder(geomFact->getPrecisionModel());
	IteratedNoder noder=IteratedNoder(precisionModel);
	vector<SegmentString*> *nodedSegStrings = NULL;

	try
	{
		nodedSegStrings=noder.node(bufferSegStrList);

		// DEBUGGING ONLY
		//BufferDebug->saveEdges(nodedEdges, "run" + BufferDebug->runCount + "_nodedEdges");
		for (int i=0;i<(int)nodedSegStrings->size();i++) {
			SegmentString *segStr=(*nodedSegStrings)[i];
			Label *oldLabel=(Label*) segStr->getContext();
			Edge *edge=new Edge((CoordinateList*) segStr->getCoordinates(), new Label(oldLabel));
			insertEdge(edge);
		}
		//saveEdges(edgeList->getEdges(), "run" + runCount + "_collapsedEdges");
	} catch (...) {
		delete nodedSegStrings;
		throw;
	}
	delete nodedSegStrings;
}

/**
* Inserted edges are checked to see if an identical edge already exists->
* If so, the edge is not inserted, but its label is merged
* with the existing edge->
*/
void BufferBuilder::insertEdge(Edge *e){
	//<FIX> MD 8 Oct 03  speed up identical edge lookup
	// fast lookup
	Edge *existingEdge=edgeList->findEqualEdge(e);
	// If an identical edge already exists, simply update its label
	if (existingEdge != NULL) {
		Label *existingLabel=existingEdge->getLabel();
		Label *labelToMerge=e->getLabel();
		// check if new edge is in reverse direction to existing edge
		// if so, must flip the label before merging it
		if (! existingEdge->isPointwiseEqual(e)) {
			labelToMerge=new Label(e->getLabel());
			labelToMerge->flip();
		}
		existingLabel->merge(labelToMerge);
		// compute new depth delta of sum of edges
		int mergeDelta=depthDelta(labelToMerge);
		int existingDelta=existingEdge->getDepthDelta();
		int newDelta=existingDelta + mergeDelta;
		existingEdge->setDepthDelta(newDelta);
		delete e;
	} else {   // no matching existing edge was found
		// add this new edge to the list of edges in this graph
		//e->setName(name + edges->size());
		edgeList->add(e);
		e->setDepthDelta(depthDelta(e->getLabel()));
	}
}

bool BufferSubgraphGT(BufferSubgraph *first, BufferSubgraph *second) {
	if (first->compareTo(second)>=0)
		return true;
	else
		return false;
}

vector<BufferSubgraph*>*
BufferBuilder::createSubgraphs(PlanarGraph *graph)
{
	vector<BufferSubgraph*> *subgraphList=new vector<BufferSubgraph*>();
	vector<Node*> *n=graph->getNodes();
	for (int i=0;i<(int)n->size();i++) {
		Node *node=(*n)[i];
		if (!node->isVisited()) {
			BufferSubgraph *subgraph=new BufferSubgraph(&cga);
			subgraph->create(node);
			subgraphList->push_back(subgraph);
		}
	}
	delete n;
	/**
	* Sort the subgraphs in descending order of their rightmost coordinate->
	* This ensures that when the Polygons for the subgraphs are built,
	* subgraphs for shells will have been built before the subgraphs for
	* any holes they contain->
	*/
	sort(subgraphList->begin(),subgraphList->end(),BufferSubgraphGT);
	return subgraphList;
}

/**
* Completes the building of the input subgraphs by depth-labelling them,
* and adds them to the PolygonBuilder->
* The subgraph list must be sorted in rightmost-coordinate order->
*
* @param subgraphList the subgraphs to build
* @param polyBuilder the PolygonBuilder which will build the final polygons
*/
void
BufferBuilder::buildSubgraphs(vector<BufferSubgraph*> *subgraphList,PolygonBuilder *polyBuilder)
{
	vector<BufferSubgraph*> *processedGraphs=new vector<BufferSubgraph*>();
	try {
		for (int i=0;i<(int)subgraphList->size();i++) {
			BufferSubgraph *subgraph=(*subgraphList)[i];
			Coordinate *p=subgraph->getRightmostCoordinate();
			SubgraphDepthLocater locater=SubgraphDepthLocater(processedGraphs);
			int outsideDepth=locater.getDepth(*p);
			subgraph->computeDepth(outsideDepth);
			subgraph->findResultEdges();
			processedGraphs->push_back(subgraph);
			polyBuilder->add(subgraph->getDirectedEdges(), subgraph->getNodes());
		}
	} catch (...) {
		delete processedGraphs;
		throw;
	}
	delete processedGraphs;
}
}
<commit_msg>Avoid use of copy c'tors on local objects initializzation<commit_after>/**********************************************************************
 * $Id$
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.refractions.net
 *
 * Copyright (C) 2001-2002 Vivid Solutions Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************
 * $Log$
 * Revision 1.13  2004/05/05 16:36:46  strk
 * Avoid use of copy c'tors on local objects initializzation
 *
 * Revision 1.12  2004/05/05 13:08:01  strk
 * Leaks fixed, explicit allocations/deallocations reduced.
 *
 * Revision 1.11  2004/05/05 10:54:48  strk
 * Removed some private static heap explicit allocation, less cleanup done by
 * the unloader.
 *
 * Revision 1.10  2004/05/03 22:56:44  strk
 * leaks fixed, exception specification omitted.
 *
 * Revision 1.9  2004/05/03 17:15:38  strk
 * leaks on exception fixed.
 *
 * Revision 1.8  2004/05/03 10:43:43  strk
 * Exception specification considered harmful - left as comment.
 *
 * Revision 1.7  2004/04/30 09:15:28  strk
 * Enlarged exception specifications to allow for AssertionFailedException.
 * Added missing initializers.
 *
 * Revision 1.6  2004/04/23 00:02:18  strk
 * const-correctness changes
 *
 * Revision 1.5  2004/04/20 10:58:04  strk
 * More memory leaks removed.
 *
 * Revision 1.4  2004/04/19 15:14:46  strk
 * Added missing virtual destructor in SpatialIndex class.
 * Memory leaks fixes. Const and throw specifications added.
 *
 * Revision 1.3  2004/04/19 12:51:01  strk
 * Memory leaks fixes. Throw specifications added.
 *
 * Revision 1.2  2004/04/14 08:38:52  strk
 * BufferBuilder constructor missed to initialize workingPrecisionModel
 *
 * Revision 1.1  2004/04/10 08:40:01  ybychkov
 * "operation/buffer" upgraded to JTS 1.4
 *
 *
 **********************************************************************/

#include "../../headers/opBuffer.h"

namespace geos {

/**
* Compute the change in depth as an edge is crossed from R to L
*/
int BufferBuilder::depthDelta(Label *label) {
	int lLoc=label->getLocation(0, Position::LEFT);
	int rLoc=label->getLocation(0, Position::RIGHT);
	if (lLoc== Location::INTERIOR && rLoc== Location::EXTERIOR)
		return 1;
	else if (lLoc== Location::EXTERIOR && rLoc== Location::INTERIOR)
		return -1;
	return 0;
}

CGAlgorithms BufferBuilder::cga=RobustCGAlgorithms();

/**
* Creates a new BufferBuilder
*/
BufferBuilder::BufferBuilder() {
	workingPrecisionModel=NULL;
	graph=new PlanarGraph(new OverlayNodeFactory());
	quadrantSegments=OffsetCurveBuilder::DEFAULT_QUADRANT_SEGMENTS;
	endCapStyle=BufferOp::CAP_ROUND;
	edgeList=new EdgeList();
}

BufferBuilder::~BufferBuilder() {
	delete edgeList;
	delete graph;
}

/**
* Sets the number of segments used to approximate a angle fillet
*
* @param quadrantSegments the number of segments in a fillet for a quadrant
*/
void BufferBuilder::setQuadrantSegments(int nQuadrantSegments){
	quadrantSegments=nQuadrantSegments;
}

/**
* Sets the precision model to use during the curve computation and noding,
* if it is different to the precision model of the Geometry->
* If the precision model is less than the precision of the Geometry precision model,
* the Geometry must have previously been rounded to that precision->
*
* @param pm the precision model to use
*/
void BufferBuilder::setWorkingPrecisionModel(PrecisionModel *pm){
	workingPrecisionModel=pm;
}

void BufferBuilder::setEndCapStyle(int nEndCapStyle){
	endCapStyle=nEndCapStyle;
}

Geometry*
BufferBuilder::buffer(Geometry *g, double distance)
	// throw(GEOSException *)
{
	const PrecisionModel *precisionModel=workingPrecisionModel;
	if (precisionModel==NULL)
		precisionModel=g->getPrecisionModel();

	// factory must be the same as the one used by the input
	geomFact=g->getFactory();
	OffsetCurveBuilder curveBuilder(precisionModel, quadrantSegments);
	curveBuilder.setEndCapStyle(endCapStyle);
	OffsetCurveSetBuilder curveSetBuilder(g, distance, &curveBuilder);
	vector<SegmentString*> *bufferSegStrList=curveSetBuilder.getCurves();
	// short-circuit test
	if ((int)bufferSegStrList->size()<=0) {
		Geometry *emptyGeom=geomFact->createGeometryCollection(new vector<Geometry*>());
		return emptyGeom;
	}

	computeNodedEdges(bufferSegStrList, precisionModel);

	Geometry* resultGeom=NULL;
	vector<Geometry*> *resultPolyList=NULL;
	vector<BufferSubgraph*> *subgraphList=NULL;
	try {
		graph->addEdges(edgeList->getEdges());
		subgraphList=createSubgraphs(graph);
		PolygonBuilder polyBuilder(geomFact,&cga);
		buildSubgraphs(subgraphList, &polyBuilder);
		resultPolyList=polyBuilder.getPolygons();
		resultGeom=geomFact->buildGeometry(resultPolyList);
	} catch (GEOSException *exc) {
		for (int i=0; i<subgraphList->size(); i++)
			delete (*subgraphList)[i];
		delete subgraphList;
		delete resultPolyList;
		throw;
	}
	for (int i=0; i<subgraphList->size(); i++)
		delete (*subgraphList)[i];
	delete subgraphList;
	delete resultPolyList;
	return resultGeom;
}

void
BufferBuilder::computeNodedEdges(vector<SegmentString*> *bufferSegStrList, const PrecisionModel *precisionModel)
	// throw(GEOSException *)
{
	//BufferCurveGraphNoder noder=new BufferCurveGraphNoder(geomFact->getPrecisionModel());
	IteratedNoder noder(precisionModel);
	vector<SegmentString*> *nodedSegStrings = NULL;

	try
	{
		nodedSegStrings=noder.node(bufferSegStrList);

		// DEBUGGING ONLY
		//BufferDebug->saveEdges(nodedEdges, "run" + BufferDebug->runCount + "_nodedEdges");
		for (int i=0;i<(int)nodedSegStrings->size();i++) {
			SegmentString *segStr=(*nodedSegStrings)[i];
			Label *oldLabel=(Label*) segStr->getContext();
			Edge *edge=new Edge((CoordinateList*) segStr->getCoordinates(), new Label(oldLabel));
			insertEdge(edge);
		}
		//saveEdges(edgeList->getEdges(), "run" + runCount + "_collapsedEdges");
	} catch (...) {
		delete nodedSegStrings;
		throw;
	}
	delete nodedSegStrings;
}

/**
* Inserted edges are checked to see if an identical edge already exists->
* If so, the edge is not inserted, but its label is merged
* with the existing edge->
*/
void BufferBuilder::insertEdge(Edge *e){
	//<FIX> MD 8 Oct 03  speed up identical edge lookup
	// fast lookup
	Edge *existingEdge=edgeList->findEqualEdge(e);
	// If an identical edge already exists, simply update its label
	if (existingEdge != NULL) {
		Label *existingLabel=existingEdge->getLabel();
		Label *labelToMerge=e->getLabel();
		// check if new edge is in reverse direction to existing edge
		// if so, must flip the label before merging it
		if (! existingEdge->isPointwiseEqual(e)) {
			labelToMerge=new Label(e->getLabel());
			labelToMerge->flip();
		}
		existingLabel->merge(labelToMerge);
		// compute new depth delta of sum of edges
		int mergeDelta=depthDelta(labelToMerge);
		int existingDelta=existingEdge->getDepthDelta();
		int newDelta=existingDelta + mergeDelta;
		existingEdge->setDepthDelta(newDelta);
		delete e;
	} else {   // no matching existing edge was found
		// add this new edge to the list of edges in this graph
		//e->setName(name + edges->size());
		edgeList->add(e);
		e->setDepthDelta(depthDelta(e->getLabel()));
	}
}

bool BufferSubgraphGT(BufferSubgraph *first, BufferSubgraph *second) {
	if (first->compareTo(second)>=0)
		return true;
	else
		return false;
}

vector<BufferSubgraph*>*
BufferBuilder::createSubgraphs(PlanarGraph *graph)
{
	vector<BufferSubgraph*> *subgraphList=new vector<BufferSubgraph*>();
	vector<Node*> *n=graph->getNodes();
	for (int i=0;i<(int)n->size();i++) {
		Node *node=(*n)[i];
		if (!node->isVisited()) {
			BufferSubgraph *subgraph=new BufferSubgraph(&cga);
			subgraph->create(node);
			subgraphList->push_back(subgraph);
		}
	}
	delete n;
	/**
	* Sort the subgraphs in descending order of their rightmost coordinate->
	* This ensures that when the Polygons for the subgraphs are built,
	* subgraphs for shells will have been built before the subgraphs for
	* any holes they contain->
	*/
	sort(subgraphList->begin(),subgraphList->end(),BufferSubgraphGT);
	return subgraphList;
}

/**
* Completes the building of the input subgraphs by depth-labelling them,
* and adds them to the PolygonBuilder->
* The subgraph list must be sorted in rightmost-coordinate order->
*
* @param subgraphList the subgraphs to build
* @param polyBuilder the PolygonBuilder which will build the final polygons
*/
void
BufferBuilder::buildSubgraphs(vector<BufferSubgraph*> *subgraphList,PolygonBuilder *polyBuilder)
{
	vector<BufferSubgraph*> *processedGraphs=new vector<BufferSubgraph*>();
	try {
		for (int i=0;i<(int)subgraphList->size();i++) {
			BufferSubgraph *subgraph=(*subgraphList)[i];
			Coordinate *p=subgraph->getRightmostCoordinate();
			SubgraphDepthLocater locater=SubgraphDepthLocater(processedGraphs);
			int outsideDepth=locater.getDepth(*p);
			subgraph->computeDepth(outsideDepth);
			subgraph->findResultEdges();
			processedGraphs->push_back(subgraph);
			polyBuilder->add(subgraph->getDirectedEdges(), subgraph->getNodes());
		}
	} catch (...) {
		delete processedGraphs;
		throw;
	}
	delete processedGraphs;
}
}
<|endoftext|>