text:
#include "VoxelWorld.hpp"
#include <boost/filesystem.hpp>
#include <iostream>
#include <Engine/ShaderManager.hpp>
#include <Engine/MainGraphic.hpp>
#include <Engine/Frustum.hpp>
#include <Engine/Display/DisplayWindow.hpp>
#include <Engine/CameraManager.hpp>
#include <Engine/Time.hpp>
#include <PathManager.hpp>

VoxelWorld::VoxelWorld(Camera &camera) :
camera_(camera) {
    camera_.getFrustum().setDebug(true);

    ShaderManager::Get().addShader("voxel");
    ShaderManager::Get().getShader("voxel").attach((PathManager::Get().getPath("shaders") / "voxel.vert").generic_string());
    ShaderManager::Get().getShader("voxel").attach((PathManager::Get().getPath("shaders") / "voxel.geom").generic_string());
    ShaderManager::Get().getShader("voxel").attach((PathManager::Get().getPath("shaders") / "voxel.frag").generic_string());
    ShaderManager::Get().getShader("voxel").link();
}

void VoxelWorld::start() {

    lastChucnkPosition_.x = camera_.getPosition().x / CHUNK_SIZE_X;
    lastChucnkPosition_.y = camera_.getPosition().z / CHUNK_SIZE_Z;

    heightMapBuilder.SetSourceModule (VoxelWorld::Get().myModule);
    heightMapBuilder.SetDestNoiseMap (heightMap);
    heightMapBuilder.SetDestSize (CHUNK_SIZE_X * 3, CHUNK_SIZE_Z * 3);

    for (int z = -DEFAULT_VOXEL_RADIUS_RENDER_DISTANCE; z < DEFAULT_VOXEL_RADIUS_RENDER_DISTANCE; z++)
        for (int x = -DEFAULT_VOXEL_RADIUS_RENDER_DISTANCE; x < DEFAULT_VOXEL_RADIUS_RENDER_DISTANCE; x++)
            chunks_.emplace_back(
                    glm::vec2(lastChucnkPosition_.x + x , lastChucnkPosition_.y + z),
                    (x + DEFAULT_VOXEL_RADIUS_RENDER_DISTANCE) + (z + DEFAULT_VOXEL_RADIUS_RENDER_DISTANCE) * DEFAULT_VOXEL_RADIUS_RENDER_DISTANCE);
}

void VoxelWorld::update() {
    std::cout << "Update" << std::endl;
    Timer timer;
    timer.start();

    glm::ivec2 newChunkPosition;

    newChunkPosition.x = camera_.getPosition().x / CHUNK_SIZE_X;
    newChunkPosition.y = camera_.getPosition().z / CHUNK_SIZE_Z;

    //std::cout << "newChunkPosition" << std::endl;
    //std::cout << "x[" << newChunkPosition.x << "]y[" << newChunkPosition.y << "]" << std::endl;

    std::list< Chunk > newChunk;
    if (lastChucnkPosition_ != newChunkPosition) {

        float f = 0.082f;
        heightMapBuilder.SetBounds ((newChunkPosition.x - DEFAULT_VOXEL_RADIUS_RENDER_DISTANCE - 1) * f,
                (newChunkPosition.x + DEFAULT_VOXEL_RADIUS_RENDER_DISTANCE + 2) * f,
                (newChunkPosition.y - DEFAULT_VOXEL_RADIUS_RENDER_DISTANCE - 1) * f,
                (newChunkPosition.y + DEFAULT_VOXEL_RADIUS_RENDER_DISTANCE + 2) * f);
        heightMapBuilder.Build ();
        renderer.SetSourceNoiseMap (heightMap);
        renderer.SetDestImage (image);
        renderer.Render ();

        glm::ivec2 test = lastChucnkPosition_ - newChunkPosition;
        //std::cout << "newChunkPosition" << std::endl;
        //std::cout << "x[" << test.x << "]y[" << test.y << "]" << std::endl;
        for(auto it = chunks_.begin(); it != chunks_.end();)
        {
            glm::ivec2 test2 = newChunkPosition - it->chunkPosition_;
            //std::cout << "test" << std::endl;
            //std::cout << "x[" << test2.x << "]y[" << test2.y << "]" << std::endl;
            if (test2.x < -DEFAULT_VOXEL_RADIUS_RENDER_DISTANCE
                || test2.x > DEFAULT_VOXEL_RADIUS_RENDER_DISTANCE
                || test2.y < -DEFAULT_VOXEL_RADIUS_RENDER_DISTANCE
                || test2.y > DEFAULT_VOXEL_RADIUS_RENDER_DISTANCE)
            {
                it->setRender(false);
            }
                ++it;
        }
        for (int z = -DEFAULT_VOXEL_RADIUS_RENDER_DISTANCE; z < DEFAULT_VOXEL_RADIUS_RENDER_DISTANCE; z++) {
            for (int x = -DEFAULT_VOXEL_RADIUS_RENDER_DISTANCE; x < DEFAULT_VOXEL_RADIUS_RENDER_DISTANCE; x++) {
                auto it = std::find_if(chunks_.begin(), chunks_.end(), [x, z, newChunkPosition](Chunk const &chunk)->bool {
                    return (chunk.chunkPosition_.x == newChunkPosition.x + x
                    && chunk.chunkPosition_.y == newChunkPosition.y + z);
                });
                if (it == chunks_.end()) {

                    auto voided = std::find_if(chunks_.begin(), chunks_.end(), [x, z, newChunkPosition](Chunk const &chunk)->bool {
                        return (!chunk.getRender());
                    });

                    if (voided != chunks_.end()) {
                        voided->reload(glm::vec2(newChunkPosition.x + x , newChunkPosition.y + z),
                                        (x + DEFAULT_VOXEL_RADIUS_RENDER_DISTANCE) + (z + DEFAULT_VOXEL_RADIUS_RENDER_DISTANCE) * DEFAULT_VOXEL_RADIUS_RENDER_DISTANCE);
                        voided->setRender(true);
                    }

                    //chunks_.emplace_back(
                    //        glm::vec2(newChunkPosition.x + x , newChunkPosition.y + z),
                    //        (x + DEFAULT_VOXEL_RADIUS_RENDER_DISTANCE) + (z + DEFAULT_VOXEL_RADIUS_RENDER_DISTANCE) * DEFAULT_VOXEL_RADIUS_RENDER_DISTANCE);
                }
            }
        }
        std::cout << "Size lst [" << chunks_.size() << "]" << std::endl;
        lastChucnkPosition_ = newChunkPosition;
    }
    timer.stop();

    std::cout << "Elapsed time : " << timer.count() << "ms" << std::endl;
}

void VoxelWorld::render() {

    if (DisplayWindow::Get().getKey(GLFW_KEY_M) == KeyState::kDown)
        camera_.getFrustum().setDebug(!camera_.getFrustum().isDebug());
   camera_.getFrustum().update();

    Shader &shader = ShaderManager::Get().getShader("voxel");

    shader.activate();
    shader.setMat4("projection", Camera::focus->getProjectionMatrix());
    shader.setMat4("view", Camera::focus->getViewMatrix());

    for (auto &i : chunks_) {
        if (!camera_.getFrustum().isDebug() || camera_.getFrustum().pointIn(i.worldPosition_.x + (CHUNK_SIZE_X >> 1), i.worldPosition_.y + (CHUNK_SIZE_Y >> 1), i.worldPosition_.z + (CHUNK_SIZE_Z >> 1)))
            i.render();
    }
}

void VoxelWorld::Init(Camera &camera) {
    VoxelWorld::instance_ = std::make_unique<VoxelWorld>(camera);
}

VoxelWorld &VoxelWorld::Get() {
    assert(!!instance_);
    return *instance_;
}

std::unique_ptr<VoxelWorld> VoxelWorld::instance_ = nullptr;


text:
/*
 * =====================================================================================
 *
 *       Filename:  lru_cache.cc
 *
 *    Description:
 *
 *        Version:  1.0
 *        Created:  2020年09月24日 16时40分50秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  YOUR NAME (),
 *   Organization:
 *
 * =====================================================================================
 */

#include <iostream>
#include <string>
#include <numeric>
#include <vector>
#include <algorithm>

#include <boost/compute/detail/lru_cache.hpp>

using namespace std;
using namespace boost::compute::detail;

int main(int argc, char **argv)
{
	lru_cache<string, int> lc(3);

	lc.insert("fanpf", 37);
	lc.insert("rose", 33);
	lc.insert("fanyf", 35);

	boost::optional<int>  opt_fpf = lc.get("fanpf");
	lc.insert("11", 35); //fanpf lose
	if(lc.contains("fanpf")){
		cout << "ok!" << endl;
	} else {
		cout << "not contain!" << endl;
		exit(1);
	}

#if 0
	assert(lc.contains("fanpf"));
	lc.insert("11", 35); //fanpf lose
	assert(!lc.contains("fanpf"));
#endif

	boost::optional<int>  opt_age = lc.get("1rose");

	if (lc.contains("rose")) {
		boost::optional<int>  opt_age = lc.get("rose");
		cout << "rose age:" << opt_age.get() << endl;
	}

	return 0;
}

ext: cc


text:
#include "tcp_socket.hpp"

#include "../utils/utils.hpp"
#include <boost/asio/write.hpp>

namespace proxy::tcp
{
	tcp_socket::tcp_socket(io_context_type& io_context)
		: socket_(io_context), buffer_() { }

	void tcp_socket::connect(const address_type& address)
	{
		socket_.connect(make_endpoint(address));
	}

	void tcp_socket::connect(const endpoint_type& endpoint)
	{
		socket_.connect(endpoint);
	}

	bool tcp_socket::close(boost::system::error_code& shutdown_ec, boost::system::error_code& close_ec)
	{
		if (!socket_.is_open())
		{
			return false;
		}

		socket_.shutdown(boost::asio::socket_base::shutdown_both, shutdown_ec);
		socket_.close(close_ec);
		return true;
	}

	void tcp_socket::close()
	{
		boost::system::error_code shutdown_dummy;
		boost::system::error_code close_dummy;
		close(shutdown_dummy, close_dummy);
	}

	tcp_socket::size_type tcp_socket::write(const buffer_type&         buffer, const size_type max_size_in_bytes,
											boost::system::error_code& error_code)
	{
		return boost::asio::write(socket_, boost::asio::buffer(buffer, max_size_in_bytes), error_code);
	}

	std::string tcp_socket::sample_buffer(const size_type size) const
	{
		return utils::bin_to_hex({buffer_.data(), size});
	}

	tcp_socket::address_type tcp_socket::get_remote_address() const
	{
		if (socket_.is_open())
		{
			try
			{
				return make_address(socket_.remote_endpoint());
			}
			catch (const std::exception&) {}
		}

		return {};
	}

	std::string tcp_socket::get_remote_address_string() const
	{
		return get_remote_address().to_string();
	}

	tcp_socket::address_type tcp_socket::get_local_address() const
	{
		if (socket_.is_open())
		{
			try
			{
				return make_address(socket_.local_endpoint());
			}
			catch (const std::exception&) {}
		}

		return {};
	}

	std::string tcp_socket::get_local_address_string() const
	{
		return get_local_address().to_string();
	}

	std::string tcp_socket::get_session_id() const
	{
		{
			return std::format("local: {} - remote: {}",
								get_local_address_string(),
								get_remote_address_string());
		}
	}

	tcp_socket::endpoint_type tcp_socket::make_endpoint(const address_type& address)
	{
		return boost::asio::ip::tcp::endpoint(
											boost::asio::ip::make_address(address.ip),
											address.port
											);
	}

	tcp_socket::address_type tcp_socket::make_address(const endpoint_type& endpoint)
	{
		return {
			.ip = endpoint.address().to_string(),
			.port = endpoint.port()
		};
	}
}

ext: cpp


text:
/* (c) Copyright 2012 Felipe Magno de Almeida
 *
 * 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 MORBID_VAR_HPP
#define MORBID_VAR_HPP

#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>

namespace morbid {

template <typename T>
struct var
{
  var(boost::shared_ptr<T> p)
    : p(p) {}

  boost::shared_ptr<T> operator->() const { return p; }
  operator boost::shared_ptr<T>() const { return p; }

  boost::shared_ptr<T> in() const { return p; }
  bool operator!() const { return !p; }

private:
  boost::shared_ptr<T> p;
};

template <typename T>
struct array_var
{
  array_var(boost::shared_array<T> p)
    : p(p) {}

  T* in() const { return p.get(); }

private:
  boost::shared_array<T> p;
};

}

#endif

ext: hpp

max_stars_repo_name: felipealmeida/mORBid

max_issues_repo_name: felipealmeida/mORBid

max_forks_repo_name: felipealmeida/mORBid


text:
/* $Id: lexical_cast.hpp 48153 2011-01-01 15:57:50Z mordante $ */
/*
   Copyright (C) 2009 - 2011 by Mark de Wever <koraq@xs4all.nl>
   Part of the Battle for Wesnoth Project http://www.wesnoth.org/

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY.

   See the COPYING file for more details.
*/

/**
 * @file
 * New lexcical_cast header.
 *
 * For debugging you can include this header _in_ a namespace (to honour ODR)
 * and have a set of functions that throws exceptions instead of doing the
 * real job. This is done for the unit tests but should normally not be done.
 */

#ifdef LEXICAL_CAST_DEBUG
#undef LEXICAL_CAST_HPP_INCLUDED
#endif

#ifndef LEXICAL_CAST_HPP_INCLUDED
#define LEXICAL_CAST_HPP_INCLUDED

#ifdef LEXICAL_CAST_DEBUG

#undef DEBUG_THROW
/**
 * Throws an exception for debugging.
 *
 * @param id                      The unique name to identify the function.
 *                                @note this name is a user defined string and
 *                                should not be modified once used!
 */
#define DEBUG_THROW(id) throw id;
#else

#ifdef __FreeBSD__
#define __LONG_LONG_SUPPORTED
#endif

#include <string>
#include <sstream>
#include <boost/mpl/set.hpp>
#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>

#define DEBUG_THROW(id)
#endif

/**
 * @namespace implementation
 * Contains the implementation details for lexical_cast and shouldn't be used
 * directly.
 */
namespace implementation {

	template<
		  typename To
		, typename From
		, typename ToEnable = void
		, typename FromEnable = void
	>
	struct tlexical_cast;

} // namespace implementation

/**
 * Lexical cast converts one type to another.
 *
 * @tparam To                     The type to convert to.
 * @tparam From                   The type to convert from.
 *
 * @param value                   The value to convert.
 *
 * @returns                       The converted value.
 */
template<typename To, typename From>
inline To lexical_cast(From value)
{
	return implementation::tlexical_cast<To, From>().operator()(value);
}

/** Thrown when a lexical_cast fails. */
struct bad_lexical_cast {};

namespace implementation {

/**
 * Base class for the conversion.
 *
 * Since functions can't be partially specialized we use a class, which can be
 * partially specialized for the conversion.
 *
 * @tparam To                     The type to convert to.
 * @tparam From                   The type to convert from.
 * @tparam ToEnable               Filter to enable the To type.
 * @tparam FromEnable             Filter to enable the From type.
 */
template<
	  typename To
	, typename From
	, typename ToEnable
	, typename FromEnable
>
struct tlexical_cast
{
	To operator()(From value)
	{
		DEBUG_THROW("generic");

		To result;
		std::stringstream sstr;

		if(!(sstr << value && sstr >> result)) {
			throw bad_lexical_cast();
		} else {
			return result;
		}
	}
};

/**
 * Specialized conversion class.
 *
 * Specialized for returning strings from an integral type or a pointer to an
 * intergral type.
 */
template <typename From>
struct tlexical_cast<
	  std::string
	, From
	, void
	, typename boost::enable_if<boost::is_integral<
			typename boost::remove_pointer<From>::type> >::type
>
{
	std::string operator()(From value)
	{
		DEBUG_THROW("specialized - To std::string - From integral (pointer)");

		std::stringstream sstr;
		sstr << value;
		return sstr.str();
	}
};

/**
 * Specialized conversion class.
 *
 * Specialized for returning a long long from a (const) char*.
 * @note is separate from the other signed types since a long long has a
 * performance penalty at 32 bit systems.
 */
template <class From>
struct tlexical_cast<
	  long long
	, From
	, void
	, typename boost::enable_if<boost::mpl::has_key<boost::mpl::set<
			char*, const char*> , From> >::type
	>
{
	long long operator()(From value)
	{
		DEBUG_THROW("specialized - To long long - From (const) char*");

		char* endptr;
		int res = strtoll(value, &endptr, 10);

		if (*value == '\0' || *endptr != '\0') {
			throw bad_lexical_cast();
		} else {
			return res;
		}
	}
};

/**
 * Specialized conversion class.
 *
 * Specialized for returning a long long from a std::string.
 * @note is separate from the other signed types since a long long has a
 * performance penalty at 32 bit systems.
 */
template <>
struct tlexical_cast<
	  long long
	, std::string
	>
{
	long long operator()(const std::string& value)
	{
		DEBUG_THROW("specialized - To long long - From std::string");

		return lexical_cast<long long>(value.c_str());
	}
};

/**
 * Specialized conversion class.
 *
 * Specialized for returning a signed type from a (const) char*.
 */
template <class To, class From>
struct tlexical_cast<
	  To
	, From
	, typename boost::enable_if<boost::is_signed<To> >::type
	, typename boost::enable_if<boost::mpl::has_key<boost::mpl::set<
			char*, const char*> , From> >::type
	>
{
	To operator()(From value)
	{
		DEBUG_THROW("specialized - To signed - From (const) char*");

		char* endptr;
		int res = strtol(value, &endptr, 10);

		if (*value == '\0' || *endptr != '\0') {
			throw bad_lexical_cast();
		} else {
			return res;
		}
	}
};

/**
 * Specialized conversion class.
 *
 * Specialized for returning a signed type from a std::string.
 */
template <class To>
struct tlexical_cast<
	  To
	, std::string
	, typename boost::enable_if<boost::is_signed<To> >::type
	>
{
	To operator()(const std::string& value)
	{
		DEBUG_THROW("specialized - To signed - From std::string");

		return lexical_cast<To>(value.c_str());
	}
};

/**
 * Specialized conversion class.
 *
 * Specialized for returning a unsigned long long from a (const) char*.
 * @note is separate from the other unsigned types since a unsigned long long
 * has a performance penalty at 32 bit systems.
 */
template <class From>
struct tlexical_cast<
	  unsigned long long
	, From
	, void
	, typename boost::enable_if<boost::mpl::has_key<boost::mpl::set<
			char*, const char*> , From> >::type
	>
{
	long long operator()(From value)
	{
		DEBUG_THROW(
				"specialized - To unsigned long long - From (const) char*");

		char* endptr;
		int res = strtoull(value, &endptr, 10);

		if (*value == '\0' || *endptr != '\0') {
			throw bad_lexical_cast();
		} else {
			return res;
		}
	}
};

/**
 * Specialized conversion class.
 *
 * Specialized for returning a unsigned long long from a std::string.
 * @note is separate from the other unsigned types since a unsigned long long
 * has a performance penalty at 32 bit systems.
 */
template <>
struct tlexical_cast<
	  unsigned long long
	, std::string
	>
{
	long long operator()(const std::string& value)
	{
		DEBUG_THROW("specialized - To unsigned long long - From std::string");

		return lexical_cast<unsigned long long>(value.c_str());
	}
};

/**
 * Specialized conversion class.
 *
 * Specialized for returning a unsigned type from a (const) char*.
 */
template <class To, class From>
struct tlexical_cast<
	  To
	, From
	, typename boost::enable_if<boost::is_unsigned<To> >::type
	, typename boost::enable_if<boost::mpl::has_key<boost::mpl::set<
			char*, const char*> , From> >::type
	>
{
	To operator()(From value)
	{
		DEBUG_THROW("specialized - To unsigned - From (const) char*");

		char* endptr;
		int res = strtoul(value, &endptr, 10);

		if (*value == '\0' || *endptr != '\0') {
			throw bad_lexical_cast();
		} else {
			return res;
		}
	}
};

/**
 * Specialized conversion class.
 *
 * Specialized for returning a unsigned type from a std::string.
 */
template <class To>
struct tlexical_cast<
	  To
	, std::string
	, typename boost::enable_if<boost::is_unsigned<To> >::type
	>
{
	To operator()(const std::string& value)
	{
		DEBUG_THROW("specialized - To unsigned - From std::string");

		return lexical_cast<To>(value.c_str());
	}
};

} // namespace implementation

#endif

max_stars_repo_name: blackberry/Wesnoth

max_issues_repo_name: blackberry/Wesnoth

max_forks_repo_name: blackberry/Wesnoth


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

/* Author: Ryan Luna */

#include "ompl/base/PlannerData.h"
#include "ompl/base/PlannerDataGraph.h"
#include "ompl/base/StateStorage.h"
#include "ompl/base/OptimizationObjective.h"
#include "ompl/base/objectives/PathLengthOptimizationObjective.h"
#include "ompl/base/ScopedState.h"

#include <boost/graph/graphviz.hpp>
#include <boost/graph/graphml.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/version.hpp>
#if BOOST_VERSION < 105100
#warning Boost version >=1.51 is needed for ompl::base::PlannerData::printGraphML
#else
#include <boost/property_map/function_property_map.hpp>
#endif

// This is a convenient macro to cast the void* graph pointer as the
// Boost.Graph structure from PlannerDataGraph.h
#define graph_ reinterpret_cast<ompl::base::PlannerData::Graph*>(graphRaw_)

const ompl::base::PlannerDataEdge   ompl::base::PlannerData::NO_EDGE = ompl::base::PlannerDataEdge();
const ompl::base::PlannerDataVertex ompl::base::PlannerData::NO_VERTEX = ompl::base::PlannerDataVertex(0);
const unsigned int ompl::base::PlannerData::INVALID_INDEX = std::numeric_limits<unsigned int>::max();

ompl::base::PlannerData::PlannerData (const SpaceInformationPtr &si) : si_(si)
{
    graphRaw_ = new Graph();
}

ompl::base::PlannerData::~PlannerData ()
{
    freeMemory();

    if (graph_)
    {
        delete graph_;
        graphRaw_ = NULL;
    }
}

void ompl::base::PlannerData::clear ()
{
    freeMemory();
    decoupledStates_.clear();
}

void ompl::base::PlannerData::decoupleFromPlanner ()
{
    unsigned int count = 0;
    for (unsigned int i = 0; i < numVertices(); ++i)
    {
        PlannerDataVertex &vtx = getVertex(i);
        // If this vertex's state is not in the decoupled list, clone it and add it
        if (decoupledStates_.find(const_cast<State*>(vtx.getState())) == decoupledStates_.end())
        {
            const State *oldState = vtx.getState();
            State *clone = si_->cloneState(oldState);
            decoupledStates_.insert(clone);
            // Replacing the shallow state pointer with our shiny new clone
            vtx.state_ = clone;

            // Remove oldState from stateIndexMap
            stateIndexMap_.erase(oldState);
            // Add the new, cloned state to stateIndexMap
            stateIndexMap_[clone] = i;
            count++;
        }
    }
}

unsigned int ompl::base::PlannerData::getEdges (unsigned int v, std::vector<unsigned int>& edgeList) const
{
    std::pair<Graph::AdjIterator, Graph::AdjIterator> iterators = boost::adjacent_vertices(boost::vertex(v, *graph_), *graph_);

    edgeList.clear();
    boost::property_map<Graph::Type, boost::vertex_index_t>::type vertices = get(boost::vertex_index, *graph_);
    for (Graph::AdjIterator iter = iterators.first; iter != iterators.second; ++iter)
        edgeList.push_back(vertices[*iter]);

    return edgeList.size();
}

unsigned int ompl::base::PlannerData::getEdges (unsigned int v, std::map<unsigned int, const PlannerDataEdge*>& edgeMap) const
{
    std::pair<Graph::OEIterator, Graph::OEIterator> iterators = boost::out_edges(boost::vertex(v, *graph_), *graph_);

    edgeMap.clear();
    boost::property_map<Graph::Type, edge_type_t>::type edges = get(edge_type_t(), *graph_);
    boost::property_map<Graph::Type, boost::vertex_index_t>::type vertices = get(boost::vertex_index, *graph_);
    for (Graph::OEIterator iter = iterators.first; iter != iterators.second; ++iter)
        edgeMap[vertices[boost::target(*iter, *graph_)]] = boost::get(edges, *iter);

    return edgeMap.size();
}

unsigned int ompl::base::PlannerData::getIncomingEdges (unsigned int v, std::vector<unsigned int>& edgeList) const
{
    std::pair<Graph::IEIterator, Graph::IEIterator> iterators = boost::in_edges(boost::vertex(v, *graph_), *graph_);

    edgeList.clear();
    boost::property_map<Graph::Type, boost::vertex_index_t>::type vertices = get(boost::vertex_index, *graph_);
    for (Graph::IEIterator iter = iterators.first; iter != iterators.second; ++iter)
        edgeList.push_back(vertices[boost::source(*iter, *graph_)]);

    return edgeList.size();
}

unsigned int ompl::base::PlannerData::getIncomingEdges (unsigned int v, std::map<unsigned int, const PlannerDataEdge*> &edgeMap) const
{
    std::pair<Graph::IEIterator, Graph::IEIterator> iterators = boost::in_edges(boost::vertex(v, *graph_), *graph_);

    edgeMap.clear();
    boost::property_map<Graph::Type, edge_type_t>::type edges = get(edge_type_t(), *graph_);
    boost::property_map<Graph::Type, boost::vertex_index_t>::type vertices = get(boost::vertex_index, *graph_);
    for (Graph::IEIterator iter = iterators.first; iter != iterators.second; ++iter)
        edgeMap[vertices[boost::source(*iter, *graph_)]] = boost::get(edges, *iter);

    return edgeMap.size();
}

bool ompl::base::PlannerData::getEdgeWeight(unsigned int v1, unsigned int v2, Cost* weight) const
{
    Graph::Edge e;
    bool exists;
    boost::tie(e, exists) = boost::edge(boost::vertex(v1, *graph_), boost::vertex(v2, *graph_), *graph_);

    if (exists)
    {
        boost::property_map<Graph::Type, boost::edge_weight_t>::type edges = get(boost::edge_weight, *graph_);
        *weight = edges[e];
        return true;
    }

    return false;
}

bool ompl::base::PlannerData::setEdgeWeight(unsigned int v1, unsigned int v2, Cost weight)
{
    Graph::Edge e;
    bool exists;
    boost::tie(e, exists) = boost::edge(boost::vertex(v1, *graph_), boost::vertex(v2, *graph_), *graph_);

    if (exists)
    {
        boost::property_map<Graph::Type, boost::edge_weight_t>::type edges = get(boost::edge_weight, *graph_);
        edges[e] = weight;
    }

    return exists;
}

bool ompl::base::PlannerData::edgeExists (unsigned int v1, unsigned int v2) const
{
    Graph::Edge e;
    bool exists;

    boost::tie(e, exists) = boost::edge(boost::vertex(v1, *graph_), boost::vertex(v2, *graph_), *graph_);
    return exists;
}

bool ompl::base::PlannerData::vertexExists (const PlannerDataVertex &v) const
{
    return vertexIndex(v) != INVALID_INDEX;
}

unsigned int ompl::base::PlannerData::numVertices () const
{
    return boost::num_vertices(*graph_);
}

unsigned int ompl::base::PlannerData::numEdges () const
{
    return boost::num_edges(*graph_);
}

const ompl::base::PlannerDataVertex& ompl::base::PlannerData::getVertex (unsigned int index) const
{
    if (index >= boost::num_vertices(*graph_))
        return NO_VERTEX;

    boost::property_map<Graph::Type, vertex_type_t>::type vertices = get(vertex_type_t(), *graph_);
    return *(vertices[boost::vertex(index, *graph_)]);
}

ompl::base::PlannerDataVertex& ompl::base::PlannerData::getVertex (unsigned int index)
{
    if (index >= boost::num_vertices(*graph_))
        return const_cast<ompl::base::PlannerDataVertex&>(NO_VERTEX);

    boost::property_map<Graph::Type, vertex_type_t>::type vertices = get(vertex_type_t(), *graph_);
    return *(vertices[boost::vertex(index, *graph_)]);
}

const ompl::base::PlannerDataEdge& ompl::base::PlannerData::getEdge (unsigned int v1, unsigned int v2) const
{
    Graph::Edge e;
    bool exists;
    boost::tie(e, exists) = boost::edge(boost::vertex(v1, *graph_), boost::vertex(v2, *graph_), *graph_);

    if (exists)
    {
        boost::property_map<Graph::Type, edge_type_t>::type edges = get(edge_type_t(), *graph_);
        return *(boost::get(edges, e));
    }

    return NO_EDGE;
}

ompl::base::PlannerDataEdge& ompl::base::PlannerData::getEdge (unsigned int v1, unsigned int v2)
{
    Graph::Edge e;
    bool exists;
    boost::tie(e, exists) = boost::edge(boost::vertex(v1, *graph_), boost::vertex(v2, *graph_), *graph_);

    if (exists)
    {
        boost::property_map<Graph::Type, edge_type_t>::type edges = get(edge_type_t(), *graph_);
        return *(boost::get(edges, e));
    }

    return const_cast<ompl::base::PlannerDataEdge&>(NO_EDGE);
}

void ompl::base::PlannerData::printGraphviz (std::ostream& out) const
{
    boost::write_graphviz(out, *graph_);
}

namespace
{
    // Property map for extracting the edge weight of a graph edge as
    // a double for printGraphML.
    double edgeWeightAsDouble(ompl::base::PlannerData::Graph::Type &g,
                              ompl::base::PlannerData::Graph::Edge e)
    {
        return get(boost::edge_weight_t(), g)[e].value();
    }

    // Property map for extracting states as arrays of doubles
    std::string vertexCoords (ompl::base::PlannerData::Graph::Type &g,
                              ompl::base::ScopedState<>& s,
                              ompl::base::PlannerData::Graph::Vertex v)
    {
        s = *get(vertex_type_t(), g)[v]->getState();
        std::vector<double> coords(s.reals());
        std::ostringstream sstream;
        if (coords.size()>0)
        {
            sstream << coords[0];
            for (std::size_t i = 1; i < coords.size(); ++i)
                sstream << ',' << coords[i];
        }
        return sstream.str();
    }
}

void ompl::base::PlannerData::printGraphML (std::ostream& out) const
{
#if BOOST_VERSION < 105100
    OMPL_WARN("Boost version >=1.51 is needed for ompl::base::PlannerData::printGraphML");
#else
    // For some reason, make_function_property_map can't infer its
    // template arguments corresponding to edgeWeightAsDouble's type
    // signature. So, we have to use this horribly verbose
    // instantiation of the property map.
    //
    // \TODO Can we use make_function_property_map() here and have it
    // infer the property template arguments?
    boost::function_property_map<
        boost::function<double (ompl::base::PlannerData::Graph::Edge)>,
        ompl::base::PlannerData::Graph::Edge,
        double>
        weightmap(boost::bind(&edgeWeightAsDouble, *graph_, _1));
    ompl::base::ScopedState<> s(si_);
    boost::function_property_map<
        boost::function<std::string (ompl::base::PlannerData::Graph::Vertex)>,
        ompl::base::PlannerData::Graph::Vertex,
        std::string >
        coordsmap(boost::bind(&vertexCoords, *graph_, s, _1));

    // Not writing vertex or edge structures.
    boost::dynamic_properties dp;
    dp.property("weight", weightmap);
    dp.property("coords", coordsmap);

    boost::write_graphml(out, *graph_, dp);
#endif
}

unsigned int ompl::base::PlannerData::vertexIndex (const PlannerDataVertex &v) const
{
    std::map<const State*, unsigned int>::const_iterator it = stateIndexMap_.find(v.getState());
    if (it != stateIndexMap_.end())
        return it->second;
    return INVALID_INDEX;
}

unsigned int ompl::base::PlannerData::numStartVertices () const
{
    return startVertexIndices_.size();
}

unsigned int ompl::base::PlannerData::numGoalVertices () const
{
    return goalVertexIndices_.size();
}

unsigned int ompl::base::PlannerData::getStartIndex (unsigned int i) const
{
    if (i >= startVertexIndices_.size())
        return INVALID_INDEX;

    return startVertexIndices_[i];
}

unsigned int ompl::base::PlannerData::getGoalIndex (unsigned int i) const
{
    if (i >= goalVertexIndices_.size())
        return INVALID_INDEX;

    return goalVertexIndices_[i];
}

bool ompl::base::PlannerData::isStartVertex (unsigned int index) const
{
    return std::binary_search(startVertexIndices_.begin(), startVertexIndices_.end(), index);
}

bool ompl::base::PlannerData::isGoalVertex (unsigned int index) const
{
    return std::binary_search(goalVertexIndices_.begin(), goalVertexIndices_.end(), index);
}

const ompl::base::PlannerDataVertex& ompl::base::PlannerData::getStartVertex (unsigned int i) const
{
    if (i >= startVertexIndices_.size())
        return NO_VERTEX;

    return getVertex(startVertexIndices_[i]);
}

ompl::base::PlannerDataVertex& ompl::base::PlannerData::getStartVertex (unsigned int i)
{
    if (i >= startVertexIndices_.size())
        return const_cast<ompl::base::PlannerDataVertex&>(NO_VERTEX);

    return getVertex(startVertexIndices_[i]);
}

const ompl::base::PlannerDataVertex& ompl::base::PlannerData::getGoalVertex (unsigned int i) const
{
    if (i >= goalVertexIndices_.size())
        return NO_VERTEX;

    return getVertex(goalVertexIndices_[i]);
}

ompl::base::PlannerDataVertex& ompl::base::PlannerData::getGoalVertex (unsigned int i)
{
    if (i >= goalVertexIndices_.size())
        return const_cast<ompl::base::PlannerDataVertex&>(NO_VERTEX);

    return getVertex(goalVertexIndices_[i]);
}

unsigned int ompl::base::PlannerData::addVertex (const PlannerDataVertex &st)
{
    // Do not add vertices with null states
    if (st.getState() == NULL)
        return INVALID_INDEX;

    unsigned int index = vertexIndex(st);
    if (index == INVALID_INDEX) // Vertex does not already exist
    {
        // Clone the state to prevent object slicing when retrieving this object
        ompl::base::PlannerDataVertex *clone = st.clone();
        Graph::Vertex v = boost::add_vertex(clone, *graph_);
        boost::property_map<Graph::Type, boost::vertex_index_t>::type vertexIndexMap = get(boost::vertex_index, *graph_);

        // Insert this entry into the stateIndexMap_ for fast lookup
        stateIndexMap_[clone->getState()] = numVertices()-1;
        return vertexIndexMap[v];
    }
    return index;
}

unsigned int ompl::base::PlannerData::addStartVertex (const PlannerDataVertex &v)
{
    unsigned int index = addVertex(v);
    if (index != INVALID_INDEX)
        markStartState(v.getState());

    return index;
}

unsigned int ompl::base::PlannerData::addGoalVertex  (const PlannerDataVertex &v)
{
    unsigned int index = addVertex(v);

    if (index != INVALID_INDEX)
        markGoalState(v.getState());

    return index;
}

bool ompl::base::PlannerData::addEdge(unsigned int v1, unsigned int v2, const PlannerDataEdge &edge, Cost weight)
{
    // If either of the vertices do not exist, don't add an edge
    if (v1 >= numVertices() || v2 >= numVertices())
        return false;

     // If an edge already exists, do not add one
     if (edgeExists (v1, v2))
        return false;

    // Clone the edge to prevent object slicing
    ompl::base::PlannerDataEdge *clone = edge.clone();
    const Graph::edge_property_type properties(clone, weight);

    Graph::Edge e;
    bool added = false;
    tie(e, added) = boost::add_edge(boost::vertex(v1, *graph_), boost::vertex(v2, *graph_), properties, *graph_);

    if (!added)
        delete clone;

    return added;
}

bool ompl::base::PlannerData::addEdge (const PlannerDataVertex & v1, const PlannerDataVertex & v2, const PlannerDataEdge &edge, Cost weight)
{
    unsigned int index1 = addVertex(v1);
    unsigned int index2 = addVertex(v2);

    // If neither vertex was added or already exists, return false
    if (index1 == INVALID_INDEX && index2 == INVALID_INDEX)
        return false;

    // Only add the edge if both vertices exist
    if (index1 != INVALID_INDEX && index2 != INVALID_INDEX)
        return addEdge (index1, index2, edge, weight);

    return true;
}

bool ompl::base::PlannerData::removeVertex (const PlannerDataVertex &st)
{
    unsigned int index = vertexIndex (st);
    if (index != INVALID_INDEX)
        return removeVertex (index);
    return false;
}

bool ompl::base::PlannerData::removeVertex (unsigned int vIndex)
{
    if (vIndex >= boost::num_vertices(*graph_))
        return false;

    // Retrieve a list of all edge structures
    boost::property_map<Graph::Type, edge_type_t>::type edgePropertyMap = get(edge_type_t(), *graph_);

    // Freeing memory associated with outgoing edges of this vertex
    std::pair<Graph::OEIterator, Graph::OEIterator> oiterators = boost::out_edges(boost::vertex(vIndex, *graph_), *graph_);
    for (Graph::OEIterator iter = oiterators.first; iter != oiterators.second; ++iter)
        delete edgePropertyMap[*iter];

    // Freeing memory associated with incoming edges of this vertex
    std::pair<Graph::IEIterator, Graph::IEIterator> initerators = boost::in_edges(boost::vertex(vIndex, *graph_), *graph_);
    for (Graph::IEIterator iter = initerators.first; iter != initerators.second; ++iter)
        delete edgePropertyMap[*iter];

    // Remove this vertex from stateIndexMap_, and update the map
    stateIndexMap_.erase(getVertex(vIndex).getState());
    boost::property_map<Graph::Type, vertex_type_t>::type vertices = get(vertex_type_t(), *graph_);
    for (unsigned int i = vIndex+1; i < boost::num_vertices(*graph_); ++i)
         stateIndexMap_[vertices[boost::vertex(i, *graph_)]->getState()]--;

    // Remove this vertex from the start and/or goal index list, if it exists.  Update the lists.
    std::vector<unsigned int>::iterator it = std::find(startVertexIndices_.begin(), startVertexIndices_.end(), vIndex);
    if (it != startVertexIndices_.end())
        startVertexIndices_.erase(it);
    for (size_t i = 0; i < startVertexIndices_.size(); ++i)
        if (startVertexIndices_[i] > vIndex)
            startVertexIndices_[i]--;

    it = std::find(goalVertexIndices_.begin(), goalVertexIndices_.end(), vIndex);
    if (it != goalVertexIndices_.end())
        goalVertexIndices_.erase(it);
    for (size_t i = 0; i < goalVertexIndices_.size(); ++i)
        if (goalVertexIndices_[i] > vIndex)
            goalVertexIndices_[i]--;

    // If the state attached to this vertex was decoupled, free it here
    State *vtxState = const_cast<State*>(getVertex(vIndex).getState());
    if (decoupledStates_.find(vtxState) != decoupledStates_.end())
    {
        decoupledStates_.erase(vtxState);
        si_->freeState(vtxState);
        vtxState = NULL;
    }

    // Slay the vertex
    boost::clear_vertex(boost::vertex(vIndex, *graph_), *graph_);
    boost::property_map<Graph::Type, vertex_type_t>::type vertexTypeMap = get(vertex_type_t(), *graph_);
    delete vertexTypeMap[boost::vertex(vIndex, *graph_)];
    boost::remove_vertex(boost::vertex(vIndex, *graph_), *graph_);

    return true;
}

bool ompl::base::PlannerData::removeEdge (unsigned int v1, unsigned int v2)
{
    Graph::Edge e;
    bool exists;
    boost::tie(e, exists) = boost::edge(boost::vertex(v1, *graph_), boost::vertex(v2, *graph_), *graph_);

    if (!exists)
        return false;

    // Freeing memory associated with this edge
    boost::property_map<Graph::Type, edge_type_t>::type edges = get(edge_type_t(), *graph_);
    delete edges[e];

    boost::remove_edge(boost::vertex(v1, *graph_), boost::vertex(v2, *graph_), *graph_);
    return true;
}

bool ompl::base::PlannerData::removeEdge (const PlannerDataVertex &v1, const PlannerDataVertex &v2)
{
    unsigned int index1, index2;
    index1 = vertexIndex(v1);
    index2 = vertexIndex(v2);

    if (index1 == INVALID_INDEX || index2 == INVALID_INDEX)
        return false;

    return removeEdge (index1, index2);
}

bool ompl::base::PlannerData::tagState (const base::State *st, int tag)
{
    std::map<const State*, unsigned int>::const_iterator it = stateIndexMap_.find(st);
    if (it != stateIndexMap_.end())
    {
        getVertex(it->second).setTag(tag);
        return true;
    }
    return false;
}

bool ompl::base::PlannerData::markStartState (const base::State *st)
{
    // Find the index in the stateIndexMap_
    std::map<const State*, unsigned int>::const_iterator it = stateIndexMap_.find(st);
    if (it != stateIndexMap_.end())
    {
        if (!isStartVertex(it->second))
        {
            startVertexIndices_.push_back(it->second);
            // Sort the indices for quick lookup
            std::sort(startVertexIndices_.begin(), startVertexIndices_.end());
        }
        return true;
    }
    return false;
}

bool ompl::base::PlannerData::markGoalState (const base::State *st)
{
    // Find the index in the stateIndexMap_
    std::map<const State*, unsigned int>::const_iterator it = stateIndexMap_.find(st);
    if (it != stateIndexMap_.end())
    {
        if (!isGoalVertex(it->second))
        {
            goalVertexIndices_.push_back(it->second);
            // Sort the indices for quick lookup
            std::sort(startVertexIndices_.begin(), startVertexIndices_.end());
        }
        return true;
    }
    return false;
}

void ompl::base::PlannerData::computeEdgeWeights (const OptimizationObjective &opt)
{
    unsigned int nv = numVertices();
    for (unsigned int i = 0; i < nv; ++i)
    {
        std::map<unsigned int, const PlannerDataEdge*> nbrs;
        getEdges(i, nbrs);

        std::map<unsigned int, const PlannerDataEdge*>::const_iterator it;
        for (it = nbrs.begin(); it != nbrs.end(); ++it)
        {
            setEdgeWeight(i, it->first, opt.motionCost(getVertex(i).getState(),
                                                       getVertex(it->first).getState()));
        }
    }
}

void ompl::base::PlannerData::computeEdgeWeights ()
{
    // Create a PathLengthOptimizationObjective to compute the edge
    // weights according to state space distance
    ompl::base::PathLengthOptimizationObjective opt(si_);
    computeEdgeWeights(opt);
}

namespace
{
    // Used in minimum spanning tree
    ompl::base::Cost project2nd (ompl::base::Cost /*unused*/, ompl::base::Cost second)
    {
        return second;
    }
}

void ompl::base::PlannerData::extractMinimumSpanningTree (unsigned int v,
                                                          const base::OptimizationObjective &opt,
                                                          base::PlannerData &mst) const
{
    std::vector<ompl::base::PlannerData::Graph::Vertex> pred(numVertices());

    // This is how boost's minimum spanning tree is actually
    // implemented, except it lacks the generality for specifying our
    // own comparison function or zero/inf values.
    //
    // \TODO Once (https://svn.boost.org/trac/boost/ticket/9368) gets
    // into boost we can use the far more direct
    // boost::prim_minimum_spanning_tree().
    boost::dijkstra_shortest_paths
        (*graph_, v,
         boost::predecessor_map(&pred[0]).
         distance_compare(boost::bind(&base::OptimizationObjective::
                                      isCostBetterThan, &opt, _1, _2)).
         distance_combine(&project2nd).
         distance_inf(opt.infiniteCost()).
         distance_zero(opt.identityCost()));

    // Adding vertices to MST
    for (std::size_t i = 0; i < pred.size(); ++i)
    {
        if (isStartVertex(i))
            mst.addStartVertex(getVertex(i));
        else if (isGoalVertex(i))
            mst.addGoalVertex(getVertex(i));
        else
            mst.addVertex(getVertex(i));
    }

    // Adding edges to MST
    for (std::size_t i = 0; i < pred.size(); ++i)
    {
        if (pred[i] != i)
        {
            Cost c;
            getEdgeWeight(pred[i], i, &c);
            mst.addEdge(pred[i], i, getEdge(pred[i], i), c);
        }
    }
}

void ompl::base::PlannerData::extractReachable(unsigned int v, base::PlannerData &data) const
{
    // If this vertex already exists in data, return
    if (data.vertexExists(getVertex(v)))
        return;

    // Adding the vertex corresponding to v into data
    unsigned int idx;
    if (isStartVertex(v))
        idx = data.addStartVertex(getVertex(v));
    else if (isGoalVertex(v))
        idx = data.addGoalVertex(getVertex(v));
    else
        idx = data.addVertex(getVertex(v));

    assert (idx != INVALID_INDEX);

    std::map<unsigned int, const PlannerDataEdge*> neighbors;
    getEdges(v, neighbors);

    // Depth-first traversal of reachable graph
    std::map<unsigned int, const PlannerDataEdge*>::iterator it;
    for (it = neighbors.begin(); it != neighbors.end(); ++it)
    {
        extractReachable(it->first, data);
        Cost weight;
        getEdgeWeight(v, it->first, &weight);
        data.addEdge(idx, data.vertexIndex(getVertex(it->first)), *(it->second), weight);
    }
}

ompl::base::StateStoragePtr ompl::base::PlannerData::extractStateStorage() const
{
    GraphStateStorage *store = new GraphStateStorage(si_->getStateSpace());
    if (graph_)
    {
        // copy the states
        std::map<unsigned int, unsigned int> indexMap;
        for (std::map<const State*, unsigned int>::const_iterator it = stateIndexMap_.begin() ; it != stateIndexMap_.end() ; ++it)
        {
            indexMap[it->second] = store->size();
            store->addState(it->first);
        }

        // add the edges
        for (std::map<unsigned int, unsigned int>::const_iterator it = indexMap.begin() ; it != indexMap.end() ; ++it)
        {
            std::vector<unsigned int> edgeList;
            getEdges(it->first, edgeList);
            GraphStateStorage::MetadataType &md = store->getMetadata(it->second);
            md.resize(edgeList.size());
            // map node indices to index values in StateStorage
            for (std::size_t k = 0 ; k < edgeList.size() ; ++k)
                md[k] = indexMap[edgeList[k]];
        }
    }
    return StateStoragePtr(store);
}

ompl::base::PlannerData::Graph& ompl::base::PlannerData::toBoostGraph()
{
    ompl::base::PlannerData::Graph *boostgraph = reinterpret_cast<ompl::base::PlannerData::Graph*>(graphRaw_);
    return *boostgraph;
}

const ompl::base::PlannerData::Graph& ompl::base::PlannerData::toBoostGraph() const
{
    const ompl::base::PlannerData::Graph *boostgraph = reinterpret_cast<const ompl::base::PlannerData::Graph*>(graphRaw_);
    return *boostgraph;
}

const ompl::base::SpaceInformationPtr& ompl::base::PlannerData::getSpaceInformation() const
{
    return si_;
}

void ompl::base::PlannerData::freeMemory()
{
    // Freeing decoupled states, if any
    for (std::set<State*>::iterator it = decoupledStates_.begin(); it != decoupledStates_.end(); ++it)
        si_->freeState(*it);

    if (graph_)
    {
        std::pair<Graph::EIterator, Graph::EIterator> eiterators = boost::edges(*graph_);
        boost::property_map<Graph::Type, edge_type_t>::type edges = get(edge_type_t(), *graph_);
        for (Graph::EIterator iter = eiterators.first; iter != eiterators.second; ++iter)
            delete boost::get(edges, *iter);

        std::pair<Graph::VIterator, Graph::VIterator> viterators = boost::vertices(*graph_);
        boost::property_map<Graph::Type, vertex_type_t>::type vertices = get(vertex_type_t(), *graph_);
        for (Graph::VIterator iter = viterators.first; iter != viterators.second; ++iter)
           delete vertices[*iter];

        graph_->clear();
    }
}

bool ompl::base::PlannerData::hasControls() const
{
    return false;
}

max_stars_repo_name: jmainpri/ompl

max_issues_repo_name: jmainpri/ompl

max_forks_repo_name: jmainpri/ompl


text:
// -*- mode: c++ -*-

/*
    Program: PepXMLViewer.cgi
    Description: CGI program to display pepxml files in a web browser
    Date: July 31 2006

    Copyright (C) 2006  Natalie Tasman (original author), ISB Seattle

    This library 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 2.1 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

    Natalie Tasman
    Insitute for Systems Biology
    1441 North 34th St.
    Seattle, WA  98103  USA

    email (remove underscores):
    n_tasman at systems_biology dot org
*/

/** @file PepXField.cxx
    @brief see PepXField.h
*/

#include <boost/regex.hpp>

#include "../Comet/comet-fastadb/calc_pI.cxx"
#include "Parsers/ramp/ramp.h"

#include "PepXUtility.h"

#include "PepXField.h"

using boost::regex;
using boost::regex_search;
using boost::match_results;
using boost::match_flag_type;
using boost::match_default;

// forward declare ramp functions, so we don't have to do the giant include
//std::string rampConstructInputFileName(const std::string &basename);

Field::Field() :
  fieldCode_(Field::unknown),
  isValueNode_(false)
{

}

// given "Gindex", "Sxcorr"
Field::Field(const string & name)  :
  isValueNode_(false)
{
  fieldName_ = name.substr(1);
  fieldCode_ = fieldCodeLookup(name[0]);
  nodeNameLookup();
}

// given ("index", "G")
Field::Field(const string & name, char fieldCode) :
  isValueNode_(false)
{
  fieldName_ = name;
  fieldCode_ = fieldCodeLookup(fieldCode);
  nodeNameLookup();
}

void
// given ("Gindex")
Field::set(const string & name, char fieldCode) {
  isValueNode_ = false;
  fieldName_ = name;
  fieldCode_ = fieldCodeLookup(fieldCode);
  nodeNameLookup();
}

/**

   clarify which pepXML node a field attribute belongs to.

   (up to date with pepXML v18)

 */

void
Field::nodeNameLookup(void) {
  //cout << "lookup: " << fieldName << endl;

  if (fieldCode_ == Field::general) {
    if (fieldName_ == "spectrum" ||
	fieldName_ == "start_scan" ||
	fieldName_ == "end_scan" ||
	fieldName_ == "precursor_neutral_mass" ||
	fieldName_ == "assumed_charge" ||
	fieldName_ == "index" ||
	fieldName_ == "search_specification" // optional
	) {
      nodeName_ = "spectrum_query";
      isValueNode_ = false;
    }
    else {
      /*

	assume it's a search_hit field; skip the specific tests to
	keep things flexible for future changes.

	if (fieldName_ == "hit_rank" ||
	fieldName_ == "peptide" ||
	fieldName_ == "peptide_prev_aa" || // optional
	fieldName_ == "peptide_next_aa" || // optional
	fieldName_ == "protein" ||
	fieldName_ == "num_tot_proteins" ||
	fieldName_ == "num_matched_ions" || // optional
	fieldName_ == "tot_num_ions" || // optional
	fieldName_ == "calc_neutral_pep_mass" ||
	fieldName_ == "massdiff" ||
	fieldName_ == "num_tol_term" || // optional
	fieldName_ == "num_missed_cleavages" || // optional
	fieldName_ == "is_rejected" || // optional
	fieldName_ == "protein_descr" // optional
	) {
      */
      nodeName_ = "search_hit";
      isValueNode_ = false;
    }
  }
  else if (fieldCode_ == Field::searchScore) {
    // one size fits all
    nodeName_ = "search_score";
      isValueNode_ = true;
  }
  else if (fieldCode_ == Field::peptideProphet) {
    if (fieldName_ == "probability") {
      nodeName_ = "peptideprophet_result";
      isValueNode_ = false;
    }
    else {
      nodeName_ = "parameter";
      isValueNode_ = true;
    }
  }
  else if (fieldCode_ == Field::interProphet) {
    if (fieldName_ == "probability") {
      nodeName_ = "interprophet_result";
      isValueNode_ = false;
    }
    else {
      nodeName_ = "parameter";
      isValueNode_ = true;
    }
  }
  else if (fieldCode_ == Field::quantitation) {
    if (fieldName_ == "xpress") {
      nodeName_ = "xpressratio_result";
      isValueNode_ = false;
    }
    else if (fieldName_ == "asapratio" ||
	     fieldName_ == "asapratio_HL") {
      nodeName_ = "asapratio_result";
      isValueNode_ = false;
    }
    else if (fieldName_.substr(0,5) == "libra") {
      nodeName_ = "libra_result";
      isValueNode_ = false;
    }
  }
  // modify the valuenode names
  if (isValueNode_) {
    nodeName_ += "[@" + fieldName_ + "]";
  }

}

// returns enum code
int
Field::fieldCodeLookup(char code) {
  int result = Field::unknown;

  switch (code) {
  case 'G':
    result = Field::general;
    break;
  case 'S':
    result = Field::searchScore;
    break;
  case 'P':
    result = Field::peptideProphet;
    break;
  case 'I':
    result = Field::interProphet;
    break;
  case 'Q':
    result = Field::quantitation;
    break;

  default:
    result = Field::unknown;
    break;
  }

  return result;
}

// returns "Gions", "Sxcorr", etc
string
Field::getFieldParamName(void) const {
  string result="";

  switch (fieldCode_) {
  case Field::general:
    result += "G";
    break;
  case Field::searchScore:
    result += "S";
    break;
  case Field::peptideProphet:
    result += "P";
    break;
  case Field::interProphet:
    result += "I";
    break;
  case Field::quantitation:
    result += "Q";
    break;
  default:
    result += "?";
    break;
  }

  result += fieldName_;
  return result;
}

bool
Field::operator==(const Field& rhs) {
  if (rhs.fieldName_ == fieldName_
      &&
      rhs.fieldCode_ == fieldCode_) {
    return true;
  }
  else {
    return false;
  }
}

string
Field::getAbbreviation(void) {
  string text = "";

  switch (fieldCode_) {

  case Field::quantitation:
    // no abbreviations here yet

    /*
    // xpress
    if (fieldName_ == "xpress") {
    }

    // libra
    else if (fieldName_.substr(0,5) == "libra") {
    }

    // asap
    else if (fieldName_ == "asapratio") {
    }
    */
    break;

  case Field::general: // general

    // straightforward spectrum_query attrs
    if (fieldName_ == "index") {
      text = "#";
    }
    else if (fieldName_ == "assumed_charge") {
      text = "z";
    }
    else if (fieldName_ == "calc_neutral_pep_mass") {
      text = "calc_mass";
    }
    else if (fieldName_ == "precursor_neutral_mass") {
      text = "exp_mass";
    }
    else if (fieldName_ == "start_scan") {
      text = "sscan";
    }
    else if (fieldName_ == "end_scan") {
      text = "escan";
    }

    /*
    // spectrum
    else if (fieldName_ == "spectrum") {
      text = "spec";
    }

    // ppm
    else if (fieldName_ == "ppm") {
    }

    // ions
    else if (fieldName_ == "ions") {
    }

    // peptide
    else if (fieldName_ == "peptide") {
    }

    // protein
    else if (fieldName_ == "protein") {
    }
    */

    else if (fieldName_ == "num_tol_term") {
      text = "ntt";
    }

    else if (fieldName_ == "num_missed_cleavages") {
      text = "nmc";
    }
    else if (fieldName_ == "pI_zscore") {
      text = "pI_zscore";
    }
    else if (fieldName_ == "RT") {
      text = "RT";
    }
    else if (fieldName_ == "RT_score") {
      text = "RT_score";
    }

    break;

  case Field::searchScore: // search scores
    // unchanged for now
    break;

  case Field::peptideProphet:

    // PROBABILITY
    if (fieldName_=="probability") {
      text = "prob";
    }

    /*
    // assume it's a parameter node: fval, etc
    else {
    }
    */

    break;
    // end Field::probability

  case Field::interProphet:

    // PROBABILITY
    if (fieldName_=="probability") {
      text = "iprob";
    }

    /*
    // assume it's a parameter node: fval, etc
    else {
    }
    */

    break;
    // end Field::probability

  default:
    break;
  }

  if (text=="") {
    // if we didn't abbr, just the name.
    text = fieldName_;
  }

  return text;

}

string
Field::getDescription(const string& searchEngine) {

  switch (fieldCode_) {
  case 'G':
    if (fieldName_ == "index")
      return string("index in pepXML file");
    else if (fieldName_ == "ions")
      return string("# matched ions / # calculated ions");
    break;
  case 'S':
    if (searchEngine == "SEQUEST") {
      if (fieldName_ == "xcorr") {
	return string("SEQUEST: cross-correlation");
      }
      else if (fieldName_ == "deltacn") {
	return string("SEQUEST: separation of xcorr of top spectrum match from next-best match.");
      }
    }
    break;
  case 'P':
    if (fieldName_ == "probability")
      return string("Peptide Prophet: probability");
    break;
  case 'I':
    if (fieldName_ == "probability")
      return string("iProphet: probability");
    break;
  default:
    break;
  }

  // by default just return the field name
  return fieldName_;

}

string
Field::getText(int mode,
	       const XMLNodePtr& node,
	       PMap& infoMap,
	       const string &highlightedPeptideText,
	       const string &highlightedProteinText,
	       const string &highlightedSpectrumText,
	       const bool includeHighlightedPepTextMods,
	       const bool libraAbsoluteValues) {
  string text = "";
  char t[255]; // temp buffer for formatting
  string name;
  XMLNodePtr np;
  string pname="";

  // used often
  string searchEngine = infoMap["searchEngine"];

  switch (fieldCode_) {

  case Field::quantitation:
    // xpress
    if (fieldName_ == "xpress") {

      // use decimal_ratio (low:high)

      if (mode == Field::plainText) {
	text=
	  node
	  ->findChild("search_result")
	  ->findChild("search_hit", "hit_rank", "1")
	  ->findChild("analysis_result","analysis","xpress")
	  ->findChild("xpressratio_result")
	  ->getAttrValue("decimal_ratio");
      }
      else if (mode == Field::html) {

	XMLNodePtr xpressratio_result =
	  node
	  ->findChild("search_result")
	  ->findChild("search_hit", "hit_rank", "1")
	  ->findChild("analysis_result","analysis","xpress")
	  ->findChild("xpressratio_result");

	if ( xpressratio_result->getAttrValue("decimal_ratio")
	     ==
	     "" ) {
	  // n/a
	  text = "unavailable";
	}
	else {

	  text = "getAttrValue("light_firstscan");
	  string light_last_scan = xpressratio_result->getAttrValue("light_lastscan");
	  string heavy_first_scan = xpressratio_result->getAttrValue("heavy_firstscan");
	  string heavy_last_scan = xpressratio_result->getAttrValue("heavy_lastscan");
	  string xpress_charge = node->getAttrValue("assumed_charge");
	  string LightMass = xpressratio_result->getAttrValue("light_mass");
	  string HeavyMass = xpressratio_result->getAttrValue("heavy_mass");
	  string MassTol = xpressratio_result->getAttrValue("mass_tol");
	  string xpress_index = node->getAttrValue("index");
	  string xpress_spec = node->getAttrValue("spectrum");

	  string xmlfile = infoMap["xmlFileName"];

	  string basename = infoMap["runSummaryBaseName"]; // per MRS
	  string xpress_display = infoMap["xpress_light"]; // per MRS

	  text += "LightFirstScan=" + light_first_scan + "&";
	  text += "LightLastScan=" + light_last_scan + "&";
	  text += "HeavyFirstScan=" + heavy_first_scan + "&";
	  text += "HeavyLastScan=" + heavy_last_scan + "&";
	  text += "XMLFile=" + rampConstructInputFileName(basename) + "&";
	  text += "ChargeState=" + xpress_charge + "&";
	  text += "LightMass=" + LightMass + "&";
	  text += "HeavyMass=" + HeavyMass + "&";
	  text += "MassTol=" + MassTol + "&";
	  text += "index=" + xpress_index + "&";
	  text += "xmlfile=" + xmlfile + "&";
	  text += "OutFile=" + xpress_spec + "&";
	  text += "bXpressLight1=" + xpress_display;

	  text += " \">";

	  text +=
	    node
	    ->findChild("search_result")
	    ->findChild("search_hit", "hit_rank", "1")
	    ->findChild("analysis_result","analysis","xpress")
	    ->findChild("xpressratio_result")
	    ->getAttrValue("decimal_ratio");

	  text += "";
	}
	// end xpress html
      }
      else if (mode == Field::value) {
	text = node
	  ->findChild("search_result")
	  ->findChild("search_hit", "hit_rank", "1")
	  ->findChild("analysis_result","analysis","xpress")
	  ->findChild("xpressratio_result")
	  ->getAttrValue("decimal_ratio");
      }
      // end field "xpress"
    }

    if (fieldName_ == "light_area") {
      text = node
	->findChild("search_result")
	->findChild("search_hit", "hit_rank", "1")
	->findChild("analysis_result","analysis","xpress")
	->findChild("xpressratio_result")
	->getAttrValue("light_area");
    }

    if (fieldName_ == "heavy_area") {
      text = node
	->findChild("search_result")
	->findChild("search_hit", "hit_rank", "1")
	->findChild("analysis_result","analysis","xpress")
	->findChild("xpressratio_result")
	->getAttrValue("heavy_area");
    }

    // libra
    if (fieldName_.substr(0,5) == "libra") {
      if (mode == Field::plainText ||
	  mode == Field::html ||
	  mode == Field::value) {
	XMLNodePtr lNode =
	  node
	  ->findChild("search_result")
	  ->findChild("search_hit", "hit_rank", "1")
	  ->findChild("analysis_result","analysis","libra")
	  ->findChild("libra_result")
	  ->findDescendent("intensity", "channel", fieldName_.substr(5));

	if (libraAbsoluteValues) {
	  text = lNode->getAttrValue("absolute");
	}
	else {
	  text = lNode->getAttrValue("normalized");
	}
      }
    }

    // asap
    else if (fieldName_ == "asapratio" || // L:H
	     fieldName_ == "asapratio_HL") {

      string asapMeanAttr;
      string asapErrorAttr;
      if (fieldName_ == "asapratio_HL") {
	asapMeanAttr = "heavy2light_mean";
	asapErrorAttr = "heavy2light_error";
      }
      else { // L:H, default
	asapMeanAttr = "mean";
	asapErrorAttr = "error";
      }

      if (mode == Field::value) {
      text=
	node
	->findChild("search_result")
	->findChild("search_hit", "hit_rank", "1")
	->findChild("analysis_result","analysis","asapratio")
	->findChild("asapratio_result")
	->getAttrValue(asapMeanAttr);
      }
      else if (mode == Field::html) {

	XMLNodePtr asapratio_result =
	  node
	  ->findChild("search_result")
	  ->findChild("search_hit", "hit_rank", "1")
	  ->findChild("analysis_result","analysis","asapratio")
	  ->findChild("asapratio_result");

	if (asapratio_result->getAttrValue(asapMeanAttr)
	    ==
	    "") {
	  // not found
	  text = "N/A";
	}
	else {
	  text = "getAttrValue("index");
	  string xpress_spec = node->getAttrValue("spectrum");

	  text += "Xmlfile="  + infoMap["xmlFileName"] + "&";
	  text += "Basename=" + infoMap["runSummaryBaseName"] + "&";
	  text += "Indx=" + xpress_index + "&";
	  text += "Timestamp=" + infoMap["asap_time"] + "&";
	  text += "Spectrum=" + xpress_spec + "&";

	  // NOTE: there was originally a choice to display light:heavy or heavy:light;
	  // with 0 for light:heavy and 1 for the opposite.  This could be added back in as a choice, if desired.
	  text += "ratioType=0";

	  //DDS ASAP quantitation opts
	  if (infoMap["asapratio[@quantHighBG]"] == "True") {
	    text += "&quantHighBG=1";
	  }
	  if (infoMap["asapratio[@zeroBG]"] == "True") {
	    text += "&zeroBG=1";
	  }
	  if (atof(infoMap["asapratio[@mzBound]"].c_str()) > 0) {
	    text += "&mzBound="+infoMap["asapratio[@mzBound]"];
	  }
	  //end DDS ASAP quantitation opts

	  text += " \">";

	  text +=
	    node
	    ->findChild("search_result")
	    ->findChild("search_hit", "hit_rank", "1")
	    ->findChild("analysis_result","analysis","asapratio")
	    ->findChild("asapratio_result")
	    ->getAttrValue(asapMeanAttr);
	  text += " ± ";
	  text += node
	    ->findChild("search_result")
	    ->findChild("search_hit", "hit_rank", "1")
	    ->findChild("analysis_result","analysis","asapratio")
	    ->findChild("asapratio_result")
	    ->getAttrValue(asapErrorAttr);

	  text += "";

	}
      }
      else if (mode == Field::plainText) {
	// actually returns as TWO tab-delim columns: mean and error
	text=
	  node
	  ->findChild("search_result")
	  ->findChild("search_hit", "hit_rank", "1")
	  ->findChild("analysis_result","analysis","asapratio")
	  ->findChild("asapratio_result")
	  ->getAttrValue(asapMeanAttr);
	if (text == "") {
	  text = "\t";
	  break;
	}
	text += "\t";
	text += node
	  ->findChild("search_result")
	  ->findChild("search_hit", "hit_rank", "1")
	  ->findChild("analysis_result","analysis","asapratio")
	  ->findChild("asapratio_result")
	  ->getAttrValue(asapErrorAttr);
      }
    }
    break;

  case Field::general: // general

    // straightforward spectrum_query attrs
    if (fieldName_ == "index" ||
	fieldName_ == "assumed_charge" ||
	fieldName_ == "precursor_neutral_mass" ||
	fieldName_ == "start_scan" ||
	fieldName_ == "end_scan" ||
	fieldName_ == "search_specification" ||
	fieldName_ == "retention_time_sec"
	) {
      if (mode == Field::value ||
	  mode == Field::plainText ||
	  mode == Field::html) {
	text = node->getAttrValue(fieldName_);
      }
    }

    // spectrum
    else if (fieldName_ == "spectrum") {
      if (mode == Field::value ||
	  mode == Field::plainText ) {
	text = node->getAttrValue(fieldName_);
      }
      else if (mode == Field::html) {

	string spectrum=node->getAttrValue("spectrum");
	string displayedSpectrumText = spectrum;

	// highlight the spectrum text, if requested
	/* regex highlighting */
	if (highlightedSpectrumText.size() > 0 ) {
	  string::const_iterator textStart, textEnd;
	  textStart = spectrum.begin();
	  textEnd = spectrum.end();

	  match_results<string::const_iterator> what;
	  match_flag_type flags = match_default;
	  //int startPos = 0;

	  regex re2(highlightedSpectrumText);
	  if (regex_search(textStart, textEnd, what, re2, flags)) {
	    displayedSpectrumText =
	      string("")
	      + spectrum
	      + string("");

	  }
	}

	if (searchEngine == "MASCOT") {
	  text = "" + displayedSpectrumText + "";
	}
	else if (searchEngine == "SPECTRAST") {
	  text = "findChild("search_result")
	    ->findChild("search_hit", "hit_rank", "1")
	    ->findDescendent("search_score[@lib_file_offset]")
	    ->getAttrValue("value");

	  string queryfile;
	  queryfile = infoMap["xmlFileName"].substr
	    (0,
	     findRightmostPathSeperator(infoMap["xmlFileName"])+1);

	  queryfile += spectrum.substr(0, spectrum.find('.'));
	  text += "&QueryFile=" + rampConstructInputFileName(queryfile);
	  text += "&QueryScanNum=" +
	    node->getAttrValue("start_scan");
	  text += "\">" + displayedSpectrumText + "";
	}
	else if (searchEngine == "SEQUEST") {
	  text = "" + displayedSpectrumText + "";
	}
	// else, unspecified search engine.
	// this catches comet / x!comet, for which the link doesn't apply
	else {
	  text = displayedSpectrumText;
	}

	// spectrast over peptide atlas
	text += "<a target=\"SpectrastPA\" href=\"";
	text += infoMap["html_dir"] + "post_to_spectrast.html?";
	// query string

	//name of fasta file used (just name, not full path)
	text += "fasta=";
	string dbase=infoMap["searchDatabase"];
	// remove everything except the actual filename
	string::size_type slashPos = findRightmostPathSeperator(dbase);
	if (slashPos != string::npos) {
	  // we can just get the filename (after the last slash)
	  dbase = dbase.substr(slashPos+1);
	}
	text += dbase;

	// path to where cgi's live. (i.e. where the PepXMLViewer is)
	text += "&tppcgi=" + infoMap["cgiBase"];

	// full path to dta file
	text += "&Dta=";
	//string spectrum=node->getAttrValue("spectrum");
	text += infoMap["runSummaryBaseName"] + "/" + spectrum + ".dta";

	// (optional)COMET=1 (if Comet results; logic same as for plot-msms.cgi)
	if (searchEngine == "COMET" ||
	    searchEngine == "X!COMET" ||
	    searchEngine == "X! COMET" ||
	    searchEngine == "X! TANDEM (COMET)") {
	  text += "&COMET=1";
	}

	text += "\">";

	text += "";

      } // end spectrum, html
    } // end spectrum

    // ppm
    // TODO: check precision?

    else if (fieldName_ == "ppm") {
      if (mode == Field::value ||
	  mode == Field::plainText ||
	  mode == Field::html) {

	double calc, measured, Z;

	if (!toDouble(node->getAttrValue("precursor_neutral_mass"), measured) ||
	    !toDouble(node
		      ->findChild("search_result")
		      ->findChild("search_hit", "hit_rank", "1")
		      ->getAttrValue("calc_neutral_pep_mass"), calc) ||
	    !toDouble(node
		      ->getAttrValue("assumed_charge"), Z) ) {
	  // bad value(s)
	  text = "";
	}
	else {
	  //sprintf(t, "%.4f", 1000000.0*(calc-measured)/measured);
	  static double protonMass = 1.00727646688;
	  sprintf(t, "%.4f", 1000000.0*( measured - calc )/(measured+Z*protonMass));
	  text = t;
	}
      }
    }

    // pI calculation
    else if (fieldName_ == "pI") {
      if (mode == Field::value ||
	  mode == Field::plainText ||
	  mode == Field::html) {
	// call Comet's calc_pI code
	// note-- doesn't take modifications into account
	string pep = node->
	  findChild("search_result")->
	  findChild("search_hit", "hit_rank", "1")->getAttrValue("peptide");
	int peplen = (int)pep.length();
	char* pepString = new char[peplen + 1];
	strcpy(pepString, pep.c_str());
	double pI = COMPUTE_PI(pepString, peplen, 0);
	delete pepString;
	sprintf(t, "%.2f", pI);
	text=t;
      }
    }

    // M/Z ratio
    //  (calc. neutral mass + Z*(H+mass)) / Z
    else if (fieldName_ == "MZratio") {
      if (mode == Field::value ||
	  mode == Field::plainText ||
	  mode == Field::html) {

	double calc; // calculated mass
	double Z; // assumed charge
	// from
	// http://physics.nist.gov/cgi-bin/cuu/Value?mpu|search_for=proton+mass:
	static double protonMass = 1.00727646688;

	if (!toDouble(node
		      ->findChild("search_result")
		      ->findChild("search_hit", "hit_rank", "1")
		      ->getAttrValue("calc_neutral_pep_mass"), calc) ||
	    !toDouble(node
		      ->getAttrValue("assumed_charge"), Z)) {
	  text = "";
	}
	else {
	  sprintf(t, "%.4f", (calc + Z*protonMass) / Z );
	  text = t;
	}
      }
    }

    // massdiff: previously, used value from pepxml file, which was only printed to 1 decimal place.
    //  node[@precursor_neutral_mass] - (node->search_result->search_hit[@calc. neutral mass]
    else if (fieldName_ == "massdiff") {
      if (mode == Field::value ||
	  mode == Field::plainText ||
	  mode == Field::html) {

	double calcmass;
	double precursorneutralmass;

	if (!toDouble(node
		      ->findChild("search_result")
		      ->findChild("search_hit", "hit_rank", "1")
		      ->getAttrValue("calc_neutral_pep_mass"), calcmass) ||
	    !toDouble(node
		      ->getAttrValue("precursor_neutral_mass"), precursorneutralmass)) {
	  text = "";
	}
	else {
	  sprintf(t, "%.4f", (precursorneutralmass - calcmass));
	  text = t;
	}
      }
    }

    // ions
    else if (fieldName_ == "ions") {
      if (mode == Field::value ||
	  mode == Field::plainText) {
	text = node->
	  findChild("search_result")->
	  findChild("search_hit", "hit_rank", "1")->getAttrValue("num_matched_ions");
	text += "/";
	text += node->
	  findChild("search_result")->
	  findChild("search_hit", "hit_rank", "1")->getAttrValue("tot_num_ions");
      }
      else if ( mode == Field::html) {

	string spectrum=node->getAttrValue("spectrum");
	text = "=+2 should include charges <2
	  // x,y,z >=+2 should include charges <=2

	  bool a=false, b=false, c=false, d=false, v=false, w=false, x=false, y=false, z=false;
	  // the strings are "1" or "0"-- there's probably a more
	  // elegant way, but...

	  // (ignoring possible bad casts; will be set to false)
	  toBool(atoi(infoMap["a-ions"].c_str()), a);
	  toBool(atoi(infoMap["b-ions"].c_str()), b);
	  toBool(atoi(infoMap["c-ions"].c_str()), c);
	  toBool(atoi(infoMap["d-ions"].c_str()), d);
	  toBool(atoi(infoMap["v-ions"].c_str()), v);
	  toBool(atoi(infoMap["w-ions"].c_str()), w);
	  toBool(atoi(infoMap["x-ions"].c_str()), x);
	  toBool(atoi(infoMap["y-ions"].c_str()), y);
	  toBool(atoi(infoMap["z-ions"].c_str()), z);

	  //text += "&origSequest=" + infoMap["sequestIonString"];
	  //text += "&sequestions=" + infoMap["a-ions"] + infoMap["b-ions"] + infoMap["c-ions"] + infoMap["d-ions"] + infoMap["v-ions"] + infoMap["w-ions"] + infoMap["x-ions"] + infoMap["y-ions"] + infoMap["z-ions"];

	  int charge;
	  if (!toInt(node
		     ->getAttrValue("assumed_charge"), charge)) {
	    charge=-1; // TODO: something better?
	  }

	  if (a || b || c || d) {
	    if (charge >= 1) { // show +1 for all changes
	      if (a) {
		text += "&ShowA=1";
	      }
	      if (b) {
		text += "&ShowB=1";
	      }
	      if (c) {
		text += "&ShowC=1";
	      }
	      // if (d) {
	      // 	text += "&ShowD=1";
	      // }
	    }
	    if (charge >= 3) { // show +2 for +3 or higher
	      if (a) {
		text += "&ShowA2=1";
	      }
	      if (b) {
		text += "&ShowB2=1";
	      }
	      if (c) {
		text += "&ShowC2=1";
	      }
	      // if (d) {
	      // 	text += "&ShowD2=1";
	      // }
	    }
	    if (charge >= 4) { // show +3 for +4 or higher
	      if (a) {
		text += "&ShowA3=1";
	      }
	      if (b) {
		text += "&ShowB3=1";
	      }
	      if (c) {
		text += "&ShowC3=1";
	      }
	      // if (d) {
	      // 	text += "&ShowD3=1";
	      // }
	    }
	  }
	  if (v || w || x || y || z) {
	    if (charge >= 1) {
	      // if (v) {
	      // 	text += "&ShowV=1";
	      // }
	      // if (w) {
	      // 	text += "&ShowW=1";
	      // }
	      if (x) {
		text += "&ShowX=1";
	      }
	      if (y) {
		text += "&ShowY=1";
	      }
	      if (z) {
		text += "&ShowZ=1";
	      }
	    }
	    if (charge >= 2) {
	      // if (v) {
	      // 	text += "&ShowV2=1";
	      // }
	      // if (w) {
	      // 	text += "&ShowW2=1";
	      // }
	      if (x) {
		text += "&ShowX2=1";
	      }
	      if (y) {
		text += "&ShowY2=1";
	      }
	      if (z) {
		text += "&ShowZ2=1";
	      }
	    }
	    if (charge >= 3) {
	      // if (v) {
	      // 	text += "&ShowV3=1";
	      // }
	      // if (w) {
	      // 	text += "&ShowW3=1";
	      // }
	      if (x) {
		text += "&ShowX3=1";
	      }
	      if (y) {
		text += "&ShowY3=1";
	      }
	      if (z) {
		text += "&ShowZ3=1";
	      }
	    }
	  }
	} // end ion series

	// add N/C term mods if they exist
	{

	  string nTermMod = node
	    ->findChild("search_result")
	    ->findChild("search_hit", "hit_rank", "1")
	    ->findChild("modification_info")
	    ->getAttrValue("mod_nterm_mass");
	  if (nTermMod != "") {
	    text += "&ModN=" + nTermMod;
	  }

	  string cTermMod = node
	    ->findChild("search_result")
	    ->findChild("search_hit", "hit_rank", "1")
	    ->findChild("modification_info")
	    ->getAttrValue("mod_cterm_mass");
	  if (cTermMod != "") {
	    text += "&ModC=" + cTermMod;
	  }

	}

	XMLNodeVec *v = &
	  (node
	   ->findChild("search_result")
	   ->findChild("search_hit", "hit_rank", "1")
	   ->findChild("modification_info")
	   ->children_);
	for (unsigned int vc=0;vc<v->size();vc++) {
	  text += "&Mod";
	  text += (*v)[vc]->getAttrValue("position");
	  text += "=";
	  text += (*v)[vc]->getAttrValue("mass");
	}

	text += "&Pep=";
	text += node->
	  findChild("search_result")->
	  findChild("search_hit", "hit_rank", "1")->getAttrValue("peptide");

	text += "&Dta=";
	text += infoMap["runSummaryBaseName"] + "/" + spectrum + ".dta";

	// output global aa mods for this MRS
	AAModInfoVec* modvec = infoMap.getModVec();
	for (unsigned int mn=0; mn<(*modvec).size(); mn++) {
	  text += "&Global_Mod="; // ex, CV9.000 is a delta 9 variable mod on cys
	  text += ((*modvec)[mn])->aa_;

	  if ( ((*modvec)[mn])->modType_ == AAModInfo::static_mod) {
	    text += "S";
	  }
	  else {
	    // assume variable
	    text += "V";
	  }

	  string modValue;
	  toString( ((*modvec)[mn])->modValue_ , modValue);
	  text += modValue;

	} // end mod loop

	if (searchEngine == "COMET" ||
	    searchEngine == "X!COMET" ||
	    searchEngine == "X! COMET" ||
	    searchEngine == "X! TANDEM (COMET)") {
	  text += "&COMET=1";
	}

	text += "\">";

	text += node->
	  findChild("search_result")->
	  findChild("search_hit", "hit_rank", "1")->getAttrValue("num_matched_ions");
	text += "/";
	text += node->
	  findChild("search_result")->
	  findChild("search_hit", "hit_rank", "1")->getAttrValue("tot_num_ions");

	text += "";
      }
    }

    // peptideModText
    else if (fieldName_ == "peptideModText"){
      string textPepString;

      XMLNodePtr searchHitNode = (node->
				  findChild("search_result")->
				  findChild("search_hit", "hit_rank", "1"));

      Field::searchPeptideText(searchHitNode,
			       string(""), // no search text
			       true, // yes, include modification text
			       false, // no, not just searching-- returning text
			       textPepString,
			       false, // no, don't return html
			       false // !no brackets on subscripts!
			       );
      text = textPepString;
    }

    // peptide
    else if (fieldName_ == "peptide") {
      if (mode == Field::value) {
	text = node->
	  findChild("search_result")->
	  findChild("search_hit", "hit_rank", "1")->getAttrValue("peptide");
      }
      else if (mode == Field::plainText) {
	{
	  text = node->
	    findChild("search_result")->
	    findChild("search_hit", "hit_rank", "1")->getAttrValue("peptide_prev_aa");
	  text += ".";

	  string textPepString;

	  XMLNodePtr searchHitNode = (node->
				      findChild("search_result")->
				      findChild("search_hit", "hit_rank", "1"));

	  Field::searchPeptideText(searchHitNode,
				   string(""), // no search text
				   true, // yes, include modification text
				   false, // no, not just searching
				   textPepString,
				   false // no, don't return html
				   );

	  // htmlPepString now contains the appropriately html-ified text

	  text += textPepString;

	  text += ".";
	  text += node->
	    findChild("search_result")->
	    findChild("search_hit", "hit_rank", "1")->getAttrValue("peptide_next_aa");
	}
      } // end plain-text peptide

      else if (mode == Field::html) {

	string htmlPepString;

	XMLNodePtr searchHitNode = node->
	  findChild("search_result")->
	  findChild("search_hit", "hit_rank", "1");

	string htext = highlightedPeptideText;
	Field::searchPeptideText(searchHitNode,
				 htext,
				 includeHighlightedPepTextMods,
				 false, // no, not just searching
				 htmlPepString,
				 true); // yes, return html!

	// htmlPepString now contains the appropriately html-ified text

	// assemble the returned value, "text"

	// prev AA
	text = node->
	  findChild("search_result")->
	  findChild("search_hit", "hit_rank", "1")->getAttrValue("peptide_prev_aa");
	text += ".";

	// peptide link
	text += "<a target=\"Win1\" href=\"";
	text += "http://www.ncbi.nlm.nih.gov/blast/Blast.cgi?CMD=Web&LAYOUT=TwoWindows&AUTO_FORMAT=Semiauto&ALIGNMENTS=50&ALIGNMENT_VIEW=Pairwise&CDD_SEARCH=on&CLIENT=web&COMPOSITION_BASED_STATISTICS=on&DATABASE=nr&DESCRIPTIONS=100&ENTREZ_QUERY=(none)&EXPECT=1000&FILTER=L&FORMAT_OBJECT=Alignment&FORMAT_TYPE=HTML&I_THRESH=0.005&MATRIX_NAME=BLOSUM62&NCBI_GI=on&PAGE=Proteins&PROGRAM=blastp&SERVICE=plain&SET_DEFAULTS.x=41&SET_DEFAULTS.y=5&SHOW_OVERVIEW=on&END_OF_HTTPGET=Yes&SHOW_LINKOUT=yes&QUERY=";

	text += node->
	  findChild("search_result")->
	  findChild("search_hit", "hit_rank", "1")->getAttrValue("peptide");

	text += "\">";

	// peptide html string
	text += htmlPepString;

	text += "";

	// next AA
	text += ".";
	text += node->
	  findChild("search_result")->
	  findChild("search_hit", "hit_rank", "1")->getAttrValue("peptide_next_aa");

	// peptide atlas callout
	text += "
	  findChild("search_result")->
	  findChild("search_hit", "hit_rank", "1")->getAttrValue("peptide");
	text += "%25;action=GO\">";

      }
    }

    // protein
    else if (fieldName_ == "protein") {
      if (mode == Field::value) {
	text= node->
	  findChild("search_result")->
	  findChild("search_hit", "hit_rank", "1")->getAttrValue("protein");
      }
      else if (mode == Field::plainText) {
	// primary protein
	text= node->
	  findChild("search_result")->
	  findChild("search_hit", "hit_rank", "1")->getAttrValue("protein");

	// alternates, if any
	XMLNodeVecPtr nv = node->
	  findChild("search_result")->
	  findChild("search_hit", "hit_rank", "1")->
	  findChildren("alternative_protein");
	int numAlt = (int)nv->size();
	if (numAlt > 0) {
	  for (int ii = 0; ii<numAlt; ii++) {
	    text += ",";
	    text += ((*nv)[ii])->getAttrValue("protein");
	  }
	}
      }

      else if (mode == Field::html) {
	text = "
	  findChild("search_result")->
	  findChild("search_hit", "hit_rank", "1")->getAttrValue("protein");
	text += "&Db=" + infoMap["searchDatabase"];
	text += "&Pep=" +  node->
	  findChild("search_result")->
	  findChild("search_hit", "hit_rank", "1")->getAttrValue("peptide");
	text += "&MassType=" + infoMap["precursorMassType"];
	text += "&sample_enzyme=" + infoMap["sampleEnzyme"];
	text += "&min_ntt=" + infoMap["searchConstraintMinNtt"];
	text += "\"";

	name = node->
	  findChild("search_result")->
	  findChild("search_hit", "hit_rank", "1")->getAttrValue("protein_descr");

	if (name != "") {
	  text += " title=\"";
	  text += name;
	  text += "\" ";
	}

	text += " >";

	/* regex highlighting */
	bool highlighting = false;
	string proteinNameText = node->
	  findChild("search_result")->
	  findChild("search_hit", "hit_rank", "1")->getAttrValue("protein");
	if (highlightedProteinText.size() > 0 ) {
	  string::const_iterator protstart, protend;
	  protstart = proteinNameText.begin();
	  protend = proteinNameText.end();

	  match_results<string::const_iterator> what;
	  match_flag_type flags = match_default;
	  //int startPos = 0;

	  regex re2(highlightedProteinText);
	  if (regex_search(protstart, protend, what, re2, flags)) {
	    highlighting = true;
	  }
	}

	if (highlighting) {
	  text += "";
	}

	text += //string(y) + string(": ") +
	  node->
	  findChild("search_result")->
	  findChild("search_hit", "hit_rank", "1")->getAttrValue("protein");

	if (highlighting) {
	  text += "";
	}

	text += "";

	XMLNodeVecPtr nv = node->
	  findChild("search_result")->
	  findChild("search_hit", "hit_rank", "1")->
	  findChildren("alternative_protein");
	int numAlt = (int)nv->size();
	if (numAlt > 0) {
	  if (infoMap["expandProteinList"] != "") {
	    // print alternative proteins, if any
	    for (int ii = 0; ii<numAlt; ii++) {
	      if (ii == 0) {
		text += "
";
	      }
	      //cout << ii << "
" << endl;
	      string altP=((*nv)[ii])->getAttrValue("protein");
	      text += "
		findChild("search_result")->
		findChild("search_hit", "hit_rank", "1")->getAttrValue("peptide");
	      text += "&MassType=" + infoMap["precursorMassType"];
	      text += "\" ";

	      name = ((*nv)[ii])->getAttrValue("protein_descr");
	      if (name != "") {
		text += " title=\"";
		text += name;
		text += "\" ";
	      }

	      text += " >";
	      text += altP;
	      text += "";
	      text += "
";
	    }
	  }
	  else {
	    //cout << "numalt: " << numAlt << "
" << endl;
	    text += "
	      findChild("search_result")->
	      findChild("search_hit", "hit_rank", "1")->getAttrValue("peptide");
	    text += "&MassType=" + infoMap["precursorMassType"];
	    text += "&sample_enzyme=" + infoMap["sampleEnzyme"];
	    text += "&min_ntt=" + infoMap["searchConstraintMinNtt"];
	    text += "\"";

	    text += " title=\"";
	    for (int ii = 0; ii<numAlt; ii++) {
	      if (ii != 0) {
		text += "<br />";
	      }
	      name = node->
		findChild("search_result")->
		findChild("search_hit", "hit_rank", "1")->getAttrValue("protein_descr");
	      string altPDesc=((*nv)[ii])->getAttrValue("protein");
	      text += altPDesc;
	    }
	    text += "\" ";

	    text += " >";

	    text += " +";
	    sprintf(t,"%d",numAlt);
	    text += t;

	    text += "";

	  }
	}
      }
    }

    // if here without finding a name match, unmatched general field;
    // assume anything else is a search_hit attr
    else {
      if (mode == Field::value ||
	  mode == Field::plainText ||
	  mode == Field::html) {
	text = node->
	  findChild("search_result")->
	  findChild("search_hit", "hit_rank", "1")->
	  getAttrValue(fieldName_);
      }
    }

    break;

  case Field::searchScore: // search scores
    if (mode == Field::value ||
	mode == Field::plainText ||
	mode == Field::html) {
      np=node->findChild("search_result")->findChild("search_hit", "hit_rank", "1");
      np=np->findDescendent(nodeName_);
      //np->print();
      //cout << "###" << endl;

      if (!np->isEmpty_) {
	text = np->getAttrValue("value");
	//cout << nodeName_ << ": " << text << endl;

	if (mode != value ) {
	  // mascot star
	  if (infoMap["searchEngine"] == "MASCOT"
	      &&
	      fieldName_ == "ionscore") {
	    name = "search_score";
	    name += "[@star]";
	    np=np->parent_.lock();
	    np=np->findDescendent(name);
	    if (np->getAttrValue("value") == "1") {
	      text += "*";
	    }
	  }
	}

      }
      else {
	// try alternates first
	bool foundAlternate = false;
	if (infoMap["searchEngine"] == "SPECTRAST"
	    &&
	    fieldName_ == "mz_diff") {
	  np=node->findChild("search_result")->findChild("search_hit", "hit_rank", "1");
	  name = "search_score";
	  name += "[@precursor_mz_diff]";
	  np=np->findDescendent(name);
	  if (!np->isEmpty_) {
	    foundAlternate = true;
	    text = np->getAttrValue("value");
	  }
	}
	else if (infoMap["searchEngine"] == "SPECTRAST"
		 &&
		 fieldName_ == "delta_dot") {
	  np=node->findChild("search_result")->findChild("search_hit", "hit_rank", "1");
	  name = "search_score";
	  name += "[@delta]";
	  np=np->findDescendent(name);
	  if (!np->isEmpty_) {
	    foundAlternate = true;
	    text = np->getAttrValue("value");
	  }
	}
      }
    }

    break;

  case Field::peptideProphet:

    // PROBABILITY
    if (fieldName_=="probability") {
      if (mode == Field::value ||
	  mode == Field::plainText
	  // disable link if interProphet, for now
	  ||
	  ((mode == Field::html) && (infoMap["interprophet"] == "true"))
	  ) {
	text =
	  node
	  ->findChild("search_result")
	  ->findChild("search_hit", "hit_rank", "1")
	  ->findChild("analysis_result","analysis","peptideprophet")
	  ->findChild("peptideprophet_result")
	  ->getAttrValue("probability");
      }
      else if (mode == Field::html) {
	XMLNodePtr pnode = node
	  ->findChild("search_result")
	  ->findChild("search_hit", "hit_rank", "1")
	  ->findChild("analysis_result","analysis","peptideprophet")
	  ->findChild("peptideprophet_result");

	string p=
	  pnode
	  ->getAttrValue("probability");

	text = "getAttrValue("spectrum");
	text += "&Scores=";
	XMLNodeVec *v = &
	  (node
	   ->findChild("search_result")
	   ->findChild("search_hit", "hit_rank", "1")
	   ->findChild("analysis_result","analysis","peptideprophet")
	   ->findChild("peptideprophet_result")
	   ->findChild("search_score_summary")
	   ->children_);
	for (unsigned int vc=0;vc<v->size();vc++) {
	  if (vc != 0) text += "%20";
	  text += (*v)[vc]->getAttrValue("name");
	  text += ":";
	  text += (*v)[vc]->getAttrValue("value");
	}
	text += "&Prob=" + p;

	text += "\">";

	// highlight any probabilities in which +2 and +3 both
	// received high prob. and were therefore adjusted down
	if (pnode->getAttrValue("analysis") == "adjusted") {
	  p = "" + p + "";
	}

	text += p;

	text += "";
      }
    }

    // assume it's a parameter node: fval, etc
    else {
      if (mode == Field::value ||
	  mode == Field::plainText ||
	  mode == Field::html) {
	text=node
	  ->findChild("search_result")
	  ->findChild("search_hit", "hit_rank", "1")
	  ->findChild("analysis_result","analysis","peptideprophet")
	  ->findChild("peptideprophet_result")
	  ->findChild("search_score_summary")
	  ->findChild(nodeName_)
	  ->getAttrValue("value");
      }
    }

    // shouldn't get here
    break;
    // end peptideProphet

  case Field::interProphet:

    // PROBABILITY
    if (fieldName_=="probability") {
      if (mode == Field::value ||
	  mode == Field::plainText
	  // for now, no link
	  ||
	  mode == Field::html
	  ) {
	text =
	  node
	  ->findChild("search_result")
	  ->findChild("search_hit", "hit_rank", "1")
	  ->findChild("analysis_result","analysis","interprophet")
	  ->findChild("interprophet_result")
	  ->getAttrValue("probability");
      }
    }

    // assume it's a parameter node: fval, etc
    else {
      if (mode == Field::value ||
	  mode == Field::plainText ||
	  mode == Field::html) {
	text=node
	  ->findChild("search_result")
	  ->findChild("search_hit", "hit_rank", "1")
	  ->findChild("analysis_result","analysis","interprophet")
	  ->findChild("interprophet_result")
	  ->findChild("search_score_summary")
	  ->findChild(nodeName_)
	  ->getAttrValue("value");
      }
    }

    // shouldn't get here
    break;
    // end interProphet

  default:
    break;
  }

  if (text == "") {
    if (mode == Field::value) {
      // no change
      // text = "";
    }
    else {
      text = "[unavailable]";
    }
  }
  return text;
}

bool
Field::searchPeptideText(XMLNodePtr node,
			 string searchText,
			 bool includeModText,
			 bool searchOnly, // then no highlight text generated
			 string& returnText,
			 bool returnHtml,
			 bool returnBrackets) {

  string peptideSequence = node->attrs_["peptide"];

  // each vector element is the text for one AA
  vector<string> peptideAAVec;

  // each vector element is the text for the subscripted numeric value
  vector<string> peptideAAVecMods;

  // add n term. modification, if any
  int nTermOffset = 0;
  string nTermMod = node
    ->findChild("modification_info")
    ->getAttrValue("mod_nterm_mass");
  if (nTermMod != "") {
    nTermOffset = 1;
    peptideSequence = string("n") + peptideSequence;
  }

  // add modified c term indicator if required
  string cTermMod = node
    ->findChild("modification_info")
    ->getAttrValue("mod_cterm_mass");
  if (cTermMod != "") {
    peptideSequence = peptideSequence + string("c");
  }

  char t[255];

  /**
     make a string vector, in which each element is one amino acid;
  */

  /*
  // put nTerm text into vector
  if (nTermMod != "") {
    peptideAAVec.push_back("n");
  }
  */

  // put main peptide text into vector
  for (unsigned int i=0; i<peptideSequence.size(); i++) {
    peptideAAVec.push_back(peptideSequence.substr(i,1));
  }

  /**
      make a string vector, in which each element is one
      AA's (or [c|n]Term's)  numeric modification
  **/

  // first, allocate blank strings in mod vector
  for (unsigned int c=0; c<peptideAAVec.size();c++) {
    peptideAAVecMods.push_back("");
  }

  // put in nTerm mod value, if any
  if (nTermMod != "") {
    double d;
    toDouble(nTermMod,d);
    sprintf(t, "%.2f", d);
    peptideAAVecMods[0] = (string(t));
  }

  // put in all main peptide text mods
  if (!
      node->findChild("modification_info")->isEmpty_) {

    // yes, there are modifications

    int numMods = (int)node->findChild("modification_info")->children_.size();

    for (int c=0; c<numMods; c++) {
      int modPos;
      toInt(node->findChild("modification_info")
	    ->children_[c]->getAttrValue("position"), modPos);
      string modVal =
	(node->findChild("modification_info")
	 ->children_[c]->getAttrValue("mass"));
      double d;
      toDouble(modVal, d);
      sprintf(t, "%.2f", d);

      // string offset starts from zero
      modPos--;
      peptideAAVecMods[modPos + nTermOffset] = t;
    }
  }

  // put in cTerm mod value, if any
  if (cTermMod != "") {
    double d;
    toDouble(cTermMod, d);
    sprintf(t, "%.2f", d);
    peptideAAVecMods[peptideAAVecMods.size() - 1] = string(t);
  }

  /**
     assemble strings back together
  */
  string peptideTextNoMods = "";
  string peptideTextMods = "";
  string peptideTextBracketMods = "";

  for (unsigned int j=0; j<peptideAAVec.size(); j++) {
    peptideTextNoMods += peptideAAVec[j];

    peptideTextMods += peptideAAVec[j]
      + peptideAAVecMods[j];

    peptideTextBracketMods += peptideAAVec[j];
    if (peptideAAVecMods[j] != "") {
      peptideTextBracketMods +=
	string("[")
	+ peptideAAVecMods[j]
	+ string("]");
    }

  }

  if (searchOnly) {
    // either search against the plain peptide text (include 'n' and 'c'),
    // for ex: nTRLKc,
    // or the peptide text with numeric numbers, but no brackets:
    // for ex: n44.01TRL234.12Kc34.56,

    if (searchText == "") {
      return true; // free pass
    }

    string textToSearch;
    if (includeModText) {
      textToSearch = peptideTextMods;
    }
    else {
      textToSearch = peptideTextNoMods;
    }

    //cout << "requred peptide text: " << searchText << endl;

    // init the regex
    regex regPeptide;
    regPeptide = searchText;

    if (!regex_search(textToSearch, regPeptide)) {
      return false;
    }
    else {
      return true;
    }
  } // end searchOnly

  // so, if we're here, we're generating text.  What kind?
  if (returnHtml == false) {
    if (includeModText) {
      if (returnBrackets) {
	returnText = peptideTextBracketMods;
      }
      else {
	returnText = peptideTextMods;
      }
      return false; // no meaning
    }
    else {
      returnText = peptideTextNoMods;
      return false; // no meaning
    }
  }

  // if HERE, returning html text

  // this always includes subscripted numerics,
  // BUT, the text we search against changes:
  //
  // either search against the plain peptide text (include 'n' and 'c'),
  // for ex: nTRLKc,
  // or the peptide text with numeric numbers, but no brackets:
  // for ex: n44.01TRL234.12Kc34.56,

  string textToSearch;
  if (includeModText) {
    textToSearch = peptideTextMods;
  }
  else {
    textToSearch = peptideTextNoMods;
  }

  /**
     make a bool vector marking each AA (and subscript if any) as highlighted or not
  */
  vector<bool> markHighlightVec;
  // first, allocate blank strings in mod vector
  for (unsigned int c=0; c<peptideAAVec.size();c++) {
    markHighlightVec.push_back(false);
  }

  /**
     do the regex highlighting with regPeptide

     we'll search against either the plain text or text-with-numbers (no brackets)

     we'll get the position of the match.

     * if not including mods, easy case: mark matched AAs as highlighted

     * if including mods:
         figure out which AA is the lower bound,
	 figure out which AA is the upper bound
	 mark highlighted

  */

  /** debug **/
  //cout << "in html text highlight production: " << endl;
  //cout << "text to search against: " << textToSearch << endl;
  //cout << "search string: " << searchText << endl;
  /** debug **/

  if (searchText.size() > 0 ) {

    string::const_iterator pepstart, pepend;
    pepstart = textToSearch.begin();
    pepend = textToSearch.end();

    match_results<string::const_iterator> what;
    match_flag_type flags = match_default;
    string::size_type startPos = 0;
    string::size_type startPosN = 0; // for numeric search

    // init the regex
    regex regPeptide;
    regPeptide = searchText;

    int round=0;
    while(regex_search(pepstart, pepend, what, regPeptide, flags)) {
      round++;
      //cout << "in regex search loop " << round << endl;

      // for each match...
      //cout << "found match:";
      //cout << startPos + what.position(0) << "): " << what[0] << ":" << endl;

      if (!includeModText) {
	// highlight the range of the matched text

	int match_index = 0;
	// defining this as an int type;
	// passing 0 (even cast as int) to what.position below results in ambigous overload

	string::size_type lowerBound = (startPos + what.position(match_index));
	string::size_type upperBound = (startPos+what.position(match_index) + what.length(match_index));
	for (string::size_type c=lowerBound; c<upperBound; c++) {
	  // easy case: no numerics
	  markHighlightVec[c] = true;
	}

	startPos += (what.position(match_index) + what.length(match_index));
      }

      else {
	// we're including numerics

	// realStart and realEnd will mark the boundaries in the
	// "textToSearch" string of what characters should be
	// highlighted; if part of the numerics are highlighted we
	// shift the boundaries to mark them all

	// we have to figure out which AA is the lower bound
	int match_index = 0; // see comments above (re: ambigious overload)
	string::size_type realStart = (startPosN + what.position(match_index)); // pos in searched-against text
	// walk realStart back to first on non-numeric text or beginning of string
	while ((realStart !=0) &&
	       (
		(textToSearch[realStart] >= '0') &&
		(textToSearch[realStart] <= '9')
		)
	       ||
	       (
		(textToSearch[realStart] == '.')
		)
	       ) {
	  realStart--;
	}

	// we have to figure out which AA is the upper bound
	string::size_type realEnd = (startPosN+what.position(match_index) + what.length(match_index));
	// advance realEnd to first non-numeric or end of string
	while ((realEnd < textToSearch.length()) &&
	       (
		(textToSearch[realEnd] >= '0') &&
		(textToSearch[realEnd] <= '9')
		)
	       ||
	       (
		(textToSearch[realEnd] == '.')
		)
	       ) {
	  realEnd++;
	}

	// now, we want to find the range of values in the AA vec to highlight

	// realStart points to an AA: map it
	int aaIndex=0;
	string::size_type stringPos=0;
	while (stringPos != realStart) {
	  char cursor = textToSearch[stringPos];
	  if (!(cursor >= '0' &&
		cursor <= '9')
	      &&
	      cursor != '.') {
	    // cursor was an AA, not mod, so
	    // cursor's AA is in peptideAAVec[aaIndex] *before* this increment
	    aaIndex++;
	  }
	  stringPos++;
	}
	int aaIndexStart = aaIndex;

	// realEnd points to an AA: map it
	aaIndex = 0;
	stringPos = 0;
	while (stringPos != realEnd) {
	  char cursor = textToSearch[stringPos];
	  if (!(cursor >= '0' &&
		cursor <= '9')
	      &&
	      cursor != '.') {
	    // cursor was an AA, not mod, so
	    // cursor's AA is in peptideAAVec[aaIndex] *before* this increment
	    aaIndex++;
	  }
	  stringPos++;
	}
	int aaIndexEnd = aaIndex;

	for (int m=aaIndexStart; m<aaIndexEnd; ++m) {
	  markHighlightVec[m] = true;
	}

	startPosN += (int)(what.position(match_index) + what.length(match_index));

      } // end numerics highlighting

      // increment the while-loop search
      pepstart = what[0].second;
    } // end regex while-loop

  } // end highlighting text

  /**
     NOW, we get to build up the final html string!

  */
  returnText = "";
  for (unsigned int jj=0; jj<peptideAAVec.size(); jj++) {

    if (markHighlightVec[jj]) {
      returnText += "";
    }

    returnText += peptideAAVec[jj];

    if (peptideAAVecMods[jj] != "") {
      returnText += "";
      returnText += peptideAAVecMods[jj];
      returnText += "";
    }

    if (markHighlightVec[jj]) {
      returnText += "";
    }
  }

  return false; // no meaning

}

ext: cxx

max_stars_repo_name: dacb/msmskit

max_issues_repo_name: dacb/msmskit

max_forks_repo_name: dacb/msmskit