text:
//
// $Id: Digestion.cpp 10922 2017-06-06 17:54:26Z chambm $
//
//
// Original author: Matt Chambers <matt.chambers .@. vanderbilt.edu>
//
// Copyright 2006 Louis Warschaw Prostate Cancer Center
//   Cedars Sinai Medical Center, Los Angeles, California  90048
// Copyright 2008 Vanderbilt University - Nashville, TN 37232
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#define PWIZ_SOURCE

#include "Digestion.hpp"
#include "Peptide.hpp"
#include "AminoAcid.hpp"
#include "pwiz/utility/misc/CharIndexedVector.hpp"
#include "pwiz/utility/misc/Exception.hpp"
#include "pwiz/utility/misc/Std.hpp"
#include "pwiz/utility/misc/Singleton.hpp"
#include <boost/xpressive/xpressive_dynamic.hpp>

namespace pwiz {
namespace proteome {

using namespace pwiz::cv;
using namespace pwiz::util;
using boost::shared_ptr;
namespace bxp = boost::xpressive;

#undef SECURE_SCL

PWIZ_API_DECL
DigestedPeptide::DigestedPeptide(const string& sequence)
:   Peptide(sequence)
{
}

PWIZ_API_DECL
DigestedPeptide::DigestedPeptide(const char* sequence)
:   Peptide(sequence)
{
}

PWIZ_API_DECL
DigestedPeptide::DigestedPeptide(std::string::const_iterator begin,
                                 std::string::const_iterator end,
                                 size_t offset,
                                 size_t missedCleavages,
                                 bool NTerminusIsSpecific,
                                 bool CTerminusIsSpecific,
                                 std::string NTerminusPrefix,
                                 std::string CTerminusSuffix)
:   Peptide(begin, end),
    offset_(offset),
    missedCleavages_(missedCleavages),
    NTerminusIsSpecific_(NTerminusIsSpecific),
    CTerminusIsSpecific_(CTerminusIsSpecific),
    NTerminusPrefix_(NTerminusPrefix),
    CTerminusSuffix_(CTerminusSuffix)
{
}

PWIZ_API_DECL
DigestedPeptide::DigestedPeptide(const Peptide& peptide,
                                 size_t offset,
                                 size_t missedCleavages,
                                 bool NTerminusIsSpecific,
                                 bool CTerminusIsSpecific,
                                 std::string NTerminusPrefix,
                                 std::string CTerminusSuffix)
:   Peptide(peptide),
    offset_(offset),
    missedCleavages_(missedCleavages),
    NTerminusIsSpecific_(NTerminusIsSpecific),
    CTerminusIsSpecific_(CTerminusIsSpecific),
    NTerminusPrefix_(NTerminusPrefix),
    CTerminusSuffix_(CTerminusSuffix)
{
}

PWIZ_API_DECL DigestedPeptide::DigestedPeptide(const DigestedPeptide& other)
:   Peptide(other),
    offset_(other.offset_),
    missedCleavages_(other.missedCleavages_),
    NTerminusIsSpecific_(other.NTerminusIsSpecific_),
    CTerminusIsSpecific_(other.CTerminusIsSpecific_),
    NTerminusPrefix_(other.NTerminusPrefix_),
    CTerminusSuffix_(other.CTerminusSuffix_)
{
}

PWIZ_API_DECL DigestedPeptide& DigestedPeptide::operator=(const DigestedPeptide& rhs)
{
    Peptide::operator=(rhs);
    offset_ = rhs.offset_;
    missedCleavages_ = rhs.missedCleavages_;
    NTerminusIsSpecific_ = rhs.NTerminusIsSpecific_;
    CTerminusIsSpecific_ = rhs.CTerminusIsSpecific_;
    NTerminusPrefix_ = rhs.NTerminusPrefix_;
    CTerminusSuffix_ = rhs.CTerminusSuffix_;
    return *this;
}

PWIZ_API_DECL DigestedPeptide::~DigestedPeptide()
{
}

PWIZ_API_DECL size_t DigestedPeptide::offset() const
{
    return offset_;
}

PWIZ_API_DECL size_t DigestedPeptide::missedCleavages() const
{
    return missedCleavages_;
}

PWIZ_API_DECL size_t DigestedPeptide::specificTermini() const
{
    return (size_t) NTerminusIsSpecific_ + (size_t) CTerminusIsSpecific_;
}

PWIZ_API_DECL bool DigestedPeptide::NTerminusIsSpecific() const
{
    return NTerminusIsSpecific_;
}

PWIZ_API_DECL bool DigestedPeptide::CTerminusIsSpecific() const
{
    return CTerminusIsSpecific_;
}

PWIZ_API_DECL std::string DigestedPeptide::NTerminusPrefix() const
{
    return NTerminusPrefix_;
}

PWIZ_API_DECL std::string DigestedPeptide::CTerminusSuffix() const
{
    return CTerminusSuffix_;
}

PWIZ_API_DECL bool DigestedPeptide::operator==(const DigestedPeptide& rhs) const
{
    return this->Peptide::operator==(rhs) &&
           offset() == rhs.offset() &&
           missedCleavages() == rhs.missedCleavages() &&
           NTerminusIsSpecific() == rhs.NTerminusIsSpecific() &&
           CTerminusIsSpecific() == rhs.CTerminusIsSpecific() &&
           NTerminusPrefix() == rhs.NTerminusPrefix() &&
           CTerminusSuffix() == rhs.CTerminusSuffix();
}

PWIZ_API_DECL
Digestion::Config::Config(int maximumMissedCleavages,
                          //double minimumMass,
                          //double maximumMass,
                          int minimumLength,
                          int maximumLength,
                          Specificity minimumSpecificity,
                          bool clipNTerminalMethionine)
:   maximumMissedCleavages(maximumMissedCleavages),
    //minimumMass(minimumMass), maximumMass(maximumMass),
    minimumLength(minimumLength), maximumLength(maximumLength),
    minimumSpecificity(minimumSpecificity),
    clipNTerminalMethionine(clipNTerminalMethionine)
{
}

namespace {

class CleavageAgentInfo : public boost::singleton<CleavageAgentInfo>
{
    public:
    CleavageAgentInfo(boost::restricted)
    {
        const vector<CVID>& cvids = pwiz::cv::cvids();
        for (vector<CVID>::const_iterator itr = cvids.begin();
             itr != cvids.end(); ++itr)
        {
            if (!cvIsA(*itr, MS_cleavage_agent_name))
                continue;

            const CVTermInfo& cvTermInfo = pwiz::cv::cvTermInfo(*itr);
            multimap<string, CVID>::const_iterator regexRelationItr =
                cvTermInfo.otherRelations.find("has_regexp");
            if (regexRelationItr != cvTermInfo.otherRelations.end())
            {
                cleavageAgents_.insert(*itr);
                cleavageAgentNames_.push_back(cvTermInfo.name);
                cleavageAgentNameToCvidMap_[bal::to_lower_copy(cvTermInfo.name)] = *itr;
                BOOST_FOREACH(const string& synonym, cvTermInfo.exactSynonyms)
                    cleavageAgentNameToCvidMap_[bal::to_lower_copy(synonym)] = *itr;
                const CVTermInfo& cleavageAgentRegexTerm = pwiz::cv::cvTermInfo(regexRelationItr->second);
                cleavageAgentRegexToCvidMap_[cleavageAgentRegexTerm.name] = *itr;
                cleavageAgentToRegexMap_[*itr] = &cleavageAgentRegexTerm;
            }
            else if (*itr == MS_unspecific_cleavage || *itr == MS_no_cleavage)
            {
                cleavageAgents_.insert(*itr);
                cleavageAgentNames_.push_back(cvTermInfo.name);
                cleavageAgentNameToCvidMap_[bal::to_lower_copy(cvTermInfo.name)] = *itr;
            }
        }
    }

    const set<CVID>& cleavageAgents() const {return cleavageAgents_;}
    const vector<string>& cleavageAgentNames() const {return cleavageAgentNames_;}

    CVID getCleavageAgentByName(const string& agentName) const
    {
        string name = bal::to_lower_copy(agentName);
        map<string, CVID>::const_iterator agentTermItr = cleavageAgentNameToCvidMap_.find(name);

        if (agentTermItr == cleavageAgentNameToCvidMap_.end())
            return CVID_Unknown;

        return agentTermItr->second;
    }

    CVID getCleavageAgentByRegex(const string& agentRegex) const
    {
        map<string, CVID>::const_iterator agentTermItr = cleavageAgentRegexToCvidMap_.find(agentRegex);

        if (agentTermItr == cleavageAgentRegexToCvidMap_.end())
            return CVID_Unknown;

        return agentTermItr->second;
    }

    const std::string& getCleavageAgentRegex(CVID agentCvid) const
    {
        if (!pwiz::cv::cvIsA(agentCvid, MS_cleavage_agent_name))
            throw invalid_argument("[getCleavageAgentRegex] CVID is not a cleavage agent.");

        map<CVID, const CVTermInfo*>::const_iterator regexTermItr =
            cleavageAgentToRegexMap_.find(agentCvid);

        if (regexTermItr == cleavageAgentToRegexMap_.end())
            throw runtime_error("[getCleavageAgentRegex] No regex relation for cleavage agent " + cvTermInfo(agentCvid).name);

        return regexTermItr->second->name;
    }

    private:
    set<CVID> cleavageAgents_;
    vector<string> cleavageAgentNames_;
    map<string, CVID> cleavageAgentNameToCvidMap_;
    map<string, CVID> cleavageAgentRegexToCvidMap_;
    map<CVID, const CVTermInfo*> cleavageAgentToRegexMap_;
};

} // namespace

const set<CVID>& Digestion::getCleavageAgents()
{
    return CleavageAgentInfo::instance->cleavageAgents();
}

const vector<string>& Digestion::getCleavageAgentNames()
{
    return CleavageAgentInfo::instance->cleavageAgentNames();
}

CVID Digestion::getCleavageAgentByName(const string& agentName)
{
    return CleavageAgentInfo::instance->getCleavageAgentByName(agentName);
}

CVID Digestion::getCleavageAgentByRegex(const string& agentRegex)
{
    return CleavageAgentInfo::instance->getCleavageAgentByRegex(agentRegex);
}

const string& Digestion::getCleavageAgentRegex(CVID agentCvid)
{
    return CleavageAgentInfo::instance->getCleavageAgentRegex(agentCvid);
}

namespace {

// match zero or one regex term like (?<=[KR]) or (?<=K) or (?<![KR]) or (?<!K)
// followed by zero or one term like (?=[KR]) or (?=K) or (?![KR]) or (?!K)
// 4 capture groups: [!=] [A-Z] for each look: 0                1                        2                3
const bxp::sregex cutNoCutRegex = bxp::sregex::compile("(?:\\(+\\?<([=!])(\\[[A-Z]+\\]|[A-Z])\\)+)?(?:\\(+\\?([=!])(\\[[A-Z]+\\]|[A-Z])\\)+)?");

} // namespace

string Digestion::disambiguateCleavageAgentRegex(const string& cleavageAgentRegex)
{
    if (cleavageAgentRegex.find_first_of("BJXZ") == string::npos)
        return cleavageAgentRegex;

    // expand ambiguous residues, i.e. B->[ND], Z->[EQ], J->[IL], X->[A-Z]
    bxp::smatch what;
    bxp::regex_match(cleavageAgentRegex, what, cutNoCutRegex);

    bool hasLookbehind = what[1].matched && what[2].matched;
    bool hasLookahead = what[3].matched && what[4].matched;
    bool lookbehindIsPositive = hasLookbehind && what[1] == "=";
    bool lookaheadIsPositive = hasLookahead && what[3] == "=";
    string lookbehindResidues = hasLookbehind ? bal::trim_copy_if(what[2].str(), bal::is_any_of("[]")) : string();
    string lookaheadResidues = hasLookahead ? bal::trim_copy_if(what[4].str(), bal::is_any_of("[]")) : string();

    // if both looks are empty, throw an exception
    if (!hasLookbehind && !hasLookahead)
        throw runtime_error("[Digestion::disambiguateCleavageAgentRegex()] No lookbehind or lookahead expressions found in \"" + cleavageAgentRegex + "\"");

    // add the ambiguous choices to each B/Z/J;
    // ambiguous choices might be listed twice ([BD] becomes [BNDD]), but that's not a problem
    bal::replace_all(lookbehindResidues, "B", "BND");
    bal::replace_all(lookbehindResidues, "Z", "ZEQ");
    bal::replace_all(lookbehindResidues, "J", "JIL");
    bal::replace_all(lookbehindResidues, "X", "A-Z");

    bal::replace_all(lookaheadResidues, "B", "BND");
    bal::replace_all(lookaheadResidues, "Z", "ZEQ");
    bal::replace_all(lookaheadResidues, "J", "JIL");
    bal::replace_all(lookaheadResidues, "X", "A-Z");

    string& lb = lookbehindResidues;
    string& la = lookaheadResidues;

    return (lb.empty() ? "" : string("(?<") + (lookbehindIsPositive ? "=" : "!") + (lb.length() > 1 ? "[" : "") + lb + (lb.length() > 1 ? "])" : ")")) +
           (la.empty() ? "" : string("(?") + (lookaheadIsPositive ? "=" : "!")  + (la.length() > 1 ? "[" : "") + la + (la.length() > 1 ? "])" : ")"));
}

class Digestion::Impl
{
    public:
    Impl(const Peptide& peptide, const std::vector<CVID>& cleavageAgents, const Config& config)
        :   peptide_(peptide), config_(config)
    {
        if (cleavageAgents.size() == 1)
        {
            cleavageAgent_ = cleavageAgents[0];
            if (cleavageAgent_ == MS_unspecific_cleavage)
                config_.minimumSpecificity = Digestion::NonSpecific;
            else if (cleavageAgent_ != MS_no_cleavage)
                cleavageAgentRegex_ = bxp::sregex::compile(disambiguateCleavageAgentRegex(getCleavageAgentRegex(cleavageAgent_)));
            return;
        }

        cleavageAgent_ = CVID_Unknown; // Avoid testing uninitialized value in digest()
        string mergedRegex = "((" + disambiguateCleavageAgentRegex(getCleavageAgentRegex(cleavageAgents[0]));
        for (size_t i=1; i < cleavageAgents.size(); ++i)
            mergedRegex += ")|(" + disambiguateCleavageAgentRegex(getCleavageAgentRegex(cleavageAgents[i]));
        mergedRegex += "))";

        cleavageAgentRegex_ = bxp::sregex::compile(mergedRegex);
    }

    Impl(const Peptide& peptide, const vector<string>& cleavageAgentRegexes, const Config& config)
        :   peptide_(peptide), config_(config)
    {
        cleavageAgent_ = CVID_Unknown; // Avoid testing uninitialized value in digest()
        if (cleavageAgentRegexes.size() == 1)
        {
            cleavageAgentRegex_ = bxp::sregex::compile(cleavageAgentRegexes[0]); //disambiguateCleavageAgentRegex(cleavageAgentRegexes[0].str());
            return;
        }

        string mergedRegex = "((" + disambiguateCleavageAgentRegex(cleavageAgentRegexes[0]);
        for (size_t i=1; i < cleavageAgentRegexes.size(); ++i)
            mergedRegex += ")|(" + disambiguateCleavageAgentRegex(cleavageAgentRegexes[i]);
        mergedRegex += "))";

        cleavageAgentRegex_ = bxp::sregex::compile(mergedRegex);
    }

    inline void digest() const
    {
        if (sites_.empty())
        {
            try
            {
                const string& sequence = peptide_.sequence();

                if (cleavageAgent_ == MS_unspecific_cleavage)
                {
                    for (int i=-1, end=(int) sequence.size()-1; i < end; ++i)
                        sites_.push_back(i);
                    sitesSet_.insert(sites_.begin(), sites_.end());
                    return;
                }
                else if (cleavageAgent_ == MS_no_cleavage)
                {
                    sites_.push_back(-1);
                    sites_.push_back(sequence.length()-1);
                    sitesSet_.insert(sites_.begin(), sites_.end());
                    return;
                }

                //if (cleavageAgentRegex_.empty())
                //    throw runtime_error("empty cleavage regex");

                std::string::const_iterator start = sequence.begin();
                std::string::const_iterator end = sequence.end();
                bxp::smatch what;
                bxp::regex_constants::match_flag_type flags = bxp::regex_constants::match_default;
                while (bxp::regex_search(start, end, what, cleavageAgentRegex_, flags))
                {
                    sites_.push_back(int(what[0].first-sequence.begin()-1));

                    // update search position and flags
                    start = max(what[0].second, start+1);
                    flags = flags | bxp::regex_constants::match_prev_avail | bxp::regex_constants::match_not_bol;
                }

                // if regex didn't match n-terminus, insert it
                if (sites_.empty() || sites_.front() > -1)
                    sites_.insert(sites_.begin(), -1);

                // if regex didn't match c-terminus, insert it
                if (sites_.back() < (int)sequence.length()-1)
                    sites_.push_back(sequence.length()-1);

                if (sites_.size() > 2 && sites_[1] != 0 &&
                    !sequence.empty() && config_.clipNTerminalMethionine && sequence[0] == 'M')
                    sites_.insert(sites_.begin()+1, 0);

                sitesSet_.insert(sites_.begin(), sites_.end());
            }
            catch (exception& e)
            {
                throw runtime_error(string("[Digestion::Impl::digest()] ") + e.what());
            }
        }
    }

    inline vector<DigestedPeptide> find_all(const Peptide& peptide)
    {
        typedef boost::iterator_range<string::const_iterator> const_string_iterator_range;

        digest(); // populate sites_ member if necessary

        const string& sequence_ = peptide_.sequence();

        vector<DigestedPeptide> result;

        if ((int) peptide.sequence().length() > config_.maximumLength ||
            (int) peptide.sequence().length() < config_.minimumLength)
            return result;

        vector<const_string_iterator_range> instances;
        bal::find_all(instances, sequence_, peptide.sequence());

        BOOST_FOREACH(const_string_iterator_range& range, instances)
        {
            size_t beginOffset = range.begin() - sequence_.begin();
            size_t endOffset = beginOffset + peptide.sequence().length() - 1;

            bool NTerminusIsSpecific = sitesSet_.count(int(beginOffset) - 1) > 0;
            bool CTerminusIsSpecific = sitesSet_.count(int(endOffset)) > 0;

            if (((size_t) NTerminusIsSpecific + (size_t) CTerminusIsSpecific) < (size_t) config_.minimumSpecificity)
                continue;

            size_t missedCleavages = 0;
            if (cleavageAgent_ != MS_unspecific_cleavage && cleavageAgent_ != MS_no_cleavage)
                for (size_t i = beginOffset; i < endOffset; ++i)
                    if (sitesSet_.count((int) i) > 0)
                        ++missedCleavages;

            if (missedCleavages > (size_t) config_.maximumMissedCleavages)
                continue;

            string NTerminusPrefix, CTerminusSuffix;
            if (beginOffset > 0)
			    NTerminusPrefix = sequence_.substr(beginOffset-1, 1);
		    if (endOffset+1 < sequence_.length())
			    CTerminusSuffix = sequence_.substr(endOffset+1, 1);

            result.push_back(DigestedPeptide(peptide,
                                             beginOffset,
                                             missedCleavages,
                                             NTerminusIsSpecific,
                                             CTerminusIsSpecific,
                                             NTerminusPrefix,
                                             CTerminusSuffix));
        }

        return result;
    }

    inline DigestedPeptide find_first(const Peptide& peptide, int offsetHint)
    {
        digest(); // populate sites_ member if necessary
        const string& sequence_ = peptide_.sequence();

        if ((int) peptide.sequence().length() > config_.maximumLength ||
            (int) peptide.sequence().length() < config_.minimumLength)
            throw runtime_error("[Digestion::find_first()] Peptide \"" + peptide.sequence() + "\" not found in \"" + sequence_ + "\"");

        if(offsetHint + peptide.sequence().length() > sequence_.length())
            offsetHint = 0;

        size_t beginOffset = sequence_.find(peptide.sequence(), offsetHint);
        if (beginOffset == string::npos)
            beginOffset = sequence_.find(peptide.sequence(), 0);

        if (beginOffset == string::npos)
            throw runtime_error("[Digestion::find_first()] Peptide \"" + peptide.sequence() + "\" not found in \"" + sequence_ + "\"");

        size_t endOffset = beginOffset + peptide.sequence().length() - 1;

        size_t missedCleavages = 0;
        if (cleavageAgent_ != MS_unspecific_cleavage && cleavageAgent_ != MS_no_cleavage)
            for (size_t i = beginOffset; i < endOffset; ++i)
                if (sitesSet_.count((int) i) > 0)
                    ++missedCleavages;

        if (missedCleavages > (size_t) config_.maximumMissedCleavages)
            throw runtime_error("[Digestion::find_first()] Peptide \"" + peptide.sequence() + "\" not found in \"" + sequence_ + "\"");

        bool NTerminusIsSpecific, CTerminusIsSpecific;
        do
        {
            endOffset = beginOffset + peptide.sequence().length() - 1;

            NTerminusIsSpecific = sitesSet_.count(int(beginOffset)-1) > 0;
            CTerminusIsSpecific = sitesSet_.count(int(endOffset)) > 0;

            if (((size_t) NTerminusIsSpecific + (size_t) CTerminusIsSpecific) >= (size_t) config_.minimumSpecificity)
                break;
            beginOffset = sequence_.find(peptide.sequence(), beginOffset + 1);
        }
        while (beginOffset != string::npos);

        if (beginOffset == string::npos ||
            ((size_t) NTerminusIsSpecific + (size_t) CTerminusIsSpecific) < (size_t) config_.minimumSpecificity)
            throw runtime_error("[Digestion::find_first()] Peptide \"" + peptide.sequence() + "\" not found in \"" + sequence_ + "\"");

        string NTerminusPrefix, CTerminusSuffix;
        if (beginOffset > 0)
		    NTerminusPrefix = sequence_.substr(beginOffset-1, 1);
	    if (endOffset+1 < sequence_.length())
		    CTerminusSuffix = sequence_.substr(endOffset+1, 1);

        return DigestedPeptide(peptide,
                               beginOffset,
                               missedCleavages,
                               NTerminusIsSpecific,
                               CTerminusIsSpecific,
                               NTerminusPrefix,
                               CTerminusSuffix);
    }

    private:
    Peptide peptide_;
    Config config_;
    CVID cleavageAgent_;
    bxp::sregex cleavageAgentRegex_;
    friend class Digestion::const_iterator::Impl;

    // precalculated offsets to digestion sites in order of occurence;
    // the sites are between offset and offset+1;
    // -1 is the N terminus digestion site
    // peptide_.sequence().length()-1 is the C terminus digestion site
    mutable vector<int> sites_;
    mutable set<int> sitesSet_;
};

PWIZ_API_DECL
Digestion::Digestion(const Peptide& peptide,
                     CVID cleavageAgent,
                     const Config& config)
:   impl_(new Impl(peptide, vector<CVID>(1, cleavageAgent), config))
{
}

PWIZ_API_DECL
Digestion::Digestion(const Peptide& peptide,
                     const vector<CVID>& cleavageAgents,
                     const Config& config)
:   impl_(new Impl(peptide, cleavageAgents, config))
{
}

PWIZ_API_DECL
Digestion::Digestion(const Peptide& peptide,
                     const string& cleavageAgentRegex,
                     const Config& config)
:   impl_(new Impl(peptide, vector<string>(1, cleavageAgentRegex), config))
{
}

PWIZ_API_DECL
Digestion::Digestion(const Peptide& peptide,
                     const vector<string>& cleavageAgentRegexes,
                     const Config& config)
:   impl_(new Impl(peptide, cleavageAgentRegexes, config))
{
}

PWIZ_API_DECL Digestion::~Digestion()
{
}

PWIZ_API_DECL vector<DigestedPeptide> Digestion::find_all(const Peptide& peptide) const
{
    return impl_->find_all(peptide);
}

PWIZ_API_DECL DigestedPeptide Digestion::find_first(const Peptide& peptide, size_t offsetHint) const
{
    return impl_->find_first(peptide, offsetHint);
}

PWIZ_API_DECL Digestion::const_iterator Digestion::begin() const
{
    return const_iterator(*this);
}

PWIZ_API_DECL Digestion::const_iterator Digestion::end() const
{
    return const_iterator();
}

class Digestion::const_iterator::Impl
{
    public:
    Impl(const Digestion& digestion)
        :   digestionImpl_(*digestion.impl_),
            config_(digestionImpl_.config_),
            sequence_(digestionImpl_.peptide_.sequence()),
            sites_(digestionImpl_.sites_),
            sitesSet_(digestionImpl_.sitesSet_)
    {
        digestionImpl_.digest();
        try
        {
            switch (config_.minimumSpecificity)
            {
                default:
                case FullySpecific:
                    initFullySpecific();
                    break;

                case SemiSpecific: // TODO: optimize semi-specific
                case NonSpecific:
                    initNonSpecific();
                    break;
            }
        }
        catch (exception& e)
        {
            throw runtime_error(string("[Digestion::const_iterator::Impl::Impl()] ") + e.what());
        }
    }

    inline void initFullySpecific()
    {
        begin_ = end_ = sites_.end();
        beginNonSpecific_ = endNonSpecific_ = -1; // So debuggers don't complain about uninit values

        // iteration requires at least 2 digestion sites
        if (sites_.size() < 2)
            return;

        // try each possible pair of digestion sites;
        // initialize begin_ and end_ to the first pair that meet
        // config's filtering criteria
        bool validSite = false;
        for (begin_ = sites_.begin(); begin_ != sites_.end(); ++begin_)
        {
            for (end_ = begin_, ++end_; end_ != sites_.end(); ++end_)
            {
                int curMissedCleavages = int(end_ - begin_) - 1;
                if (curMissedCleavages > 0 && config_.clipNTerminalMethionine && begin_ != sites_.end() && *begin_ < 0 && sequence_[0] == 'M')
                    --curMissedCleavages;
                if (curMissedCleavages > config_.maximumMissedCleavages)
                    break;

                int curLength = *end_ - *begin_;
                if (curLength > config_.maximumLength)
                    break;
                if (curLength < config_.minimumLength)
                    continue;

                validSite = true;
                break;
            }

            if (validSite)
                break;
        }
    }

    inline void initNonSpecific()
    {
        begin_ = end_ = sites_.begin();
        beginNonSpecific_ = endNonSpecific_ = sequence_.length();
        int maxLength = (int) sequence_.length();

        // try each possible pair of digestion sites;
        // initialize beginNonSpecific_ and beginNonSpecific_ to the first pair that meet
        // config's filtering criteria
        bool passesFilter = false;
        for (int testBegin = -1; testBegin < maxLength && !passesFilter; ++testBegin)
        {
            for (int testEnd = testBegin+config_.minimumLength; testEnd < maxLength; ++testEnd)
            {
                // end offset is too far, start again with a new begin offset
                int curLength = testEnd - testBegin;
                if (curLength > config_.maximumLength)
                    break;

                beginNonSpecific_ = testBegin;
                endNonSpecific_ = testEnd;
                while (begin_ != sites_.end() && *begin_ <= beginNonSpecific_)
                    ++begin_;
                if (begin_ != sites_.end())
                {
                    end_ = begin_--;
                    while (end_ != sites_.end() && *end_ < endNonSpecific_)
                        ++end_;
                }

                // end offset is too far, start again with a new begin offset
                int curMissedCleavages = digestionImpl_.cleavageAgent_ == MS_unspecific_cleavage ? 0 : int(end_ - begin_)-1;
                if (curMissedCleavages > 0 && config_.clipNTerminalMethionine && begin_ != sites_.end() && *begin_ < 0 && sequence_[0] == 'M')
                    --curMissedCleavages;
                if (curMissedCleavages > config_.maximumMissedCleavages)
                    break;

                if (beginNonSpecific_ != maxLength)
                {
                    passesFilter = true;
                    break;
                }
            }
        }
    }

    const DigestedPeptide& peptide() const
    {
        try
        {
            string prefix = "";
            string suffix = "";

            int missedCleavages = 0;

            if (!peptide_.get())
            {
                switch (config_.minimumSpecificity)
                {
                    default:
                    case FullySpecific:
                        if(*begin_ >= 0 && *begin_ < (int) sequence_.length())
                            prefix = sequence_.substr(*begin_, 1); //this could be changed to be something other than 1 by a config option later
                        if(*end_ != (int) sequence_.length())
                            suffix = sequence_.substr(*end_ + 1, 1);

                        missedCleavages = int(end_ - begin_) - 1;
                        if (missedCleavages > 0 && config_.clipNTerminalMethionine && begin_ != sites_.end() && *begin_ < 0 && sequence_[0] == 'M')
                            --missedCleavages;
                        if (missedCleavages > config_.maximumMissedCleavages)
                            throw logic_error("digestion result exceeds maximumMissedClevages (something went wrong in a next*() function)");

                        peptide_.reset(
                            new DigestedPeptide(sequence_.begin()+(*begin_+1),
                                                sequence_.begin()+(*end_+1),
                                                *begin_+1,
                                                missedCleavages,
                                                true,
                                                true,
                                                prefix,
                                                suffix
						));

                    break;

                    case SemiSpecific:
                    case NonSpecific:
                        if(beginNonSpecific_ >= 0 && beginNonSpecific_ < (int) sequence_.length())
                            prefix = sequence_.substr(beginNonSpecific_, 1); //this could be changed to be something other than 1 by a config option later
                        if(endNonSpecific_ != (int) sequence_.length())
                            suffix = sequence_.substr(endNonSpecific_ + 1, 1);

                        if (digestionImpl_.cleavageAgent_ != MS_unspecific_cleavage && digestionImpl_.cleavageAgent_ != MS_no_cleavage)
                        {
                            for (int i = beginNonSpecific_+1; i < endNonSpecific_; ++i)
                                if (sitesSet_.count(i) > 0)
                                    ++missedCleavages;
                            if (missedCleavages > 0 && config_.clipNTerminalMethionine && begin_ != sites_.end() && *begin_ < 0 && sequence_[0] == 'M')
                                --missedCleavages;
                        }

                        peptide_.reset(
                            new DigestedPeptide(sequence_.begin()+(beginNonSpecific_+1),
                                                sequence_.begin()+(endNonSpecific_+1),
                                                beginNonSpecific_+1,
                                                missedCleavages,
                                                begin_ != sites_.end() && *begin_ == beginNonSpecific_,
                                                end_ != sites_.end() && *end_ == endNonSpecific_,
                                                prefix,
                                                suffix
						));
                        break;
                }
            }
            return *peptide_;
        }
        catch (exception& e)
        {
            throw runtime_error(string("[Digestion::const_iterator::Impl::peptide()] ") + e.what());
        }
    }

    inline void nextFullySpecific()
    {
        bool newBegin = (end_ == sites_.end());
        if (!newBegin)
        {
            // advance end_ to the next digestion site
            bool foundNextValidSitePair = false;
            for (++end_; end_ != sites_.end(); ++end_)
            {
                int curMissedCleavages = int(end_ - begin_)-1;
                if (curMissedCleavages > 0 && config_.clipNTerminalMethionine && begin_ != sites_.end() && *begin_ < 0 && sequence_[0] == 'M')
                    --curMissedCleavages;
                if (curMissedCleavages > config_.maximumMissedCleavages)
                    break;

                int curLength = *end_ - *begin_;
                if (curLength > config_.maximumLength)
                    break;
                if (curLength < config_.minimumLength)
                    continue;

                foundNextValidSitePair = true;
                break;
            }

            // there may not be another site that makes a valid site pair
            newBegin = !foundNextValidSitePair;
        }

        if (newBegin)
        {
            // advance to the next valid digestion site pair
            bool foundNextValidSitePair = false;
            for (++begin_; begin_ != sites_.end(); ++begin_)
            {
                for (end_ = begin_+1; end_ != sites_.end(); ++end_)
                {
                    int curMissedCleavages = int(end_ - begin_)-1;
                    if (curMissedCleavages > config_.maximumMissedCleavages)
                        break;

                    int curLength = *end_ - *begin_;
                    if (curLength > config_.maximumLength)
                        break;
                    if (curLength < config_.minimumLength)
                        continue;

                    foundNextValidSitePair = true;
                    break;
                }

                if (foundNextValidSitePair)
                    break;
            }
        }
    }

    inline void nextNonSpecific()
    {
        int maxLength = (int) sequence_.length();
        bool newBegin = (endNonSpecific_ == maxLength);
        if (!newBegin)
        {
            // advance endNonSpecific_ to the next digestion site
            bool foundNextValidSitePair = false;
            end_ = begin_;
            for (++endNonSpecific_; endNonSpecific_ < maxLength; ++endNonSpecific_)
            {
                while (end_ != sites_.end() && *end_ < endNonSpecific_)
                    ++end_;

                int curMissedCleavages = digestionImpl_.cleavageAgent_ == MS_unspecific_cleavage ? 0 : int(end_ - begin_)-1;
                if (curMissedCleavages > 0 && config_.clipNTerminalMethionine && begin_ != sites_.end() && *begin_ < 0 && sequence_[0] == 'M')
                    --curMissedCleavages;
                if (curMissedCleavages > config_.maximumMissedCleavages)
                    break;

                int curLength = endNonSpecific_ - beginNonSpecific_;
                if (curLength > config_.maximumLength)
                    break;
                if (curLength < config_.minimumLength)
                    continue;

                foundNextValidSitePair = true;
                break;
            }

            // there may not be another site that makes a valid site pair
            newBegin = !foundNextValidSitePair;
        }

        if (newBegin)
        {
            // advance to the next valid digestion site pair
            bool foundNextValidSitePair = false;
            for (++beginNonSpecific_; beginNonSpecific_ < maxLength; ++beginNonSpecific_)
            {
                while (begin_ != sites_.end() && *begin_ <= beginNonSpecific_)
                    ++begin_;
                end_ = begin_--;

                for (endNonSpecific_ = beginNonSpecific_+config_.minimumLength; endNonSpecific_ < maxLength; ++endNonSpecific_)
                {
                    while (end_ != sites_.end() && *end_ < endNonSpecific_)
                        ++end_;

                    int curMissedCleavages = digestionImpl_.cleavageAgent_ == MS_unspecific_cleavage ? 0 : int(end_ - begin_)-1;
                    if (curMissedCleavages > 0 && config_.clipNTerminalMethionine && begin_ != sites_.end() && *begin_ < 0 && sequence_[0] == 'M')
                        --curMissedCleavages;
                    if (curMissedCleavages > config_.maximumMissedCleavages)
                        break;

                    int curLength = endNonSpecific_ - beginNonSpecific_;
                    if (curLength > config_.maximumLength)
                        break;
                    if (curLength < config_.minimumLength)
                        continue;

                    foundNextValidSitePair = true;
                    break;
                }

                if (foundNextValidSitePair)
                    break;
            }
        }
    }

    inline Impl& operator++()
    {
        try
        {
            peptide_.reset();

            switch (config_.minimumSpecificity)
            {
                default:
                case FullySpecific:
                    nextFullySpecific();
                    break;

                case SemiSpecific:
                    while (beginNonSpecific_ < (int) sequence_.length())
                    {
                        nextNonSpecific();
                        if ((begin_ != sites_.end() && *begin_ == beginNonSpecific_) ||
                            (end_ != sites_.end() && *end_ == endNonSpecific_))
                            break;
                    }
                    break;

                case NonSpecific:
                    nextNonSpecific();
                    break;
            }
        }
        catch (exception& e)
        {
            throw runtime_error(string("[Digestion::Impl::operator++()] ") + e.what());
        }

        return *this;
    }

    inline Impl operator++(int)
    {
        Impl tmp(*this);
        ++*this;
        return tmp;
    }

    inline bool atEnd()
    {
        switch (config_.minimumSpecificity)
        {
            case SemiSpecific: // TODO: optimize semi-specific
            case NonSpecific:
                return beginNonSpecific_ == (int) sequence_.length();

            case FullySpecific:
            default:
                return begin_ == sites_.end();
        }
    }

    private:
    const Digestion::Impl& digestionImpl_;
    const Config& config_;
    const string& sequence_;
    const vector<int>& sites_;
    const set<int>& sitesSet_;

    // used for all digests
    // fully specific: iterator to the current peptide's N terminal offset-1
    // semi- and non-specific: iterator to the previous valid digestion site before or at beginNonSpecific_
    vector<int>::const_iterator begin_;

    // fully specific: iterator to the current peptide's C terminal offset
    // semi- and non-specific: iterator to the next valid digestion site at or after endNonSpecific_
    vector<int>::const_iterator end_;

    // used for semi- and non-specific digest
    int beginNonSpecific_;
    int endNonSpecific_;

    mutable shared_ptr<DigestedPeptide> peptide_;
    friend class Digestion::const_iterator;
};

PWIZ_API_DECL Digestion::const_iterator::const_iterator()
{
}

PWIZ_API_DECL Digestion::const_iterator::const_iterator(const Digestion& digestion)
:   impl_(new Impl(digestion))
{
}

PWIZ_API_DECL Digestion::const_iterator::const_iterator(const const_iterator& rhs)
:   impl_(rhs.impl_.get() ? new Impl(*rhs.impl_) : 0)
{
}

PWIZ_API_DECL Digestion::const_iterator::~const_iterator()
{
}

PWIZ_API_DECL const DigestedPeptide& Digestion::const_iterator::operator*() const
{
    return impl_->peptide();
}

PWIZ_API_DECL const DigestedPeptide* Digestion::const_iterator::operator->() const
{
    return &(impl_->peptide());
}

PWIZ_API_DECL Digestion::const_iterator& Digestion::const_iterator::operator++()
{
    ++(*impl_);
    return *this;
}

PWIZ_API_DECL Digestion::const_iterator Digestion::const_iterator::operator++(int)
{
    const_iterator tmp(*this);
    ++(*impl_);
    return tmp;
}

PWIZ_API_DECL bool Digestion::const_iterator::operator!=(const Digestion::const_iterator& that) const
{
    return !(*this == that);
}

PWIZ_API_DECL bool Digestion::const_iterator::operator==(const Digestion::const_iterator& that) const
{
    bool gotThis = this->impl_.get() != NULL;
    bool gotThat = that.impl_.get() != NULL;

    if (gotThis && gotThat)
        return this->impl_->begin_ == that.impl_->begin_ &&
               this->impl_->end_ == that.impl_->end_;
    else if (!gotThis && !gotThat) // end() == end()
        return true;
    else if (gotThis)
        return this->impl_->atEnd();
    else // gotThat
        return that.impl_->atEnd();
}

} // namespace proteome
} // namespace pwiz

max_stars_repo_name: edyp-lab/pwiz-mzdb

max_issues_repo_name: edyp-lab/pwiz-mzdb

max_forks_repo_name: edyp-lab/pwiz-mzdb


text:
///////////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2008-2012  Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
//
//  See accompanying file COPYING.TXT file for licensing details.
//
///////////////////////////////////////////////////////////////////////////////
#define CPPCMS_SOURCE
#include "cgi_api.h"
#include <cppcms/service.h>
#include <cppcms/http_context.h>
#include <cppcms/http_request.h>
#include <cppcms/http_response.h>
#include <cppcms/application.h>
#include <cppcms/applications_pool.h>
#include <cppcms/thread_pool.h>
#include <cppcms/views_pool.h>
#include <cppcms/cache_interface.h>
#include <cppcms/session_interface.h>
#include <cppcms/cppcms_error.h>
#include <booster/log.h>
#include <booster/backtrace.h>
#include <booster/aio/io_service.h>
#include <cppcms/http_content_filter.h>
#include <stdio.h>

#include "cached_settings.h"

#include <cppcms/config.h>

#include <utility>
#include "binder.h"

namespace cppcms {
namespace http {

	struct context::_data {
		std::locale locale;
		std::string skin;
		http::request request;
		std::unique_ptr<http::response> response;
		std::unique_ptr<cache_interface> cache;
		std::unique_ptr<session_interface> session;
		booster::shared_ptr<application_specific_pool> pool;
		booster::intrusive_ptr<application> app;
		std::string matched;
		booster::hold_ptr<context::holder> specific;
		_data(context &cntx) :
			locale(cntx.connection().service().locale()),
			request(cntx.connection())
		{
		}
	};
context::context(booster::shared_ptr<impl::cgi::connection> conn) :
	conn_(conn)
{
	d.reset(new _data(*this));
	d->response.reset(new http::response(*this));
	skin(service().views_pool().default_skin());
}

void context::set_holder(holder *p)
{
	d->specific.reset(p);
}
context::holder *context::get_holder()
{
	return d->specific.get();
}

std::string context::skin()
{
	return d->skin;
}

cache_interface &context::cache()
{
	if(!d->cache.get()) {
		d->cache.reset(new cache_interface(*this));
	}
	return *d->cache;
}

void context::skin(std::string const &skin)
{
	d->skin=skin;
}

namespace {
	struct ct_to_bool {
		void (context::*member)(bool r);
		booster::shared_ptr<context> ctx;
		void operator()(context::completion_type c)
		{
			((*ctx).*member)(c!=context::operation_completed);
		}
	};
}

void context::run()
{
	ct_to_bool cb = { &context::on_request_ready, self() };
	conn_->async_prepare_request(this,cb);
}

namespace {
	struct dispatcher {
		void (*func)(booster::shared_ptr<application_specific_pool> const &,booster::shared_ptr<context> const &,std::string const &);
		booster::shared_ptr<application_specific_pool> pool;
		booster::shared_ptr<context> ctx;
		std::string url;
		void operator()() {
			func(pool,ctx,url);
		}
	};
}

void context::submit_to_pool(booster::shared_ptr<application_specific_pool> pool,std::string const &matched)
{
	submit_to_pool_internal(pool,matched,false);
}

namespace {
	struct dispatch_binder {
		void (*dispatch)(booster::intrusive_ptr<application> const &,std::string const &,bool);
		booster::shared_ptr<context> ctx;
		booster::intrusive_ptr<application> app;
		std::string matched;
		bool flag;

		void operator()()
		{
			app->assign_context(ctx);
			dispatch(app,matched,flag);
		}

	};

	class context_guard {
	public:
		context_guard(cppcms::application *app,cppcms::http::context &ctx) : app_(app)
		{
			if(app_)
				app_->add_context(ctx);
		}
		~context_guard()
		{
			if(app_)
				app_->remove_context();
		}
	private:
		cppcms::application *app_;
	};
}

void context::submit_to_asynchronous_application(booster::intrusive_ptr<application> app,std::string const &matched)
{
	dispatch_binder bd = { &context::dispatch, self(), app,matched,false };
	conn_->get_io_service().post(bd);
}

void context::submit_to_pool_internal(booster::shared_ptr<application_specific_pool> pool,std::string const &matched,bool now)
{
	if((pool->flags() & app::op_mode_mask)!=app::synchronous) {
		// asynchronous
		booster::intrusive_ptr<application> app = pool->get(service());

		if(!app) {
			BOOSTER_ERROR("cppcms") << "Cound fetch asynchronous application from pool";
			response().io_mode(http::response::asynchronous);
			response().make_error_response(http::response::internal_server_error);
			async_complete_response();
			return;
		}
		if(now) {
			app->assign_context(self());
			response().io_mode(http::response::asynchronous);
			dispatch(app,matched,false);
		}
		else {
			submit_to_asynchronous_application(app,matched);
		}

		return;
	}
	else {
		dispatcher dt;
		dt.func = &context::dispatch;
		dt.pool = pool;
		dt.ctx = self();
		dt.url=matched;
		service().thread_pool().post(dt);
		return;
	}
}

int context::translate_exception()
{
	try {
		throw;
	}
	catch(abort_upload const &e) {
		return e.code();
	}
	catch(std::exception const &e) {
		make_error_message(e);
		return 500;
	}
	catch(...) {
		BOOSTER_ERROR("cppcms") << "Unknown exception";
		return 500;
	}
	return 0;
}

int context::on_headers_ready()
{
	char const *host = conn_->cgetenv("HTTP_HOST");
	char const *path_info = conn_->cgetenv("PATH_INFO");
	char const *script_name = conn_->cgetenv("SCRIPT_NAME");
	std::string matched;

	booster::intrusive_ptr<application> app;
	booster::shared_ptr<application_specific_pool> pool =
		service().applications_pool().get_application_specific_pool(
			host,
			script_name,
			path_info,
			matched
			);
	if(!pool)
		return 404;

	request().prepare();

	int flags;

	if(request().content_length() != 0 && ((flags=pool->flags()) & app::op_mode_mask) != app::synchronous && (flags & app::content_filter)!=0) {
		app = pool->get(service());
		if(!app)
			return 500;
		try {
			context_guard g(app.get(),*this);
			app->main(matched);
		}
		catch(...) {
			return translate_exception();
		}
	}

	d->pool.swap(pool);
	d->matched.swap(matched);
	d->app.swap(app);

	return request().on_content_start();
}

int context::on_content_progress(size_t n)
{
	context_guard g(d->app.get(),*this);
	return request().on_content_progress(n);
}

void context::on_request_ready(bool error)
{
	booster::shared_ptr<application_specific_pool> pool;
	booster::intrusive_ptr<application> app;
	pool.swap(d->pool);
	app.swap(d->app);

	if(error) {
		if(app) {
			try {
				context_guard g(app.get(),*this);
				request().on_error();
			}
			catch(std::exception const &e) {
				BOOSTER_ERROR("cppcms") << "exception at request::on_error" << e.what() << booster::trace(e);
			}
			catch(...) {
				BOOSTER_ERROR("cppcms") << "Unknown exception at request::on_error";
			}
		}
		return;
	}

	if(app) {
		app->assign_context(self());
		dispatch(app,d->matched,false);
		return;
	}

	submit_to_pool_internal(pool,d->matched,true);
}

namespace {
	struct run_ctx {
		booster::shared_ptr<context> ctx;
		void operator()() {
			ctx->run();
		}
	};
}

void context::complete_response()
{
	response().finalize();
	if(conn_->is_reuseable()) {
		booster::shared_ptr<context> cont(new context(conn_));
		run_ctx rn = { cont };
		service().post(rn);
	}
	conn_.reset();
}
// static
void context::dispatch(booster::shared_ptr<application_specific_pool> const &pool,booster::shared_ptr<context> const &self,std::string const &url)
{
	booster::intrusive_ptr<application> app = pool->get(self->service());
	if(!app) {
		BOOSTER_ERROR("cppcms") << "Cound fetch synchronous application from a pool";
		self->response().make_error_response(http::response::internal_server_error);
		self->complete_response();
		return;
	}
	app->assign_context(self);
	dispatch(app,url,true);
}

void context::make_error_message(std::exception const &e)
{
	BOOSTER_ERROR("cppcms") << "Caught exception ["<<e.what()<<"]\n" << booster::trace(e)  ;
	if(!response().some_output_was_written()) {
		if(service().cached_settings().security.display_error_message) {
			std::ostringstream ss;
			ss << e.what() << '\n';
			ss << booster::trace(e);
			response().make_error_response(http::response::internal_server_error,ss.str());
		}
		else
			response().make_error_response(http::response::internal_server_error);
	}
}
// static
void context::dispatch(booster::intrusive_ptr<application> const &app,std::string const &url,bool syncronous)
{
	try {
		if(syncronous) {
			app->response().io_mode(http::response::normal);
			if(!app->context().service().cached_settings().session.disable_automatic_load)
				app->context().session().load();
		}
		else {
			app->response().io_mode(http::response::asynchronous);
		}

		if(syncronous && !app->context().service().cached_settings().session.disable_automatic_load)
			app->context().session().load();
		app->main(url);
	}
	catch(request_forgery_error const &e) {
		if(app->get_context() && !app->response().some_output_was_written()) {
			app->response().make_error_response(http::response::forbidden);
		}
	}
	catch(...){
		if(app->get_context())
			app->context().translate_exception();
	}

	if(app->get_context()) {
		try {
			if(syncronous) {
				app->context().complete_response();
			}
			else  {
				app->context().async_complete_response();
			}
		}
		catch(...) {
			app->release_context();
			throw;
		}
		app->release_context();
	}
}

void context::async_flush_output(context::handler const &h)
{
	if(response().io_mode() != http::response::asynchronous && response().io_mode()!=http::response::asynchronous_raw) {
		throw cppcms_error("Can't use asynchronouse operations when I/O mode is synchronous");
	}
	conn_->async_write_response(
		response(),
		false,
		h);
}

void context::async_complete_response()
{
	response().finalize();
	if(response().io_mode() == http::response::asynchronous || response().io_mode() == http::response::asynchronous_raw) {
		ct_to_bool cb = { &context::try_restart, self() };
		conn_->async_write_response(
			response(),
			true,
			cb);
		return;
	}
	complete_response();
}

void context::try_restart(bool e)
{
	if(e) return;

	if(conn_->is_reuseable()) {
		booster::shared_ptr<context> cont(new context(conn_));
		cont->run();
	}
	conn_.reset();
}

booster::shared_ptr<context> context::self()
{
	return shared_from_this();
}

context::~context()
{
}

void context::async_on_peer_reset(booster::callback<void()> const &h)
{
	conn_->aync_wait_for_close_by_peer(h);
}

impl::cgi::connection &context::connection()
{
	return *conn_;
}

cppcms::service &context::service()
{
	return conn_->service();
}

http::request &context::request()
{
	return d->request;
}

http::response &context::response()
{
	return *d->response;
}

json::value const &context::settings()
{
	return conn_->service().settings();
}

std::locale context::locale()
{
	return d->locale;
}
void context::locale(std::locale const &new_locale)
{
	d->locale=new_locale;
	if(response().some_output_was_written())
		response().out().imbue(d->locale);
}
void context::locale(std::string const &name)
{
	locale(service().locale(name));
}
session_interface &context::session()
{
	if(!d->session.get())
		d->session.reset(new session_interface(*this));
	return *d->session;
}

} // http
} // cppcms

ext: cpp

max_stars_repo_name: gatehouse/cppcms

max_issues_repo_name: gatehouse/cppcms

max_forks_repo_name: gatehouse/cppcms


text:
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE JPetTaskIOTest
#include <boost/test/unit_test.hpp>
#include "./JPetCmdParser/JPetCmdParser.h"
#include "./JPetTaskIO/JPetTaskIO.h"
#include "./JPetOptionsGenerator/JPetOptionsGenerator.h"

BOOST_AUTO_TEST_SUITE(FirstSuite)

BOOST_AUTO_TEST_CASE(progressBarTest)
{
  JPetTaskIO taskIO;
  taskIO.displayProgressBar(5, 100);
}

//BOOST_AUTO_TEST_CASE(progressBarTest)
//{
  //JPetTaskIO taskIO;
  //taskIO.displayProgressBar(5, 100);
//}
//class JPetTaskIO_test: public JPetTaskIO
//{
//public:
  //JPetTaskIO_test() {}
  //virtual ~JPetTaskIO_test() {}

  //using JPetTaskIO::setUserLimits;
//};

////std::vector<JPetOptions> getOptionsBasedOnCmdLineArgs(const std::string& cmdLine)
////{
  ////auto args_char = JPetCommonTools::createArgs(cmdLine);
  ////auto argc = args_char.size();
  ////auto argv = args_char.data();

  ////JPetCmdParser parser;
  ////JPetOptionsGenerator optGenerator;
  ////return optGenerator.generateOptions(parser.parseCmdLineArgs(argc, const_cast<const char**>(argv)));
////}

//BOOST_AUTO_TEST_CASE( setUserLimits)
//{
  //auto commandLine = "./main.x -t root -f unitTestData/JPetTaskIOTest/cosm_barrel.hld.root -i 26 -r 1000 1001";
  //auto options = getOptionsBasedOnCmdLineArgs(commandLine); //optGenerator.generateOptions(parser.parseCmdLineArgs(argc, const_cast<const char**>(argv)));
  //auto first = 0ll;
  //auto last = 0ll;
  //auto opt = options.front().getOptions();
  //JPetOptions optObject(opt);
  //JPetTaskIO_test task;
  //task.setUserLimits(optObject, 10000, first, last);
  //BOOST_REQUIRE_EQUAL(first, 1000);
  //BOOST_REQUIRE_EQUAL(last, 1001);
//}

//BOOST_AUTO_TEST_CASE( setUserLimits2 )
//{
  //auto commandLine = "./main.x -t root -f unitTestData/JPetTaskIOTest/cosm_barrel.hld.root -i 26 -r 1000 1001";
  //auto options = getOptionsBasedOnCmdLineArgs(commandLine);
  //auto first = 0ll;
  //auto last = 0ll;
  //auto opt = options.front().getOptions();
  //JPetOptions optObject(opt);
  //JPetTaskIO_test task;
  //task.setUserLimits(optObject, 1, first, last);
  //BOOST_REQUIRE_EQUAL(first, 0);
  //BOOST_REQUIRE_EQUAL(last, 0);
//}

BOOST_AUTO_TEST_SUITE_END()

max_stars_repo_name: Alvarness/j-pet-framework

max_issues_repo_name: Alvarness/j-pet-framework

max_forks_repo_name: Alvarness/j-pet-framework


text:
// Copyright (C) 2012 Hartmut Kaiser
// Copyright (C) 2001-2003 William E. Kempf
// Copyright (C) 2008 Anthony Williams
//
//  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)

#include <hpx/hpx_init.hpp>
#include <hpx/include/threadmanager.hpp>
#include <hpx/include/lcos.hpp>
#include <hpx/util/lightweight_test.hpp>

#include <boost/assign/std/vector.hpp>
#include <boost/lexical_cast.hpp>

using boost::program_options::variables_map;
using boost::program_options::options_description;

///////////////////////////////////////////////////////////////////////////////
inline void set_description(char const* test_name)
{
    hpx::threads::set_thread_description(hpx::threads::get_self_id(), test_name);
}

///////////////////////////////////////////////////////////////////////////////
inline int
time_cmp(boost::posix_time::ptime const& xt1, boost::posix_time::ptime const& xt2)
{
    if (xt1 == xt2)
        return 0;
    return xt1 > xt2 ? 1 : -1;
}

inline bool in_range(boost::posix_time::ptime const& xt, int secs = 1)
{
    boost::posix_time::ptime now =
        boost::date_time::second_clock<boost::posix_time::ptime>::universal_time();
    boost::posix_time::ptime mint(now + boost::posix_time::seconds(-secs));
    return time_cmp(xt, mint) >= 0 && time_cmp(xt, now) <= 0;
}

///////////////////////////////////////////////////////////////////////////////
template <typename F>
void timed_test(F func, int /*secs*/)
{
    hpx::thread thrd(func);
    thrd.join();

    // FIXME: implement execution monitor to verify in-time execution and to
    //        prevent deadlocks
}

///////////////////////////////////////////////////////////////////////////////
int test_value = 0;

void simple_thread()
{
    test_value = 999;
}

void comparison_thread(hpx::thread::id parent)
{
    hpx::thread::id const my_id = hpx::this_thread::get_id();
    HPX_TEST_NEQ(my_id, parent);

    hpx::thread::id const my_id2 = hpx::this_thread::get_id();
    HPX_TEST_EQ(my_id, my_id2);

    hpx::thread::id const no_thread_id = hpx::thread::id();
    HPX_TEST_NEQ(my_id, no_thread_id);
}

///////////////////////////////////////////////////////////////////////////////
void test_sleep()
{
    set_description("test_sleep");

    boost::posix_time::ptime now =
        boost::date_time::second_clock<boost::posix_time::ptime>::universal_time();
    hpx::this_thread::sleep_for(boost::posix_time::seconds(3));

    // Ensure it's in a range instead of checking actual equality due to time
    // lapse
    HPX_TEST(in_range(now, 4));
}

///////////////////////////////////////////////////////////////////////////////
void do_test_creation()
{
    test_value = 0;
    hpx::thread thrd(&simple_thread);
    thrd.join();
    HPX_TEST_EQ(test_value, 999);
}

void test_creation()
{
    set_description("test_creation");
    timed_test(&do_test_creation, 1);
}

///////////////////////////////////////////////////////////////////////////////
void do_test_id_comparison()
{
    hpx::thread::id const self = hpx::this_thread::get_id();
    hpx::thread thrd(HPX_STD_BIND(&comparison_thread, self));
    thrd.join();
}

void test_id_comparison()
{
    set_description("test_id_comparison");
    timed_test(&do_test_id_comparison, 1);
}

///////////////////////////////////////////////////////////////////////////////
void interruption_point_thread(hpx::lcos::local::barrier* b,
    hpx::lcos::local::mutex* m, bool* failed)
{
    try {
        hpx::lcos::local::mutex::scoped_lock lk(*m);
        hpx::this_thread::interruption_point();
        *failed = true;
    }
    catch(...) {
        b->wait();
        throw;
    }
    b->wait();
}

void do_test_thread_interrupts_at_interruption_point()
{
    hpx::lcos::local::mutex m;
    hpx::lcos::local::barrier b(2);
    bool failed = false;
    hpx::lcos::local::mutex::scoped_lock lk(m);
    hpx::thread thrd(
        HPX_STD_BIND(&interruption_point_thread, &b, &m, &failed));
    thrd.interrupt();
    lk.unlock();

    b.wait();       // Make sure the test thread has been executed, as join is
                    // a interruption point which might get triggered.

    thrd.join();
    HPX_TEST(!failed);
}

void test_thread_interrupts_at_interruption_point()
{
    set_description("test_thread_interrupts_at_interruption_point");
    timed_test(&do_test_thread_interrupts_at_interruption_point, 1);
}

///////////////////////////////////////////////////////////////////////////////
void disabled_interruption_point_thread(hpx::lcos::local::mutex* m,
    hpx::lcos::local::barrier* b, bool* failed)
{
    hpx::this_thread::disable_interruption dc;
    try {
        hpx::lcos::local::mutex::scoped_lock lk(*m);
        hpx::this_thread::interruption_point();
        *failed = false;
    }
    catch(...) {
        b->wait();
        throw;
    }
    b->wait();
}

void do_test_thread_no_interrupt_if_interrupts_disabled_at_interruption_point()
{
    hpx::lcos::local::mutex m;
    hpx::lcos::local::barrier b(2);
    bool failed = true;
    hpx::lcos::local::mutex::scoped_lock lk(m);
    hpx::thread thrd(
        HPX_STD_BIND(&disabled_interruption_point_thread, &m, &b, &failed));
    thrd.interrupt();
    lk.unlock();

    b.wait();       // Make sure the test thread has been executed, as join is
                    // a interruption point which might get triggered.

    thrd.join();
    HPX_TEST(!failed);
}

void test_thread_no_interrupt_if_interrupts_disabled_at_interruption_point()
{
    set_description("test_thread_no_interrupt_if_interrupts_disabled_at_interruption_point");
    timed_test(&do_test_thread_no_interrupt_if_interrupts_disabled_at_interruption_point, 1);
}

///////////////////////////////////////////////////////////////////////////////
struct non_copyable_functor:
    boost::noncopyable
{
    unsigned value;

    non_copyable_functor()
      : value(0)
    {}

    void operator()()
    {
        value = 999;
    }
};

void do_test_creation_through_reference_wrapper()
{
    non_copyable_functor f;

    hpx::thread thrd(boost::ref(f));
    thrd.join();
    HPX_TEST_EQ(f.value, 999u);
}

void test_creation_through_reference_wrapper()
{
    set_description("test_creation_through_reference_wrapper");
    timed_test(&do_test_creation_through_reference_wrapper, 1);
}

///////////////////////////////////////////////////////////////////////////////
// struct long_running_thread
// {
//     boost::condition_variable cond;
//     boost::mutex mut;
//     bool done;
//
//     long_running_thread()
//       : done(false)
//     {}
//
//     void operator()()
//     {
//         boost::mutex::scoped_lock lk(mut);
//         while(!done)
//         {
//             cond.wait(lk);
//         }
//     }
// };
//
// void do_test_timed_join()
// {
//     long_running_thread f;
//     hpx::thread thrd(boost::ref(f));
//     HPX_TEST(thrd.joinable());
//     boost::system_time xt=delay(3);
//     bool const joined=thrd.timed_join(xt);
//     HPX_TEST(in_range(boost::get_xtime(xt), 2));
//     HPX_TEST(!joined);
//     HPX_TEST(thrd.joinable());
//     {
//         boost::mutex::scoped_lock lk(f.mut);
//         f.done=true;
//         f.cond.notify_one();
//     }
//
//     xt=delay(3);
//     bool const joined2=thrd.timed_join(xt);
//     boost::system_time const now=boost::get_system_time();
//     HPX_TEST(xt>now);
//     HPX_TEST(joined2);
//     HPX_TEST(!thrd.joinable());
// }
//
// void test_timed_join()
// {
//     timed_test(&do_test_timed_join, 10);
// }

void simple_sync_thread(hpx::lcos::local::barrier& b1, hpx::lcos::local::barrier& b2)
{
    b1.wait();   // wait for both threads to be started
    // ... do nothing
    b2.wait();   // wait for the tests to be completed
}

void test_swap()
{
    set_description("test_swap");

    hpx::lcos::local::barrier b1(3);
    hpx::lcos::local::barrier b2(3);
    hpx::thread t1(hpx::util::bind(&simple_sync_thread, boost::ref(b1), boost::ref(b2)));
    hpx::thread t2(hpx::util::bind(&simple_sync_thread, boost::ref(b1), boost::ref(b2)));

    b1.wait();   // wait for both threads to be started

    hpx::thread::id id1 = t1.get_id();
    hpx::thread::id id2 = t2.get_id();

    t1.swap(t2);
    HPX_TEST(t1.get_id() == id2);
    HPX_TEST(t2.get_id() == id1);

    swap(t1, t2);
    HPX_TEST(t1.get_id() == id1);
    HPX_TEST(t2.get_id() == id2);

    b2.wait();   // wait for the tests to be completed

    t1.join();
    t2.join();
}

///////////////////////////////////////////////////////////////////////////////
int hpx_main(variables_map&)
{
    {
        test_sleep();
        test_creation();
        test_id_comparison();
        test_thread_interrupts_at_interruption_point();
        test_thread_no_interrupt_if_interrupts_disabled_at_interruption_point();
        test_creation_through_reference_wrapper();
        test_swap();
    }

    hpx::finalize();
    return hpx::util::report_errors();
}

///////////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[])
{
    // Configure application-specific options
    options_description cmdline("Usage: " HPX_APPLICATION_STRING " [options]");

    // Initialize and run HPX
    return hpx::init(cmdline, argc, argv);
}

max_stars_repo_name: andreasbuhr/hpx

max_issues_repo_name: andreasbuhr/hpx

max_forks_repo_name: andreasbuhr/hpx


text:
/*
 * DebugUtil.cpp
 * This file defines the utility functions which can be used for debugging purpose
 *
 *   Created on:
 *      Author: renewang
 */

#include "Global.h"
#include <boost/thread/thread.hpp>
#include <boost/thread/lock_guard.hpp>

#ifndef NDEBUG
boost::recursive_mutex _recursive_mutex;
safeostream safecerr(std::cerr, _recursive_mutex);
safeostream safecout(std::cout, _recursive_mutex);
safeostream safeclog(std::clog, _recursive_mutex);
#endif
#ifdef BOOST_ENABLE_ASSERT_HANDLER
void boost::assertion_failed(char const * expr, char const * function,
                             char const * file, long line) {
#if !defined(BOOST_NO_STDC_NAMESPACE)
  using std::printf;
#endif

  printf("Expression: %s\nFunction: %s\nFile: %s\nLine: %ld\n\n", expr,
         function, file, line);
}
//define BOOST_ENABLE_ASSERT_HANDLER
void boost::assertion_failed_msg(char const * expr, char const * msg,
                                 char const * function, char const * file,
                                 long line) {
#if !defined(BOOST_NO_STDC_NAMESPACE)
  using std::printf;
#endif

  printf("Expression: %s Message: %s\nFunction: %s\nFile: %s\nLine: %ld\n\n",
         expr, msg, function, file, line);
}
#endif
#ifndef NDEBUG
void debugmsg(char const* file, unsigned long line, char const * function,
              char const * date, char const * time) {
  DEBUG_OSTREAM<< "[DEBUG] " << file << ":" << line << " " << function
  << " [" << date << " " << time << " " << hexgame::chrono::duration_cast<hexgame::chrono::milliseconds>(hexgame::chrono::system_clock::now().time_since_epoch()).count()%1000<<"] ";
}
#endif

max_stars_repo_name: renewang/HexGame

max_issues_repo_name: renewang/HexGame

max_forks_repo_name: renewang/HexGame


text:
#include <ros/ros.h>
#include <visualization_msgs/Marker.h>
#include <visualization_msgs/MarkerArray.h>
#include <laser_node/Obstacle.h>
#include <laser_node/Obstacles.h>
#include <gvg/FollowEdgeAction.h>
#include <boost/lexical_cast.hpp>
#include <cmath>

ros::Publisher obstacles_pub;
ros::Publisher obstacles_minima_pub;
ros::Publisher obstacle_names_pub;
ros::Publisher gvg_line_pub;

void handle_follow_edge_feedback(const gvg::FollowEdgeActionFeedbackConstPtr& fbk);

int main( int argc, char** argv ) {
  ros::init(argc, argv, "follow_edge_viz");
  ros::NodeHandle nh;
  obstacle_names_pub   = nh.advertise<visualization_msgs::MarkerArray>("obstacle_names", 1);
  obstacles_pub        = nh.advertise<visualization_msgs::MarkerArray>("obstacles", 1);
  obstacles_minima_pub = nh.advertise<visualization_msgs::MarkerArray>("obstacle_minima", 1);
  gvg_line_pub         = nh.advertise<visualization_msgs::Marker>("gvg_line", 1);
  ros::Subscriber fef_sub = nh.subscribe("/indoor/gvg/follow_edge/feedback", 1, &handle_follow_edge_feedback);
  ros::spin();
  return 0;
}

void handle_follow_edge_feedback(const gvg::FollowEdgeActionFeedbackConstPtr& fbk) {
  gvg::FollowEdgeFeedback msg = fbk->feedback;
  std::string ns = "follow_edge_inputs";
  std::string frame_id = "/base_laser_link";

  laser_node::Obstacles obstacles;
  obstacles.collection.push_back(msg.left);
  obstacles.collection.push_back(msg.right);

  //ROS_INFO("dy %f", msg.dy);
  //ROS_INFO("dtheta_deg %f", msg.dtheta_in_deg);

  /*
   * Populating obstacles
   */
  visualization_msgs::MarkerArray ma;
  for (int i = 0; i < (int) obstacles.collection.size(); i++) {
    visualization_msgs::Marker m;
    m.header.frame_id = frame_id;
    m.header.stamp = ros::Time::now();
    m.ns = ns;
    m.id = i;
    m.type = visualization_msgs::Marker::LINE_STRIP;
    m.action = visualization_msgs::Marker::ADD;
    m.scale.x = 0.03;

    if (i % 2 == 0) {
      m.color.a = 1.0;   m.color.r = 0.0;   m.color.g = 1.0;  m.color.b = 0.0;
    } else {
      m.color.a = 1.0;   m.color.r = 0.0;   m.color.g = 0.0;  m.color.b = 1.0;
    }

    std::vector<geometry_msgs::Point> pts;
    for (int j = 0; j < (int) obstacles.collection.at(i).surface.size(); j++) {
      geometry_msgs::Point pt;
      pt.x = obstacles.collection.at(i).surface.at(j).x;
      pt.y = obstacles.collection.at(i).surface.at(j).y;
      pts.push_back(pt);
    }

    m.points.assign(pts.begin(), pts.end());
    m.lifetime = ros::Duration(1.0/15.0);   //1/15th of a second
    ma.markers.push_back(m);
  }

  /*
   * Populating lines from the robot to the closest points of obstacles
   */
  visualization_msgs::MarkerArray ma_closest;
  for (int i = 0; i < (int) obstacles.collection.size(); i++) {
    visualization_msgs::Marker m;
    m.header.frame_id = frame_id;
    m.header.stamp = ros::Time::now();
    m.ns = ns;
    m.id = i + (int) obstacles.collection.size();
    m.type = visualization_msgs::Marker::LINE_STRIP;
    m.action = visualization_msgs::Marker::ADD;
    m.scale.x = 0.01;

    if (i % 2 == 0) {
      m.color.a = 1.0;   m.color.r = 0.0;   m.color.g = 1.0;  m.color.b = 0.0;
    } else {
      m.color.a = 1.0;   m.color.r = 0.0;   m.color.g = 0.0;  m.color.b = 1.0;
    }

    geometry_msgs::Point origin;
    origin.x = 0; origin.y = 0;

    geometry_msgs::Point closest_pt;
    closest_pt.x = obstacles.collection.at(i).closest_point.x;
    closest_pt.y = obstacles.collection.at(i).closest_point.y;
    m.points.push_back(origin);
    m.points.push_back(closest_pt);
    m.lifetime = ros::Duration(1.0/15.0);   //1/15th of a second
    ma_closest.markers.push_back(m);
  }

  /*
   * Populating names of obstacles
   */
  visualization_msgs::MarkerArray ma_names;
  for (int i = 0; i < (int) obstacles.collection.size(); i++) {
    visualization_msgs::Marker m;
    m.header.frame_id = frame_id;
    m.header.stamp = ma.markers.at(i).header.stamp;
    m.ns = ns;
    m.id = i + (int) 2*obstacles.collection.size();
    m.type = visualization_msgs::Marker::TEXT_VIEW_FACING;
    m.action = visualization_msgs::Marker::ADD;
    m.scale.z = 0.4;
    m.text = (i == 0) ? "left" : "right";
    m.lifetime = ma.markers.at(i).lifetime;
    m.color = ma.markers.at(i).color;
    int size = (int) obstacles.collection.at(i).surface.size();
    m.pose.position.x = obstacles.collection.at(i).surface.at(floor(size/2.0)).x;
    m.pose.position.y = obstacles.collection.at(i).surface.at(floor(size/2.0)).y;
    m.pose.position.z = obstacles.collection.at(i).surface.at(floor(size/2.0)).z;
    ma_names.markers.push_back(m);
  }

  visualization_msgs::Marker m;
  m.header.frame_id = frame_id;
  m.header.stamp = ros::Time::now();
  m.ns = ns;
  m.id = 1 + (int) 3*obstacles.collection.size();
  m.type = visualization_msgs::Marker::LINE_LIST;
  m.action = visualization_msgs::Marker::ADD;
  m.scale.x = 0.01;
  m.lifetime = ros::Duration(1.0/15.0);    //1/15th of a second
  m.color.a = 1.0;   m.color.r = 1.0;   m.color.g = 0.0;  m.color.b = 0.0;

  geometry_msgs::Point leftp;
  leftp.x = msg.left.closest_point.x; leftp.y = msg.left.closest_point.y;

  geometry_msgs::Point rightp;
  rightp.x = msg.right.closest_point.x; rightp.y = msg.right.closest_point.y;

  geometry_msgs::Point startp;
  startp.x = msg.midpoint.x - 0.5*msg.normal.x;
  startp.y = msg.midpoint.y - 0.5*msg.normal.y;

  geometry_msgs::Point endp;
  endp.x = msg.midpoint.x + msg.normal.x;
  endp.y = msg.midpoint.y + msg.normal.y;

  m.points.push_back(leftp);
  m.points.push_back(rightp);
  m.points.push_back(startp);
  m.points.push_back(endp);

  obstacles_pub.publish(ma);
  obstacles_minima_pub.publish(ma_closest);
  obstacle_names_pub.publish(ma_names);
  gvg_line_pub.publish(m);
}

max_stars_repo_name: QiwenZhang/gvg

max_issues_repo_name: QiwenZhang/gvg

max_forks_repo_name: QiwenZhang/gvg


text: #include <boost/interprocess/sync/named_condition_any.hpp>

ext: hpp

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
/* test_gamma.cpp
 *
 * Copyright Steven Watanabe 2010
 * 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)
 *
 * $Id$
 *
 */

#include <boost/random/gamma_distribution.hpp>
#include <boost/random/uniform_real.hpp>
#include <boost/math/distributions/gamma.hpp>

#define BOOST_RANDOM_DISTRIBUTION boost::random::gamma_distribution<>
#define BOOST_RANDOM_DISTRIBUTION_NAME gamma
#define BOOST_MATH_DISTRIBUTION boost::math::gamma_distribution<>
#define BOOST_RANDOM_ARG1_TYPE double
#define BOOST_RANDOM_ARG1_NAME alpha
#define BOOST_RANDOM_ARG1_DEFAULT 1000.0
#define BOOST_RANDOM_ARG1_DISTRIBUTION(n) boost::uniform_real<>(0.00001, n)
#define BOOST_RANDOM_ARG2_TYPE double
#define BOOST_RANDOM_ARG2_NAME beta
#define BOOST_RANDOM_ARG2_DEFAULT 1000.0
#define BOOST_RANDOM_ARG2_DISTRIBUTION(n) boost::uniform_real<>(0.00001, n)

#include "test_real_distribution.ipp"


text:
#ifndef PACKING_CHECK_TOOLS_TCC
#define PACKING_CHECK_TOOLS_TCC

#include <boost/mpl/fold.hpp>
#include <boost/mpl/push_front.hpp>
#include <boost/mpl/list.hpp>
#include <boost/static_assert.hpp>

namespace
{
    using namespace boost::mpl;

    template<typename A, typename B>
    struct discover
    {
        typedef A First;
        typedef B Second;

        A first;
        B second;
    };

    /** Given a discover type (one of discover and discover_arrays)
     * returns the offset of second in
     *
     *   struct { First first; Second second; };
     *
     */
    template<class Discover>
    struct packingof
    {
        typedef typename Discover::First    First;
        typedef typename Discover::Second   Second;

        static const int packing = offsetof(Discover, second);
    };

    // takes a type and a typelist, and builds
    // the typelist of packingof<type, it> for each
    // type in SecondList
    template<class First, class SecondList>
    struct iterate_second
    {
        typedef typename fold
            < SecondList
            , list<>
            , push_front< _1, packingof< discover<First, _2> > >
            >::type type;
    };

    typedef list<char, short, int, long, float, double, char*> podlist;

    template<class Packing>
    struct is_same_as_simple
    {
        BOOST_STATIC_ASSERT((
            Packing::packing ==
            packingof
                < discover
                    < typename Packing::First
                    , typename Packing::Second
                    >
                >::packing
            ));
    };
}

#endif

ext: tcc

max_stars_repo_name: meyerj/typelib

max_issues_repo_name: meyerj/typelib

max_forks_repo_name: meyerj/typelib


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

#include "solver_options.hpp"
#include <cstdlib>
#include <string>
#include <iostream>
#include <boost/program_options.hpp>

namespace po = boost::program_options;

SolverOptions::SolverOptions(const std::string& fileDesc) : description("Allowed Options")
{
  description.add_options()
    ("help", "produce help message")
    ("iterations", po::value<int>(&iterations)->default_value(256), "number of iterations to perform")
    ("sparse", "use sparse representation for matrix storage")
    ("single-line-result", "print statistics on single line")
    ("format", po::value<std::string>(&format)->default_value("hb"), "format of input file: Harwell-Boeing=hb, Matrix-Market=mm")
    ("input-file", po::value<std::string>(), fileDesc.c_str());

  positional_description.add("input-file", -1);
}

void SolverOptions::processOptions(int argc, char* argv[])
{
  po::store(po::parse_command_line(argc, argv, description), vm);
  po::store(po::command_line_parser(argc, argv).options(description).
                                  positional(positional_description).run(), vm);
  po::notify(vm);

  if (vm.count("help"))
  {
    std::cout << std::endl << description << std::endl;
    exit(EXIT_SUCCESS);
  }

  if (vm.count("input-file") == 0)
  {
    std::cerr << std::endl << description << std::endl;
    std::cerr << "Please supply input file!" << std::endl << std::endl;
    exit(EXIT_FAILURE);
  }
}

std::string SolverOptions::getFile() const
{
  return vm["input-file"].as<std::string>();
}

bool SolverOptions::singleLineResult() const
{
  return vm.count("single-line-result") > 0;
}

bool SolverOptions::useSparse() const
{
  return vm.count("sparse") > 0;
}

int SolverOptions::getIterations() const
{
  return iterations;
}

bool SolverOptions::fileIsHB() const
{
  return format=="hb";
}

bool SolverOptions::fileIsMM() const
{
  return format=="mm";
}

max_stars_repo_name: FrancisRussell/desola

max_issues_repo_name: FrancisRussell/desola

max_forks_repo_name: FrancisRussell/desola


text:
// ----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
#pragma once

#include "stdafx.h"

#include <boost/test/unit_test.hpp>
#include "Common/boost-taef.h"
#include "ReliableConcurrentQueue.h"
#include "ReliableConcurrentQueue.TestBase.h"
#include "../tstore/TStoreTestBase.h"

namespace ReliableConcurrentQueueTests
{
    using namespace ktl;
    using namespace Data::TStore;
    using namespace Data::Utilities;

    class UndoFalseProgressTest : public ReliableConcurrentQueueTestBase<int>
    {
    public:
        UndoFalseProgressTest()
        {
            NTSTATUS status = TestStateSerializer<LONG64>::Create(GetAllocator(), long64SerializerSPtr_);
            Diagnostics::Validate(status);
            status = TestStateSerializer<int>::Create(GetAllocator(), intSerializerSPtr_);
            Diagnostics::Validate(status);
        }

        ~UndoFalseProgressTest()
        {
            long64SerializerSPtr_ = nullptr;
            intSerializerSPtr_ = nullptr;
        }

        OperationData::SPtr GetBytes(__in LONG64 value)
        {
            Utilities::BinaryWriter binaryWriter(GetAllocator());
            long64SerializerSPtr_->Write(value, binaryWriter);

            OperationData::SPtr operationDataSPtr = OperationData::Create(this->GetAllocator());
            operationDataSPtr->Append(*binaryWriter.GetBuffer(0));

            return operationDataSPtr;
        }

        OperationData::SPtr GetBytes(__in int value)
        {
            Utilities::BinaryWriter binaryWriter(GetAllocator());
            intSerializerSPtr_->Write(value, binaryWriter);

            OperationData::SPtr operationDataSPtr = OperationData::Create(this->GetAllocator());
            operationDataSPtr->Append(*binaryWriter.GetBuffer(0));

            return operationDataSPtr;
        }

        void SecondaryUndoFalseProgress(
            __in LONG64 sequenceNumber,
            __in StoreModificationType::Enum operationType,
            __in LONG64 key)
        {
            KAllocator& allocator = GetAllocator();

            Transaction::SPtr tx = CreateReplicatorTransaction();
            Transaction::CSPtr txnCSPtr = tx.RawPtr();
            tx->CommitSequenceNumber = sequenceNumber;

            OperationData::SPtr keyBytes = GetBytes(key);

            OperationData::CSPtr metadataCSPtr = nullptr;

            KSharedPtr<MetadataOperationDataK<LONG64> const> metadataKCSPtr = nullptr;
            NTSTATUS status = MetadataOperationDataK<LONG64>::Create(
                key,
                Constants::SerializedVersion,
                operationType,
                txnCSPtr->TransactionId,
                keyBytes,
                allocator,
                metadataKCSPtr);
            Diagnostics::Validate(status);
            metadataCSPtr = static_cast<const OperationData* const>(metadataKCSPtr.RawPtr());

            auto operationContext = SyncAwait(RCQ->ApplyAsync(
                sequenceNumber,
                *txnCSPtr,
                ApplyContext::SecondaryFalseProgress,
                metadataCSPtr.RawPtr(),
                nullptr));

            if (operationContext != nullptr)
            {
                RCQ->Unlock(*operationContext);
            }
        }

        void UndoFalseProgressAdd(__in LONG64 sequenceNumber, __in LONG64 key)
        {
            SecondaryUndoFalseProgress(sequenceNumber, StoreModificationType::Enum::Add, key);
        }

        void UndoFalseProgressUpdate(__in LONG64 sequenceNumber, __in LONG64 key)
        {
            SecondaryUndoFalseProgress(sequenceNumber, StoreModificationType::Enum::Update, key);
        }

        void UndoFalseProgressRemove(__in LONG64 sequenceNumber, __in LONG64 key)
        {
            SecondaryUndoFalseProgress(sequenceNumber, StoreModificationType::Enum::Remove, key);
        }

        Common::CommonConfig config; // load the config object as its needed for the tracing to work

    private:
        KtlSystem* ktlSystem_;
        KSharedPtr<TestStateSerializer<LONG64>> long64SerializerSPtr_;
        KSharedPtr<TestStateSerializer<int>> intSerializerSPtr_;
    };

    BOOST_FIXTURE_TEST_SUITE(UndoFalseProgressTestSuite, UndoFalseProgressTest)

    BOOST_AUTO_TEST_CASE(UndoFalseProgress_Single_Enqueue_ShouldSucceed)
    {
        LONG64 undoSequenceNumber = -1;

        {
            auto txn = CreateReplicatorTransaction();
            KFinally([&] { txn->Dispose(); });

            SyncAwait(RCQ->EnqueueAsync(*txn, 10, Common::TimeSpan::MaxValue, CancellationToken::None));
            SyncAwait(txn->CommitAsync());

            undoSequenceNumber = txn->CommitSequenceNumber;
        }

        UndoFalseProgressAdd(undoSequenceNumber, 1);

        SyncExpectEmpty();
    }

    BOOST_AUTO_TEST_CASE(UndoFalseProgress_Multiple_Enqueue_ShouldSucceed)
    {
        LONG64 undoSequenceNumber = -1;

        SyncEnqueueItem(10);
        SyncEnqueueItem(20);
        SyncEnqueueItem(30);

        {
            auto txn = CreateReplicatorTransaction();
            KFinally([&] { txn->Dispose(); });

            SyncAwait(RCQ->EnqueueAsync(*txn, 40, Common::TimeSpan::MaxValue, CancellationToken::None));
            SyncAwait(txn->CommitAsync());

            undoSequenceNumber = txn->CommitSequenceNumber;
        }

        UndoFalseProgressAdd(undoSequenceNumber, 4);

        SyncExpectDequeue(10);
        SyncExpectDequeue(20);
        SyncExpectDequeue(30);
        SyncExpectEmpty();
    }

    BOOST_AUTO_TEST_CASE(UndoFalseProgress_Single_Dequeue_ShouldSucceed)
    {
        LONG64 undoSequenceNumber = -1;

        SyncEnqueueItem(10);

        {
            auto txn = CreateReplicatorTransaction();
            KFinally([&] { txn->Dispose(); });

            int value;
            bool succeeded = SyncAwait(RCQ->TryDequeueAsync(*txn, value, Common::TimeSpan::MaxValue, CancellationToken::None));
            CODING_ERROR_ASSERT(succeeded);
            CODING_ERROR_ASSERT(value == 10);;

            SyncAwait(txn->CommitAsync());

            undoSequenceNumber = txn->CommitSequenceNumber;
        }

        UndoFalseProgressRemove(undoSequenceNumber, 1);

        SyncExpectDequeue(10);
        SyncExpectEmpty();
    }

    BOOST_AUTO_TEST_CASE(UndoFalseProgress_Multiple_Dequeue_ShouldSucceed)
    {
        LONG64 undoSequenceNumber = -1;

        SyncEnqueueItem(10);
        SyncEnqueueItem(20);
        SyncEnqueueItem(30);

        {
            auto txn = CreateReplicatorTransaction();
            KFinally([&] { txn->Dispose(); });

            int value;
            bool succeeded = SyncAwait(RCQ->TryDequeueAsync(*txn, value, Common::TimeSpan::MaxValue, CancellationToken::None));
            CODING_ERROR_ASSERT(succeeded);
            CODING_ERROR_ASSERT(value == 10);

            SyncAwait(txn->CommitAsync());

            undoSequenceNumber = txn->CommitSequenceNumber;
        }

        UndoFalseProgressRemove(undoSequenceNumber, 1);

        SyncExpectDequeue(20);
        SyncExpectDequeue(30);
        SyncExpectDequeue(10);
        SyncExpectEmpty();
    }

    BOOST_AUTO_TEST_CASE(UndoFalseProgress_Enqueue_Dequeue_ShouldSucceed)
    {
        LONG64 undoSequenceNumber = -1;

        SyncEnqueueItem(10);
        SyncEnqueueItem(20);
        SyncEnqueueItem(30);

        SyncExpectDequeue(10);
        SyncEnqueueItem(40);

        {
            auto txn = CreateReplicatorTransaction();
            KFinally([&] { txn->Dispose(); });

            SyncAwait(RCQ->EnqueueAsync(*txn, 50, Common::TimeSpan::MaxValue, CancellationToken::None));

            int value;
            bool succeeded = SyncAwait(RCQ->TryDequeueAsync(*txn, value, Common::TimeSpan::MaxValue, CancellationToken::None));
            CODING_ERROR_ASSERT(succeeded);
            CODING_ERROR_ASSERT(value == 20);

            SyncAwait(txn->CommitAsync());

            undoSequenceNumber = txn->CommitSequenceNumber;
        }

        UndoFalseProgressRemove(undoSequenceNumber, 2);
        UndoFalseProgressAdd(undoSequenceNumber, 5);

        SyncExpectDequeue(30);
        SyncExpectDequeue(40);
        SyncExpectDequeue(20);
        SyncExpectEmpty();
    }

    BOOST_AUTO_TEST_SUITE_END()
}

max_stars_repo_name: gridgentoo/ServiceFabricAzure

max_issues_repo_name: gridgentoo/ServiceFabricAzure

max_forks_repo_name: gridgentoo/ServiceFabricAzure


text:
#ifndef _GAIT_LOGGER_HPP
#define _GAIT_LOGGER_HPP

#include <unordered_map>
#include <vector>
#include <Eigen/Core>

namespace raisim {

class GaitLogger {

 public:
  GaitLogger() = default;

  void init(int size = 0) {
    clean();
    if(size != 0){
      for(size_t i = 0; i < 4; i++) {
        contactStates_[i].reserve(size);
      }
      phases_.reserve(size);
    }
  }

  void clean() {
    for(size_t i = 0; i < 4; i++) {
      contactStates_[i].clear();
    }
    phases_.clear();
  }

  void appendContactStates(std::array<bool,4> & in){
    for(size_t i = 0; i < 4; i++){
      contactStates_[i].push_back((float)in[i]);
    }
  }

//  void appendPhases(std::array<double,4> & in){
//    phases_.push_back(in);
//  }

  std::vector<float> contactStates_[4];
  std::vector<std::array<float, 4>> phases_;
};

};
#endif //_RAISIM_GYM_REWARDLOGGER_HPP