text:
/*
 * Copyright 2016-2021 Aaron Barany
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "Compiler.h"
#include <MSL/Compile/Output.h>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/lexical_cast.hpp>
#include <atomic>
#include <cstring>

#include <spirv-tools/optimizer.hpp>

#if MSL_GCC || MSL_CLANG
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wsign-compare"
#elif MSL_MSC
#pragma warning(push)
#pragma warning(disable: 4018)
#endif

#include "SPIRV/GlslangToSpv.h"
#include "SPIRV/SPVRemapper.h"
#include "OGLCompilersDLL/InitializeDll.h"
#include "StandAlone/ResourceLimits.h"

#if MSL_GCC || MSL_CLANG
#pragma GCC diagnostic pop
#elif MSL_MSC
#pragma warning(pop)
#endif

namespace msl
{

static const EShLanguage stageMap[] =
{
	EShLangVertex,
	EShLangTessControl,
	EShLangTessEvaluation,
	EShLangGeometry,
	EShLangFragment,
	EShLangCompute
};

static_assert(sizeof(stageMap)/sizeof(*stageMap) == stageCount,
	"Stage map has an incorrect number of elements");

static EShMessages glslMessages =
	static_cast<EShMessages>(EShMsgDefault | EShMsgSpvRules | EShMsgVulkanRules);

static std::atomic<unsigned int> initCounter;

static void addToOutput(Output& output, const std::string& baseFileName,
	const std::vector<Parser::LineMapping>& lineMappings, const std::string& infoStr,
	std::size_t defaultLineNumber = 0)
{
	const char* warningPrefix = "WARNING: ";
	const char* errorPrefix = "ERROR: ";
	const char* internalErrorPrefix = "INTERNAL ERROR: ";
	const char* unimplementedPrefix = "UNIMPLEMENTED: ";
	const char* notePrefix = "NOTE: ";
	const char* unknownPrefix = "UNKNOWN ERROR: ";

	const char* ignoreMessages[] =
	{
		"No code generated.",
		"most version-specific features are present, but some are missing.",
		"stage:",
		"all default precisions are highp; use precision statements to quiet warning, e.g.:",
		"\"precision mediump int; precision highp float;\""
	};

	for (std::size_t start = 0; start < infoStr.size();)
	{
		std::size_t end = infoStr.find_first_of('\n', start);
		std::size_t curLen;
		if (end == std::string::npos)
			curLen = std::string::npos;
		else
			curLen = end - start;
		std::string curMessage = infoStr.substr(start, curLen);
		boost::algorithm::trim(curMessage);

		bool ignored = false;
		for (const char* suffix : ignoreMessages)
		{
			if (boost::algorithm::ends_with(curMessage, suffix))
			{
				ignored = true;
				break;
			}
		}

		if (curMessage.empty() || ignored)
		{
			start = end;
			if (start != std::string::npos)
				++start;
			continue;
		}

		std::string prefix;
		Output::Level level = Output::Level::Info;
		if (boost::algorithm::starts_with(curMessage, warningPrefix))
		{
			curMessage = curMessage.substr(std::strlen(warningPrefix));
			level = Output::Level::Warning;
		}
		else if (boost::algorithm::starts_with(curMessage, errorPrefix))
		{
			curMessage = curMessage.substr(std::strlen(errorPrefix));
			level = Output::Level::Error;
		}
		else if (boost::algorithm::starts_with(curMessage, internalErrorPrefix))
		{
			curMessage = curMessage.substr(std::strlen(internalErrorPrefix));
			level = Output::Level::Error;
			prefix = "internal error: ";
		}
		else if (boost::algorithm::starts_with(curMessage, unimplementedPrefix))
		{
			curMessage = curMessage.substr(std::strlen(unimplementedPrefix));
			level = Output::Level::Error;
			prefix = "unimplemented: ";
		}
		else if (boost::algorithm::starts_with(curMessage, notePrefix))
		{
			curMessage = curMessage.substr(std::strlen(notePrefix));
			level = Output::Level::Info;
		}
		else if (boost::algorithm::starts_with(curMessage, unknownPrefix))
		{
			curMessage = curMessage.substr(std::strlen(unknownPrefix));
			level = Output::Level::Error;
		}

		const char* fileName = nullptr;;
		std::size_t lineNumber = 0;
		std::size_t separator = curMessage.find_first_of(':');
		if (separator != std::string::npos)
		{
			std::size_t endLineNumber = curMessage.find_first_of(':', separator + 1);
			if (endLineNumber != std::string::npos)
			{
				try
				{
					lineNumber = boost::lexical_cast<std::size_t>(curMessage.substr(separator + 1,
						endLineNumber - separator - 1)) - 1;
					if (lineNumber < lineMappings.size())
					{
						fileName = lineMappings[lineNumber].fileName;
						lineNumber = lineMappings[lineNumber].line;
						curMessage = curMessage.substr(endLineNumber + 2);
					}
				}
				catch (...)
				{
				}
			}
		}

		if (!fileName)
		{
			fileName = baseFileName.c_str();
			lineNumber = defaultLineNumber;
		}

		output.addMessage(level, fileName, lineNumber, 0, false, prefix + curMessage);

		start = end;
		if (start != std::string::npos)
			++start;
	}
}

static bool addToOutput(Output &output, const spv::SpvBuildLogger& logger,
	const std::string& fileName, std::size_t line, std::size_t column)
{
	std::string messages = logger.getAllMessages();
	if (messages.empty())
		return false;

	const char* tbdFeaturePrefix = "TBD functionality: ";
	const char* missingFeaturePrefix = "Missing functionality: ";
	const char* warningPrefix = "warning: ";
	const char* errorPrefix = "error: ";

	for (std::size_t start = 0; start < messages.size();)
	{
		std::size_t end = messages.find_first_of('\n', start);
		std::size_t curLen;
		if (end == std::string::npos)
			curLen = std::string::npos;
		else
			curLen = end - start;
		std::string curMessage = messages.substr(start, curLen);
		boost::algorithm::trim(curMessage);

		std::string prefix;
		Output::Level level = Output::Level::Error;
		if (boost::algorithm::starts_with(curMessage, tbdFeaturePrefix))
		{
			curMessage = curMessage.substr(std::strlen(tbdFeaturePrefix));
			level = Output::Level::Error;
			prefix = "tbd feature: ";
		}
		else if (boost::algorithm::starts_with(curMessage, missingFeaturePrefix))
		{
			curMessage = curMessage.substr(std::strlen(errorPrefix));
			level = Output::Level::Error;
			prefix = "missing feature: ";
		}
		else if (boost::algorithm::starts_with(curMessage, warningPrefix))
		{
			curMessage = curMessage.substr(std::strlen(warningPrefix));
			level = Output::Level::Warning;
		}
		else if (boost::algorithm::starts_with(curMessage, errorPrefix))
		{
			curMessage = curMessage.substr(std::strlen(errorPrefix));
			level = Output::Level::Error;
		}

		output.addMessage(level, fileName, line, column, false, prefix + curMessage);

		start = end;
		if (start != std::string::npos)
			++start;
	}

	return true;
}

Compiler::Stages::Stages()
{
}

Compiler::Stages::~Stages()
{
}

Compiler::Program::Program()
	: program(new glslang::TProgram)
{
}

Compiler::Program::~Program()
{
}

void Compiler::initialize()
{
	if (initCounter++ == 0)
		glslang::InitializeProcess();
}

void Compiler::shutdown()
{
	if (--initCounter == 0)
		glslang::FinalizeProcess();
}

const TBuiltInResource& Compiler::getDefaultResources()
{
	return glslang::DefaultTBuiltInResource;
}

bool Compiler::compile(Stages& stages, Output &output, const std::string& baseFileName,
	const std::string& glsl, const std::vector<Parser::LineMapping>& lineMappings,
	Stage stage, const TBuiltInResource& resources)
{
	const char* glslStr = glsl.c_str();
	std::unique_ptr<glslang::TShader> shader(
		new glslang::TShader(stageMap[static_cast<unsigned int>(stage)]));
	shader->setStrings(&glslStr, 1);
	shader->setAutoMapBindings(true);
	shader->setAutoMapLocations(true);

	bool success = shader->parse(&resources, 450, ECoreProfile, true, false, glslMessages);
	addToOutput(output, baseFileName, lineMappings, shader->getInfoLog());

	if (success)
		stages.shaders[static_cast<unsigned int>(stage)] = std::move(shader);
	return success;
}

bool Compiler::link(Program& program, Output& output, const Parser::Pipeline& pipeline,
	const Stages& stages)
{
	for (unsigned int i = 0; i < stageCount; ++i)
	{
		if (stages.shaders[i])
			program.program->addShader(stages.shaders[i].get());
	}

	bool success = program.program->link(glslMessages);
	std::vector<Parser::LineMapping> dummyLineMappings;
	addToOutput(output, pipeline.token->fileName, dummyLineMappings, program.program->getInfoLog(),
		pipeline.token->line);
	return success;
}

Compiler::SpirV Compiler::assemble(Output& output, const Program& program,
	Stage stage, const Parser::Pipeline& pipeline)
{
	glslang::TIntermediate* intermediate = program.program->getIntermediate(
		stageMap[static_cast<unsigned int>(stage)]);

	if (!intermediate)
		return SpirV();

	SpirV spirv;
	spv::SpvBuildLogger logger;
	glslang::GlslangToSpv(*intermediate, spirv, &logger);
	if (addToOutput(output, logger, pipeline.token->fileName, pipeline.token->line,
		pipeline.token->column))
	{
		return SpirV();
	}

	return spirv;
}

void Compiler::process(SpirV& spirv, int processOptions)
{
	if (processOptions == 0)
		return;

	std::uint32_t options = 0;
	if (processOptions & RemapVariables)
		options |= spv::spirvbin_t::MAP_ALL;
	if (processOptions & DeadCodeElimination)
		options |= spv::spirvbin_t::DCE_ALL;
	if (processOptions & StripDebug)
		options |= spv::spirvbin_t::STRIP;

	spv::spirvbin_t remapper;
	remapper.remap(spirv, options);

	if (processOptions & Optimize)
	{
		// NOTE: We have some known invalid code, such as missing bindings. Therefore we need to
		// skip validation.
		spv_optimizer_options options = spvOptimizerOptionsCreate();
		spvOptimizerOptionsSetRunValidator(options, false);
		spvtools::Optimizer optimizer(SPV_ENV_VULKAN_1_0);
		optimizer.RegisterPerformancePasses();
		SpirV optimizedSpirV;
		if (optimizer.Run(spirv.data(), spirv.size(), &optimizedSpirV, options))
			spirv = std::move(optimizedSpirV);
		spvOptimizerOptionsDestroy(options);
	}
}

} // namespace msl


text:
/*==============================================================================
  Copyright (c) 2017, 2018 Matt Calabrese

  Distributed under the Boost Software License, Version 1.0. (See accompanying
  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/

#ifndef ARGOT_NO_UNIQUE_ADDRESS_HPP_
#define ARGOT_NO_UNIQUE_ADDRESS_HPP_

#include <boost/predef.h>

#if __has_cpp_attribute( no_unique_address )
#define ARGOT_NO_UNIQUE_ADDRESS [[no_unique_address]]
#else
#define ARGOT_NO_UNIQUE_ADDRESS
#endif  // __has_cpp_attribute( no_unique_address )

// GCC screws up [[no_unique_address]] for unions in a way that ICEs
#if BOOST_COMP_GNUC
#define ARGOT_DETAIL_NO_UNIQUE_ADDRESS_FOR_UNION
#else
#define ARGOT_DETAIL_NO_UNIQUE_ADDRESS_FOR_UNION ARGOT_NO_UNIQUE_ADDRESS
#endif

#endif  // ARGOT_NO_UNIQUE_ADDRESS_HPP_

ext: hpp

max_stars_repo_name: mattcalabrese/argot

max_issues_repo_name: mattcalabrese/argot

max_forks_repo_name: mattcalabrese/argot


text:
#ifndef ASLAM_CAMERAS_TRIANGULATION_HPP
#define ASLAM_CAMERAS_TRIANGULATION_HPP

#include <Eigen/Core>

namespace aslam {
namespace cameras {

/// \brief Closed form linear triangulation
///
/// Returns the point that is in between the closest point
/// between the two lines. The gap is the distance between
/// the two lines. s0 and s1 are the distance along each ray
/// to the closest point
void triangulate(const Eigen::Vector3d& point0, const Eigen::Vector3d& ray0, const Eigen::Vector3d& point1,
                 const Eigen::Vector3d& ray1, Eigen::Vector3d& outTriangulatedPoint, double& outGap, double& outS0,
                 double& outS1);
}  // namespace cameras
}  // namespace aslam

#endif /* ASLAM_CAMERAS_TRIANGULATION_HPP */

max_stars_repo_name: chengfzy/kalibr

max_issues_repo_name: chengfzy/kalibr

max_forks_repo_name: chengfzy/kalibr


text:
/************************************************************************/
/*                                                                      */
/*     Copyright 2011-2012 Stefan Schmidt and Ullrich Koethe            */
/*                                                                      */
/*    This file is part of the VIGRA computer vision library.           */
/*    The VIGRA Website is                                              */
/*        http://hci.iwr.uni-heidelberg.de/vigra/                       */
/*    Please direct questions, bug reports, and contributions to        */
/*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
/*        vigra@informatik.uni-hamburg.de                               */
/*                                                                      */
/*    Permission is hereby granted, free of charge, to any person       */
/*    obtaining a copy of this software and associated documentation    */
/*    files (the "Software"), to deal in the Software without           */
/*    restriction, including without limitation the rights to use,      */
/*    copy, modify, merge, publish, distribute, sublicense, and/or      */
/*    sell copies of the Software, and to permit persons to whom the    */
/*    Software is furnished to do so, subject to the following          */
/*    conditions:                                                       */
/*                                                                      */
/*    The above copyright notice and this permission notice shall be    */
/*    included in all copies or substantial portions of the             */
/*    Software.                                                         */
/*                                                                      */
/*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
/*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
/*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
/*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
/*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
/*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
/*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
/*    OTHER DEALINGS IN THE SOFTWARE.                                   */
/*                                                                      */
/************************************************************************/

/**
 * This header provides definitions of graph-related types
 * and optionally provides a gateway to popular graph libraries
 * (for now, BGL is supported).
 */

#ifndef VIGRA_PYTHON_GRAPH_HXX
#define VIGRA_PYTHON_GRAPH_HXX

/*boost*/
#include <boost/python.hpp>
#include <boost/iterator/transform_iterator.hpp>

/*vigra*/
#include <vigra/graphs.hxx>
#include <vigra/numpy_array.hxx>
#include <vigra/multi_gridgraph.hxx>
#include <vigra/graph_generalization.hxx>
#include <vigra/multi_array.hxx>
#include <vigra/graphs.hxx>
#include <vigra/priority_queue.hxx>
#include <vigra/merge_graph_adaptor.hxx>
namespace vigra{

template<class MAP>
struct GraphMapTypeTraits;

template< unsigned int DIM,class T>
struct GraphMapTypeTraits<NumpyArray<DIM,T> >{
    typedef typename NumpyArray<DIM,T>::value_type Value;
    typedef Value &                                Reference;
    typedef const Value  &                         ConstReference;
};

template<class GRAPH>
struct NodeHolder :  GRAPH::Node
{
    typedef typename GRAPH::Node Node;
    NodeHolder(const lemon::Invalid & iv = lemon::INVALID)
    : Node(lemon::INVALID),
      graph_(NULL)
    {}
    NodeHolder(const GRAPH & g , const Node & item)
    : Node(item),
      graph_(&g)
    {}

    typename GRAPH::index_type id()const{
        return graph_->id(*this);
    }

    typename GraphDescriptorToMultiArrayIndex<GRAPH>::IntrinsicNodeMapShape
    intrinsicNodeCoordinate()const{
        return GraphDescriptorToMultiArrayIndex<GRAPH>::intrinsicNodeCoordinate(*graph_,*this);
    }

    const GRAPH * graph_;
};

template<class GRAPH>
struct EdgeHolder : GRAPH::Edge
{

    typedef typename GRAPH::Edge Edge;
    EdgeHolder(const lemon::Invalid & iv = lemon::INVALID)
    : Edge(lemon::INVALID),
      graph_(NULL)
    {}
    EdgeHolder(const GRAPH & g , const Edge & item)
    : Edge(item),
      graph_(&g)
    {}

    typename GRAPH::index_type id()const{
        return graph_->id(*this);
    }

    NodeHolder<GRAPH> u()const{
        return NodeHolder<GRAPH>(*graph_,graph_->u(*this));
    }
    NodeHolder<GRAPH> v()const{
        return NodeHolder<GRAPH>(*graph_,graph_->v(*this));
    }

    typename GraphDescriptorToMultiArrayIndex<GRAPH>::IntrinsicEdgeMapShape
    intrinsicEdgeCoordinate()const{
        return GraphDescriptorToMultiArrayIndex<GRAPH>::intrinsicEdgeCoordinate(*graph_,*this);
    }

    const GRAPH * graph_;
};

template<class GRAPH>
struct ArcHolder: GRAPH::Arc {
    typedef typename GRAPH::Arc Arc;
    ArcHolder(const lemon::Invalid & iv = lemon::INVALID)
    : Arc(lemon::INVALID),
      graph_(NULL)
    {}
    ArcHolder(const GRAPH & g , const Arc & item)
    : Arc(item),
      graph_(&g)
    {}

    typename GRAPH::index_type id()const{
        return graph_->id(*this);
    }

    typename GraphDescriptorToMultiArrayIndex<GRAPH>::IntrinsicArcMapShape
    intrinsicArcCoordinate()const{
        return GraphDescriptorToMultiArrayIndex<GRAPH>::intrinsicArcCoordinate(*graph_,*this);
    }

    const GRAPH * graph_;
};

namespace detail_python_graph{

template<class GRAPH>
struct ArcToTargetNodeHolder{
    typedef typename GRAPH::Node Node;
    typedef typename GRAPH::Arc Arc;
    ArcToTargetNodeHolder(const GRAPH & graph)
    : graph_(&graph){
    }
    NodeHolder<GRAPH> operator()(const Arc & arc)const{
        return NodeHolder<GRAPH>(*graph_,graph_->target(arc));
    }
    const GRAPH * graph_;
};

template<class GRAPH>
struct ArcToEdgeHolder{
    typedef typename GRAPH::Edge Edge;
    typedef typename GRAPH::Arc Arc;
    ArcToEdgeHolder(const GRAPH & graph)
    : graph_(&graph){
    }
    EdgeHolder<GRAPH> operator()(const Arc & arc)const{
        const Edge edge(arc);
        return EdgeHolder<GRAPH>(*graph_,edge);
    }
    const GRAPH * graph_;
};

template<class GRAPH>
struct NodeToNodeHolder{
    typedef typename GRAPH::Node Node;
    NodeToNodeHolder(const GRAPH & graph)
    : graph_(&graph){
    }
    NodeHolder<GRAPH> operator()(const Node & node)const{
        return NodeHolder<GRAPH>(*graph_,node);
    }
    const GRAPH * graph_;
};

template<class GRAPH>
struct EdgeToEdgeHolder{
    typedef typename GRAPH::Edge Edge;
    EdgeToEdgeHolder(const GRAPH & graph)
    : graph_(&graph){
    }
    EdgeHolder<GRAPH> operator()(const Edge & edge)const{
        return EdgeHolder<GRAPH>(*graph_,edge);
    }
    const GRAPH * graph_;
};

} // end namespace detail_python_graph

template<class GRAPH>
struct NodeIteratorHolder{
    typedef typename GRAPH::Node Node;
    typedef typename GRAPH::NodeIt Iter;
    typedef detail_python_graph::NodeToNodeHolder<GRAPH> Transform;
    typedef boost::transform_iterator<Transform ,Iter ,NodeHolder<GRAPH>, NodeHolder<GRAPH> > const_iterator;
    NodeIteratorHolder(const GRAPH & graph,const Node & node = Node(lemon::INVALID) )
    : graph_(&graph),
      node_(node){
    }
    const_iterator begin()const{

        Iter iter = GraphIteratorAccessor<GRAPH>::nodesBegin(*graph_);
        return const_iterator(iter,Transform(*graph_));
    }
    const_iterator end()const{
        Iter iter = GraphIteratorAccessor<GRAPH>::nodesEnd(*graph_);
        return const_iterator(iter,Transform(*graph_));
    }
    const GRAPH * graph_;
    Node node_;
};

template<class GRAPH>
struct EdgeIteratorHolder{
    typedef typename GRAPH::Edge Edge;
    typedef typename GRAPH::EdgeIt Iter;
    typedef detail_python_graph::EdgeToEdgeHolder<GRAPH> Transform;
    typedef boost::transform_iterator<Transform ,Iter ,EdgeHolder<GRAPH>, EdgeHolder<GRAPH> > const_iterator;
    EdgeIteratorHolder(const GRAPH & graph,const Edge & edge = Edge(lemon::INVALID) )
    : graph_(&graph),
      edge_(edge){
    }
    const_iterator begin()const{

        Iter iter = GraphIteratorAccessor<GRAPH>::edgesBegin(*graph_);
        return const_iterator(iter,Transform(*graph_));
    }
    const_iterator end()const{
        Iter iter = GraphIteratorAccessor<GRAPH>::edgesEnd(*graph_);
        return const_iterator(iter,Transform(*graph_));
    }
    const GRAPH * graph_;
    Edge edge_;
};

template<class GRAPH>
struct NeighbourNodeIteratorHolder{
    typedef typename GRAPH::Node Node;
    typedef typename GRAPH::OutArcIt Iter;
    typedef detail_python_graph::ArcToTargetNodeHolder<GRAPH> Transform;
    typedef boost::transform_iterator<Transform ,Iter ,NodeHolder<GRAPH>, NodeHolder<GRAPH> > const_iterator;
    NeighbourNodeIteratorHolder(const GRAPH & graph,const Node & node)
    : graph_(&graph),
      node_(node){
    }
    const_iterator begin()const{
        Iter iter = GraphIteratorAccessor<GRAPH>::outArcBegin(*graph_,node_);
        return const_iterator(iter,Transform(*graph_));
    }
    const_iterator end()const{
        Iter iter = GraphIteratorAccessor<GRAPH>::outArcEnd(*graph_,node_);
        return const_iterator(iter,Transform(*graph_));
    }
    const GRAPH * graph_;
    Node node_;
};

template<class GRAPH>
struct IncEdgeIteratorHolder{
    typedef typename GRAPH::Node Node;
    typedef typename GRAPH::Edge Edge;
    typedef typename GRAPH::OutArcIt Iter;
    typedef detail_python_graph::ArcToEdgeHolder<GRAPH> Transform;
    typedef boost::transform_iterator<Transform ,Iter ,EdgeHolder<GRAPH>, EdgeHolder<GRAPH> > const_iterator;
    IncEdgeIteratorHolder(const GRAPH & graph,const Node & node)
    : graph_(&graph),
      node_(node){
    }
    const_iterator begin()const{
        Iter iter = GraphIteratorAccessor<GRAPH>::outArcBegin(*graph_,node_);
        return const_iterator(iter,Transform(*graph_));
    }
    const_iterator end()const{
        Iter iter = GraphIteratorAccessor<GRAPH>::outArcEnd(*graph_,node_);
        return const_iterator(iter,Transform(*graph_));
    }
    const GRAPH * graph_;
    Node node_;
};

template<class G,class AV>
class NumpyScalarEdgeMap{

public:
    typedef G  Graph;
    typedef AV ArrayView;
    typedef typename  Graph::Edge                Key;
    typedef typename  ArrayView::value_type      Value;
    typedef typename  ArrayView::reference       Reference;
    typedef typename  ArrayView::const_reference ConstReference;

    typedef typename  Graph::Edge                key_type;
    typedef typename  ArrayView::value_type      value_type;
    typedef typename  ArrayView::reference       reference;
    typedef typename  ArrayView::const_reference const_reference;

    NumpyScalarEdgeMap()
    :   graph_(NULL),
        array_(){
    }

    NumpyScalarEdgeMap(const Graph & graph,ArrayView array)
    :   graph_(&graph),
        array_(array){
    }

    Reference operator[](const Key & key){
        return array_[GraphDescriptorToMultiArrayIndex<Graph>::intrinsicEdgeCoordinate(*graph_,key)];
    }
    ConstReference operator[](const Key & key)const{
        return   array_[GraphDescriptorToMultiArrayIndex<Graph>::intrinsicEdgeCoordinate(*graph_,key)];
    }
private:
    bool any()const{
        return array_.any();
    }
    const Graph * graph_;
    MultiArrayView<IntrinsicGraphShape<Graph>::IntrinsicEdgeMapDimension,Value> array_;

};

template<class G,class AV>
class NumpyScalarNodeMap{

public:
    typedef G  Graph;
    typedef AV ArrayView;
    typedef typename  Graph::Node                Key;
    typedef typename  ArrayView::value_type      Value;
    typedef typename  ArrayView::reference       Reference;
    typedef typename  ArrayView::const_reference ConstReference;

    typedef typename  Graph::Node                key_type;
    typedef typename  ArrayView::value_type      value_type;
    typedef typename  ArrayView::reference       reference;
    typedef typename  ArrayView::const_reference const_reference;
    //typedef Value &                                Reference;
    //typedef const Value &                          ConstReference;

    NumpyScalarNodeMap()
    :   graph_(NULL),
        array_(){
    }

    NumpyScalarNodeMap(const Graph & graph,ArrayView array)
    :   graph_(&graph),
        array_(array){
    }

    Reference operator[](const Key & key){
        return array_[GraphDescriptorToMultiArrayIndex<Graph>::intrinsicNodeCoordinate(*graph_,key)];
    }
    ConstReference operator[](const Key & key)const{
        return   array_[GraphDescriptorToMultiArrayIndex<Graph>::intrinsicNodeCoordinate(*graph_,key)];
    }
    bool any()const{
        return array_.any();
    }
private:
    const Graph * graph_;
    MultiArrayView<IntrinsicGraphShape<Graph>::IntrinsicNodeMapDimension,Value> array_;

};

template<class G,class AV>
class NumpyMultibandNodeMap{

public:
    typedef G  Graph;
    typedef AV ArrayView;
    typedef typename  Graph::Node                Key;
    typedef typename  Graph::Node                key_type;

    //typedef typename  ArrayView::value_type      Value;
    //typedef typename  ArrayView::reference       Reference;
    //typedef typename  ArrayView::const_reference ConstReference;

    typedef  MultiArray<1,typename AV::value_type>           Value;
    typedef  MultiArrayView<1,typename AV::value_type>       Reference;
    typedef  MultiArrayView<1,typename AV::value_type> ConstReference;
    typedef  MultiArray<1,typename AV::value_type>           value_type;
    typedef  MultiArrayView<1,typename AV::value_type>       reference;
    typedef  MultiArrayView<1,typename AV::value_type> const_reference;
    //typedef Value &                                Reference;
    //typedef const Value &                          ConstReference;

    NumpyMultibandNodeMap()
    :   graph_(NULL),
        array_(){
    }

    NumpyMultibandNodeMap(const Graph & graph,ArrayView array)
    :   graph_(&graph),
        array_(array){
    }

    Reference operator[](const Key & key){
        return array_[GraphDescriptorToMultiArrayIndex<Graph>::intrinsicNodeCoordinate(*graph_,key)];
    }
    ConstReference operator[](const Key & key)const{
        return array_[GraphDescriptorToMultiArrayIndex<Graph>::intrinsicNodeCoordinate(*graph_,key)];
    }
    bool any()const{
        return array_.any();
    }
private:
    const Graph * graph_;
    mutable AV array_;

};

template<class G,class AV>
class NumpyMultibandEdgeMap{

public:
    typedef G  Graph;
    typedef AV ArrayView;
    typedef typename  Graph::Edge                Key;
    typedef typename  Graph::Edge                key_type;

    //typedef typename  ArrayView::value_type      Value;
    //typedef typename  ArrayView::reference       Reference;
    //typedef typename  ArrayView::const_reference ConstReference;

    typedef  MultiArray<1,typename AV::value_type>           Value;
    typedef  MultiArrayView<1,typename AV::value_type>       Reference;
    typedef  MultiArrayView<1,typename AV::value_type> ConstReference;
    typedef  MultiArray<1,typename AV::value_type>           value_type;
    typedef  MultiArrayView<1,typename AV::value_type>       reference;
    typedef  MultiArrayView<1,typename AV::value_type> const_reference;
    //typedef Value &                                Reference;
    //typedef const Value &                          ConstReference;

    NumpyMultibandEdgeMap()
    :   graph_(NULL),
        array_(){
    }

    NumpyMultibandEdgeMap(const Graph & graph,ArrayView array)
    :   graph_(&graph),
        array_(array){
    }

    Reference operator[](const Key & key){
        return array_[GraphDescriptorToMultiArrayIndex<Graph>::intrinsicEdgeCoordinate(*graph_,key)];
    }
    ConstReference operator[](const Key & key)const{
        return   array_[GraphDescriptorToMultiArrayIndex<Graph>::intrinsicEdgeCoordinate(*graph_,key)];
    }
    bool any()const{
        return array_.any();
    }
private:
    const Graph * graph_;
    mutable AV array_;

};

// tagged shape for lemon graphs
// edge map / node map / arc map
template<class G>
class TaggedGraphShape{
public:
    typedef G Graph;
    const static unsigned int ND = IntrinsicGraphShape<Graph>::IntrinsicNodeMapDimension;
    const static unsigned int ED = IntrinsicGraphShape<Graph>::IntrinsicEdgeMapDimension;
    const static unsigned int AD = IntrinsicGraphShape<Graph>::IntrinsicArcMapDimension;
    static TaggedShape  taggedNodeMapShape(const Graph & graph){
        return NumpyArray<ND,int>::ArrayTraits::taggedShape(IntrinsicGraphShape<Graph>::intrinsicNodeMapShape(graph),"n");
    }
    static TaggedShape  taggedEdgeMapShape(const Graph & graph){
        return NumpyArray<ED,int>::ArrayTraits::taggedShape(IntrinsicGraphShape<Graph>::intrinsicEdgeMapShape(graph),"e");
    }
    static TaggedShape  taggedArcMapShape(const Graph & graph){
        return NumpyArray<AD,int>::ArrayTraits::taggedShape(IntrinsicGraphShape<Graph>::intrinsicArcMapShape(graph),"e");
    }

    static AxisInfo  axistagsNodeMap(const Graph & graph){
        return AxisInfo("n");
    }
    static AxisInfo  axistagsEdgeMap(const Graph & graph){
        return AxisInfo("e");
    }
    static AxisTags  axistagsArcMap(const Graph & graph){
        return AxisInfo("e");
    }
};

// macro to specialize TaggedGraphShape for
// grid graphs up to 4 dimensions
#define VIGRA_MAKE_TAGGED_GRAPH_SHAPE_MACRO(DIM,tn,te,ta) \
template<class BOOST_DIRECTED_TAG> \
class TaggedGraphShape<GridGraph<DIM,BOOST_DIRECTED_TAG> >{ \
public: \
    typedef GridGraph<DIM,BOOST_DIRECTED_TAG> Graph; \
    const static unsigned int ND = IntrinsicGraphShape<Graph>::IntrinsicNodeMapDimension; \
    const static unsigned int ED = IntrinsicGraphShape<Graph>::IntrinsicEdgeMapDimension; \
    const static unsigned int AD = IntrinsicGraphShape<Graph>::IntrinsicArcMapDimension; \
    static TaggedShape  taggedNodeMapShape(const Graph & graph){ \
       return NumpyArray<ND,int>::ArrayTraits::taggedShape(IntrinsicGraphShape<Graph>::intrinsicNodeMapShape(graph),tn); \
    } \
    static TaggedShape  taggedEdgeMapShape(const Graph & graph){  \
       return NumpyArray<ED,int>::ArrayTraits::taggedShape(IntrinsicGraphShape<Graph>::intrinsicEdgeMapShape(graph),te);  \
    } \
    static TaggedShape  taggedArcMapShape(const Graph & graph){  \
       return NumpyArray<AD,int>::ArrayTraits::taggedShape(IntrinsicGraphShape<Graph>::intrinsicArcMapShape(graph),ta);  \
    } \
    static AxisInfo  axistagsNodeMap(const Graph & graph){ \
        return AxisInfo(tn); \
    } \
    static AxisInfo  axistagsEdgeMap(const Graph & graph){ \
        return AxisInfo(te); \
    } \
    static AxisTags  axistagsArcMap(const Graph & graph){ \
        return AxisInfo(ta); \
    } \
};

VIGRA_MAKE_TAGGED_GRAPH_SHAPE_MACRO(1,"x","xe","xe");
VIGRA_MAKE_TAGGED_GRAPH_SHAPE_MACRO(2,"xy","xye","xye");
VIGRA_MAKE_TAGGED_GRAPH_SHAPE_MACRO(3,"xyz","xyze","xyze");
VIGRA_MAKE_TAGGED_GRAPH_SHAPE_MACRO(4,"xyzt","xyzte","xyzte");

#undef VIGRA_MAKE_TAGGED_GRAPH_SHAPE_MACRO

/*
// TODO ASK UKOETHE FOR HELP HERE
template<unsigned int G_DIM ,class T,class G,unsigned int OG_DIM>
void reshapeNodeMapIfEmpty(
    const G & graph,
    const NumpyArray<OG_DIM,T> & otherArray,
    NumpyArray<G_DIM ,T> & toReshapeArray
){
    const static unsigned int GraphNodeMapDim = IntrinsicGraphShape<G>::IntrinsicNodeMapDimension;
    const static unsigned int OutShapeLength  = GraphNodeMapDim == G_DIM ? G_DIM  : GraphNodeMapDim +1;
    typedef typename MultiArray<OutShapeLength,int>::difference_type OutShapeType;
    OutShapeType outShape;
    for(size_t d=0;d<GraphNodeMapDim;++d){
        outShape[d]=IntrinsicGraphShape<G>::intrinsicNodeMapShape(graph)[d];
    }
    if( G_DIM == GraphNodeMapDim + 1){

        outShape[GraphNodeMapDim]=otherArray.shape(OG_DIM);
        if(GraphNodeMapDim==1)
            toReshapeArray.reshapeIfEmpty( NumpyArray<G_DIM ,T>::ArrayTraits::taggedShape(outShape,"xc"));
        else if(GraphNodeMapDim==2)
            toReshapeArray.reshapeIfEmpty( NumpyArray<G_DIM ,T>::ArrayTraits::taggedShape(outShape,"xyc"));
        else if(GraphNodeMapDim==3)
            toReshapeArray.reshapeIfEmpty( NumpyArray<G_DIM ,T>::ArrayTraits::taggedShape(outShape,"xyzc"));
        else if(GraphNodeMapDim==4)
            toReshapeArray.reshapeIfEmpty( NumpyArray<G_DIM ,T>::ArrayTraits::taggedShape(outShape,"xyztc"));
        else
            throw std::runtime_error("reshapeNodeMapIfEmpty does onnly support graphs with an intrinsic node map shape <=4");
    }
    else{
        toReshapeArray.reshapeIfEmpty(outShape);
    }
}
*/

template<class G,class T>
struct NumpyNodeMap
:
    IfBool<
        IsMultiband<T>::value,
        NumpyMultibandNodeMap< G ,  NumpyArray<IntrinsicGraphShape<G>::IntrinsicNodeMapDimension+1,T> > ,
        NumpyScalarNodeMap<    G ,  NumpyArray<IntrinsicGraphShape<G>::IntrinsicNodeMapDimension  ,T> >
    >::type

{
    typedef typename IfBool<
        IsMultiband<T>::value,
        NumpyArray<IntrinsicGraphShape<G>::IntrinsicNodeMapDimension+1,T> ,
        NumpyArray<IntrinsicGraphShape<G>::IntrinsicNodeMapDimension  ,T>
    >::type NumpyArrayType;

    typedef typename IfBool<
        IsMultiband<T>::value,
        NumpyMultibandNodeMap< G ,  NumpyArray<IntrinsicGraphShape<G>::IntrinsicNodeMapDimension+1,T> > ,
        NumpyScalarNodeMap<    G ,  NumpyArray<IntrinsicGraphShape<G>::IntrinsicNodeMapDimension  ,T> >
    >::type BaseType;

    NumpyNodeMap(const G & g, NumpyArrayType numpyArray)
    :BaseType(g,numpyArray){
    }

};

template<class G,class T>
struct NumpyEdgeMap
:
    IfBool<
        IsMultiband<T>::value,
        NumpyMultibandEdgeMap< G ,  NumpyArray<IntrinsicGraphShape<G>::IntrinsicEdgeMapDimension+1,T> > ,
        NumpyScalarEdgeMap<    G ,  NumpyArray<IntrinsicGraphShape<G>::IntrinsicEdgeMapDimension  ,T> >
    >::type

{
    typedef typename IfBool<
        IsMultiband<T>::value,
        NumpyArray<IntrinsicGraphShape<G>::IntrinsicEdgeMapDimension+1,T> ,
        NumpyArray<IntrinsicGraphShape<G>::IntrinsicEdgeMapDimension  ,T>
    >::type NumpyArrayType;

    typedef typename IfBool<
        IsMultiband<T>::value,
        NumpyMultibandEdgeMap< G ,  NumpyArray<IntrinsicGraphShape<G>::IntrinsicEdgeMapDimension+1,T> > ,
        NumpyScalarEdgeMap<    G ,  NumpyArray<IntrinsicGraphShape<G>::IntrinsicEdgeMapDimension  ,T> >
    >::type BaseType;

    NumpyEdgeMap(const G & g, NumpyArrayType numpyArray)
    :BaseType(g,numpyArray){
    }

};

template<class G,class T>
struct PyEdgeMapTraits{
    typedef NumpyEdgeMap<G,T> Map;
    typedef typename IfBool<
        IsMultiband<T>::value,
        NumpyArray<IntrinsicGraphShape<G>::IntrinsicEdgeMapDimension+1,T> ,
        NumpyArray<IntrinsicGraphShape<G>::IntrinsicEdgeMapDimension  ,T>
    >::type Array;
};

template<class G,class T>
struct PyNodeMapTraits{
    typedef NumpyNodeMap<G,T> Map;
    typedef typename IfBool<
        IsMultiband<T>::value,
        NumpyArray<IntrinsicGraphShape<G>::IntrinsicNodeMapDimension+1,T> ,
        NumpyArray<IntrinsicGraphShape<G>::IntrinsicNodeMapDimension  ,T>
    >::type Array;
};

namespace cluster_operators{

template<class MERGE_GRAPH>
class PythonOperator{

    typedef PythonOperator<MERGE_GRAPH > SelfType;
public:

    typedef float WeightType;
    typedef MERGE_GRAPH MergeGraph;
    typedef typename MergeGraph::Graph Graph;
    typedef typename Graph::Edge GraphEdge;
    typedef typename Graph::Node GraphNode;
    typedef typename MergeGraph::Edge Edge;
    typedef typename MergeGraph::Node Node;
    typedef typename MergeGraph::EdgeIt EdgeIt;
    typedef typename MergeGraph::NodeIt NodeIt;
    typedef typename MergeGraph::IncEdgeIt IncEdgeIt;
    typedef typename MergeGraph::index_type index_type;
    typedef MergeGraphItemHelper<MergeGraph,Edge> EdgeHelper;
    typedef MergeGraphItemHelper<MergeGraph,Node> NodeHelper;

    typedef NodeHolder<MERGE_GRAPH> NodeHolderType;
    typedef EdgeHolder<MERGE_GRAPH> EdgeHolderType;

    PythonOperator(
        MergeGraph & mergeGraph,
        boost::python::object object,
        const bool useMergeNodeCallback,
        const bool useMergeEdgesCallback,
        const bool useEraseEdgeCallback
    )
    :   mergeGraph_(mergeGraph),
        object_(object)
    {
        if(useMergeNodeCallback){
            typedef typename MergeGraph::MergeNodeCallBackType Callback;
            Callback cb(Callback:: template from_method<SelfType,&SelfType::mergeNodes>(this));
            mergeGraph_.registerMergeNodeCallBack(cb);

        }
        if(useMergeEdgesCallback){
            typedef typename MergeGraph::MergeEdgeCallBackType Callback;
            Callback cb(Callback:: template from_method<SelfType,&SelfType::mergeEdges>(this));
            mergeGraph_.registerMergeEdgeCallBack(cb);
        }
        if(useEraseEdgeCallback){
            typedef typename MergeGraph::EraseEdgeCallBackType Callback;
            Callback cb(Callback:: template from_method<SelfType,&SelfType::eraseEdge>(this));
            mergeGraph_.registerEraseEdgeCallBack(cb);
        }

    }

    void mergeEdges(const Edge & a,const Edge & b){
        const EdgeHolderType aa(mergeGraph_,a);
        const EdgeHolderType bb(mergeGraph_,b);
        object_.attr("mergeEdges")(aa,bb);
    }
    void mergeNodes(const Node & a,const Node & b){
        const NodeHolderType aa(mergeGraph_,a);
        const NodeHolderType bb(mergeGraph_,b);
        object_.attr("mergeNodes")(aa,bb);
    }
    void eraseEdge(const Edge & e){
        const EdgeHolderType ee(mergeGraph_,e);
        object_.attr("eraseEdge")(ee);
    }
    Edge contractionEdge(){
        EdgeHolderType eh = boost::python::extract<EdgeHolderType>(object_.attr("contractionEdge")());
        return eh;
    }
    WeightType contractionWeight()const{
        return boost::python::extract<WeightType>(object_.attr("contractionWeight")());
    }

    MergeGraph & mergeGraph(){
        return mergeGraph_;
    }
private:
    MergeGraph & mergeGraph_;
    boost::python::object object_;
};

} // end namespace cluster_operators

} // namespace vigra

#endif // VIGRA_PYTHON_GRAPH_HXX

ext: hxx

max_stars_repo_name: hmeine/vigra

max_issues_repo_name: hmeine/vigra

max_forks_repo_name: hmeine/vigra


text:
//
// Created by 邓健 on 2022/1/26.
//
#include <iostream>
#include <boost/version.hpp>
#include <boost/coroutine2/all.hpp>
#include <boost/thread/thread.hpp>

void coroutine_function(boost::coroutines2::coroutine<void>::pull_type & coro_back)
{
    std::cout << "a ";
    coro_back(); // 锚点，返回
    std::cout << "b ";
    coro_back(); //锚点 返回
    std::cout << "c ";
}

void new_thread(){
    std::cout << "hello world, I'm a thread!" << std::endl;
}

int main() {
    boost::coroutines2::coroutine<void>::push_type coroutine_object(coroutine_function); 	// 创建协程
    std::cout << "1 ";
    coroutine_object(); // 运行协程
    std::cout << "2 ";
    coroutine_object(); // 返回锚点，继续运行协程
    std::cout << "3 ";
    coroutine_object(); // 返回锚点，继续运行协程
    std::cout << "Boost版本：" << BOOST_VERSION << std::endl;

    boost::thread thrd(&new_thread);
    thrd.join();

    return 0;
}

ext: cpp

max_stars_repo_name: DreamCloudWalker/CppReviewProj

max_issues_repo_name: DreamCloudWalker/CppReviewProj

max_forks_repo_name: DreamCloudWalker/CppReviewProj


text:
// Boost.Geometry

// Copyright (c) 2020-2021, Oracle and/or its affiliates.

// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle

// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html

#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_HPP

#include <boost/geometry/strategies/area/cartesian.hpp>
#include <boost/geometry/strategies/azimuth/cartesian.hpp>
#include <boost/geometry/strategies/buffer/cartesian.hpp>
#include <boost/geometry/strategies/convex_hull/cartesian.hpp>
#include <boost/geometry/strategies/distance/cartesian.hpp>
#include <boost/geometry/strategies/envelope/cartesian.hpp>
#include <boost/geometry/strategies/expand/cartesian.hpp>
#include <boost/geometry/strategies/io/cartesian.hpp>
#include <boost/geometry/strategies/index/cartesian.hpp>
#include <boost/geometry/strategies/is_convex/cartesian.hpp>
#include <boost/geometry/strategies/relate/cartesian.hpp>
#include <boost/geometry/strategies/simplify/cartesian.hpp>

namespace boost { namespace geometry
{

namespace strategies
{

template <typename CalculationType = void>
class cartesian
    // derived from the umbrella strategy defining the most strategies
    : public strategies::index::cartesian<CalculationType>
{
public:

    static auto azimuth()
    {
        return strategy::azimuth::cartesian<CalculationType>();
    }

    static auto point_order()
    {
        return strategy::point_order::cartesian<CalculationType>();
    }
};

} // namespace strategies

}} // namespace boost::geometry

#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_HPP


text:
#include <iostream>
#include <boost/filesystem.hpp>
#include "imu.h"
#include "datapkgr.h"

// usage: cutImuH5ByUnixTimestamps path/to/file.h5 file/to/save.h5 (int)StartTime (int)StopTime

int main(int argc, char** argv){
    // check that exactly five arguments are entered
    if(argc!=5){
        std::cerr<<"enter 4 arguments! usage: path/to/file.h5 file/to/save.h5 (int)StartIdx (int)StopIdx"<<std::endl;
        return 1;
    }
    // check that first argument is a valid h5 file
    std::string inputFile=argv[1];
    std::string inputFileExt=boost::filesystem::extension(inputFile);
    std::cout<<"input file is: "<<inputFile<<" with extension "<<inputFileExt<<std::endl;
    if(!boost::filesystem::exists(inputFile) || ".h5"!=inputFileExt){
        std::cerr<<"input file "<<inputFile<<" either does not exist or is not an .h5 file"<<std::endl;
        return 2;
    }
    // check that second argument is an h5 file and its parent directory exists (create if not)
    boost::filesystem::path outputFile(argv[2]);
    boost::filesystem::create_directory(outputFile.parent_path());
    std::string outputFileExt=boost::filesystem::extension(outputFile);
    if(".h5"!=outputFileExt){
        std::cerr<<"output file "<<outputFile<<" does not represent a valid .h5 file"<<std::endl;
        return 3;
    }
    // construct integers for third and fourth arguments
    double startTime=(double)strtol(argv[3],nullptr,0);
    double stopTime=(double)strtol(argv[4],nullptr,0);
    // construct imu map from input file
    std::map<std::string,imu> ImuMap=imu::getImuMapFromDataFile(inputFile);
    // check that both unix times are within (inclusive) the times of the IMU
    if(((ImuMap.begin())->second).unixTimeUtc.size()==0){ // unix time has not been read
        std::cerr<<"unix time is not yet read for this IMU!"<<std::endl;
        return 4;
    }
    double minStartTime=((ImuMap.begin())->second).unixTimeUtc[0];
    double maxStopTime=((ImuMap.begin())->second).unixTimeUtc[((ImuMap.begin())->second).length()-1];
    if(startTime<minStartTime){
        std::cerr<<"start time must be greater than or equal to "<<std::to_string((unsigned long) minStartTime)<<" (input start time = "<<startTime<<")"<<std::endl;
        return 5;
    }
    if(stopTime>maxStopTime){
        std::cerr<<"stop time must be less than or equal to "<<std::to_string((unsigned long) maxStopTime)<<" (input stop time = "<<stopTime<<")"<<std::endl;
        return 6;
    }
    // todo: get closest associated indexes and cut by index
    uint startTimeIdx=datapkgr::getNearestIdxFromVector<double>(ImuMap.begin()->second.unixTimeUtc, startTime);
    uint stopTimeIdx=datapkgr::getNearestIdxFromVector<double>(ImuMap.begin()->second.unixTimeUtc, stopTime);
    // now cut imu map
    std::map<std::string,imu> ImuMapCut=datapkgr::cutImuMapByIdx(ImuMap,startTimeIdx,stopTimeIdx);
    // write imu map to output h5 file
    datapkgr::writeImuToApdmOpalH5File(ImuMapCut,outputFile.string());
    return 0;
}


text:
#ifndef FASTA_HPP
#define FASTA_HPP

#include "shred.hpp"

#include <Eigen/Dense>
#include <Eigen/Sparse>

#include <cmath>
#include <cstdint>
#include <exception>
#include <fstream>
#include <iostream>
#include <map>
#include <numeric>
#include <sstream>

/**
 * A structure to hold a sparse map from k-mer indexes to k-mer
 * counts with increments.
 */
template <typename T = size_t>
struct counter {
  std::map<T, size_t> counts_;

  /**
   * Increment the count for the specified key by one.
   *
   * @param key key whose count is incremented
   */
  void increment(const T& key) {
    if (counts_.find(key) == counts_.end())
      counts_[key] = 0;
    ++counts_[key];
  }

  /**
   * Return the sum of the values of all of the keys.
   */
  size_t count() const {
    size_t y = 0;
    for (const auto& key_count : counts_)
      y += key_count.second;
    return y;
  }
};

/**
 * Return the identifier in the range 0-3 for the specified base.
 * The mapping is defined alphabetically, indexing from zero, so that
 * 'A' maps to 0, 'C' maps to 1, 'G' maps to 2, and 'T' maps to 3,
 * with any other input throwing an exception.
 *
 * @param c character representing a base
 * @return numerical identifier for the base
 * @throw std::runtime_error if c is not one of 'A', 'C', 'G', or
 * 'T'.
 */
std::size_t base_id(char c) {
  switch (c) {
    case 'A' : return 0;
    case 'C' : return 1;
    case 'G' : return 2;
    case 'T' : return 3;
    default: throw
        std::runtime_error("argument to base_id must be one of:"
                           "'A', 'C', 'G', 'T'");
  }
}

/**
 * Return a numerical identifier for the specified kmer.  Each k-mer
 * is read as a base-4 number given the base_id() for each k-mer.  For
 * a fixed K, this assigns each K-mer gets a unique ID between 0 and
 * 4^K - 1 based on a lexicographic start, indexing from 0.
 *
 * @param kmer string representing a k-mer
 * @return identifier for the k-mer.
 * @throw std::runtime_error if there are characters in kmer other
 * than 'A', 'C', 'G', or 'T'.
 */
std::size_t kmer_id(const std::string& kmer) {
  size_t id = 0;
  for (const char& b : kmer)
    id = 4 * id + base_id(b);
  return id;
}

/**
 * A holder mapping sequence ids to their sequence and k-mers.
 */
struct seq_map {
  using mat_t = Eigen::SparseMatrix<double, Eigen::RowMajor>;
  using trip_t = Eigen::Triplet<double>;
  using trips_t = std::vector<trip_t>;

  std::map<std::string, std::string> id_to_seq_;
  int64_t K_;

  /**
   * Return the number of sequences in the domain of the map.
   *
   * @return number of sequences being mapped
   */
  int64_t size() const {
    return id_to_seq_.size();
  }

  /**
   * Return the total number of bases in the range of the map.
   *
   * @return total number of bases in the map
   */
  int64_t total_bases() const {
    return std::accumulate(id_to_seq_.begin(), id_to_seq_.end(), 0,
                           [](const auto& tot, const auto& seq) {
                             return tot + seq.second.size(); });
  }

  /**
   * Return the total number of unique k-mers using this map's k-mer
   *   size.
   *
   * @return total number of unique k-mers
   */
  int64_t kmers() const {
    return pow(4, K_);
  }

  /**
   * Return a vector of strings corresponding to the sequences in the
   * domain of this map.
   *
   * @return the identifiers being mapped
   */
  std::vector<std::string> identifiers() const {
    std::vector<std::string> ids;
    for (const auto& id_seq : id_to_seq_) {
      ids.push_back(id_seq.first);
    }
    return ids;
  }

  std::vector<int> kmer_freq() const {
    int M = std::pow(4, K_);
    int mask = M - 1; // (1u << (2 * K + 1)) - 1;

    std::vector<int> counts(M, 0);
    int n = 0;
    for (const auto& id_seq : id_to_seq_) {
      ++n;
      std::string s = id_seq.second;
      // std::stringstream in(s);
      // shred(K_, in, counts, mask);
      shred2(K_, s, counts, mask);
    }
    return counts;
  }

  /**
   * Return a counter mapping kmers to their frequencies.
   */
  counter<std::string> kmer_frequency() const {
    counter<std::string> c;
    int N = 0;
    for (const auto& id_seq : id_to_seq_) {
      ++N;
      if ((N % 1000) == 0)
	std::cout << N << " / " << id_to_seq_.size() << " isoforms indexed"
		  << std::endl;
      std::string seq = id_seq.second;
      for (size_t i = 0; i < seq.size(); ++i)
	if (seq[i] != 'A' && seq[i] != 'C' && seq[i] != 'G' && seq[i] != 'T')
	  std::cout << "*********** WHOA, found seq[" << i << "] = " << seq[i]
		    << std::endl;
      for (size_t i = 0; i + K_ < seq.size(); ++i) {
        auto kmer = seq.substr(i, K_);
        c.increment(kmer);
      }
    }
    return c;
  }

  /**
   * Return a counter mapping k-mer frequencies to the number of k-mers
   * with that frequency.
   */
  counter<size_t> kmer_frequency_counts() const {
    counter<std::string> c = kmer_frequency();
    counter<size_t> h;
    for (const auto& kmer_freq : c.counts_) {
      h.increment(kmer_freq.second);
    }
    return h;
  }

  mat_t kmer_gene_matrix() const {
    size_t num_kmers = kmers();
    mat_t m(kmers(), size());
    trips_t trips;
    size_t id = 0;
    for (const auto& id_seq : id_to_seq_) {
      std::string seq = id_seq.second;
      counter<size_t> c;
      for (size_t i = 0; i + K_ < seq.size(); ++i) {
        auto kmer = seq.substr(i, K_);
        auto k_id = kmer_id(kmer);
        c.increment(k_id);
      }
      double seq_sz = c.count();
      for (const auto& kmerid_count : c.counts_)
        trips.push_back(trip_t(kmerid_count.first, id,
                               kmerid_count.second / seq_sz));
      ++id;
    }
    m.setFromTriplets(trips.begin(), trips.end());
    return m;
  }

  bool start_seq(std::string& line) {
    return line.size() > 0 && line[0] == '>';
  }

  bool getnextline(std::ifstream& in, const std::string& last,
                   std::string& line) {
    if (!last.empty()) {
      line = last;
      return true;
    }
    while (std::getline(in, line).good())
      if (!line.empty()) {
        return true;
      }
    return false;
  }

  /**
   * Read FASTA formatted data from file with specified name.
   * @param K length of K-mers
   * @param filename name of file from which to read
   */
  seq_map(int64_t K, const std::string& filename)
      : K_(K) {
    std::ifstream in(filename, std::ifstream::in);
    std::string line;
    int64_t count = 0;
    int64_t total_bases = 0;
    std::string lastline = "";
    while (getnextline(in, lastline, line)) {
      lastline = "";
      if (!start_seq(line)) continue;
      std::string id = line.substr(1);
      std::stringstream val;
      while (getnextline(in, lastline, line)) {
        lastline = "";
	if (start_seq(line)) {
          lastline = line;
	  break;
        }
	val << line;
      }
      std::string bp_seq = val.str();
      id_to_seq_[id] = bp_seq;
      total_bases += bp_seq.size();
    }
    in.close();
  }
};

Eigen::VectorXd softmax(const Eigen::VectorXd& alpha) {
  auto alpha_exp = alpha.array().exp();
  return alpha_exp / alpha_exp.sum();
}

struct log_posterior_gradient {
  const double lambda_;
  const Eigen::VectorXd& y_;  // 4^K x 1
  const seq_map::mat_t& x_;   // 4^K x G

  log_posterior_gradient(double lambda,
                         const Eigen::VectorXd& y,
                         const seq_map::mat_t& x)
      : lambda_(lambda), y_(y), x_(x) { }

  double operator()(const Eigen::VectorXd& alpha,
                    Eigen::VectorXd& grad) {
    // implementation lifted and lightly refactored from matrixcalculus.org
    Eigen::VectorXd t0 = alpha.array().exp();
    double t1 = t0.array().sum();
    Eigen::VectorXd t2 = x_.transpose() * (y_.array() * (1 / t1 * x_ * t0).array()).matrix();
    double lpd = y_.transpose() * (x_ * t0 / t1)
        + alpha.dot(alpha) / (2 * lambda_);
    grad = (((1 / t1) * t2).array() * t0.array()).matrix()
        - 1 / (t1 * t1) * t0.transpose() * t2 * t0
        - 1 / lambda_ * alpha;
    return lpd;
  }
};

#endif

max_stars_repo_name: bob-carpenter/case-studies

max_issues_repo_name: bob-carpenter/case-studies

max_forks_repo_name: bob-carpenter/case-studies


text:
#include <oslo/node/node.hpp>
#include <oslo/node/repcrawler.hpp>

#include <boost/format.hpp>

oslo::rep_crawler::rep_crawler (oslo::node & node_a) :
node (node_a)
{
	if (!node.flags.disable_rep_crawler)
	{
		node.observers.endpoint.add ([this](std::shared_ptr<oslo::transport::channel> channel_a) {
			this->query (channel_a);
		});
	}
}

void oslo::rep_crawler::remove (oslo::block_hash const & hash_a)
{
	oslo::lock_guard<std::mutex> lock (active_mutex);
	active.erase (hash_a);
}

void oslo::rep_crawler::start ()
{
	ongoing_crawl ();
}

void oslo::rep_crawler::validate ()
{
	decltype (responses) responses_l;
	{
		oslo::lock_guard<std::mutex> lock (active_mutex);
		responses_l.swap (responses);
	}
	auto transaction (node.store.tx_begin_read ());
	auto minimum = node.minimum_principal_weight ();
	for (auto const & i : responses_l)
	{
		auto & vote = i.second;
		auto & channel = i.first;
		debug_assert (channel != nullptr);
		oslo::uint128_t rep_weight = node.ledger.weight (vote->account);
		if (rep_weight > minimum)
		{
			auto updated_or_inserted = false;
			oslo::unique_lock<std::mutex> lock (probable_reps_mutex);
			auto existing (probable_reps.find (vote->account));
			if (existing != probable_reps.end ())
			{
				probable_reps.modify (existing, [rep_weight, &updated_or_inserted, &vote, &channel](oslo::representative & info) {
					info.last_response = std::chrono::steady_clock::now ();

					// Update if representative channel was changed
					if (info.channel->get_endpoint () != channel->get_endpoint ())
					{
						debug_assert (info.account == vote->account);
						updated_or_inserted = true;
						info.weight = rep_weight;
						info.channel = channel;
					}
				});
			}
			else
			{
				probable_reps.emplace (oslo::representative (vote->account, rep_weight, channel));
				updated_or_inserted = true;
			}
			lock.unlock ();
			if (updated_or_inserted)
			{
				node.logger.try_log (boost::str (boost::format ("Found a representative at %1%") % channel->to_string ()));
			}
		}
		// This tries to assist rep nodes that have lost track of their highest sequence number by replaying our highest known vote back to them
		// Only do this if the sequence number is significantly different to account for network reordering
		// Amplify attack considerations: We're sending out a confirm_ack in response to a confirm_ack for no net traffic increase
		auto max_vote (node.store.vote_max (transaction, vote));
		if (max_vote->sequence > vote->sequence + 10000)
		{
			oslo::confirm_ack confirm (max_vote);
			channel->send (confirm); // this is non essential traffic as it will be resolicited if not received
		}
	}
}

void oslo::rep_crawler::ongoing_crawl ()
{
	auto now (std::chrono::steady_clock::now ());
	auto total_weight_l (total_weight ());
	cleanup_reps ();
	update_weights ();
	validate ();
	query (get_crawl_targets (total_weight_l));
	auto sufficient_weight (total_weight_l > node.config.online_weight_minimum.number ());
	// If online weight drops below minimum, reach out to preconfigured peers
	if (!sufficient_weight)
	{
		node.keepalive_preconfigured (node.config.preconfigured_peers);
	}
	// Reduce crawl frequency when there's enough total peer weight
	unsigned next_run_ms = node.network_params.network.is_test_network () ? 100 : sufficient_weight ? 7000 : 3000;
	std::weak_ptr<oslo::node> node_w (node.shared ());
	node.alarm.add (now + std::chrono::milliseconds (next_run_ms), [node_w, this]() {
		if (auto node_l = node_w.lock ())
		{
			this->ongoing_crawl ();
		}
	});
}

std::vector<std::shared_ptr<oslo::transport::channel>> oslo::rep_crawler::get_crawl_targets (oslo::uint128_t total_weight_a)
{
	constexpr size_t conservative_count = 10;
	constexpr size_t aggressive_count = 40;

	// Crawl more aggressively if we lack sufficient total peer weight.
	bool sufficient_weight (total_weight_a > node.config.online_weight_minimum.number ());
	uint16_t required_peer_count = sufficient_weight ? conservative_count : aggressive_count;

	// Add random peers. We do this even if we have enough weight, in order to pick up reps
	// that didn't respond when first observed. If the current total weight isn't sufficient, this
	// will be more aggressive. When the node first starts, the rep container is empty and all
	// endpoints will originate from random peers.
	required_peer_count += required_peer_count / 2;

	// The rest of the endpoints are picked randomly
	auto random_peers (node.network.random_set (required_peer_count, 0, true)); // Include channels with ephemeral remote ports
	std::vector<std::shared_ptr<oslo::transport::channel>> result;
	result.insert (result.end (), random_peers.begin (), random_peers.end ());
	return result;
}

void oslo::rep_crawler::query (std::vector<std::shared_ptr<oslo::transport::channel>> const & channels_a)
{
	auto transaction (node.store.tx_begin_read ());
	std::shared_ptr<oslo::block> block (node.store.block_random (transaction));
	auto hash (block->hash ());
	{
		oslo::lock_guard<std::mutex> lock (active_mutex);
		// Don't send same block multiple times in tests
		if (node.network_params.network.is_test_network ())
		{
			for (auto i (0); active.count (hash) != 0 && i < 4; ++i)
			{
				block = node.store.block_random (transaction);
				hash = block->hash ();
			}
		}
		active.insert (hash);
	}
	for (auto i (channels_a.begin ()), n (channels_a.end ()); i != n; ++i)
	{
		debug_assert (*i != nullptr);
		on_rep_request (*i);
		node.network.send_confirm_req (*i, block);
	}

	// A representative must respond with a vote within the deadline
	std::weak_ptr<oslo::node> node_w (node.shared ());
	node.alarm.add (std::chrono::steady_clock::now () + std::chrono::seconds (5), [node_w, hash]() {
		if (auto node_l = node_w.lock ())
		{
			node_l->rep_crawler.remove (hash);
		}
	});
}

void oslo::rep_crawler::query (std::shared_ptr<oslo::transport::channel> const & channel_a)
{
	std::vector<std::shared_ptr<oslo::transport::channel>> peers;
	peers.emplace_back (channel_a);
	query (peers);
}

bool oslo::rep_crawler::is_pr (oslo::transport::channel const & channel_a) const
{
	oslo::lock_guard<std::mutex> lock (probable_reps_mutex);
	auto existing = probable_reps.get<tag_channel_ref> ().find (channel_a);
	bool result = false;
	if (existing != probable_reps.get<tag_channel_ref> ().end ())
	{
		result = existing->weight > node.minimum_principal_weight ();
	}
	return result;
}

bool oslo::rep_crawler::response (std::shared_ptr<oslo::transport::channel> & channel_a, std::shared_ptr<oslo::vote> & vote_a)
{
	bool error = true;
	oslo::lock_guard<std::mutex> lock (active_mutex);
	for (auto i = vote_a->begin (), n = vote_a->end (); i != n; ++i)
	{
		if (active.count (*i) != 0)
		{
			responses.emplace_back (channel_a, vote_a);
			error = false;
			break;
		}
	}
	return error;
}

oslo::uint128_t oslo::rep_crawler::total_weight () const
{
	oslo::lock_guard<std::mutex> lock (probable_reps_mutex);
	oslo::uint128_t result (0);
	for (auto i (probable_reps.get<tag_weight> ().begin ()), n (probable_reps.get<tag_weight> ().end ()); i != n; ++i)
	{
		auto weight (i->weight.number ());
		if (weight > 0)
		{
			result = result + weight;
		}
		else
		{
			break;
		}
	}
	return result;
}

void oslo::rep_crawler::on_rep_request (std::shared_ptr<oslo::transport::channel> channel_a)
{
	oslo::lock_guard<std::mutex> lock (probable_reps_mutex);
	if (channel_a->get_tcp_endpoint ().address () != boost::asio::ip::address_v6::any ())
	{
		probably_rep_t::index<tag_channel_ref>::type & channel_ref_index = probable_reps.get<tag_channel_ref> ();

		// Find and update the timestamp on all reps available on the endpoint (a single host may have multiple reps)
		auto itr_pair = channel_ref_index.equal_range (*channel_a);
		for (; itr_pair.first != itr_pair.second; itr_pair.first++)
		{
			channel_ref_index.modify (itr_pair.first, [](oslo::representative & value_a) {
				value_a.last_request = std::chrono::steady_clock::now ();
			});
		}
	}
}

void oslo::rep_crawler::cleanup_reps ()
{
	std::vector<std::shared_ptr<oslo::transport::channel>> channels;
	{
		// Check known rep channels
		oslo::lock_guard<std::mutex> lock (probable_reps_mutex);
		auto iterator (probable_reps.get<tag_last_request> ().begin ());
		while (iterator != probable_reps.get<tag_last_request> ().end ())
		{
			if (iterator->channel->get_tcp_endpoint ().address () != boost::asio::ip::address_v6::any ())
			{
				channels.push_back (iterator->channel);
				++iterator;
			}
			else
			{
				// Remove reps with closed channels
				iterator = probable_reps.get<tag_last_request> ().erase (iterator);
			}
		}
	}
	// Remove reps with inactive channels
	for (auto const & i : channels)
	{
		bool equal (false);
		if (i->get_type () == oslo::transport::transport_type::tcp)
		{
			auto find_channel (node.network.tcp_channels.find_channel (i->get_tcp_endpoint ()));
			if (find_channel != nullptr && *find_channel == *static_cast<oslo::transport::channel_tcp *> (i.get ()))
			{
				equal = true;
			}
		}
		else if (i->get_type () == oslo::transport::transport_type::udp)
		{
			auto find_channel (node.network.udp_channels.channel (i->get_endpoint ()));
			if (find_channel != nullptr && *find_channel == *static_cast<oslo::transport::channel_udp *> (i.get ()))
			{
				equal = true;
			}
		}
		if (!equal)
		{
			oslo::lock_guard<std::mutex> lock (probable_reps_mutex);
			probable_reps.get<tag_channel_ref> ().erase (*i);
		}
	}
}

void oslo::rep_crawler::update_weights ()
{
	oslo::lock_guard<std::mutex> lock (probable_reps_mutex);
	for (auto i (probable_reps.get<tag_last_request> ().begin ()), n (probable_reps.get<tag_last_request> ().end ()); i != n;)
	{
		auto weight (node.ledger.weight (i->account));
		if (weight > 0)
		{
			if (i->weight.number () != weight)
			{
				probable_reps.get<tag_last_request> ().modify (i, [weight](oslo::representative & info) {
					info.weight = weight;
				});
			}
			++i;
		}
		else
		{
			// Erase non representatives
			i = probable_reps.get<tag_last_request> ().erase (i);
		}
	}
}

std::vector<oslo::representative> oslo::rep_crawler::representatives (size_t count_a, oslo::uint128_t const weight_a, boost::optional<decltype (oslo::protocol_constants::protocol_version)> const & opt_version_min_a)
{
	auto version_min (opt_version_min_a.value_or (node.network_params.protocol.protocol_version_min (node.ledger.cache.epoch_2_started)));
	std::vector<representative> result;
	oslo::lock_guard<std::mutex> lock (probable_reps_mutex);
	for (auto i (probable_reps.get<tag_weight> ().begin ()), n (probable_reps.get<tag_weight> ().end ()); i != n && result.size () < count_a; ++i)
	{
		if (i->weight > weight_a && i->channel->get_network_version () >= version_min)
		{
			result.push_back (*i);
		}
	}
	return result;
}

std::vector<oslo::representative> oslo::rep_crawler::principal_representatives (size_t count_a, boost::optional<decltype (oslo::protocol_constants::protocol_version)> const & opt_version_min_a)
{
	return representatives (count_a, node.minimum_principal_weight (), opt_version_min_a);
}

std::vector<std::shared_ptr<oslo::transport::channel>> oslo::rep_crawler::representative_endpoints (size_t count_a)
{
	std::vector<std::shared_ptr<oslo::transport::channel>> result;
	auto reps (representatives (count_a));
	for (auto const & rep : reps)
	{
		result.push_back (rep.channel);
	}
	return result;
}

/** Total number of representatives */
size_t oslo::rep_crawler::representative_count ()
{
	oslo::lock_guard<std::mutex> lock (probable_reps_mutex);
	return probable_reps.size ();
}

max_stars_repo_name: oslocurrency/oslo-node

max_issues_repo_name: oslocurrency/oslo-node

max_forks_repo_name: oslocurrency/oslo-node


text:
// @@@LICENSE
//
//      Copyright (c) 2010-2013 LG Electronics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// LICENSE@@@

#include "protocol/FetchResponseParser.h"
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/erase.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <sstream>
#include "client/MockImapSession.h"
#include "protocol/MockDoneSlot.h"
#include "data/ImapEmail.h"
#include "data/EmailAddress.h"
#include "MockTestSetup.h"
#include "data/EmailPart.h"
#include <fstream>
#include "data/ImapEmailAdapter.h"
#include "ImapPrivate.h"
#include <gtest/gtest.h>

using namespace std;

static inline string reformat_quoted(const string& s)
{
	string temp = s;

	boost::trim(temp);
	boost::erase_first(temp, "(");
	boost::erase_last(temp, ")");
	boost::trim(temp);
	boost::replace_all(temp, "\n", " ");

	return temp;
}

#define QUOTE_IMAP(x) (reformat_quoted(#x))
#define TEST_ALL 1

void dump_json(ImapEmail& email)
{
	MojObject obj;
	ImapEmailAdapter::SerializeToDatabaseObject(email, obj);
	fprintf(stderr, "email object: %s", AsJsonString(obj).c_str());
}

void BuildEnvelope(string date, string subject, string from, string sender,
		string replyTo, string to, string cc, string bcc, string inReplyTo, string messageId)
{
	stringstream ss;
	ss << date << " " << subject << " " << from << " " << sender << " " << replyTo << "";
	ss << to << " " << cc << " " << bcc << " " << inReplyTo << " " << messageId;
}

TEST(FetchResponseParserTest, TestSimpleHeaders)
{
#if TEST_ALL
	MockTestSetup setup;
	MockImapSession& session = setup.GetSession();

	const MockInputStreamPtr& is = session.GetMockInputStream();

	MockDoneSlot slot;
	MojRefCountedPtr<FetchResponseParser> parser(new FetchResponseParser(session, slot.GetSlot()));

	session.SendRequest("FETCH 10 ALL", parser);

	string line = QUOTE_IMAP((
		* 10 FETCH (FLAGS (\\Seen) INTERNALDATE "16-Apr-2010 10:32:38 -0400"
		RFC822.SIZE 8382 ENVELOPE ("Fri, 16 Apr 2010 10:32:37 -0400" "Subject"
		(("From Person" NIL "from" "example.com"))
		(("Sender Person" NIL "sender" "example.com"))
		(("ReplyTo Person" NIL "replyto" "example.com"))
		(("To Person" NIL "to" "example.com"))
		NIL NIL NIL
		"<messageid>"))
	));

	is->FeedLine(line);

	const vector<FetchUpdate> updates = parser->GetUpdates();
	ASSERT_EQ( (size_t) 1, updates.size() );
	ImapEmail* email = updates.at(0).email.get();

	ASSERT_EQ( "Subject", email->GetSubject() );
#endif
}

TEST(FetchResponseParserTest, TestLiteralHeaders)
{
#if TEST_ALL
	MockTestSetup setup;
	MockImapSession& session = setup.GetSession();

	const MockInputStreamPtr& is = session.GetMockInputStream();

	MockDoneSlot slot;
	MojRefCountedPtr<FetchResponseParser> parser(new FetchResponseParser(session, slot.GetSlot()));

	session.SendRequest("FETCH 11 (ENVELOPE)", parser);

	string subject = "This is a subject";
	string toName = "To Person";
	string toDomain = "example.org";

	stringstream ss;
	ss << "* 1 FETCH (UID 1234 ENVELOPE (NIL {" << subject.length() << "}\r\n" << subject;
	ss << " ((\"From Person\" NIL \"from\" \"example.com\"))";
	ss << " NIL NIL"; // sender, reply-to
	ss << " (({" << toName.length() << "}\r\n" << toName; // to
	ss << " NIL \"to.person\" {" << toDomain.length() << "}\r\n";

	is->Feed(ss.str());
	is->Feed(toDomain);
	is->FeedLine(")) NIL NIL NIL \"<messageid>\"))"); // cc bcc in-reply-to message-id

	is->FlushBuffer();

	const vector<FetchUpdate>& emails = parser->GetUpdates();
	ASSERT_EQ( (size_t) 1, emails.size() );
	ImapEmail* email = emails.at(0).email.get();

	ASSERT_EQ( subject, email->GetSubject() );
	ASSERT_EQ( (size_t) 1, email->GetTo()->size() );
	ASSERT_EQ( toName, email->GetTo()->at(0)->GetDisplayName() );
#endif
}

const boost::shared_ptr<ImapEmail>& GetOneEmail(const MojRefCountedPtr<FetchResponseParser>& parser)
{
	parser->CheckStatus();

	const vector<FetchUpdate>& emails = parser->GetUpdates();

	//ASSERT_EQ( (size_t) 1, emails.size() );

	const FetchUpdate& update = emails.at(0);

	if(update.email.get() == NULL) {
		throw MailException("no email", __FILE__, __LINE__);
	}

	return update.email;
}

boost::shared_ptr<ImapEmail> ParseOneEmail(string line)
{
	MockTestSetup setup;
	MockImapSession& session = setup.GetSession();

	const MockInputStreamPtr& is = session.GetMockInputStream();

	MockDoneSlot slot;
	MojRefCountedPtr<FetchResponseParser> parser(new FetchResponseParser(session, slot.GetSlot()));

	session.SendRequest("UID FETCH 1024 (BODYSTRUCTURE)", parser);

	is->FeedLine(line);
	is->FeedLine("~A1 OK");
	is->FlushBuffer();

	return GetOneEmail(parser);
}

// Basic body structure parsing
TEST(FetchResponseParserTest, TestBodyStructure)
{
#if TEST_ALL
	MockTestSetup setup;
	MockImapSession& session = setup.GetSession();

	const MockInputStreamPtr& is = session.GetMockInputStream();

	MockDoneSlot slot;
	MojRefCountedPtr<FetchResponseParser> parser(new FetchResponseParser(session, slot.GetSlot()));

	session.SendRequest("UID FETCH 1024 (BODYSTRUCTURE)", parser);

	string line = QUOTE_IMAP((
		* 1 FETCH (UID 1024
		BODYSTRUCTURE (("TEXT" "PLAIN" ("CHARSET" "iso-8859-1") NIL NIL "QUOTED-PRINTABLE" 2518 94 NIL NIL NIL)("TEXT" "HTML" ("CHARSET" "iso-8859-1") NIL NIL "QUOTED-PRINTABLE" 8504 162 NIL NIL NIL) "ALTERNATIVE" ("BOUNDARY" "======1272494251854======") NIL NIL))
	));

	is->FeedLine(line);
	is->FeedLine("~A1 OK");
	is->FlushBuffer();

	boost::shared_ptr<ImapEmail> email = GetOneEmail(parser);

	// Only the HTML part is kept since it's multipart/alternative
	const EmailPartList& parts = email->GetPartList();

	ASSERT_EQ( parts.size(), (size_t) 1 );
	ASSERT_EQ( parts.at(0)->GetCharset(), "iso-8859-1" );
	ASSERT_EQ( parts.at(0)->GetEncoding(), "quoted-printable" );
	ASSERT_EQ( parts.at(0)->GetEncodedSize(), 8504 );
#endif
}

// Test illegal body structure sent by Gmail for message/rfc822 parts (appears as a regular body-type-basic)
TEST(FetchResponseParserTest, TestMessageRfc822Gmail)
{
#if TEST_ALL
	string line = QUOTE_IMAP((
		* 1 FETCH (UID 1024
		BODYSTRUCTURE (("TEXT" "HTML" NIL NIL NIL "7BIT" 13 1 NIL NIL NIL)("MESSAGE" "RFC822" NIL NIL NIL "7BIT" 227 NIL ("ATTACHMENT" ("FILENAME" "test.eml")) NIL) "MIXED" ("BOUNDARY" "BOUNDARY") NIL NIL))
	));

	boost::shared_ptr<ImapEmail> email = ParseOneEmail(line);

	// The text/html part and the message/rfc822 attachment
	const EmailPartList& parts = email->GetPartList();

	ASSERT_EQ( parts.size(), (size_t) 2 );
	ASSERT_TRUE( parts.at(0)->IsBodyPart() );
	ASSERT_TRUE( parts.at(1)->IsAttachment() );
	ASSERT_TRUE( parts.at(1)->GetDisplayName() == "test.eml" );
#endif
}

// Test nested rfc822 email
TEST(FetchResponseParserTest, TestMessageRfc822)
{
#if TEST_ALL
	string line = QUOTE_IMAP((
	* 1 FETCH (UID 1024
	ENVELOPE (NIL "Test rfc822" ((NIL NIL "username" "gmail.com")) ((NIL NIL "username" "gmail.com")) ((NIL NIL "username" "gmail.com")) ((NIL NIL "username" "gmail.com")) NIL NIL NIL NIL)
	BODYSTRUCTURE (("TEXT" "HTML" NIL NIL NIL "7BIT" 13 1 NIL NIL NIL NIL)("MESSAGE" "RFC822" NIL NIL NIL "7BIT" 227 (NIL "Test attached email" ((NIL NIL "username" "palm.com")) ((NIL NIL "username" "palm.com")) ((NIL NIL "username" "palm.com")) ((NIL NIL "username" "palm.com")) NIL NIL NIL NIL) (("TEXT" "HTML" NIL NIL NIL "7BIT" 22 1 NIL NIL NIL NIL) "ALTERNATIVE" ("BOUNDARY" "INNER") NIL NIL NIL) 12 NIL ("attachment" ("FILENAME" "test.eml")) NIL NIL) "MIXED" ("BOUNDARY" "BOUNDARY") NIL NIL NIL))
	));

	boost::shared_ptr<ImapEmail> email = ParseOneEmail(line);

	ASSERT_EQ( email->GetSubject(), "Test rfc822" );

	EmailAddressListPtr toAddresses = email->GetTo();
	ASSERT_EQ( toAddresses->size(), (size_t) 1 );
	ASSERT_EQ( toAddresses->at(0)->GetAddress(), "username@gmail.com" );

	// Body part and a message/rfc822 attachment
	EmailPartList parts = email->GetPartList();
	ASSERT_EQ( parts.size(), (size_t) 2 );

	EmailPartPtr& bodyPart = parts.at(0);
	ASSERT_EQ( bodyPart->GetMimeType(), "text/html" );
	ASSERT_TRUE( bodyPart->IsBodyPart() );
	ASSERT_EQ( bodyPart->GetEncodedSize(), 13 );

	EmailPartPtr& messagePart = parts.at(1);
	ASSERT_EQ( messagePart->GetMimeType(), "message/rfc822" );
	ASSERT_TRUE( messagePart->IsAttachment() );
	ASSERT_EQ( messagePart->GetEncodedSize(), 227 );

	//fprintf(stderr, "Display name %s\n", messagePart->GetDisplayName().c_str() );
	ASSERT_EQ( messagePart->GetDisplayName(), "test.eml" );

#endif
}

// Multiple levels of nesting
TEST(FetchResponseParserTest, TestNestedEmail)
{
#if TEST_ALL
	string line = QUOTE_IMAP((
		* 1 FETCH (UID 1024
		BODYSTRUCTURE (("TEXT" "HTML" NIL NIL NIL "7BIT" 100 2 NIL NIL NIL NIL)("MESSAGE" "RFC822" NIL NIL NIL "7BIT" 469 (NIL "FW: Totally Awesome" ((NIL NIL "username" "palm.com")) ((NIL NIL "username" "palm.com")) ((NIL NIL "username" "palm.com")) ((NIL NIL "username" "palm.com")) NIL NIL NIL NIL) (("TEXT" "HTML" NIL NIL NIL "7BIT" 17 1 NIL NIL NIL NIL)("MESSAGE" "RFC822" NIL NIL NIL "7BIT" 122 (NIL "Totally Awesome" ((NIL NIL "test" "example.com")) ((NIL NIL "test" "example.com")) ((NIL NIL "test" "example.com")) ((NIL NIL "tester" "example.com")) NIL NIL NIL NIL) ("TEXT" "PLAIN" ("CHARSET" "us-ascii") NIL NIL "7BIT" 20 1 NIL NIL NIL NIL) 6 NIL ("attachment" ("FILENAME" "fw-fw.eml")) NIL NIL) "MIXED" ("BOUNDARY" "INNER") NIL NIL NIL) 24 NIL ("attachment" ("FILENAME" "test.eml")) NIL NIL) "MIXED" ("BOUNDARY" "BOUNDARY") NIL NIL NIL)
		ENVELOPE (NIL "FW: FW: Totally Awesome" ((NIL NIL "username" "gmail.com")) ((NIL NIL "username" "gmail.com")) ((NIL NIL "username" "gmail.com")) ((NIL NIL "username" "gmail.com")) NIL NIL NIL NIL))
	));

	boost::shared_ptr<ImapEmail> email = ParseOneEmail(line);

	ASSERT_EQ( email->GetSubject(), "FW: FW: Totally Awesome" );

	EmailAddressListPtr toAddresses = email->GetTo();
	ASSERT_EQ( toAddresses->size(), (size_t) 1 );
	ASSERT_EQ( toAddresses->at(0)->GetAddress(), "username@gmail.com" );

	// Body part and a message/rfc822 attachment
	EmailPartList parts = email->GetPartList();
	ASSERT_EQ( parts.size(), (size_t) 2 );

	EmailPartPtr& bodyPart = parts.at(0);
	ASSERT_EQ( bodyPart->GetMimeType(), "text/html" );
	ASSERT_TRUE( bodyPart->IsBodyPart() );

	EmailPartPtr& messagePart = parts.at(1);
	ASSERT_EQ( messagePart->GetMimeType(), "message/rfc822" );
	ASSERT_TRUE( messagePart->IsAttachment() );
	ASSERT_EQ( messagePart->GetDisplayName(), "test.eml" );
#endif
}

TEST(FetchResponseParserTest, TestYahooEmlAttachments)
{
#if 0 // Yahoo server bug
	string line = QUOTE_IMAP((
		* 1 FETCH (BODYSTRUCTURE (("text" "plain" ("charset" "ISO-8859-1" " format" "flowed") NIL NIL "7bit" 6 1 NIL NIL NIL NIL)("message" "rfc822" ("name" "Some attachments.eml") NIL NIL "7bit" 208177 ("Fri, 10 Sep 2010 11:22:05 -0700" "Some attachments" (("Person Name" NIL "username" "gmail.com")) (("Person Name" NIL "username" "gmail.com")) (("Person Name" NIL "username" "gmail.com")) ((NIL NIL "username" "gmail.com")) NIL NIL NIL "<4C8A774D.30307@gmail.com>") (("text" "plain" ("charset" "ISO-8859-1" " format" "flowed") NIL NIL "7bit" 4 1 NIL NIL NIL NIL)("image" "png" ("name" "accounts_2010-21-07_185928.png") NIL NIL "base64" 98864 NIL ("inline" ("filename" "accounts_2010-21-07_185928.png")) NIL NIL)("image" "png" ("name" "eas-145.png") NIL NIL "base64" 52296 NIL ("inline" ("filename" "eas-145.png")) NIL NIL)("image" "png" ("name" "eas-main.png") NIL NIL "base64" 55582 NIL ("inline" ("filename" "eas-main.png")) NIL NIL) "mixed" ("boundary" "------------030400010902000606030807") NIL ) 2840 NIL ("inline" ("filename" "eas-main.png")) NIL NIL) "mixed" ("boundary" "------------000106010706010908000801") NIL ) ENVELOPE ("Fri, 10 Sep 2010 11:27:17 -0700" "[Fwd: Some attachments]" (("Person Name" NIL "username" "gmail.com")) (("Person Name" NIL "username" "gmail.com")) (("Person Name" NIL "username" "gmail.com")) ((NIL NIL "username2" "yahoo.com")) NIL NIL NIL "<4C8A7885.9040404@gmail.com>"))
	));

	boost::shared_ptr<ImapEmail> email = ParseOneEmail(line);

	dump_json(*email);
#endif
}

// Test message/delivery-status part
TEST(FetchResponseParserTest, TestMessageDeliveryStatus)
{
#if TEST_ALL
	string line = QUOTE_IMAP((
		* 1 FETCH (UID 1024
		BODYSTRUCTURE (("TEXT" "HTML" NIL NIL NIL "7BIT" 13 1 NIL NIL NIL NIL)("MESSAGE" "DELIVERY-STATUS" NIL NIL NIL "7BIT" 6 NIL NIL NIL NIL) "MIXED" ("BOUNDARY" "BOUNDARY") NIL NIL NIL))
	));

	ParseOneEmail(line);
#endif
}

// make sure that MESSAGE_IN_QUOTES can still appear as a regular string
TEST(FetchResponseParserTest, TestTokenInQuotes)
{
#if TEST_ALL
	string line = QUOTE_IMAP((
		* 1 FETCH (UID 1024
		ENVELOPE ("Wed, 4 Aug 2010 02:10:15 -0700" "message" (("Person Name" NIL "username" "gmail.com")) (("Person Name" NIL "username" "gmail.com")) (("Person Name" NIL "username" "gmail.com")) (("Person Name" NIL "username" "gmail.com")) NIL NIL NIL "<messageid>"))
	));

	boost::shared_ptr<ImapEmail> email = ParseOneEmail(line);
	//fprintf(stderr, "subject: %s\n", email->GetSubject().c_str());
	ASSERT_EQ( email->GetSubject(), "message" );
#endif
}

// Test handling of buggy Gmail behavior when a subject line contains \r\n in the middle (NOV-87436)
TEST(FetchResponseParserTest, TestGmailBrokenLine)
{
#if TEST_ALL
	MockTestSetup setup;
	MockImapSession& session = setup.GetSession();

	const MockInputStreamPtr& is = session.GetMockInputStream();

	MockDoneSlot slot;
	MojRefCountedPtr<FetchResponseParser> parser(new FetchResponseParser(session, slot.GetSlot()));

	session.SendRequest("UID FETCH 1024 (BODYSTRUCTURE)", parser);

	string line = QUOTE_IMAP((
			* 1 FETCH (UID 1024 ENVELOPE ("Tue, 5 Jan 2010 12:41:34 -0800 (PST)" "The quick brown fox jumped over the lazy dog" ((NIL NIL "username" "gmail.com")) ((NIL NIL "username" "gmail.com")) ((NIL NIL "username" "gmail.com")) ((NIL NIL "username" "gmail.com")) NIL NIL NIL "<3465387674237263106@unknownmsgid>") BODYSTRUCTURE ("TEXT" "PLAIN" NIL NIL NIL "7BIT" 9 1 NIL NIL NIL))
	));

	// split line after the 'j' in jumped; a newline will be inserted in the middle
	string line1 = line.substr( 0, line.find("umpe") );
	string line2 = line.substr( line.find("umpe") );

	is->FeedLine(line1);
	is->FeedLine(line2);

	//fprintf(stderr, "line 1: [%s]\n", line1.c_str());
	//fprintf(stderr, "line 2: [%s]\n", line2.c_str());

	is->FeedLine("~A1 OK");
	is->FlushBuffer();

	const Email& email = *GetOneEmail(parser);
	//fprintf(stderr, "email subject: [%s]\n", email.GetSubject().c_str());
	ASSERT_EQ( email.GetSubject(), "The quick brown fox j\r\numped over the lazy dog" );
#endif
}

// Test handling of buggy Yahoo behavior with extra space after the filename (NOV-112816)
TEST(FetchResponseParserTest, TestYahooExtraSpace)
{
#if TEST_ALL
	MockTestSetup setup;
	MockImapSession& session = setup.GetSession();

	const MockInputStreamPtr& is = session.GetMockInputStream();

	MockDoneSlot slot;
	MojRefCountedPtr<FetchResponseParser> parser(new FetchResponseParser(session, slot.GetSlot()));

	session.SendRequest("UID FETCH 1024 (BODYSTRUCTURE)", parser);

	string line = QUOTE_IMAP((
		* 1234 FETCH (BODYSTRUCTURE (("text" "plain" ("charset" "iso-8859-1") NIL NIL "7bit" 870 31 NIL NIL NIL "attachment.htm" )("text" "html" ("charset" "us-ascii") NIL NIL "7bit" 2285 6 NIL NIL NIL "attachment.htm" ) "alternative" ("boundary" "----BOUNDARY") NIL ) ENVELOPE ("Sat, 01 Aug 2010 01:01:01 -0700" "Subject" (("DisplayName" NIL "Name" "Domain")) (("DisplayName" NIL "Name" "Domain")) (("DisplayName" NIL "Name" "Domain")) (("DisplayName" NIL "Name" "Domain")) NIL NIL NIL "<messageid>") FLAGS (\\Seen) INTERNALDATE "01-Sat-2010 01:01:01 +0000" UID 12345)
	));

	is->FeedLine(line);

	is->FeedLine("~A1 OK");
	is->FlushBuffer();

	const Email& email = *GetOneEmail(parser);
	//fprintf(stderr, "email subject: [%s]\n", email.GetSubject().c_str());
	ASSERT_EQ( email.GetSubject(), "Subject" );
#endif
}

// Test parsing GMX email sent from Gmail (NOV-114378)
TEST(FetchResponseParserTest, TestGmxGmail)
{
#if TEST_ALL
	MockTestSetup setup;
	MockImapSession& session = setup.GetSession();

	const MockInputStreamPtr& is = session.GetMockInputStream();

	MockDoneSlot slot;
	MojRefCountedPtr<FetchResponseParser> parser(new FetchResponseParser(session, slot.GetSlot()));

	session.SendRequest("UID FETCH 1024 (BODYSTRUCTURE)", parser);

	string line = QUOTE_IMAP((
		* 3 FETCH (UID 3 FLAGS (\\Seen) INTERNALDATE " 1-Sep-2010 07:41:29 +0000" ENVELOPE ("Wed, 1 Sep 2010 00:41:28 -0700" "Test from Gmail" (("Person Name" NIL "username" "gmail.com")) (("Person Name" NIL "username" "gmail.com")) (("Person Name" NIL "username" "gmail.com")) ((NIL NIL "username" "gmx.com")) NIL NIL NIL "<AANLkTikO5jp73tOVKZaT2OumxsaFkFv84M8g3r9OYt_g@mail.gmail.com>") BODYSTRUCTURE (("text" "plain" ("charset" "UTF-8") NIL NIL NIL 7 1 NIL NIL NIL NIL)("text" "html" ("charset" "UTF-8") NIL NIL NIL 11 1 NIL NIL NIL NIL) "alternative" ("boundary" "00504501427351c79a048f2dd333") NIL NIL NIL))
	));

	is->FeedLine(line);

	is->FeedLine("~A1 OK");
	is->FlushBuffer();

	const Email& email = *GetOneEmail(parser);
	ASSERT_EQ( email.GetPartList().size(), (size_t) 1 );
#endif
}

TEST(FetchResponseParserTest, TestPriority)
{
#if TEST_ALL
	MockTestSetup setup;
	MockImapSession& session = setup.GetSession();

	const MockInputStreamPtr& is = session.GetMockInputStream();

	MockDoneSlot slot;
	MojRefCountedPtr<FetchResponseParser> parser(new FetchResponseParser(session, slot.GetSlot()));

	session.SendRequest("UID FETCH 1024 (BODY.PEEK[HEADER.FIELDS (X-PRIORITY IMPORTANCE)])", parser);

	stringstream data;
	data << "* 1 FETCH (UID 1024 BODY[HEADER.FIELDS (X-PRIORITY IMPORTANCE)] ";
	string headers = "X-Priority: 1\r\nImportance: high\r\n\r\n";
	data << "{" << headers.size() << "}\r\n" << headers;
	data << ")\r\n";

	is->Feed(data.str());

	is->FeedLine("~A1 OK");
	is->FlushBuffer();

	const Email& email = *GetOneEmail(parser);
	ASSERT_EQ( email.GetPriority(), Email::Priority_High );
#endif
}

TEST(FetchResponseParserTest, TestNewsletter)
{
#if TEST_ALL
	MockTestSetup setup;
	MockImapSession& session = setup.GetSession();

	const MockInputStreamPtr& is = session.GetMockInputStream();

	MockDoneSlot slot;
	MojRefCountedPtr<FetchResponseParser> parser(new FetchResponseParser(session, slot.GetSlot()));

	session.SendRequest("UID FETCH 16592 (UID FLAGS INTERNALDATE ENVELOPE BODYSTRUCTURE BODY.PEEK[HEADER.FIELDS (X-PRIORITY IMPORTANCE)])", parser);

	is->Feed("* 1865 FETCH (");

	string line = QUOTE_IMAP((
		UID 16592 INTERNALDATE "22-Dec-2010 00:43:02 +0000" FLAGS () ENVELOPE ("Wed, 22 Dec 2010 00:15:28 +0000" "Newsletter subject" (("Newsletter" NIL "no-reply" "example.org")) (("Newsletter" NIL "no-reply" "example.org")) (("Newsletter" NIL "no-reply" "example.org")) ((NIL NIL "username" "gmail.com")) NIL NIL NIL "<182282256630734534706@example.net>") BODYSTRUCTURE (("TEXT" "PLAIN" ("CHARSET" "ISO-8859-1") NIL NIL "7BIT" 1195 29 NIL NIL NIL)("TEXT" "HTML" ("CHARSET" "ISO-8859-1") NIL NIL "7BIT" 4846 135 NIL NIL NIL) "ALTERNATIVE" ("BOUNDARY" "----AGJNG_9303_0.430396692595324") NIL NIL) BODY[HEADER.FIELDS (X-PRIORITY IMPORTANCE)] {17}
	));

	is->FeedLine(line);

	is->Feed("X-Priority: 3\r\n\r\n");
	is->FeedLine(")");

	is->FeedLine("~A1 OK");
	is->FlushBuffer();
#endif
}

#if 0
TEST(FetchResponseParserTest, TestFromFile)
{
	MockTestSetup setup;
	MockImapSession& session = setup.GetSession();

	const MockInputStreamPtr& is = session.GetMockInputStream();

	MockDoneSlot slot;
	MojRefCountedPtr<FetchResponseParser> parser(new FetchResponseParser(session, slot.GetSlot()));

	session.SendRequest("UID FETCH 1024 (ENVELOPE BODYSTRUCTURE)", parser);

	ifstream stream("testmail.txt", ifstream::in);

	while(stream.good()) {
		string line;
		getline(stream, line);
		is->FeedLine(line);
	}

	is->FeedLine("~A1 OK");
	is->FlushBuffer();

	parser->CheckStatus();
}
#endif

TEST(FetchResponseParserTest, TestDelivery)
{
#if TEST_ALL
	MockTestSetup setup;
	MockImapSession& session = setup.GetSession();

	const MockInputStreamPtr& is = session.GetMockInputStream();

	MockDoneSlot slot;
	MojRefCountedPtr<FetchResponseParser> parser(new FetchResponseParser(session, slot.GetSlot()));

	session.SendRequest("UID FETCH 16592 (UID FLAGS INTERNALDATE ENVELOPE BODYSTRUCTURE BODY.PEEK[HEADER.FIELDS (X-PRIORITY IMPORTANCE)])", parser);

	//is->Feed("* 1865 FETCH (");

	string line = QUOTE_IMAP((
		* 9315 FETCH (UID 18990 INTERNALDATE "07-May-2011 03:47:58 +0000" ENVELOPE ("Fri, 6 May 2011 20:47:58 -0700 (PDT)" "Re: Re: FW: Subject" ((NIL NIL "noreply" "example.com")) ((NIL NIL "noreply" "example.com")) ((NIL NIL "username3" "gmail.com")) (("Person Name" NIL "username" "gmail.com")) NIL NIL NIL "<913133060.323598.1304740078102.JavaMail.prod@app010.dmz>") BODYSTRUCTURE ((("TEXT" "PLAIN" ("CHARSET" "us-ascii") NIL NIL "7BIT" 481 20 NIL ("INLINE" NIL) NIL)("TEXT" "HTML" ("CHARSET" "us-ascii") NIL NIL "7BIT" 1259 41 NIL ("INLINE" NIL) NIL) "ALTERNATIVE" ("BOUNDARY" "----=_Part_323596_529173644.1304740078099") ("INLINE" NIL) NIL)("MESSAGE" "DELIVERY-STATUS" NIL NIL "Delivery report" "7BIT" 296 NIL NIL NIL)("MESSAGE" "RFC822" NIL NIL "Undelivered Message" "7BIT" 2687 ("Fri, 6 May 2011 20:47:37 -0700" "Re: FW: my last sunset at palm (now with correct photo album link)" (("Person Name" NIL "username" "gmail.com")) (("Person Name" NIL "username" "gmail.com")) (("Person Name" NIL "username" "gmail.com")) ((NIL NIL "username2" "gmail.com")) NIL NIL "<C9EA0E53.F3FD%username@palm.com>" "<BANLkTimFmki7Gr9tY-F5-XorjtoaPCsjDA@mail.gmail.com>") ("ALTERNATIVE" ("BOUNDARY" "20cf307f37c8ad482004a2a77770") NIL NIL) 50 NIL NIL NIL) "REPORT" ("BOUNDARY" "----=_Part_323597_1355088785.1304740078099" "REPORT-TYPE" "delivery-status") NIL NIL))
	));

	is->FeedLine(line);
	is->FeedLine("~A1 OK");
	is->FlushBuffer();
#endif
}

TEST(FetchResponseParserTest, TestDelivery2)
{
#if TEST_ALL
	MockTestSetup setup;
	MockImapSession& session = setup.GetSession();

	const MockInputStreamPtr& is = session.GetMockInputStream();

	MockDoneSlot slot;
	MojRefCountedPtr<FetchResponseParser> parser(new FetchResponseParser(session, slot.GetSlot()));

	session.SendRequest("UID FETCH 16592 (UID FLAGS INTERNALDATE ENVELOPE BODYSTRUCTURE BODY.PEEK[HEADER.FIELDS (X-PRIORITY IMPORTANCE)])", parser);

	string line = QUOTE_IMAP((
		* 58 FETCH (BODYSTRUCTURE ((("TEXT" "PLAIN" ("CHARSET" "us-ascii") NIL NIL "7BIT" 433 20 NIL ("INLINE" NIL) NIL)("TEXT" "HTML" ("CHARSET" "us-ascii") NIL NIL "7BIT" 1210 41 NIL ("INLINE" NIL) NIL) "ALTERNATIVE" ("BOUNDARY" "----=_Part_588821_1929170139.1304880014424") ("INLINE" NIL) NIL)("MESSAGE" "DELIVERY-STATUS" NIL NIL "Delivery report" "7BIT" 287 NIL NIL NIL)("MESSAGE" "RFC822" NIL NIL "Undelivered Message" "7BIT" 2213 ("Sun, 8 May 2011 11:40:07 -0700" "Subject of original email" (("Name" NIL "name" "gmail.com")) (("Name" NIL "username2" "gmail.com")) (("Name" NIL "name" "gmail.com")) ((NIL NIL "name" "name")) NIL NIL "NIL" "<msgid>") ("ALTERNATIVE" ("BOUNDARY" "bcaec52155a757fdc604a2c80da0") NIL NIL) 39 NIL NIL NIL) "REPORT" ("BOUNDARY" "----=_Part_588822_854423767.1304880014424" "REPORT-TYPE" "delivery-status") NIL NIL))
	));

	is->FeedLine(line);
	is->FeedLine("~A1 OK");
	is->FlushBuffer();
#endif
}

TEST(FetchResponseParserTest, TestNoAlternatives)
{
#if TEST_ALL
	MockTestSetup setup;
	MockImapSession& session = setup.GetSession();

	const MockInputStreamPtr& is = session.GetMockInputStream();

	MockDoneSlot slot;
	MojRefCountedPtr<FetchResponseParser> parser(new FetchResponseParser(session, slot.GetSlot()));

	session.SendRequest("UID FETCH 16592 (UID FLAGS INTERNALDATE ENVELOPE BODYSTRUCTURE BODY.PEEK[HEADER.FIELDS (X-PRIORITY IMPORTANCE)])", parser);

	string line = QUOTE_IMAP((
			* 2536 FETCH (BODYSTRUCTURE ("ALTERNATIVE" ("BOUNDARY" "XYZZY") NIL NIL))
	));

	is->FeedLine(line);
	is->FeedLine("~A1 OK");
	is->FlushBuffer();
#endif
}

max_stars_repo_name: webOS-ports/mojomail

max_issues_repo_name: openwebos/app-services

max_forks_repo_name: openwebos/app-services


text:
#ifndef POTOK_HPACK_ENCODE_HPP_
#define POTOK_HPACK_ENCODE_HPP_

#include <potok/hpack/common.hpp>
#include <potok/hpack/error.hpp>

#include <potok/stdint.hpp>

#include <boost/asio/buffer.hpp>
#include <boost/asio/buffers_iterator.hpp>

#include <boost/assert.hpp>

#include <boost/throw_exception.hpp>

#include <stdexcept>

namespace potok {
namespace hpack {

// from the hpack rfc (https://datatracker.ietf.org/doc/html/rfc7541#section-5.1):
//  Pseudocode to represent an integer I is as follows:
//  if I < 2^N - 1, encode I on N bits
//  else
//      encode (2^N - 1) on N bits
//      I = I - (2^N - 1)
//      while I >= 128
//           encode (I % 128 + 128) on 8 bits
//           I = I / 128
//      encode I on 8 bits

struct integer_encoder {
  enum class state { first, continuation, final, done };

  u64      v_               = 0;
  state    state_           = state::first;
  u8 const num_prefix_bits_ = 0;

  integer_encoder()                       = delete;
  integer_encoder(integer_encoder const&) = default;
  integer_encoder(integer_encoder&&)      = default;

  integer_encoder(u64 const v, u8 const num_prefix_bits)
      : v_{v}
      , num_prefix_bits_{num_prefix_bits}
  {
  }

  template <class MutableBufferSequence>
  auto operator()(MutableBufferSequence      mutable_buf_seq,    //
                  boost::system::error_code& ec) -> usize
  {
    auto pos = boost::asio::buffers_begin(mutable_buf_seq);
    auto end = boost::asio::buffers_end(mutable_buf_seq);

    auto bytes_written = usize{0};

    if (pos == end) {
      ec = error::needs_more;
      return bytes_written;
    }

    u64 const max_prefix_value = get_max_prefix_value(num_prefix_bits_);

    switch (state_) {
      case state::first: {
        // clear the initial octet in preparation of writing the first N bits of the integer
        //
        *pos &= ~max_prefix_value;

        if (v_ < max_prefix_value) {
          *pos++ |= v_;
          ++bytes_written;

          state_ = state::done;

          break;
        }

        *pos++ |= max_prefix_value;
        ++bytes_written;

        state_ = state::continuation;

        v_ -= max_prefix_value;
      }

      case state::continuation: {
        for (; (pos != end) && (v_ >= 128); ++pos, ++bytes_written, v_ /= 128) {
          auto const v = (v_ % 128 + 128);

          *pos = v;
        }

        if (v_ >= 128) {
          ec     = error::needs_more;
          state_ = state::continuation;
          break;
        }

        if (pos == end) {
          ec     = error::needs_more;
          state_ = state::final;
          break;
        }
      }

      case state::final: {
        *pos++ = v_;
        ++bytes_written;

        state_ = state::done;
        break;
      }

      case state::done:
        break;
    }

    return bytes_written;
  }
};

}    // namespace hpack
}    // namespace potok

#endif    // POTOK_HPACK_ENCODE_HPP_