<commit_before>#include <map>
#include <sstream>
#include "GtpLayer.h"
#include "IPv4Layer.h"
#include "IPv6Layer.h"
#include "PayloadLayer.h"
#include "EndianPortable.h"

namespace pcpp
{

#define PCPP_GTP_V1_GPDU_MESSAGE_TYPE 0xff

/// ==================
/// GtpExtension class
/// ==================

GtpV1Layer::GtpExtension::GtpExtension()
{
    m_Data = NULL;
    m_DataLen = 0;
    m_ExtType = 0;
}

GtpV1Layer::GtpExtension::GtpExtension(uint8_t* data, size_t dataLen, uint8_t type)
{
    m_Data = data;
    m_DataLen = dataLen;
    m_ExtType = type;
}

GtpV1Layer::GtpExtension::GtpExtension(const GtpExtension& other)
{
    m_Data = other.m_Data;
    m_DataLen = other.m_DataLen;
    m_ExtType = other.m_ExtType;
}

GtpV1Layer::GtpExtension& GtpV1Layer::GtpExtension::operator=(const GtpV1Layer::GtpExtension& other)
{
    m_Data = other.m_Data;
    m_DataLen = other.m_DataLen;
    m_ExtType = other.m_ExtType;
    return *this;
}

bool GtpV1Layer::GtpExtension::isNull()
{
    return m_Data == NULL;
}

uint8_t GtpV1Layer::GtpExtension::getExtensionType()
{
    return m_ExtType;
}

size_t GtpV1Layer::GtpExtension::getTotalLength()
{
    if (m_Data == NULL)
    {
        return 0;
    }

    size_t len = (size_t)(m_Data[0]*4);
    if (len <= m_DataLen)
    {
        return len;
    }

    return m_DataLen;
}

size_t GtpV1Layer::GtpExtension::getContentLength()
{
    size_t res = getTotalLength();

    if (res >= 2*sizeof(uint8_t))
    {
        return (size_t)(res - 2*sizeof(uint8_t));
    }

    return 0;
}

uint8_t* GtpV1Layer::GtpExtension::getContent()
{
    if (m_Data == NULL || getContentLength() == 0)
    {
        return NULL;
    }

    return m_Data + sizeof(uint8_t);
}

uint8_t GtpV1Layer::GtpExtension::getNextExtensionHeaderType()
{
    if (m_Data == NULL || getTotalLength() < 4)
    {
        return 0;
    }

    uint8_t res = *(uint8_t*)(m_Data + sizeof(uint8_t) + getContentLength());

    return res;
}

GtpV1Layer::GtpExtension GtpV1Layer::GtpExtension::getNextExtension()
{
    size_t totalLength = getTotalLength();
    uint8_t nextExtType = getNextExtensionHeaderType();
    if (nextExtType > 0 && m_DataLen > totalLength + sizeof(uint8_t))
    {
        return GtpV1Layer::GtpExtension(m_Data + totalLength, m_DataLen - totalLength, nextExtType);
    }
    else
    {
        return GtpV1Layer::GtpExtension();
    }
}

/// ================
/// GtpV1Layer class
/// ================

bool GtpV1Layer::isGTPv1(const uint8_t* data, size_t dataSize)
{
    if (data != NULL && dataSize > 1 && (data[0] & 0xE0) == 0x20)
    {
        return true;
    }

    return false;
}

GtpV1Layer::gtpv1_header_extra* GtpV1Layer::getHeaderExtra()
{
    if (m_Data != NULL && m_DataLen >= sizeof(gtpv1_header) + sizeof(gtpv1_header_extra))
    {
        return (gtpv1_header_extra*)(m_Data + sizeof(gtpv1_header));
    }

    return NULL;
}

bool GtpV1Layer::getSequenceNumber(uint16_t& seqNumber)
{
    gtpv1_header* header = getHeader();
    gtpv1_header_extra* headerExtra = getHeaderExtra();
    if (header != NULL && headerExtra != NULL && header->sequenceNumberFlag == 1)
    {
        seqNumber = ntohs(headerExtra->sequenceNumber);
        return true;
    }

    return false;
}

bool GtpV1Layer::getNpduNumber(uint8_t& npduNum)
{
    gtpv1_header* header = getHeader();
    gtpv1_header_extra* headerExtra = getHeaderExtra();
    if (header != NULL && headerExtra != NULL && header->npduNumberFlag == 1)
    {
        npduNum = headerExtra->npduNumber;
        return true;
    }

    return false;
}

bool GtpV1Layer::getNextExtensionHeaderType(uint8_t& nextExtType)
{
    gtpv1_header* header = getHeader();
    gtpv1_header_extra* headerExtra = getHeaderExtra();
    if (header != NULL && headerExtra != NULL && header->extensionHeaderFlag == 1)
    {
        nextExtType = headerExtra->nextExtensionHeader;
        return true;
    }

    return false;
}

GtpV1Layer::GtpExtension GtpV1Layer::getNextExtension()
{
    uint8_t nextExtType = 0;
    bool nextExtExists = getNextExtensionHeaderType(nextExtType);
    if (!nextExtExists || nextExtType == 0 || m_DataLen < sizeof(gtpv1_header) + sizeof(uint8_t))
    {
        return GtpV1Layer::GtpExtension();
    }

    return GtpV1Layer::GtpExtension(m_Data + sizeof(gtpv1_header) + sizeof(gtpv1_header_extra), m_DataLen - sizeof(gtpv1_header) - sizeof(gtpv1_header_extra), nextExtType);
}

GtpV1MessageType GtpV1Layer::getMessageType()
{
    gtpv1_header* header = getHeader();

    if (header == NULL)
    {
        return GtpV1_MessageTypeUnknown;
    }

    return (GtpV1MessageType)header->messageType;
}

std::map<uint8_t, std::string> createGtpV1MessageTypeToStringMap()
{
	std::map<uint8_t, std::string> tempMap;

    tempMap[0] =   "GTPv1 Message Type Unknown";
    tempMap[1] =   "Echo Request";
    tempMap[2] =   "Echo Response";
    tempMap[3] =   "Version Not Supported";
    tempMap[4] =   "Node Alive Request";
    tempMap[5] =   "Node Alive Response";
    tempMap[6] =   "Redirection Request";
    tempMap[7] =   "Create PDP Context Request";
    tempMap[16] =  "Create PDP Context Response";
    tempMap[17] =  "Update PDP Context Request";
    tempMap[18] =  "Update PDP Context Response";
    tempMap[19] =  "Delete PDP Context Request";
    tempMap[20] =  "Delete PDP Context Response";
    tempMap[22] =  "Initiate PDP Context Activation Request";
    tempMap[23] =  "Initiate PDP Context Activation Response";
    tempMap[26] =  "Error Indication";
    tempMap[27] =  "PDU Notification Request";
    tempMap[28] =  "PDU Notification Response";
    tempMap[29] =  "PDU Notification Reject Request";
    tempMap[30] =  "PDU Notification Reject Response";
    tempMap[31] =  "Supported Extensions Header Notification";
    tempMap[32] =  "Send Routing for GPRS Request";
    tempMap[33] =  "Send Routing for GPRS Response";
    tempMap[34] =  "Failure Report Request";
    tempMap[35] =  "Failure Report Response";
    tempMap[36] =  "Note MS Present Request";
    tempMap[37] =  "Note MS Present Response";
    tempMap[38] =  "Identification Request";
    tempMap[39] =  "Identification Response";
    tempMap[50] =  "SGSN Context Request";
    tempMap[51] =  "SGSN Context Response";
    tempMap[52] =  "SGSN Context Acknowledge";
    tempMap[53] =  "Forward Relocation Request";
    tempMap[54] =  "Forward Relocation Response";
    tempMap[55] =  "Forward Relocation Complete";
    tempMap[56] =  "Relocation Cancel Request";
    tempMap[57] =  "Relocation Cancel Response";
    tempMap[58] =  "Forward SRNS Context";
    tempMap[59] =  "Forward Relocation Complete Acknowledge";
    tempMap[60] =  "Forward SRNS Context Acknowledge";
    tempMap[61] =  "UE Registration Request";
    tempMap[62] =  "UE Registration Response";
    tempMap[70] =  "RAN Information Relay";
    tempMap[96] =  "MBMS Notification Request";
    tempMap[97] =  "MBMS Notification Response";
    tempMap[98] =  "MBMS Notification Reject Request";
    tempMap[99] =  "MBMS Notification Reject Response";
    tempMap[100] = "Create MBMS Notification Request";
    tempMap[101] = "Create MBMS Notification Response";
    tempMap[102] = "Update MBMS Notification Request";
    tempMap[103] = "Update MBMS Notification Response";
    tempMap[104] = "Delete MBMS Notification Request";
    tempMap[105] = "Delete MBMS Notification Response";
    tempMap[112] = "MBMS Registration Request";
    tempMap[113] = "MBMS Registration Response";
    tempMap[114] = "MBMS De-Registration Request";
    tempMap[115] = "MBMS De-Registration Response";
    tempMap[116] = "MBMS Session Start Request";
    tempMap[117] = "MBMS Session Start Response";
    tempMap[118] = "MBMS Session Stop Request";
    tempMap[119] = "MBMS Session Stop Response";
    tempMap[120] = "MBMS Session Update Request";
    tempMap[121] = "MBMS Session Update Response";
    tempMap[128] = "MS Info Change Request";
    tempMap[129] = "MS Info Change Response";
    tempMap[240] = "Data Record Transfer Request";
    tempMap[241] = "Data Record Transfer Response";
    tempMap[254] = "End Marker";
    tempMap[255] = "G-PDU";

	return tempMap;
}

const std::map<uint8_t, std::string> GTPv1MsgTypeToStringMap = createGtpV1MessageTypeToStringMap();

std::string GtpV1Layer::getMessageTypeAsString()
{
    gtpv1_header* header = getHeader();

    if (header == NULL)
    {
        return GTPv1MsgTypeToStringMap.find(0)->second;
    }

    std::map<uint8_t, std::string>::const_iterator iter = GTPv1MsgTypeToStringMap.find(header->messageType);
    if (iter != GTPv1MsgTypeToStringMap.end())
    {
        return iter->second;
    }
    else
    {
        return GTPv1MsgTypeToStringMap.find(0)->second;
    }
}

bool GtpV1Layer::isGTPUMessage()
{
    gtpv1_header* header = getHeader();
    if (header == NULL)
    {
        return false;
    }

    return header->messageType == PCPP_GTP_V1_GPDU_MESSAGE_TYPE;
}

bool GtpV1Layer::isGTPCMessage()
{
    gtpv1_header* header = getHeader();
    if (header == NULL)
    {
        return false;
    }

    return header->messageType != PCPP_GTP_V1_GPDU_MESSAGE_TYPE;
}

void GtpV1Layer::parseNextLayer()
{
    size_t headerLen = getHeaderLen();
    if (headerLen < sizeof(gtpv1_header))
    {
        // do nothing
        return;
    }

    gtpv1_header* header = getHeader();
    if (header->messageType != PCPP_GTP_V1_GPDU_MESSAGE_TYPE)
    {
        // this is a GTP-C message, hence it is the last layer
        return;
    }

    if (m_DataLen <= headerLen)
    {
        // no data beyond headerLen, nothing to parse further
        return;
    }

    // GTP-U message, try to parse the next layer

    uint8_t subProto = *(uint8_t*)(m_Data + headerLen);
    if (subProto >= 0x45 && subProto <= 0x4e)
    {
        m_NextLayer = new IPv4Layer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet);
    }
    else if ((subProto & 0xf0) == 0x60)
    {
        m_NextLayer = new IPv6Layer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet);
    }
    else
    {
        m_NextLayer = new PayloadLayer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet);
    }
}

size_t GtpV1Layer::getHeaderLen()
{
    gtpv1_header* header = getHeader();
    if (header == NULL)
    {
        return 0;
    }

    size_t res = sizeof(gtpv1_header);

    if (header->messageType != PCPP_GTP_V1_GPDU_MESSAGE_TYPE)
    {
        size_t msgLen = ntohs(header->messageLength);
        res += (msgLen > m_DataLen - sizeof(gtpv1_header) ? m_DataLen - sizeof(gtpv1_header) : msgLen);
    }
    else
    {
        gtpv1_header_extra* headerExtra = getHeaderExtra();
        if (headerExtra != NULL && (header->extensionHeaderFlag == 1 || header->sequenceNumberFlag == 1 || header->npduNumberFlag == 1))
        {
               res += sizeof(gtpv1_header_extra);
            GtpExtension nextExt = getNextExtension();
            while (!nextExt.isNull())
            {
                res += nextExt.getTotalLength();
                nextExt = nextExt.getNextExtension();
            }
        }
    }

    return res;
}

std::string GtpV1Layer::toString()
{
    std::string res = "GTP v1 Layer";

    gtpv1_header* header = getHeader();
    if (header != NULL)
    {
   		std::stringstream teidStream;
		teidStream << ntohl(header->teid);

        std::string gtpu_gtpc;
        if (header->messageType == PCPP_GTP_V1_GPDU_MESSAGE_TYPE)
        {
            gtpu_gtpc = "GTP-U message";
        }
        else
        {
            gtpu_gtpc = "GTP-C message: " + getMessageTypeAsString();
        }

        res += ", " + gtpu_gtpc + ", TEID: " + teidStream.str();
    }

    return res;
}

}<commit_msg>Small fix<commit_after>#include <map>
#include <sstream>
#include "GtpLayer.h"
#include "IPv4Layer.h"
#include "IPv6Layer.h"
#include "PayloadLayer.h"
#include "EndianPortable.h"

namespace pcpp
{

#define PCPP_GTP_V1_GPDU_MESSAGE_TYPE 0xff

/// ==================
/// GtpExtension class
/// ==================

GtpV1Layer::GtpExtension::GtpExtension()
{
    m_Data = NULL;
    m_DataLen = 0;
    m_ExtType = 0;
}

GtpV1Layer::GtpExtension::GtpExtension(uint8_t* data, size_t dataLen, uint8_t type)
{
    m_Data = data;
    m_DataLen = dataLen;
    m_ExtType = type;
}

GtpV1Layer::GtpExtension::GtpExtension(const GtpExtension& other)
{
    m_Data = other.m_Data;
    m_DataLen = other.m_DataLen;
    m_ExtType = other.m_ExtType;
}

GtpV1Layer::GtpExtension& GtpV1Layer::GtpExtension::operator=(const GtpV1Layer::GtpExtension& other)
{
    m_Data = other.m_Data;
    m_DataLen = other.m_DataLen;
    m_ExtType = other.m_ExtType;
    return *this;
}

bool GtpV1Layer::GtpExtension::isNull()
{
    return m_Data == NULL;
}

uint8_t GtpV1Layer::GtpExtension::getExtensionType()
{
    return m_ExtType;
}

size_t GtpV1Layer::GtpExtension::getTotalLength()
{
    if (m_Data == NULL)
    {
        return 0;
    }

    size_t len = (size_t)(m_Data[0]*4);
    if (len <= m_DataLen)
    {
        return len;
    }

    return m_DataLen;
}

size_t GtpV1Layer::GtpExtension::getContentLength()
{
    size_t res = getTotalLength();

    if (res >= 2*sizeof(uint8_t))
    {
        return (size_t)(res - 2*sizeof(uint8_t));
    }

    return 0;
}

uint8_t* GtpV1Layer::GtpExtension::getContent()
{
    if (m_Data == NULL || getContentLength() == 0)
    {
        return NULL;
    }

    return m_Data + sizeof(uint8_t);
}

uint8_t GtpV1Layer::GtpExtension::getNextExtensionHeaderType()
{
    if (m_Data == NULL || getTotalLength() < 4)
    {
        return 0;
    }

    uint8_t res = *(uint8_t*)(m_Data + sizeof(uint8_t) + getContentLength());

    return res;
}

GtpV1Layer::GtpExtension GtpV1Layer::GtpExtension::getNextExtension()
{
    size_t totalLength = getTotalLength();
    uint8_t nextExtType = getNextExtensionHeaderType();
    if (nextExtType > 0 && m_DataLen > totalLength + sizeof(uint8_t))
    {
        return GtpV1Layer::GtpExtension(m_Data + totalLength, m_DataLen - totalLength, nextExtType);
    }
    else
    {
        return GtpV1Layer::GtpExtension();
    }
}

/// ================
/// GtpV1Layer class
/// ================

bool GtpV1Layer::isGTPv1(const uint8_t* data, size_t dataSize)
{
    if (data != NULL && dataSize > 1 && (data[0] & 0xE0) == 0x20)
    {
        return true;
    }

    return false;
}

GtpV1Layer::gtpv1_header_extra* GtpV1Layer::getHeaderExtra()
{
    if (m_Data != NULL && m_DataLen >= sizeof(gtpv1_header) + sizeof(gtpv1_header_extra))
    {
        return (gtpv1_header_extra*)(m_Data + sizeof(gtpv1_header));
    }

    return NULL;
}

bool GtpV1Layer::getSequenceNumber(uint16_t& seqNumber)
{
    gtpv1_header* header = getHeader();
    gtpv1_header_extra* headerExtra = getHeaderExtra();
    if (header != NULL && headerExtra != NULL && header->sequenceNumberFlag == 1)
    {
        seqNumber = be16toh(headerExtra->sequenceNumber);
        return true;
    }

    return false;
}

bool GtpV1Layer::getNpduNumber(uint8_t& npduNum)
{
    gtpv1_header* header = getHeader();
    gtpv1_header_extra* headerExtra = getHeaderExtra();
    if (header != NULL && headerExtra != NULL && header->npduNumberFlag == 1)
    {
        npduNum = headerExtra->npduNumber;
        return true;
    }

    return false;
}

bool GtpV1Layer::getNextExtensionHeaderType(uint8_t& nextExtType)
{
    gtpv1_header* header = getHeader();
    gtpv1_header_extra* headerExtra = getHeaderExtra();
    if (header != NULL && headerExtra != NULL && header->extensionHeaderFlag == 1)
    {
        nextExtType = headerExtra->nextExtensionHeader;
        return true;
    }

    return false;
}

GtpV1Layer::GtpExtension GtpV1Layer::getNextExtension()
{
    uint8_t nextExtType = 0;
    bool nextExtExists = getNextExtensionHeaderType(nextExtType);
    if (!nextExtExists || nextExtType == 0 || m_DataLen < sizeof(gtpv1_header) + sizeof(uint8_t))
    {
        return GtpV1Layer::GtpExtension();
    }

    return GtpV1Layer::GtpExtension(m_Data + sizeof(gtpv1_header) + sizeof(gtpv1_header_extra), m_DataLen - sizeof(gtpv1_header) - sizeof(gtpv1_header_extra), nextExtType);
}

GtpV1MessageType GtpV1Layer::getMessageType()
{
    gtpv1_header* header = getHeader();

    if (header == NULL)
    {
        return GtpV1_MessageTypeUnknown;
    }

    return (GtpV1MessageType)header->messageType;
}

std::map<uint8_t, std::string> createGtpV1MessageTypeToStringMap()
{
	std::map<uint8_t, std::string> tempMap;

    tempMap[0] =   "GTPv1 Message Type Unknown";
    tempMap[1] =   "Echo Request";
    tempMap[2] =   "Echo Response";
    tempMap[3] =   "Version Not Supported";
    tempMap[4] =   "Node Alive Request";
    tempMap[5] =   "Node Alive Response";
    tempMap[6] =   "Redirection Request";
    tempMap[7] =   "Create PDP Context Request";
    tempMap[16] =  "Create PDP Context Response";
    tempMap[17] =  "Update PDP Context Request";
    tempMap[18] =  "Update PDP Context Response";
    tempMap[19] =  "Delete PDP Context Request";
    tempMap[20] =  "Delete PDP Context Response";
    tempMap[22] =  "Initiate PDP Context Activation Request";
    tempMap[23] =  "Initiate PDP Context Activation Response";
    tempMap[26] =  "Error Indication";
    tempMap[27] =  "PDU Notification Request";
    tempMap[28] =  "PDU Notification Response";
    tempMap[29] =  "PDU Notification Reject Request";
    tempMap[30] =  "PDU Notification Reject Response";
    tempMap[31] =  "Supported Extensions Header Notification";
    tempMap[32] =  "Send Routing for GPRS Request";
    tempMap[33] =  "Send Routing for GPRS Response";
    tempMap[34] =  "Failure Report Request";
    tempMap[35] =  "Failure Report Response";
    tempMap[36] =  "Note MS Present Request";
    tempMap[37] =  "Note MS Present Response";
    tempMap[38] =  "Identification Request";
    tempMap[39] =  "Identification Response";
    tempMap[50] =  "SGSN Context Request";
    tempMap[51] =  "SGSN Context Response";
    tempMap[52] =  "SGSN Context Acknowledge";
    tempMap[53] =  "Forward Relocation Request";
    tempMap[54] =  "Forward Relocation Response";
    tempMap[55] =  "Forward Relocation Complete";
    tempMap[56] =  "Relocation Cancel Request";
    tempMap[57] =  "Relocation Cancel Response";
    tempMap[58] =  "Forward SRNS Context";
    tempMap[59] =  "Forward Relocation Complete Acknowledge";
    tempMap[60] =  "Forward SRNS Context Acknowledge";
    tempMap[61] =  "UE Registration Request";
    tempMap[62] =  "UE Registration Response";
    tempMap[70] =  "RAN Information Relay";
    tempMap[96] =  "MBMS Notification Request";
    tempMap[97] =  "MBMS Notification Response";
    tempMap[98] =  "MBMS Notification Reject Request";
    tempMap[99] =  "MBMS Notification Reject Response";
    tempMap[100] = "Create MBMS Notification Request";
    tempMap[101] = "Create MBMS Notification Response";
    tempMap[102] = "Update MBMS Notification Request";
    tempMap[103] = "Update MBMS Notification Response";
    tempMap[104] = "Delete MBMS Notification Request";
    tempMap[105] = "Delete MBMS Notification Response";
    tempMap[112] = "MBMS Registration Request";
    tempMap[113] = "MBMS Registration Response";
    tempMap[114] = "MBMS De-Registration Request";
    tempMap[115] = "MBMS De-Registration Response";
    tempMap[116] = "MBMS Session Start Request";
    tempMap[117] = "MBMS Session Start Response";
    tempMap[118] = "MBMS Session Stop Request";
    tempMap[119] = "MBMS Session Stop Response";
    tempMap[120] = "MBMS Session Update Request";
    tempMap[121] = "MBMS Session Update Response";
    tempMap[128] = "MS Info Change Request";
    tempMap[129] = "MS Info Change Response";
    tempMap[240] = "Data Record Transfer Request";
    tempMap[241] = "Data Record Transfer Response";
    tempMap[254] = "End Marker";
    tempMap[255] = "G-PDU";

	return tempMap;
}

const std::map<uint8_t, std::string> GTPv1MsgTypeToStringMap = createGtpV1MessageTypeToStringMap();

std::string GtpV1Layer::getMessageTypeAsString()
{
    gtpv1_header* header = getHeader();

    if (header == NULL)
    {
        return GTPv1MsgTypeToStringMap.find(0)->second;
    }

    std::map<uint8_t, std::string>::const_iterator iter = GTPv1MsgTypeToStringMap.find(header->messageType);
    if (iter != GTPv1MsgTypeToStringMap.end())
    {
        return iter->second;
    }
    else
    {
        return GTPv1MsgTypeToStringMap.find(0)->second;
    }
}

bool GtpV1Layer::isGTPUMessage()
{
    gtpv1_header* header = getHeader();
    if (header == NULL)
    {
        return false;
    }

    return header->messageType == PCPP_GTP_V1_GPDU_MESSAGE_TYPE;
}

bool GtpV1Layer::isGTPCMessage()
{
    gtpv1_header* header = getHeader();
    if (header == NULL)
    {
        return false;
    }

    return header->messageType != PCPP_GTP_V1_GPDU_MESSAGE_TYPE;
}

void GtpV1Layer::parseNextLayer()
{
    size_t headerLen = getHeaderLen();
    if (headerLen < sizeof(gtpv1_header))
    {
        // do nothing
        return;
    }

    gtpv1_header* header = getHeader();
    if (header->messageType != PCPP_GTP_V1_GPDU_MESSAGE_TYPE)
    {
        // this is a GTP-C message, hence it is the last layer
        return;
    }

    if (m_DataLen <= headerLen)
    {
        // no data beyond headerLen, nothing to parse further
        return;
    }

    // GTP-U message, try to parse the next layer

    uint8_t subProto = *(uint8_t*)(m_Data + headerLen);
    if (subProto >= 0x45 && subProto <= 0x4e)
    {
        m_NextLayer = new IPv4Layer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet);
    }
    else if ((subProto & 0xf0) == 0x60)
    {
        m_NextLayer = new IPv6Layer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet);
    }
    else
    {
        m_NextLayer = new PayloadLayer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet);
    }
}

size_t GtpV1Layer::getHeaderLen()
{
    gtpv1_header* header = getHeader();
    if (header == NULL)
    {
        return 0;
    }

    size_t res = sizeof(gtpv1_header);

    if (header->messageType != PCPP_GTP_V1_GPDU_MESSAGE_TYPE)
    {
        size_t msgLen = be16toh(header->messageLength);
        res += (msgLen > m_DataLen - sizeof(gtpv1_header) ? m_DataLen - sizeof(gtpv1_header) : msgLen);
    }
    else
    {
        gtpv1_header_extra* headerExtra = getHeaderExtra();
        if (headerExtra != NULL && (header->extensionHeaderFlag == 1 || header->sequenceNumberFlag == 1 || header->npduNumberFlag == 1))
        {
               res += sizeof(gtpv1_header_extra);
            GtpExtension nextExt = getNextExtension();
            while (!nextExt.isNull())
            {
                res += nextExt.getTotalLength();
                nextExt = nextExt.getNextExtension();
            }
        }
    }

    return res;
}

std::string GtpV1Layer::toString()
{
    std::string res = "GTP v1 Layer";

    gtpv1_header* header = getHeader();
    if (header != NULL)
    {
   		std::stringstream teidStream;
		teidStream << be32toh(header->teid);

        std::string gtpu_gtpc;
        if (header->messageType == PCPP_GTP_V1_GPDU_MESSAGE_TYPE)
        {
            gtpu_gtpc = "GTP-U message";
        }
        else
        {
            gtpu_gtpc = "GTP-C message: " + getMessageTypeAsString();
        }

        res += ", " + gtpu_gtpc + ", TEID: " + teidStream.str();
    }

    return res;
}

}<|endoftext|>


<commit_before>/*
 * Copyright 2016-present Facebook, 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.
 */

#include <folly/ssl/SSLSession.h>
#include <folly/io/async/test/AsyncSSLSocketTest.h>
#include <folly/portability/GTest.h>
#include <folly/portability/Sockets.h>

#include <memory>

using namespace std;
using namespace testing;
using folly::ssl::SSLSession;

namespace folly {

void getfds(int fds[2]) {
  if (socketpair(PF_LOCAL, SOCK_STREAM, 0, fds) != 0) {
    LOG(ERROR) << "failed to create socketpair: " << errnoStr(errno);
  }
  for (int idx = 0; idx < 2; ++idx) {
    int flags = fcntl(fds[idx], F_GETFL, 0);
    if (flags == -1) {
      LOG(ERROR) << "failed to get flags for socket " << idx << ": "
                 << errnoStr(errno);
    }
    if (fcntl(fds[idx], F_SETFL, flags | O_NONBLOCK) != 0) {
      LOG(ERROR) << "failed to put socket " << idx
                 << " in non-blocking mode: " << errnoStr(errno);
    }
  }
}

void getctx(
    std::shared_ptr<folly::SSLContext> clientCtx,
    std::shared_ptr<folly::SSLContext> serverCtx) {
  clientCtx->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");

  serverCtx->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
  serverCtx->loadCertificate(kTestCert);
  serverCtx->loadPrivateKey(kTestKey);
}

class SSLSessionTest : public testing::Test {
 public:
  void SetUp() override {
    clientCtx.reset(new folly::SSLContext());
    dfServerCtx.reset(new folly::SSLContext());
    hskServerCtx.reset(new folly::SSLContext());
    serverName = "xyz.newdev.facebook.com";
    getctx(clientCtx, dfServerCtx);
  }

  void TearDown() override {}

  folly::EventBase eventBase;
  std::shared_ptr<SSLContext> clientCtx;
  std::shared_ptr<SSLContext> dfServerCtx;
  // Use the same SSLContext to continue the handshake after
  // tlsext_hostname match.
  std::shared_ptr<SSLContext> hskServerCtx;
  std::string serverName;
};

/**
 * 1. Client sends TLSEXT_HOSTNAME in client hello.
 * 2. Server found a match SSL_CTX and use this SSL_CTX to
 *    continue the SSL handshake.
 * 3. Server sends back TLSEXT_HOSTNAME in server hello.
 */
TEST_F(SSLSessionTest, BasicTest) {
  std::unique_ptr<SSLSession> sess;

  {
    int fds[2];
    getfds(fds);
    AsyncSSLSocket::UniquePtr clientSock(
        new AsyncSSLSocket(clientCtx, &eventBase, fds[0], serverName));
    auto clientPtr = clientSock.get();
    AsyncSSLSocket::UniquePtr serverSock(
        new AsyncSSLSocket(dfServerCtx, &eventBase, fds[1], true));
    SSLHandshakeClient client(std::move(clientSock), false, false);
    SSLHandshakeServerParseClientHello server(
        std::move(serverSock), false, false);

    eventBase.loop();
    ASSERT_TRUE(client.handshakeSuccess_);

    sess = std::make_unique<SSLSession>(clientPtr->getSSLSession());
    ASSERT_NE(sess.get(), nullptr);
  }

  {
    int fds[2];
    getfds(fds);
    AsyncSSLSocket::UniquePtr clientSock(
        new AsyncSSLSocket(clientCtx, &eventBase, fds[0], serverName));
    auto clientPtr = clientSock.get();
    clientSock->setSSLSession(sess->getRawSSLSessionDangerous(), true);
    AsyncSSLSocket::UniquePtr serverSock(
        new AsyncSSLSocket(dfServerCtx, &eventBase, fds[1], true));
    SSLHandshakeClient client(std::move(clientSock), false, false);
    SSLHandshakeServerParseClientHello server(
        std::move(serverSock), false, false);

    eventBase.loop();
    ASSERT_TRUE(client.handshakeSuccess_);
    ASSERT_TRUE(clientPtr->getSSLSessionReused());
  }
}
TEST_F(SSLSessionTest, SerializeDeserializeTest) {
  std::string sessiondata;

  {
    int fds[2];
    getfds(fds);
    AsyncSSLSocket::UniquePtr clientSock(
        new AsyncSSLSocket(clientCtx, &eventBase, fds[0], serverName));
    auto clientPtr = clientSock.get();
    AsyncSSLSocket::UniquePtr serverSock(
        new AsyncSSLSocket(dfServerCtx, &eventBase, fds[1], true));
    SSLHandshakeClient client(std::move(clientSock), false, false);
    SSLHandshakeServerParseClientHello server(
        std::move(serverSock), false, false);

    eventBase.loop();
    ASSERT_TRUE(client.handshakeSuccess_);

    std::unique_ptr<SSLSession> sess =
        std::make_unique<SSLSession>(clientPtr->getSSLSession());
    sessiondata = sess->serialize();
    ASSERT_TRUE(!sessiondata.empty());
  }

  {
    int fds[2];
    getfds(fds);
    AsyncSSLSocket::UniquePtr clientSock(
        new AsyncSSLSocket(clientCtx, &eventBase, fds[0], serverName));
    auto clientPtr = clientSock.get();
    std::unique_ptr<SSLSession> sess =
        std::make_unique<SSLSession>(sessiondata);
    ASSERT_NE(sess.get(), nullptr);
    clientSock->setSSLSession(sess->getRawSSLSessionDangerous(), true);
    AsyncSSLSocket::UniquePtr serverSock(
        new AsyncSSLSocket(dfServerCtx, &eventBase, fds[1], true));
    SSLHandshakeClient client(std::move(clientSock), false, false);
    SSLHandshakeServerParseClientHello server(
        std::move(serverSock), false, false);

    eventBase.loop();
    ASSERT_TRUE(client.handshakeSuccess_);
    ASSERT_TRUE(clientPtr->getSSLSessionReused());
  }
}

TEST_F(SSLSessionTest, GetSessionID) {
  int fds[2];
  getfds(fds);
  AsyncSSLSocket::UniquePtr clientSock(
      new AsyncSSLSocket(clientCtx, &eventBase, fds[0], serverName));
  auto clientPtr = clientSock.get();
  AsyncSSLSocket::UniquePtr serverSock(
      new AsyncSSLSocket(dfServerCtx, &eventBase, fds[1], true));
  SSLHandshakeClient client(std::move(clientSock), false, false);
  SSLHandshakeServerParseClientHello server(
      std::move(serverSock), false, false);

  eventBase.loop();
  ASSERT_TRUE(client.handshakeSuccess_);

  std::unique_ptr<SSLSession> sess =
      std::make_unique<SSLSession>(clientPtr->getSSLSession());
  ASSERT_NE(sess, nullptr);
  auto sessID = sess->getSessionID();
  ASSERT_GE(sessID.length(), 0);
}
} // namespace folly
<commit_msg>SSLSessionTest now uses NetworkSocket<commit_after>/*
 * Copyright 2016-present Facebook, 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.
 */

#include <folly/ssl/SSLSession.h>
#include <folly/io/async/test/AsyncSSLSocketTest.h>
#include <folly/net/NetOps.h>
#include <folly/net/NetworkSocket.h>
#include <folly/portability/GTest.h>
#include <folly/portability/Sockets.h>

#include <memory>

using namespace std;
using namespace testing;
using folly::ssl::SSLSession;

namespace folly {

void getfds(NetworkSocket fds[2]) {
  if (netops::socketpair(PF_LOCAL, SOCK_STREAM, 0, fds) != 0) {
    FAIL() << "failed to create socketpair: " << errnoStr(errno);
  }
  for (int idx = 0; idx < 2; ++idx) {
    if (netops::set_socket_non_blocking(fds[idx]) != 0) {
      FAIL() << "failed to put socket " << idx
             << " in non-blocking mode: " << errnoStr(errno);
    }
  }
}

void getctx(
    std::shared_ptr<folly::SSLContext> clientCtx,
    std::shared_ptr<folly::SSLContext> serverCtx) {
  clientCtx->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");

  serverCtx->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
  serverCtx->loadCertificate(kTestCert);
  serverCtx->loadPrivateKey(kTestKey);
}

class SSLSessionTest : public testing::Test {
 public:
  void SetUp() override {
    clientCtx.reset(new folly::SSLContext());
    dfServerCtx.reset(new folly::SSLContext());
    hskServerCtx.reset(new folly::SSLContext());
    serverName = "xyz.newdev.facebook.com";
    getctx(clientCtx, dfServerCtx);
  }

  void TearDown() override {}

  folly::EventBase eventBase;
  std::shared_ptr<SSLContext> clientCtx;
  std::shared_ptr<SSLContext> dfServerCtx;
  // Use the same SSLContext to continue the handshake after
  // tlsext_hostname match.
  std::shared_ptr<SSLContext> hskServerCtx;
  std::string serverName;
};

/**
 * 1. Client sends TLSEXT_HOSTNAME in client hello.
 * 2. Server found a match SSL_CTX and use this SSL_CTX to
 *    continue the SSL handshake.
 * 3. Server sends back TLSEXT_HOSTNAME in server hello.
 */
TEST_F(SSLSessionTest, BasicTest) {
  std::unique_ptr<SSLSession> sess;

  {
    NetworkSocket fds[2];
    getfds(fds);
    AsyncSSLSocket::UniquePtr clientSock(
        new AsyncSSLSocket(clientCtx, &eventBase, fds[0], serverName));
    auto clientPtr = clientSock.get();
    AsyncSSLSocket::UniquePtr serverSock(
        new AsyncSSLSocket(dfServerCtx, &eventBase, fds[1], true));
    SSLHandshakeClient client(std::move(clientSock), false, false);
    SSLHandshakeServerParseClientHello server(
        std::move(serverSock), false, false);

    eventBase.loop();
    ASSERT_TRUE(client.handshakeSuccess_);

    sess = std::make_unique<SSLSession>(clientPtr->getSSLSession());
    ASSERT_NE(sess.get(), nullptr);
  }

  {
    NetworkSocket fds[2];
    getfds(fds);
    AsyncSSLSocket::UniquePtr clientSock(
        new AsyncSSLSocket(clientCtx, &eventBase, fds[0], serverName));
    auto clientPtr = clientSock.get();
    clientSock->setSSLSession(sess->getRawSSLSessionDangerous(), true);
    AsyncSSLSocket::UniquePtr serverSock(
        new AsyncSSLSocket(dfServerCtx, &eventBase, fds[1], true));
    SSLHandshakeClient client(std::move(clientSock), false, false);
    SSLHandshakeServerParseClientHello server(
        std::move(serverSock), false, false);

    eventBase.loop();
    ASSERT_TRUE(client.handshakeSuccess_);
    ASSERT_TRUE(clientPtr->getSSLSessionReused());
  }
}
TEST_F(SSLSessionTest, SerializeDeserializeTest) {
  std::string sessiondata;

  {
    NetworkSocket fds[2];
    getfds(fds);
    AsyncSSLSocket::UniquePtr clientSock(
        new AsyncSSLSocket(clientCtx, &eventBase, fds[0], serverName));
    auto clientPtr = clientSock.get();
    AsyncSSLSocket::UniquePtr serverSock(
        new AsyncSSLSocket(dfServerCtx, &eventBase, fds[1], true));
    SSLHandshakeClient client(std::move(clientSock), false, false);
    SSLHandshakeServerParseClientHello server(
        std::move(serverSock), false, false);

    eventBase.loop();
    ASSERT_TRUE(client.handshakeSuccess_);

    std::unique_ptr<SSLSession> sess =
        std::make_unique<SSLSession>(clientPtr->getSSLSession());
    sessiondata = sess->serialize();
    ASSERT_TRUE(!sessiondata.empty());
  }

  {
    NetworkSocket fds[2];
    getfds(fds);
    AsyncSSLSocket::UniquePtr clientSock(
        new AsyncSSLSocket(clientCtx, &eventBase, fds[0], serverName));
    auto clientPtr = clientSock.get();
    std::unique_ptr<SSLSession> sess =
        std::make_unique<SSLSession>(sessiondata);
    ASSERT_NE(sess.get(), nullptr);
    clientSock->setSSLSession(sess->getRawSSLSessionDangerous(), true);
    AsyncSSLSocket::UniquePtr serverSock(
        new AsyncSSLSocket(dfServerCtx, &eventBase, fds[1], true));
    SSLHandshakeClient client(std::move(clientSock), false, false);
    SSLHandshakeServerParseClientHello server(
        std::move(serverSock), false, false);

    eventBase.loop();
    ASSERT_TRUE(client.handshakeSuccess_);
    ASSERT_TRUE(clientPtr->getSSLSessionReused());
  }
}

TEST_F(SSLSessionTest, GetSessionID) {
  NetworkSocket fds[2];
  getfds(fds);
  AsyncSSLSocket::UniquePtr clientSock(
      new AsyncSSLSocket(clientCtx, &eventBase, fds[0], serverName));
  auto clientPtr = clientSock.get();
  AsyncSSLSocket::UniquePtr serverSock(
      new AsyncSSLSocket(dfServerCtx, &eventBase, fds[1], true));
  SSLHandshakeClient client(std::move(clientSock), false, false);
  SSLHandshakeServerParseClientHello server(
      std::move(serverSock), false, false);

  eventBase.loop();
  ASSERT_TRUE(client.handshakeSuccess_);

  std::unique_ptr<SSLSession> sess =
      std::make_unique<SSLSession>(clientPtr->getSSLSession());
  ASSERT_NE(sess, nullptr);
  auto sessID = sess->getSessionID();
  ASSERT_GE(sessID.length(), 0);
}
} // namespace folly
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: boolexpression.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 23:14:15 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "boolexpression.hxx"

namespace xforms
{

/** BoolExpression represents a computed XPath expression that returns
 * a bool value and caches the results.
 *
 * As this class has no virtual methods, it should never be used
 * polymorphically. */

BoolExpression::BoolExpression() : ComputedExpression()
{
}

BoolExpression::~BoolExpression()
{
}

void BoolExpression::setExpression( const rtl::OUString& rExpression )
{
    ComputedExpression::setExpression( rExpression );
    mbIsSimple = _checkExpression( " *(true)|(false) *\\( *\\) *" );
}

} // namespace xforms

<commit_msg>INTEGRATION: CWS pchfix02 (1.3.112); FILE MERGED 2006/09/01 17:27:45 kaib 1.3.112.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: boolexpression.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 00:02:51 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_forms.hxx"

#include "boolexpression.hxx"

namespace xforms
{

/** BoolExpression represents a computed XPath expression that returns
 * a bool value and caches the results.
 *
 * As this class has no virtual methods, it should never be used
 * polymorphically. */

BoolExpression::BoolExpression() : ComputedExpression()
{
}

BoolExpression::~BoolExpression()
{
}

void BoolExpression::setExpression( const rtl::OUString& rExpression )
{
    ComputedExpression::setExpression( rExpression );
    mbIsSimple = _checkExpression( " *(true)|(false) *\\( *\\) *" );
}

} // namespace xforms

<|endoftext|>


<commit_before>#ifndef ALEPH_TOPOLOGY_SPINE_HH__
#define ALEPH_TOPOLOGY_SPINE_HH__

#include <aleph/topology/Intersections.hh>

#include <set>
#include <vector>

namespace aleph
{

namespace topology
{

/**
  Checks whether a simplex in a simplicial complex is principal, i.e.
  whether it is not a proper face of any other simplex in K.
*/

template <class SimplicialComplex, class Simplex> bool isPrincipal( const Simplex& s, const SimplicialComplex& K )
{
  // Individual vertices cannot be considered to be principal because
  // they do not have a free face.
  if( s.dimension() == 0 )
    return false;

  bool principal = true;
  auto itPair    = K.range( s.dimension() + 1 );

  for( auto it = itPair.first; it != itPair.second; ++it )
  {
    auto&& t = *it;

    // This check assumes that the simplicial complex is valid, so it
    // suffices to search faces in one dimension _below_ s. Note that
    // the check only has to evaluate the *size* of the intersection,
    // as this is sufficient to determine whether a simplex is a face
    // of another simplex.
    if( sizeOfIntersection(s,t) == s.size() )
      principal = false;
  }

  return principal;
}

/**
  Checks whether a simplex in a simplicial complex is admissible, i.e.
  the simplex is *principal* and has at least one free face.
*/

template <class SimplicialComplex, class Simplex> bool isAdmissible( const Simplex& s, const SimplicialComplex& K )
{
  if( !isPrincipal(s,K) )
    return false;

  // Check whether a free face exists ----------------------------------

  std::vector<Simplex> faces( s.begin_boundary(), s.end_boundary() );
  std::vector<bool> admissible( faces.size(), true );

  std::size_t i = 0;
  auto itPair   = K.range( s.dimension() ); // valid range for searches, viz. *all*
                                            // faces in "one dimension up"

  for( auto&& face : faces )
  {
    for( auto it = itPair.first; it != itPair.second; ++it )
    {
      auto&& t = *it;

      // We do not have to check for intersections with the original
      // simplex from which we started---we already know that we are
      // a face.
      if( t != s )
      {
        if( sizeOfIntersection(face,t) == face.size() )
        {
          admissible[i] = false;
          break;
        }
      }
    }

    ++i;
  }

  // TODO: return free face along with admissibility condition
  return std::find( admissible.begin(), admissible.end(), true ) != admissible.end();
}

/**
  Checks whether a pair of a simplex and its face are admissible, i.e.
  the simplex is *principal* and the face is free.
*/

template <class SimplicialComplex, class Simplex> bool isAdmissible( const Simplex& sigma, const Simplex& delta, const SimplicialComplex& K )
{
  if( !isPrincipal(sigma,K) )
    return false;

  // Check whether the face is free ------------------------------------

  bool admissible = true;
  auto itPair     = K.range( delta.dimension() + 1 );

  for( auto it = itPair.first; it != itPair.second; ++it )
  {
    auto&& s = *it;

    // The simplex we are looking for should be a free face of sigma, so
    // we must skip it when checking for other co-faces.
    if( s != sigma )
    {
      if( sizeOfIntersection(delta, s) == delta.size() )
      {
        admissible = false;
        break;
      }
    }
  }

  return admissible;
}

/**
  Performs one step of an elementary simplicial collapse in a given
  simplicial complex. The function assumes that the given simplices
  are *valid* for performing the collapse.
*/

template <class SimplicialComplex, class Simplex> SimplicialComplex elementarySimplicialCollapse(
  const Simplex& sigma,
  const Simplex& delta,
  const SimplicialComplex& K )
{
  auto L = K;

  L.remove_without_validation( sigma );
  L.remove_without_validation( delta );
}

/**
  Performs an iterated elementary simplicial collapse until *all* of the
  admissible simplices have been collapsed. This leads to the *spine* of
  the simplicial complex.

  @see S. Matveev, "Algorithmic Topology and Classification of 3-Manifolds"
*/

template <class SimplicialComplex> SimplicialComplex spine( const SimplicialComplex& K )
{
  using Simplex = typename SimplicialComplex::value_type;
  auto L        = K;

  std::set<Simplex> admissible;

  // Step 1: determine free faces --------------------------------------
  //
  // This first checks which simplices have at least one free face,
  // meaning that they may be potentially admissible.

  for( auto it = L.begin(); it != L.end(); ++it )
  {
    if( it->dimension() == 0 )
      continue;

    // The range of the complex M is sufficient because we have
    // already encountered all lower-dimensional simplices that
    // precede the current one given by `it`.
    //
    // This complex will be used for testing free faces.
    SimplicialComplex M( L.begin(), it );

    bool hasFreeFace = false;
    for( auto itFace = it->begin_boundary(); itFace != it->end_boundary(); ++itFace )
    {
      bool isFace = false;
      for( auto&& simplex : M )
      {
        if( itFace->dimension() + 1 == simplex.dimension() )
        {
          // The current face must *not* be a face of another simplex in
          // the simplicial complex.
          if( intersect( *itFace, simplex ) == *itFace )
          {
            isFace = true;
            break;
          }
        }
      }

      hasFreeFace = !isFace;
      if( hasFreeFace )
        break;
    }

    if( hasFreeFace )
      admissible.insert( *it );
  }

  // Step 2: determine principality ------------------------------------
  //
  // All simplices that are faces of higher-dimensional simplices are
  // now removed from the map of admissible simplices.

  for( auto&& s : L )
  {
    for( auto itFace = s.begin_boundary(); itFace != s.end_boundary(); ++itFace )
      admissible.erase( *itFace );
  }

  // Step 3: collapse until no admissible simplices are left -----------

  while( !admissible.empty() )
  {
    auto s           = *admissible.begin();
    bool hasFreeFace = false;

    // TODO: this check could be simplified by *storing* the free face
    // along with the given simplex
    for( auto itFace = s.begin_boundary(); itFace != s.end_boundary(); ++itFace )
    {
      auto t = *itFace;

      if( isAdmissible( s, t, L ) )
      {
        L.remove_without_validation( s );
        L.remove_without_validation( t );

        admissible.erase( s );

        // New simplices -----------------------------------------------
        //
        // Add new admissible simplices that may potentially have been
        // spawned by the removal of s.

        std::vector<Simplex> faces( s.begin_boundary(), s.end_boundary() );

        std::for_each( faces.begin(), faces.end(),
          [&t, &L, &admissible] ( const Simplex& s )
          {
            if( t != s && isAdmissible( s, L ) )
              admissible.insert( s );
          }
        );

        faces.assign( t.begin_boundary(), t.end_boundary() );

        std::for_each( faces.begin(), faces.end(),
          [&L, &admissible] ( const Simplex& s )
          {
            if( isAdmissible( s, L ) )
              admissible.insert( s );
          }
        );

        hasFreeFace = true;
        break;
      }
    }

    // The admissible simplex does not have a free face, so it must not
    // be used.
    if( !hasFreeFace )
      admissible.erase( s );
  }

  return L;
}

} // namespace topology

} // namespace aleph

#endif
<commit_msg>New function for determining principal faces in a simplicial complex<commit_after>#ifndef ALEPH_TOPOLOGY_SPINE_HH__
#define ALEPH_TOPOLOGY_SPINE_HH__

#include <aleph/topology/Intersections.hh>

#include <set>
#include <vector>

namespace aleph
{

namespace topology
{

/**
  Checks whether a simplex in a simplicial complex is principal, i.e.
  whether it is not a proper face of any other simplex in K.
*/

template <class SimplicialComplex, class Simplex> bool isPrincipal( const Simplex& s, const SimplicialComplex& K )
{
  // Individual vertices cannot be considered to be principal because
  // they do not have a free face.
  if( s.dimension() == 0 )
    return false;

  bool principal = true;
  auto itPair    = K.range( s.dimension() + 1 );

  for( auto it = itPair.first; it != itPair.second; ++it )
  {
    auto&& t = *it;

    // This check assumes that the simplicial complex is valid, so it
    // suffices to search faces in one dimension _below_ s. Note that
    // the check only has to evaluate the *size* of the intersection,
    // as this is sufficient to determine whether a simplex is a face
    // of another simplex.
    if( sizeOfIntersection(s,t) == s.size() )
      principal = false;
  }

  return principal;
}

/**
  Checks whether a simplex in a simplicial complex is admissible, i.e.
  the simplex is *principal* and has at least one free face.
*/

template <class SimplicialComplex, class Simplex> bool isAdmissible( const Simplex& s, const SimplicialComplex& K )
{
  if( !isPrincipal(s,K) )
    return false;

  // Check whether a free face exists ----------------------------------

  std::vector<Simplex> faces( s.begin_boundary(), s.end_boundary() );
  std::vector<bool> admissible( faces.size(), true );

  std::size_t i = 0;
  auto itPair   = K.range( s.dimension() ); // valid range for searches, viz. *all*
                                            // faces in "one dimension up"

  for( auto&& face : faces )
  {
    for( auto it = itPair.first; it != itPair.second; ++it )
    {
      auto&& t = *it;

      // We do not have to check for intersections with the original
      // simplex from which we started---we already know that we are
      // a face.
      if( t != s )
      {
        if( sizeOfIntersection(face,t) == face.size() )
        {
          admissible[i] = false;
          break;
        }
      }
    }

    ++i;
  }

  // TODO: return free face along with admissibility condition
  return std::find( admissible.begin(), admissible.end(), true ) != admissible.end();
}

/**
  Checks whether a pair of a simplex and its face are admissible, i.e.
  the simplex is *principal* and the face is free.
*/

template <class SimplicialComplex, class Simplex> bool isAdmissible( const Simplex& sigma, const Simplex& delta, const SimplicialComplex& K )
{
  if( !isPrincipal(sigma,K) )
    return false;

  // Check whether the face is free ------------------------------------

  bool admissible = true;
  auto itPair     = K.range( delta.dimension() + 1 );

  for( auto it = itPair.first; it != itPair.second; ++it )
  {
    auto&& s = *it;

    // The simplex we are looking for should be a free face of sigma, so
    // we must skip it when checking for other co-faces.
    if( s != sigma )
    {
      if( sizeOfIntersection(delta, s) == delta.size() )
      {
        admissible = false;
        break;
      }
    }
  }

  return admissible;
}

/**
  Calculates all principal faces of a given simplicial complex and
  returns them.
*/

template <class SimplicialComplex> std::unordered_set<typename SimplicialComplex::value_type> principalFaces( const SimplicialComplex& K )
{
  using Simplex = typename SimplicialComplex::value_type;
  auto L        = K;

  std::unordered_set<Simplex> admissible;

  // Step 1: determine free faces --------------------------------------
  //
  // This first checks which simplices have at least one free face,
  // meaning that they may be potentially admissible.

  for( auto it = L.begin(); it != L.end(); ++it )
  {
    if( it->dimension() == 0 )
      continue;

    // The range of the complex M is sufficient because we have
    // already encountered all lower-dimensional simplices that
    // precede the current one given by `it`.
    //
    // This complex will be used for testing free faces.
    SimplicialComplex M( L.begin(), it );

    // FIXME:
    //
    // In case of equal data values, the assignment from above does
    // *not* work and will result in incorrect candidates.
    M = L;

    bool hasFreeFace = false;
    for( auto itFace = it->begin_boundary(); itFace != it->end_boundary(); ++itFace )
    {
      bool isFace = false;
      for( auto&& simplex : M )
      {
        if( itFace->dimension() + 1 == simplex.dimension() && simplex != *it )
        {
          // The current face must *not* be a face of another simplex in
          // the simplicial complex.
          if( intersect( *itFace, simplex ) == *itFace )
          {
            isFace = true;
            break;
          }
        }
      }

      hasFreeFace = !isFace;
      if( hasFreeFace )
        break;
    }

    if( hasFreeFace )
      admissible.insert( *it );
  }

  // Step 2: determine principality ------------------------------------
  //
  // All simplices that are faces of higher-dimensional simplices are
  // now removed from the map of admissible simplices.

  for( auto&& s : L )
  {
    for( auto itFace = s.begin_boundary(); itFace != s.end_boundary(); ++itFace )
      admissible.erase( *itFace );
  }

  return admissible;
}

/**
  Performs one step of an elementary simplicial collapse in a given
  simplicial complex. The function assumes that the given simplices
  are *valid* for performing the collapse.
*/

template <class SimplicialComplex, class Simplex> SimplicialComplex elementarySimplicialCollapse(
  const Simplex& sigma,
  const Simplex& delta,
  const SimplicialComplex& K )
{
  auto L = K;

  L.remove_without_validation( sigma );
  L.remove_without_validation( delta );
}

/**
  Performs an iterated elementary simplicial collapse until *all* of the
  admissible simplices have been collapsed. This leads to the *spine* of
  the simplicial complex.

  @see S. Matveev, "Algorithmic Topology and Classification of 3-Manifolds"
*/

template <class SimplicialComplex> SimplicialComplex spine( const SimplicialComplex& K )
{
  using Simplex = typename SimplicialComplex::value_type;
  auto L        = K;

  std::set<Simplex> admissible;

  // Step 1: determine free faces --------------------------------------
  //
  // This first checks which simplices have at least one free face,
  // meaning that they may be potentially admissible.

  for( auto it = L.begin(); it != L.end(); ++it )
  {
    if( it->dimension() == 0 )
      continue;

    // The range of the complex M is sufficient because we have
    // already encountered all lower-dimensional simplices that
    // precede the current one given by `it`.
    //
    // This complex will be used for testing free faces.
    SimplicialComplex M( L.begin(), it );

    bool hasFreeFace = false;
    for( auto itFace = it->begin_boundary(); itFace != it->end_boundary(); ++itFace )
    {
      bool isFace = false;
      for( auto&& simplex : M )
      {
        if( itFace->dimension() + 1 == simplex.dimension() )
        {
          // The current face must *not* be a face of another simplex in
          // the simplicial complex.
          if( intersect( *itFace, simplex ) == *itFace )
          {
            isFace = true;
            break;
          }
        }
      }

      hasFreeFace = !isFace;
      if( hasFreeFace )
        break;
    }

    if( hasFreeFace )
      admissible.insert( *it );
  }

  // Step 2: determine principality ------------------------------------
  //
  // All simplices that are faces of higher-dimensional simplices are
  // now removed from the map of admissible simplices.

  for( auto&& s : L )
  {
    for( auto itFace = s.begin_boundary(); itFace != s.end_boundary(); ++itFace )
      admissible.erase( *itFace );
  }

  // Step 3: collapse until no admissible simplices are left -----------

  while( !admissible.empty() )
  {
    auto s           = *admissible.begin();
    bool hasFreeFace = false;

    // TODO: this check could be simplified by *storing* the free face
    // along with the given simplex
    for( auto itFace = s.begin_boundary(); itFace != s.end_boundary(); ++itFace )
    {
      auto t = *itFace;

      if( isAdmissible( s, t, L ) )
      {
        L.remove_without_validation( s );
        L.remove_without_validation( t );

        admissible.erase( s );

        // New simplices -----------------------------------------------
        //
        // Add new admissible simplices that may potentially have been
        // spawned by the removal of s.

        std::vector<Simplex> faces( s.begin_boundary(), s.end_boundary() );

        std::for_each( faces.begin(), faces.end(),
          [&t, &L, &admissible] ( const Simplex& s )
          {
            if( t != s && isAdmissible( s, L ) )
              admissible.insert( s );
          }
        );

        faces.assign( t.begin_boundary(), t.end_boundary() );

        std::for_each( faces.begin(), faces.end(),
          [&L, &admissible] ( const Simplex& s )
          {
            if( isAdmissible( s, L ) )
              admissible.insert( s );
          }
        );

        hasFreeFace = true;
        break;
      }
    }

    // The admissible simplex does not have a free face, so it must not
    // be used.
    if( !hasFreeFace )
      admissible.erase( s );
  }

  return L;
}

} // namespace topology

} // namespace aleph

#endif
<|endoftext|>


<commit_before>#pragma once
class HttpRouter
{
public:

private:

};
<commit_msg>update http_router.hpp 修改<commit_after>#pragma once
#include <vector>
#include <map>
#include <string>
#include <functional>
#include "function_traits.hpp"
#include "lexical_cast.hpp"

class HttpRouter
{
	class token_parser
	{
		std::vector<std::string> m_v;
		static std::vector<std::string> split(std::string& s, char seperator)
		{
			std::vector<std::string> v;
			int pos = 0;
			while (true)
			{
				pos = s.find(seperator, 0);
				if (pos == std::string::npos)
				{
					if (!s.empty())
						v.push_back(s);
					break;
				}
				if (pos != 0)
					v.push_back(s.substr(0, pos));
				s = s.substr(pos + 1, s.length());
			}

			return v;
		}
	public:

		token_parser(std::string& s, char seperator)
		{
			m_v = split(s, seperator);
		}

	public:
		template<typename RequestedType>
		typename std::decay<RequestedType>::type get()
		{
			if (m_v.empty())
				throw std::runtime_error("unexpected end of input");

			try
			{
				typedef typename std::decay<RequestedType>::type result_type;

				auto it = m_v.begin();
				result_type result = lexical_cast<typename std::decay<result_type>::type>(*it);
				m_v.erase(it);
				return result;
			}
			catch (std::exception& e)
			{
				throw std::invalid_argument(std::string("invalid argument: ") + e.what());
			}
		}

		bool empty(){ return m_v.empty(); }
	};

	typedef std::function<void(token_parser &)> invoker_function;

	std::map<std::string, invoker_function> map_invokers;

public:
	std::function<void(const std::string&)> log;

	template<typename Function>
	void assign(std::string const & name, Function f) {
		return register_nonmenber_impl<Function>(name, f);
	}

	void remove_function(std::string const& name) {
		this->map_invokers.erase(name);
	}

	void run(std::string  & text) const
	{
		token_parser parser(text, '/');

		while (!parser.empty())
		{
			// read function name
			std::string func_name = parser.get<std::string>();

			// look up function
			auto it = map_invokers.find(func_name);
			if (it == map_invokers.end())
				throw std::runtime_error("unknown function: " + func_name);

			// call the invoker which controls argument parsing
			it->second(parser);
		}
	}

public:
	template<class Signature, typename Function>
	void register_nonmenber_impl(std::string const & name, Function f)
	{
		// instantiate and store the invoker by name
		this->map_invokers[name] = std::bind(
			&invoker<Function, Signature>::template apply<std::tuple<>>,
			f,
			std::placeholders::_1,
			std::tuple<>()
			);
	}

private:
	template<typename Function, class Signature = Function, size_t N = 0, size_t M = function_traits<Signature>::arity>
	struct invoker;

	template<typename Function, class Signature, size_t N, size_t M>
	struct invoker
	{
		// add an argument to a Fusion cons-list for each parameter type
		template<typename Args>
		static inline void apply(Function func, token_parser & parser, Args const & args)
		{
			typedef typename function_traits<Signature>::template args<N>::type arg_type;
			HttpRouter::invoker<Function, Signature, N + 1, M>::apply
				(func, parser, std::tuple_cat(args, std::make_tuple(parser.get<arg_type>())));
		}
	};

	template<typename Function, class Signature, size_t M>
	struct invoker<Function, Signature, M, M>
	{
		// the argument list is complete, now call the function
		template<typename Args>
		static inline void apply(Function func, token_parser &, Args const & args)
		{
			call(func, args);
		}
	};

	template<int...>
	struct IndexTuple{};

	template<int N, int... Indexes>
	struct MakeIndexes : MakeIndexes<N - 1, N - 1, Indexes...>{};

	template<int... indexes>
	struct MakeIndexes<0, indexes...>
	{
		typedef IndexTuple<indexes...> type;
	};

	template<typename F, int ... Indexes, typename ... Args>
	static void call_helper(F f, IndexTuple<Indexes...>, std::tuple<Args...> tup)
	{
		f(std::get<Indexes>(tup)...);
	}

	template<typename F, typename ... Args>
	static void call(F f, std::tuple<Args...> tp)
	{
		call_helper(f, typename MakeIndexes<sizeof... (Args)>::type(), tp);
	}

};
<|endoftext|>


<commit_before>#include "stdafx.h"

#include <string>
#include <map>
#include <vector>
#include "../Application.h"
#include "../ModuleScripting.h"
#include "../ModuleInput.h"
#include "../ModuleWindow.h"
#include "../GameObject.h"
#include "../ComponentScript.h"
#include "../ComponentTransform.h"
#include "../SDL/include/SDL_scancode.h"
#include "../PhysBody3D.h"
#include "../ComponentCollider.h"
#include "../ModuleGOManager.h"
#include "../Globals.h"

namespace Player_Camera
{
	float Player_Camera_distrance_y = 0.0;
	float Player_Camera_distrance_z = 0.0;
	GameObject* Player_Camera_target = nullptr;

	void Player_Camera_GetPublics(map<const char*, string>* public_chars, map<const char*, int>* public_ints, map<const char*, float>* public_float, map<const char*, bool>* public_bools, map<const char*, GameObject*>* public_gos)
	{
		public_float->insert(pair<const char*, float>("dist_y", Player_Camera_distrance_y));
		public_float->insert(pair<const char*, float>("dist_z", Player_Camera_distrance_z));
		public_gos->insert(pair<const char*, GameObject*>("target", nullptr));
	}

	void Player_Camera_UpdatePublics(GameObject* game_object)
	{
		ComponentScript* Player_Camera_script = (ComponentScript*)game_object->GetComponent(ComponentType::C_SCRIPT);

		Player_Camera_distrance_y = Player_Camera_script->public_floats.at("dist_y");
		Player_Camera_distrance_z = Player_Camera_script->public_floats.at("dist_z");
		Player_Camera_target = Player_Camera_script->public_gos.at("target");
	}

	void Player_Camera_Start(GameObject* game_object)
	{
	}

	void Player_Camera_Update(GameObject* game_object)
	{
		Quat Player_Camera_rot = game_object->transform->GetRotation();
		float3 Player_Camera_euler_rot = game_object->transform->GetRotationEuler();
		game_object->transform->SetRotation(float3(0.0, Player_Camera_euler_rot.y, 0.0));

		if (Player_Camera_target != nullptr)
		{
			game_object->transform->SetRotation(float3(0.0, Player_Camera_target->transform->GetRotationEuler().y, 0.0));

			float3 Player_Camera_target_pos = float3::zero;
			Player_Camera_target_pos += (float3(game_object->transform->GetForward().Normalized().x, 0.0, game_object->transform->GetForward().Normalized().z) * Player_Camera_distrance_z);
			Player_Camera_target_pos += (float3(0.0, Player_Camera_distrance_y, 0.0));

			Player_Camera_target_pos += Player_Camera_target->transform->GetPosition();

			game_object->transform->SetPosition(Player_Camera_target_pos);
		}
	}
}<commit_msg>Change camera y and z with car x rotation<commit_after>#include "stdafx.h"

#include <string>
#include <map>
#include <vector>
#include "../Application.h"
#include "../ModuleScripting.h"
#include "../ModuleInput.h"
#include "../ModuleWindow.h"
#include "../GameObject.h"
#include "../ComponentScript.h"
#include "../ComponentTransform.h"
#include "../SDL/include/SDL_scancode.h"
#include "../PhysBody3D.h"
#include "../ComponentCollider.h"
#include "../ModuleGOManager.h"
#include "../ComponentCamera.h"
#include "../Globals.h"

namespace Player_Camera
{
	float Player_Camera_distrance_y = 0.0;
	float Player_Camera_distrance_z = 0.0;
	GameObject* Player_Camera_target = nullptr;
	float Player_Camera_inclination_separation_y = 0.0;
	float Player_Camera_inclination_separation_z = 0.0;

	void Player_Camera_GetPublics(map<const char*, string>* public_chars, map<const char*, int>* public_ints, map<const char*, float>* public_float, map<const char*, bool>* public_bools, map<const char*, GameObject*>* public_gos)
	{
		public_float->insert(pair<const char*, float>("dist_y", Player_Camera_distrance_y));
		public_float->insert(pair<const char*, float>("dist_z", Player_Camera_distrance_z));
		public_gos->insert(pair<const char*, GameObject*>("target", nullptr));
		public_float->insert(pair<const char*, float>("inclination separation max and min y", Player_Camera_inclination_separation_y));
		public_float->insert(pair<const char*, float>("inclination separation max and min z", Player_Camera_inclination_separation_z));
	}

	void Player_Camera_UpdatePublics(GameObject* game_object)
	{
		ComponentScript* Player_Camera_script = (ComponentScript*)game_object->GetComponent(ComponentType::C_SCRIPT);

		Player_Camera_distrance_y = Player_Camera_script->public_floats.at("dist_y");
		Player_Camera_distrance_z = Player_Camera_script->public_floats.at("dist_z");
		Player_Camera_target = Player_Camera_script->public_gos.at("target");
		Player_Camera_inclination_separation_y = Player_Camera_script->public_floats.at("inclination separation max and min y");
		Player_Camera_inclination_separation_z = Player_Camera_script->public_floats.at("inclination separation max and min z");
	}

	void Player_Camera_Start(GameObject* game_object)
	{
	}

	void Player_Camera_Update(GameObject* game_object)
	{
		Quat Player_Camera_rot = game_object->transform->GetRotation();
		float3 Player_Camera_euler_rot = game_object->transform->GetRotationEuler();
		game_object->transform->SetRotation(float3(0.0, Player_Camera_euler_rot.y, 0.0));

		if (Player_Camera_target != nullptr)
		{
			game_object->transform->SetRotation(float3(0.0, Player_Camera_target->transform->GetRotationEuler().y, 0.0));

			float rotation_x = Player_Camera_target->transform->GetRotationEuler().x;
			if (rotation_x > 90)
				rotation_x = 90;
			else if (rotation_x < -90)
				rotation_x = -90;

			float3 Player_Camera_target_pos = float3::zero;
			Player_Camera_target_pos += (float3(game_object->transform->GetForward().Normalized().x, 0.0, game_object->transform->GetForward().Normalized().z) * (Player_Camera_distrance_z + rotation_x / 90 * Player_Camera_inclination_separation_z));
			Player_Camera_target_pos += (float3(0.0, Player_Camera_distrance_y + rotation_x / 90 * Player_Camera_inclination_separation_y, 0.0));

			Player_Camera_target_pos += Player_Camera_target->transform->GetPosition();

			game_object->transform->SetPosition(Player_Camera_target_pos);

			ComponentCamera* Player_Camera_cam = (ComponentCamera*)game_object->GetComponent(ComponentType::C_CAMERA);
			if (Player_Camera_cam != nullptr)
			{
				Player_Camera_cam->LookAt(Player_Camera_target->transform->GetPosition());
			}
		}
	}
}<|endoftext|>


<commit_before>#ifndef GHULBUS_LIBRARY_INCLUDE_GUARD_VULKAN_PHYSICAL_DEVICE_HPP
#define GHULBUS_LIBRARY_INCLUDE_GUARD_VULKAN_PHYSICAL_DEVICE_HPP

/** @file
*
* @brief Physical device.
* @author Andreas Weis (der_ghulbus@ghulbus-inc.de)
*/

#include <gbVk/config.hpp>

#include <vulkan/vulkan.h>
#include <vulkan/vulkan.hpp>

#include <optional>
#include <vector>

namespace GHULBUS_VULKAN_NAMESPACE
{
class Device;
class DeviceBuilder;

struct NoSwapchainSupport_T {};
inline constexpr NoSwapchainSupport_T no_swapchain_support {};

class PhysicalDevice {
private:
    VkPhysicalDevice m_physicalDevice;
public:
    explicit PhysicalDevice(VkPhysicalDevice physical_device);

    VkPhysicalDevice getVkPhysicalDevice();

    VkPhysicalDeviceProperties getProperties();

    VkPhysicalDeviceFeatures getFeatures();

    VkPhysicalDeviceMemoryProperties getMemoryProperties();

    std::vector<VkQueueFamilyProperties> getQueueFamilyProperties();

    VkFormatProperties getFormatProperties(VkFormat format);

    std::optional<VkFormat> findSupportedFormat(std::vector<VkFormat> const& candidates,
                                                VkImageTiling tiling, VkFormatFeatureFlags features);

    std::optional<VkFormat> findDepthBufferFormat();

    VkImageFormatProperties getImageFormatProperties(VkFormat format, VkImageType type,
                                                     VkImageTiling tiling, VkImageUsageFlags usage,
                                                     VkImageCreateFlags create_flags);

    std::optional<uint32_t> findMemoryTypeIndex(VkMemoryPropertyFlags requested_properties);

    std::optional<uint32_t> findMemoryTypeIndex(VkMemoryPropertyFlags requested_properties,
                                                VkMemoryRequirements const& requirements);

    bool getSurfaceSupport(uint32_t queue_family, VkSurfaceKHR surface);

    std::vector<VkLayerProperties> [[deprecated]] enumerateDeviceLayerProperties();

    std::vector<VkExtensionProperties> enumerateDeviceExtensionProperties();

    std::vector<VkExtensionProperties> enumerateDeviceExtensionProperties(VkLayerProperties layer);

    DeviceBuilder createDeviceBuilder(NoSwapchainSupport_T const&);

    DeviceBuilder createDeviceBuilder();

    Device createDevice();
};
}
#endif
<commit_msg>fixed misplaced deprecated attribute<commit_after>#ifndef GHULBUS_LIBRARY_INCLUDE_GUARD_VULKAN_PHYSICAL_DEVICE_HPP
#define GHULBUS_LIBRARY_INCLUDE_GUARD_VULKAN_PHYSICAL_DEVICE_HPP

/** @file
*
* @brief Physical device.
* @author Andreas Weis (der_ghulbus@ghulbus-inc.de)
*/

#include <gbVk/config.hpp>

#include <vulkan/vulkan.h>
#include <vulkan/vulkan.hpp>

#include <optional>
#include <vector>

namespace GHULBUS_VULKAN_NAMESPACE
{
class Device;
class DeviceBuilder;

struct NoSwapchainSupport_T {};
inline constexpr NoSwapchainSupport_T no_swapchain_support {};

class PhysicalDevice {
private:
    VkPhysicalDevice m_physicalDevice;
public:
    explicit PhysicalDevice(VkPhysicalDevice physical_device);

    VkPhysicalDevice getVkPhysicalDevice();

    VkPhysicalDeviceProperties getProperties();

    VkPhysicalDeviceFeatures getFeatures();

    VkPhysicalDeviceMemoryProperties getMemoryProperties();

    std::vector<VkQueueFamilyProperties> getQueueFamilyProperties();

    VkFormatProperties getFormatProperties(VkFormat format);

    std::optional<VkFormat> findSupportedFormat(std::vector<VkFormat> const& candidates,
                                                VkImageTiling tiling, VkFormatFeatureFlags features);

    std::optional<VkFormat> findDepthBufferFormat();

    VkImageFormatProperties getImageFormatProperties(VkFormat format, VkImageType type,
                                                     VkImageTiling tiling, VkImageUsageFlags usage,
                                                     VkImageCreateFlags create_flags);

    std::optional<uint32_t> findMemoryTypeIndex(VkMemoryPropertyFlags requested_properties);

    std::optional<uint32_t> findMemoryTypeIndex(VkMemoryPropertyFlags requested_properties,
                                                VkMemoryRequirements const& requirements);

    bool getSurfaceSupport(uint32_t queue_family, VkSurfaceKHR surface);

    [[deprecated]] std::vector<VkLayerProperties> enumerateDeviceLayerProperties();

    std::vector<VkExtensionProperties> enumerateDeviceExtensionProperties();

    std::vector<VkExtensionProperties> enumerateDeviceExtensionProperties(VkLayerProperties layer);

    DeviceBuilder createDeviceBuilder(NoSwapchainSupport_T const&);

    DeviceBuilder createDeviceBuilder();

    Device createDevice();
};
}
#endif
<|endoftext|>


<commit_before>#ifndef GRL_KUKA_DRIVER
#define GRL_KUKA_DRIVER

#include <tuple>
#include <memory>
#include <thread>
#include <boost/asio.hpp>
#include <boost/circular_buffer.hpp>
#include <boost/exception/all.hpp>
#include <boost/config.hpp>

#include <boost/make_shared.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <boost/range/algorithm/transform.hpp>

#include <boost/make_shared.hpp>

#ifdef BOOST_NO_CXX11_ATOMIC_SMART_PTR
#include <boost/thread.hpp>
#endif

#include "Kuka.hpp"
#include "grl/kuka/KukaJAVAdriver.hpp"
#include "grl/kuka/KukaFRIdriver.hpp"
#include "grl/tags.hpp"

namespace grl { namespace robot { namespace arm {

    ///
    ///
    /// @brief Kuka LBR iiwa Primary Multi Mode Driver, supports communication over FRI and JAVA interfaces
    ///
    /// @todo enable commanding and monitoring to be independently configured for both FRI and JAVA interface.
    ///
    class KukaDriver : public std::enable_shared_from_this<KukaDriver> {
    public:

      enum ParamIndex {
        RobotName,
        LocalZMQAddress,
        RemoteZMQAddress,
        LocalHostKukaKoniUDPAddress,
        LocalHostKukaKoniUDPPort,
        RemoteHostKukaKoniUDPAddress,
        RemoteHostKukaKoniUDPPort,
        KukaCommandMode,
        KukaMonitorMode
      };

      /// @todo allow default params
      typedef std::tuple<
        std::string,
        std::string,
        std::string,
        std::string,
        std::string,
        std::string,
        std::string,
        std::string,
        std::string
          > Params;

      static const Params defaultParams(){
        return std::make_tuple(
            "Robotiiwa"               , // RobotName,
            "tcp://0.0.0.0:30010"     , // LocalZMQAddress
            "tcp://172.31.1.147:30010", // RemoteZMQAddress
            "192.170.10.100"          , // LocalHostKukaKoniUDPAddress,
            "30200"                   , // LocalHostKukaKoniUDPPort,
            "192.170.10.2"            , // RemoteHostKukaKoniUDPAddress,
            "30200"                   , // RemoteHostKukaKoniUDPPort
            "JAVA"                    , // KukaCommandMode (options are FRI, JAVA)
            "JAVA"                      // KukaMonitorMode (options are FRI, JAVA)
            );
      }

      KukaDriver(Params params = defaultParams())
        : params_(params)
      {}

      void construct(){ construct(params_);}

      bool destruct(){ return JAVAdriverP_->destruct(); }

      /// @todo create a function that calls simGetObjectHandle and throws an exception when it fails
      /// @warning getting the ik group is optional, so it does not throw an exception
      void construct(Params params) {

        params_ = params;
        // keep driver threads from exiting immediately after creation, because they have work to do!
        //device_driver_workP_.reset(new boost::asio::io_service::work(device_driver_io_service));

        /// @todo figure out how to re-enable when .so isn't loaded
        if(    boost::iequals(std::get<KukaCommandMode>(params_),std::string("FRI"))
            || boost::iequals(std::get<KukaMonitorMode>(params_),std::string("FRI")))
        {
          FRIdriverP_.reset(
              new grl::robot::arm::KukaFRIdriver(
                  //device_driver_io_service,
                  std::make_tuple(
                      std::string(std::get<LocalHostKukaKoniUDPAddress >        (params)),
                      std::string(std::get<LocalHostKukaKoniUDPPort    >        (params)),
                      std::string(std::get<RemoteHostKukaKoniUDPAddress>        (params)),
                      std::string(std::get<RemoteHostKukaKoniUDPPort   >        (params)),
                      ms_per_tick ,
                      grl::robot::arm::KukaFRIClientDataDriver::run_automatically
                      )
                  )

              );
              FRIdriverP_->construct();
        }

        /// @todo implement reading configuration in both FRI and JAVA mode from JAVA interface
        if(    boost::iequals(std::get<KukaCommandMode>(params_),std::string("JAVA"))){
        try {
          JAVAdriverP_ = boost::make_shared<KukaJAVAdriver>(params_);
          JAVAdriverP_->construct();

          // start up the driver thread
          /// @todo perhaps allow user to control this?
          //driver_threadP.reset(new std::thread([&]{ device_driver_io_service.run(); }));
        } catch( boost::exception &e) {
          e << errmsg_info("KukaDriver: Unable to connect to ZeroMQ Socket from " +
                           std::get<LocalZMQAddress>             (params_) + " to " +
                           std::get<RemoteZMQAddress>            (params_));
          throw;
        }

        }
      }

      const Params & getParams(){
        return params_;
      }

      ~KukaDriver(){
        device_driver_workP_.reset();

        if(driver_threadP){
          device_driver_io_service.stop();
          driver_threadP->join();
        }
      }

     /**
      * spin once
      *
      */
      bool run_one(){

        // @todo CHECK FOR REAL DATA BEFORE SENDING COMMANDS
        //if(!m_haveReceivedRealDataCount) return;
        bool haveNewData = false;

        /// @todo make this handled by template driver implementations/extensions

        if(JAVAdriverP_.get() != nullptr)
        {
          std::cout << "commandedpos:" << armState_.commandedPosition;
          /////////////////////////////////////////
          // Client sends to server asynchronously!
          if( boost::iequals(std::get<KukaCommandMode>(params_),std::string("JAVA")))
          {
            JAVAdriverP_->set(armState_.commandedPosition,revolute_joint_angle_open_chain_command_tag());
          }
          std::cout << "commandedpos:" << armState_.commandedPosition;

          haveNewData = JAVAdriverP_->run_one();

          if( boost::iequals(std::get<KukaMonitorMode>(params_),std::string("JAVA")))
          {
            JAVAdriverP_->get(armState_);
          }
          std::cout << "commandedpos:" << armState_.commandedPosition;
        }

        if(FRIdriverP_.get() != nullptr)
        {
          if( boost::iequals(std::get<KukaCommandMode>(params_),std::string("FRI")))
          {
            FRIdriverP_->set(armState_.commandedPosition,revolute_joint_angle_open_chain_command_tag());
          }

          haveNewData = FRIdriverP_->run_one();

          if( boost::iequals(std::get<KukaMonitorMode>(params_),std::string("FRI")))
          {
            FRIdriverP_->get(armState_);
          }
        }

        return haveNewData;
      }

   /// set the mode of the arm. Examples: Teach or MoveArmJointServo
   /// @see grl::flatbuffer::ArmState in ArmControlState_generated.h
   void set(const flatbuffer::ArmState & armControlMode)
   {
        if(JAVAdriverP_)
        {
            JAVAdriverP_->set(armControlMode);
        }
   }

     /**
      * \brief Set the joint positions for the current interpolation step.
      *
      * This method is only effective when the client is in a commanding state.
      * @param state Object which stores the current state of the robot, including the command to send next
      * @param range Array with the new joint positions (in radians)
      * @param tag identifier object indicating that revolute joint angle commands should be modified
      */
   template<typename Range>
   void set(Range&& range, grl::revolute_joint_angle_open_chain_command_tag) {
       boost::unique_lock<boost::mutex> lock(jt_mutex);
       armState_.clearCommands();
       boost::copy(range, std::back_inserter(armState_.commandedPosition));
       boost::copy(range, std::back_inserter(armState_.commandedPosition_goal));

          std::cout << "set commandedpos:" << armState_.commandedPosition;
    }

     /**
      * \brief Set the applied joint torques for the current interpolation step.
      *
      * This method is only effective when the client is in a commanding state.
      * The ControlMode of the robot has to be joint impedance control mode. The
      * Client Command Mode has to be torque.
      *
      * @param state Object which stores the current state of the robot, including the command to send next
      * @param torques Array with the applied torque values (in Nm)
      * @param tag identifier object indicating that the torqe value command should be modified
      */
   template<typename Range>
   void set(Range&& range, grl::revolute_joint_torque_open_chain_command_tag) {
       boost::unique_lock<boost::mutex> lock(jt_mutex);
       armState_.clearCommands();
       boost::copy(range, std::back_inserter(armState_.commandedTorque));
    }

     /**
      * \brief Set the applied wrench vector of the current interpolation step.
      *
      * The wrench vector consists of:
      * [F_x, F_y, F_z, tau_A, tau_B, tau_C]
      *
      * F ... forces (in N) applied along the Cartesian axes of the
      * currently used motion center.
      * tau ... torques (in Nm) applied along the orientation angles
      * (Euler angles A, B, C) of the currently used motion center.
      *
      * This method is only effective when the client is in a commanding state.
      * The ControlMode of the robot has to be Cartesian impedance control mode. The
      * Client Command Mode has to be wrench.
      *
      * @param state object storing the command data that will be sent to the physical device
      * @param range wrench Applied Cartesian wrench vector, in x, y, z, roll, pitch, yaw force measurments.
      * @param tag identifier object indicating that the wrench value command should be modified
      *
      * @todo perhaps support some specific more useful data layouts
      */
   template<typename Range>
   void set(Range&& range, grl::cartesian_wrench_command_tag) {
       boost::unique_lock<boost::mutex> lock(jt_mutex);
       armState_.clearCommands();
       std::copy(range,armState_.commandedCartesianWrenchFeedForward);
    }

    /// @todo implement get function
    template<typename OutputIterator>
    void get(OutputIterator output, grl::revolute_joint_angle_open_chain_state_tag)
    {
       boost::unique_lock<boost::mutex> lock(jt_mutex);
        boost::copy(armState_.position,output);
    }

    /// @todo implement get function
    template<typename OutputIterator>
    void get(OutputIterator output, grl::revolute_joint_torque_open_chain_state_tag)
    {
       boost::unique_lock<boost::mutex> lock(jt_mutex);
       boost::copy(armState.torque,output);

    }

    template<typename OutputIterator>
    void get(OutputIterator output, grl::revolute_joint_torque_external_open_chain_state_tag)
    {
        boost::unique_lock<boost::mutex> lock(jt_mutex);
        boost::copy(armState.externalTorque,output);

    }

    template<typename OutputIterator>
    void get(OutputIterator output, grl::cartesian_external_force_tag)
    {
        boost::unique_lock<boost::mutex> lock(jt_mutex);
        boost::copy(armState.externalForce,output);

    }

      volatile std::size_t m_haveReceivedRealDataCount = 0;
      volatile std::size_t m_attemptedCommunicationCount = 0;
      volatile std::size_t m_attemptedCommunicationConsecutiveFailureCount = 0;
      volatile std::size_t m_attemptedCommunicationConsecutiveSuccessCount = 0;

      boost::asio::io_service device_driver_io_service;
      std::unique_ptr<boost::asio::io_service::work> device_driver_workP_;
      std::unique_ptr<std::thread> driver_threadP;

    private:

      /// @todo read ms_per_tick from JAVA interface
      std::size_t ms_per_tick = 1;
      KukaState armState_;

      boost::mutex jt_mutex;
      boost::shared_ptr<KukaFRIdriver> FRIdriverP_;
      boost::shared_ptr<KukaJAVAdriver> JAVAdriverP_;

      Params params_;

    };

}}}// namespace grl::robot::arm

#endif
<commit_msg>fix minor KukaDriver compiler errors from merge<commit_after>#ifndef GRL_KUKA_DRIVER
#define GRL_KUKA_DRIVER

#include <tuple>
#include <memory>
#include <thread>
#include <boost/asio.hpp>
#include <boost/circular_buffer.hpp>
#include <boost/exception/all.hpp>
#include <boost/config.hpp>

#include <boost/make_shared.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <boost/range/algorithm/transform.hpp>

#include <boost/make_shared.hpp>

#ifdef BOOST_NO_CXX11_ATOMIC_SMART_PTR
#include <boost/thread.hpp>
#endif

#include "Kuka.hpp"
#include "grl/kuka/KukaJAVAdriver.hpp"
#include "grl/kuka/KukaFRIdriver.hpp"
#include "grl/tags.hpp"

namespace grl { namespace robot { namespace arm {

    ///
    ///
    /// @brief Kuka LBR iiwa Primary Multi Mode Driver, supports communication over FRI and JAVA interfaces
    ///
    /// @todo enable commanding and monitoring to be independently configured for both FRI and JAVA interface.
    ///
    class KukaDriver : public std::enable_shared_from_this<KukaDriver> {
    public:

      enum ParamIndex {
        RobotName,
        LocalZMQAddress,
        RemoteZMQAddress,
        LocalHostKukaKoniUDPAddress,
        LocalHostKukaKoniUDPPort,
        RemoteHostKukaKoniUDPAddress,
        RemoteHostKukaKoniUDPPort,
        KukaCommandMode,
        KukaMonitorMode
      };

      /// @todo allow default params
      typedef std::tuple<
        std::string,
        std::string,
        std::string,
        std::string,
        std::string,
        std::string,
        std::string,
        std::string,
        std::string
          > Params;

      static const Params defaultParams(){
        return std::make_tuple(
            "Robotiiwa"               , // RobotName,
            "tcp://0.0.0.0:30010"     , // LocalZMQAddress
            "tcp://172.31.1.147:30010", // RemoteZMQAddress
            "192.170.10.100"          , // LocalHostKukaKoniUDPAddress,
            "30200"                   , // LocalHostKukaKoniUDPPort,
            "192.170.10.2"            , // RemoteHostKukaKoniUDPAddress,
            "30200"                   , // RemoteHostKukaKoniUDPPort
            "JAVA"                    , // KukaCommandMode (options are FRI, JAVA)
            "JAVA"                      // KukaMonitorMode (options are FRI, JAVA)
            );
      }

      KukaDriver(Params params = defaultParams())
        : params_(params)
      {}

      void construct(){ construct(params_);}

      bool destruct(){ return JAVAdriverP_->destruct(); }

      /// @todo create a function that calls simGetObjectHandle and throws an exception when it fails
      /// @warning getting the ik group is optional, so it does not throw an exception
      void construct(Params params) {

        params_ = params;
        // keep driver threads from exiting immediately after creation, because they have work to do!
        //device_driver_workP_.reset(new boost::asio::io_service::work(device_driver_io_service));

        /// @todo figure out how to re-enable when .so isn't loaded
        if(    boost::iequals(std::get<KukaCommandMode>(params_),std::string("FRI"))
            || boost::iequals(std::get<KukaMonitorMode>(params_),std::string("FRI")))
        {
          FRIdriverP_.reset(
              new grl::robot::arm::KukaFRIdriver(
                  //device_driver_io_service,
                  std::make_tuple(
                      std::string(std::get<LocalHostKukaKoniUDPAddress >        (params)),
                      std::string(std::get<LocalHostKukaKoniUDPPort    >        (params)),
                      std::string(std::get<RemoteHostKukaKoniUDPAddress>        (params)),
                      std::string(std::get<RemoteHostKukaKoniUDPPort   >        (params)),
                      ms_per_tick ,
                      grl::robot::arm::KukaFRIClientDataDriver::run_automatically
                      )
                  )

              );
              FRIdriverP_->construct();
        }

        /// @todo implement reading configuration in both FRI and JAVA mode from JAVA interface
        if(    boost::iequals(std::get<KukaCommandMode>(params_),std::string("JAVA"))){
        try {
          JAVAdriverP_ = boost::make_shared<KukaJAVAdriver>(params_);
          JAVAdriverP_->construct();

          // start up the driver thread
          /// @todo perhaps allow user to control this?
          //driver_threadP.reset(new std::thread([&]{ device_driver_io_service.run(); }));
        } catch( boost::exception &e) {
          e << errmsg_info("KukaDriver: Unable to connect to ZeroMQ Socket from " +
                           std::get<LocalZMQAddress>             (params_) + " to " +
                           std::get<RemoteZMQAddress>            (params_));
          throw;
        }

        }
      }

      const Params & getParams(){
        return params_;
      }

      ~KukaDriver(){
        device_driver_workP_.reset();

        if(driver_threadP){
          device_driver_io_service.stop();
          driver_threadP->join();
        }
      }

     /**
      * spin once
      *
      */
      bool run_one(){

        // @todo CHECK FOR REAL DATA BEFORE SENDING COMMANDS
        //if(!m_haveReceivedRealDataCount) return;
        bool haveNewData = false;

        /// @todo make this handled by template driver implementations/extensions

        if(JAVAdriverP_.get() != nullptr)
        {
          std::cout << "commandedpos:" << armState_.commandedPosition;
          /////////////////////////////////////////
          // Client sends to server asynchronously!
          if( boost::iequals(std::get<KukaCommandMode>(params_),std::string("JAVA")))
          {
            JAVAdriverP_->set(armState_.commandedPosition,revolute_joint_angle_open_chain_command_tag());
          }
          std::cout << "commandedpos:" << armState_.commandedPosition;

          haveNewData = JAVAdriverP_->run_one();

          if( boost::iequals(std::get<KukaMonitorMode>(params_),std::string("JAVA")))
          {
            JAVAdriverP_->get(armState_);
          }
          std::cout << "commandedpos:" << armState_.commandedPosition;
        }

        if(FRIdriverP_.get() != nullptr)
        {
          if( boost::iequals(std::get<KukaCommandMode>(params_),std::string("FRI")))
          {
            FRIdriverP_->set(armState_.commandedPosition,revolute_joint_angle_open_chain_command_tag());
          }

          haveNewData = FRIdriverP_->run_one();

          if( boost::iequals(std::get<KukaMonitorMode>(params_),std::string("FRI")))
          {
            FRIdriverP_->get(armState_);
          }
        }

        return haveNewData;
      }

   /// set the mode of the arm. Examples: Teach or MoveArmJointServo
   /// @see grl::flatbuffer::ArmState in ArmControlState_generated.h
   void set(const flatbuffer::ArmState & armControlMode)
   {
        if(JAVAdriverP_)
        {
            JAVAdriverP_->set(armControlMode);
        }
   }

     /**
      * \brief Set the joint positions for the current interpolation step.
      *
      * This method is only effective when the client is in a commanding state.
      * @param state Object which stores the current state of the robot, including the command to send next
      * @param range Array with the new joint positions (in radians)
      * @param tag identifier object indicating that revolute joint angle commands should be modified
      */
   template<typename Range>
   void set(Range&& range, grl::revolute_joint_angle_open_chain_command_tag) {
       boost::unique_lock<boost::mutex> lock(jt_mutex);
       armState_.clearCommands();
       boost::copy(range, std::back_inserter(armState_.commandedPosition));
       boost::copy(range, std::back_inserter(armState_.commandedPosition_goal));

          std::cout << "set commandedpos:" << armState_.commandedPosition;
    }

     /**
      * \brief Set the applied joint torques for the current interpolation step.
      *
      * This method is only effective when the client is in a commanding state.
      * The ControlMode of the robot has to be joint impedance control mode. The
      * Client Command Mode has to be torque.
      *
      * @param state Object which stores the current state of the robot, including the command to send next
      * @param torques Array with the applied torque values (in Nm)
      * @param tag identifier object indicating that the torqe value command should be modified
      */
   template<typename Range>
   void set(Range&& range, grl::revolute_joint_torque_open_chain_command_tag) {
       boost::unique_lock<boost::mutex> lock(jt_mutex);
       armState_.clearCommands();
       boost::copy(range, std::back_inserter(armState_.commandedTorque));
    }

     /**
      * \brief Set the applied wrench vector of the current interpolation step.
      *
      * The wrench vector consists of:
      * [F_x, F_y, F_z, tau_A, tau_B, tau_C]
      *
      * F ... forces (in N) applied along the Cartesian axes of the
      * currently used motion center.
      * tau ... torques (in Nm) applied along the orientation angles
      * (Euler angles A, B, C) of the currently used motion center.
      *
      * This method is only effective when the client is in a commanding state.
      * The ControlMode of the robot has to be Cartesian impedance control mode. The
      * Client Command Mode has to be wrench.
      *
      * @param state object storing the command data that will be sent to the physical device
      * @param range wrench Applied Cartesian wrench vector, in x, y, z, roll, pitch, yaw force measurments.
      * @param tag identifier object indicating that the wrench value command should be modified
      *
      * @todo perhaps support some specific more useful data layouts
      */
   template<typename Range>
   void set(Range&& range, grl::cartesian_wrench_command_tag) {
       boost::unique_lock<boost::mutex> lock(jt_mutex);
       armState_.clearCommands();
       std::copy(range,armState_.commandedCartesianWrenchFeedForward);
    }

    /// @todo implement get function
    template<typename OutputIterator>
    void get(OutputIterator output, grl::revolute_joint_angle_open_chain_state_tag)
    {
       boost::unique_lock<boost::mutex> lock(jt_mutex);
        boost::copy(armState_.position,output);
    }

    /// @todo implement get function
    template<typename OutputIterator>
    void get(OutputIterator output, grl::revolute_joint_torque_open_chain_state_tag)
    {
       boost::unique_lock<boost::mutex> lock(jt_mutex);
       boost::copy(armState_.torque,output);

    }

    template<typename OutputIterator>
    void get(OutputIterator output, grl::revolute_joint_torque_external_open_chain_state_tag)
    {
        boost::unique_lock<boost::mutex> lock(jt_mutex);
        boost::copy(armState_.externalTorque,output);

    }

    template<typename OutputIterator>
    void get(OutputIterator output, grl::cartesian_external_force_tag)
    {
        boost::unique_lock<boost::mutex> lock(jt_mutex);
        boost::copy(armState_.externalForce,output);

    }

      volatile std::size_t m_haveReceivedRealDataCount = 0;
      volatile std::size_t m_attemptedCommunicationCount = 0;
      volatile std::size_t m_attemptedCommunicationConsecutiveFailureCount = 0;
      volatile std::size_t m_attemptedCommunicationConsecutiveSuccessCount = 0;

      boost::asio::io_service device_driver_io_service;
      std::unique_ptr<boost::asio::io_service::work> device_driver_workP_;
      std::unique_ptr<std::thread> driver_threadP;

    private:

      /// @todo read ms_per_tick from JAVA interface
      std::size_t ms_per_tick = 1;
      KukaState armState_;

      boost::mutex jt_mutex;
      boost::shared_ptr<KukaFRIdriver> FRIdriverP_;
      boost::shared_ptr<KukaJAVAdriver> JAVAdriverP_;

      Params params_;

    };

}}}// namespace grl::robot::arm

#endif
<|endoftext|>