text:
/*
 * Copyright (c) 2017-2018
 *
 *  Dmytro Iakovliev daemondzk@gmail.com
 *  Oleksii Kogutenko https://github.com/oleksii-kogutenko
 *
 * 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 <organization> 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 Dmytro Iakovliev daemondzk@gmail.com ''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 Dmytro Iakovliev daemondzk@gmail.com BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <ctime>
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <vector>
#include <gavc.h>
#include <gavccache.h>
#include "gavcconstants.h"
#include <gavcversionsfilter.h>
#include <gavcversionsrangefilter.h>
#include <gavcversionscomparator.h>
#include <artbaseconstants.h>
#include <artbasedownloadhandlers.h>
#include <artgavchandlers.h>
#include <logging.h>
#include <mavenmetadata.h>
#include <artbaseapihandlers.h>
#include <properties.h>

#include <boost/bind.hpp>
#include <boost_property_tree_ext.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/predicate.hpp>

namespace al = art::lib;
namespace pl = piel::lib;
namespace fs = boost::filesystem;
namespace pt = boost::property_tree;
namespace po = boost::program_options;

namespace piel { namespace cmd {

GAVCCache::GAVCCache(const std::string& server_api_access_token
           , const std::string& server_url
           , const std::string& server_repository
           , const art::lib::GavcQuery& query
           , const bool have_to_download_results
           , const std::string &cache_path
           , const std::string& output_file
           , const std::string& notifications_file
           , unsigned int max_attempts
           , unsigned int retry_timeout_s
           , bool force_offline)
    : pl::IOstreamsHolder()
    , server_url_(server_url)
    , server_api_access_token_(server_api_access_token)
    , server_repository_(server_repository)
    , query_(query)
    , path_to_download_()
    , have_to_download_results_(have_to_download_results)
    , output_file_(output_file)
    , cache_path_(cache_path)
    , max_attempts_(max_attempts)
    , retry_timeout_s_(retry_timeout_s)
    , notifications_file_(notifications_file)
    , force_offline_(force_offline)
    , query_results_()
    , list_of_queued_files_()
{
}

GAVCCache::~GAVCCache()
{
}

std::vector<std::string> GAVCCache::get_cached_versions(const std::string& path) const
{
    std::vector<std::string> result;

    if(!fs::is_directory(path)) {
        throw piel::cmd::errors::cache_folder_does_not_exist(path);
    }

    for(auto entry : boost::make_iterator_range(fs::directory_iterator(path), {})){
        LOGT << entry.path().filename().c_str() << ELOG;
        if(fs::is_directory(entry)) {
            result.push_back(entry.path().filename().c_str());
        }
    }

    if (result.empty()) {
        LOGT << "Nothing in cache for query." << ELOG;
        return result;
    }

    return query_.filter(result);
}

std::vector<std::string> GAVCCache::get_cached_classifiers_list(const std::string& artifacts_cache) {
    std::vector<std::string> result;

    for(auto entry : boost::make_iterator_range(fs::directory_iterator(artifacts_cache), {})){
        LOGT << entry.path().filename().c_str() << ELOG;
        if(!fs::is_regular_file(entry.path())) {
            continue;
        }

        if (!boost::algorithm::ends_with(entry.path().filename().string(), GAVCConstants::properties_ext)) {
            continue;
        }

        std::ifstream is(entry.path().string());
        pl::Properties props = pl::Properties::load(is);

        std::string classifier = props.get(GAVCConstants::object_classifier_property, "");
        if (classifier.empty())
            continue;

        LOGT << "Cached classifier: " << classifier << ELOG;
        result.push_back(classifier);
    }

    return result;
}

std::string GAVCCache::find_file_for_classifier(const std::string& artifacts_cache, const std::string& classifier)
{
    std::string result;

    for(auto entry : boost::make_iterator_range(fs::directory_iterator(artifacts_cache), {})){
        LOGT << entry.path().filename().c_str() << ELOG;
        if(!fs::is_regular_file(entry.path())) {
            continue;
        }

        if (!boost::algorithm::ends_with(entry.path().filename().string(), GAVCConstants::properties_ext)) {
            continue;
        }

        std::ifstream is(entry.path().string());
        pl::Properties props = pl::Properties::load(is);

        if(props.get(GAVCConstants::object_classifier_property, "") == classifier) {
            result = artifacts_cache + fs::path::preferred_separator + props.get(GAVCConstants::object_id_property, "");
            break;
        }
    }

    return result;
}

/*static*/ std::string GAVCCache::now_string()
{
    std::ostringstream buffer;
    std::time_t tm = std::time(nullptr);
    buffer << std::put_time(std::localtime(&tm), GAVCConstants::last_access_time_format.c_str());
    return buffer.str();
}

/*static*/ void GAVCCache::update_last_access_time(const fs::path& cache_object_path)
{
    pl::Properties props = GAVC::load_object_properties(cache_object_path);
    std::ostringstream buffer;
    buffer << now_string();
    props.set(GAVCConstants::last_access_time_property, buffer.str());
    GAVC::store_object_properties(cache_object_path, props);
}

/*static*/ std::tm GAVCCache::get_last_access_time(const fs::path& cache_object_path)
{
    pl::Properties props = GAVC::load_object_properties(cache_object_path);
    std::tm t = {};
    std::istringstream ss(props.get(GAVCConstants::last_access_time_property, now_string()));
    ss >> std::get_time(&t, GAVCConstants::last_access_time_format.c_str());

    t.tm_isdst = 1;

    return t;
}

GAVC::paths_list GAVCCache::get_cached_files_list(const std::vector<std::string>& versions_to_process, const std::string& path)
{
    std::string classifier_spec = query_.classifier();
    std::string query_name      = query_.name();

    std::vector<std::string> classifiers;

    boost::split(classifiers, classifier_spec, boost::is_any_of(","));
    bool have_errors = false;

    GAVC::paths_list results;

    for (auto ver = versions_to_process.begin(), end = versions_to_process.end(); ver != end; ++ver)
    {
        LOGT << "Version: " << *ver << ELOG;

        std::string artifact_cache_path = path + fs::path::preferred_separator + *ver;

        LOGT << "Version cache: " << artifact_cache_path << ELOG;

        if (classifiers.size() == 1 && classifiers[0].empty()) {
            classifiers = get_cached_classifiers_list(artifact_cache_path);
        }

        for (auto it = classifiers.begin(), cend = classifiers.end(); it != cend; ++it)
        {
            std::vector<std::string> craw_parts;
            boost::split(craw_parts, *it, boost::is_any_of("."));

            std::string c = craw_parts[0];

            if (c.empty()) {
                LOGT << "empty classifier " << ELOG;
                continue;
            }

            std::string file_path               = find_file_for_classifier(artifact_cache_path, c);
            std::string classifier_file_name    = fs::path(file_path).filename().string();

            LOGT << "Classifier: " << c << " path: " << file_path << ELOG;

            if (!fs::is_regular_file(file_path)) {
                LOGT << "No file: " << file_path << " for classifier: " << c << ELOG;

                have_errors = true;
                break;
            }

            pl::Properties props    = GAVC::load_object_properties(file_path);
            bool is_valid           = GAVC::validate_local_file(file_path, props);

            if (!is_valid) {
                LOGT << "File: " << file_path  << " for classifier: " << c << " is not valid!" << ELOG;

                have_errors = true;
                break;
            }

            if (std::find(results.begin(), results.end(), file_path) == results.end()) {
                results.push_back(file_path);
            }
        }
    }

    if (have_errors)
        return GAVC::paths_list();

    return results;
}

/*static*/ std::string GAVCCache::cache_properties_file(const std::string& cache_path)
{
    return cache_path + fs::path::preferred_separator + GAVCConstants::cache_properties_filename;
}

/*static*/ void GAVCCache::init(const std::string& cache_path)
{
    if (!fs::is_directory(cache_path) || !fs::exists(cache_path)) {
        fs::remove_all(cache_path);
        fs::create_directories(cache_path);
    }

    pl::Properties props = pl::Properties();
    props.set(GAVCConstants::cache_version_property, GAVCConstants::cache_version);

    std::ofstream os(cache_properties_file(cache_path));
    props.store(os);
}

/*static*/ bool GAVCCache::validate(const std::string& cache_path)
{
    std::string properties_file = cache_properties_file(cache_path);
    if (!fs::is_regular_file(properties_file)) {
        return false;
    }

    std::ifstream is(properties_file);
    pl::Properties props = pl::Properties::load(is);
    return GAVCConstants::cache_version == props.get(GAVCConstants::cache_version_property, "");
}

bool GAVCCache::is_force_offline() const
{
    bool offline            = force_offline_;
    if (!offline) {
        const char *offline_str = ::getenv("PIE_GAVC_FORCE_OFFLINE");
        if (offline_str) {
            offline = std::string(offline_str) == "1" || std::string(offline_str) == "true";
        }
    }
    LOGT << "Force offline mode: " << offline << ELOG;
    return offline;
}

void GAVCCache::perform()
{
    if (!validate(cache_path_)) {
        try {
            fs::remove_all(cache_path_);
        } catch (...) {}
        init(cache_path_);
    }

    piel::cmd::GAVC gavc(
         server_api_access_token_,
         server_url_,
         server_repository_,
         query_,
         have_to_download_results_,
         "",
         notifications_file_);

    gavc.set_cache_mode(true);

    LOGT << " gavc.get_maven_metadata_path:"    << gavc.get_maven_metadata_path()   << ELOG;

    std::string mm_path = cache_path_ + gavc.get_maven_metadata_path();

    LOGT << " cache_path_:"                     << cache_path_                      << ELOG;
    LOGT << " mm_path:"                         << mm_path                          << ELOG;

    std::vector<std::string> versions_to_process_remote;
    std::vector<std::string> versions_to_process_cache;
    std::vector<std::string> versions_to_process;

    bool force_offline      = is_force_offline();
    bool offline            = force_offline;
    bool have_cached_files  = false;

    if (!offline) {
        try {
            versions_to_process_remote  = gavc.get_versions_to_process();
        }
        catch (piel::cmd::errors::no_server_maven_metadata& e) {
            // No server metadata. Force use cache.
            offline                     = true;
        }
    }

    GAVC::paths_list list_files;

    try {
        versions_to_process_cache   = get_cached_versions(mm_path);
        // Initial cache files list
        list_files                  = get_cached_files_list(versions_to_process_cache, mm_path);
        have_cached_files           = !list_files.empty();
    } catch (errors::cache_folder_does_not_exist& e) {
        // Don't see anything in cache.
    }

    LOGT << "force_offline: " << force_offline << " offline: " << offline << " have_cached_files: " << have_cached_files << ELOG;

    if (offline) {
        for (auto ver = versions_to_process_cache.begin(), end = versions_to_process_cache.end(); ver != end; ++ver) {
            cout() << "Version: " << *ver << std::endl;
            if (force_offline) {
                cout() << "Mode: force offline"     << std::endl;
            } else {
                cout() << "Mode: offline"           << std::endl;
            }

            gavc.notify_gavc_version(*ver);
        }

        versions_to_process = versions_to_process_cache;
    } else {
        for (auto i = versions_to_process_remote.begin(), end = versions_to_process_remote.end(); i != end; ++i) {
            LOGT << "Version: " << *i << ELOG;

            std::string path = mm_path + "/" + *i;

            gavc.set_path_to_download(path);
            gavc.process_version(*i);

            // Get actial files list
            list_files = gavc.get_list_of_actual_files();
        }

        versions_to_process = versions_to_process_remote;
    }

    if (offline) {
        for (GAVC::paths_list::iterator f = list_files.begin(), end = list_files.end(); f != end; ++f) {

            fs::path object_name        = fs::path(*f).filename();

            LOGT << *f << "->" << object_name << ELOG;

            cout() << "c " << object_name.string() << std::endl;
        }
    }

    if (have_to_download_results_) {

        if (offline && !have_cached_files) {
            throw errors::cache_no_cache_for_query(query_.to_string());
        }

        for (GAVC::paths_list::iterator f = list_files.begin(), end = list_files.end(); f != end; ++f) {

            fs::path path        = output_file_.empty()         ?   fs::path(*f).filename() : output_file_                          ;
            fs::path object_path = path_to_download_.empty()    ?   path                    : path_to_download_ / path.filename()   ;

            LOGT << *f << "->" << object_path << ELOG;

            cout() << "+ " << object_path.filename().string() << std::endl;

            fs::copy_file(*f, object_path, fs::copy_option::overwrite_if_exists);
            update_last_access_time(*f);

            pl::Properties props    = GAVC::load_object_properties(*f);

            std::string object_classifier = props.get(GAVCConstants::object_classifier_property, "");
            std::string version = fs::path(*f).parent_path().filename().string();

            query_results_.insert(std::make_pair(object_path, std::make_pair(object_classifier, version)));
            list_of_queued_files_.push_back(object_path.string());
        }
    }
}

void GAVCCache::operator()()
{
    unsigned int        attempt = 0;
    const unsigned int  max_attempts  = std::max(1u, max_attempts_);
    const unsigned int  retry_timeout = std::max(5u, retry_timeout_s_);
    while(true) {
        try {
            LOGT << "GAVCCache query attempt: " << attempt << " from: " << max_attempts << " start." << ELOG;
            perform();
            LOGT << "GAVCCache query attempt: " << attempt << " success." <<  ELOG;
            break;
        } catch (...) {
            LOGT << "GAVCCache query attempt: " << attempt << " from: " << max_attempts << " failed." <<  ELOG;
            if (attempt++ >= max_attempts) {
                LOGT << "GAVCCache rethrow." << ELOG;
                throw;
            } else {
                LOGT << "GAVCCache sleep: " << retry_timeout << "s." <<  ELOG;
                sleep(retry_timeout);
            }
        }
    }
}

void GAVCCache::set_path_to_download(const boost::filesystem::path& path)
{
    path_to_download_ = path;
}

boost::filesystem::path GAVCCache::get_path_to_download() const
{
    return path_to_download_;
}

GAVC::query_results GAVCCache::get_query_results() const
{
    return query_results_;
}

GAVC::paths_list GAVCCache::get_list_of_queued_files() const
{
    return list_of_queued_files_;
}

} } // namespace piel::cmd

max_stars_repo_name: diakovliev/pie

max_issues_repo_name: diakovliev/pie

max_forks_repo_name: diakovliev/pie


text:
/*************************************************************************
 * odil - Copyright (C) Universite de Strasbourg
 * Distributed under the terms of the CeCILL-B license, as published by
 * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
 * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
 * for details.
 ************************************************************************/

#include "odil/webservices/STOWRSRequest.h"

#include <sstream>

#include <boost/lexical_cast.hpp>
#include <boost/fusion/include/std_pair.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/uuid/random_generator.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/version.hpp>

#include <json/json.h>

#include "odil/DataSet.h"
#include "odil/json_converter.h"
#include "odil/Reader.h"
#include "odil/VRFinder.h"
#include "odil/Writer.h"
#include "odil/webservices/ItemWithParameters.h"
#include "odil/webservices/multipart_related.h"
#include "odil/webservices/Selector.h"
#include "odil/webservices/Utils.h"
#include "odil/webservices/URL.h"
#include "odil/xml_converter.h"

namespace  odil
{

namespace webservices
{

STOWRSRequest
::STOWRSRequest(URL const & base_url)
    : _base_url(base_url), _transfer_syntax(""), _selector(), _url(),
      _media_type(""), _representation(), _data_sets()
{
    // Nothing else.
}

STOWRSRequest
::STOWRSRequest(HTTPRequest const & request)
{
    this->_url = request.get_target();
    if (request.has_header("Host"))
    {
        this->_url.authority = request.get_header("Host");
    }

    // find the media type in Content-Type header
    if (!request.has_header("Content-Type"))
    {
        throw Exception("Cannot parse request : Content-Type header is missing");
    }
    auto const header_content_type = boost::lexical_cast<ItemWithParameters>(
        request.get_header("Content-Type"));
    if (header_content_type.name == "multipart/related")
    {
        auto const it = header_content_type.name_parameters.find("type");
        if(it == header_content_type.name_parameters.end())
        {
            std::ostringstream message;
            message << "Missing type is Accept header :"
                    << request.get_header("Accept");
            throw Exception(message.str());
        }
        this->_media_type = it->second;
    }
    else
    {
        throw Exception("Malformed Content-Type header");
    }

    if (this->_media_type == "application/dicom")
    {
        this->_representation = Representation::DICOM;
        auto const converter =
            [](Message const & part)
            {
                std::stringstream stream(part.get_body());
                Reader reader(stream, odil::registry::ExplicitVRLittleEndian);
                auto const ds = reader.read_file(stream);
                return ds.second;
            };
        transform_parts(
            request, std::back_inserter(this->get_data_sets()), converter);
    }
    else if (this->_media_type == "application/dicom+xml")
    {
        this->_representation = Representation::DICOM_XML;
        std::map< std::string, std::string> uuid_to_bulk_raw;

        auto converter_part =
            [&uuid_to_bulk_raw, this](Message const & part)
            {
                auto const header_content_type = boost::lexical_cast<ItemWithParameters>(
                    part.get_header("Content-Type"));
                if (header_content_type.name == "application/dicom+xml")
                {
                    // get the transfer syntax in the ContentType header
                    auto const transfer_syntax_it = header_content_type.name_parameters.find(
                        "transfer-syntax");
                    if(transfer_syntax_it != header_content_type.name_parameters.end())
                    {
                        this->_transfer_syntax = transfer_syntax_it->second;
                    }
                    else
                    {
                        throw Exception("Transfer-syntax option is missing in the header");
                    }
                    // Check here if correct probably ok
                    std::stringstream stream(part.get_body());
                    boost::property_tree::ptree xml;
                    boost::property_tree::read_xml(stream, xml);
                    this->get_data_sets().push_back(as_dataset(xml));
                }
                else
                {
                    auto const location = part.get_header("Content-Location");
                    uuid_to_bulk_raw.insert(std::make_pair(location, part.get_body()));
                }
            };

        for_each_part(request, converter_part);

        // Here restore dataSets to their initial states (With Bulk Data in the correct location)
        for (auto & data_set : this->get_data_sets())
        {
            STOWRSRequest::_restore_data_set(data_set, uuid_to_bulk_raw);
        }
    }
    else if (this->_media_type == "application/dicom+json")
    {
        this->_representation = Representation::DICOM_JSON;
        std::map< std::string, std::string> uuid_to_bulk_raw;

        auto converter_part =
            [&uuid_to_bulk_raw, this](Message const & part)
            {
                auto const header_content_type = boost::lexical_cast<ItemWithParameters>(
                    part.get_header("Content-Type"));
                if (header_content_type.name == "application/dicom+json")
                {
                    // get the transfer syntax in the ContentType header
                    auto const transfer_syntax_it = header_content_type.name_parameters.find(
                        "transfer-syntax");
                    if(transfer_syntax_it != header_content_type.name_parameters.end())
                    {
                        this->_transfer_syntax = transfer_syntax_it->second;
                    }
                    else
                    {
                        throw Exception("Transfer-syntax option is missing in the header");
                    }
                    std::stringstream stream(part.get_body());
                    Json::Value array;
                    stream >> array;
                    if(!array.isArray())
                    {
                        throw Exception("Body must be an array");
                    }
                    for (auto const json : array)
                    {
                        this->get_data_sets().push_back(as_dataset(json));
                    }
                }
                else
                {
                    auto const location = part.get_header("Content-Location");
                    uuid_to_bulk_raw.insert(std::make_pair(location, part.get_body()));
                }
            };
        for_each_part(request, converter_part);

        // Here restore dataSets to their initial state (With Bulk Data in the correct location)
        for (auto & data_set : this->get_data_sets())
        {
            STOWRSRequest::_restore_data_set(data_set, uuid_to_bulk_raw);
        }
    }
    else
    {
        throw Exception("Unknown media type" + this->_media_type);
    }
    std::tie(this->_base_url, this->_selector) =
            STOWRSRequest::_split_full_url(this->_url);
}

bool
STOWRSRequest
::operator==(STOWRSRequest const & other) const
{
    return(
        this->_base_url == other._base_url
        && this->_transfer_syntax == other._transfer_syntax
        && this->_selector == other._selector
        && this->_url == other._url
        && this->_data_sets == other._data_sets
        && this->_representation == other._representation
        && this->_media_type == other._media_type);
}

bool
STOWRSRequest
::operator!=(STOWRSRequest const & other) const
{
    return !(*this == other);
}

std::pair<URL, Selector>
STOWRSRequest
::_split_full_url(URL const &url)
{
    URL base_url;

    std::string study;
    auto const position = url.path.rfind("/studies");

    if (position != std::string::npos)
    {
        base_url = {
            url.scheme, url.authority, url.path.substr(0, position), "", "" };
        auto const resource = url.path.substr(position+1);

        typedef std::string::const_iterator Iterator;

        namespace qi = boost::spirit::qi;
        namespace p = boost::phoenix;

        using boost::spirit::qi::char_;
        using boost::spirit::qi::lit;
        using boost::spirit::qi::string;
        using boost::spirit::qi::_1;

        qi::rule<Iterator, std::string()> value = +(~char_("/"));

        qi::rule<Iterator> retrieve_study =
            lit("studies/") >> value[p::ref(study) = _1];

        auto iterator = resource.begin();
        qi::phrase_parse(
            iterator, resource.end(),
            retrieve_study,
            boost::spirit::qi::ascii::space
        );
    }

    Selector selector({{"studies", study}});

    return std::make_pair(base_url, selector);
}

bool
STOWRSRequest
::_is_selector_valid(Selector const & selector)
{
    return (selector.is_study_present() && !selector.is_series_present()
            && !selector.is_instance_present() && selector.get_frames().empty());
}

void
STOWRSRequest
::request_dicom(std::vector<DataSet> const & data_sets, Selector const & selector,
                Representation const & representation, std::string const & transfer_syntax)
{
    switch (representation)
    {
    case Representation::DICOM :
        this->_representation = Representation::DICOM;
        this->_media_type = "application/dicom";
        break;
    case Representation::DICOM_XML :
        this->_representation = Representation::DICOM_XML;
        this->_media_type = "application/dicom+xml";
        this->_transfer_syntax = transfer_syntax;
        break;
    case Representation::DICOM_JSON :
        this->_representation = Representation::DICOM_JSON;
        this->_media_type = "application/dicom+json";
        this->_transfer_syntax = transfer_syntax;
        break;
    default :
        throw Exception("Invalid representation");
        break;
    }

    this->_data_sets = data_sets;
    if (!_is_selector_valid(selector))
    {
        throw Exception("Selector is not valid (" + selector.get_path(false) + ")");
    }
    this->_selector = selector;
    auto path = this->_base_url.path + selector.get_path(false);
    this->_url = {
        this->_base_url.scheme, this->_base_url.authority, path, "", ""};
}

std::vector<DataSet> const &
STOWRSRequest
::get_data_sets() const
{
    return _data_sets;
}

std::vector<DataSet> &
STOWRSRequest
::get_data_sets()
{
    return this->_data_sets;
}

URL const &
STOWRSRequest
::get_base_url() const
{
    return this->_base_url;
}

void
STOWRSRequest
::set_base_url(URL const & url)
{
    this->_base_url = url;
}

std::string const &
STOWRSRequest
::get_transfer_syntax() const
{
    return this->_transfer_syntax;
}

void
STOWRSRequest
::set_transfer_syntax(std::string const & transfer_syntax)
{
    this->_transfer_syntax = transfer_syntax;
}

std::string const &
STOWRSRequest
::get_media_type() const
{
    return this->_media_type;
}

Representation const &
STOWRSRequest
::get_representation() const
{
    return this->_representation;
}

URL const &
STOWRSRequest
::get_url() const
{
    return this->_url;
}

Selector const &
STOWRSRequest
::get_selector() const
{
    return this->_selector;
}

HTTPRequest
STOWRSRequest
::get_http_request() const
{
    HTTPRequest request;
    if(this->_representation == Representation::DICOM)
    {
        auto const accumulator =
            [](DataSet const & data_set)
            {
                std::ostringstream stream(
                    std::ios_base::out | std::ios_base::binary);
                odil::Writer::write_file(
                    data_set, stream, DataSet());
                return Message(
                    {
                        {
                            "Content-Type",
                            ItemWithParameters(
                            "application/dicom",
                            {})
                        }
                    },
                    stream.str()
                );
            };
        auto const boundary = random_boundary();
        std::ostringstream body;
        accumulate_parts(
            this->get_data_sets().begin(), this->get_data_sets().end(),
            accumulator, body, boundary);
        request.set_body(body.str());

        request.set_header(
            "Content-Type",
            ItemWithParameters(
                "multipart/related", {
                            {"type", "application/dicom"},
                            {"boundary", boundary}}));
    }
    else if(this->_representation == Representation::DICOM_JSON)
    {
        std::vector<BulkData> bulk_data;

        // Copy the dataSets in order to let them unchanged
        std::vector<odil::DataSet> copy = this->_data_sets;
        for (auto & ds :copy)
        {
            STOWRSRequest::_extract_bulk_data(ds, bulk_data);
        }
        auto const accumulator_bulk_data =
            [](BulkData const & bulk_data)
            {
                return Message(
                    {
                        { "Content-Type", bulk_data.type },
                        { "Content-Location", bulk_data.location }
                    },
                { bulk_data.data.begin(), bulk_data.data.end() }
                );
            };
        auto const transfer_syntax = this->_transfer_syntax;
        int meta_data_count = 0;
        // Here we use a vector only to keep the same behaviour for accumulate_parts
        std::vector<Json::Value> json_vec;
        Json::Value json;
        json.resize(this->_data_sets.size());
        for (auto const data_set : copy )
        {
            json[meta_data_count++] = as_json(data_set);
        }
        json_vec.push_back(json);

        auto const accumulator_meta_data =
            [transfer_syntax](Json::Value const & json_)
            {
                Json::FastWriter writer;
                return Message(
                    {{
                        "Content-Type",
                        ItemWithParameters(
                            "application/dicom+json",
                            {{"transfer-syntax", transfer_syntax}})
                    }},
                    writer.write(json_)
                );
            };
        auto const boundary = random_boundary();
        std::ostringstream body;
        // add here first the meta_data
        accumulate_parts(
            json_vec.begin(), json_vec.end(),
            accumulator_meta_data, body, boundary);
        // add then the bulk data
        if (!bulk_data.empty())
        {
            // Remove the last boundary of the message
            auto body_content = body.str();
            body_content = body_content.substr(
                0, body_content.size()-boundary.size()-6);
            body.str(std::string()); // clear the content
            body << body_content;

            accumulate_parts(
                bulk_data.begin(), bulk_data.end(),
                accumulator_bulk_data, body, boundary);
        }

        request.set_body(body.str());

        request.set_header(
            "Content-Type",
            ItemWithParameters(
                "multipart/related", {
                    {"type", "application/dicom+json"},
                    {"boundary", boundary}}));
    }
    else if(this->_representation == Representation::DICOM_XML)
    {
        std::vector<BulkData> bulk_data;

        // Copy the dataSets in order to let them unchanged
        std::vector<odil::DataSet> copy = this->_data_sets;
        for (auto & ds :copy)
        {
            STOWRSRequest::_extract_bulk_data(ds, bulk_data);
        }

        auto const accumulator_bulk_data =
            [](BulkData const & bulk_data)
            {
                return Message(
                    {
                        { "Content-Type", bulk_data.type },
                        { "Content-Location", bulk_data.location }
                    },
                { bulk_data.data.begin(), bulk_data.data.end() }
                );
            };

        auto const transfer_syntax = this->_transfer_syntax;
        auto const accumulator_meta_data =
            [transfer_syntax](DataSet const & data_set)
            {
                auto const xml = as_xml(data_set);
                std::ostringstream stream;

#if BOOST_VERSION >= 105600
                typedef boost::property_tree::xml_writer_settings<std::string> SettingsType;
#else
                typedef boost::property_tree::xml_writer_settings<char> SettingsType;
#endif

                boost::property_tree::write_xml(stream, xml, SettingsType());

                return Message(
                    {{
                        "Content-Type",
                        ItemWithParameters(
                            "application/dicom+xml",
                            {{"transfer-syntax", transfer_syntax}})
                    }},
                    stream.str()
                );
            };

        auto const boundary = random_boundary();
        std::ostringstream body;
        // add here first the meta_data
        accumulate_parts(
            copy.begin(), copy.end(),
            accumulator_meta_data, body, boundary);
        // add then the bulk data
        if (!bulk_data.empty())
        {
            // Remove the last boundary of the message
            auto body_content = body.str();
            body_content = body_content.substr(
                0, body_content.size()-boundary.size()-6);
            body.str(std::string()); // clear the content
            body << body_content;

            accumulate_parts(
                bulk_data.begin(), bulk_data.end(),
                accumulator_bulk_data, body, boundary);
        }

        request.set_body(body.str());

        request.set_header(
            "Content-Type",
            ItemWithParameters(
                "multipart/related", {
                    {"type", "application/dicom+xml"},
                    {"boundary", boundary}}));
    }
    else
    {
        throw Exception("Unknown type");
    }
    request.set_method("POST");
    request.set_target(this->_url);
    request.set_http_version("HTTP/1.0");
    return request;
}

void
STOWRSRequest
::_extract_bulk_data(DataSet &data_set, std::vector<BulkData> & bulk_data)
{
    for (auto &it : data_set)
    {
        auto & tag = it.first;
        auto & element = it.second;
        if (data_set.is_binary(tag))
        {
            // 1. generate uuid
            boost::uuids::random_generator gen;
            boost::uuids::uuid uuid = gen();
            std::string uuid_string = boost::uuids::to_string(uuid);

            // 2. Get Transfer Syntax from dataSet
            auto const default_transfer_syntax =
                odil::registry::ExplicitVRLittleEndian;
            std::string const & transfer_syntax =
                    data_set.get_transfer_syntax().empty()
                        ?default_transfer_syntax
                        :data_set.get_transfer_syntax();

            // 3. Create a new BulkData
            BulkData data;
            data.data = *element.as_binary().data();
            data.location = uuid_string;
            if (tag == odil::registry::PixelData)
            {
                data.type = STOWRSRequest::_media_type_from_transfer_syntax(transfer_syntax);
            }
            else
            {
                data.type = "application/octet-stream";
            }

            // 4. add an entry to uuid_to_bulk
            bulk_data.push_back(data);

            // 5. Update the data_set giving in parameter
            data_set.add(tag, {uuid_string}, odil::VR::UR);
        }
        else if (data_set.is_data_set(tag))
        {
            // Case of sequence with multiple sub-elements
            for (auto sq : data_set.as_data_set(tag))
            {
                STOWRSRequest::_extract_bulk_data(sq, bulk_data);
            }
        }
        else
        {
            // Do nothing
        }
    }
}

void
STOWRSRequest
::_restore_data_set(DataSet &data_set, std::map<std::string, std::string>& uuid_bulk_raw)
{
    for (auto & it : data_set)
    {
        auto & tag = it.first;
        auto & element = it.second;
        if (data_set.get_vr(tag) == odil::VR::UR)
        {
            if (uuid_bulk_raw.find(element.as_string()[0]) !=
                    uuid_bulk_raw.end())
            {
                auto const uuid = element.as_string()[0];
                auto const bulk = uuid_bulk_raw.at(uuid);
                std::stringstream stream(bulk);

                auto const default_transfer_syntax =
                    odil::registry::ExplicitVRLittleEndian;
                std::string const & transfer_syntax =
                        data_set.get_transfer_syntax().empty()
                            ?default_transfer_syntax
                            :data_set.get_transfer_syntax();

                Reader reader(stream, transfer_syntax);
                std::vector<uint8_t>  data;
                for (auto const character : bulk)
                {
                    data.push_back(character);
                }

                // Update the data_set
                odil::VRFinder vr_finder;
                odil::VR vr = vr_finder(tag, data_set, transfer_syntax);
                data_set.add(tag, odil::Value::Binary({data}), vr);
            }
            else
            {
                // Do nothing (some other UR but not concerned by the bulk data restoration)
            }
        }
        else if (data_set.is_data_set(tag))
        {
            for (auto sq : data_set.as_data_set(tag))
            {
                STOWRSRequest::_restore_data_set(sq, uuid_bulk_raw);
            }
        }
        else
        {
            // Do nothing
        }
    }
}

std::string
STOWRSRequest
::_media_type_from_transfer_syntax(std::string const & transfer_syntax)
{
    std::map<std::string, std::string> transfer_syntax_media_type =
    {
        {"1.2.840.10008.1.2.1" , "application/octet-stream"},
        {"1.2.840.10008.1.2.4.70" , "image/jpeg"},
        {"1.2.840.10008.1.2.4.50" , "image/jpeg"},
        {"1.2.840.10008.1.2.4.51" , "image/jpeg"},
        {"1.2.840.10008.1.2.4.57" , "image/jpeg"},
        {"1.2.840.10008.1.2.5"    , "image/x-dicom-rle"},
        {"1.2.840.10008.1.2.4.80" , "image/x-jls"},
        {"1.2.840.10008.1.2.4.81" , "image/x-jls"},
        {"1.2.840.10008.1.2.4.90" , "image/jp2"},
        {"1.2.840.10008.1.2.4.91" , "image/jp2"},
        {"1.2.840.10008.1.2.4.92" , "image/jpx"},
        {"1.2.840.10008.1.2.4.93" , "image/jpx"},
        {"1.2.840.10008.1.2.4.100" , "video/mpeg2"},
        {"1.2.840.10008.1.2.4.101" , "video/mpeg2"},
        {"1.2.840.10008.1.2.4.102" , "video/mp4"},
        {"1.2.840.10008.1.2.4.103" , "video/mp4"},
        {"1.2.840.10008.1.2.4.104" , "video/mp4"},
        {"1.2.840.10008.1.2.4.105" , "video/mp4"},
        {"1.2.840.10008.1.2.4.106" , "video/mp4"},
    };

    return transfer_syntax_media_type.at(transfer_syntax);
}

}

}

ext: cpp

max_stars_repo_name: icryrainix/odil

max_issues_repo_name: icryrainix/odil

max_forks_repo_name: icryrainix/odil


text:
//===========================================================================
// Name         : dnamatrix_contiguous.hpp
// Author       : Roger Fraser
// Contributors :
// Version      : 1.00
// Copyright    : Copyright 2017 Geoscience Australia
//
//                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.
//
// Description  : DynAdjust Matrix library
//                Matrices are stored as a contiguous 1 dimensional array [row * column]
//                Storage buffer is ordered column wise to achieve highest efficiency with
//                Intel MKL
//============================================================================

#ifndef DNAMATRIX_CONTIGUOUS_H_
#define DNAMATRIX_CONTIGUOUS_H_

#if defined(_MSC_VER)
	#if defined(LIST_INCLUDES_ON_BUILD)
		#pragma message("  " __FILE__)
	#endif
#endif

#include <mkl.h>

#include <exception>
#include <stdexcept>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <vector>
#include <include/config/dnatypes.hpp>
#include <include/config/dnaversion.hpp>
#include <include/config/dnaconsts.hpp>
#include <include/exception/dnaexception.hpp>
#include <include/memory/dnamemory_handler.hpp>
#include <include/functions/dnatemplatecalcfuncs.hpp>

#ifdef _MSDEBUG
#include <include/ide/trace.hpp>
#endif

//#include <boost/algorithm/string.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/bind/bind.hpp>

#include <math.h>
#include <cstring>		// memset

using namespace std;
using namespace boost;
using namespace dynadjust::memory;
using namespace dynadjust::exception;

namespace dynadjust { namespace math {

class matrix_2d;
typedef vector<matrix_2d> v_mat_2d, *pv_mat_2d;
typedef v_mat_2d::iterator _it_v_mat_2d;
typedef v_mat_2d::const_iterator _it_v_mat_2d_const;
typedef vector<v_mat_2d> vv_mat_2d;

// Uncomment the following to store matrices in row-wise fashion
//#define DNAMATRIX_ROW_WISE

#if defined(DNAMATRIX_ROW_WISE)

// row * _mem_cols + column
#define DNAMATRIX_INDEX(no_rows, no_cols, row, column) row * no_cols + column

#else // DNAMATRIX_COL_WISE

// column * _mem_rows + row
#define DNAMATRIX_INDEX(no_rows, no_cols, row, column) column * no_rows + row

#endif

#define DNAMATRIX_ELEMENT(A, no_rows, no_cols, row, column) A[ DNAMATRIX_INDEX(no_rows, no_cols, row, column) ]

template <typename T>
std::size_t byteSize(const UINT32 elements=1)
{
	return elements * sizeof(T);
}

class matrix_2d: public new_handler_support<matrix_2d>
{
public:
	// Constructors/deconstructors
	matrix_2d();
	matrix_2d(const UINT32& rows, const UINT32& columns);		// explicit constructor
	matrix_2d(const UINT32& rows, const UINT32& columns,
		const double data[], const UINT32& data_size, const UINT32& matrix_type = mtx_full);
	matrix_2d(const matrix_2d&);	// copy constructor
	~matrix_2d();					// destructor

	inline bool empty() { return _buffer == NULL; }

	std::size_t get_size();

	///////////////////////////////////////////////////////////////////////
	// Get
	inline UINT32 memRows() const { return _mem_rows; }
	inline UINT32 memColumns() const { return _mem_cols; }
	inline UINT32 rows() const { return _rows; }
	inline UINT32 columns() const { return _cols; }
	inline double* getbuffer() const { return _buffer; }

	// element retrieval
	// see DNAMATRIX_ROW_WISE
	inline double& get(const UINT32& row, const UINT32& column) const { return DNAMATRIX_ELEMENT(_buffer, _mem_rows, _mem_cols, row, column); }
	inline double* getbuffer(const UINT32& row, const UINT32& column) const {
		return _buffer + DNAMATRIX_INDEX(_mem_rows, _mem_cols, row, column);
	}

	void submatrix(const UINT32& row_begin, const UINT32& col_begin, matrix_2d* dest,
		const UINT32& rows, const UINT32& columns) const;
	matrix_2d submatrix(const UINT32& row_begin, const UINT32& col_begin,
		const UINT32& rows, const UINT32& columns) const;

	inline double maxvalue() const { return get(_maxvalRow, _maxvalCol); }
	inline UINT32 maxvalueRow() const { return _maxvalRow; }
	inline UINT32 maxvalueCol() const { return _maxvalCol; }

	inline double* getelementref(const UINT32& row, const UINT32& column) const { return &(DNAMATRIX_ELEMENT(_buffer, _mem_rows, _mem_cols, row, column)); }
	inline double* getelementref(const UINT32& row, const UINT32& column) { return &(DNAMATRIX_ELEMENT(_buffer, _mem_rows, _mem_cols, row, column)); }

	inline void mem_rows(const UINT32& r) { _mem_rows = r; }
	inline void mem_columns(const UINT32& c) { _mem_cols = c; }
	inline void rows(const UINT32& r) { _rows = r; }
	inline void columns(const UINT32& c) { _cols = c; }
	inline void maxvalueRow(const UINT32& r) { _maxvalRow = r; }
	inline void maxvalueCol(const UINT32& c) { _maxvalCol = c; }

	inline void put(const UINT32& row, const UINT32& column, const double& value) { DNAMATRIX_ELEMENT(_buffer, _mem_rows, _mem_cols, row, column) = value; }

	inline UINT32 matrixType() const { return _matrixType; }
	inline void matrixType(const UINT32 t) { _matrixType = t; }

	// Matrix functions
	void copyelements(const UINT32& row_dest, const UINT32& column_dest, const matrix_2d& src, const UINT32& row_src, const UINT32& column_src, const UINT32& rows, const UINT32& columns);
	void copyelements(const UINT32& row_dest, const UINT32& column_dest, const matrix_2d* src, const UINT32& row_src, const UINT32& column_src, const UINT32& rows, const UINT32& columns);

	inline void elementadd(const UINT32& row, const UINT32& column, const double& increment) {
		*getelementref(row, column) += increment;
	}

	inline void elementsubtract(const UINT32& row, const UINT32& column, const double& decrement) {
		*getelementref(row, column) -= decrement;
	}

	inline void elementmultiply(const UINT32& row, const UINT32& column, const double& scale) {
		*getelementref(row, column) *= scale;
	}

#if defined(__SAFE_MATRIX_OPERATIONS__)
	//void copyelements(const UINT32& row_dest, const UINT32& column_dest, const UINT32& row_src, const UINT32& column_src, const UINT32& rows, const UINT32& columns);
	//void copyelements_safe(const UINT32& row_dest, const UINT32& column_dest, const UINT32& row_src, const UINT32& column_src, const UINT32& rows, const UINT32& columns);
	//void copyelements_safe(const UINT32& row_dest, const UINT32& column_dest, const matrix_2d& src, const UINT32& row_src, const UINT32& column_src, const UINT32& rows, const UINT32& columns);
	//double get_safe(const UINT32& row, const UINT32& column) const;
	//void put(const double data[], const UINT32& data_size);
	//void put_safe(const UINT32& row, const UINT32& column, const double& value);
	//void elementadd_safe(const UINT32& row, const UINT32& column, const double& increment);
	//void blockadd_safe(const UINT32& row_dest, const UINT32& col_dest, const matrix_2d& mat_src,
	//					 const UINT32& row_src, const UINT32& col_src, const UINT32& rows, const UINT32& cols);
	//void blockTadd_safe(const UINT32& row_dest, const UINT32& col_dest, const matrix_2d& mat_src,
	//					 const UINT32& row_src, const UINT32& col_src, const UINT32& rows, const UINT32& cols);
	//matrix_2d scale(const double& scalar,				//  ''
	//	const UINT32& row_begin, const UINT32& col_begin,
	//	UINT32 rows=0, UINT32 columns=0);
	//void zero_safe(const UINT32& row_begin, const UINT32& col_begin, const UINT32& rows, const UINT32& columns);
#endif

	void blockadd(const UINT32& row_dest, const UINT32& col_dest, const matrix_2d& mat_src,
						 const UINT32& row_src, const UINT32& col_src, const UINT32& rows, const UINT32& cols);
	void blockTadd(const UINT32& row_dest, const UINT32& col_dest, const matrix_2d& mat_src,
						 const UINT32& row_src, const UINT32& col_src, const UINT32& rows, const UINT32& cols);
	void blocksubtract(const UINT32& row_dest, const UINT32& col_dest, const matrix_2d& mat_src,
						 const UINT32& row_src, const UINT32& col_src, const UINT32& rows, const UINT32& cols);

	matrix_2d add(const matrix_2d& rhs);
	matrix_2d add(const matrix_2d& lhs, const matrix_2d& rhs);

	matrix_2d multiply(const matrix_2d& rhs);			// multiplication
	matrix_2d multiply(const matrix_2d& lhs,
		const matrix_2d& rhs);							// multiplication

	matrix_2d multiply_mkl(const char* lhs_trans,
		const matrix_2d& rhs, const char* rhs_trans);			// multiplication
	matrix_2d multiply_mkl(const matrix_2d& lhs, const char* lhs_trans,
		const matrix_2d& rhs, const char* rhs_trans);			// multiplication

	matrix_2d multiply_square(const matrix_2d& lhs,		// multiplication, calculate upper triangle only, then copy to lower
		const matrix_2d& rhs);
	matrix_2d multiply_square_triangular(const matrix_2d& lhs,		// multiplication, calculate upper triangle only, then copy to lower
		const matrix_2d& rhs);
	matrix_2d multiply_square_t(const matrix_2d& lhs,	// same as multiply_square, except lhs is multiplied by transpose of rhs.
		const matrix_2d& rhs);
	matrix_2d sweepinverse();							// Sweep inverse (good for rotation matrices)
	matrix_2d gaussianinverse();						// Gaussian inverse
	matrix_2d choleskyinverse(bool LOWER_IS_CLEARED=false);				// Cholesky inverse
	void decomposeupper();								// Cholesky decomposition

	matrix_2d choleskyinverse_mkl(bool LOWER_IS_CLEARED=false);	// Cholesky inverse using MKL

	matrix_2d transpose(const matrix_2d&);				// Transpose
	matrix_2d transpose();								//  ''
	matrix_2d scale(const double& scalar);				// scale

	// overloaded operators
	// equality
	bool operator==(const matrix_2d& rhs) const {
		if (_mem_cols != rhs._mem_cols)
			return false;
		if (_mem_rows != rhs._mem_rows)
			return false;
		if (_cols != rhs._cols)
			return false;
		if (_rows != rhs._rows)
			return false;
		if (*_buffer != *rhs._buffer)
			return false;
		if (_maxvalCol != rhs._maxvalCol)
			return false;
		if (_maxvalRow != rhs._maxvalRow)
			return false;
		if (_matrixType != rhs._matrixType)
			return false;
		return true;
	}

	// equality
	bool operator!=(const matrix_2d& rhs) const {
		if (_mem_cols == rhs._mem_cols)
			return false;
		if (_mem_rows == rhs._mem_rows)
			return false;
		if (_cols == rhs._cols)
			return false;
		if (_rows == rhs._rows)
			return false;
		if (*_buffer == *rhs._buffer)
			return false;
		if (_maxvalCol == rhs._maxvalCol)
			return false;
		if (_maxvalRow == rhs._maxvalRow)
			return false;
		if (_matrixType == rhs._matrixType)
			return false;
		return true;
	}

	matrix_2d operator=(const matrix_2d& rhs);
	matrix_2d operator*(const double& rhs) const;
	matrix_2d operator*(const matrix_2d& rhs) const;
	matrix_2d operator+(const matrix_2d& rhs) const;
	matrix_2d operator-(const matrix_2d& rhs) const;

	matrix_2d operator*=(const matrix_2d& rhs);
	matrix_2d operator+=(const matrix_2d& rhs);
	matrix_2d operator-=(const matrix_2d& rhs);
	double operator() (const UINT32& row, const UINT32& column);

	// Initialisation / manipulation
	void allocate();
	void allocate(const UINT32& rows, const UINT32& columns);
	void setsize(const UINT32& rows, const UINT32& columns);		// sets matrix size to rows * columns only (buffer not allocated any memory)
	void redim(const UINT32& rows, const UINT32& columns);			// redimensions matrix to rows * columns
	void replace(const UINT32& rowstart, const UINT32& columnstart, const matrix_2d& newmat);
	void replace(const UINT32& rowstart, const UINT32& columnstart, const UINT32& rows, const UINT32& columns, const matrix_2d& newmat);
	//void append(const matrix_2d& newmat);
	//void appendcolumns(const UINT32& columns);
	//void appendrows(const UINT32& rows);
	void shrink(const UINT32& rows, const UINT32& columns);
	void grow(const UINT32& rows, const UINT32& columns);
	void clearlower();			// sets lower tri elements to zero
	void filllower();			// copies upper tri to lower
	void fillupper();			// copies lower tri to upper
	void zero();				// sets all elements to zero
	void zero(const UINT32& row_begin, const UINT32& col_begin, const UINT32& rows, const UINT32& columns);
	void identity();													// set matrix to Identity
	void identity(const UINT32& rowstart, const UINT32& columnstart);	// set sub-matrix to Identity (from
	void identity(const UINT32& rowstart, const UINT32& columnstart,	// at rowstart, columnstart to end)
		const UINT32& rows, const UINT32& columns);						// set sub-matrix to Identity

	// comparison
	void difference(const matrix_2d* lhs, const matrix_2d* rhs);
	void difference(const UINT32& row_begin, const UINT32& col_begin, const matrix_2d& lhs, const matrix_2d& rhs);
	void differenceabs(const matrix_2d& lhs, const matrix_2d& rhs);
	void differenceabs(const matrix_2d& lhs, const matrix_2d* rhs);
	double vectordifference(const matrix_2d& rhs);
	double compute_maximum_value();

	// Printing
	void coutmatrix(const string& sTitle, const short& precision) const;
	friend ostream& operator<< (ostream& os, const matrix_2d& rhs);
	friend ostream& operator<< (ostream& os, const matrix_2d* rhs);
	friend ostream& operator<< (ostream& os, const v_mat_2d& rhs);
	friend ostream& operator<< (ostream& os, const v_mat_2d* rhs);

	// Reading
	friend istream& operator>> (istream& is, matrix_2d& rhs);
	friend istream& operator>> (istream& is, matrix_2d* rhs);
	friend istream& operator>> (istream& is, v_mat_2d& rhs);
	friend istream& operator>> (istream& is, v_mat_2d* rhs);

	// Reading from memory mapped file
	void ReadMappedFileRegion(void* addr);

	// Writing to memory mapped file
	void WriteMappedFileRegion(void* addr);

	// debug
	void trace(const char* comment, const char* format) const;
	void trace(const char* comment, const char *submat_comment, const char* format,
		const UINT32& row_begin, const UINT32& col_begin,
		const UINT32& rows, const UINT32& columns) const;

	//void replacebuffer(const UINT32& rows, const UINT32& columns, double**	buffer);

private:

	inline std::size_t buffersize() const { return _mem_rows * _mem_cols * sizeof(double); }

	void deallocate();
	void buy(const UINT32& rows, const UINT32& columns, double** mem_space);
	void copybuffer(const UINT32& rows, const UINT32& columns, const matrix_2d& oldmat);
	void copybuffer(const UINT32& rowstart, const UINT32& columnstart,
		const UINT32& rows, const UINT32& columns, const matrix_2d& mat);
	//void copybuffer(const UINT32& rows, const UINT32& columns, double**	buffer);

	void sweep(UINT32 k1, UINT32 k2);

	UINT32		_mem_cols;		// actual buffer size (cols)
	UINT32		_mem_rows;		// actual buffer size (rows)
	UINT32		_cols;		// number of actual cols
	UINT32		_rows;			// number of actual rows
	double*		_buffer;		// matrix buffer elements

	UINT32		_maxvalCol;		// col of max value
	UINT32		_maxvalRow;		// row of max value

	UINT32		_matrixType;	// full, upper/lower, sparse
};

}	// namespace math
}	// namespace dynadjust

#endif	// DNAMATRIX_CONTIGUOUS_H_

ext: hpp

max_stars_repo_name: ccrook/DynAdjust

max_issues_repo_name: ccrook/DynAdjust

max_forks_repo_name: ccrook/DynAdjust


text:
// Copyright DEWETRON GmbH 2017

#include "odkapi_block_descriptor_xml.h"
#include "odkfw_block_iterator.h"

#include <boost/test/unit_test.hpp>

using namespace odk::framework;

BOOST_AUTO_TEST_SUITE(block_iterator)

BOOST_AUTO_TEST_CASE(null_block_iterator_test)
{
    BlockIterator it;
    BOOST_CHECK_EQUAL(it.data(), nullptr);
    BOOST_CHECK_EQUAL(it.timestamp(), 0);

    ++it;
    BOOST_CHECK_EQUAL(it.data(), nullptr);
    BOOST_CHECK_EQUAL(it.timestamp(), 1);
}

BOOST_AUTO_TEST_CASE(timeless_block_iterator_test)
{
    const float data[] = {3.1415f, 2.718f, 1.618f};

    BlockIterator it(data, sizeof(float), 123);
    BOOST_CHECK_EQUAL(it.data(), data);
    BOOST_CHECK_EQUAL(it.timestamp(), 123);

    ++it;
    BOOST_CHECK_EQUAL(it.data(), data + 1);
    BOOST_CHECK_EQUAL(it.timestamp(), 124);

    --it;
    BOOST_CHECK_EQUAL(it.data(), data);
    BOOST_CHECK_EQUAL(it.timestamp(), 123);
}

BOOST_AUTO_TEST_CASE(timepointer_block_iterator_test)
{
    const double data[] = {3.1415, 2.718, 1.618};
    const std::uint64_t timestamps[] = {1, 2, 3};

    BlockIterator it(data, sizeof(double), timestamps, sizeof(std::uint64_t));
    auto it0 = it;
    BOOST_CHECK_EQUAL(it.data(), data);
    BOOST_CHECK_EQUAL(it.timestamp(), 1);

    ++it;
    auto it1 = it;
    BOOST_CHECK_EQUAL(it.data(), data + 1);
    BOOST_CHECK_EQUAL(it.timestamp(), 2);

    BOOST_CHECK(it == it1);
    BOOST_CHECK_EQUAL(it.distanceTo(it1), 0);
    BOOST_CHECK_EQUAL(it0.distanceTo(it1), 1);

    --it;
    BOOST_CHECK_EQUAL(it.data(), data);
    BOOST_CHECK_EQUAL(it.timestamp(), 1);

    BOOST_CHECK(it == it0);
    BOOST_CHECK(it != it1);
    BOOST_CHECK_EQUAL(it.distanceTo(it1), 1);
}

BOOST_AUTO_TEST_SUITE_END()

max_stars_repo_name: HpLightcorner/OXYGEN-SDK

max_issues_repo_name: HpLightcorner/OXYGEN-SDK

max_forks_repo_name: HpLightcorner/OXYGEN-SDK


text:
#include <Oceaniolib/Oceanio.hpp>
#include <Oceaniolib/print.hpp>
#include <Oceaniolib/singleton.hpp>
#include <Oceaniolib/crypto.h>
#include <boost/algorithm/string.hpp>

using namespace Oceanio;
using namespace std;

typedef uint128_t key_n_t;

class hello : public Oceanio::contract {
    public:
        using contract::contract;

        hello( account_name self )
        : contract(self)
        , _keyval(_self, _self)
        , counter(28)
        {}

        int counter;

        // @abi table
        struct keyval {
            uint64_t id;
            key_n_t key_n;
            string key_s;
            string val;

            uint64_t primary_key() const { return id; }
            key_n_t get_key_n() const { return key_n; }

            OceanLIB_SERIALIZE( keyval, (id)(key_n)(key_s)(val) )
        };

        string u64_to_string(name value)const {
            static const char* charmap = ".12345abcdefghijklmnopqrstuvwxyz";

            string str(13,'.');

            uint64_t tmp = value;
            for( uint32_t i = 0; i <= 12; ++i ) {
                char c = charmap[tmp & (i == 0 ? 0x0f : 0x1f)];
                str[12-i] = c;
                tmp >>= (i == 0 ? 4 : 5);
            }

            boost::algorithm::trim_right_if( str, []( char c ){ return c == '.'; } );
            return str;
        }

        static constexpr uint64_t string_to_u64( const char* str ) {

            uint32_t len = 0;
            while( str[len] ) ++len;

            uint64_t value = 0;

            for( uint32_t i = 0; i <= 12; ++i ) {
                uint64_t c = 0;
                if( i < len && i <= 12 ) c = uint64_t(char_to_symbol( str[i] ));

                if( i < 12 ) {
                    c &= 0x1f;
                    c <<= 64-5*(i+1);
                }
                else {
                    c &= 0x0f;
                }

                value |= c;
            }

            return value;
        }

        static const int maxl = 25;
        static const int maxb = 128;

        static constexpr uint128_t string_to_u128( const char* str ) {

            uint32_t len = 0;
            while( str[len] ) ++len;

            uint128_t value = 0;

            for( uint32_t i = 0; i <= maxl; ++i ) {
                uint128_t c = 0;
                if( i < len && i <= maxl ) c = uint64_t(char_to_symbol( str[i] ));

                if( i < maxl ) {
                    c &= 0x1f;
                    c <<= maxb-5*(i+1);
                }
                else {
                    c &= 0x07;
                }

                value |= c;
            }

            return value;
        }

        static string u128_to_string(uint128_t  value) {
            static const char* charmap = ".12345abcdefghijklmnopqrstuvwxyz";

            string str(maxl+1,'.');

            uint128_t tmp = value;
            for( uint32_t i = 0; i <= maxl; ++i ) {
                char c = charmap[tmp & (i == 0 ? 0x07 : 0x1f)];
                str[maxl-i] = c;
                tmp >>= (i == 0 ? 3 : 5);
            }

            boost::trim_right_if( str, []( char c ){ return c == '.'; } );
            return str;
        }

        /// @abi action
        void addprm( name user, string key, string val, uint64_t id ) {
            print( "add key val for user by primary idx, user = ", user, ": ", getCounter());

            Oceanio::multi_index<N(keyval), keyval
            , indexed_by< N(by_key_n),   const_mem_fun<keyval, key_n_t, &keyval::get_key_n> >
            > tbl(_self, user);

            auto primary_idx = tbl.find(id);
            if (primary_idx!=tbl.end())
            {
                print("key already found = ", key.c_str(), "id= ", primary_idx->id);

                tbl.modify( primary_idx, user, [&]( auto& row) {
                    // row.key_n = string_to_u64(key.c_str());
                    row.key_n = string_to_u128(key.c_str());
                    row.key_s = key;
                    row.val = val;
                });

            }
            // get here when need to insert
            else
            {
                print("adding new key  ", key.c_str());
                tbl.emplace( user, [&]( auto& row) {
                    row.id = incCounter();
                    // row.key_n = string_to_u64(key.c_str());
                    row.key_n = string_to_u128(key.c_str());
                    row.key_s = key;
                    row.val = val;
                });
            }
        }

        /// @abi action
        void addsec( name user, string key, string val ) {
            print( "add key val for user by secondary idx (key), user= ", user, "\n");

            Oceanio::multi_index<N(keyval), keyval
            , indexed_by< N(by_key_n),   const_mem_fun<keyval, key_n_t, &keyval::get_key_n> >
            > tbl(_self, user);
            // > tbl(_self, _self /*user*/);

            auto keyn_idx = tbl.get_index<N(by_key_n)>();
            // auto it = keyn_idx.find(string_to_u64(key.c_str()));
            auto it = keyn_idx.find(string_to_u128(key.c_str()));
            if (it != keyn_idx.end())
            {
                print("key already found = ", key.c_str(), " id= ", it->id);
                auto pkidx = tbl.find(it->id);

                tbl.modify( pkidx, user, [&]( auto& row) {
                    row.val = val;
                });
            }
            else
            {
                print("adding new key  ", key.c_str());
                tbl.emplace( user, [&]( auto& row) {
                    row.id = incCounter();
                    // row.key_n = string_to_u64(key.c_str());
                    row.key_n = string_to_u128(key.c_str());
                    row.key_s = key;
                    row.val = val;
                });
            }
        }

        /// @abi action
        void remove( name user, uint64_t id ) {
            print("got remove cmd: ", user, "id=  ", id);
            auto it = db_find_i64(_self, /*_self*/user, N(keyval), id);
            if (it >= 0) {
                db_remove_i64(it);
            }
        }

    private:

        multi_index<N(keyval), keyval> _keyval;

        singleton<N(hello3), N(g_counter), N(hello3), uint64_t>  g_counter;

        uint64_t incCounter() {
            uint64_t next = g_counter.exists() ? g_counter.get()+1 : 0;
            g_counter.set(next);
            return next;
        }

        uint64_t getCounter() {
            uint64_t cur = g_counter.exists() ? g_counter.get() : 0;
            return cur;
        }

};

OceanIO_ABI( hello, (remove)(addprm)(addsec) )

max_stars_repo_name: OceanCS/MEPC

max_issues_repo_name: OceanCS/MEPC

max_forks_repo_name: OceanCS/MEPC


text: #include <boost/mpl/aux_/preprocessed/msvc70/set_c.hpp>

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
/// @file
/// @brief

#include <set>
#include <sstream>
#include <iterator>

#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/null.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/algorithm/string/erase.hpp>
#include <boost/utility/string_view.hpp>

#include <celero/Celero.h>

#include <iostreams/filters.h>

using namespace std::literals;

namespace {
namespace bm_env {
namespace consts {

static constexpr auto N_SAMPLES = 2u;
static constexpr auto N_ITERATIONS = 3000u;

static const auto SOURCE = R"txt(
Far far away, behind the word mountains, far from the countries Vokalia and
Consonantia, there live the blind texts. Separated they live in Bookmarksgrove right at the
coast of the Semantics, a large language ocean. A small river named Duden flows by
their place and supplies it with the necessary regelialia. It is a paradisematic
country, in which roasted parts of sentences fly into your mouth. Even the all-powerful
Pointing has no control about the blind texts it is an almost unorthographic life One
day however a small line of blind text by the name of Lorem Ipsum decided to leave
for the far World of Grammar. The Big Oxmox advised her not to do so, because
there were thousands of bad Commas, wild Question Marks and devious Semikoli, but
the Little Blind Text didn’t listen. She packed her seven versalia, put her
initial into the belt and made herself on the way. When she reached the first hills of
the Italic Mountains, she had a last view back on the skyline of her hometown
Bookmarksgrove, the headline of Alphabet Village and the subline of her own road, the Line
Lane. Pityful a rethoric question ran over her cheek, then she continued her way. On
her way she met a copy. The copy warned the Little Blind Text, that where it came
from it would have been rewritten a thousand times and everything that was left
from its origin would be the word "and" and the Little Blind Text should turn
around and return to its own, safe country.

But nothing the copy said could convince her and so it didn’t take long until
a few insidious Copy Writers ambushed her, made her drunk with Longe and Parole
and dragged her into their agency, where they abused her for their projects again
and again. And if she hasn’t been rewritten, then they are still using her. Far
far away, behind the word mountains, far from the countries Vokalia and
Consonantia, there live the blind texts. Separated they live in Bookmarksgrove right at the
coast of the Semantics, a large language ocean. A small river named Duden flows by
their place and supplies it with the necessary regelialia. It is a paradisematic
country, in which roasted parts of sentences fly into your mouth. Even the all-powerful
Pointing has no control about the blind texts it is an almost unorthographic life One
day however a small line of blind text by the name of Lorem Ipsum decided to leave
for the far World of Grammar. The Big Oxmox advised her not to do so, because
there were thousands of bad Commas, wild Question Marks and devious Semikoli, but
the Little Blind Text didn’t listen. She packed her seven versalia, put her
initial into the belt and made herself on the way. When she reached the first hills of
the Italic Mountains, she had a last view back on the skyline of her hometown
Bookmarksgrove, the headline of Alphabet Village and the subline of her own road, the Line
Lane.

Pityful a rethoric question ran over her cheek, then she continued her way. On
her way she met a copy. The copy warned the Little Blind Text, that where it came
from it would have been rewritten a thousand times and everything that was left
from its origin would be the word "and" and the Little Blind Text should turn
around and return to its own, safe country. But nothing the copy said could convince
her and so it didn’t take long until a few insidious Copy Writers ambushed her,
made her drunk with Longe and Parole and dragged her into their agency, where they
abused her for their projects again and again. And if she hasn’t been rewritten, then
they are still using her. Far far away, behind the word mountains, far from the
countries Vokalia and Consonantia, there live the blind texts. Separated they live in
Bookmarksgrove right at the coast of the Semantics, a large language ocean. A small river
named Duden flows by their place and supplies it with the necessary regelialia. It
is a paradisematic country, in which roasted parts of sentences fly into your
mouth. Even the all-powerful Pointing has no control about the blind texts it is an
almost unorthographic life One day however a small line of blind text by the name of
Lorem Ipsum decided to leave for the far World of Grammar. The Big Oxmox advised her
not to do so, because there were thousands of bad Commas, wild Question Marks and
devious Semikoli, but the Little Blind Text didn’t listen.
)txt"s;

static const auto RESULT = R"txt(
Fr fr wy, bhnd th wrd mntns, fr frm th cntrs Vkl nd
Cnsnnt, thr lv th blnd txts. Sprtd thy lv n Bkmrksgrv rght t th
cst f th Smntcs,  lrg lngg cn.  smll rvr nmd Ddn flws by
thr plc nd sppls t wth th ncssry rgll. t s  prdsmtc
cntry, n whch rstd prts f sntncs fly nt yr mth. vn th ll-pwrfl
Pntng hs n cntrl bt th blnd txts t s n lmst nrthgrphc lf n
dy hwvr  smll ln f blnd txt by th nm f Lrm psm dcdd t lv
fr th fr Wrld f Grmmr. Th Bg xmx dvsd hr nt t d s, bcs
thr wr thsnds f bd Cmms, wld Qstn Mrks nd dvs Smkl, bt
th Lttl Blnd Txt ddn’t lstn. Sh pckd hr svn vrsl, pt hr
ntl nt th blt nd md hrslf n th wy. Whn sh rchd th frst hlls f
th tlc Mntns, sh hd  lst vw bck n th skyln f hr hmtwn
Bkmrksgrv, th hdln f lphbt Vllg nd th sbln f hr wn rd, th Ln
Ln. Ptyfl  rthrc qstn rn vr hr chk, thn sh cntnd hr wy. n
hr wy sh mt  cpy. Th cpy wrnd th Lttl Blnd Txt, tht whr t cm
frm t wld hv bn rwrttn  thsnd tms nd vrythng tht ws lft
frm ts rgn wld b th wrd "nd" nd th Lttl Blnd Txt shld trn
rnd nd rtrn t ts wn, sf cntry.

Bt nthng th cpy sd cld cnvnc hr nd s t ddn’t tk lng ntl
 fw nsds Cpy Wrtrs mbshd hr, md hr drnk wth Lng nd Prl
nd drggd hr nt thr gncy, whr thy bsd hr fr thr prjcts gn
nd gn. nd f sh hsn’t bn rwrttn, thn thy r stll sng hr. Fr
fr wy, bhnd th wrd mntns, fr frm th cntrs Vkl nd
Cnsnnt, thr lv th blnd txts. Sprtd thy lv n Bkmrksgrv rght t th
cst f th Smntcs,  lrg lngg cn.  smll rvr nmd Ddn flws by
thr plc nd sppls t wth th ncssry rgll. t s  prdsmtc
cntry, n whch rstd prts f sntncs fly nt yr mth. vn th ll-pwrfl
Pntng hs n cntrl bt th blnd txts t s n lmst nrthgrphc lf n
dy hwvr  smll ln f blnd txt by th nm f Lrm psm dcdd t lv
fr th fr Wrld f Grmmr. Th Bg xmx dvsd hr nt t d s, bcs
thr wr thsnds f bd Cmms, wld Qstn Mrks nd dvs Smkl, bt
th Lttl Blnd Txt ddn’t lstn. Sh pckd hr svn vrsl, pt hr
ntl nt th blt nd md hrslf n th wy. Whn sh rchd th frst hlls f
th tlc Mntns, sh hd  lst vw bck n th skyln f hr hmtwn
Bkmrksgrv, th hdln f lphbt Vllg nd th sbln f hr wn rd, th Ln
Ln.

Ptyfl  rthrc qstn rn vr hr chk, thn sh cntnd hr wy. n
hr wy sh mt  cpy. Th cpy wrnd th Lttl Blnd Txt, tht whr t cm
frm t wld hv bn rwrttn  thsnd tms nd vrythng tht ws lft
frm ts rgn wld b th wrd "nd" nd th Lttl Blnd Txt shld trn
rnd nd rtrn t ts wn, sf cntry. Bt nthng th cpy sd cld cnvnc
hr nd s t ddn’t tk lng ntl  fw nsds Cpy Wrtrs mbshd hr,
md hr drnk wth Lng nd Prl nd drggd hr nt thr gncy, whr thy
bsd hr fr thr prjcts gn nd gn. nd f sh hsn’t bn rwrttn, thn
thy r stll sng hr. Fr fr wy, bhnd th wrd mntns, fr frm th
cntrs Vkl nd Cnsnnt, thr lv th blnd txts. Sprtd thy lv n
Bkmrksgrv rght t th cst f th Smntcs,  lrg lngg cn.  smll rvr
nmd Ddn flws by thr plc nd sppls t wth th ncssry rgll. t
s  prdsmtc cntry, n whch rstd prts f sntncs fly nt yr
mth. vn th ll-pwrfl Pntng hs n cntrl bt th blnd txts t s n
lmst nrthgrphc lf n dy hwvr  smll ln f blnd txt by th nm f
Lrm psm dcdd t lv fr th fr Wrld f Grmmr. Th Bg xmx dvsd hr
nt t d s, bcs thr wr thsnds f bd Cmms, wld Qstn Mrks nd
dvs Smkl, bt th Lttl Blnd Txt ddn’t lstn.
)txt"s;

static constexpr auto VOWELS = "aeiouAEIOU";

} // namespace consts

void copy( std::istream& is, std::ostream& os )
{
     celero::DoNotOptimizeAway( std::copy(
          std::istreambuf_iterator< char >{ is }
          , std::istreambuf_iterator< char >{}
          , std::ostreambuf_iterator< char >{ os }
          ) );
}

} // namespace bm_env
} // namespace {unnamed}

BASELINE( CharRemover, UseCopyIf, bm_env::consts::N_SAMPLES, bm_env::consts::N_ITERATIONS )
{
     std::istringstream is{ bm_env::consts::SOURCE };
     std::ostringstream os;

     const std::set< char > ignored{
          bm_env::consts::VOWELS
          , bm_env::consts::VOWELS + std::strlen( bm_env::consts::VOWELS )
     };

     BOOST_ASSERT( ignored.size() == std::strlen( bm_env::consts::VOWELS ) );

     std::copy_if(
          std::istreambuf_iterator< char >{ is }
          , std::istreambuf_iterator< char >{}
          , std::ostreambuf_iterator< char >{ os }
          , [ &ignored ]( const auto c ){
               return !ignored.count( c );
          }
          );

     BOOST_ASSERT( os.str() == bm_env::consts::RESULT );
}

BENCHMARK( CharRemover, UseBoostErase, bm_env::consts::N_SAMPLES, bm_env::consts::N_ITERATIONS )
{
     std::string mutableSrc = bm_env::consts::SOURCE;
     for( auto&& c: boost::string_view{ bm_env::consts::VOWELS } )
     {
          boost::algorithm::erase_all( mutableSrc, boost::string_view{ &c, 1u } );
     }

     BOOST_ASSERT( mutableSrc == bm_env::consts::RESULT );
}

BENCHMARK( CharRemover, CharStdIos, bm_env::consts::N_SAMPLES, bm_env::consts::N_ITERATIONS )
{
     std::istringstream is{ bm_env::consts::SOURCE };
     std::ostringstream os;

     using_boost::iostreams::filters::single_char::CharRemover cr{ bm_env::consts::VOWELS };

     boost::iostreams::filtering_istream fis;
     fis.push( boost::ref( cr ) );
     fis.push( is );

     bm_env::copy( fis, os );

     BOOST_ASSERT( os.str() == bm_env::consts::RESULT );
}

BENCHMARK( CharRemover, BlockStdIos, bm_env::consts::N_SAMPLES, bm_env::consts::N_ITERATIONS )
{
     std::istringstream is{ bm_env::consts::SOURCE };
     std::ostringstream os;

     using_boost::iostreams::filters::multichar::CharRemover cr{ bm_env::consts::VOWELS };

     boost::iostreams::filtering_istream fis;
     fis.push( boost::ref( cr ) );
     fis.push( is );

     bm_env::copy( fis, os );

     BOOST_ASSERT( os.str() == bm_env::consts::RESULT );
}

BENCHMARK( CharRemover, CharBoostIos, bm_env::consts::N_SAMPLES, bm_env::consts::N_ITERATIONS )
{
     boost::iostreams::stream< boost::iostreams::array_source > is{
          boost::iostreams::array_source{
               bm_env::consts::SOURCE.data(), bm_env::consts::SOURCE.size()
          }
     };
     std::ostringstream os;

     using_boost::iostreams::filters::single_char::CharRemover cr{ bm_env::consts::VOWELS };

     boost::iostreams::filtering_istream fis;
     fis.push( boost::ref( cr ) );
     fis.push( is );

     bm_env::copy( fis, os );

     BOOST_ASSERT( os.str() == bm_env::consts::RESULT );
}

BENCHMARK( CharRemover, BlockBoostIos, bm_env::consts::N_SAMPLES, bm_env::consts::N_ITERATIONS )
{
     boost::iostreams::stream< boost::iostreams::array_source > is{
          boost::iostreams::array_source{
               bm_env::consts::SOURCE.data(), bm_env::consts::SOURCE.size()
          }
     };
     std::ostringstream os;

     using_boost::iostreams::filters::multichar::CharRemover cr{ bm_env::consts::VOWELS };

     boost::iostreams::filtering_istream fis;
     fis.push( boost::ref( cr ) );
     fis.push( is );

     bm_env::copy( fis, os );

     BOOST_ASSERT( os.str() == bm_env::consts::RESULT );
}


text:
// Copyright 2020 Hans Dembinski
//
// 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)

//[ guide_histogram_in_api

#include <boost/histogram.hpp>
#include <cassert>

// function accepts any histogram and returns a copy
template <class Axes, class Storage>
boost::histogram::histogram<Axes, Storage> any_histogram(
    boost::histogram::histogram<Axes, Storage>& h) {
  return h;
}

// function only accepts histograms with fixed axis types and returns a copy
template <class Storage, class... Axes>
boost::histogram::histogram<std::tuple<Axes...>, Storage> only_static_histogram(
    boost::histogram::histogram<std::tuple<Axes...>, Storage>& h) {
  return h;
}

// function only accepts histograms with dynamic axis types and returns a copy
template <class Storage, class... Axes>
boost::histogram::histogram<std::vector<boost::histogram::axis::variant<Axes...>>,
                            Storage>
only_dynamic_histogram(
    boost::histogram::histogram<std::vector<boost::histogram::axis::variant<Axes...>>,
                                Storage>& h) {
  return h;
}

int main() {
  using namespace boost::histogram;

  auto histogram_with_static_axes = make_histogram(axis::regular<>(10, 0, 1));

  using axis_variant = axis::variant<axis::regular<>, axis::integer<>>;
  std::vector<axis_variant> axes;
  axes.emplace_back(axis::regular<>(5, 0, 1));
  axes.emplace_back(axis::integer<>(0, 1));
  auto histogram_with_dynamic_axes = make_histogram(axes);

  assert(any_histogram(histogram_with_static_axes) == histogram_with_static_axes);
  assert(any_histogram(histogram_with_dynamic_axes) == histogram_with_dynamic_axes);
  assert(only_static_histogram(histogram_with_static_axes) == histogram_with_static_axes);
  assert(only_dynamic_histogram(histogram_with_dynamic_axes) ==
         histogram_with_dynamic_axes);

  // does not compile: only_static_histogram(histogram_with_dynamic_axes)
  // does not compile: only_dynamic_histogram(histogram_with_static_axes)
}

//]

max_issues_repo_name: qingkouwei/mediaones

max_forks_repo_name: qingkouwei/mediaones


text:
//
// fiber/detail/io_fiber_read_op.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2014-2015
//

#ifndef SSF_COMMON_BOOST_ASIO_FIBER_DETAIL_IO_FIBER_READ_OP_HPP_
#define SSF_COMMON_BOOST_ASIO_FIBER_DETAIL_IO_FIBER_READ_OP_HPP_

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
#pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)

#include <boost/asio/detail/config.hpp>

#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
#include <boost/asio/detail/operation.hpp>
#include <boost/asio/detail/socket_ops.hpp>
#include <boost/asio/error.hpp>

#include "common/boost/fiber/detail/io_operation.hpp"
#include "common/boost/fiber/detail/fiber_id.hpp"

#include <boost/asio/detail/push_options.hpp>

namespace boost {
namespace asio {
namespace fiber {
namespace detail {

/// Class to store buffers and read operations on a fiber
/**
* @tparam MutableBufferSequence The type of the sequence of mutable buffers used
* @tparam Handler The type of the handler to be called upon completion
*/
template <typename MutableBufferSequence, typename Handler>
class pending_read_operation : public basic_pending_read_operation
{
public:
  BOOST_ASIO_DEFINE_HANDLER_PTR(pending_read_operation);

  /// Constructor
  /**
  * @param buffers The reading buffers
  * @param handler The handler to call upon completion
  */
  pending_read_operation(const MutableBufferSequence& buffers, Handler& handler)
    : basic_pending_read_operation(&pending_read_operation::do_complete,
                                   &pending_read_operation::do_fill_buffers,
                                   nullptr),
    buffers_(buffers),
    handler_(handler)
  {
  }

  /// Constructor
  /**
  * @param buffers The reading buffers
  * @param handler The handler to call upon completion
  * @param p_remote_port A pointer to the remote port from where the data was
  * received
  */
  pending_read_operation(const MutableBufferSequence& buffers,
                         Handler& handler,
                         fiber_id::remote_port_type* p_remote_port)
                         : basic_pending_read_operation(&pending_read_operation::do_complete,
                                                        &pending_read_operation::do_fill_buffers,
                                                        p_remote_port),
                           buffers_(buffers),
                           handler_(handler)
  {
  }

  /// Implementation of the completion callback
  /**
  * @param base A pointer to the base class
  * @param destroy A boolean to decide if the op should be destroyed
  * @param result_ec The error_code of the operation
  * @param bytes_transferred The number of bytes handled
  */
  static void do_complete(basic_pending_io_operation* base, bool destroy,
                          const boost::system::error_code& result_ec,
                          std::size_t bytes_transferred)
  {
    boost::system::error_code ec(result_ec);

    // Take ownership of the operation object.
    pending_read_operation* o(static_cast<pending_read_operation*>(base));

    ptr p = { boost::asio::detail::addressof(o->handler_), o, o };

    BOOST_ASIO_HANDLER_COMPLETION((o));

    // Make a copy of the handler so that the memory can be deallocated before
    // the upcall is made. Even if we're not about to make an upcall, a
    // sub-object of the handler may be the true owner of the memory associated
    // with the handler. Consequently, a local copy of the handler is required
    // to ensure that any owning sub-object remains valid until after we have
    // deallocated the memory here.
    boost::asio::detail::binder2<Handler,
                                 boost::system::error_code,
                                 std::size_t> handler(
      o->handler_, ec, bytes_transferred);
    p.h = boost::asio::detail::addressof(handler.handler_);
    p.reset();

    // Make the upcall if required.
    if (!destroy)
    {
      boost::asio::detail::fenced_block b(boost::asio::detail::fenced_block::half);
      BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
      boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
      BOOST_ASIO_HANDLER_INVOCATION_END;
    }
  }

  /// Implementation of the filling buffer callback
  /**
  * @param base A pointer to the base class
  * @param stream The buffer to copy the data to
  */
  static size_t do_fill_buffers(basic_pending_io_operation* base,
                                boost::asio::streambuf& stream)
  {
    pending_read_operation* o(static_cast<pending_read_operation*>(base));

    size_t copied = 0;

    for (auto it_buffer = o->buffers_.begin(); it_buffer != o->buffers_.end();
          ++it_buffer)
    {
      size_t just_copied = boost::asio::buffer_copy(*it_buffer, stream.data());
      stream.consume(just_copied);
      copied += just_copied;
      if (!stream.size())
      {
        break;
      }
    }

    return copied;
  }

private:
  boost::asio::detail::consuming_buffers<mutable_buffer, MutableBufferSequence> buffers_;
  Handler handler_;
};

} // namespace detail
} // namespace fiber
} // namespace asio
} // namespace boost

#include <boost/asio/detail/pop_options.hpp>

#endif  // SSF_COMMON_BOOST_ASIO_FIBER_DETAIL_IO_FIBER_READ_OP_HPP_

max_stars_repo_name: ZhiQiAnSecFork/ssf

max_issues_repo_name: ZhiQiAnSecFork/ssf

max_forks_repo_name: ZhiQiAnSecFork/ssf


text:
/***************************************************************************
 * Copyright 1998-2020 by authors (see AUTHORS.txt)                        *
 *                                                                         *
 *   This file is part of LuxCoreRender.                                   *
 *                                                                         *
 * 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 <stdexcept>
#include <boost/foreach.hpp>
#include <boost/regex.hpp>

#include "slg/film/film.h"
#include "slg/film/imagepipeline/plugins/bakemapmargin.h"

using namespace std;
using namespace luxrays;
using namespace slg;

//------------------------------------------------------------------------------
// BakeMapMarginPlugin plugin
//------------------------------------------------------------------------------

BOOST_CLASS_EXPORT_IMPLEMENT(slg::BakeMapMarginPlugin)

BakeMapMarginPlugin::BakeMapMarginPlugin(const u_int pixels, const float threshold) :
		marginPixels(pixels), samplesThreshold(threshold) {
}

ImagePipelinePlugin *BakeMapMarginPlugin::Copy() const {
	return new BakeMapMarginPlugin(marginPixels, samplesThreshold);
}

void BakeMapMarginPlugin::Apply(Film &film, const u_int index) {
	Apply(film, index, marginPixels, samplesThreshold, false);
}

void BakeMapMarginPlugin::Apply(Film &film, const u_int index,
		const u_int marginPixels, const float samplesThreshold,
		const bool applyAlpha) {
	const bool hasPN = film.HasChannel(Film::RADIANCE_PER_PIXEL_NORMALIZED);
	const bool hasSN = film.HasChannel(Film::RADIANCE_PER_SCREEN_NORMALIZED);
	const bool hasAlpha = film.HasChannel(Film::ALPHA);

	const int width = (int)film.GetWidth();
	const int height = (int)film.GetHeight();
	const u_int pixelCount = width * height;

	Spectrum *pixels = (Spectrum *)film.channel_IMAGEPIPELINEs[index]->GetPixels();
	vector<Spectrum> tmpPixels(pixelCount);
	vector<float> tmpAlphas(pixelCount);
	vector<bool> srcPixelsMask(pixelCount);
	vector<bool> dstPixelsMask(pixelCount);

	#pragma omp parallel for
	for (int y = 0; y < height; ++y) {
		for (int x = 0; x < width; ++x) {
			const u_int pixelIndex = x + y * width;
			srcPixelsMask[pixelIndex] = film.HasThresholdSamples(hasPN, hasSN, pixelIndex, samplesThreshold);
		}
	}

	for (u_int step = 0; step < marginPixels; ++step) {
		#pragma omp parallel for
		for (int y = 0; y < height; ++y) {
			for (int x = 0; x < width; ++x) {
				const u_int pixelIndex = x + y * width;

				if (!srcPixelsMask[pixelIndex]) {
					// It is a pixel without any sample

					// Compute the average of all neighbors
					u_int count = 0;
					Spectrum c;
					float a = 0.f;
					for (int dy = -1; dy <= 1; ++dy) {
						for (int dx = -1; dx <= 1; ++dx) {
							int xx = x + dx;
							int yy = y + dy;
							const u_int index = xx + yy * width;

							// Check if it is a valid pixel
							if ((xx < 0) || (xx >= width) ||
									(yy < 0) || (yy >= height) ||
									((dx == 0) && (dy == 0)) ||
									!srcPixelsMask[index])
								continue;

							c += pixels[index];
							if (hasAlpha) {
								float value;
								film.channel_ALPHA->GetWeightedPixel(index, &value);
								a += value;
							}
							++count;
						}
					}

					if (count == 0) {
						tmpPixels[pixelIndex] = Spectrum();
						dstPixelsMask[pixelIndex] = false;

						if (hasAlpha)
							tmpAlphas[pixelIndex] = 1.f;
					} else {
						c /= count;
						tmpPixels[pixelIndex] = c;
						dstPixelsMask[pixelIndex] = true;

						if (hasAlpha) {
							a /= count;
							tmpAlphas[pixelIndex] = a;
						}
					}
				} else {
					// Just copy the pixel
					tmpPixels[pixelIndex] = pixels[pixelIndex];
					dstPixelsMask[pixelIndex] = true;

					if (hasAlpha) {
						float value;
						film.channel_ALPHA->GetWeightedPixel(pixelIndex, &value);

						tmpAlphas[pixelIndex] = value;
					}
				}
			}
		}

		copy(tmpPixels.begin(), tmpPixels.end(), &pixels[0]);
		if (hasAlpha && applyAlpha) {
			for (int y = 0; y < height; ++y) {
				for (int x = 0; x < width; ++x) {
					float *a = film.channel_ALPHA->GetPixel(x, y);
					a[0] = tmpAlphas[x + y * width];
					a[1] = 1.f;
				}
			}
		}
		copy(dstPixelsMask.begin(), dstPixelsMask.end(), srcPixelsMask.begin());
	}
}

max_stars_repo_name: OmidGhotbi/LuxCore

max_issues_repo_name: OmidGhotbi/LuxCore

max_forks_repo_name: OmidGhotbi/LuxCore


text:
// test_secretstream.cpp -- Test sodium::secretstream
//
// ISC License
//
// Copyright (C) 2018 Farid Hajji <farid@hajji.name>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

// To see test messages, including timing results:
//    ./test_secretstream --log_level=message

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE sodium::secretstream Test
#include <boost/test/included/unit_test.hpp>

#include "common.h"
#include "key.h"
#include "secretstream.h"
#include <sodium.h>
#include <stdexcept>
#include <string>
#include <utility>

template<typename BT>
BT
s2b(const std::string& s)
{
    BT vec{ s.cbegin(), s.cend() };
    return vec;
}

template<typename BT>
BT
s2b(void)
{
    BT vec;
    return vec; // empty vector
}

template<typename BT = sodium::bytes>
bool
test_of_correctness(bool falsify_ciphertext = false,
                    bool falsify_added_data = false,
                    bool falsify_header = false,
                    bool falsify_order = false,
                    bool falsify_skip_message = false,
                    bool falsify_skip_last_message = false,
                    bool test_rekey_out_of_band = false,
                    bool test_rekey_in_band = false)
{
    std::vector<BT> m{
        s2b<BT>("m0"), s2b<BT>("m#1"), s2b<BT>(), s2b<BT>("m3")
    }; // plaintexts
    std::vector<BT> a{
        s2b<BT>("a0"), s2b<BT>(), s2b<BT>("a#2"), s2b<BT>("a3")
    };                 // added data
    std::vector<BT> c; // ciphertexts with MAC
    BT m_dec;          // decrypted ciphertext

    auto tag_message{ sodium::secretstream<BT>::tag_message() };
    auto tag_final{ sodium::secretstream<BT>::tag_final() };
    auto tag_rekey{ sodium::secretstream<BT>::tag_rekey() };

    typename sodium::secretstream<BT>::key_type key; // random secret key

    // 1. encrypt stream

    sodium::secretstream<BT> se{ key }; // an encrypting stream
    BT header = se.init_push();

    for (std::size_t i = 0; i != m.size(); ++i) {
        if (test_rekey_out_of_band && i == 2) {
            se.rekey();
            BOOST_TEST_MESSAGE("sender: rekey(out-of-band) done");
        }

        auto tag = (test_rekey_in_band && i == 2) ? tag_rekey : tag_message;

        c.push_back(se.push(m[i], a[i], (i == m.size() - 1 ? tag_final : tag)));

        if (test_rekey_in_band && i == 2)
            BOOST_TEST_MESSAGE("sender: rekey(in-band) sent");
    }

    // 2. falsify stuff when needed
    if (falsify_ciphertext)
        ++(c[0].data()[0]);
    if (falsify_added_data)
        ++(a[0].data()[0]);
    if (falsify_header)
        ++(header.data()[0]);
    if (falsify_order) {
        std::swap(c[0], c[1]); // swap 1st and 2nd message
        std::swap(a[0], a[1]); // keep c and a in sync
        std::swap(m[0], m[1]); // keep c and m in sync
    }
    if (falsify_skip_message) {
        c.erase(c.begin() + 1); // remove 2nd message
        a.erase(a.begin() + 1); // keep c and a in sync
        m.erase(m.begin() + 1); // keep c and m in sync
    }
    if (falsify_skip_last_message) {
        c.pop_back(); // remove last message (w/ TAG_FINAL)
        a.pop_back(); // keep c and a in sync
        m.pop_back(); // keep c and m in sync
    }

    // 3. decrypt stream

    sodium::secretstream<BT> sd{ key }; // a decryption stream w/ same key

    std::size_t i = 0;
    try {
        sd.init_pull(header);

        auto tag{ sodium::secretstream<BT>::tag_message() };

        for (i = 0; i != c.size(); ++i) {
            if (test_rekey_out_of_band && i == 2) {
                sd.rekey();
                BOOST_TEST_MESSAGE("receiver: rekey(out-of-band) done");
            }

            m_dec = sd.pull(c[i], a[i], tag);

            BOOST_TEST(m_dec == m[i]);

            if (tag == tag_rekey)
                BOOST_TEST_MESSAGE("receiver: rekey(in-band) tag received");

            if (tag == tag_final)
                break; // that was the last message
        }
    } catch (std::runtime_error& e) {
        BOOST_TEST_MESSAGE(e.what());

        // if decryption failed, and one of the falsify_
        // flags was set, then it was expected and the
        // test _succeeded_. if no flags were set, the
        // test failed.
        return falsify_ciphertext || falsify_added_data || falsify_header ||
               falsify_order || falsify_skip_message;
    }

    if ((i + 1 != c.size()) && falsify_skip_last_message) {
        BOOST_TEST_MESSAGE("Program detected missing TAG_FINAL (as expected)");
        return true;
    }

    BOOST_TEST(i + 1 == c.size()); // or we missed some messages

    return true;
}

struct SodiumFixture
{
    SodiumFixture()
    {
        BOOST_REQUIRE(sodium_init() != -1);
        // BOOST_TEST_MESSAGE("SodiumFixture(): sodium_init() successful.");
    }
    ~SodiumFixture()
    {
        // BOOST_TEST_MESSAGE("~SodiumFixture(): teardown -- no-op.");
    }
};

BOOST_FIXTURE_TEST_SUITE(sodium_test_suite, SodiumFixture)

// 1: sodium::bytes ----------------------------------------------

BOOST_AUTO_TEST_CASE(sodium_secretstream_test_no_falsification_bytes)
{
    BOOST_TEST(test_of_correctness<>());
}

BOOST_AUTO_TEST_CASE(sodium_secretstream_test_falsify_ciphertext_bytes)
{
    BOOST_TEST(test_of_correctness<>(true));
}

BOOST_AUTO_TEST_CASE(sodium_secretstream_test_falsify_added_data_bytes)
{
    BOOST_TEST(test_of_correctness<>(false, true));
}

BOOST_AUTO_TEST_CASE(sodium_secretstream_test_falsify_header_bytes)
{
    BOOST_TEST(test_of_correctness<>(false, false, true));
}

BOOST_AUTO_TEST_CASE(sodium_secretstream_test_falsify_order_bytes)
{
    BOOST_TEST(test_of_correctness<>(false, false, false, true));
}

BOOST_AUTO_TEST_CASE(sodium_secretstream_test_falsify_skip_message_bytes)
{
    BOOST_TEST(test_of_correctness<>(false, false, false, false, true));
}

BOOST_AUTO_TEST_CASE(sodium_secretstream_test_falsify_skip_last_message_bytes)
{
    BOOST_TEST(test_of_correctness<>(false, false, false, false, false, true));
}

BOOST_AUTO_TEST_CASE(sodium_secretstream_test_rekey_out_of_band_bytes)
{
    BOOST_TEST(
      test_of_correctness<>(false, false, false, false, false, false, true));
}

BOOST_AUTO_TEST_CASE(sodium_secretstream_test_rekey_in_band_bytes)
{
    BOOST_TEST(test_of_correctness<>(
      false, false, false, false, false, false, false, true));
}

// 2: sodium::byte_protected ------------------------------------------

BOOST_AUTO_TEST_CASE(sodium_secretstream_test_no_falsification_bytes_protected)
{
    BOOST_TEST(test_of_correctness<sodium::bytes_protected>());
}

BOOST_AUTO_TEST_CASE(
  sodium_secretstream_test_falsify_ciphertext_bytes_protected)
{
    BOOST_TEST(test_of_correctness<sodium::bytes_protected>(true));
}

BOOST_AUTO_TEST_CASE(
  sodium_secretstream_test_falsify_added_data_bytes_protected)
{
    BOOST_TEST(test_of_correctness<sodium::bytes_protected>(false, true));
}

BOOST_AUTO_TEST_CASE(sodium_secretstream_test_falsify_header_bytes_protected)
{
    BOOST_TEST(
      test_of_correctness<sodium::bytes_protected>(false, false, true));
}

BOOST_AUTO_TEST_CASE(sodium_secretstream_test_falsify_order_bytes_protected)
{
    BOOST_TEST(
      test_of_correctness<sodium::bytes_protected>(false, false, false, true));
}

BOOST_AUTO_TEST_CASE(
  sodium_secretstream_test_falsify_skip_message_bytes_protected)
{
    BOOST_TEST(test_of_correctness<sodium::bytes_protected>(
      false, false, false, false, true));
}

BOOST_AUTO_TEST_CASE(
  sodium_secretstream_test_falsify_skip_last_message_bytes_protected)
{
    BOOST_TEST(test_of_correctness<sodium::bytes_protected>(
      false, false, false, false, false, true));
}

BOOST_AUTO_TEST_CASE(
  sodium_secretstream_test_falsify_test_rekey_out_of_band_bytes_protected)
{
    BOOST_TEST(test_of_correctness<sodium::bytes_protected>(
      false, false, false, false, false, false, true));
}

BOOST_AUTO_TEST_CASE(
  sodium_secretstream_test_falsify_test_rekey_in_band_bytes_protected)
{
    BOOST_TEST(test_of_correctness<sodium::bytes_protected>(
      false, false, false, false, false, false, false, true));
}

// XXX TODO: Test that other types for F are being rejected at compile-time.

BOOST_AUTO_TEST_SUITE_END()


text:
//==================================================================================================
/*!
  @file

  @copyright 2016 NumScale SAS

  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
//==================================================================================================
#ifndef BOOST_SIMD_CONSTANT_TRUE_HPP_INCLUDED
#define BOOST_SIMD_CONSTANT_TRUE_HPP_INCLUDED

/*!
  @ingroup group-constant
  @defgroup constant-True True (function template)

  Generates a constant that evaluates to the boolean @c true

  @headerref{<boost/simd/constant/true.hpp>}

  @par Description

  1.  @code
      template<typename T> as_logical_t<T> True();
      @endcode

  2.  @code
      template<typename T> as_logical_t<T> True( boost::simd::as_<T> const& target );
      @endcode

  Generates a value of type @c as_logical_t<T> that evaluates to the boolean @c true

  @par Parameters

  | Name                | Description                                                    |
  |--------------------:|:---------------------------------------------------------------|
  | **target**          | a [placeholder](@ref as) value encapsulating the constant type |

  @par Return Value
  A value of type @c as_logical_t<T> that evaluates to @c as_logical_t<T>(true).

  @par Requirements
  - **T** models Value
**/

#include <boost/simd/constant/scalar/true.hpp>
#include <boost/simd/constant/simd/true.hpp>

#endif

max_stars_repo_name: SylvainCorlay/pythran

max_issues_repo_name: SylvainCorlay/pythran

max_forks_repo_name: SylvainCorlay/pythran