<commit_before>#include "navstack_module.h"
#include <ros/ros.h>
#include <nav_msgs/GetPlan.h>
#include <geometry_msgs/PoseStamped.h>
#include <map>
using std::map;
#include <utility>
using std::pair; using std::make_pair;
#include <boost/foreach.hpp>
#ifdef __CDT_PARSER__
#define forEach(a, b) for(a : b)
#else
#define forEach BOOST_FOREACH
#endif
#include <sys/times.h>
#include <tf/tf.h>
#include <tf/transform_listener.h>

VERIFY_CONDITIONCHECKER_DEF(pathCost);

ros::NodeHandle* g_NodeHandle = NULL;
ros::ServiceClient g_GetPlan;

/// Plan requests are issued using this frame - so the poses from the planner are given in this frame (e.g. map)
std::string g_WorldFrame;

double g_GoalTolerance = 0.5;

// Using a cache of queried path costs to prevent calling the path planning service multiple times
// Better: Can we assume symmetric path costs?
map< pair<string,string>, double> g_PathCostCache;

void navstack_init(int argc, char** argv)
{
    ROS_ASSERT(argc == 4);

    // get world frame
    ros::NodeHandle nhPriv("~");
    std::string tfPrefix = tf::getPrefixParam(nhPriv);
    g_WorldFrame = tf::resolve(tfPrefix, argv[1]);
    ROS_INFO("World frame is: %s", g_WorldFrame.c_str());

    // get goal tolerance
    char* checkPtr;
    g_GoalTolerance = strtod(argv[2], &checkPtr);
    if(checkPtr == argv[2]) {    // conversion error!
        ROS_ERROR("%s: Could not convert argument for goal tolerance: %s", __func__, argv[2]);
        g_GoalTolerance = 0.5;
    }

    if(strcmp(argv[3], "0") == 0) {
        ROS_INFO("Using absolute goal tolerance.");
    } else { // relative goal tolerance, argv[3] contains the base_local_planner namespace
        ROS_INFO("Using relative goal tolerance.");
        // get base_local_planner's xy_goal_tolerance
        std::string base_local_planner_ns = argv[3];
        double move_base_tol;
        ros::NodeHandle nh;
        if(!nh.getParam(base_local_planner_ns + "/xy_goal_tolerance", move_base_tol)) {
            ROS_ERROR_STREAM("requested relative goal tolerance, but "
                    << (base_local_planner_ns + "/xy_goal_tolerance") << " was not set"
                    << " - falling back to absolute mode");
        } else { // 2. add move_base's tolerance to our relative tolerance
            g_GoalTolerance += move_base_tol;
        }
    }

    ROS_INFO("Goal Tolerance is: %f.", g_GoalTolerance);

    // init service query for make plan
    string service_name = "move_base/make_plan";
    g_NodeHandle = new ros::NodeHandle();
    while(!ros::service::waitForService(service_name, ros::Duration(3.0))) {
        ROS_ERROR("Service %s not available - waiting.", service_name.c_str());
    }

    g_GetPlan = g_NodeHandle->serviceClient<nav_msgs::GetPlan>(service_name, true);
    if(!g_GetPlan) {
        ROS_FATAL("Could not initialize get plan service from %s (client name: %s)", service_name.c_str(), g_GetPlan.getService().c_str());
    }

    ROS_INFO("Initialized Navstack Module.\n");
}

bool fillPathRequest(const ParameterList & parameterList, numericalFluentCallbackType numericalFluentCallback,
        nav_msgs::GetPlan::Request & request)
{
    // get robot and target location from planner interface
    ROS_ASSERT(parameterList.size() == 2);

    ParameterList startParams;
    startParams.push_back(parameterList[0]);
    ParameterList goalParams;
    goalParams.push_back(parameterList[1]);
    NumericalFluentList nfRequest;
    nfRequest.reserve(14);
    nfRequest.push_back(NumericalFluent("x", startParams));
    nfRequest.push_back(NumericalFluent("y", startParams));
    nfRequest.push_back(NumericalFluent("z", startParams));
    nfRequest.push_back(NumericalFluent("qx", startParams));
    nfRequest.push_back(NumericalFluent("qy", startParams));
    nfRequest.push_back(NumericalFluent("qz", startParams));
    nfRequest.push_back(NumericalFluent("qw", startParams));
    nfRequest.push_back(NumericalFluent("x", goalParams));
    nfRequest.push_back(NumericalFluent("y", goalParams));
    nfRequest.push_back(NumericalFluent("z", goalParams));
    nfRequest.push_back(NumericalFluent("qx", goalParams));
    nfRequest.push_back(NumericalFluent("qy", goalParams));
    nfRequest.push_back(NumericalFluent("qz", goalParams));
    nfRequest.push_back(NumericalFluent("qw", goalParams));

    NumericalFluentList* nfRequestP = &nfRequest;
    if(!numericalFluentCallback(nfRequestP)) {
        ROS_ERROR("numericalFluentCallback failed.");
        return false;
    }

    // create the path planning query for service
    request.start.header.frame_id = g_WorldFrame;
    request.goal.header.frame_id = g_WorldFrame;
    request.start.pose.position.x = nfRequest[0].value;
    request.start.pose.position.y = nfRequest[1].value;
    request.start.pose.position.z = nfRequest[2].value;
    request.start.pose.orientation.x = nfRequest[3].value;
    request.start.pose.orientation.y = nfRequest[4].value;
    request.start.pose.orientation.z = nfRequest[5].value;
    request.start.pose.orientation.w = nfRequest[6].value;
    request.goal.pose.position.x = nfRequest[7].value;
    request.goal.pose.position.y = nfRequest[8].value;
    request.goal.pose.position.z = nfRequest[9].value;
    request.goal.pose.orientation.x = nfRequest[10].value;
    request.goal.pose.orientation.y = nfRequest[11].value;
    request.goal.pose.orientation.z = nfRequest[12].value;
    request.goal.pose.orientation.w = nfRequest[13].value;
    request.tolerance = g_GoalTolerance;
    return true;
}

double pathCost(const ParameterList & parameterList,
        predicateCallbackType predicateCallback, numericalFluentCallbackType numericalFluentCallback, int relaxed)
{
    if(g_Debug) {        // prevent spamming ROS_DEBUG calls unless we really want debug
        // debugging raw planner calls
        static unsigned int calls = 0;
        calls++;
        if(calls % 10000 == 0) {
            ROS_DEBUG("Got %d module calls.\n", calls);
        }
    }

    // first lookup in the cache if we answered the query already
    map<pair<string, string>, double>::iterator it = g_PathCostCache.find(make_pair(parameterList[0].value, parameterList[1].value));
    if(it != g_PathCostCache.end()) {
        return it->second;
    }

    nav_msgs::GetPlan srv;
    if(!fillPathRequest(parameterList, numericalFluentCallback, srv.request)) {
        return INFINITE_COST;
    }

    double cost = INFINITE_COST;

    if(!g_GetPlan) {
        ROS_ERROR("Persistent service connection to %s failed.", g_GetPlan.getService().c_str());
        // FIXME reconnect - this shouldn't happen.
        return INFINITE_COST;
    }

    // statistics about using the ros path planner service
    static double plannerCalls = 0;
    static ros::Duration totalCallsTime = ros::Duration(0.0);
    plannerCalls += 1.0;

    ros::Time callStartTime = ros::Time::now();
    // This construct is here, because when the robot is moving move_base will not produce other paths
    // we retry for a certain amount of time to not fail directly.
    // FIXME: Cleanup the goto code
retryGetPlan:
    static unsigned int failCounter = 0;

    // perform the actual path planner call
    if(g_GetPlan.call(srv)) {
        failCounter = 0;

        if(g_Debug) {
            ros::Time callEndTime = ros::Time::now();
            ros::Duration dt = callEndTime - callStartTime;
            totalCallsTime += dt;
            ROS_DEBUG("ServiceCall took: %f, avg: %f (num %f).", dt.toSec(), totalCallsTime.toSec()/plannerCalls, plannerCalls);
        }

        if(!srv.response.plan.poses.empty()) {
            // get plan cost
            double pathLength = 0;
            geometry_msgs::PoseStamped lastPose = srv.response.plan.poses[0];
            forEach(const geometry_msgs::PoseStamped & p, srv.response.plan.poses) {
                double d = hypot(lastPose.pose.position.x - p.pose.position.x,
                        lastPose.pose.position.y - p.pose.position.y);
                pathLength += d;
                lastPose = p;
            }
            cost = pathLength;
        } else {
            ROS_WARN("Got empty plan: %s -> %s", parameterList[0].value.c_str(), parameterList[1].value.c_str());
        }

        //ROS_INFO("Got plan: %s -> %s cost: %f.", parameterList[0].value.c_str(), parameterList[1].value.c_str(), cost);
        // also empty plan = OK or fail or none?
    } else {
        ROS_ERROR("Failed to call service %s - is the robot moving?", g_GetPlan.getService().c_str());
        failCounter++;
        if(failCounter < 300) {
            usleep(1000 * 1000);
            goto retryGetPlan;
        }
        // FIXME: what if target is unreachable, do we get false or an empty plan? i.e. is this an error
        return INFINITE_COST;
    }

    // return pathcost and cache
    g_PathCostCache[make_pair(parameterList[0].value, parameterList[1].value)] = cost;

    return cost;
}

<commit_msg>navstack_module tries to auto estimate ns<commit_after>#include "navstack_module.h"
#include <ros/ros.h>
#include <nav_msgs/GetPlan.h>
#include <geometry_msgs/PoseStamped.h>
#include <map>
using std::map;
#include <utility>
using std::pair; using std::make_pair;
#include <boost/foreach.hpp>
#ifdef __CDT_PARSER__
#define forEach(a, b) for(a : b)
#else
#define forEach BOOST_FOREACH
#endif
#include <sys/times.h>
#include <tf/tf.h>
#include <tf/transform_listener.h>

VERIFY_CONDITIONCHECKER_DEF(pathCost);

ros::NodeHandle* g_NodeHandle = NULL;
ros::ServiceClient g_GetPlan;

/// Plan requests are issued using this frame - so the poses from the planner are given in this frame (e.g. map)
std::string g_WorldFrame;

double g_GoalTolerance = 0.5;

// Using a cache of queried path costs to prevent calling the path planning service multiple times
// Better: Can we assume symmetric path costs?
map< pair<string,string>, double> g_PathCostCache;

void navstack_init(int argc, char** argv)
{
    ROS_ASSERT(argc == 4);

    // get world frame
    ros::NodeHandle nhPriv("~");
    std::string tfPrefix = tf::getPrefixParam(nhPriv);
    g_WorldFrame = tf::resolve(tfPrefix, argv[1]);
    ROS_INFO("World frame is: %s", g_WorldFrame.c_str());

    // get goal tolerance
    char* checkPtr;
    g_GoalTolerance = strtod(argv[2], &checkPtr);
    if(checkPtr == argv[2]) {    // conversion error!
        ROS_ERROR("%s: Could not convert argument for goal tolerance: %s", __func__, argv[2]);
        g_GoalTolerance = 0.5;
    }

    ros::NodeHandle nh;
    std::string base_local_planner_ns;
    if(strcmp(argv[3], "0") == 0) {
        ROS_INFO("Using absolute goal tolerance.");
    } else if(strcmp(argv[3], "1") == 0) {
        ROS_INFO("Trying to estimate base_local_planner namespace");

        std::string local_planner;
        if(!nh.getParam("move_base_node/base_local_planner", local_planner)
                && !nh.getParam("move_base/base_local_planner", local_planner)) {
            ROS_ERROR("move_base(_node)/base_local_planner not set - falling back to absolute mode.");
        } else {
            // dwa_local_planner/DWAPlannerROS -> DWAPlannerROS
            std::string::size_type x = local_planner.find_last_of("/");
            if(x == std::string::npos)
                base_local_planner_ns = local_planner;
            else
                base_local_planner_ns = local_planner.substr(x + 1);
            ROS_INFO("Estimated base_local_planner_ns to %s.", base_local_planner_ns.c_str());
        }
    } else {
        base_local_planner_ns = argv[3];
    }

    if(!base_local_planner_ns.empty()) {
        // relative goal tolerance, argv[3] contains the base_local_planner namespace
        ROS_INFO("Using relative goal tolerance.");
        // get base_local_planner's xy_goal_tolerance
        double move_base_tol;
        if(!nh.getParam(base_local_planner_ns + "/xy_goal_tolerance", move_base_tol)) {
            ROS_ERROR_STREAM("requested relative goal tolerance, but "
                    << (base_local_planner_ns + "/xy_goal_tolerance") << " was not set"
                    << " - falling back to absolute mode");
        } else { // 2. add move_base's tolerance to our relative tolerance
            g_GoalTolerance += move_base_tol;
        }
    }

    ROS_INFO("Goal Tolerance is: %f.", g_GoalTolerance);

    // init service query for make plan
    string service_name = "move_base/make_plan";
    g_NodeHandle = new ros::NodeHandle();
    while(!ros::service::waitForService(service_name, ros::Duration(3.0))) {
        ROS_ERROR("Service %s not available - waiting.", service_name.c_str());
    }

    g_GetPlan = g_NodeHandle->serviceClient<nav_msgs::GetPlan>(service_name, true);
    if(!g_GetPlan) {
        ROS_FATAL("Could not initialize get plan service from %s (client name: %s)", service_name.c_str(), g_GetPlan.getService().c_str());
    }

    ROS_INFO("Initialized Navstack Module.\n");
}

bool fillPathRequest(const ParameterList & parameterList, numericalFluentCallbackType numericalFluentCallback,
        nav_msgs::GetPlan::Request & request)
{
    // get robot and target location from planner interface
    ROS_ASSERT(parameterList.size() == 2);

    ParameterList startParams;
    startParams.push_back(parameterList[0]);
    ParameterList goalParams;
    goalParams.push_back(parameterList[1]);
    NumericalFluentList nfRequest;
    nfRequest.reserve(14);
    nfRequest.push_back(NumericalFluent("x", startParams));
    nfRequest.push_back(NumericalFluent("y", startParams));
    nfRequest.push_back(NumericalFluent("z", startParams));
    nfRequest.push_back(NumericalFluent("qx", startParams));
    nfRequest.push_back(NumericalFluent("qy", startParams));
    nfRequest.push_back(NumericalFluent("qz", startParams));
    nfRequest.push_back(NumericalFluent("qw", startParams));
    nfRequest.push_back(NumericalFluent("x", goalParams));
    nfRequest.push_back(NumericalFluent("y", goalParams));
    nfRequest.push_back(NumericalFluent("z", goalParams));
    nfRequest.push_back(NumericalFluent("qx", goalParams));
    nfRequest.push_back(NumericalFluent("qy", goalParams));
    nfRequest.push_back(NumericalFluent("qz", goalParams));
    nfRequest.push_back(NumericalFluent("qw", goalParams));

    NumericalFluentList* nfRequestP = &nfRequest;
    if(!numericalFluentCallback(nfRequestP)) {
        ROS_ERROR("numericalFluentCallback failed.");
        return false;
    }

    // create the path planning query for service
    request.start.header.frame_id = g_WorldFrame;
    request.goal.header.frame_id = g_WorldFrame;
    request.start.pose.position.x = nfRequest[0].value;
    request.start.pose.position.y = nfRequest[1].value;
    request.start.pose.position.z = nfRequest[2].value;
    request.start.pose.orientation.x = nfRequest[3].value;
    request.start.pose.orientation.y = nfRequest[4].value;
    request.start.pose.orientation.z = nfRequest[5].value;
    request.start.pose.orientation.w = nfRequest[6].value;
    request.goal.pose.position.x = nfRequest[7].value;
    request.goal.pose.position.y = nfRequest[8].value;
    request.goal.pose.position.z = nfRequest[9].value;
    request.goal.pose.orientation.x = nfRequest[10].value;
    request.goal.pose.orientation.y = nfRequest[11].value;
    request.goal.pose.orientation.z = nfRequest[12].value;
    request.goal.pose.orientation.w = nfRequest[13].value;
    request.tolerance = g_GoalTolerance;
    return true;
}

double pathCost(const ParameterList & parameterList,
        predicateCallbackType predicateCallback, numericalFluentCallbackType numericalFluentCallback, int relaxed)
{
    if(g_Debug) {        // prevent spamming ROS_DEBUG calls unless we really want debug
        // debugging raw planner calls
        static unsigned int calls = 0;
        calls++;
        if(calls % 10000 == 0) {
            ROS_DEBUG("Got %d module calls.\n", calls);
        }
    }

    // first lookup in the cache if we answered the query already
    map<pair<string, string>, double>::iterator it = g_PathCostCache.find(make_pair(parameterList[0].value, parameterList[1].value));
    if(it != g_PathCostCache.end()) {
        return it->second;
    }

    nav_msgs::GetPlan srv;
    if(!fillPathRequest(parameterList, numericalFluentCallback, srv.request)) {
        return INFINITE_COST;
    }

    double cost = INFINITE_COST;

    if(!g_GetPlan) {
        ROS_ERROR("Persistent service connection to %s failed.", g_GetPlan.getService().c_str());
        // FIXME reconnect - this shouldn't happen.
        return INFINITE_COST;
    }

    // statistics about using the ros path planner service
    static double plannerCalls = 0;
    static ros::Duration totalCallsTime = ros::Duration(0.0);
    plannerCalls += 1.0;

    ros::Time callStartTime = ros::Time::now();
    // This construct is here, because when the robot is moving move_base will not produce other paths
    // we retry for a certain amount of time to not fail directly.
    // FIXME: Cleanup the goto code
retryGetPlan:
    static unsigned int failCounter = 0;

    // perform the actual path planner call
    if(g_GetPlan.call(srv)) {
        failCounter = 0;

        if(g_Debug) {
            ros::Time callEndTime = ros::Time::now();
            ros::Duration dt = callEndTime - callStartTime;
            totalCallsTime += dt;
            ROS_DEBUG("ServiceCall took: %f, avg: %f (num %f).", dt.toSec(), totalCallsTime.toSec()/plannerCalls, plannerCalls);
        }

        if(!srv.response.plan.poses.empty()) {
            // get plan cost
            double pathLength = 0;
            geometry_msgs::PoseStamped lastPose = srv.response.plan.poses[0];
            forEach(const geometry_msgs::PoseStamped & p, srv.response.plan.poses) {
                double d = hypot(lastPose.pose.position.x - p.pose.position.x,
                        lastPose.pose.position.y - p.pose.position.y);
                pathLength += d;
                lastPose = p;
            }
            cost = pathLength;
        } else {
            ROS_WARN("Got empty plan: %s -> %s", parameterList[0].value.c_str(), parameterList[1].value.c_str());
        }

        //ROS_INFO("Got plan: %s -> %s cost: %f.", parameterList[0].value.c_str(), parameterList[1].value.c_str(), cost);
        // also empty plan = OK or fail or none?
    } else {
        ROS_ERROR("Failed to call service %s - is the robot moving?", g_GetPlan.getService().c_str());
        failCounter++;
        if(failCounter < 300) {
            usleep(1000 * 1000);
            goto retryGetPlan;
        }
        // FIXME: what if target is unreachable, do we get false or an empty plan? i.e. is this an error
        return INFINITE_COST;
    }

    // return pathcost and cache
    g_PathCostCache[make_pair(parameterList[0].value, parameterList[1].value)] = cost;

    return cost;
}

<|endoftext|>


<commit_before>#include <iostream>

// Include before boost::log headers
#include "restc-cpp/logging.h"

#include "restc-cpp/restc-cpp.h"
#include "restc-cpp/RequestBuilder.h"

#include "restc-cpp/test_helper.h"
#include "lest/lest.hpp"

using namespace std;
using namespace restc_cpp;

static const string defunct_proxy_address = GetDockerUrl("http://172.17.0.1:0");
static const string http_proxy_address = GetDockerUrl("http://172.17.0.1:3003");
static const string socks5_proxy_address = GetDockerUrl("172.17.0.1:3004");

const lest::test specification[] = {

STARTCASE(TestFailToConnect)
{
    Request::Properties properties;
    properties.proxy.type = Request::Proxy::Type::HTTP;
    properties.proxy.address = defunct_proxy_address;

    // Create the client with our configuration
    auto rest_client = RestClient::Create(properties);

    EXPECT_THROWS(rest_client->ProcessWithPromise([&](Context& ctx) {
        auto reply = RequestBuilder(ctx)
            .Get("http://api.example.com/normal/posts/1")
            .Execute();

    }).get());
} ENDCASE

STARTCASE(TestWithHttpProxy)
{
    Request::Properties properties;
    properties.proxy.type = Request::Proxy::Type::HTTP;
    properties.proxy.address = http_proxy_address;

    // Create the client with our configuration
    auto rest_client = RestClient::Create(properties);

    rest_client->ProcessWithPromise([&](Context& ctx) {
        auto reply = RequestBuilder(ctx)
            .Get("http://api.example.com/normal/posts/1")
            .Execute();

            cout << "Got: " << reply->GetBodyAsString() << endl;
    }).get();
} ENDCASE

STARTCASE(TestWithSocks5Proxy)
{
    Request::Properties properties;
    properties.proxy.type = Request::Proxy::Type::SOCKS5;
    properties.proxy.address = socks5_proxy_address;

    // Create the client with our configuration
    auto rest_client = RestClient::Create(properties);

    rest_client->ProcessWithPromise([&](Context& ctx) {
        auto reply = RequestBuilder(ctx)
            .Get("http://api.example.com/normal/posts/1")
            .Execute();

            cout << "Got: " << reply->GetBodyAsString() << endl;
    }).get();
} ENDCASE

}; //lest

int main( int argc, char * argv[] )
{
    RESTC_CPP_TEST_LOGGING_SETUP("debug");

    return lest::run( specification, argc, argv );
}
<commit_msg>Changed (back) the default address to mock backend<commit_after>#include <iostream>

// Include before boost::log headers
#include "restc-cpp/logging.h"

#include "restc-cpp/restc-cpp.h"
#include "restc-cpp/RequestBuilder.h"

#include "restc-cpp/test_helper.h"
#include "lest/lest.hpp"

using namespace std;
using namespace restc_cpp;

static const string defunct_proxy_address = GetDockerUrl("http://localhost:0");
static const string http_proxy_address = GetDockerUrl("http://localhost:3003");
static const string socks5_proxy_address = GetDockerUrl("localhost:3004");

const lest::test specification[] = {

STARTCASE(TestFailToConnect)
{
    Request::Properties properties;
    properties.proxy.type = Request::Proxy::Type::HTTP;
    properties.proxy.address = defunct_proxy_address;

    // Create the client with our configuration
    auto rest_client = RestClient::Create(properties);

    EXPECT_THROWS(rest_client->ProcessWithPromise([&](Context& ctx) {
        auto reply = RequestBuilder(ctx)
            .Get("http://api.example.com/normal/posts/1")
            .Execute();

    }).get());
} ENDCASE

STARTCASE(TestWithHttpProxy)
{
    Request::Properties properties;
    properties.proxy.type = Request::Proxy::Type::HTTP;
    properties.proxy.address = http_proxy_address;

    // Create the client with our configuration
    auto rest_client = RestClient::Create(properties);

    rest_client->ProcessWithPromise([&](Context& ctx) {
        auto reply = RequestBuilder(ctx)
            .Get("http://api.example.com/normal/posts/1")
            .Execute();

            cout << "Got: " << reply->GetBodyAsString() << endl;
    }).get();
} ENDCASE

STARTCASE(TestWithSocks5Proxy)
{
    Request::Properties properties;
    properties.proxy.type = Request::Proxy::Type::SOCKS5;
    properties.proxy.address = socks5_proxy_address;

    // Create the client with our configuration
    auto rest_client = RestClient::Create(properties);

    rest_client->ProcessWithPromise([&](Context& ctx) {
        auto reply = RequestBuilder(ctx)
            .Get("http://api.example.com/normal/posts/1")
            .Execute();

            cout << "Got: " << reply->GetBodyAsString() << endl;
    }).get();
} ENDCASE

}; //lest

int main( int argc, char * argv[] )
{
    RESTC_CPP_TEST_LOGGING_SETUP("debug");

    return lest::run( specification, argc, argv );
}
<|endoftext|>


<commit_before>/*-------------------------------------------------------------------------
* Vulkan Conformance Tests
* ------------------------
*
* Copyright (c) 2018 Advanced Micro Devices, Inc.
* Copyright (c) 2018 The Khronos Group Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*//*!
* \file
* \brief VK_KHR_driver_properties tests
*//*--------------------------------------------------------------------*/

#include "vktApiDriverPropertiesTests.hpp"
#include "vktTestGroupUtil.hpp"
#include "vktTestCaseUtil.hpp"
#include "vkQueryUtil.hpp"
#include "vkTypeUtil.hpp"
#include "vkKnownDriverIds.inl"

using namespace vk;

namespace vkt
{
namespace api
{
namespace
{

enum TestType
{
	TEST_TYPE_DRIVER_ID_MATCH			= 0,
	TEST_TYPE_NAME_IS_NOT_EMPTY,
	TEST_TYPE_NAME_ZERO_TERMINATED,
	TEST_TYPE_INFO_ZERO_TERMINATED,
	TEST_TYPE_VERSION,
};

static const VkConformanceVersion knownConformanceVersions[] =
{
#ifndef CTS_USES_VULKANSC
	makeConformanceVersion(1, 3, 3, 0),
	makeConformanceVersion(1, 3, 2, 0),
	makeConformanceVersion(1, 3, 1, 1),
	makeConformanceVersion(1, 3, 1, 0),
	makeConformanceVersion(1, 3, 0, 0),
	makeConformanceVersion(1, 2, 8, 0),
	makeConformanceVersion(1, 2, 7, 2),
	makeConformanceVersion(1, 2, 7, 1),
	makeConformanceVersion(1, 2, 7, 0),
	makeConformanceVersion(1, 2, 6, 2),
	makeConformanceVersion(1, 2, 6, 1),
	makeConformanceVersion(1, 2, 6, 0),
	makeConformanceVersion(1, 2, 5, 2),
	makeConformanceVersion(1, 2, 5, 1),
	makeConformanceVersion(1, 2, 5, 0),
	makeConformanceVersion(1, 2, 4, 1),
	makeConformanceVersion(1, 2, 4, 0),
	makeConformanceVersion(1, 2, 3, 3),
	makeConformanceVersion(1, 2, 3, 2),
	makeConformanceVersion(1, 2, 3, 1),
	makeConformanceVersion(1, 2, 3, 0),
	makeConformanceVersion(1, 2, 2, 2),
	makeConformanceVersion(1, 2, 2, 1),
	makeConformanceVersion(1, 2, 2, 0),
	makeConformanceVersion(1, 2, 1, 2),
	makeConformanceVersion(1, 2, 1, 1),
	makeConformanceVersion(1, 2, 1, 0),
	makeConformanceVersion(1, 2, 0, 2),
	makeConformanceVersion(1, 2, 0, 1),
	makeConformanceVersion(1, 2, 0, 0),
	makeConformanceVersion(1, 1, 6, 3),
	makeConformanceVersion(1, 1, 6, 2),
	makeConformanceVersion(1, 1, 6, 1),
	makeConformanceVersion(1, 1, 6, 0),
	makeConformanceVersion(1, 1, 5, 2),
	makeConformanceVersion(1, 1, 5, 1),
	makeConformanceVersion(1, 1, 5, 0),
	makeConformanceVersion(1, 1, 4, 3),
	makeConformanceVersion(1, 1, 4, 2),
	makeConformanceVersion(1, 1, 4, 1),
	makeConformanceVersion(1, 1, 4, 0),
	makeConformanceVersion(1, 1, 3, 3),
	makeConformanceVersion(1, 1, 3, 2),
	makeConformanceVersion(1, 1, 3, 1),
	makeConformanceVersion(1, 1, 3, 0),
#else
	makeConformanceVersion(1, 0, 0, 0),
#endif // CTS_USES_VULKANSC
};

DE_INLINE bool isNullTerminated(const char* str, const deUint32 maxSize)
{
	return deStrnlen(str, maxSize) < maxSize;
}

DE_INLINE bool operator==(const VkConformanceVersion& a, const VkConformanceVersion& b)
{
	return ((a.major == b.major)		&&
			(a.minor == b.minor)		&&
			(a.subminor == b.subminor)	&&
			(a.patch == b.patch));
}

void checkSupport (Context& context, const TestType config)
{
	DE_UNREF(config);
	context.requireDeviceFunctionality("VK_KHR_driver_properties");
}

void testDriverMatch (const VkPhysicalDeviceDriverProperties& deviceDriverProperties)
{
	for (deUint32 driverNdx = 0; driverNdx < DE_LENGTH_OF_ARRAY(driverIds); driverNdx++)
	{
		if (deviceDriverProperties.driverID == driverIds[driverNdx].id)
			return;
	}

	TCU_FAIL("Driver ID did not match any known driver");
}

void testNameIsNotEmpty (const VkPhysicalDeviceDriverProperties& deviceDriverProperties)
{
	if (deviceDriverProperties.driverName[0] == 0)
		TCU_FAIL("Driver name is empty");
}

void testNameZeroTerminated (const VkPhysicalDeviceDriverProperties& deviceDriverProperties)
{
	if (!isNullTerminated(deviceDriverProperties.driverName, VK_MAX_DRIVER_NAME_SIZE))
		TCU_FAIL("Driver name is not a null-terminated string");
}

void testInfoZeroTerminated (const VkPhysicalDeviceDriverProperties& deviceDriverProperties)
{
	if (!isNullTerminated(deviceDriverProperties.driverInfo, VK_MAX_DRIVER_INFO_SIZE))
		TCU_FAIL("Driver info is not a null-terminated string");
}

void testVersion (const VkPhysicalDeviceDriverProperties& deviceDriverProperties, deUint32 usedApiVersion)
{
	const deUint32 apiMajorVersion = VK_API_VERSION_MAJOR(usedApiVersion);
	const deUint32 apiMinorVersion = VK_API_VERSION_MINOR(usedApiVersion);

	if (deviceDriverProperties.conformanceVersion.major < apiMajorVersion ||
		(deviceDriverProperties.conformanceVersion.major == apiMajorVersion &&
		 deviceDriverProperties.conformanceVersion.minor < apiMinorVersion))
	{
		TCU_FAIL("Wrong driver conformance version (older than used API version)");
	}

	for (const VkConformanceVersion*	pConformanceVersion  = knownConformanceVersions;
										pConformanceVersion != DE_ARRAY_END(knownConformanceVersions);
									  ++pConformanceVersion)
	{
		if (deviceDriverProperties.conformanceVersion == *pConformanceVersion)
			return;
	}

	TCU_FAIL("Wrong driver conformance version (not known)");
}

tcu::TestStatus testQueryProperties (Context& context, const TestType testType)
{
	// Query the driver properties
	const VkPhysicalDevice				physDevice			= context.getPhysicalDevice();
	const int							memsetPattern		= 0xaa;
	VkPhysicalDeviceProperties2			deviceProperties2;
	VkPhysicalDeviceDriverProperties	deviceDriverProperties;

	deMemset(&deviceDriverProperties, memsetPattern, sizeof(deviceDriverProperties));
	deviceDriverProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
	deviceDriverProperties.pNext = DE_NULL;

	deMemset(&deviceProperties2, memsetPattern, sizeof(deviceProperties2));
	deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
	deviceProperties2.pNext = &deviceDriverProperties;

	context.getInstanceInterface().getPhysicalDeviceProperties2(physDevice, &deviceProperties2);

	// Verify the returned values
	switch (testType)
	{
		case TEST_TYPE_DRIVER_ID_MATCH:			testDriverMatch			(deviceDriverProperties);								break;
		case TEST_TYPE_NAME_IS_NOT_EMPTY:		testNameIsNotEmpty		(deviceDriverProperties);								break;
		case TEST_TYPE_NAME_ZERO_TERMINATED:	testNameZeroTerminated	(deviceDriverProperties);								break;
		case TEST_TYPE_INFO_ZERO_TERMINATED:	testInfoZeroTerminated	(deviceDriverProperties);								break;
		case TEST_TYPE_VERSION:					testVersion				(deviceDriverProperties, context.getUsedApiVersion());	break;
		default:								TCU_THROW(InternalError, "Unknown test type specified");
	}

	return tcu::TestStatus::pass("Pass");
}

void createTestCases (tcu::TestCaseGroup* group)
{
	addFunctionCase(group, "driver_id_match",		"Check driverID is supported",					checkSupport,	testQueryProperties,	TEST_TYPE_DRIVER_ID_MATCH);
	addFunctionCase(group, "name_is_not_empty",		"Check name field is not empty",				checkSupport,	testQueryProperties,	TEST_TYPE_NAME_IS_NOT_EMPTY);
	addFunctionCase(group, "name_zero_terminated",	"Check name field is zero-terminated",			checkSupport,	testQueryProperties,	TEST_TYPE_NAME_ZERO_TERMINATED);
	addFunctionCase(group, "info_zero_terminated",	"Check info field is zero-terminated",			checkSupport,	testQueryProperties,	TEST_TYPE_INFO_ZERO_TERMINATED);
	addFunctionCase(group, "conformance_version",	"Check conformanceVersion reported by driver",	checkSupport,	testQueryProperties,	TEST_TYPE_VERSION);
}

} // anonymous

tcu::TestCaseGroup*	createDriverPropertiesTests(tcu::TestContext& testCtx)
{
	return createTestGroup(testCtx, "driver_properties", "VK_KHR_driver_properties tests", createTestCases);
}

} // api
} // vkt
<commit_msg>Update known conformance version for 1.3.3.1<commit_after>/*-------------------------------------------------------------------------
* Vulkan Conformance Tests
* ------------------------
*
* Copyright (c) 2018 Advanced Micro Devices, Inc.
* Copyright (c) 2018 The Khronos Group Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*//*!
* \file
* \brief VK_KHR_driver_properties tests
*//*--------------------------------------------------------------------*/

#include "vktApiDriverPropertiesTests.hpp"
#include "vktTestGroupUtil.hpp"
#include "vktTestCaseUtil.hpp"
#include "vkQueryUtil.hpp"
#include "vkTypeUtil.hpp"
#include "vkKnownDriverIds.inl"

using namespace vk;

namespace vkt
{
namespace api
{
namespace
{

enum TestType
{
	TEST_TYPE_DRIVER_ID_MATCH			= 0,
	TEST_TYPE_NAME_IS_NOT_EMPTY,
	TEST_TYPE_NAME_ZERO_TERMINATED,
	TEST_TYPE_INFO_ZERO_TERMINATED,
	TEST_TYPE_VERSION,
};

static const VkConformanceVersion knownConformanceVersions[] =
{
#ifndef CTS_USES_VULKANSC
	makeConformanceVersion(1, 3, 3, 1),
	makeConformanceVersion(1, 3, 3, 0),
	makeConformanceVersion(1, 3, 2, 0),
	makeConformanceVersion(1, 3, 1, 1),
	makeConformanceVersion(1, 3, 1, 0),
	makeConformanceVersion(1, 3, 0, 0),
	makeConformanceVersion(1, 2, 8, 0),
	makeConformanceVersion(1, 2, 7, 2),
	makeConformanceVersion(1, 2, 7, 1),
	makeConformanceVersion(1, 2, 7, 0),
	makeConformanceVersion(1, 2, 6, 2),
	makeConformanceVersion(1, 2, 6, 1),
	makeConformanceVersion(1, 2, 6, 0),
	makeConformanceVersion(1, 2, 5, 2),
	makeConformanceVersion(1, 2, 5, 1),
	makeConformanceVersion(1, 2, 5, 0),
	makeConformanceVersion(1, 2, 4, 1),
	makeConformanceVersion(1, 2, 4, 0),
	makeConformanceVersion(1, 2, 3, 3),
	makeConformanceVersion(1, 2, 3, 2),
	makeConformanceVersion(1, 2, 3, 1),
	makeConformanceVersion(1, 2, 3, 0),
	makeConformanceVersion(1, 2, 2, 2),
	makeConformanceVersion(1, 2, 2, 1),
	makeConformanceVersion(1, 2, 2, 0),
	makeConformanceVersion(1, 2, 1, 2),
	makeConformanceVersion(1, 2, 1, 1),
	makeConformanceVersion(1, 2, 1, 0),
	makeConformanceVersion(1, 2, 0, 2),
	makeConformanceVersion(1, 2, 0, 1),
	makeConformanceVersion(1, 2, 0, 0),
	makeConformanceVersion(1, 1, 6, 3),
	makeConformanceVersion(1, 1, 6, 2),
	makeConformanceVersion(1, 1, 6, 1),
	makeConformanceVersion(1, 1, 6, 0),
	makeConformanceVersion(1, 1, 5, 2),
	makeConformanceVersion(1, 1, 5, 1),
	makeConformanceVersion(1, 1, 5, 0),
	makeConformanceVersion(1, 1, 4, 3),
	makeConformanceVersion(1, 1, 4, 2),
	makeConformanceVersion(1, 1, 4, 1),
	makeConformanceVersion(1, 1, 4, 0),
	makeConformanceVersion(1, 1, 3, 3),
	makeConformanceVersion(1, 1, 3, 2),
	makeConformanceVersion(1, 1, 3, 1),
	makeConformanceVersion(1, 1, 3, 0),
#else
	makeConformanceVersion(1, 0, 0, 0),
#endif // CTS_USES_VULKANSC
};

DE_INLINE bool isNullTerminated(const char* str, const deUint32 maxSize)
{
	return deStrnlen(str, maxSize) < maxSize;
}

DE_INLINE bool operator==(const VkConformanceVersion& a, const VkConformanceVersion& b)
{
	return ((a.major == b.major)		&&
			(a.minor == b.minor)		&&
			(a.subminor == b.subminor)	&&
			(a.patch == b.patch));
}

void checkSupport (Context& context, const TestType config)
{
	DE_UNREF(config);
	context.requireDeviceFunctionality("VK_KHR_driver_properties");
}

void testDriverMatch (const VkPhysicalDeviceDriverProperties& deviceDriverProperties)
{
	for (deUint32 driverNdx = 0; driverNdx < DE_LENGTH_OF_ARRAY(driverIds); driverNdx++)
	{
		if (deviceDriverProperties.driverID == driverIds[driverNdx].id)
			return;
	}

	TCU_FAIL("Driver ID did not match any known driver");
}

void testNameIsNotEmpty (const VkPhysicalDeviceDriverProperties& deviceDriverProperties)
{
	if (deviceDriverProperties.driverName[0] == 0)
		TCU_FAIL("Driver name is empty");
}

void testNameZeroTerminated (const VkPhysicalDeviceDriverProperties& deviceDriverProperties)
{
	if (!isNullTerminated(deviceDriverProperties.driverName, VK_MAX_DRIVER_NAME_SIZE))
		TCU_FAIL("Driver name is not a null-terminated string");
}

void testInfoZeroTerminated (const VkPhysicalDeviceDriverProperties& deviceDriverProperties)
{
	if (!isNullTerminated(deviceDriverProperties.driverInfo, VK_MAX_DRIVER_INFO_SIZE))
		TCU_FAIL("Driver info is not a null-terminated string");
}

void testVersion (const VkPhysicalDeviceDriverProperties& deviceDriverProperties, deUint32 usedApiVersion)
{
	const deUint32 apiMajorVersion = VK_API_VERSION_MAJOR(usedApiVersion);
	const deUint32 apiMinorVersion = VK_API_VERSION_MINOR(usedApiVersion);

	if (deviceDriverProperties.conformanceVersion.major < apiMajorVersion ||
		(deviceDriverProperties.conformanceVersion.major == apiMajorVersion &&
		 deviceDriverProperties.conformanceVersion.minor < apiMinorVersion))
	{
		TCU_FAIL("Wrong driver conformance version (older than used API version)");
	}

	for (const VkConformanceVersion*	pConformanceVersion  = knownConformanceVersions;
										pConformanceVersion != DE_ARRAY_END(knownConformanceVersions);
									  ++pConformanceVersion)
	{
		if (deviceDriverProperties.conformanceVersion == *pConformanceVersion)
			return;
	}

	TCU_FAIL("Wrong driver conformance version (not known)");
}

tcu::TestStatus testQueryProperties (Context& context, const TestType testType)
{
	// Query the driver properties
	const VkPhysicalDevice				physDevice			= context.getPhysicalDevice();
	const int							memsetPattern		= 0xaa;
	VkPhysicalDeviceProperties2			deviceProperties2;
	VkPhysicalDeviceDriverProperties	deviceDriverProperties;

	deMemset(&deviceDriverProperties, memsetPattern, sizeof(deviceDriverProperties));
	deviceDriverProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
	deviceDriverProperties.pNext = DE_NULL;

	deMemset(&deviceProperties2, memsetPattern, sizeof(deviceProperties2));
	deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
	deviceProperties2.pNext = &deviceDriverProperties;

	context.getInstanceInterface().getPhysicalDeviceProperties2(physDevice, &deviceProperties2);

	// Verify the returned values
	switch (testType)
	{
		case TEST_TYPE_DRIVER_ID_MATCH:			testDriverMatch			(deviceDriverProperties);								break;
		case TEST_TYPE_NAME_IS_NOT_EMPTY:		testNameIsNotEmpty		(deviceDriverProperties);								break;
		case TEST_TYPE_NAME_ZERO_TERMINATED:	testNameZeroTerminated	(deviceDriverProperties);								break;
		case TEST_TYPE_INFO_ZERO_TERMINATED:	testInfoZeroTerminated	(deviceDriverProperties);								break;
		case TEST_TYPE_VERSION:					testVersion				(deviceDriverProperties, context.getUsedApiVersion());	break;
		default:								TCU_THROW(InternalError, "Unknown test type specified");
	}

	return tcu::TestStatus::pass("Pass");
}

void createTestCases (tcu::TestCaseGroup* group)
{
	addFunctionCase(group, "driver_id_match",		"Check driverID is supported",					checkSupport,	testQueryProperties,	TEST_TYPE_DRIVER_ID_MATCH);
	addFunctionCase(group, "name_is_not_empty",		"Check name field is not empty",				checkSupport,	testQueryProperties,	TEST_TYPE_NAME_IS_NOT_EMPTY);
	addFunctionCase(group, "name_zero_terminated",	"Check name field is zero-terminated",			checkSupport,	testQueryProperties,	TEST_TYPE_NAME_ZERO_TERMINATED);
	addFunctionCase(group, "info_zero_terminated",	"Check info field is zero-terminated",			checkSupport,	testQueryProperties,	TEST_TYPE_INFO_ZERO_TERMINATED);
	addFunctionCase(group, "conformance_version",	"Check conformanceVersion reported by driver",	checkSupport,	testQueryProperties,	TEST_TYPE_VERSION);
}

} // anonymous

tcu::TestCaseGroup*	createDriverPropertiesTests(tcu::TestContext& testCtx)
{
	return createTestGroup(testCtx, "driver_properties", "VK_KHR_driver_properties tests", createTestCases);
}

} // api
} // vkt
<|endoftext|>


<commit_before>/*-------------------------------------------------------------------------
* Vulkan Conformance Tests
* ------------------------
*
* Copyright (c) 2018 Advanced Micro Devices, Inc.
* Copyright (c) 2018 The Khronos Group Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*//*!
* \file
* \brief VK_KHR_driver_properties tests
*//*--------------------------------------------------------------------*/

#include "vktApiDriverPropertiesTests.hpp"
#include "vktTestGroupUtil.hpp"
#include "vktTestCaseUtil.hpp"
#include "vkQueryUtil.hpp"
#include "vkTypeUtil.hpp"

using namespace vk;

namespace vkt
{
namespace api
{
namespace
{

enum TestType
{
	TEST_TYPE_DRIVER_ID_MATCH			= 0,
	TEST_TYPE_NAME_IS_NOT_EMPTY,
	TEST_TYPE_NAME_ZERO_TERMINATED,
	TEST_TYPE_INFO_ZERO_TERMINATED,
	TEST_TYPE_VERSION,
};

static const deUint32 knownDriverIds[] =
{
	// Specified in the Vulkan registry (vk.xml)
	1,	// author = "Advanced Micro Devices, Inc."   comment = "AMD proprietary driver"
	2,	// author = "Advanced Micro Devices, Inc."   comment = "AMD open-source driver"
	3,	// author = "Mesa open source project"       comment = "Mesa RADV driver"
	4,	// author = "NVIDIA Corporation"             comment = "NVIDIA proprietary driver"
	5,	// author = "Intel Corporation"              comment = "Intel proprietary Windows driver"
	6,	// author = "Intel Corporation"              comment = "Intel open-source Mesa driver"
	7,	// author = "Imagination Technologies"       comment = "Imagination proprietary driver"
	8,	// author = "Qualcomm Technologies, Inc."    comment = "Qualcomm proprietary driver"
	9,	// author = "Arm Limited"                    comment = "Arm proprietary driver"
	10,	// <enum value="10"      name="VK_DRIVER_ID_GOOGLE_SWIFTSHADER_KHR"        comment="Google LLC"/>
	11,	// <enum value="11"      name="VK_DRIVER_ID_GGP_PROPRIETARY_KHR"           comment="Google LLC"/>
	12,	// <enum value="12"      name="VK_DRIVER_ID_BROADCOM_PROPRIETARY_KHR"      comment="Broadcom Inc."/>
};

static const VkConformanceVersionKHR knownConformanceVersions[] =
{
	makeConformanceVersion(1, 2, 2, 0),
	makeConformanceVersion(1, 2, 1, 1),
	makeConformanceVersion(1, 2, 1, 0),
	makeConformanceVersion(1, 2, 0, 2),
	makeConformanceVersion(1, 2, 0, 1),
	makeConformanceVersion(1, 2, 0, 0),
	makeConformanceVersion(1, 1, 6, 3),
	makeConformanceVersion(1, 1, 6, 2),
	makeConformanceVersion(1, 1, 6, 1),
	makeConformanceVersion(1, 1, 6, 0),
	makeConformanceVersion(1, 1, 5, 2),
	makeConformanceVersion(1, 1, 5, 1),
	makeConformanceVersion(1, 1, 5, 0),
	makeConformanceVersion(1, 1, 4, 3),
	makeConformanceVersion(1, 1, 4, 2),
	makeConformanceVersion(1, 1, 4, 1),
	makeConformanceVersion(1, 1, 4, 0),
	makeConformanceVersion(1, 1, 3, 3),
	makeConformanceVersion(1, 1, 3, 2),
	makeConformanceVersion(1, 1, 3, 1),
	makeConformanceVersion(1, 1, 3, 0),
};

DE_INLINE bool isNullTerminated(const char* str, const deUint32 maxSize)
{
	return deStrnlen(str, maxSize) < maxSize;
}

DE_INLINE bool operator==(const VkConformanceVersion& a, const VkConformanceVersion& b)
{
	return ((a.major == b.major)		&&
			(a.minor == b.minor)		&&
			(a.subminor == b.subminor)	&&
			(a.patch == b.patch));
}

void checkSupport (Context& context, const TestType config)
{
	DE_UNREF(config);
	context.requireDeviceFunctionality("VK_KHR_driver_properties");
}

void testDriverMatch (const VkPhysicalDeviceDriverPropertiesKHR& deviceDriverProperties)
{
	for (const deUint32* pDriverId = knownDriverIds; pDriverId != DE_ARRAY_END(knownDriverIds); ++pDriverId)
	{
		if (deviceDriverProperties.driverID == *pDriverId)
			return;
	}

	TCU_FAIL("Driver ID did not match any known driver");
}

void testNameIsNotEmpty (const VkPhysicalDeviceDriverPropertiesKHR& deviceDriverProperties)
{
	if (deviceDriverProperties.driverName[0] == 0)
		TCU_FAIL("Driver name is empty");
}

void testNameZeroTerminated (const VkPhysicalDeviceDriverPropertiesKHR& deviceDriverProperties)
{
	if (!isNullTerminated(deviceDriverProperties.driverName, VK_MAX_DRIVER_NAME_SIZE_KHR))
		TCU_FAIL("Driver name is not a null-terminated string");
}

void testInfoZeroTerminated (const VkPhysicalDeviceDriverPropertiesKHR& deviceDriverProperties)
{
	if (!isNullTerminated(deviceDriverProperties.driverInfo, VK_MAX_DRIVER_INFO_SIZE_KHR))
		TCU_FAIL("Driver info is not a null-terminated string");
}

void testVersion (const VkPhysicalDeviceDriverPropertiesKHR& deviceDriverProperties, deUint32 usedApiVersion)
{
	const deUint32 apiMajorVersion = VK_VERSION_MAJOR(usedApiVersion);
	const deUint32 apiMinorVersion = VK_VERSION_MINOR(usedApiVersion);

	if (deviceDriverProperties.conformanceVersion.major < apiMajorVersion ||
		(deviceDriverProperties.conformanceVersion.major == apiMajorVersion &&
		 deviceDriverProperties.conformanceVersion.minor < apiMinorVersion))
	{
		TCU_FAIL("Wrong driver conformance version (older than used API version)");
	}

	for (const VkConformanceVersionKHR* pConformanceVersion  = knownConformanceVersions;
										pConformanceVersion != DE_ARRAY_END(knownConformanceVersions);
									  ++pConformanceVersion)
	{
		if (deviceDriverProperties.conformanceVersion == *pConformanceVersion)
			return;
	}

	TCU_FAIL("Wrong driver conformance version (not known)");
}

tcu::TestStatus testQueryProperties (Context& context, const TestType testType)
{
	// Query the driver properties
	const VkPhysicalDevice				physDevice			= context.getPhysicalDevice();
	const int							memsetPattern		= 0xaa;
	VkPhysicalDeviceProperties2			deviceProperties2;
	VkPhysicalDeviceDriverProperties	deviceDriverProperties;

	deMemset(&deviceDriverProperties, memsetPattern, sizeof(deviceDriverProperties));
	deviceDriverProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR;
	deviceDriverProperties.pNext = DE_NULL;

	deMemset(&deviceProperties2, memsetPattern, sizeof(deviceProperties2));
	deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
	deviceProperties2.pNext = &deviceDriverProperties;

	context.getInstanceInterface().getPhysicalDeviceProperties2(physDevice, &deviceProperties2);

	// Verify the returned values
	switch (testType)
	{
		case TEST_TYPE_DRIVER_ID_MATCH:			testDriverMatch			(deviceDriverProperties);								break;
		case TEST_TYPE_NAME_IS_NOT_EMPTY:		testNameIsNotEmpty		(deviceDriverProperties);								break;
		case TEST_TYPE_NAME_ZERO_TERMINATED:	testNameZeroTerminated	(deviceDriverProperties);								break;
		case TEST_TYPE_INFO_ZERO_TERMINATED:	testInfoZeroTerminated	(deviceDriverProperties);								break;
		case TEST_TYPE_VERSION:					testVersion				(deviceDriverProperties, context.getUsedApiVersion());	break;
		default:								TCU_THROW(InternalError, "Unknown test type specified");
	}

	return tcu::TestStatus::pass("Pass");
}

void createTestCases (tcu::TestCaseGroup* group)
{
	addFunctionCase(group, "driver_id_match",		"Check driverID is supported",					checkSupport,	testQueryProperties,	TEST_TYPE_DRIVER_ID_MATCH);
	addFunctionCase(group, "name_is_not_empty",		"Check name field is not empty",				checkSupport,	testQueryProperties,	TEST_TYPE_NAME_IS_NOT_EMPTY);
	addFunctionCase(group, "name_zero_terminated",	"Check name field is zero-terminated",			checkSupport,	testQueryProperties,	TEST_TYPE_NAME_ZERO_TERMINATED);
	addFunctionCase(group, "info_zero_terminated",	"Check info field is zero-terminated",			checkSupport,	testQueryProperties,	TEST_TYPE_INFO_ZERO_TERMINATED);
	addFunctionCase(group, "conformance_version",	"Check conformanceVersion reported by driver",	checkSupport,	testQueryProperties,	TEST_TYPE_VERSION);
}

} // anonymous

tcu::TestCaseGroup*	createDriverPropertiesTests(tcu::TestContext& testCtx)
{
	return createTestGroup(testCtx, "driver_properties", "VK_KHR_driver_properties tests", createTestCases);
}

} // api
} // vkt
<commit_msg>Whitelist Vulkan CTS 1.2.2.1<commit_after>/*-------------------------------------------------------------------------
* Vulkan Conformance Tests
* ------------------------
*
* Copyright (c) 2018 Advanced Micro Devices, Inc.
* Copyright (c) 2018 The Khronos Group Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*//*!
* \file
* \brief VK_KHR_driver_properties tests
*//*--------------------------------------------------------------------*/

#include "vktApiDriverPropertiesTests.hpp"
#include "vktTestGroupUtil.hpp"
#include "vktTestCaseUtil.hpp"
#include "vkQueryUtil.hpp"
#include "vkTypeUtil.hpp"

using namespace vk;

namespace vkt
{
namespace api
{
namespace
{

enum TestType
{
	TEST_TYPE_DRIVER_ID_MATCH			= 0,
	TEST_TYPE_NAME_IS_NOT_EMPTY,
	TEST_TYPE_NAME_ZERO_TERMINATED,
	TEST_TYPE_INFO_ZERO_TERMINATED,
	TEST_TYPE_VERSION,
};

static const deUint32 knownDriverIds[] =
{
	// Specified in the Vulkan registry (vk.xml)
	1,	// author = "Advanced Micro Devices, Inc."   comment = "AMD proprietary driver"
	2,	// author = "Advanced Micro Devices, Inc."   comment = "AMD open-source driver"
	3,	// author = "Mesa open source project"       comment = "Mesa RADV driver"
	4,	// author = "NVIDIA Corporation"             comment = "NVIDIA proprietary driver"
	5,	// author = "Intel Corporation"              comment = "Intel proprietary Windows driver"
	6,	// author = "Intel Corporation"              comment = "Intel open-source Mesa driver"
	7,	// author = "Imagination Technologies"       comment = "Imagination proprietary driver"
	8,	// author = "Qualcomm Technologies, Inc."    comment = "Qualcomm proprietary driver"
	9,	// author = "Arm Limited"                    comment = "Arm proprietary driver"
	10,	// <enum value="10"      name="VK_DRIVER_ID_GOOGLE_SWIFTSHADER_KHR"        comment="Google LLC"/>
	11,	// <enum value="11"      name="VK_DRIVER_ID_GGP_PROPRIETARY_KHR"           comment="Google LLC"/>
	12,	// <enum value="12"      name="VK_DRIVER_ID_BROADCOM_PROPRIETARY_KHR"      comment="Broadcom Inc."/>
};

static const VkConformanceVersionKHR knownConformanceVersions[] =
{
	makeConformanceVersion(1, 2, 2, 1),
	makeConformanceVersion(1, 2, 2, 0),
	makeConformanceVersion(1, 2, 1, 1),
	makeConformanceVersion(1, 2, 1, 0),
	makeConformanceVersion(1, 2, 0, 2),
	makeConformanceVersion(1, 2, 0, 1),
	makeConformanceVersion(1, 2, 0, 0),
	makeConformanceVersion(1, 1, 6, 3),
	makeConformanceVersion(1, 1, 6, 2),
	makeConformanceVersion(1, 1, 6, 1),
	makeConformanceVersion(1, 1, 6, 0),
	makeConformanceVersion(1, 1, 5, 2),
	makeConformanceVersion(1, 1, 5, 1),
	makeConformanceVersion(1, 1, 5, 0),
	makeConformanceVersion(1, 1, 4, 3),
	makeConformanceVersion(1, 1, 4, 2),
	makeConformanceVersion(1, 1, 4, 1),
	makeConformanceVersion(1, 1, 4, 0),
	makeConformanceVersion(1, 1, 3, 3),
	makeConformanceVersion(1, 1, 3, 2),
	makeConformanceVersion(1, 1, 3, 1),
	makeConformanceVersion(1, 1, 3, 0),
};

DE_INLINE bool isNullTerminated(const char* str, const deUint32 maxSize)
{
	return deStrnlen(str, maxSize) < maxSize;
}

DE_INLINE bool operator==(const VkConformanceVersion& a, const VkConformanceVersion& b)
{
	return ((a.major == b.major)		&&
			(a.minor == b.minor)		&&
			(a.subminor == b.subminor)	&&
			(a.patch == b.patch));
}

void checkSupport (Context& context, const TestType config)
{
	DE_UNREF(config);
	context.requireDeviceFunctionality("VK_KHR_driver_properties");
}

void testDriverMatch (const VkPhysicalDeviceDriverPropertiesKHR& deviceDriverProperties)
{
	for (const deUint32* pDriverId = knownDriverIds; pDriverId != DE_ARRAY_END(knownDriverIds); ++pDriverId)
	{
		if (deviceDriverProperties.driverID == *pDriverId)
			return;
	}

	TCU_FAIL("Driver ID did not match any known driver");
}

void testNameIsNotEmpty (const VkPhysicalDeviceDriverPropertiesKHR& deviceDriverProperties)
{
	if (deviceDriverProperties.driverName[0] == 0)
		TCU_FAIL("Driver name is empty");
}

void testNameZeroTerminated (const VkPhysicalDeviceDriverPropertiesKHR& deviceDriverProperties)
{
	if (!isNullTerminated(deviceDriverProperties.driverName, VK_MAX_DRIVER_NAME_SIZE_KHR))
		TCU_FAIL("Driver name is not a null-terminated string");
}

void testInfoZeroTerminated (const VkPhysicalDeviceDriverPropertiesKHR& deviceDriverProperties)
{
	if (!isNullTerminated(deviceDriverProperties.driverInfo, VK_MAX_DRIVER_INFO_SIZE_KHR))
		TCU_FAIL("Driver info is not a null-terminated string");
}

void testVersion (const VkPhysicalDeviceDriverPropertiesKHR& deviceDriverProperties, deUint32 usedApiVersion)
{
	const deUint32 apiMajorVersion = VK_VERSION_MAJOR(usedApiVersion);
	const deUint32 apiMinorVersion = VK_VERSION_MINOR(usedApiVersion);

	if (deviceDriverProperties.conformanceVersion.major < apiMajorVersion ||
		(deviceDriverProperties.conformanceVersion.major == apiMajorVersion &&
		 deviceDriverProperties.conformanceVersion.minor < apiMinorVersion))
	{
		TCU_FAIL("Wrong driver conformance version (older than used API version)");
	}

	for (const VkConformanceVersionKHR* pConformanceVersion  = knownConformanceVersions;
										pConformanceVersion != DE_ARRAY_END(knownConformanceVersions);
									  ++pConformanceVersion)
	{
		if (deviceDriverProperties.conformanceVersion == *pConformanceVersion)
			return;
	}

	TCU_FAIL("Wrong driver conformance version (not known)");
}

tcu::TestStatus testQueryProperties (Context& context, const TestType testType)
{
	// Query the driver properties
	const VkPhysicalDevice				physDevice			= context.getPhysicalDevice();
	const int							memsetPattern		= 0xaa;
	VkPhysicalDeviceProperties2			deviceProperties2;
	VkPhysicalDeviceDriverProperties	deviceDriverProperties;

	deMemset(&deviceDriverProperties, memsetPattern, sizeof(deviceDriverProperties));
	deviceDriverProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR;
	deviceDriverProperties.pNext = DE_NULL;

	deMemset(&deviceProperties2, memsetPattern, sizeof(deviceProperties2));
	deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
	deviceProperties2.pNext = &deviceDriverProperties;

	context.getInstanceInterface().getPhysicalDeviceProperties2(physDevice, &deviceProperties2);

	// Verify the returned values
	switch (testType)
	{
		case TEST_TYPE_DRIVER_ID_MATCH:			testDriverMatch			(deviceDriverProperties);								break;
		case TEST_TYPE_NAME_IS_NOT_EMPTY:		testNameIsNotEmpty		(deviceDriverProperties);								break;
		case TEST_TYPE_NAME_ZERO_TERMINATED:	testNameZeroTerminated	(deviceDriverProperties);								break;
		case TEST_TYPE_INFO_ZERO_TERMINATED:	testInfoZeroTerminated	(deviceDriverProperties);								break;
		case TEST_TYPE_VERSION:					testVersion				(deviceDriverProperties, context.getUsedApiVersion());	break;
		default:								TCU_THROW(InternalError, "Unknown test type specified");
	}

	return tcu::TestStatus::pass("Pass");
}

void createTestCases (tcu::TestCaseGroup* group)
{
	addFunctionCase(group, "driver_id_match",		"Check driverID is supported",					checkSupport,	testQueryProperties,	TEST_TYPE_DRIVER_ID_MATCH);
	addFunctionCase(group, "name_is_not_empty",		"Check name field is not empty",				checkSupport,	testQueryProperties,	TEST_TYPE_NAME_IS_NOT_EMPTY);
	addFunctionCase(group, "name_zero_terminated",	"Check name field is zero-terminated",			checkSupport,	testQueryProperties,	TEST_TYPE_NAME_ZERO_TERMINATED);
	addFunctionCase(group, "info_zero_terminated",	"Check info field is zero-terminated",			checkSupport,	testQueryProperties,	TEST_TYPE_INFO_ZERO_TERMINATED);
	addFunctionCase(group, "conformance_version",	"Check conformanceVersion reported by driver",	checkSupport,	testQueryProperties,	TEST_TYPE_VERSION);
}

} // anonymous

tcu::TestCaseGroup*	createDriverPropertiesTests(tcu::TestContext& testCtx)
{
	return createTestGroup(testCtx, "driver_properties", "VK_KHR_driver_properties tests", createTestCases);
}

} // api
} // vkt
<|endoftext|>


<commit_before>#include <bits/stdc++.h>
#define dbug(x) cout << '>' << #x << ':' << x << endl
#define pline    cout << "_________________________" << endl
#define mem(x, v) memset(x, v, sizeof(x))

#define eef else if
#define sf scanf
#define pf printf
#define i64 long long
#define ll  long long
#define ui64 unsigned long long

#define pcount(num)  __builtin_popcount(num)
#define all(x) x.begin(), x.end()
#define lla(x) x.rbegin(), x.rend()
#define SORT(c) sort(all(c))
#define ssort(v) stable_sort(v.begin(), v.end())
#define sz(v) (int)(v).size()
#define _lst(X) (X)[sz((X))-1]

#define IT iterator
#define pb push_back
#define ppb pop_back
#define mp make_pair
#define fi first
#define se second
#define CTN(T, x) (T.find(x) != T.end())

#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define maximum(v)  *max_element(all(v)
#define minimum(v)  *min_element(all(v))
#define Reverse(x)  reverse(x.begin(),x.end())

#define loop(i,s,e) for(__typeof(s) i=(s);i<=(e);i++)
#define pool(i,e,s) for(__typeof(e) i=(e);i>=(s);i--)

#define FORIT(i, m) for (__typeof((m).begin()) i=(m).begin(); i!=(m).end(); ++i)

#define siter(n,T1)  for(set<T1>::iterator it=n.begin();it!=n.end();it++)
#define miter(n,T1,T2)  for(map<T1,T2>::iterator it=n.begin();it!=n.end();it++)

#define ps(x) cout<<"Case "<<++x<<": "
#define pcs(x) pf("Case %d: ", ++x)
#define newl '\n'
#define Newl "\n"
#define nl puts ("")
#define sqr(a) ((a)*(a))
#define MAX 1e12

#define FAST ios_base::sync_with_stdio(0)
using namespace std;

int main(){
    int matches, goals, a, b, m, wins, stop, draw;

    while(sf("%d %d", &matches, &goals)==2){
        wins = draw = 0, m = matches;
        vector<int> need;
        while(m--){
            sf("%d %d", &a, &b);
            if ( a > b ) wins++;
            else {
                need.pb((b+1) - a );
            }
        }
        sort(all(need));
        for(int i = 0; i<sz(need); i++){
            if ( goals < 1 ){
                loop(j, i, sz(need)-1){
                    if ( need[j] == 1 ){
                        draw++;
                        goals--;
                    }
                }
                break;
            }
            if ( goals >= need[i] ){
                goals -= need[i];
                wins++;

            }
            if ( goals > 0 && goals+1 == need[i] ){
                draw++;
                goals--;
            }
        }

        pf("%d\n", (wins*3) + draw);
    }

    return 0;
}
/*
Input:

3 1
2 1
1 2
1 3
3 3
1 1
2 2
3 3
2 1
1 1
2 2
7 0
4 2
1 1
1 5
2 2
3 3
4 4
0 6
4 0
1 1
2 2
1 3
0 4
3 10
0 8
0 2
0 0
5 3
1 1
1 3
1 2
1 2
1 2
5 4
0 1
0 1
0 1
0 1
1 8
2 1
0 1
2 2
2 1
0 1
0 1

Output:

4
9
4
7
2
6
6
6
3
1

*/
<commit_msg>Update Football_12673.cpp<commit_after>#include <bits/stdc++.h>
#define dbug(x)     cout << '>' << #x << ':' << x << endl
#define pline       cout << "_________________________" << endl
#define mem(x, v)   memset(x, v, sizeof(x))

#define eef         else if
#define sf          scanf
#define pf          printf
#define i64         long long
#define ll          long long
#define ui64        unsigned long long

#define pcount(num)  __builtin_popcount(num)
#define all(x)      x.begin(), x.end()
#define lla(x)      x.rbegin(), x.rend()
#define SORT(c)     sort(all(c))
#define ssort(v)    stable_sort(v.begin(), v.end())
#define sz(v)       (int)(v).size()
#define _lst(X)     (X)[sz((X))-1]

#define IT          iterator
#define pb          push_back
#define ppb         pop_back
#define mp          make_pair
#define fi          first
#define se          second
#define CTN(T, x)   (T.find(x) != T.end())

#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
#define maximum(v)  *max_element(all(v)
#define minimum(v)  *min_element(all(v))
#define Reverse(x)  reverse(x.begin(),x.end())

#define loop(i,s,e) for(__typeof(s) i=(s);i<=(e);i++)
#define pool(i,e,s) for(__typeof(e) i=(e);i>=(s);i--)

#define FORIT(i, m) for (__typeof((m).begin()) i=(m).begin(); i!=(m).end(); ++i)

#define siter(n,T1)  for(set<T1>::iterator it=n.begin();it!=n.end();it++)
#define miter(n,T1,T2) for(map<T1,T2>::iterator it=n.begin();it!=n.end();it++)

#define ps(x)       cout<<"Case "<<++x<<": "
#define pcs(x)      pf("Case %d: ", ++x)
#define newl        '\n'
#define Newl        "\n"
#define nl          puts("")
#define sqr(a)      ((a)*(a))
#define MAX         1e12

#define FAST        ios_base::sync_with_stdio(0)
using namespace std;

int main(){
    int matches, goals, a, b, m, wins, stop, draw;

    while(sf("%d %d", &matches, &goals)==2){
        wins = draw = 0, m = matches;
        vector<int> need;
        while(m--){
            sf("%d %d", &a, &b);
            if ( a > b ) wins++;
            else {
                need.pb((b+1) - a );
            }
        }
        sort(all(need));
        for(int i = 0; i<sz(need); i++){
            if ( goals < 1 ){
                loop(j, i, sz(need)-1){
                    if ( need[j] == 1 ){
                        draw++;
                        goals--;
                    }
                }
                break;
            }
            if ( goals >= need[i] ){
                goals -= need[i];
                wins++;

            }
            if ( goals > 0 && goals+1 == need[i] ){
                draw++;
                goals--;
            }
        }

        pf("%d\n", (wins*3) + draw);
    }

    return 0;
}
/*
Input:

3 1
2 1
1 2
1 3
3 3
1 1
2 2
3 3
2 1
1 1
2 2
7 0
4 2
1 1
1 5
2 2
3 3
4 4
0 6
4 0
1 1
2 2
1 3
0 4
3 10
0 8
0 2
0 0
5 3
1 1
1 3
1 2
1 2
1 2
5 4
0 1
0 1
0 1
0 1
1 8
2 1
0 1
2 2
2 1
0 1
0 1

Output:

4
9
4
7
2
6
6
6
3
1

*/
<|endoftext|>


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

#ifndef RCLCPP_RCLCPP_UTILITIES_HPP_
#define RCLCPP_RCLCPP_UTILITIES_HPP_

// TODO: remove
#include <iostream>

#include <cerrno>
#include <chrono>
#include <condition_variable>
#include <csignal>
#include <cstring>
#include <mutex>
#include <thread>

#include <ros_middleware_interface/functions.h>
#include <ros_middleware_interface/handles.h>

// Determine if sigaction is available
#if _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE
#define HAS_SIGACTION
#endif

namespace
{
  volatile sig_atomic_t g_signal_status = 0;
  ros_middleware_interface::GuardConditionHandle g_sigint_guard_cond_handle = \
    ros_middleware_interface::create_guard_condition();
  std::condition_variable g_interrupt_condition_variable;
  std::mutex g_interrupt_mutex;

#ifdef HAS_SIGACTION
  struct sigaction old_action;
#else
  void (*old_signal_handler)(int) = 0;
#endif

  void
#ifdef HAS_SIGACTION
  signal_handler(int signal_value, siginfo_t *siginfo, void *context)
#else
  signal_handler(int signal_value)
#endif
  {
    // TODO: remove
    std::cout << "signal_handler(" << signal_value << ")" << std::endl;
#ifdef HAS_SIGACTION
    if (old_action.sa_flags & SA_SIGINFO)
    {
      if (old_action.sa_sigaction != NULL)
      {
        old_action.sa_sigaction(signal_value, siginfo, context);
      }
    }
    else
    {
      if (old_action.sa_handler != NULL &&  // Is set
          old_action.sa_handler != SIG_DFL &&  // Is not default
          old_action.sa_handler != SIG_IGN)  // Is not ignored
      {
        old_action.sa_handler(signal_value);
      }
    }
#else
    if (old_signal_handler)
    {
      old_signal_handler(signal_value);
    }
#endif
    g_signal_status = signal_value;
    using ros_middleware_interface::trigger_guard_condition;
    trigger_guard_condition(g_sigint_guard_cond_handle);
    g_interrupt_condition_variable.notify_all();
  }
}

namespace rclcpp
{

__thread size_t thread_id = 0;

namespace utilities
{

void
init(int argc, char *argv[])
{
  ros_middleware_interface::init();
#ifdef HAS_SIGACTION
  struct sigaction action;
  memset(&action, 0, sizeof(action));
  sigemptyset(&action.sa_mask);
  action.sa_sigaction = ::signal_handler;
  action.sa_flags = SA_SIGINFO;
  ssize_t ret = sigaction(SIGINT, &action, &old_action);
  if (ret == -1)
#else
  ::old_signal_handler = std::signal(SIGINT, ::signal_handler);
  if (::old_signal_handler == SIG_ERR)
#endif
  {
    throw std::runtime_error(
      std::string("Failed to set SIGINT signal handler: (" +
                  std::to_string(errno) + ")") +
      std::strerror(errno));
  }
}

bool
ok()
{
  return ::g_signal_status == 0;
}

ros_middleware_interface::GuardConditionHandle
get_global_sigint_guard_condition()
{
  return ::g_sigint_guard_cond_handle;
}

template<class Rep, class Period>
bool
sleep_for(const std::chrono::duration<Rep, Period>& sleep_duration)
{
  // TODO: determine if posix's nanosleep(2) is more efficient here
  std::unique_lock<std::mutex> lock(::g_interrupt_mutex);
  auto cvs = ::g_interrupt_condition_variable.wait_for(lock, sleep_duration);
  return cvs == std::cv_status::no_timeout;
}

} /* namespace utilities */
} /* namespace rclcpp */

#ifdef HAS_SIGACTION
#undef HAS_SIGACTION
#endif

#endif /* RCLCPP_RCLCPP_UTILITIES_HPP_ */
<commit_msg>update sigaction detection to support os x<commit_after>/* Copyright 2014 Open Source Robotics Foundation, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef RCLCPP_RCLCPP_UTILITIES_HPP_
#define RCLCPP_RCLCPP_UTILITIES_HPP_

// TODO: remove
#include <iostream>

#include <cerrno>
#include <chrono>
#include <condition_variable>
#include <csignal>
#include <cstring>
#include <mutex>
#include <thread>

#include <ros_middleware_interface/functions.h>
#include <ros_middleware_interface/handles.h>

// Determine if sigaction is available
#if __APPLE__ || _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE
#define HAS_SIGACTION
#endif

namespace
{
  volatile sig_atomic_t g_signal_status = 0;
  ros_middleware_interface::GuardConditionHandle g_sigint_guard_cond_handle = \
    ros_middleware_interface::create_guard_condition();
  std::condition_variable g_interrupt_condition_variable;
  std::mutex g_interrupt_mutex;

#ifdef HAS_SIGACTION
  struct sigaction old_action;
#else
  void (*old_signal_handler)(int) = 0;
#endif

  void
#ifdef HAS_SIGACTION
  signal_handler(int signal_value, siginfo_t *siginfo, void *context)
#else
  signal_handler(int signal_value)
#endif
  {
    // TODO: remove
    std::cout << "signal_handler(" << signal_value << ")" << std::endl;
#ifdef HAS_SIGACTION
    if (old_action.sa_flags & SA_SIGINFO)
    {
      if (old_action.sa_sigaction != NULL)
      {
        old_action.sa_sigaction(signal_value, siginfo, context);
      }
    }
    else
    {
      if (old_action.sa_handler != NULL &&  // Is set
          old_action.sa_handler != SIG_DFL &&  // Is not default
          old_action.sa_handler != SIG_IGN)  // Is not ignored
      {
        old_action.sa_handler(signal_value);
      }
    }
#else
    if (old_signal_handler)
    {
      old_signal_handler(signal_value);
    }
#endif
    g_signal_status = signal_value;
    using ros_middleware_interface::trigger_guard_condition;
    trigger_guard_condition(g_sigint_guard_cond_handle);
    g_interrupt_condition_variable.notify_all();
  }
}

namespace rclcpp
{

__thread size_t thread_id = 0;

namespace utilities
{

void
init(int argc, char *argv[])
{
  ros_middleware_interface::init();
#ifdef HAS_SIGACTION
  struct sigaction action;
  memset(&action, 0, sizeof(action));
  sigemptyset(&action.sa_mask);
  action.sa_sigaction = ::signal_handler;
  action.sa_flags = SA_SIGINFO;
  ssize_t ret = sigaction(SIGINT, &action, &old_action);
  if (ret == -1)
#else
  ::old_signal_handler = std::signal(SIGINT, ::signal_handler);
  if (::old_signal_handler == SIG_ERR)
#endif
  {
    throw std::runtime_error(
      std::string("Failed to set SIGINT signal handler: (" +
                  std::to_string(errno) + ")") +
      std::strerror(errno));
  }
}

bool
ok()
{
  return ::g_signal_status == 0;
}

ros_middleware_interface::GuardConditionHandle
get_global_sigint_guard_condition()
{
  return ::g_sigint_guard_cond_handle;
}

template<class Rep, class Period>
bool
sleep_for(const std::chrono::duration<Rep, Period>& sleep_duration)
{
  // TODO: determine if posix's nanosleep(2) is more efficient here
  std::unique_lock<std::mutex> lock(::g_interrupt_mutex);
  auto cvs = ::g_interrupt_condition_variable.wait_for(lock, sleep_duration);
  return cvs == std::cv_status::no_timeout;
}

} /* namespace utilities */
} /* namespace rclcpp */

#ifdef HAS_SIGACTION
#undef HAS_SIGACTION
#endif

#endif /* RCLCPP_RCLCPP_UTILITIES_HPP_ */
<|endoftext|>


<commit_before>/*---------------------------------------------------------------------------*\
 *                           OpenSG NURBS Library                            *
 *                                                                           *
 *                                                                           *
 * Copyright (C) 2001-2006 by the University of Bonn, Computer Graphics Group*
 *                                                                           *
 *                         http://cg.cs.uni-bonn.de/                         *
 *                                                                           *
 * contact: edhellon@cs.uni-bonn.de, guthe@cs.uni-bonn.de, rk@cs.uni-bonn.de *
 *                                                                           *
\*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*\
 *                                License                                    *
 *                                                                           *
 * This library is free software; you can redistribute it and/or modify it   *
 * under the terms of the GNU Library General Public License as published    *
 * by the Free Software Foundation, version 2.                               *
 *                                                                           *
 * This library is distributed in the hope that it will be useful, but       *
 * WITHOUT ANY WARRANTY; without even the implied warranty of                *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
 * Library General Public License for more details.                          *
 *                                                                           *
 * You should have received a copy of the GNU Library General Public         *
 * License along with this library; if not, write to the Free Software       *
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
 *                                                                           *
\*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*\
 *                                Changes                                    *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
\*---------------------------------------------------------------------------*/

OSG_BEGIN_NAMESPACE

// default constructor
template <typename T0, typename T1>
DirectedGraph<T0, T1>::DirectedGraph()
{
  invalid = true;
}

// add a new node
// returns node index
template <typename T0, typename T1>
int DirectedGraph<T0, T1>::AddNode( T0 &n )
{
  DirectedNode<T0> nn;
  nn.nodeinfo = n;
  nodes.push_back( nn );
  return Int32(nodes.size()) - 1;
}

// add a new (possibly directed) edge
// returns edge index or -1
template <typename T0, typename T1>
int DirectedGraph<T0, T1>::AddEdge( T1 &t, int from, int to, bool direction)
{
  if ( from < 0 || from >= int(nodes.size()) ||
       to < 0 || to >= int(nodes.size()) ) return -1;

  DirectedEdge<T1> e;
  int eidx;
  e.edgeinfo = t;
  e.from = from;
  e.to = to;
  e.direction = direction;
  e.valid = true; //DEBUG
  edges.push_back( e );
  eidx = Int32(edges.size()) - 1;

  nodes[ from ].edges.push_back( eidx );
  nodes[ to ].edges.push_back( eidx );
  return eidx;
}

// delete edge specified by index
template <typename T0, typename T1>
int DirectedGraph<T0, T1>::DeleteEdge( int edgeidx )
{
  if ( edgeidx < 0 || edgeidx >= int(edges.size()) )
    return -1;

  // note: we don't need to actually erase from here
//  edges.erase( edgeidx );

  edges[ edgeidx ].valid = false;

  DirectedNode<T0> &fromnode = nodes[ edges [ edgeidx ].from ];
  DCTPivector::iterator nee = fromnode.edges.end();
  DCTPivector::iterator i;
  for( i = fromnode.edges.begin(); i != nee; ++i )
    if ( *i == edgeidx ) {
      fromnode.edges.erase( i );
      break;
    }

  DirectedNode<T0> &tonode = nodes[ edges [ edgeidx ].to ];
  nee = tonode.edges.end();
  for( i = tonode.edges.begin(); i != nee; ++i )
    if ( *i == edgeidx ) {
      tonode.edges.erase( i );
      break;
    }

  return 0;
}

template <typename T0, typename T1>
DCTPivector & DirectedGraph<T0, T1>::getEdges( int n ) // get all edges (indexes) from a node
{
  return &nodes.edges;
}

// get one node
template <typename T0, typename T1>
DirectedNode<T0>& DirectedGraph<T0, T1>::getNode( int nodeindex, int &error )
{
  error = 0;
  if ( nodeindex < 0 || nodeindex >= nodes.size() ) {
    error = -1;
    return NULL;
  }
  return &nodes[ nodeindex ] ;
}

// get one edge
template <typename T0, typename T1>
DirectedEdge<T1>& DirectedGraph<T0, T1>::getEdge( int edgeindex, int &error )
{
  error = 0;
  if ( edgeindex < 0 || edgeindex >= edges.size() ) {
    error = -1;
    return NULL;
  }
  return &edges[ edgeindex ] ;
}

// get one edge's direction
template <typename T0, typename T1>
bool DirectedGraph<T0, T1>::getEdgeDirection( int edgeindex, int &error )
{
  error = 0;
  if ( edgeindex < 0 || edgeindex >= edges.size() ) {
    error = -1;
    return NULL;
  }

  return edges[ edgeindex ].orientation;
}

// set the direction of an edge
template <typename T0, typename T1>
int DirectedGraph<T0, T1>::setEdgeDirection( int edgeindex, int to )
{
  if ( edgeindex < 0 || edgeindex >= int(edges.size()) ) return -1;

  if ( edges[ edgeindex ].from != to && edges[ edgeindex ].to != to )
    return -1;
  if ( edges[ edgeindex ].to != to ) {
    int tmp = edges[ edgeindex ].to;
    edges[ edgeindex ].to = to;
    edges[ edgeindex ].from = tmp;
  }
  edges[ edgeindex ].direction = true;
  return 0;
}

// change (invert) the direction of an edge
template <typename T0, typename T1>
int DirectedGraph<T0, T1>::changeEdgeDirection( int edgeindex )
{
  if ( edgeindex < 0 || edgeindex >= edges.size() )
    return -1;
  if ( !edges[ edgeindex ].orientation )
    return -1;

  int tmp = edges[ edgeindex ].to;
  edges[ edgeindex ].to = edges[ edgeindex ].from;
  edges[ edgeindex ].from = tmp;

  return 0;
}

template <typename T0, typename T1>
bool DirectedGraph<T0, T1>::isInvalid( void )
{
  return invalid;
}

template <typename T0, typename T1>
int DirectedGraph<T0, T1>::FindNode( T0 &nodeinfo )
{
	for( unsigned int i = 0; i < nodes.size( ); ++i )
	{
		if( nodes[ i ].nodeinfo == nodeinfo ) return i;
	}

	return -1;
}

template <typename T0, typename T1>
int DirectedGraph<T0, T1>::FindEdge( int from, int to )
{
	for( unsigned int i = 0; i < edges.size( ); ++i )
	{
//		std::cerr << "checking edge from " << edges[ i ].from << " to " << edges[ i ].to << std::endl;
		if( ( edges[ i ].from == from ) &&
			( edges[ i ].to == to ) ) return i;
		if( ( edges[ i ].from == to ) &&
			( edges[ i ].to == from ) ) return i;
	}

	return -1;
}

OSG_END_NAMESPACE
<commit_msg>fix return type<commit_after>/*---------------------------------------------------------------------------*\
 *                           OpenSG NURBS Library                            *
 *                                                                           *
 *                                                                           *
 * Copyright (C) 2001-2006 by the University of Bonn, Computer Graphics Group*
 *                                                                           *
 *                         http://cg.cs.uni-bonn.de/                         *
 *                                                                           *
 * contact: edhellon@cs.uni-bonn.de, guthe@cs.uni-bonn.de, rk@cs.uni-bonn.de *
 *                                                                           *
\*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*\
 *                                License                                    *
 *                                                                           *
 * This library is free software; you can redistribute it and/or modify it   *
 * under the terms of the GNU Library General Public License as published    *
 * by the Free Software Foundation, version 2.                               *
 *                                                                           *
 * This library is distributed in the hope that it will be useful, but       *
 * WITHOUT ANY WARRANTY; without even the implied warranty of                *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
 * Library General Public License for more details.                          *
 *                                                                           *
 * You should have received a copy of the GNU Library General Public         *
 * License along with this library; if not, write to the Free Software       *
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
 *                                                                           *
\*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*\
 *                                Changes                                    *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
 *                                                                           *
\*---------------------------------------------------------------------------*/

OSG_BEGIN_NAMESPACE

// default constructor
template <typename T0, typename T1>
DirectedGraph<T0, T1>::DirectedGraph()
{
  invalid = true;
}

// add a new node
// returns node index
template <typename T0, typename T1>
int DirectedGraph<T0, T1>::AddNode( T0 &n )
{
  DirectedNode<T0> nn;
  nn.nodeinfo = n;
  nodes.push_back( nn );
  return Int32(nodes.size()) - 1;
}

// add a new (possibly directed) edge
// returns edge index or -1
template <typename T0, typename T1>
int DirectedGraph<T0, T1>::AddEdge( T1 &t, int from, int to, bool direction)
{
  if ( from < 0 || from >= int(nodes.size()) ||
       to < 0 || to >= int(nodes.size()) ) return -1;

  DirectedEdge<T1> e;
  int eidx;
  e.edgeinfo = t;
  e.from = from;
  e.to = to;
  e.direction = direction;
  e.valid = true; //DEBUG
  edges.push_back( e );
  eidx = Int32(edges.size()) - 1;

  nodes[ from ].edges.push_back( eidx );
  nodes[ to ].edges.push_back( eidx );
  return eidx;
}

// delete edge specified by index
template <typename T0, typename T1>
int DirectedGraph<T0, T1>::DeleteEdge( int edgeidx )
{
  if ( edgeidx < 0 || edgeidx >= int(edges.size()) )
    return -1;

  // note: we don't need to actually erase from here
//  edges.erase( edgeidx );

  edges[ edgeidx ].valid = false;

  DirectedNode<T0> &fromnode = nodes[ edges [ edgeidx ].from ];
  DCTPivector::iterator nee = fromnode.edges.end();
  DCTPivector::iterator i;
  for( i = fromnode.edges.begin(); i != nee; ++i )
    if ( *i == edgeidx ) {
      fromnode.edges.erase( i );
      break;
    }

  DirectedNode<T0> &tonode = nodes[ edges [ edgeidx ].to ];
  nee = tonode.edges.end();
  for( i = tonode.edges.begin(); i != nee; ++i )
    if ( *i == edgeidx ) {
      tonode.edges.erase( i );
      break;
    }

  return 0;
}

template <typename T0, typename T1>
DCTPivector & DirectedGraph<T0, T1>::getEdges( int n ) // get all edges (indexes) from a node
{
  return &nodes.edges;
}

// get one node
template <typename T0, typename T1>
DirectedNode<T0>& DirectedGraph<T0, T1>::getNode( int nodeindex, int &error )
{
  error = 0;
  if ( nodeindex < 0 || nodeindex >= nodes.size() ) {
    error = -1;
    return NULL;
  }
  return &nodes[ nodeindex ] ;
}

// get one edge
template <typename T0, typename T1>
DirectedEdge<T1>& DirectedGraph<T0, T1>::getEdge( int edgeindex, int &error )
{
  error = 0;
  if ( edgeindex < 0 || edgeindex >= edges.size() ) {
    error = -1;
    return NULL;
  }
  return &edges[ edgeindex ] ;
}

// get one edge's direction
template <typename T0, typename T1>
bool DirectedGraph<T0, T1>::getEdgeDirection( int edgeindex, int &error )
{
  error = 0;
  if ( edgeindex < 0 || edgeindex >= edges.size() ) {
    error = -1;
    return false;
  }

  return edges[ edgeindex ].orientation;
}

// set the direction of an edge
template <typename T0, typename T1>
int DirectedGraph<T0, T1>::setEdgeDirection( int edgeindex, int to )
{
  if ( edgeindex < 0 || edgeindex >= int(edges.size()) ) return -1;

  if ( edges[ edgeindex ].from != to && edges[ edgeindex ].to != to )
    return -1;
  if ( edges[ edgeindex ].to != to ) {
    int tmp = edges[ edgeindex ].to;
    edges[ edgeindex ].to = to;
    edges[ edgeindex ].from = tmp;
  }
  edges[ edgeindex ].direction = true;
  return 0;
}

// change (invert) the direction of an edge
template <typename T0, typename T1>
int DirectedGraph<T0, T1>::changeEdgeDirection( int edgeindex )
{
  if ( edgeindex < 0 || edgeindex >= edges.size() )
    return -1;
  if ( !edges[ edgeindex ].orientation )
    return -1;

  int tmp = edges[ edgeindex ].to;
  edges[ edgeindex ].to = edges[ edgeindex ].from;
  edges[ edgeindex ].from = tmp;

  return 0;
}

template <typename T0, typename T1>
bool DirectedGraph<T0, T1>::isInvalid( void )
{
  return invalid;
}

template <typename T0, typename T1>
int DirectedGraph<T0, T1>::FindNode( T0 &nodeinfo )
{
	for( unsigned int i = 0; i < nodes.size( ); ++i )
	{
		if( nodes[ i ].nodeinfo == nodeinfo ) return i;
	}

	return -1;
}

template <typename T0, typename T1>
int DirectedGraph<T0, T1>::FindEdge( int from, int to )
{
	for( unsigned int i = 0; i < edges.size( ); ++i )
	{
//		std::cerr << "checking edge from " << edges[ i ].from << " to " << edges[ i ].to << std::endl;
		if( ( edges[ i ].from == from ) &&
			( edges[ i ].to == to ) ) return i;
		if( ( edges[ i ].from == to ) &&
			( edges[ i ].to == from ) ) return i;
	}

	return -1;
}

OSG_END_NAMESPACE
<|endoftext|>


<commit_before>#ifdef JOYSMOOTH_H_INC
#define JOYSMOOTH_H_INC

#include <bitset>
#include <GenericHID.h>
#include "612.h"
#include "update.h"
#include "joysmooth.h"

//provide definition of constants:
const int joysmooth::HOLDBACK;
const int joysmooth::NUMBUTTONS;
const int joysmooth::NUMAXES;

void register_callback(void*);
void update_callback_joysmooth(void*);

joysmooth::joysmooth(GenericHID* ghid) : joy(ghid) {
    register_callback((void*)this);
}

joysmooth::joysmooth(GenericHID& ghid) : joy(&ghid) {
    register_callback((void*)this);
}

joysmooth::~joysmooth() {
    registry().unregister_func(update_callback, (void*)this);
}

joysmooth::void update() {
    for (int d = 0; d < NUMBUTTONS; d++) {
        for (int i = 1; i < HOLDBACK; i++) {
            buttons[d][i - 1] = buttons[d][i];
        }
        buttons[d][HOLDBACK - 1] = joy->GetRawButton(d);
    }
    for(int d = 0; d < NUMAXES; d++) {
        axes[d] = joy->GetRawAxis(d);
    }
}

float joysmooth::GetX(GenericHID::JoystickHand h) {
   return axes[X_AXIS];
}

float joysmooth::GetY(GenericHID::JoystickHand h) {
   return axes[Y_AXIS];
}

float joysmooth::GetZ(){
    return axes[Z_AXIS];
}

float joysmooth::GetTwist(){
    return axis[TWIST_AXIS];
}

float joysmooth::GetThrottle(){
    return axes[THROTTLE_AXIS];
}

float joysmooth::GetRawAxis(UINT32 axisId){
    return axes[axisId];
}

bool joysmooth::GetTop(){
    return GetRawButton(2);
}

bool joysmooth::GetBumper(){
    return joy->GetBumper();
}

bool joysmooth::GetRawButton(UINT32 btnId){
    for(int i = 0; i < HOLDBACK; i++) {
        if(!buttons[btnId][i]) {
            return false;
        }
    }
    return true;
}

void register_callback(void* thisPtr) {
    registry().register_func(update_callback_joysmooth, thisPtr);
}

void update_callback_joysmooth(void* thisPtr) {
    ((joysmooth*)thisPtr)->update();
}

#endif
<commit_msg>Fixed bad syntax.  May resolve some undefined symbol errors (hopefully)<commit_after>#ifdef JOYSMOOTH_H_INC
#define JOYSMOOTH_H_INC

#include <bitset>
#include <GenericHID.h>
#include "612.h"
#include "update.h"
#include "joysmooth.h"

//provide definition of constants:
const int joysmooth::HOLDBACK;
const int joysmooth::NUMBUTTONS;
const int joysmooth::NUMAXES;

void register_callback(void*);
void update_callback_joysmooth(void*);

joysmooth::joysmooth(GenericHID* ghid) : joy(ghid) {
    register_callback((void*)this);
}

joysmooth::joysmooth(GenericHID& ghid) : joy(&ghid) {
    register_callback((void*)this);
}

joysmooth::~joysmooth() {
    registry().unregister_func(update_callback, (void*)this);
}

void joysmooth::update() {
    for (int d = 0; d < NUMBUTTONS; d++) {
        for (int i = 1; i < HOLDBACK; i++) {
            buttons[d][i - 1] = buttons[d][i];
        }
        buttons[d][HOLDBACK - 1] = joy->GetRawButton(d);
    }
    for(int d = 0; d < NUMAXES; d++) {
        axes[d] = joy->GetRawAxis(d);
    }
}

float joysmooth::GetX(GenericHID::JoystickHand h) {
   return axes[X_AXIS];
}

float joysmooth::GetY(GenericHID::JoystickHand h) {
   return axes[Y_AXIS];
}

float joysmooth::GetZ(){
    return axes[Z_AXIS];
}

float joysmooth::GetTwist(){
    return axis[TWIST_AXIS];
}

float joysmooth::GetThrottle(){
    return axes[THROTTLE_AXIS];
}

float joysmooth::GetRawAxis(UINT32 axisId){
    return axes[axisId];
}

bool joysmooth::GetTop(){
    return GetRawButton(2);
}

bool joysmooth::GetBumper(){
    return joy->GetBumper();
}

bool joysmooth::GetRawButton(UINT32 btnId){
    for(int i = 0; i < HOLDBACK; i++) {
        if(!buttons[btnId][i]) {
            return false;
        }
    }
    return true;
}

void register_callback(void* thisPtr) {
    registry().register_func(update_callback_joysmooth, thisPtr);
}

void update_callback_joysmooth(void* thisPtr) {
    ((joysmooth*)thisPtr)->update();
}

#endif
<|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2016 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// 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.

#pragma once
#ifndef MODEL_SQUIRREL_HPP
#define MODEL_SQUIRREL_HPP

#include <locale>

#include "json.hpp"

namespace acorn {

/**
 *
 */
struct Squirrel : json::Serializable {
  size_t key;

  Squirrel() : key(0) {}

  /**
   *
   */
  Squirrel(std::string name, size_t age, std::string occupation)
    : key         {0}
    , name_       {name}
    , age_        {age}
    , occupation_ {occupation}
  {}

  /**
   *
   */
  std::string json() const;

  /**
   *
   */
  virtual void serialize(rapidjson::Writer<rapidjson::StringBuffer>&) const override;

  /**
   *
   */
  virtual bool deserialize(const rapidjson::Document&) override;

  /**
   *
   */
  bool is_equal(const Squirrel&) const;

  /**
   *
   */
  static bool is_equal(const Squirrel&, const Squirrel&);

private:
  const std::string name_;
  const size_t      age_;
  const std::string occupation_;
}; //< struct Squirrel

/**--v----------- Implementation Details -----------v--**/

inline std::ostream& operator << (std::ostream& output_device, const Squirrel& s) {
  return output_device.json();
}

void Squirrel::serialize(rapidjson::Writer<rapidjson::StringBuffer>& writer) const {
  writer.StartObject();

  writer.Key("key");
  writer.Uint(key);

  writer.Key("name");
  writer.String(name_);

  writer.Key("age");
  writer.Uint(age_);

  writer.Key("occupation");
  writer.String(occupation_);

  writer.EndObject();
}

bool Squirrel::deserialize(const rapidjson::Document& doc) {
  name_       = doc["name"].GetString();
  age_        = doc["age"].GetUint();
  occupation_ = doc["occupation"].GetString();
  return true;
}

std::string Squirrel::json() const {
  using namespace rapidjson;
  StringBuffer sb;
  Writer<StringBuffer> writer(sb);
  serialize(writer);
  return sb.GetString();
}

bool Squirrel::is_equal(const Squirrel& s) const {
  if(name_.size() != s.name_.size())
    return false;
  for(size_t i = 0; i < name_.size(); i++) {
    if(std::tolower(name_[i]) != std::tolower(s.name_[i]))
      return false;
  }
  return true;
}

bool Squirrel::is_equal(const Squirrel& s1, const Squirrel& s2) {
  return s1.is_equal(s2);
}

/**--^----------- Implementation Details -----------^--**/

} //< namespace acorn

#endif //< MODEL_SQUIRREL_HPP
<commit_msg>Refactored Squirrel::is_equal<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2016 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// 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.

#pragma once
#ifndef MODEL_SQUIRREL_HPP
#define MODEL_SQUIRREL_HPP

#include <locale>
#include <algorithm>

#include "json.hpp"

namespace acorn {

/**
 *
 */
struct Squirrel : json::Serializable {
  size_t key;

  Squirrel() : key(0) {}

  /**
   *
   */
  Squirrel(std::string name, size_t age, std::string occupation)
    : key         {0}
    , name_       {name}
    , age_        {age}
    , occupation_ {occupation}
  {}

  /**
   *
   */
  std::string json() const;

  /**
   *
   */
  virtual void serialize(rapidjson::Writer<rapidjson::StringBuffer>&) const override;

  /**
   *
   */
  virtual bool deserialize(const rapidjson::Document&) override;

  /**
   *
   */
  bool is_equal(const Squirrel&) const;

  /**
   *
   */
  static bool is_equal(const Squirrel&, const Squirrel&);

private:
  const std::string name_;
  const size_t      age_;
  const std::string occupation_;
}; //< struct Squirrel

/**--v----------- Implementation Details -----------v--**/

inline std::ostream& operator << (std::ostream& output_device, const Squirrel& s) {
  return output_device.json();
}

void Squirrel::serialize(rapidjson::Writer<rapidjson::StringBuffer>& writer) const {
  writer.StartObject();

  writer.Key("key");
  writer.Uint(key);

  writer.Key("name");
  writer.String(name_);

  writer.Key("age");
  writer.Uint(age_);

  writer.Key("occupation");
  writer.String(occupation_);

  writer.EndObject();
}

bool Squirrel::deserialize(const rapidjson::Document& doc) {
  name_       = doc["name"].GetString();
  age_        = doc["age"].GetUint();
  occupation_ = doc["occupation"].GetString();
  return true;
}

std::string Squirrel::json() const {
  using namespace rapidjson;
  StringBuffer sb;
  Writer<StringBuffer> writer(sb);
  serialize(writer);
  return sb.GetString();
}

bool Squirrel::is_equal(const Squirrel& s) const {
  if(name_.size() not_eq s.name_.size()) {
    return false;
  }

  return std::equal(name_.begin(), name_.end(), s.name_.begin(), s.name_.end(),
    [](const auto a, const auto b) { return ::tolower(a) == ::tolower(b);
  });
}

bool Squirrel::is_equal(const Squirrel& s1, const Squirrel& s2) {
  return s1.is_equal(s2);
}

/**--^----------- Implementation Details -----------^--**/

} //< namespace acorn

#endif //< MODEL_SQUIRREL_HPP
<|endoftext|>