<commit_before>#ifndef TOML_UTF_CODEPOINT
#define TOML_UTF_CODEPOINT
#include <string>

namespace toml
{

template<typename charT, typename traits, typename alloc>
std::basic_string<charT, traits, alloc>
utf8_to_char(const std::basic_string<charT, traits, alloc>& str)
{
    uint32_t codepoint;
    std::basic_istringstream<charT, traits, alloc> iss(str);
    iss >> std::hex >> codepoint;

    std::basic_string<charT, traits, alloc> charactor;
    if(codepoint < 0x80)
    {
        charactor += static_cast<unsigned char>(codepoint);
    }
    else if(codepoint < 0x800)
    {
        charactor += (static_cast<unsigned char>(0xC0 | codepoint >> 6));
        charactor += (static_cast<unsigned char>(0x80 | codepoint & 0x3F));
    }
    else if(codepoint < 0x10000)
    {
        charactor += (static_cast<unsigned char>(0xE0 | codepoint >> 12));
        charactor += (static_cast<unsigned char>(0x80 | codepoint >> 6 & 0x3F));
        charactor += (static_cast<unsigned char>(0x80 | codepoint & 0x3F));
    }
    else
    {
        charactor += (static_cast<unsigned char>(0xF0 | codepoint >> 18));
        charactor += (static_cast<unsigned char>(0x80 | codepoint >> 12& 0x3F));
        charactor += (static_cast<unsigned char>(0x80 | codepoint >> 6 & 0x3F));
        charactor += (static_cast<unsigned char>(0x80 | codepoint & 0x3F));
    }
    return charactor;
}

/* @brief unescape basic_string.          *
 * @param str inside of quatation marks   *
 * @return unescaped string.              */
template<typename charT, typename traits, typename alloc>
std::basic_string<charT, traits, alloc>
unescape(const std::basic_string<charT, traits, alloc>& str)
{
    std::basic_string<charT, traits, alloc> retval;
    for(typename std::basic_string<charT, traits, alloc>::const_iterator
            iter = str.begin(); iter != str.end(); ++iter)
    {
        if(*iter != '\\')
        {
            retval += *iter;
        }
        else // *iter == '\'
        {
            ++iter;
                 if(*iter == 'b') retval += '\b';
            else if(*iter == 't') retval += '\t';
            else if(*iter == 'n') retval += '\n';
            else if(*iter == 'f') retval += '\f';
            else if(*iter == 'r') retval += '\r';
            else if(*iter == '\"') retval += '\"';
            else if(*iter == '\\') retval += '\\';
            else if(*iter == 'u')
            {
                std::string utf8code("0000");
                for(std::size_t i=0; i<4; ++i)
                {
                    ++iter;
                    utf8code += *iter;
                }
                retval += utf8_to_char(utf8code);
            }
            else if(*iter == 'U')
            {
                std::string utf8code;
                for(std::size_t i=0; i<8; ++i)
                {
                    ++iter;
                    utf8code += *iter;
                }
                retval += utf8_to_char(utf8code);
            }
        }
    }
    return retval;
}

}//toml

#endif /*TOML_UTF_CODEPOINT*/
<commit_msg>use cstdint and uint_least32_t in utfcodepoint<commit_after>#ifndef TOML_UTF_CODEPOINT
#define TOML_UTF_CODEPOINT
#include <string>
#include <cstdint>

namespace toml
{

template<typename charT, typename traits, typename alloc>
std::basic_string<charT, traits, alloc>
utf8_to_char(const std::basic_string<charT, traits, alloc>& str)
{
    std::uint_least32_t codepoint;
    std::basic_istringstream<charT, traits, alloc> iss(str);
    iss >> std::hex >> codepoint;

    std::basic_string<charT, traits, alloc> charactor;
    if(codepoint < 0x80)
    {
        charactor += static_cast<unsigned char>(codepoint);
    }
    else if(codepoint < 0x800)
    {
        charactor += (static_cast<unsigned char>(0xC0 | codepoint >> 6));
        charactor += (static_cast<unsigned char>(0x80 | codepoint & 0x3F));
    }
    else if(codepoint < 0x10000)
    {
        charactor += (static_cast<unsigned char>(0xE0 | codepoint >> 12));
        charactor += (static_cast<unsigned char>(0x80 | codepoint >> 6 & 0x3F));
        charactor += (static_cast<unsigned char>(0x80 | codepoint & 0x3F));
    }
    else
    {
        charactor += (static_cast<unsigned char>(0xF0 | codepoint >> 18));
        charactor += (static_cast<unsigned char>(0x80 | codepoint >> 12& 0x3F));
        charactor += (static_cast<unsigned char>(0x80 | codepoint >> 6 & 0x3F));
        charactor += (static_cast<unsigned char>(0x80 | codepoint & 0x3F));
    }
    return charactor;
}

/* @brief unescape basic_string.          *
 * @param str inside of quatation marks   *
 * @return unescaped string.              */
template<typename charT, typename traits, typename alloc>
std::basic_string<charT, traits, alloc>
unescape(const std::basic_string<charT, traits, alloc>& str)
{
    std::basic_string<charT, traits, alloc> retval;
    for(typename std::basic_string<charT, traits, alloc>::const_iterator
            iter = str.begin(); iter != str.end(); ++iter)
    {
        if(*iter != '\\')
        {
            retval += *iter;
        }
        else // *iter == '\'
        {
            ++iter;
                 if(*iter == 'b') retval += '\b';
            else if(*iter == 't') retval += '\t';
            else if(*iter == 'n') retval += '\n';
            else if(*iter == 'f') retval += '\f';
            else if(*iter == 'r') retval += '\r';
            else if(*iter == '\"') retval += '\"';
            else if(*iter == '\\') retval += '\\';
            else if(*iter == 'u')
            {
                std::string utf8code("0000");
                for(std::size_t i=0; i<4; ++i)
                {
                    ++iter;
                    utf8code += *iter;
                }
                retval += utf8_to_char(utf8code);
            }
            else if(*iter == 'U')
            {
                std::string utf8code;
                for(std::size_t i=0; i<8; ++i)
                {
                    ++iter;
                    utf8code += *iter;
                }
                retval += utf8_to_char(utf8code);
            }
        }
    }
    return retval;
}

}//toml

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


<commit_before>
#include "nethandlers.h"
#include "netmessages.h"
#include <cassert>
#include <cstdint>

#if !defined( MAX_OSPATH )
#define MAX_OSPATH      260         // max length of a filesystem pathname
#endif

#include "net_nop.h"
#include "net_disconnect.h"
#include "net_file.h"
#include "net_tick.h"
#include "net_stringcmd.h"
#include "net_setconvar.h"
#include "net_signonstate.h"
#include "svc_print.h"
#include "svc_serverinfo.h"
#include "svc_sendtable.h"
#include "svc_classinfo.h"
#include "svc_setpause.h"
#include "svc_createstringtable.h"
#include "svc_updatestringtable.h"
#include "svc_voiceinit.h"
#include "svc_voicedata.h"
#include "svc_hltv.h"
#include "svc_sounds.h"
#include "svc_setview.h"
#include "svc_fixangle.h"
#include "svc_crosshairangle.h"
#include "svc_bspdecal.h"
#include "svc_terrainmod.h"
#include "svc_usermessage.h"
#include "svc_entitymessage.h"
#include "svc_gameevent.h"
#include "svc_packetentities.h"
#include "svc_tempentities.h"
#include "svc_prefetch.h"
#include "svc_menu.h"
#include "svc_gameeventlist.h"
#include "svc_getcvarvalue.h"

void NetHandlers::CreateNetMsgStructs(NetDataStructArray& netDataStructs)
{
    netDataStructs[0] = new NetMsg::Net_NOP();
    netDataStructs[1] = new NetMsg::Net_Disconnect();
    netDataStructs[2] = new NetMsg::Net_File();
    netDataStructs[3] = new NetMsg::Net_Tick();
    netDataStructs[4] = new NetMsg::Net_StringCmd();
    netDataStructs[5] = new NetMsg::Net_SetConVar();
    netDataStructs[6] = new NetMsg::Net_SignonState();
    netDataStructs[7] = new NetMsg::SVC_Print();
    netDataStructs[8] = new NetMsg::SVC_ServerInfo();
    netDataStructs[9] = new NetMsg::SVC_SendTable();
    netDataStructs[10] = new NetMsg::SVC_ClassInfo();
    netDataStructs[11] = new NetMsg::SVC_SetPause();
    netDataStructs[12] = new NetMsg::SVC_CreateStringTable();
    netDataStructs[13] = new NetMsg::SVC_UpdateStringTable();
    netDataStructs[14] = new NetMsg::SVC_VoiceInit();
    netDataStructs[15] = new NetMsg::SVC_VoiceData();
    netDataStructs[16] = new NetMsg::SVC_HLTV();
    netDataStructs[17] = new NetMsg::SVC_Sounds();
    netDataStructs[18] = new NetMsg::SVC_SetView();
    netDataStructs[19] = new NetMsg::SVC_FixAngle();
    netDataStructs[20] = new NetMsg::SVC_CrosshairAngle();
    netDataStructs[21] = new NetMsg::SVC_BSPDecal();
    netDataStructs[22] = new NetMsg::SVC_TerrainMod();
    netDataStructs[23] = new NetMsg::SVC_UserMessage();
    netDataStructs[24] = new NetMsg::SVC_EntityMessage();
    netDataStructs[25] = new NetMsg::SVC_GameEvent();
    netDataStructs[26] = new NetMsg::SVC_PacketEntities();
    netDataStructs[27] = new NetMsg::SVC_TempEntities();
    netDataStructs[28] = new NetMsg::SVC_Prefetch();
    netDataStructs[29] = new NetMsg::SVC_Menu();
    netDataStructs[30] = new NetMsg::SVC_GameEventList();
    netDataStructs[31] = new NetMsg::SVC_GetCvarValue();
}

void NetHandlers::DestroyNetMsgStructs(NetDataStructArray& netDataStructs)
{
    delete reinterpret_cast<NetMsg::Net_NOP*>(netDataStructs[0]);
    delete reinterpret_cast<NetMsg::Net_Disconnect*>(netDataStructs[1]);
    delete reinterpret_cast<NetMsg::Net_File*>(netDataStructs[2]);
    delete reinterpret_cast<NetMsg::Net_Tick*>(netDataStructs[3]);
    delete reinterpret_cast<NetMsg::Net_StringCmd*>(netDataStructs[4]);
    delete reinterpret_cast<NetMsg::Net_SetConVar*>(netDataStructs[5]);
    delete reinterpret_cast<NetMsg::Net_SignonState*>(netDataStructs[6]);
    delete reinterpret_cast<NetMsg::SVC_Print*>(netDataStructs[7]);
    delete reinterpret_cast<NetMsg::SVC_ServerInfo*>(netDataStructs[8]);
    delete reinterpret_cast<NetMsg::SVC_SendTable*>(netDataStructs[9]);
    delete reinterpret_cast<NetMsg::SVC_ClassInfo*>(netDataStructs[10]);
    delete reinterpret_cast<NetMsg::SVC_SetPause*>(netDataStructs[11]);
    delete reinterpret_cast<NetMsg::SVC_CreateStringTable*>(netDataStructs[12]);
    delete reinterpret_cast<NetMsg::SVC_UpdateStringTable*>(netDataStructs[13]);
    delete reinterpret_cast<NetMsg::SVC_VoiceInit*>(netDataStructs[14]);
    delete reinterpret_cast<NetMsg::SVC_VoiceData*>(netDataStructs[15]);
    delete reinterpret_cast<NetMsg::SVC_HLTV*>(netDataStructs[16]);
    delete reinterpret_cast<NetMsg::SVC_Sounds*>(netDataStructs[17]);
    delete reinterpret_cast<NetMsg::SVC_SetView*>(netDataStructs[18]);
    delete reinterpret_cast<NetMsg::SVC_FixAngle*>(netDataStructs[19]);
    delete reinterpret_cast<NetMsg::SVC_CrosshairAngle*>(netDataStructs[20]);
    delete reinterpret_cast<NetMsg::SVC_BSPDecal*>(netDataStructs[21]);
    delete reinterpret_cast<NetMsg::SVC_TerrainMod*>(netDataStructs[22]);
    delete reinterpret_cast<NetMsg::SVC_UserMessage*>(netDataStructs[23]);
    delete reinterpret_cast<NetMsg::SVC_EntityMessage*>(netDataStructs[24]);
    delete reinterpret_cast<NetMsg::SVC_GameEvent*>(netDataStructs[25]);
    delete reinterpret_cast<NetMsg::SVC_PacketEntities*>(netDataStructs[26]);
    delete reinterpret_cast<NetMsg::SVC_TempEntities*>(netDataStructs[27]);
    delete reinterpret_cast<NetMsg::SVC_Prefetch*>(netDataStructs[28]);
    delete reinterpret_cast<NetMsg::SVC_Menu*>(netDataStructs[29]);
    delete reinterpret_cast<NetMsg::SVC_GameEventList*>(netDataStructs[30]);
    delete reinterpret_cast<NetMsg::SVC_GetCvarValue*>(netDataStructs[31]);
}

#define DECLARE_NET_HANDLER_ARRAY(funcname) \
    { \
        &NetHandlers::Net_NOP_##funcname, \
        &NetHandlers::Net_Disconnect_##funcname, \
        &NetHandlers::Net_File_##funcname, \
        &NetHandlers::Net_Tick_##funcname, \
        &NetHandlers::Net_StringCmd_##funcname, \
        &NetHandlers::Net_SetConVar_##funcname, \
        &NetHandlers::Net_SignonState_##funcname, \
        &NetHandlers::SVC_Print_##funcname, \
        &NetHandlers::SVC_ServerInfo_##funcname, \
        &NetHandlers::SVC_SendTable_##funcname, \
        &NetHandlers::SVC_ClassInfo_##funcname, \
        &NetHandlers::SVC_SetPause_##funcname, \
        &NetHandlers::SVC_CreateStringTable_##funcname, \
        &NetHandlers::SVC_UpdateStringTable_##funcname, \
        &NetHandlers::SVC_VoiceInit_##funcname, \
        &NetHandlers::SVC_VoiceData_##funcname, \
        &NetHandlers::SVC_HLTV_##funcname, \
        &NetHandlers::SVC_Sounds_##funcname, \
        &NetHandlers::SVC_SetView_##funcname, \
        &NetHandlers::SVC_FixAngle_##funcname, \
        &NetHandlers::SVC_CrosshairAngle_##funcname, \
        &NetHandlers::SVC_BSPDecal_##funcname, \
        &NetHandlers::SVC_TerrainMod_##funcname, \
        &NetHandlers::SVC_UserMessage_##funcname, \
        &NetHandlers::SVC_EntityMessage_##funcname, \
        &NetHandlers::SVC_GameEvent_##funcname, \
        &NetHandlers::SVC_PacketEntities_##funcname, \
        &NetHandlers::SVC_TempEntities_##funcname, \
        &NetHandlers::SVC_Prefetch_##funcname, \
        &NetHandlers::SVC_Menu_##funcname, \
        &NetHandlers::SVC_GameEventList_##funcname, \
        &NetHandlers::SVC_GetCvarValue_##funcname \
    }

typedef bool (*NetMsgBitReadFn)(NetHandlers::BitRead& bitbuf, SourceGameContext& context, void* data);
typedef bool (*NetMsgBitWriteFn)(NetHandlers::BitWrite& bitbuf, const SourceGameContext& context, void* data);
typedef bool (*NetMsgJsonReadFn)(NetHandlers::JsonRead& jsonbuf, SourceGameContext& context, void* data);
typedef bool (*NetMsgJsonWriteFn)(NetHandlers::JsonWrite& jsonbuf, const SourceGameContext& context, void* data);
typedef void (*NetMsgToStringFn)(std::ostringstream& out, void* data);

bool NetHandlers::NetMsg_BitRead(uint32_t type, BitRead& bitbuf, SourceGameContext& context, void* data)
{
    static const NetMsgBitReadFn netHandlers[] = DECLARE_NET_HANDLER_ARRAY(BitRead);
    if (type >= (sizeof(netHandlers) / sizeof(NetMsgBitReadFn)))
    {
        return false;
    }
    return netHandlers[type](bitbuf, context, data);
}

bool NetHandlers::NetMsg_BitWrite(uint32_t type, BitWrite& bitbuf, const SourceGameContext& context, void* data)
{
    static const NetMsgBitWriteFn netHandlers[] = DECLARE_NET_HANDLER_ARRAY(BitWrite);
    if (type >= (sizeof(netHandlers) / sizeof(NetMsgBitWriteFn)))
    {
        return false;
    }
    return netHandlers[type](bitbuf, context, data);
}

bool NetHandlers::NetMsg_JsonRead(uint32_t type, JsonRead& jsonbuf, SourceGameContext& context, void* data)
{
    static const NetMsgJsonReadFn netHandlers[] = DECLARE_NET_HANDLER_ARRAY(JsonRead);
    if (type >= (sizeof(netHandlers) / sizeof(NetMsgJsonReadFn)))
    {
        return false;
    }
    return netHandlers[type](jsonbuf, context, data);
}

bool NetHandlers::NetMsg_JsonWrite(uint32_t type, JsonWrite& jsonbuf, const SourceGameContext& context, void* data)
{
    static const NetMsgJsonWriteFn netHandlers[] = DECLARE_NET_HANDLER_ARRAY(JsonWrite);
    if (type >= (sizeof(netHandlers) / sizeof(NetMsgJsonWriteFn)))
    {
        return false;
    }
    return netHandlers[type](jsonbuf, context, data);
}

void NetHandlers::NetMsg_ToString(uint32_t type, std::ostringstream& out, void* data)
{
    static const NetMsgToStringFn netHandlers[] = DECLARE_NET_HANDLER_ARRAY(ToString);
    if (type >= (sizeof(netHandlers) / sizeof(NetMsgToStringFn)))
    {
        return;
    }
    netHandlers[type](out, data);
}
<commit_msg>Reduced code duplication<commit_after>
#include "nethandlers.h"
#include "netmessages.h"
#include <cassert>
#include <cstdint>

#if !defined( MAX_OSPATH )
#define MAX_OSPATH      260         // max length of a filesystem pathname
#endif

#include "net_nop.h"
#include "net_disconnect.h"
#include "net_file.h"
#include "net_tick.h"
#include "net_stringcmd.h"
#include "net_setconvar.h"
#include "net_signonstate.h"
#include "svc_print.h"
#include "svc_serverinfo.h"
#include "svc_sendtable.h"
#include "svc_classinfo.h"
#include "svc_setpause.h"
#include "svc_createstringtable.h"
#include "svc_updatestringtable.h"
#include "svc_voiceinit.h"
#include "svc_voicedata.h"
#include "svc_hltv.h"
#include "svc_sounds.h"
#include "svc_setview.h"
#include "svc_fixangle.h"
#include "svc_crosshairangle.h"
#include "svc_bspdecal.h"
#include "svc_terrainmod.h"
#include "svc_usermessage.h"
#include "svc_entitymessage.h"
#include "svc_gameevent.h"
#include "svc_packetentities.h"
#include "svc_tempentities.h"
#include "svc_prefetch.h"
#include "svc_menu.h"
#include "svc_gameeventlist.h"
#include "svc_getcvarvalue.h"

void NetHandlers::CreateNetMsgStructs(NetDataStructArray& netDataStructs)
{
    netDataStructs[0] = new NetMsg::Net_NOP();
    netDataStructs[1] = new NetMsg::Net_Disconnect();
    netDataStructs[2] = new NetMsg::Net_File();
    netDataStructs[3] = new NetMsg::Net_Tick();
    netDataStructs[4] = new NetMsg::Net_StringCmd();
    netDataStructs[5] = new NetMsg::Net_SetConVar();
    netDataStructs[6] = new NetMsg::Net_SignonState();
    netDataStructs[7] = new NetMsg::SVC_Print();
    netDataStructs[8] = new NetMsg::SVC_ServerInfo();
    netDataStructs[9] = new NetMsg::SVC_SendTable();
    netDataStructs[10] = new NetMsg::SVC_ClassInfo();
    netDataStructs[11] = new NetMsg::SVC_SetPause();
    netDataStructs[12] = new NetMsg::SVC_CreateStringTable();
    netDataStructs[13] = new NetMsg::SVC_UpdateStringTable();
    netDataStructs[14] = new NetMsg::SVC_VoiceInit();
    netDataStructs[15] = new NetMsg::SVC_VoiceData();
    netDataStructs[16] = new NetMsg::SVC_HLTV();
    netDataStructs[17] = new NetMsg::SVC_Sounds();
    netDataStructs[18] = new NetMsg::SVC_SetView();
    netDataStructs[19] = new NetMsg::SVC_FixAngle();
    netDataStructs[20] = new NetMsg::SVC_CrosshairAngle();
    netDataStructs[21] = new NetMsg::SVC_BSPDecal();
    netDataStructs[22] = new NetMsg::SVC_TerrainMod();
    netDataStructs[23] = new NetMsg::SVC_UserMessage();
    netDataStructs[24] = new NetMsg::SVC_EntityMessage();
    netDataStructs[25] = new NetMsg::SVC_GameEvent();
    netDataStructs[26] = new NetMsg::SVC_PacketEntities();
    netDataStructs[27] = new NetMsg::SVC_TempEntities();
    netDataStructs[28] = new NetMsg::SVC_Prefetch();
    netDataStructs[29] = new NetMsg::SVC_Menu();
    netDataStructs[30] = new NetMsg::SVC_GameEventList();
    netDataStructs[31] = new NetMsg::SVC_GetCvarValue();
}

void NetHandlers::DestroyNetMsgStructs(NetDataStructArray& netDataStructs)
{
    delete reinterpret_cast<NetMsg::Net_NOP*>(netDataStructs[0]);
    delete reinterpret_cast<NetMsg::Net_Disconnect*>(netDataStructs[1]);
    delete reinterpret_cast<NetMsg::Net_File*>(netDataStructs[2]);
    delete reinterpret_cast<NetMsg::Net_Tick*>(netDataStructs[3]);
    delete reinterpret_cast<NetMsg::Net_StringCmd*>(netDataStructs[4]);
    delete reinterpret_cast<NetMsg::Net_SetConVar*>(netDataStructs[5]);
    delete reinterpret_cast<NetMsg::Net_SignonState*>(netDataStructs[6]);
    delete reinterpret_cast<NetMsg::SVC_Print*>(netDataStructs[7]);
    delete reinterpret_cast<NetMsg::SVC_ServerInfo*>(netDataStructs[8]);
    delete reinterpret_cast<NetMsg::SVC_SendTable*>(netDataStructs[9]);
    delete reinterpret_cast<NetMsg::SVC_ClassInfo*>(netDataStructs[10]);
    delete reinterpret_cast<NetMsg::SVC_SetPause*>(netDataStructs[11]);
    delete reinterpret_cast<NetMsg::SVC_CreateStringTable*>(netDataStructs[12]);
    delete reinterpret_cast<NetMsg::SVC_UpdateStringTable*>(netDataStructs[13]);
    delete reinterpret_cast<NetMsg::SVC_VoiceInit*>(netDataStructs[14]);
    delete reinterpret_cast<NetMsg::SVC_VoiceData*>(netDataStructs[15]);
    delete reinterpret_cast<NetMsg::SVC_HLTV*>(netDataStructs[16]);
    delete reinterpret_cast<NetMsg::SVC_Sounds*>(netDataStructs[17]);
    delete reinterpret_cast<NetMsg::SVC_SetView*>(netDataStructs[18]);
    delete reinterpret_cast<NetMsg::SVC_FixAngle*>(netDataStructs[19]);
    delete reinterpret_cast<NetMsg::SVC_CrosshairAngle*>(netDataStructs[20]);
    delete reinterpret_cast<NetMsg::SVC_BSPDecal*>(netDataStructs[21]);
    delete reinterpret_cast<NetMsg::SVC_TerrainMod*>(netDataStructs[22]);
    delete reinterpret_cast<NetMsg::SVC_UserMessage*>(netDataStructs[23]);
    delete reinterpret_cast<NetMsg::SVC_EntityMessage*>(netDataStructs[24]);
    delete reinterpret_cast<NetMsg::SVC_GameEvent*>(netDataStructs[25]);
    delete reinterpret_cast<NetMsg::SVC_PacketEntities*>(netDataStructs[26]);
    delete reinterpret_cast<NetMsg::SVC_TempEntities*>(netDataStructs[27]);
    delete reinterpret_cast<NetMsg::SVC_Prefetch*>(netDataStructs[28]);
    delete reinterpret_cast<NetMsg::SVC_Menu*>(netDataStructs[29]);
    delete reinterpret_cast<NetMsg::SVC_GameEventList*>(netDataStructs[30]);
    delete reinterpret_cast<NetMsg::SVC_GetCvarValue*>(netDataStructs[31]);
}

#define DECLARE_NET_HANDLER_ARRAY(funcname) \
    { \
        &NetHandlers::Net_NOP_##funcname, \
        &NetHandlers::Net_Disconnect_##funcname, \
        &NetHandlers::Net_File_##funcname, \
        &NetHandlers::Net_Tick_##funcname, \
        &NetHandlers::Net_StringCmd_##funcname, \
        &NetHandlers::Net_SetConVar_##funcname, \
        &NetHandlers::Net_SignonState_##funcname, \
        &NetHandlers::SVC_Print_##funcname, \
        &NetHandlers::SVC_ServerInfo_##funcname, \
        &NetHandlers::SVC_SendTable_##funcname, \
        &NetHandlers::SVC_ClassInfo_##funcname, \
        &NetHandlers::SVC_SetPause_##funcname, \
        &NetHandlers::SVC_CreateStringTable_##funcname, \
        &NetHandlers::SVC_UpdateStringTable_##funcname, \
        &NetHandlers::SVC_VoiceInit_##funcname, \
        &NetHandlers::SVC_VoiceData_##funcname, \
        &NetHandlers::SVC_HLTV_##funcname, \
        &NetHandlers::SVC_Sounds_##funcname, \
        &NetHandlers::SVC_SetView_##funcname, \
        &NetHandlers::SVC_FixAngle_##funcname, \
        &NetHandlers::SVC_CrosshairAngle_##funcname, \
        &NetHandlers::SVC_BSPDecal_##funcname, \
        &NetHandlers::SVC_TerrainMod_##funcname, \
        &NetHandlers::SVC_UserMessage_##funcname, \
        &NetHandlers::SVC_EntityMessage_##funcname, \
        &NetHandlers::SVC_GameEvent_##funcname, \
        &NetHandlers::SVC_PacketEntities_##funcname, \
        &NetHandlers::SVC_TempEntities_##funcname, \
        &NetHandlers::SVC_Prefetch_##funcname, \
        &NetHandlers::SVC_Menu_##funcname, \
        &NetHandlers::SVC_GameEventList_##funcname, \
        &NetHandlers::SVC_GetCvarValue_##funcname \
    }

typedef bool (*NetMsgBitReadFn)(NetHandlers::BitRead& bitbuf, SourceGameContext& context, void* data);
typedef bool (*NetMsgBitWriteFn)(NetHandlers::BitWrite& bitbuf, const SourceGameContext& context, void* data);
typedef bool (*NetMsgJsonReadFn)(NetHandlers::JsonRead& jsonbuf, SourceGameContext& context, void* data);
typedef bool (*NetMsgJsonWriteFn)(NetHandlers::JsonWrite& jsonbuf, const SourceGameContext& context, void* data);
typedef void (*NetMsgToStringFn)(std::ostringstream& out, void* data);

template<typename BufType, typename FnType, typename ContextType, size_t NumHandlers>
bool NetMsgFuncRunner(const FnType (&netHandlers)[NumHandlers], uint32_t type, BufType& buf, ContextType& context, void* data)
{
    if (type >= NumHandlers)
    {
        return false;
    }
    return netHandlers[type](buf, context, data);
}

bool NetHandlers::NetMsg_BitRead(uint32_t type, BitRead& bitbuf, SourceGameContext& context, void* data)
{
    static const NetMsgBitReadFn netHandlers[] = DECLARE_NET_HANDLER_ARRAY(BitRead);
    return NetMsgFuncRunner(netHandlers, type, bitbuf, context, data);
}

bool NetHandlers::NetMsg_BitWrite(uint32_t type, BitWrite& bitbuf, const SourceGameContext& context, void* data)
{
    static const NetMsgBitWriteFn netHandlers[] = DECLARE_NET_HANDLER_ARRAY(BitWrite);
    return NetMsgFuncRunner(netHandlers, type, bitbuf, context, data);
}

bool NetHandlers::NetMsg_JsonRead(uint32_t type, JsonRead& jsonbuf, SourceGameContext& context, void* data)
{
    static const NetMsgJsonReadFn netHandlers[] = DECLARE_NET_HANDLER_ARRAY(JsonRead);
    return NetMsgFuncRunner(netHandlers, type, jsonbuf, context, data);
}

bool NetHandlers::NetMsg_JsonWrite(uint32_t type, JsonWrite& jsonbuf, const SourceGameContext& context, void* data)
{
    static const NetMsgJsonWriteFn netHandlers[] = DECLARE_NET_HANDLER_ARRAY(JsonWrite);
    return NetMsgFuncRunner(netHandlers, type, jsonbuf, context, data);
}

void NetHandlers::NetMsg_ToString(uint32_t type, std::ostringstream& out, void* data)
{
    static const NetMsgToStringFn netHandlers[] = DECLARE_NET_HANDLER_ARRAY(ToString);
    if (type >= (sizeof(netHandlers) / sizeof(NetMsgToStringFn)))
    {
        return;
    }
    netHandlers[type](out, data);
}
<|endoftext|>


<commit_before><commit_msg>apf stk : towards ice sheet support<commit_after><|endoftext|>


<commit_before>#ifndef UTILS_UTILS_HPP
#define UTILS_UTILS_HPP

// Copyright (c) 2016, Dmitry Koplyarov <koplyarov.da@gmail.com>
//
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted,
// provided that the above copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#include <chrono>
#include <thread>

namespace wigwag
{

	class thread
	{
	public:
		using thread_func = std::function<void(const std::atomic<bool>&)>;

	private:
		std::atomic<bool>		_alive;
		thread_func				_thread_func;
		std::string				_error_message;
		std::thread				_impl;

	public:
		thread(const thread_func& f)
			:	_alive(true),
				_thread_func(f)
		{ _impl = std::thread(std::bind(&thread::func, this)); }

		~thread()
		{
			_alive = false;
			if (_impl.joinable())
				_impl.join();
			if (!_error_message.empty())
				TS_FAIL(("Uncaught exception in thread: " + _error_message).c_str());
		}

		static void sleep(int64_t ms)
		{ std::this_thread::sleep_for(std::chrono::milliseconds(ms)); }

	private:
		void func()
		{
			try
			{ _thread_func(_alive); }
			catch (const std::exception& ex)
			{ _error_message = ex.what(); }
		}
	};

	template < typename Lockable_ >
	std::unique_lock<Lockable_> lock(Lockable_& lockable)
	{ return std::unique_lock<Lockable_>(lockable); }

}

#endif
<commit_msg>Writing a warning to stderr if test thread is not joinable at its destructor<commit_after>#ifndef UTILS_UTILS_HPP
#define UTILS_UTILS_HPP

// Copyright (c) 2016, Dmitry Koplyarov <koplyarov.da@gmail.com>
//
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted,
// provided that the above copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#include <chrono>
#include <thread>

namespace wigwag
{

	class thread
	{
	public:
		using thread_func = std::function<void(const std::atomic<bool>&)>;

	private:
		std::atomic<bool>		_alive;
		thread_func				_thread_func;
		std::string				_error_message;
		std::thread				_impl;

	public:
		thread(const thread_func& f)
			:	_alive(true),
				_thread_func(f)
		{ _impl = std::thread(std::bind(&thread::func, this)); }

		~thread()
		{
			_alive = false;

			if (_impl.joinable())
				_impl.join();
			else
				std::cerr << "WARNING: thread is not joinable!" << std::endl;

			if (!_error_message.empty())
				TS_FAIL(("Uncaught exception in thread: " + _error_message).c_str());
		}

		static void sleep(int64_t ms)
		{ std::this_thread::sleep_for(std::chrono::milliseconds(ms)); }

	private:
		void func()
		{
			try
			{ _thread_func(_alive); }
			catch (const std::exception& ex)
			{ _error_message = ex.what(); }
		}
	};

	template < typename Lockable_ >
	std::unique_lock<Lockable_> lock(Lockable_& lockable)
	{ return std::unique_lock<Lockable_>(lockable); }

}

#endif
<|endoftext|>


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

#include <DebouncedInput.h>

DebouncedInput::DebouncedInput(byte pin, unsigned long dbt, boolean pullup = true, uint8_t keep)
{
    _pin = pin;
    _debounceTime = dbt;
    _pullup = pullup;
    _keep = keep;
    if (_keep > 0) {
        _lastHigh = (unsigned long *)malloc(_keep * sizeof(unsigned long));
        _lastLow = (unsigned long *)malloc(_keep * sizeof(unsigned long));
        for (int i = 0; i < _keep; i++) {
            _lastHigh[i] = _lastLow[i] = 0;
        }
    } else {
        _lastHigh = NULL;
        _lastLow = NULL;
    }
}

void DebouncedInput::begin()
{
    if (_pullup) {
        pinMode(_pin, INPUT_PULLUP);
    } else {
        pinMode(_pin, INPUT);
    }
    _value = digitalRead(_pin);
    _lastValue = _value;
}

int DebouncedInput::read()
{
    int r;
    unsigned long now = millis();
    r = digitalRead(_pin);
    if (r != _lrt) {
        _lrt = r;
        _lastChange = now;
    }
    if (now - _lastChange > _debounceTime) {
        if (_value != _lrt) {
            _value = _lrt;
            if (_keep > 0) {
                if (_value) {
                    for (int i = _keep-1; i > 0; i--) {
                        _lastHigh[i] = _lastHigh[i-1];
                    }
                    _lastHigh[0] = now;
                } else {
                    for (int i = _keep-1; i > 0; i--) {
                        _lastLow[i] = _lastLow[i-1];
                    }
                    _lastLow[0] = now;
                }
            }
        }
    }
    return _value;
}

boolean DebouncedInput::changed()
{
    int r = read();
    if (r != _lastValue) {
        _lastValue = r;
        return true;
    }
    return false;
}

boolean DebouncedInput::changed(uint8_t *val) {
    if (changed()) {
        *val = _lastValue;
        return true;
    }
    return false;
}

boolean DebouncedInput::changedTo(uint8_t val) {
    if (changed()) {
        return val == _lastValue;
    }
    return false;
}

unsigned long DebouncedInput::getHighTime(uint8_t seq) {
    if (seq >= _keep) {
        return 0;
    }
    return _lastHigh[seq];
}

unsigned long DebouncedInput::getLowTime(uint8_t seq) {
    if (seq >= _keep) {
        return 0;
    }
    return _lastLow[seq];
}

void DebouncedInput::clearTimes() {
    if (_keep == 0) {
        return;
    }
    for (int i = 0; i < _keep; i++) {
        _lastLow[i] = _lastHigh[i] = 0;
    }
}

#if defined(__PIC32MX__) || defined(__PIC32MZ__)
struct CNInputs {
    DebouncedInput *in;
    struct CNInputs *next;
};

struct CNInputs *ChangeNotificationInputList = NULL;

void __attribute__((interrupt)) DebouncedInputChangeNotificationHandler() {
    struct CNInputs *scan;

    (void)PORTA;
    for (scan = ChangeNotificationInputList; scan; scan = scan->next) {
        scan->in->callOnChange();
    }
#ifdef _CHANGE_NOTICE_IRQ
    clearIntFlag(_CHANGE_NOTICE_IRQ);
#endif
#ifdef _CHANGE_NOTICE_A_IRQ
    clearIntFlag(_CHANGE_NOTICE_A_IRQ);
#endif
#ifdef _CHANGE_NOTICE_B_IRQ
    clearIntFlag(_CHANGE_NOTICE_B_IRQ);
#endif
#ifdef _CHANGE_NOTICE_C_IRQ
    clearIntFlag(_CHANGE_NOTICE_C_IRQ);
#endif
}

void DebouncedInput::callOnChange() {
    int r = digitalRead(_pin);
    if (r != _lastValue) {
        _lastValue = r;
        if (r == LOW && _intDir == FALLING) {
            if ((_intTime == 0) || ((millis() - _intTime) > _debounceTime)) {
                _intTime = millis();
                _onChange(_lastValue);
            }
        } else if (r == HIGH && _intDir == RISING) {
            if ((_intTime == 0) || ((millis() - _intTime) > _debounceTime)) {
                _intTime = millis();
                _onChange(_lastValue);
            }
        }
    }
}

void DebouncedInput::attachInterrupt(void (*func)(int), int dir) {

#if defined(CNEN)
    int cn = digitalPinToCN(_pin);

    if (cn == NOT_CN_PIN) {
        return;
    }

    CNENSET = cn;
    CNCONbits.ON    =   1;
    CNCONbits.SIDL  =   0;
    setIntVector(_CHANGE_NOTICE_VECTOR, DebouncedInputChangeNotificationHandler);
    setIntPriority(_CHANGE_NOTICE_VECTOR, 1, 0);
    clearIntFlag(_CHANGE_NOTICE_IRQ);
    setIntEnable(_CHANGE_NOTICE_IRQ);
#else

    volatile p32_ioport *   iop;
    int port, bit;
    if ((port = digitalPinToPort(_pin)) == NOT_A_PIN)
    {
        return;
    }

    //* Obtain pointer to the registers for this io port.
    iop = (p32_ioport *)portRegisters(port);

    //* Obtain bit mask for the specific bit for this pin.
    bit = digitalPinToBitMask(_pin);

    iop->cnen.set = bit;
    iop->cncon.set = 1<<15;
    setIntVector(_CHANGE_NOTICE_VECTOR, DebouncedInputChangeNotificationHandler);
    setIntPriority(_CHANGE_NOTICE_VECTOR, 1, 0);
    if (port == _IOPORT_PA) {
        clearIntFlag(_CHANGE_NOTICE_A_IRQ);
        setIntEnable(_CHANGE_NOTICE_A_IRQ);
    }
    if (port == _IOPORT_PB) {
        clearIntFlag(_CHANGE_NOTICE_B_IRQ);
        setIntEnable(_CHANGE_NOTICE_B_IRQ);
    }
    if (port == _IOPORT_PC) {
        clearIntFlag(_CHANGE_NOTICE_C_IRQ);
        setIntEnable(_CHANGE_NOTICE_C_IRQ);
    }
#endif
    _onChange = func;
    _intDir = dir;
    _intTime = 0;

    if (ChangeNotificationInputList == NULL) {
        ChangeNotificationInputList = (struct CNInputs *)malloc(sizeof(struct CNInputs));
        ChangeNotificationInputList->in = this;
        ChangeNotificationInputList->next = NULL;
        return;
    }

    struct CNInputs *scan;
    for (scan = ChangeNotificationInputList; scan->next; scan = scan->next);
    scan->next = (struct CNInputs *)malloc(sizeof(struct CNInputs));
    scan->next->next = NULL;
    scan->next->in = this;
}

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

#include <DebouncedInput.h>

DebouncedInput::DebouncedInput(byte pin, unsigned long dbt, boolean pullup = true, uint8_t keep)
{
    _pin = pin;
    _debounceTime = dbt;
    _pullup = pullup;
    _keep = keep;
    if (_keep > 0) {
        _lastHigh = (unsigned long *)malloc(_keep * sizeof(unsigned long));
        _lastLow = (unsigned long *)malloc(_keep * sizeof(unsigned long));
        for (int i = 0; i < _keep; i++) {
            _lastHigh[i] = _lastLow[i] = 0;
        }
    } else {
        _lastHigh = NULL;
        _lastLow = NULL;
    }
}

void DebouncedInput::begin()
{
    if (_pullup) {
        pinMode(_pin, INPUT_PULLUP);
    } else {
        pinMode(_pin, INPUT);
    }
    _value = digitalRead(_pin);
    _lastValue = _value;
}

int DebouncedInput::read()
{
    int r;
    unsigned long now = millis();
    r = digitalRead(_pin);
    if (r != _lrt) {
        _lrt = r;
        _lastChange = now;
    }
    if (now - _lastChange > _debounceTime) {
        if (_value != _lrt) {
            _value = _lrt;
            if (_keep > 0) {
                if (_value) {
                    for (int i = _keep-1; i > 0; i--) {
                        _lastHigh[i] = _lastHigh[i-1];
                    }
                    _lastHigh[0] = now;
                } else {
                    for (int i = _keep-1; i > 0; i--) {
                        _lastLow[i] = _lastLow[i-1];
                    }
                    _lastLow[0] = now;
                }
            }
        }
    }
    return _value;
}

boolean DebouncedInput::changed()
{
    int r = read();
    if (r != _lastValue) {
        _lastValue = r;
        return true;
    }
    return false;
}

boolean DebouncedInput::changed(uint8_t *val) {
    if (changed()) {
        *val = _lastValue;
        return true;
    }
    return false;
}

boolean DebouncedInput::changedTo(uint8_t val) {
    if (changed()) {
        return val == _lastValue;
    }
    return false;
}

unsigned long DebouncedInput::getHighTime(uint8_t seq) {
    if (seq >= _keep) {
        return 0;
    }
    return _lastHigh[seq];
}

unsigned long DebouncedInput::getLowTime(uint8_t seq) {
    if (seq >= _keep) {
        return 0;
    }
    return _lastLow[seq];
}

void DebouncedInput::clearTimes() {
    if (_keep == 0) {
        return;
    }
    for (int i = 0; i < _keep; i++) {
        _lastLow[i] = _lastHigh[i] = 0;
    }
}

#if defined(__PIC32MX__) || defined(__PIC32MZ__)
struct CNInputs {
    DebouncedInput *in;
    struct CNInputs *next;
};

struct CNInputs *ChangeNotificationInputList = NULL;

void __attribute__((interrupt)) DebouncedInputChangeNotificationHandler() {
    struct CNInputs *scan;

    for (scan = ChangeNotificationInputList; scan; scan = scan->next) {
        scan->in->callOnChange();
    }
#ifdef _CHANGE_NOTICE_IRQ
    clearIntFlag(_CHANGE_NOTICE_IRQ);
#endif
#ifdef _CHANGE_NOTICE_A_IRQ
    clearIntFlag(_CHANGE_NOTICE_A_IRQ);
#endif
#ifdef _CHANGE_NOTICE_B_IRQ
    clearIntFlag(_CHANGE_NOTICE_B_IRQ);
#endif
#ifdef _CHANGE_NOTICE_C_IRQ
    clearIntFlag(_CHANGE_NOTICE_C_IRQ);
#endif
}

void DebouncedInput::callOnChange() {
    int r = digitalRead(_pin);
    if (r != _lastValue) {
        _lastValue = r;
        if (r == LOW && _intDir == FALLING) {
            if ((_intTime == 0) || ((millis() - _intTime) > _debounceTime)) {
                _intTime = millis();
                _onChange(_lastValue);
            }
        } else if (r == HIGH && _intDir == RISING) {
            if ((_intTime == 0) || ((millis() - _intTime) > _debounceTime)) {
                _intTime = millis();
                _onChange(_lastValue);
            }
        }
    }
}

void DebouncedInput::attachInterrupt(void (*func)(int), int dir) {

#if defined(_CHANGE_NOTICE_IRQ)
    int cn = digitalPinToCN(_pin);

    if (cn == NOT_CN_PIN) {
        return;
    }

    CNENSET = cn;
    CNCONbits.ON    =   1;
    CNCONbits.SIDL  =   0;
    setIntVector(_CHANGE_NOTICE_VECTOR, DebouncedInputChangeNotificationHandler);
    setIntPriority(_CHANGE_NOTICE_VECTOR, 1, 0);
    clearIntFlag(_CHANGE_NOTICE_IRQ);
    setIntEnable(_CHANGE_NOTICE_IRQ);
#else

    volatile p32_ioport *   iop;
    int port, bit;
    if ((port = digitalPinToPort(_pin)) == NOT_A_PIN)
    {
        return;
    }

    //* Obtain pointer to the registers for this io port.
    iop = (p32_ioport *)portRegisters(port);

    //* Obtain bit mask for the specific bit for this pin.
    bit = digitalPinToBitMask(_pin);

    iop->cnen.set = bit;
    iop->cncon.set = 1<<15;
    setIntVector(_CHANGE_NOTICE_VECTOR, DebouncedInputChangeNotificationHandler);
    setIntPriority(_CHANGE_NOTICE_VECTOR, 1, 0);
    if (port == _IOPORT_PA) {
        clearIntFlag(_CHANGE_NOTICE_A_IRQ);
        setIntEnable(_CHANGE_NOTICE_A_IRQ);
    }
    if (port == _IOPORT_PB) {
        clearIntFlag(_CHANGE_NOTICE_B_IRQ);
        setIntEnable(_CHANGE_NOTICE_B_IRQ);
    }
    if (port == _IOPORT_PC) {
        clearIntFlag(_CHANGE_NOTICE_C_IRQ);
        setIntEnable(_CHANGE_NOTICE_C_IRQ);
    }
#endif
    _onChange = func;
    _intDir = dir;
    _intTime = 0;

    if (ChangeNotificationInputList == NULL) {
        ChangeNotificationInputList = (struct CNInputs *)malloc(sizeof(struct CNInputs));
        ChangeNotificationInputList->in = this;
        ChangeNotificationInputList->next = NULL;
        return;
    }

    struct CNInputs *scan;
    for (scan = ChangeNotificationInputList; scan->next; scan = scan->next);
    scan->next = (struct CNInputs *)malloc(sizeof(struct CNInputs));
    scan->next->next = NULL;
    scan->next->in = this;
}

#endif
<|endoftext|>


<commit_before>/****************************************************************************
 *   Copyright (C) 2012-2018 Savoir-faire Linux                          *
 *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> *
 *                                                                          *
 *   This library is free software; you can redistribute it and/or          *
 *   modify it under the terms of the GNU Lesser General Public             *
 *   License as published by the Free Software Foundation; either           *
 *   version 2.1 of the License, or (at your option) any later version.     *
 *                                                                          *
 *   This library is distributed in the hope that it will be useful,        *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU      *
 *   Lesser General Public License for more details.                        *
 *                                                                          *
 *   You should have received a copy of the GNU General Public License      *
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
 ***************************************************************************/
#include "device.h"

//Qt
#include <QtCore/QTimer>

//Ring
#include "../dbus/videomanager.h"
#include "devicemodel.h"
#include "resolution.h"
#include "rate.h"
#include "channel.h"
#include "renderer.h"
#include "previewmanager.h"

//Ring private
#include "../private/videochannel_p.h"
#include "../private/videodevice_p.h"
#include "../private/videorate_p.h"
#include "../private/videoresolution_p.h"
#include "../private/videorenderermanager.h"

VideoDevicePrivate::VideoDevicePrivate(Video::Device* parent) : QObject(parent),m_pCurrentChannel(nullptr),m_RequireSave(false),q_ptr(parent)
{
}

///Constructor
Video::Device::Device(const QString &id) : QAbstractListModel(nullptr),
d_ptr(new VideoDevicePrivate(this))
{
   d_ptr->m_DeviceId = id;
   VideoManagerInterface& interface = VideoManager::instance();
   MapStringMapStringVectorString cap = interface.getCapabilities(id);
   QMapIterator<QString, MapStringVectorString> channels(cap);
   while (channels.hasNext()) {
      channels.next();

      Video::Channel* chan = new Video::Channel(this,channels.key());
      d_ptr->m_lChannels << chan;
      QList<Video::Resolution*> validResolutions;

      QMapIterator<QString, VectorString> resolutions(channels.value());
      while (resolutions.hasNext()) {
         resolutions.next();

         Video::Resolution* res = new Video::Resolution(resolutions.key(),chan);
         validResolutions << res;

         foreach(const QString& rate, resolutions.value()) {
            Video::Rate* r = new Video::Rate(res,rate);
            res->d_ptr->m_lValidRates << r;
         }
      }

      // Sort resolutions by size area.
      qSort(validResolutions.begin(),
      validResolutions.end(),
      [](Video::Resolution* resA, Video::Resolution* resB) {
          return resA->width()  * resA->height() > resB->width() * resB->height();
      });
      chan->d_ptr->m_lValidResolutions = validResolutions;
   }
   Q_UNUSED(cap)
}

///Destructor
Video::Device::~Device()
{
//    delete d_ptr;
}

QVariant Video::Device::data( const QModelIndex& index, int role) const
{
   if (index.isValid() && role == Qt::DisplayRole && d_ptr->m_lChannels.size() > index.row()) {
      return d_ptr->m_lChannels[index.row()]->name();
   }
   return QVariant();
}

int Video::Device::rowCount( const QModelIndex& parent) const
{
   return (parent.isValid())?0:d_ptr->m_lChannels.size();
}

Qt::ItemFlags Video::Device::flags( const QModelIndex& idx) const
{
   if (idx.column() == 0)
      return QAbstractItemModel::flags(idx) | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
   return QAbstractItemModel::flags(idx);
}

bool Video::Device::setData( const QModelIndex& index, const QVariant &value, int role)
{
   Q_UNUSED(index)
   Q_UNUSED(value)
   Q_UNUSED(role)
   return false;
}

// int Video::Device::relativeIndex() {
//    return m_pDevice->channelList().indexOf(this);
// }

///Get the valid channel list
QList<Video::Channel*> Video::Device::channelList() const
{
   return d_ptr->m_lChannels;
}

///Save the current settings
void Video::Device::save()
{
   if (!d_ptr->m_RequireSave) {
      d_ptr->m_RequireSave = true;
      //A little delay won't hurt
      QTimer::singleShot(100,d_ptr.data(),SLOT(saveIdle()));
   }
}

///Get the device id
const QString Video::Device::id() const
{
   return d_ptr->m_DeviceId;
}

///Get the device name
const QString Video::Device::name() const
{
   VideoManagerInterface& interface = VideoManager::instance();
   return QMap<QString,QString>(interface.getSettings(d_ptr->m_DeviceId))[VideoDevicePrivate::PreferenceNames::NAME];;
}

///Is this device the default one
bool Video::Device::isActive() const
{
   return Video::DeviceModel::instance().activeDevice() == this;
}

bool Video::Device::setActiveChannel(Video::Channel* chan)
{
   if ((!chan) || (d_ptr->m_lChannels.indexOf(chan) == -1)) {
      qWarning() << "Trying to set an invalid channel" << (chan?chan->name():"NULL") << "for" << id();
      return false;
   }

   if (d_ptr->m_pCurrentChannel == chan)
      return false;

   d_ptr->m_pCurrentChannel = chan;
   save();
   return true;
}

bool Video::Device::setActiveChannel(int idx)
{
   if (idx < 0 || idx >= d_ptr->m_lChannels.size()) return false;
   return setActiveChannel(d_ptr->m_lChannels[idx]);
}

Video::Channel* Video::Device::activeChannel() const
{
   if (!d_ptr->m_pCurrentChannel) {
      VideoManagerInterface& interface = VideoManager::instance();
      const QString chan = QMap<QString,QString>(interface.getSettings(d_ptr->m_DeviceId))[VideoDevicePrivate::PreferenceNames::CHANNEL];
      foreach(Video::Channel* c, d_ptr->m_lChannels) {
         if (c->name() == chan) {
            d_ptr->m_pCurrentChannel = c;
            break;
         }
      }
   }
   if (!d_ptr->m_pCurrentChannel && d_ptr->m_lChannels.size()) {
      d_ptr->m_pCurrentChannel = d_ptr->m_lChannels[0];
   }
   return d_ptr->m_pCurrentChannel;
}

void VideoDevicePrivate::saveIdle()
{
   m_RequireSave = false;

   //In case new (unsupported) fields are added, merge with existing
   VideoManagerInterface& interface = VideoManager::instance();
   MapStringString pref = interface.getSettings(m_DeviceId);

   Video::Channel* chan = q_ptr->activeChannel();

   if (!chan) {
      qWarning() << "Saving video failed: Invalid channel";
      return;
   }

   Video::Resolution* res = chan->activeResolution();

   if (!res) {
      qWarning() << "Saving video failed: Invalid resolution";
      return;
   }

   Video::Rate* rate = res->activeRate();

   if (!rate) {
      qWarning() << "Saving video failed: Invalid rate";
      return;
   }

   pref[VideoDevicePrivate::PreferenceNames::CHANNEL] = chan->name ();
   pref[VideoDevicePrivate::PreferenceNames::SIZE   ] = res ->name ();
   pref[VideoDevicePrivate::PreferenceNames::RATE   ] = rate->name ();
   interface.applySettings(m_DeviceId,pref);

   //If the preview is running, reload it
   //doing this during a call will cause re-invite, this is unwanted
   if (Video::PreviewManager::instance().isPreviewing() && VideoRendererManager::instance().size() == 1) {
      Video::PreviewManager::instance().stopPreview();
      Video::PreviewManager::instance().startPreview();
   }
}
<commit_msg>fix: sort and deduplicate frame rates<commit_after>/****************************************************************************
 *   Copyright (C) 2012-2018 Savoir-faire Linux                          *
 *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> *
 *                                                                          *
 *   This library is free software; you can redistribute it and/or          *
 *   modify it under the terms of the GNU Lesser General Public             *
 *   License as published by the Free Software Foundation; either           *
 *   version 2.1 of the License, or (at your option) any later version.     *
 *                                                                          *
 *   This library is distributed in the hope that it will be useful,        *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU      *
 *   Lesser General Public License for more details.                        *
 *                                                                          *
 *   You should have received a copy of the GNU General Public License      *
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
 ***************************************************************************/
#include "device.h"

//Qt
#include <QtCore/QTimer>

//Ring
#include "../dbus/videomanager.h"
#include "devicemodel.h"
#include "resolution.h"
#include "rate.h"
#include "channel.h"
#include "renderer.h"
#include "previewmanager.h"

//Ring private
#include "../private/videochannel_p.h"
#include "../private/videodevice_p.h"
#include "../private/videorate_p.h"
#include "../private/videoresolution_p.h"
#include "../private/videorenderermanager.h"

VideoDevicePrivate::VideoDevicePrivate(Video::Device* parent) : QObject(parent),m_pCurrentChannel(nullptr),m_RequireSave(false),q_ptr(parent)
{
}

///Constructor
Video::Device::Device(const QString &id) : QAbstractListModel(nullptr),
d_ptr(new VideoDevicePrivate(this))
{
   d_ptr->m_DeviceId = id;
   VideoManagerInterface& interface = VideoManager::instance();
   MapStringMapStringVectorString cap = interface.getCapabilities(id);
   QMapIterator<QString, MapStringVectorString> channels(cap);
   while (channels.hasNext()) {
      channels.next();

      Video::Channel* chan = new Video::Channel(this,channels.key());
      d_ptr->m_lChannels << chan;
      QList<Video::Resolution*> validResolutions;

      QMapIterator<QString, VectorString> resolutions(channels.value());
      while (resolutions.hasNext()) {
         resolutions.next();

         Video::Resolution* res = new Video::Resolution(resolutions.key(),chan);
         validResolutions << res;

         foreach(const QString& rate, resolutions.value()) {
            Video::Rate* r = new Video::Rate(res,rate);
            if (!res->d_ptr->m_lValidRates.contains(r)) {
                res->d_ptr->m_lValidRates << r;
            }
         }

         // Sort rates in increasing order.
         qSort(res->d_ptr->m_lValidRates.begin(),
         res->d_ptr->m_lValidRates.end(),
         [](Video::Rate* rateA, Video::Rate* rateB) {
             return rateA->name().toInt() > rateB->name().toInt();
         });
      }

      // Sort resolutions by size area.
      qSort(validResolutions.begin(),
      validResolutions.end(),
      [](Video::Resolution* resA, Video::Resolution* resB) {
          return resA->width()  * resA->height() > resB->width() * resB->height();
      });
      chan->d_ptr->m_lValidResolutions = validResolutions;
   }
   Q_UNUSED(cap)
}

///Destructor
Video::Device::~Device()
{
//    delete d_ptr;
}

QVariant Video::Device::data( const QModelIndex& index, int role) const
{
   if (index.isValid() && role == Qt::DisplayRole && d_ptr->m_lChannels.size() > index.row()) {
      return d_ptr->m_lChannels[index.row()]->name();
   }
   return QVariant();
}

int Video::Device::rowCount( const QModelIndex& parent) const
{
   return (parent.isValid())?0:d_ptr->m_lChannels.size();
}

Qt::ItemFlags Video::Device::flags( const QModelIndex& idx) const
{
   if (idx.column() == 0)
      return QAbstractItemModel::flags(idx) | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
   return QAbstractItemModel::flags(idx);
}

bool Video::Device::setData( const QModelIndex& index, const QVariant &value, int role)
{
   Q_UNUSED(index)
   Q_UNUSED(value)
   Q_UNUSED(role)
   return false;
}

// int Video::Device::relativeIndex() {
//    return m_pDevice->channelList().indexOf(this);
// }

///Get the valid channel list
QList<Video::Channel*> Video::Device::channelList() const
{
   return d_ptr->m_lChannels;
}

///Save the current settings
void Video::Device::save()
{
   if (!d_ptr->m_RequireSave) {
      d_ptr->m_RequireSave = true;
      //A little delay won't hurt
      QTimer::singleShot(100,d_ptr.data(),SLOT(saveIdle()));
   }
}

///Get the device id
const QString Video::Device::id() const
{
   return d_ptr->m_DeviceId;
}

///Get the device name
const QString Video::Device::name() const
{
   VideoManagerInterface& interface = VideoManager::instance();
   return QMap<QString,QString>(interface.getSettings(d_ptr->m_DeviceId))[VideoDevicePrivate::PreferenceNames::NAME];;
}

///Is this device the default one
bool Video::Device::isActive() const
{
   return Video::DeviceModel::instance().activeDevice() == this;
}

bool Video::Device::setActiveChannel(Video::Channel* chan)
{
   if ((!chan) || (d_ptr->m_lChannels.indexOf(chan) == -1)) {
      qWarning() << "Trying to set an invalid channel" << (chan?chan->name():"NULL") << "for" << id();
      return false;
   }

   if (d_ptr->m_pCurrentChannel == chan)
      return false;

   d_ptr->m_pCurrentChannel = chan;
   save();
   return true;
}

bool Video::Device::setActiveChannel(int idx)
{
   if (idx < 0 || idx >= d_ptr->m_lChannels.size()) return false;
   return setActiveChannel(d_ptr->m_lChannels[idx]);
}

Video::Channel* Video::Device::activeChannel() const
{
   if (!d_ptr->m_pCurrentChannel) {
      VideoManagerInterface& interface = VideoManager::instance();
      const QString chan = QMap<QString,QString>(interface.getSettings(d_ptr->m_DeviceId))[VideoDevicePrivate::PreferenceNames::CHANNEL];
      foreach(Video::Channel* c, d_ptr->m_lChannels) {
         if (c->name() == chan) {
            d_ptr->m_pCurrentChannel = c;
            break;
         }
      }
   }
   if (!d_ptr->m_pCurrentChannel && d_ptr->m_lChannels.size()) {
      d_ptr->m_pCurrentChannel = d_ptr->m_lChannels[0];
   }
   return d_ptr->m_pCurrentChannel;
}

void VideoDevicePrivate::saveIdle()
{
   m_RequireSave = false;

   //In case new (unsupported) fields are added, merge with existing
   VideoManagerInterface& interface = VideoManager::instance();
   MapStringString pref = interface.getSettings(m_DeviceId);

   Video::Channel* chan = q_ptr->activeChannel();

   if (!chan) {
      qWarning() << "Saving video failed: Invalid channel";
      return;
   }

   Video::Resolution* res = chan->activeResolution();

   if (!res) {
      qWarning() << "Saving video failed: Invalid resolution";
      return;
   }

   Video::Rate* rate = res->activeRate();

   if (!rate) {
      qWarning() << "Saving video failed: Invalid rate";
      return;
   }

   pref[VideoDevicePrivate::PreferenceNames::CHANNEL] = chan->name ();
   pref[VideoDevicePrivate::PreferenceNames::SIZE   ] = res ->name ();
   pref[VideoDevicePrivate::PreferenceNames::RATE   ] = rate->name ();
   interface.applySettings(m_DeviceId,pref);

   //If the preview is running, reload it
   //doing this during a call will cause re-invite, this is unwanted
   if (Video::PreviewManager::instance().isPreviewing() && VideoRendererManager::instance().size() == 1) {
      Video::PreviewManager::instance().stopPreview();
      Video::PreviewManager::instance().startPreview();
   }
}
<|endoftext|>


<commit_before><commit_msg>Added read benchmark<commit_after><|endoftext|>


<commit_before>#include <string>
#include <ros/console.h>

#include <tr_hub_parser/serial_port.h>
#include <tr_hub_parser/tr_hub_parser.h>

namespace tr_hub_parser
{

SerialPort::SerialPort() :
    serial_callback_function()
{
  serial_thread_should_exit_ = false;
  serial_port_fd_ = 0;
}

SerialPort::~SerialPort()
{
  disconnect();
}

bool SerialPort::connect(const std::string port)
{
  // Open serial port
  // O_RDWR - Read and write
  // O_NOCTTY - Ignore special chars like CTRL-C
  serial_port_fd_ = open(port.c_str(), O_RDWR | O_NOCTTY);
  if (serial_port_fd_ == -1)
  {
    ROS_ERROR("%s could not open serial port %s", ros::this_node::getName().c_str(), port.c_str());
    return false;
  }
  else
  {
    fcntl(serial_port_fd_, F_SETFL, 10);
  }

  struct termios newtio;
  bzero(&newtio, sizeof(newtio)); // clear struct for new port settings

  cfsetispeed(&newtio, B115200); // Input port speed
  cfsetospeed(&newtio, B115200); // Output port speed

  newtio.c_cflag &= ~PARENB; // no parity bit
  newtio.c_cflag &= ~CSTOPB; // 1 stop bit
  newtio.c_cflag &= ~CSIZE; // Only one stop bit
  newtio.c_cflag |= CS8; // 8 bit word

  newtio.c_iflag = 0; // Raw output since no parity checking is done
  newtio.c_oflag = 0; // Raw output
  newtio.c_lflag = 0; // Raw input is unprocessed

  tcflush(serial_port_fd_, TCIFLUSH);
  tcsetattr(serial_port_fd_, TCSANOW, &newtio);

  serial_thread_ = boost::thread(&SerialPort::serialThread, this);
  return true;
}

void SerialPort::disconnect()
{
  serial_thread_should_exit_ = true;
  close(serial_port_fd_);
}

bool SerialPort::sendChar(const char c[])
{
  // this function is used to support legacy 3char hub1 command
  return write(serial_port_fd_, (const void*)c, 3);
}

bool SerialPort::sendChar(const char c[], int count){
  return write(serial_port_fd_, (const void*)c, count);
}

void SerialPort::setSerialCallbackFunction(boost::function<void(uint8_t)> * f)
{
  serial_callback_function = f;
}

void SerialPort::serialThread()
{
  uint8_t single_character;

  // Non read
  while (!serial_thread_should_exit_ && ros::ok())
  {
    if (read(serial_port_fd_, &single_character, 1))
    {
      (*serial_callback_function)(single_character);
    }
    ros::Duration(0.0001).sleep();
  }
  return;

}

} // tr_hub_parser
<commit_msg>Removed serial callback sleep aka 10kHz limitation<commit_after>#include <string>
#include <ros/console.h>

#include <tr_hub_parser/serial_port.h>
#include <tr_hub_parser/tr_hub_parser.h>

namespace tr_hub_parser
{

SerialPort::SerialPort() :
    serial_callback_function()
{
  serial_thread_should_exit_ = false;
  serial_port_fd_ = 0;
}

SerialPort::~SerialPort()
{
  disconnect();
}

bool SerialPort::connect(const std::string port)
{
  // Open serial port
  // O_RDWR - Read and write
  // O_NOCTTY - Ignore special chars like CTRL-C
  serial_port_fd_ = open(port.c_str(), O_RDWR | O_NOCTTY);
  if (serial_port_fd_ == -1)
  {
    ROS_ERROR("%s could not open serial port %s", ros::this_node::getName().c_str(), port.c_str());
    return false;
  }
  else
  {
    fcntl(serial_port_fd_, F_SETFL, 10);
  }

  struct termios newtio;
  bzero(&newtio, sizeof(newtio)); // clear struct for new port settings

  cfsetispeed(&newtio, B115200); // Input port speed
  cfsetospeed(&newtio, B115200); // Output port speed

  newtio.c_cflag &= ~PARENB; // no parity bit
  newtio.c_cflag &= ~CSTOPB; // 1 stop bit
  newtio.c_cflag &= ~CSIZE; // Only one stop bit
  newtio.c_cflag |= CS8; // 8 bit word

  newtio.c_iflag = 0; // Raw output since no parity checking is done
  newtio.c_oflag = 0; // Raw output
  newtio.c_lflag = 0; // Raw input is unprocessed

  tcflush(serial_port_fd_, TCIFLUSH);
  tcsetattr(serial_port_fd_, TCSANOW, &newtio);

  serial_thread_ = boost::thread(&SerialPort::serialThread, this);
  return true;
}

void SerialPort::disconnect()
{
  serial_thread_should_exit_ = true;
  close(serial_port_fd_);
}

bool SerialPort::sendChar(const char c[])
{
  // this function is used to support legacy 3char hub1 command
  return write(serial_port_fd_, (const void*)c, 3);
}

bool SerialPort::sendChar(const char c[], int count){
  return write(serial_port_fd_, (const void*)c, count);
}

void SerialPort::setSerialCallbackFunction(boost::function<void(uint8_t)> * f)
{
  serial_callback_function = f;
}

void SerialPort::serialThread()
{
  uint8_t single_character;

  // Non read
  while (!serial_thread_should_exit_ && ros::ok())
  {
    if (read(serial_port_fd_, &single_character, 1))
    {
      (*serial_callback_function)(single_character);
    }
  }
  return;

}

} // tr_hub_parser
<|endoftext|>


<commit_before>/**
 * @file fslogicProxy.cc
 * @author Beata Skiba
 * @author Rafal Slota
 * @copyright (C) 2013 ACK CYFRONET AGH
 * @copyright This software is released under the MIT license cited in 'LICENSE.txt'
 */

#include "fslogicProxy.h"

#include "communication_protocol.pb.h"
#include "communication/communicator.h"
#include "communication/exception.h"
#include "config.h"
#include "context.h"
#include "fuse_messages.pb.h"
#include "jobScheduler.h"
#include "logging.h"
#include "messageBuilder.h"
#include "options.h"
#include "veilErrors.h"
#include "veilfs.h"

#include <boost/algorithm/string.hpp>
#include <google/protobuf/descriptor.h>
#include <sys/types.h>
#include <unistd.h>

#include <fstream>
#include <string>

using namespace std;
using namespace boost::algorithm;
using namespace veil::protocol::communication_protocol;
using namespace veil::protocol::fuse_messages;

namespace veil {
namespace client {

FslogicProxy::FslogicProxy(std::weak_ptr<Context> context)
    : m_messageBuilder{std::make_shared<MessageBuilder>(context)}
    , m_context{std::move(context)}
{
    LOG(INFO) << "FslogicProxy created";
}

FslogicProxy::~FslogicProxy()
{
    LOG(INFO) << "FslogicProxy destroyed";
}

bool FslogicProxy::getFileAttr(const string& logicName, FileAttr& attr)
{
    LOG(INFO) << "getting attributes from cluster for file: " << logicName;

    GetFileAttr msg;
    msg.set_file_logic_name(logicName);

    if(!sendFuseReceiveAnswer(msg, attr))
    {
        LOG(ERROR) << "cannot parse cluster answer";
        return false;
    }

    return true;
}

bool FslogicProxy::getFileLocation(const string &logicName, FileLocation& location, const string &openMode, bool forceClusterProxy)
{
    LOG(INFO) << "getting file location from cluster for file: " << logicName;

    GetFileLocation msg;
    msg.set_file_logic_name(logicName);
    msg.set_open_mode(openMode);
    msg.set_force_cluster_proxy(forceClusterProxy);

    if(!sendFuseReceiveAnswer(msg, location))
    {
        LOG(ERROR) << "cannot parse cluster answer";
        return false;
    }

    return true;
}

bool FslogicProxy::getNewFileLocation(const string &logicName, mode_t mode, FileLocation& location, bool forceClusterProxy)
{
    LOG(INFO) << "getting new file location for file: " << logicName;

    GetNewFileLocation msg;
    msg.set_file_logic_name(logicName);
    msg.set_mode(mode);
    msg.set_force_cluster_proxy(forceClusterProxy);

    if(!sendFuseReceiveAnswer(msg, location))
    {
        LOG(ERROR) << "cannot parse cluster answer";
        return false;
    }

    return true;
}

string FslogicProxy::sendFileCreatedAck(const string &logicName)
{
    LOG(INFO) << "getting new file location for file: " << logicName;

    CreateFileAck msg;
    msg.set_file_logic_name(logicName);

    string serializedAnswer = sendFuseReceiveAtom(msg);

    return serializedAnswer;
}

int FslogicProxy::renewFileLocation(const string &logicName)
{
    LOG(INFO) << "renew file location for file: " << logicName;

    RenewFileLocation msg;
    FileLocationValidity locationValidity;
    msg.set_file_logic_name(logicName);

    if(!sendFuseReceiveAnswer(msg, locationValidity))
    {
        LOG(ERROR) << "cannot parse cluster answer";
        return -1;
    }

    if(locationValidity.answer() != VOK || !locationValidity.has_validity())
    {
        LOG(WARNING) << "cannot renew file location mapping. cluster answer: " << locationValidity.answer();
        return -1;
    }

    return locationValidity.validity();
}

bool FslogicProxy::getFileChildren(const string &dirLogicName, uint32_t children_num, uint32_t offset, vector<string>& childrenNames)
{
    LOG(INFO) << "getting file children for: " << dirLogicName;

    GetFileChildren msg;
    FileChildren children;
    msg.set_dir_logic_name(dirLogicName);
    msg.set_children_num(children_num);
    msg.set_offset(offset);

    if (!sendFuseReceiveAnswer(msg, children))
    {
        LOG(ERROR) << "cannot parse cluster answer";
        return false;
    }

    for(int i = 0; i < children.child_logic_name_size(); ++i)
    {
        childrenNames.push_back(children.child_logic_name(i));
    }

    return true;
}

string FslogicProxy::createDir(const string& logicName, mode_t mode)
{
    LOG(INFO) << "creaing dir: " << logicName;

    CreateDir msg;
    msg.set_dir_logic_name(logicName);
    msg.set_mode(mode);

    string serializedAnswer = sendFuseReceiveAtom(msg);

    return serializedAnswer;
}

string FslogicProxy::deleteFile(const string& logicName)
{
    DeleteFile msg;
    msg.set_file_logic_name(logicName);

    string serializedAnswer = sendFuseReceiveAtom(msg);

    return serializedAnswer;

}
bool FslogicProxy::sendFileNotUsed(const string& logicName)
{
    FileNotUsed msg;
    msg.set_file_logic_name(logicName);

    string serializedAnswer = sendFuseReceiveAtom(msg);

    if(serializedAnswer != VOK)
    {
        return false;
    }

    return true;
}

string FslogicProxy::renameFile(const string& fromLogicName, const string& toLogicName)
{
    RenameFile msg;
    msg.set_from_file_logic_name(fromLogicName);
    msg.set_to_file_logic_name(toLogicName);

    string serializedAnswer = sendFuseReceiveAtom(msg);

    return serializedAnswer;
}

string FslogicProxy::changeFilePerms(const string& path, mode_t mode)
{
    ChangeFilePerms msg;
    msg.set_file_logic_name(path);
    msg.set_perms(mode);

    string serializedAnswer = sendFuseReceiveAtom(msg);

    return serializedAnswer;
}

string FslogicProxy::updateTimes(const string& path, time_t atime, time_t mtime, time_t ctime)
{
    UpdateTimes msg;
    msg.set_file_logic_name(path);
    if(atime)
        msg.set_atime(atime);
    if(mtime)
        msg.set_mtime(mtime);
    if(ctime)
        msg.set_ctime(ctime);

    string serializedAnswer = sendFuseReceiveAtom(msg);

    return serializedAnswer;
}

string FslogicProxy::changeFileOwner(const string& path, uid_t uid, const string& uname)
{
    ChangeFileOwner msg;
    msg.set_file_logic_name(path);
    msg.set_uid(uid);
    if(uname.size() > 0)
        msg.set_uname(uname);

    string serializedAnswer = sendFuseReceiveAtom(msg);

    return serializedAnswer;
}

string FslogicProxy::changeFileGroup(const string& path, gid_t gid, const string& gname)
{
    ChangeFileGroup msg;
    msg.set_file_logic_name(path);
    msg.set_gid(gid);
    if(gname.size() > 0)
        msg.set_gname(gname);

    string serializedAnswer = sendFuseReceiveAtom(msg);

    return serializedAnswer;
}

string FslogicProxy::createLink(const string& from, const string& to)
{
    CreateLink msg;
    msg.set_from_file_logic_name(from);
    msg.set_to_file_logic_name(to);

    string serializedAnswer = sendFuseReceiveAtom(msg);

    return serializedAnswer;
}

pair<string, string> FslogicProxy::getLink(const string& path)
{
    GetLink msg;
    LinkInfo answer;
    msg.set_file_logic_name(path);

    if(!sendFuseReceiveAnswer(msg, answer))
    {
        LOG(ERROR) << "cannot parse cluster answer";
        return make_pair(VEIO, "");
    }

    return make_pair(answer.answer(), answer.file_logic_name());
}

template<typename Ans>
bool FslogicProxy::sendFuseReceiveAnswer(const google::protobuf::Message &fMsg, Ans &response)
{
    if(!fMsg.IsInitialized())
    {
        LOG(ERROR) << "Message with type: " << fMsg.GetDescriptor()->name() << " is not initialized";
        return false;
    }

    auto fuseMsg = m_messageBuilder->createFuseMessage(m_context.lock()->getConfig()->getFuseID(),
                                                       fMsg.GetDescriptor()->name(),
                                                       fMsg.SerializeAsString());

    auto communicator = m_context.lock()->getCommunicator();
    try
    {
        LOG(INFO) << "Sending message (type: " << fMsg.GetDescriptor()->name() << "). Expecting answer with type: " << response.GetDescriptor()->name();

        auto answer = communicator->communicate<Ans>(communication::ServerModule::FSLOGIC, fuseMsg, 2);

        if(answer->answer_status() != VOK)
        {
            LOG(WARNING) << "Cluster send non-ok message. status = " << answer->answer_status();
            if(answer->answer_status() == INVALID_FUSE_ID)
                m_context.lock()->getConfig()->negotiateFuseID(0);
            return false;
        }

        return response.ParseFromString(answer->worker_answer());
    }
    catch(communication::Exception &e)
    {
        LOG(ERROR) << "Cannot select connection from connectionPool: " << e.what();
        return false;
    }
}

string FslogicProxy::sendFuseReceiveAtom(const google::protobuf::Message& fMsg)
{
    if(!fMsg.IsInitialized())
    {
        LOG(ERROR) << "Message with type: " << fMsg.GetDescriptor()->name() << " is not initialized";
        return VEIO;
    }

    auto fuseMsg = m_messageBuilder->createFuseMessage(m_context.lock()->getConfig()->getFuseID(),
                                                       fMsg.GetDescriptor()->name(),
                                                       fMsg.SerializeAsString());

    auto communicator = m_context.lock()->getCommunicator();
    try
    {
        LOG(INFO) << "Sending message (type: " << fMsg.GetDescriptor()->name() << "). Expecting answer with type: atom";

        auto answer = communicator->communicate<>(communication::ServerModule::FSLOGIC, fuseMsg, 2);

        if(answer->answer_status() == INVALID_FUSE_ID)
            m_context.lock()->getConfig()->negotiateFuseID(0);

        std::string atom = m_messageBuilder->decodeAtomAnswer(*answer);

        if(atom.size() == 0)
        {
            LOG(ERROR) << "Cannot parse cluster atom answer";
            return VEIO;
        }

        return atom;
    }
    catch(communication::Exception &e)
    {
        LOG(ERROR) << "Cannot select connection from connectionPool: " << e.what();
        return VEIO;
    }
}

pair<string, struct statvfs> FslogicProxy::getStatFS()
{
   GetStatFS msg;
   StatFSInfo answer;
   struct statvfs statFS;

   if(!sendFuseReceiveAnswer(msg, answer))
    {
        LOG(ERROR) << "cannot parse cluster answer";
        return make_pair(VEIO, statFS);
    }

    statFS.f_bsize      = 4096;
    statFS.f_frsize     = 4096;
    statFS.f_blocks     = answer.quota_size() / statFS.f_frsize;                          /* size of fs in f_frsize units */
    statFS.f_bfree      = (answer.quota_size() - answer.files_size()) / statFS.f_frsize;  /* # free blocks */
    statFS.f_bavail     = (answer.quota_size() - answer.files_size()) / statFS.f_frsize;  /* # free blocks for unprivileged users */
    statFS.f_files      = 10000;                                                          /* # inodes */
    statFS.f_ffree      = 10000;                                                          /* # free inodes */
    statFS.f_favail     = 10000;                                                          /* # free inodes for unprivileged users */
    statFS.f_fsid       = 0;                                                              /* file system ID */
    statFS.f_flag       = 0;
    statFS.f_namemax    = NAME_MAX;

    return make_pair(answer.answer(), statFS);
}

void FslogicProxy::pingCluster(const string &nth)
{
    auto communicator = m_context.lock()->getCommunicator();
    try
{
    Atom ping;
    ping.set_value("ping");
        auto answer = communicator->communicate<>(communication::ServerModule::FSLOGIC, ping);

        if(answer->answer_status() == VEIO)
            LOG(WARNING) << "Pinging cluster failed";
        else
            LOG(INFO) << "Cluster ping... ---> " << answer->answer_status();
    }
    catch(communication::Exception &e)
    {
        LOG(ERROR) << "Cluster ping failed: " << e.what();
    }

    // Send another...
    Job pingTask = Job(time(NULL) + m_context.lock()->getOptions()->get_cluster_ping_interval(), shared_from_this(), ISchedulable::TASK_PING_CLUSTER, nth);
    m_context.lock()->getScheduler(ISchedulable::TASK_PING_CLUSTER)->addTask(pingTask);
}

bool FslogicProxy::runTask(TaskID taskId, const string& arg0, const string&, const string&)
{
    string res;
    switch(taskId)
    {
    case TASK_SEND_FILE_NOT_USED:
        res = sendFileNotUsed(arg0);
        LOG(INFO) << "FUSE sendFileNotUsed for file: " << arg0 << ", response: " << res;
        return true;
    case TASK_PING_CLUSTER:
        pingCluster(arg0);
        return true;
    default:
        return false;
    }
}

} // namespace client
} // namespace veil
<commit_msg>VFS-749: fix whitespaces<commit_after>/**
 * @file fslogicProxy.cc
 * @author Beata Skiba
 * @author Rafal Slota
 * @copyright (C) 2013 ACK CYFRONET AGH
 * @copyright This software is released under the MIT license cited in 'LICENSE.txt'
 */

#include "fslogicProxy.h"

#include "communication_protocol.pb.h"
#include "communication/communicator.h"
#include "communication/exception.h"
#include "config.h"
#include "context.h"
#include "fuse_messages.pb.h"
#include "jobScheduler.h"
#include "logging.h"
#include "messageBuilder.h"
#include "options.h"
#include "veilErrors.h"
#include "veilfs.h"

#include <boost/algorithm/string.hpp>
#include <google/protobuf/descriptor.h>
#include <sys/types.h>
#include <unistd.h>

#include <fstream>
#include <string>

using namespace std;
using namespace boost::algorithm;
using namespace veil::protocol::communication_protocol;
using namespace veil::protocol::fuse_messages;

namespace veil {
namespace client {

FslogicProxy::FslogicProxy(std::weak_ptr<Context> context)
    : m_messageBuilder{std::make_shared<MessageBuilder>(context)}
    , m_context{std::move(context)}
{
    LOG(INFO) << "FslogicProxy created";
}

FslogicProxy::~FslogicProxy()
{
    LOG(INFO) << "FslogicProxy destroyed";
}

bool FslogicProxy::getFileAttr(const string& logicName, FileAttr& attr)
{
    LOG(INFO) << "getting attributes from cluster for file: " << logicName;

    GetFileAttr msg;
    msg.set_file_logic_name(logicName);

    if(!sendFuseReceiveAnswer(msg, attr))
    {
        LOG(ERROR) << "cannot parse cluster answer";
        return false;
    }

    return true;
}

bool FslogicProxy::getFileLocation(const string &logicName, FileLocation& location, const string &openMode, bool forceClusterProxy)
{
    LOG(INFO) << "getting file location from cluster for file: " << logicName;

    GetFileLocation msg;
    msg.set_file_logic_name(logicName);
    msg.set_open_mode(openMode);
    msg.set_force_cluster_proxy(forceClusterProxy);

    if(!sendFuseReceiveAnswer(msg, location))
    {
        LOG(ERROR) << "cannot parse cluster answer";
        return false;
    }

    return true;
}

bool FslogicProxy::getNewFileLocation(const string &logicName, mode_t mode, FileLocation& location, bool forceClusterProxy)
{
    LOG(INFO) << "getting new file location for file: " << logicName;

    GetNewFileLocation msg;
    msg.set_file_logic_name(logicName);
    msg.set_mode(mode);
    msg.set_force_cluster_proxy(forceClusterProxy);

    if(!sendFuseReceiveAnswer(msg, location))
    {
        LOG(ERROR) << "cannot parse cluster answer";
        return false;
    }

    return true;
}

string FslogicProxy::sendFileCreatedAck(const string &logicName)
{
    LOG(INFO) << "getting new file location for file: " << logicName;

    CreateFileAck msg;
    msg.set_file_logic_name(logicName);

    string serializedAnswer = sendFuseReceiveAtom(msg);

    return serializedAnswer;
}

int FslogicProxy::renewFileLocation(const string &logicName)
{
    LOG(INFO) << "renew file location for file: " << logicName;

    RenewFileLocation msg;
    FileLocationValidity locationValidity;
    msg.set_file_logic_name(logicName);

    if(!sendFuseReceiveAnswer(msg, locationValidity))
    {
        LOG(ERROR) << "cannot parse cluster answer";
        return -1;
    }

    if(locationValidity.answer() != VOK || !locationValidity.has_validity())
    {
        LOG(WARNING) << "cannot renew file location mapping. cluster answer: " << locationValidity.answer();
        return -1;
    }

    return locationValidity.validity();
}

bool FslogicProxy::getFileChildren(const string &dirLogicName, uint32_t children_num, uint32_t offset, vector<string>& childrenNames)
{
    LOG(INFO) << "getting file children for: " << dirLogicName;

    GetFileChildren msg;
    FileChildren children;
    msg.set_dir_logic_name(dirLogicName);
    msg.set_children_num(children_num);
    msg.set_offset(offset);

    if (!sendFuseReceiveAnswer(msg, children))
    {
        LOG(ERROR) << "cannot parse cluster answer";
        return false;
    }

    for(int i = 0; i < children.child_logic_name_size(); ++i)
    {
        childrenNames.push_back(children.child_logic_name(i));
    }

    return true;
}

string FslogicProxy::createDir(const string& logicName, mode_t mode)
{
    LOG(INFO) << "creaing dir: " << logicName;

    CreateDir msg;
    msg.set_dir_logic_name(logicName);
    msg.set_mode(mode);

    string serializedAnswer = sendFuseReceiveAtom(msg);

    return serializedAnswer;
}

string FslogicProxy::deleteFile(const string& logicName)
{
    DeleteFile msg;
    msg.set_file_logic_name(logicName);

    string serializedAnswer = sendFuseReceiveAtom(msg);

    return serializedAnswer;

}
bool FslogicProxy::sendFileNotUsed(const string& logicName)
{
    FileNotUsed msg;
    msg.set_file_logic_name(logicName);

    string serializedAnswer = sendFuseReceiveAtom(msg);

    if(serializedAnswer != VOK)
    {
        return false;
    }

    return true;
}

string FslogicProxy::renameFile(const string& fromLogicName, const string& toLogicName)
{
    RenameFile msg;
    msg.set_from_file_logic_name(fromLogicName);
    msg.set_to_file_logic_name(toLogicName);

    string serializedAnswer = sendFuseReceiveAtom(msg);

    return serializedAnswer;
}

string FslogicProxy::changeFilePerms(const string& path, mode_t mode)
{
    ChangeFilePerms msg;
    msg.set_file_logic_name(path);
    msg.set_perms(mode);

    string serializedAnswer = sendFuseReceiveAtom(msg);

    return serializedAnswer;
}

string FslogicProxy::updateTimes(const string& path, time_t atime, time_t mtime, time_t ctime)
{
    UpdateTimes msg;
    msg.set_file_logic_name(path);
    if(atime)
        msg.set_atime(atime);
    if(mtime)
        msg.set_mtime(mtime);
    if(ctime)
        msg.set_ctime(ctime);

    string serializedAnswer = sendFuseReceiveAtom(msg);

    return serializedAnswer;
}

string FslogicProxy::changeFileOwner(const string& path, uid_t uid, const string& uname)
{
    ChangeFileOwner msg;
    msg.set_file_logic_name(path);
    msg.set_uid(uid);
    if(uname.size() > 0)
        msg.set_uname(uname);

    string serializedAnswer = sendFuseReceiveAtom(msg);

    return serializedAnswer;
}

string FslogicProxy::changeFileGroup(const string& path, gid_t gid, const string& gname)
{
    ChangeFileGroup msg;
    msg.set_file_logic_name(path);
    msg.set_gid(gid);
    if(gname.size() > 0)
        msg.set_gname(gname);

    string serializedAnswer = sendFuseReceiveAtom(msg);

    return serializedAnswer;
}

string FslogicProxy::createLink(const string& from, const string& to)
{
    CreateLink msg;
    msg.set_from_file_logic_name(from);
    msg.set_to_file_logic_name(to);

    string serializedAnswer = sendFuseReceiveAtom(msg);

    return serializedAnswer;
}

pair<string, string> FslogicProxy::getLink(const string& path)
{
    GetLink msg;
    LinkInfo answer;
    msg.set_file_logic_name(path);

    if(!sendFuseReceiveAnswer(msg, answer))
    {
        LOG(ERROR) << "cannot parse cluster answer";
        return make_pair(VEIO, "");
    }

    return make_pair(answer.answer(), answer.file_logic_name());
}

template<typename Ans>
bool FslogicProxy::sendFuseReceiveAnswer(const google::protobuf::Message &fMsg, Ans &response)
{
    if(!fMsg.IsInitialized())
    {
        LOG(ERROR) << "Message with type: " << fMsg.GetDescriptor()->name() << " is not initialized";
        return false;
    }

    auto fuseMsg = m_messageBuilder->createFuseMessage(m_context.lock()->getConfig()->getFuseID(),
                                                       fMsg.GetDescriptor()->name(),
                                                       fMsg.SerializeAsString());

    auto communicator = m_context.lock()->getCommunicator();
    try
    {
        LOG(INFO) << "Sending message (type: " << fMsg.GetDescriptor()->name() << "). Expecting answer with type: " << response.GetDescriptor()->name();

        auto answer = communicator->communicate<Ans>(communication::ServerModule::FSLOGIC, fuseMsg, 2);

        if(answer->answer_status() != VOK)
        {
            LOG(WARNING) << "Cluster send non-ok message. status = " << answer->answer_status();
            if(answer->answer_status() == INVALID_FUSE_ID)
                m_context.lock()->getConfig()->negotiateFuseID(0);
            return false;
        }

        return response.ParseFromString(answer->worker_answer());
    }
    catch(communication::Exception &e)
    {
        LOG(ERROR) << "Cannot select connection from connectionPool: " << e.what();
        return false;
    }
}

string FslogicProxy::sendFuseReceiveAtom(const google::protobuf::Message& fMsg)
{
    if(!fMsg.IsInitialized())
    {
        LOG(ERROR) << "Message with type: " << fMsg.GetDescriptor()->name() << " is not initialized";
        return VEIO;
    }

    auto fuseMsg = m_messageBuilder->createFuseMessage(m_context.lock()->getConfig()->getFuseID(),
                                                       fMsg.GetDescriptor()->name(),
                                                       fMsg.SerializeAsString());

    auto communicator = m_context.lock()->getCommunicator();
    try
    {
        LOG(INFO) << "Sending message (type: " << fMsg.GetDescriptor()->name() << "). Expecting answer with type: atom";

        auto answer = communicator->communicate<>(communication::ServerModule::FSLOGIC, fuseMsg, 2);

        if(answer->answer_status() == INVALID_FUSE_ID)
            m_context.lock()->getConfig()->negotiateFuseID(0);

        std::string atom = m_messageBuilder->decodeAtomAnswer(*answer);

        if(atom.size() == 0)
        {
            LOG(ERROR) << "Cannot parse cluster atom answer";
            return VEIO;
        }

        return atom;
    }
    catch(communication::Exception &e)
    {
        LOG(ERROR) << "Cannot select connection from connectionPool: " << e.what();
        return VEIO;
    }
}

pair<string, struct statvfs> FslogicProxy::getStatFS()
{
   GetStatFS msg;
   StatFSInfo answer;
   struct statvfs statFS;

   if(!sendFuseReceiveAnswer(msg, answer))
    {
        LOG(ERROR) << "cannot parse cluster answer";
        return make_pair(VEIO, statFS);
    }

    statFS.f_bsize      = 4096;
    statFS.f_frsize     = 4096;
    statFS.f_blocks     = answer.quota_size() / statFS.f_frsize;                          /* size of fs in f_frsize units */
    statFS.f_bfree      = (answer.quota_size() - answer.files_size()) / statFS.f_frsize;  /* # free blocks */
    statFS.f_bavail     = (answer.quota_size() - answer.files_size()) / statFS.f_frsize;  /* # free blocks for unprivileged users */
    statFS.f_files      = 10000;                                                          /* # inodes */
    statFS.f_ffree      = 10000;                                                          /* # free inodes */
    statFS.f_favail     = 10000;                                                          /* # free inodes for unprivileged users */
    statFS.f_fsid       = 0;                                                              /* file system ID */
    statFS.f_flag       = 0;
    statFS.f_namemax    = NAME_MAX;

    return make_pair(answer.answer(), statFS);
}

void FslogicProxy::pingCluster(const string &nth)
{
    auto communicator = m_context.lock()->getCommunicator();
    try
    {
        Atom ping;
        ping.set_value("ping");
        auto answer = communicator->communicate<>(communication::ServerModule::FSLOGIC, ping);

        if(answer->answer_status() == VEIO)
            LOG(WARNING) << "Pinging cluster failed";
        else
            LOG(INFO) << "Cluster ping... ---> " << answer->answer_status();
    }
    catch(communication::Exception &e)
    {
        LOG(ERROR) << "Cluster ping failed: " << e.what();
    }

    // Send another...
    Job pingTask = Job(time(NULL) + m_context.lock()->getOptions()->get_cluster_ping_interval(), shared_from_this(), ISchedulable::TASK_PING_CLUSTER, nth);
    m_context.lock()->getScheduler(ISchedulable::TASK_PING_CLUSTER)->addTask(pingTask);
}

bool FslogicProxy::runTask(TaskID taskId, const string& arg0, const string&, const string&)
{
    string res;
    switch(taskId)
    {
    case TASK_SEND_FILE_NOT_USED:
        res = sendFileNotUsed(arg0);
        LOG(INFO) << "FUSE sendFileNotUsed for file: " << arg0 << ", response: " << res;
        return true;
    case TASK_PING_CLUSTER:
        pingCluster(arg0);
        return true;
    default:
        return false;
    }
}

} // namespace client
} // namespace veil
<|endoftext|>