<commit_before>#include "stdafx.h"
#include "Symbols.h"

#include <fstream>

Symbols::Symbols( ) :
    m_bInitialized( FALSE )
{
    ResolveSearchPath( );

    if (!WriteSymSrvDll( ))
        throw std::exception( "WriteSymSrvDll_failed" );

    if (!Init( ))
        throw std::exception( "init_failed" );

    ntdll::RtlInitializeCriticalSection( &m_CriticalSection );
}

Symbols::~Symbols( )
{
    ntdll::RtlDeleteCriticalSection( &m_CriticalSection );

    Cleanup( );
    DeleteFile( _T( "symsrv.dll" ) );
}

void Symbols::ResolveSearchPath( )
{
    CString searchPath;
    LRESULT lRet;
    HKEY hKey = NULL;

    //C:\Users\User\AppData\Local\Temp\SymbolCache
    for (int i = 14; i >= 8; i--)
    {
        CString regPath = _T( "Software\\Microsoft\\VisualStudio\\" );
        wchar_t version[4];
        _itow_s( i, version, 10 );

        #ifdef UNICODE
        regPath.Append( version );
        #else
        regPath.Append( CW2A( version ) );
        #endif

        regPath.Append( _T( ".0\\Debugger" ) );

        lRet = RegOpenKeyEx( HKEY_CURRENT_USER, regPath.GetString( ), 0, KEY_READ, &hKey );
        if (hKey)
        {
            TCHAR szBuffer[MAX_PATH];
            DWORD dwBufferSize = MAX_PATH;
            lRet = RegQueryValueEx( hKey, _T( "SymbolCacheDir" ), 0, NULL, (LPBYTE)szBuffer, &dwBufferSize );
            if (lRet == ERROR_SUCCESS && szBuffer)
            {
                searchPath = szBuffer;
                RegCloseKey( hKey );
                break;
            }
            RegCloseKey( hKey );
        }
    }

    if (!searchPath.IsEmpty( ))
    {
        m_strSearchPath.Format( _T( "srv*%s*http://msdl.microsoft.com/download/symbols" ), searchPath.GetString( ) );
        PrintOut( _T( "Symbol server path found from Visual Studio config: %s" ), searchPath.GetString( ) );
    }
    else
    {
        TCHAR szWindowsDir[MAX_PATH];
        GetCurrentDirectory( MAX_PATH, szWindowsDir );
        m_strSearchPath.Format( _T( "srv*%s\\symbols*http://msdl.microsoft.com/download/symbols" ), szWindowsDir );
        PrintOut( _T( "Symbol server path not found, using windows dir: %s" ), szWindowsDir );
    }
}

BOOLEAN Symbols::WriteSymSrvDll( )
{
    HRSRC hSymSrvRes = NULL;
    HGLOBAL hGlobal = NULL;
    LPVOID pSymSrvData = NULL;
    DWORD dwSymSrvDataSize = 0;

    #ifdef _WIN64
    hSymSrvRes = FindResource( NULL, MAKEINTRESOURCE( IDR_RCDATA_SYMSRV64 ), RT_RCDATA );
    #else
    hSymSrvRes = FindResource( NULL, MAKEINTRESOURCE( IDR_RCDATA_SYMSRV32 ), RT_RCDATA );
    #endif
    if (hSymSrvRes != NULL)
    {
        hGlobal = LoadResource( NULL, hSymSrvRes );
        if (hGlobal != NULL)
        {
            pSymSrvData = LockResource( hGlobal );
            dwSymSrvDataSize = SizeofResource( NULL, hSymSrvRes );
            if (pSymSrvData != NULL)
            {
                std::ofstream fSymSrvDll( _T( "symsrv.dll" ), std::ios::binary );
                if (fSymSrvDll)
                {
                    fSymSrvDll.write( (const char*)pSymSrvData, dwSymSrvDataSize );
                    fSymSrvDll.close( );

                    UnlockResource( hGlobal );
                    FreeResource( hGlobal );

                    return TRUE;
                }
            }
        }

        UnlockResource( hGlobal );
        FreeResource( hGlobal );
    }

    return FALSE;
}

void Symbols::Cleanup( )
{
    if (m_bInitialized == TRUE)
    {
        for (auto it = m_SymbolAddresses.begin( ); it != m_SymbolAddresses.end( ); ++it)
            delete it->second;
        m_SymbolAddresses.clear( );

        for (auto it = m_SymbolNames.begin( ); it != m_SymbolNames.end( ); ++it)
            delete it->second;
        m_SymbolNames.clear( );

        CoUninitialize( );

        m_bInitialized = FALSE;
    }
}

BOOLEAN Symbols::Init( )
{
    if (m_bInitialized == FALSE)
    {
        HRESULT hr = S_OK;
        hr = CoInitialize( NULL );
        if (FAILED( hr ))
        {
            PrintOut( _T( "[Symbols::Init] CoInitialize failed - HRESULT = %08X" ), hr );
            return FALSE;
        }
        m_bInitialized = TRUE;
    }
    return TRUE;
}

BOOLEAN Symbols::LoadSymbolsForModule( CString ModulePath, ULONG_PTR ModuleBaseAddress, ULONG SizeOfModule )
{
    int idx = -1;
    CString ModuleName;
    const TCHAR* szSearchPath = NULL;
    SymbolReader* reader = NULL;
    BOOLEAN bSucc = FALSE;

    idx = ModulePath.ReverseFind( '/' );
    if (idx == -1)
        idx = ModulePath.ReverseFind( '\\' );
    ModuleName = ModulePath.Mid( ++idx );

    if (!m_strSearchPath.IsEmpty( ))
        szSearchPath = m_strSearchPath.GetString( );

    reader = new SymbolReader( );

    //ntdll::RtlEnterCriticalSection( &m_CriticalSection );

    bSucc = reader->LoadFile( ModuleName, ModulePath, ModuleBaseAddress, SizeOfModule, szSearchPath );

    //ntdll::RtlLeaveCriticalSection( &m_CriticalSection );

    if (bSucc)
    {
        PrintOut( _T( "[Symbols::LoadSymbolsForModule] Symbols for module %s loaded" ), ModuleName.GetString( ) );
        m_SymbolAddresses.insert( std::make_pair( ModuleBaseAddress, reader ) );
        return TRUE;
    }

    delete reader;

    return FALSE;
}

BOOLEAN Symbols::LoadSymbolsForPdb( CString PdbPath )
{
    int idx = -1;
    CString PdbFileName;
    const TCHAR* szSearchPath = NULL;
    SymbolReader* reader = NULL;
    BOOLEAN bSucc = FALSE;

    idx = PdbPath.ReverseFind( '/' );
    if (idx == -1)
        idx = PdbPath.ReverseFind( '\\' );
    PdbFileName = PdbPath.Mid( ++idx );

    if (!m_strSearchPath.IsEmpty( ))
        szSearchPath = m_strSearchPath.GetString( );

    reader = new SymbolReader( );

    ntdll::RtlEnterCriticalSection( &m_CriticalSection );

    bSucc = reader->LoadFile( PdbFileName, PdbPath, 0, 0, szSearchPath );

    ntdll::RtlLeaveCriticalSection( &m_CriticalSection );

    if (bSucc)
    {
        PrintOut( _T( "[Symbols::LoadSymbolsForPdb] Symbols for module %s loaded" ), PdbFileName.GetString( ) );
        m_SymbolNames.insert( std::make_pair( PdbFileName, reader ) );
        return TRUE;
    }

    delete reader;

    return FALSE;
}

//void Symbols::LoadModuleSymbols()
//{
//	PPROCESS_BASIC_INFORMATION pbi = NULL;
//	PEB peb;
//	PEB_LDR_DATA peb_ldr;
//
//	// Try to allocate buffer
//	HANDLE	hHeap = GetProcessHeap();
//	DWORD dwSize = sizeof(PROCESS_BASIC_INFORMATION);
//	pbi = (PPROCESS_BASIC_INFORMATION)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwSize);
//
//	ULONG dwSizeNeeded = 0;
//	NTSTATUS dwStatus = ntdll::NtQueryInformationProcess(g_hProcess, ProcessBasicInformation, pbi, dwSize, &dwSizeNeeded);
//	if (NT_SUCCESS(dwStatus) && dwSize < dwSizeNeeded)
//	{
//		if (pbi)
//			HeapFree(hHeap, 0, pbi);
//
//		pbi = (PPROCESS_BASIC_INFORMATION)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwSizeNeeded);
//		if (!pbi) {
//			_tprintf(_T("[LoadModuleSymbols] Couldn't allocate heap buffer!\n"));
//			return;
//		}
//
//		dwStatus = ntdll::NtQueryInformationProcess(g_hProcess, ProcessBasicInformation, pbi, dwSizeNeeded, &dwSizeNeeded);
//	}
//
//	// Did we successfully get basic info on process
//	if (NT_SUCCESS(dwStatus))
//	{
//		// Read Process Environment Block (PEB)
//		if (pbi->PebBaseAddress)
//		{
//			SIZE_T dwBytesRead = 0;
//			if (ReClassReadMemory(pbi->PebBaseAddress, &peb, sizeof(peb), &dwBytesRead))
//			{
//				dwBytesRead = 0;
//				if (ReClassReadMemory(peb.Ldr, &peb_ldr, sizeof(peb_ldr), &dwBytesRead))
//				{
//					ULONG numOfEntries = peb_ldr.Length;
//					ULONG currentEntryNum = 0;
//					LIST_ENTRY *pLdrListHead = (LIST_ENTRY *)peb_ldr.InMemoryOrderModuleList.Flink;
//					LIST_ENTRY *pLdrCurrentNode = peb_ldr.InMemoryOrderModuleList.Flink;
//					do
//					{
//						LDR_DATA_TABLE_ENTRY lstEntry = { 0 };
//						dwBytesRead = 0;
//						if (!ReClassReadMemory((LPVOID)pLdrCurrentNode, &lstEntry, sizeof(LDR_DATA_TABLE_ENTRY), &dwBytesRead))
//						{
//							_tprintf(_T("[LoadModuleSymbols] Could not read list entry from LDR list. Error: %s\n"), Utils::GetLastErrorAsString().c_str());
//							if (pbi)
//								HeapFree(hHeap, 0, pbi);
//							return;
//						}
//
//						pLdrCurrentNode = lstEntry.InLoadOrderLinks.Flink;
//
//						wchar_t wcsFullDllName[MAX_PATH] = { 0 };
//						if (lstEntry.FullDllName.Buffer && lstEntry.FullDllName.Length > 0)
//						{
//							dwBytesRead = 0;
//							if (!ReClassReadMemory((LPVOID)lstEntry.FullDllName.Buffer, &wcsFullDllName, lstEntry.FullDllName.Length, &dwBytesRead))
//							{
//								_tprintf(_T("[LoadModuleSymbols] Could not read list entry DLL name. Error: %s\n"), Utils::GetLastErrorAsString().c_str());
//								if (pbi)
//									HeapFree(hHeap, 0, pbi);
//								return;
//							}
//						}
//
//						if (lstEntry.DllBase != 0 && lstEntry.SizeOfImage != 0)
//						{
//							if (LoadSymbolsForModule(wcsFullDllName, (size_t)lstEntry.DllBase, lstEntry.SizeOfImage)) {
//								PrintOut(_T("Symbol module %ls loaded"), wcsFullDllName);
//							}
//							currentEntryNum++;
//							float progress = ((float)currentEntryNum / (float)numOfEntries) * 100;
//							printf("[%d/%d] progress: %f\n", currentEntryNum, numOfEntries, progress);
//						}
//					} while (pLdrListHead != pLdrCurrentNode);
//
//				} // Get Ldr
//			} // Read PEB
//		} // Check for PEB
//	}
//
//	if (pbi)
//		HeapFree(hHeap, 0, pbi);
//}

SymbolReader* Symbols::GetSymbolsForModuleAddress( ULONG_PTR ModuleAddress )
{
    SymbolReader* script = NULL;
    auto iter = m_SymbolAddresses.find( ModuleAddress );
    if (iter != m_SymbolAddresses.end( ))
        script = iter->second;
    return script;
}

SymbolReader* Symbols::GetSymbolsForModuleName( CString ModuleName )
{
    SymbolReader* script = NULL;
    auto iter = m_SymbolNames.find( ModuleName );
    if (iter != m_SymbolNames.end( ))
        script = iter->second;
    return script;
}

typedef void*( CDECL * Alloc_t )(unsigned int);
typedef void( CDECL * Free_t )(void *);
typedef PCHAR( CDECL *PUNDNAME )(char *, const char *, int, Alloc_t, Free_t, unsigned short);

void *CDECL AllocIt( unsigned int cb ) { return HeapAlloc( GetProcessHeap( ), 0, cb ); }
void CDECL FreeIt( void * p ) { HeapFree( GetProcessHeap( ), 0, p ); }

DWORD
WINAPI
UndecorateSymbolName(
    LPCSTR name,
    LPSTR outputString,
    DWORD maxStringLength,
    DWORD flags
)
{
    static HMODULE hMsvcrt = NULL;
    static PUNDNAME pfUnDname = NULL;

    DWORD rc;

    if (!hMsvcrt)
    {
        hMsvcrt = (HMODULE)Utils::GetLocalModuleBase( _T( "msvcrt.dll" ) );
        if (hMsvcrt)
            pfUnDname = (PUNDNAME)Utils::GetLocalProcAddress( hMsvcrt, _T( "__unDName" ) );
    }

    rc = 0;

    if (pfUnDname)
    {
        if (name && outputString && maxStringLength >= 2)
        {
            if (pfUnDname( outputString, name, maxStringLength - 1, AllocIt, FreeIt, (USHORT)flags ))
            {
                rc = strlen( outputString );
            }
        }
    }
    else
    {
        strncpy_s( outputString, maxStringLength, "Unable to load msvcrt!__unDName", maxStringLength );
        rc = strlen( outputString );
        SetLastError( ERROR_MOD_NOT_FOUND );
    }

    if (!rc)
        SetLastError( ERROR_INVALID_PARAMETER );

    return rc;
}

DWORD
WINAPI
UndecorateSymbolNameUnicode(
    LPCWSTR name,
    LPWSTR outputString,
    DWORD maxStringLength,
    DWORD flags
)
{
    LPSTR AnsiName;
    LPSTR AnsiOutputString;
    int AnsiNameLength;
    DWORD rc;

    AnsiNameLength = WideCharToMultiByte( CP_ACP, WC_COMPOSITECHECK | WC_SEPCHARS, name, -1, NULL, 0, NULL, NULL );
    if (!AnsiNameLength)
        return 0;

    AnsiName = (char *)AllocIt( AnsiNameLength );
    if (!AnsiName)
    {
        SetLastError( ERROR_NOT_ENOUGH_MEMORY );
        return 0;
    }

    ZeroMemory( AnsiName, AnsiNameLength );
    if (!WideCharToMultiByte( CP_ACP, WC_COMPOSITECHECK | WC_SEPCHARS, name, -1, AnsiName, AnsiNameLength, NULL, NULL ))
    {
        FreeIt( AnsiName );
        return 0;
    }

    AnsiOutputString = (LPSTR)AllocIt( maxStringLength + 1 );
    if (!AnsiOutputString)
    {
        FreeIt( AnsiName );
        SetLastError( ERROR_NOT_ENOUGH_MEMORY );
        return 0;
    }

    *AnsiOutputString = '\0';
    rc = UndecorateSymbolName( AnsiName, AnsiOutputString, maxStringLength, flags );
    MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, AnsiOutputString, -1, outputString, maxStringLength );

    FreeIt( AnsiName );
    FreeIt( AnsiOutputString );

    return rc;
}

<commit_msg>Fix for warning<commit_after>#include "stdafx.h"
#include "Symbols.h"

#include <fstream>

Symbols::Symbols( ) :
    m_bInitialized( FALSE )
{
    ResolveSearchPath( );

    if (!WriteSymSrvDll( ))
        throw std::exception( "WriteSymSrvDll_failed" );

    if (!Init( ))
        throw std::exception( "init_failed" );

    ntdll::RtlInitializeCriticalSection( &m_CriticalSection );
}

Symbols::~Symbols( )
{
    ntdll::RtlDeleteCriticalSection( &m_CriticalSection );

    Cleanup( );
    DeleteFile( _T( "symsrv.dll" ) );
}

void Symbols::ResolveSearchPath( )
{
    CString searchPath;
    LRESULT lRet;
    HKEY hKey = NULL;

    //C:\Users\User\AppData\Local\Temp\SymbolCache
    for (int i = 14; i >= 8; i--)
    {
        CString regPath = _T( "Software\\Microsoft\\VisualStudio\\" );
        wchar_t version[4];
        _itow_s( i, version, 10 );

        #ifdef UNICODE
        regPath.Append( version );
        #else
        regPath.Append( CW2A( version ) );
        #endif

        regPath.Append( _T( ".0\\Debugger" ) );

        lRet = RegOpenKeyEx( HKEY_CURRENT_USER, regPath.GetString( ), 0, KEY_READ, &hKey );
        if (hKey)
        {
            TCHAR szBuffer[MAX_PATH];
            DWORD dwBufferSize = MAX_PATH;
            lRet = RegQueryValueEx( hKey, _T( "SymbolCacheDir" ), 0, NULL, (LPBYTE)szBuffer, &dwBufferSize );
            if (lRet == ERROR_SUCCESS && szBuffer)
            {
                searchPath = szBuffer;
                RegCloseKey( hKey );
                break;
            }
            RegCloseKey( hKey );
        }
    }

    if (!searchPath.IsEmpty( ))
    {
        m_strSearchPath.Format( _T( "srv*%s*http://msdl.microsoft.com/download/symbols" ), searchPath.GetString( ) );
        PrintOut( _T( "Symbol server path found from Visual Studio config: %s" ), searchPath.GetString( ) );
    }
    else
    {
        TCHAR szWindowsDir[MAX_PATH];
        GetCurrentDirectory( MAX_PATH, szWindowsDir );
        m_strSearchPath.Format( _T( "srv*%s\\symbols*http://msdl.microsoft.com/download/symbols" ), szWindowsDir );
        PrintOut( _T( "Symbol server path not found, using windows dir: %s" ), szWindowsDir );
    }
}

BOOLEAN Symbols::WriteSymSrvDll( )
{
    HRSRC hSymSrvRes = NULL;
    HGLOBAL hGlobal = NULL;
    LPVOID pSymSrvData = NULL;
    DWORD dwSymSrvDataSize = 0;

    #ifdef _WIN64
    hSymSrvRes = FindResource( NULL, MAKEINTRESOURCE( IDR_RCDATA_SYMSRV64 ), RT_RCDATA );
    #else
    hSymSrvRes = FindResource( NULL, MAKEINTRESOURCE( IDR_RCDATA_SYMSRV32 ), RT_RCDATA );
    #endif
    if (hSymSrvRes != NULL)
    {
        hGlobal = LoadResource( NULL, hSymSrvRes );
        if (hGlobal != NULL)
        {
            pSymSrvData = LockResource( hGlobal );
            dwSymSrvDataSize = SizeofResource( NULL, hSymSrvRes );
            if (pSymSrvData != NULL)
            {
                std::ofstream fSymSrvDll( _T( "symsrv.dll" ), std::ios::binary );
                if (fSymSrvDll)
                {
                    fSymSrvDll.write( (const char*)pSymSrvData, dwSymSrvDataSize );
                    fSymSrvDll.close( );

                    UnlockResource( hGlobal );
                    FreeResource( hGlobal );

                    return TRUE;
                }
            }
        }

        UnlockResource( hGlobal );
        FreeResource( hGlobal );
    }

    return FALSE;
}

void Symbols::Cleanup( )
{
    if (m_bInitialized == TRUE)
    {
        for (auto it = m_SymbolAddresses.begin( ); it != m_SymbolAddresses.end( ); ++it)
            delete it->second;
        m_SymbolAddresses.clear( );

        for (auto it = m_SymbolNames.begin( ); it != m_SymbolNames.end( ); ++it)
            delete it->second;
        m_SymbolNames.clear( );

        CoUninitialize( );

        m_bInitialized = FALSE;
    }
}

BOOLEAN Symbols::Init( )
{
    if (m_bInitialized == FALSE)
    {
        HRESULT hr = S_OK;
        hr = CoInitialize( NULL );
        if (FAILED( hr ))
        {
            PrintOut( _T( "[Symbols::Init] CoInitialize failed - HRESULT = %08X" ), hr );
            return FALSE;
        }
        m_bInitialized = TRUE;
    }
    return TRUE;
}

BOOLEAN Symbols::LoadSymbolsForModule( CString ModulePath, ULONG_PTR ModuleBaseAddress, ULONG SizeOfModule )
{
    int idx = -1;
    CString ModuleName;
    const TCHAR* szSearchPath = NULL;
    SymbolReader* reader = NULL;
    BOOLEAN bSucc = FALSE;

    idx = ModulePath.ReverseFind( '/' );
    if (idx == -1)
        idx = ModulePath.ReverseFind( '\\' );
    ModuleName = ModulePath.Mid( ++idx );

    if (!m_strSearchPath.IsEmpty( ))
        szSearchPath = m_strSearchPath.GetString( );

    reader = new SymbolReader( );

    //ntdll::RtlEnterCriticalSection( &m_CriticalSection );

    bSucc = reader->LoadFile( ModuleName, ModulePath, ModuleBaseAddress, SizeOfModule, szSearchPath );

    //ntdll::RtlLeaveCriticalSection( &m_CriticalSection );

    if (bSucc)
    {
        PrintOut( _T( "[Symbols::LoadSymbolsForModule] Symbols for module %s loaded" ), ModuleName.GetString( ) );
        m_SymbolAddresses.insert( std::make_pair( ModuleBaseAddress, reader ) );
        return TRUE;
    }

    delete reader;

    return FALSE;
}

BOOLEAN Symbols::LoadSymbolsForPdb( CString PdbPath )
{
    int idx = -1;
    CString PdbFileName;
    const TCHAR* szSearchPath = NULL;
    SymbolReader* reader = NULL;
    BOOLEAN bSucc = FALSE;

    idx = PdbPath.ReverseFind( '/' );
    if (idx == -1)
        idx = PdbPath.ReverseFind( '\\' );
    PdbFileName = PdbPath.Mid( ++idx );

    if (!m_strSearchPath.IsEmpty( ))
        szSearchPath = m_strSearchPath.GetString( );

    reader = new SymbolReader( );

    ntdll::RtlEnterCriticalSection( &m_CriticalSection );

    bSucc = reader->LoadFile( PdbFileName, PdbPath, 0, 0, szSearchPath );

    ntdll::RtlLeaveCriticalSection( &m_CriticalSection );

    if (bSucc)
    {
        PrintOut( _T( "[Symbols::LoadSymbolsForPdb] Symbols for module %s loaded" ), PdbFileName.GetString( ) );
        m_SymbolNames.insert( std::make_pair( PdbFileName, reader ) );
        return TRUE;
    }

    delete reader;

    return FALSE;
}

//void Symbols::LoadModuleSymbols()
//{
//	PPROCESS_BASIC_INFORMATION pbi = NULL;
//	PEB peb;
//	PEB_LDR_DATA peb_ldr;
//
//	// Try to allocate buffer
//	HANDLE	hHeap = GetProcessHeap();
//	DWORD dwSize = sizeof(PROCESS_BASIC_INFORMATION);
//	pbi = (PPROCESS_BASIC_INFORMATION)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwSize);
//
//	ULONG dwSizeNeeded = 0;
//	NTSTATUS dwStatus = ntdll::NtQueryInformationProcess(g_hProcess, ProcessBasicInformation, pbi, dwSize, &dwSizeNeeded);
//	if (NT_SUCCESS(dwStatus) && dwSize < dwSizeNeeded)
//	{
//		if (pbi)
//			HeapFree(hHeap, 0, pbi);
//
//		pbi = (PPROCESS_BASIC_INFORMATION)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwSizeNeeded);
//		if (!pbi) {
//			_tprintf(_T("[LoadModuleSymbols] Couldn't allocate heap buffer!\n"));
//			return;
//		}
//
//		dwStatus = ntdll::NtQueryInformationProcess(g_hProcess, ProcessBasicInformation, pbi, dwSizeNeeded, &dwSizeNeeded);
//	}
//
//	// Did we successfully get basic info on process
//	if (NT_SUCCESS(dwStatus))
//	{
//		// Read Process Environment Block (PEB)
//		if (pbi->PebBaseAddress)
//		{
//			SIZE_T dwBytesRead = 0;
//			if (ReClassReadMemory(pbi->PebBaseAddress, &peb, sizeof(peb), &dwBytesRead))
//			{
//				dwBytesRead = 0;
//				if (ReClassReadMemory(peb.Ldr, &peb_ldr, sizeof(peb_ldr), &dwBytesRead))
//				{
//					ULONG numOfEntries = peb_ldr.Length;
//					ULONG currentEntryNum = 0;
//					LIST_ENTRY *pLdrListHead = (LIST_ENTRY *)peb_ldr.InMemoryOrderModuleList.Flink;
//					LIST_ENTRY *pLdrCurrentNode = peb_ldr.InMemoryOrderModuleList.Flink;
//					do
//					{
//						LDR_DATA_TABLE_ENTRY lstEntry = { 0 };
//						dwBytesRead = 0;
//						if (!ReClassReadMemory((LPVOID)pLdrCurrentNode, &lstEntry, sizeof(LDR_DATA_TABLE_ENTRY), &dwBytesRead))
//						{
//							_tprintf(_T("[LoadModuleSymbols] Could not read list entry from LDR list. Error: %s\n"), Utils::GetLastErrorAsString().c_str());
//							if (pbi)
//								HeapFree(hHeap, 0, pbi);
//							return;
//						}
//
//						pLdrCurrentNode = lstEntry.InLoadOrderLinks.Flink;
//
//						wchar_t wcsFullDllName[MAX_PATH] = { 0 };
//						if (lstEntry.FullDllName.Buffer && lstEntry.FullDllName.Length > 0)
//						{
//							dwBytesRead = 0;
//							if (!ReClassReadMemory((LPVOID)lstEntry.FullDllName.Buffer, &wcsFullDllName, lstEntry.FullDllName.Length, &dwBytesRead))
//							{
//								_tprintf(_T("[LoadModuleSymbols] Could not read list entry DLL name. Error: %s\n"), Utils::GetLastErrorAsString().c_str());
//								if (pbi)
//									HeapFree(hHeap, 0, pbi);
//								return;
//							}
//						}
//
//						if (lstEntry.DllBase != 0 && lstEntry.SizeOfImage != 0)
//						{
//							if (LoadSymbolsForModule(wcsFullDllName, (size_t)lstEntry.DllBase, lstEntry.SizeOfImage)) {
//								PrintOut(_T("Symbol module %ls loaded"), wcsFullDllName);
//							}
//							currentEntryNum++;
//							float progress = ((float)currentEntryNum / (float)numOfEntries) * 100;
//							printf("[%d/%d] progress: %f\n", currentEntryNum, numOfEntries, progress);
//						}
//					} while (pLdrListHead != pLdrCurrentNode);
//
//				} // Get Ldr
//			} // Read PEB
//		} // Check for PEB
//	}
//
//	if (pbi)
//		HeapFree(hHeap, 0, pbi);
//}

SymbolReader* Symbols::GetSymbolsForModuleAddress( ULONG_PTR ModuleAddress )
{
    SymbolReader* script = NULL;
    auto iter = m_SymbolAddresses.find( ModuleAddress );
    if (iter != m_SymbolAddresses.end( ))
        script = iter->second;
    return script;
}

SymbolReader* Symbols::GetSymbolsForModuleName( CString ModuleName )
{
    SymbolReader* script = NULL;
    auto iter = m_SymbolNames.find( ModuleName );
    if (iter != m_SymbolNames.end( ))
        script = iter->second;
    return script;
}

typedef void*( CDECL * Alloc_t )(unsigned int);
typedef void( CDECL * Free_t )(void *);
typedef PCHAR( CDECL *PUNDNAME )(char *, const char *, int, Alloc_t, Free_t, unsigned short);

void *CDECL AllocIt( unsigned int cb ) { return HeapAlloc( GetProcessHeap( ), 0, cb ); }
void CDECL FreeIt( void * p ) { HeapFree( GetProcessHeap( ), 0, p ); }

DWORD
WINAPI
UndecorateSymbolName(
    LPCSTR name,
    LPSTR outputString,
    DWORD maxStringLength,
    DWORD flags
)
{
    static HMODULE hMsvcrt = NULL;
    static PUNDNAME pfUnDname = NULL;

    DWORD rc;

    if (!hMsvcrt)
    {
        hMsvcrt = (HMODULE)Utils::GetLocalModuleBase( _T( "msvcrt.dll" ) );
        if (hMsvcrt)
            pfUnDname = (PUNDNAME)Utils::GetLocalProcAddress( hMsvcrt, _T( "__unDName" ) );
    }

    rc = 0;

    if (pfUnDname)
    {
        if (name && outputString && maxStringLength >= 2)
        {
            if (pfUnDname( outputString, name, maxStringLength - 1, AllocIt, FreeIt, (USHORT)flags ))
            {
                rc = (DWORD)strlen( outputString );
            }
        }
    }
    else
    {
        strncpy_s( outputString, maxStringLength, "Unable to load msvcrt!__unDName", maxStringLength );
        rc = (DWORD)strlen( outputString );
        SetLastError( ERROR_MOD_NOT_FOUND );
    }

    if (!rc)
        SetLastError( ERROR_INVALID_PARAMETER );

    return rc;
}

DWORD
WINAPI
UndecorateSymbolNameUnicode(
    LPCWSTR name,
    LPWSTR outputString,
    DWORD maxStringLength,
    DWORD flags
)
{
    LPSTR AnsiName;
    LPSTR AnsiOutputString;
    int AnsiNameLength;
    DWORD rc;

    AnsiNameLength = WideCharToMultiByte( CP_ACP, WC_COMPOSITECHECK | WC_SEPCHARS, name, -1, NULL, 0, NULL, NULL );
    if (!AnsiNameLength)
        return 0;

    AnsiName = (char *)AllocIt( AnsiNameLength );
    if (!AnsiName)
    {
        SetLastError( ERROR_NOT_ENOUGH_MEMORY );
        return 0;
    }

    ZeroMemory( AnsiName, AnsiNameLength );
    if (!WideCharToMultiByte( CP_ACP, WC_COMPOSITECHECK | WC_SEPCHARS, name, -1, AnsiName, AnsiNameLength, NULL, NULL ))
    {
        FreeIt( AnsiName );
        return 0;
    }

    AnsiOutputString = (LPSTR)AllocIt( maxStringLength + 1 );
    if (!AnsiOutputString)
    {
        FreeIt( AnsiName );
        SetLastError( ERROR_NOT_ENOUGH_MEMORY );
        return 0;
    }

    *AnsiOutputString = '\0';
    rc = UndecorateSymbolName( AnsiName, AnsiOutputString, maxStringLength, flags );
    MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, AnsiOutputString, -1, outputString, maxStringLength );

    FreeIt( AnsiName );
    FreeIt( AnsiOutputString );

    return rc;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: cessentl.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: hr $ $Date: 2007-11-02 16:11:44 $
 *
 *  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 <precomp.h>
#include <ary/cessentl.hxx>

// NOT FULLY DEFINED SERVICES
#include <ary/cpp/c_ce.hxx>
#include <ary/doc/d_oldcppdocu.hxx>

namespace ary
{
namespace cpp
{

CeEssentials::CeEssentials()
    :   sLocalName(),
        nOwner(0),
        nLocation(0)
{
}

CeEssentials::CeEssentials( const String  &     i_sLocalName,
                            Cid                 i_nOwner,
                            loc::Le_id          i_nLocation )
    :   sLocalName(i_sLocalName),
        nOwner(i_nOwner),
        nLocation(i_nLocation)
{
}

CeEssentials::~CeEssentials()
{
}

inline bool
IsInternal(const doc::Documentation & i_doc)
{
    const ary::doc::OldCppDocu *
        docu = dynamic_cast< const ary::doc::OldCppDocu* >(i_doc.Data());
    if (docu != 0)
        return docu->IsInternal();
    return false;
}

bool
CodeEntity::IsVisible() const
{
    // KORR_FUTURE:   Improve the whole handling of internal and visibility.
    return bIsVisible && NOT IsInternal(Docu());
}

}   // namespace cpp
}   // namespace ary
<commit_msg>INTEGRATION: CWS changefileheader (1.8.22); FILE MERGED 2008/03/28 16:01:53 rt 1.8.22.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: cessentl.cxx,v $
 * $Revision: 1.9 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include <precomp.h>
#include <ary/cessentl.hxx>

// NOT FULLY DEFINED SERVICES
#include <ary/cpp/c_ce.hxx>
#include <ary/doc/d_oldcppdocu.hxx>

namespace ary
{
namespace cpp
{

CeEssentials::CeEssentials()
    :   sLocalName(),
        nOwner(0),
        nLocation(0)
{
}

CeEssentials::CeEssentials( const String  &     i_sLocalName,
                            Cid                 i_nOwner,
                            loc::Le_id          i_nLocation )
    :   sLocalName(i_sLocalName),
        nOwner(i_nOwner),
        nLocation(i_nLocation)
{
}

CeEssentials::~CeEssentials()
{
}

inline bool
IsInternal(const doc::Documentation & i_doc)
{
    const ary::doc::OldCppDocu *
        docu = dynamic_cast< const ary::doc::OldCppDocu* >(i_doc.Data());
    if (docu != 0)
        return docu->IsInternal();
    return false;
}

bool
CodeEntity::IsVisible() const
{
    // KORR_FUTURE:   Improve the whole handling of internal and visibility.
    return bIsVisible && NOT IsInternal(Docu());
}

}   // namespace cpp
}   // namespace ary
<|endoftext|>


<commit_before>// Copyright 2017 Rick van Schijndel

#include <Arduino.h>
#include <stdio.h>

#include <Bounce2.h>
#include <U8g2lib.h>

#include "logo.h"
#include "player_dick.h"
#include "game_state.h"
#include "asset.h"
#include "player.h"

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

const uint8_t kButtonPin = D3;
const uint8_t kScreenWidth = 128;
const uint8_t kScreenHeight = 64;

// Global game state
gameState game_state = start;

// The player in the game
Player player;

// Asset
Asset player_asset(player_width, player_height, player_bits);
Asset logo_asset(bootup_width, bootup_height, bootup_bits);

// The display object
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0);

Bounce button;

void setupButton() {
  pinMode(kButtonPin, INPUT_PULLUP);
  button.attach(kButtonPin);
  button.interval(10);
}

void setupGraphics() {
  u8g2.begin();
  u8g2.setFlipMode(0);
  u8g2.setFont(u8g2_font_artossans8_8r);
}

void setup(void) {
  setupGraphics();
  setupButton();
  Serial.begin(115200);
}

inline void nextGameState() {
  game_state = static_cast<gameState>((game_state + 1) % (gameOver + 1));
}

void drawPlayer(uint16_t y = 0) {
  int16_t y_position_from_ground = kScreenHeight - player_asset.getHeight() - y;
  int16_t player_x = ((kScreenWidth / 3) - (player_asset.getHeight() / 2));
  u8g2.drawXBM(
    player_x,
    y_position_from_ground,
    player_asset.getHeight(),
    player_asset.getHeight(),
    player_asset.getBitmap());
}

void drawObstacles() {
  // TODO: draw obstacles according to the values in some array
}

void drawBootupScreen() {
  int16_t logoMiddleX = (kScreenWidth / 2) - (bootup_width / 2);
  int16_t logoMiddleY = (kScreenHeight / 2) - (bootup_height / 2);
  u8g2.drawXBM(
    logoMiddleX,
    logoMiddleY,
    bootup_width,
    bootup_height,
    bootup_bits);
}

void drawGameOver() {
  static const uint8_t x_pos_gameover = 20;
  static const uint8_t y_pos_gameover = 20;
  u8g2.drawStr(x_pos_gameover, y_pos_gameover, "GAME OVER");
  // TODO: draw fancy asset?
}

void drawScore() {
  static const uint8_t kScoreX = 20;
  static const uint8_t kScoreY = 60;
  static const size_t kScoreBufferSize = 20;
  char score_buffer[kScoreBufferSize];
  snprintf(score_buffer, kScoreBufferSize, "Score: %u", player.getScore());
  u8g2.drawStr(kScoreX, kScoreY, score_buffer);
}

void drawHiscoreScreen() {
  static const uint8_t kHiscoreX = 0;
  static const uint8_t kHiscoreY = 20;
  u8g2.drawStr(kHiscoreX, kHiscoreY, "HI SCORES");
  // TODO: draw hi scores
}

bool collisionDetected() {
  /*
  if player_right_x_position >= obstacle_left_x_position and
    player_left_x_position <= obstacle_right_x_position
    player_bottom_y_position <= obstacle_top_y_position
  */

  // TODO: implement algorithm, remove auto logic
  return player.getScore() > (unsigned)random(100, 250);
}

void updateObstaclePosition() {
  // TODO
}

void resetGame() {
  player = Player();
}

void loop(void) {
  // In the loop so it's only true once, after this it's false again.
  // This is so it won't think the button is pressed again every loop.
  bool buttonPressed = false;

  if (button.update()) {
    buttonPressed = button.read();
    Serial.println("Button update");
  }

  // update game logic
  switch (game_state) {
    case start:
      {
        if (buttonPressed) {
          nextGameState();
        }
        break;
      }
    case hiscore:
      {
        if (buttonPressed) {
          nextGameState();
        }
        break;
      }
    case play:
      {
        if (buttonPressed) {
          if (player.onGround()) {
            player.jump();
          }
        }

        player.updateYPosition();
        updateObstaclePosition();

        if (collisionDetected()) {
          nextGameState();
          break;
        }
        // happens after collision detection, so score will only get higher
        // if player does not collide
        player.updateScore();
        break;
      }
    case gameOver:
      {
        if (buttonPressed) {
          resetGame();
          nextGameState();
        }
        break;
      }
    default:
      {
        Serial.println("Invalid game state");
        break;
      }
  }

  // clear buffer to start drawing
  u8g2.clearBuffer();

  // update graphics
  switch (game_state) {
    case start:
      {
        drawBootupScreen();
        break;
      }
    case hiscore:
      {
        drawHiscoreScreen();
        break;
      }
    case play:
      {
        drawPlayer(player.getYPosition());
        drawObstacles();
        break;
      }
    case gameOver:
      {
        drawGameOver();
        drawScore();
        break;
      }
    default:
      {
        Serial.println("invalid game state");
        break;
      }
  }

  // draw everything on the screen
  u8g2.sendBuffer();
}
<commit_msg>Multiple of asset in comment<commit_after>// Copyright 2017 Rick van Schijndel

#include <Arduino.h>
#include <stdio.h>

#include <Bounce2.h>
#include <U8g2lib.h>

#include "logo.h"
#include "player_dick.h"
#include "game_state.h"
#include "asset.h"
#include "player.h"

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

const uint8_t kButtonPin = D3;
const uint8_t kScreenWidth = 128;
const uint8_t kScreenHeight = 64;

// Global game state
gameState game_state = start;

// The player in the game
Player player;

// Assets
Asset player_asset(player_width, player_height, player_bits);
Asset logo_asset(bootup_width, bootup_height, bootup_bits);

// The display object
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0);

Bounce button;

void setupButton() {
  pinMode(kButtonPin, INPUT_PULLUP);
  button.attach(kButtonPin);
  button.interval(10);
}

void setupGraphics() {
  u8g2.begin();
  u8g2.setFlipMode(0);
  u8g2.setFont(u8g2_font_artossans8_8r);
}

void setup(void) {
  setupGraphics();
  setupButton();
  Serial.begin(115200);
}

inline void nextGameState() {
  game_state = static_cast<gameState>((game_state + 1) % (gameOver + 1));
}

void drawPlayer(uint16_t y = 0) {
  int16_t y_position_from_ground = kScreenHeight - player_asset.getHeight() - y;
  int16_t player_x = ((kScreenWidth / 3) - (player_asset.getHeight() / 2));
  u8g2.drawXBM(
    player_x,
    y_position_from_ground,
    player_asset.getHeight(),
    player_asset.getHeight(),
    player_asset.getBitmap());
}

void drawObstacles() {
  // TODO: draw obstacles according to the values in some array
}

void drawBootupScreen() {
  int16_t logoMiddleX = (kScreenWidth / 2) - (bootup_width / 2);
  int16_t logoMiddleY = (kScreenHeight / 2) - (bootup_height / 2);
  u8g2.drawXBM(
    logoMiddleX,
    logoMiddleY,
    bootup_width,
    bootup_height,
    bootup_bits);
}

void drawGameOver() {
  static const uint8_t x_pos_gameover = 20;
  static const uint8_t y_pos_gameover = 20;
  u8g2.drawStr(x_pos_gameover, y_pos_gameover, "GAME OVER");
  // TODO: draw fancy asset?
}

void drawScore() {
  static const uint8_t kScoreX = 20;
  static const uint8_t kScoreY = 60;
  static const size_t kScoreBufferSize = 20;
  char score_buffer[kScoreBufferSize];
  snprintf(score_buffer, kScoreBufferSize, "Score: %u", player.getScore());
  u8g2.drawStr(kScoreX, kScoreY, score_buffer);
}

void drawHiscoreScreen() {
  static const uint8_t kHiscoreX = 0;
  static const uint8_t kHiscoreY = 20;
  u8g2.drawStr(kHiscoreX, kHiscoreY, "HI SCORES");
  // TODO: draw hi scores
}

bool collisionDetected() {
  /*
  if player_right_x_position >= obstacle_left_x_position and
    player_left_x_position <= obstacle_right_x_position
    player_bottom_y_position <= obstacle_top_y_position
  */

  // TODO: implement algorithm, remove auto logic
  return player.getScore() > (unsigned)random(100, 250);
}

void updateObstaclePosition() {
  // TODO
}

void resetGame() {
  player = Player();
}

void loop(void) {
  // In the loop so it's only true once, after this it's false again.
  // This is so it won't think the button is pressed again every loop.
  bool buttonPressed = false;

  if (button.update()) {
    buttonPressed = button.read();
    Serial.println("Button update");
  }

  // update game logic
  switch (game_state) {
    case start:
      {
        if (buttonPressed) {
          nextGameState();
        }
        break;
      }
    case hiscore:
      {
        if (buttonPressed) {
          nextGameState();
        }
        break;
      }
    case play:
      {
        if (buttonPressed) {
          if (player.onGround()) {
            player.jump();
          }
        }

        player.updateYPosition();
        updateObstaclePosition();

        if (collisionDetected()) {
          nextGameState();
          break;
        }
        // happens after collision detection, so score will only get higher
        // if player does not collide
        player.updateScore();
        break;
      }
    case gameOver:
      {
        if (buttonPressed) {
          resetGame();
          nextGameState();
        }
        break;
      }
    default:
      {
        Serial.println("Invalid game state");
        break;
      }
  }

  // clear buffer to start drawing
  u8g2.clearBuffer();

  // update graphics
  switch (game_state) {
    case start:
      {
        drawBootupScreen();
        break;
      }
    case hiscore:
      {
        drawHiscoreScreen();
        break;
      }
    case play:
      {
        drawPlayer(player.getYPosition());
        drawObstacles();
        break;
      }
    case gameOver:
      {
        drawGameOver();
        drawScore();
        break;
      }
    default:
      {
        Serial.println("invalid game state");
        break;
      }
  }

  // draw everything on the screen
  u8g2.sendBuffer();
}
<|endoftext|>


<commit_before>#include <ar2mav/ar2mav.h>
#include <arpa/inet.h>
#include <x264_image_transport/x264Packet.h>
#include <sys/socket.h>

typedef boost::shared_ptr<x264_image_transport::x264Packet> x264PacketPtr;

/**
 * The following structures are all written as in the ARDrone SDK 2.0
 */
typedef struct { //PaVE
    char signiture[4]; // "PaVE" - used to identify the start of frame
    uint8_t version; // Version code
    uint8_t video_codec; // Codec of the following frame
    uint16_t header_size; // Size of the parrot_video_encapsulation_t
    uint32_t payload_size; // Amount of data following this PaVE
    uint16_t encoded_stream_width; // ex: 640
    uint16_t encoded_stream_height; // ex: 368
    uint16_t display_width; // ex: 640
    uint16_t display_height; // ex: 360
    uint32_t frame_number; // Frame position inside the current stream
    uint32_t timestamp; // In milliseconds
    uint8_t total_chuncks; // Number of UDP packets containing the current decodable payload - currently unused
    uint8_t chunck_index; // Position of the packet - first chunk is #0 - currenty unused
    uint8_t frame_type; // I-frame, P-frame - parrot_video_encapsulation_frametypes_t
    uint8_t control; // Special commands like end-of-stream or advertised frames
    uint32_t stream_byte_position_lw; // Byte position of the current payload in the encoded stream - lower 32-bit word
    uint32_t stream_byte_position_uw; // Byte position of the current payload in the encoded stream - upper 32-bit word
    uint16_t stream_id; // This ID indentifies packets that should be recorded together
    uint8_t total_slices; // number of slices composing the current frame
    uint8_t slice_index; // position of the current slice in the frame
    uint8_t header1_size; // H.264 only : size of SPS inside payload - no SPS present if value is zero
    uint8_t header2_size; // H.264 only : size of PPS inside payload - no PPS present if value is zero
    uint8_t reserved2[2]; // Padding to align on 48 bytes
    uint32_t advertised_size; // Size of frames announced as advertised frames
    uint8_t reserved3[12]; // Padding to align on 64 bytes
    uint8_t reserved4[4]; // padding -- added b/c it was in the KIPR library code
} __attribute__ ((packed)) parrot_video_encapsulation_t;

typedef enum {
    CODEC_UNKNNOWN = 0,
    CODEC_VLIB,
    CODEC_P264,
    CODEC_MPEG4_VISUAL,
    CODEC_MPEG4_AVC
} parrot_video_encapsulation_codecs_t;

typedef enum {
    FRAME_TYPE_UNKNNOWN = 0, FRAME_TYPE_IDR_FRAME,
    FRAME_TYPE_I_FRAME, FRAME_TYPE_P_FRAME, FRAME_TYPE_HEADERS
} parrot_video_encapsulation_frametypes_t;

/**
 * @brief prints most significant parts of a PaVE packet
 * @param[in] PaVE - the PaVE to be printed
 */
void printPaVE(parrot_video_encapsulation_t* PaVE) {
        printf("\n---------------------------\n");

        printf("Codec : %s\n",
                        (PaVE->video_codec == CODEC_MPEG4_VISUAL) ?
                                        "MP4" :
                                        ((PaVE->video_codec == CODEC_MPEG4_AVC) ? "H264" : "Unknown"));

        printf("StreamID : %d \n", PaVE->stream_id);
        printf("Timestamp : %d ms\n", PaVE->timestamp);
        printf("Encoded dims : %d x %d\n", PaVE->encoded_stream_width,
                        PaVE->encoded_stream_height);
        printf("Display dims : %d x %d\n", PaVE->display_width, PaVE->display_height);
        ////printf ("Header size  : %d (PaVE size : %d)\n", PaVE->header_size, sizeof (parrot_video_encapsulation_t));
        printf("Header size : %d\n", PaVE->header_size);
        printf("Payload size : %d\n", PaVE->payload_size);
        printf("Size of SPS inside payload : %d\n", PaVE->header1_size);
        printf("Size of PPS inside payload : %d\n", PaVE->header2_size);
        printf("Slices in the frame : %d\n", PaVE->total_slices);
        printf("Frame Type / Number : %s : %d : slide %d/%d\n",
                        (PaVE->frame_type == FRAME_TYPE_P_FRAME) ?
                                        "P-Frame" :
                                        ((PaVE->frame_type == FRAME_TYPE_I_FRAME) ?
                                                        "I-Frame" : "IDR-Frame"), PaVE->frame_number,
                        PaVE->slice_index + 1, PaVE->total_slices);

        printf("---------------------------\n\n");
}

/**
 * @brief Sets up a socket connection on which to receive data
 * @param[in] name String representing the name of the drone, for logging purposes
 * @param[in] myAddr strucutre representing the host ip address
 * @param[in] droneAddr sturcture representing the drone ip address
 * @param[in] timeout timeval sturcture to set up reconnection timeouts
 * @returns the socketNumber assigned
 */
int establish_socket(const std::string* name, sockaddr_in* myAddr, sockaddr_in* droneAddr, const struct timeval* timeout){
    const int one = 1;
    int socketNumber = socket(AF_INET, SOCK_STREAM, 0);
    while(ros::ok() && connect(socketNumber, (sockaddr*) droneAddr, sizeof(sockaddr_in)) != 0) {
        ROS_INFO("[%s]Did not manage to establish connection", (*name).c_str());
        ros::Duration((*timeout).tv_sec + (*timeout).tv_usec / 1000000.0).sleep();
    }
    setsockopt(socketNumber, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
    setsockopt(socketNumber, SOL_SOCKET, SO_RCVTIMEO, (char *)timeout,sizeof(struct timeval));
    return socketNumber;
}

namespace ar2mav{
    /**
     * See header file
     */
    ARDroneVideo::ARDroneVideo(ros::NodeHandle nh){
        int temp;
        nh.param<int>("buffer_size", this->buffer_size, 65536);
        nh.param<int>("drone_port", this->drone_port, 5555);
        nh.param<int>("timeout", temp, 1000);
        this->timeout.tv_sec = temp / 1000;
        this->timeout.tv_usec = (temp - timeout.tv_sec) * 1000;
        nh.param<std::string>("name", this->name, "drone");
        this->active = false;
        this->drone_ip = "";
        std::vector<std::string> active;
        if(ros::param::get("/drones_active", active))
            for(int i=0;i<active.size();i++)
                if(active[i].compare(name) == 0)
                    this->active = true;
        if(this->active){
            nh.getParam("/drones/" + this->name + "/ip", this->drone_ip);
            if(this->drone_ip.compare("") == 0){
                //ROS_INFO("[%s]Did not found IP in the parameter server, switchin to args for IP", this->name.c_str());
                nh.param<std::string>("drone_ip", this->drone_ip, "192.168.1.1");
            }
            this->pub = nh.advertise<x264_image_transport::x264Packet>("/" + this->name + "/video/x264", 1000);
        }
    }

    /**
     * See header file
     */
    void ARDroneVideo::fetch_video(){
        if(!this->active)
            return;
        //***************************************************************************
        //   Socket Addresses
        //***************************************************************************
        sockaddr_in myAddr;
        sockaddr_in droneAddr;
        bzero(&myAddr, sizeof(myAddr));
        bzero(&droneAddr, sizeof(droneAddr));
        myAddr.sin_family = AF_INET;
        myAddr.sin_addr.s_addr = INADDR_ANY;
        droneAddr.sin_family = AF_INET;
        droneAddr.sin_addr.s_addr = inet_addr(this->drone_ip.c_str());
        droneAddr.sin_port = htons(this->drone_port);
        //***************************************************************************
        //   Helper variables
        //***************************************************************************
        int index, read, i;
        unsigned char part[buffer_size];
        int partLength;
        bool check;
        x264PacketPtr message;
        parrot_video_encapsulation_t* pave;
        index = 0;
        int errorCount = 0;
        //***************************************************************************
        //   Initialise connection
        //***************************************************************************
        int socketNumber = establish_socket(&this->name, &myAddr, &droneAddr, &this->timeout);
        //***************************************************************************
        //   Decode PaVE packet and send the encoded video stream
        //***************************************************************************
        ROS_INFO("[%s]***** START VIDEO STREAM *****", this->name.c_str());
        while (ros::ok() && this->active) {
            if(index == 0) {
                partLength = TEMP_FAILURE_RETRY(recv(socketNumber, part, this->buffer_size,0));
                if (partLength <= 0) {
                    ROS_INFO("[%s][%d]Did not receive video data, trying to recover", this->name.c_str(), partLength);
                    if(errorCount > 5){
                        close(socketNumber);
                        ros::Duration(this->timeout.tv_sec + this->timeout.tv_usec / 1000000.0).sleep();
                    }
                    socketNumber = establish_socket(&this->name, &myAddr, &droneAddr, &this->timeout);
                    errorCount++;
                    index = 0;
                    continue;
                }
                errorCount = 0;
            }
            pave = (parrot_video_encapsulation_t *) (part+index);
            //***************************************************************************
            //   Verify that we have aligned correctly the PaVE packet
            //   If not try to seek its signiture in the buffer
            //***************************************************************************
            if (strncmp(pave->signiture,"PaVE", 4) != 0) {
                ROS_INFO("[%s]PaVE not synchronized, trying to rebind", this->name.c_str());
                for(i = 0;i<this->buffer_size-index-3;i++)
                    if(strncmp((const char*) (part+index+i),"PaVE", 4) == 0){
                        index += i;
                        break;
                    }
                if(i == this->buffer_size-index-3)
                    index = 0;
                continue;
            }
            //***************************************************************************
            //   When packet is aligned fill in the image meta data into the message
            //***************************************************************************
            message = x264PacketPtr(new x264_image_transport::x264Packet());
            message->img_width = pave->display_width;
            message->img_height = pave->display_height;
            message->header.stamp.fromSec(pave->timestamp / 1000.0);
            message->codec = pave->video_codec == CODEC_MPEG4_AVC ? x264_image_transport::x264Packet::CODEC_H264 :
                    pave->video_codec == CODEC_MPEG4_VISUAL ? x264_image_transport::x264Packet::CODEC_MPEG4 : -1;
            if(index + pave->header_size + pave->payload_size > this->buffer_size){
                ROS_INFO("[%s]Too big payload, skipping frame.(ADVICE: Increase buffer_size)", this->name.c_str());
                index = 0;
                continue;
            }
            //***************************************************************************
            //   If the packet did not contain all the payload have to wait for the rest
            //   to arrive
            //***************************************************************************
            if(partLength - index -  pave->header_size < pave->payload_size) {
                read = partLength - index - pave->header_size;
                check = false;
                while (read < pave->payload_size) {
                    partLength = TEMP_FAILURE_RETRY(recv(socketNumber, part+index+pave->header_size+read, pave->payload_size - read,0));
                    if(partLength <= 0){
                        check = true;
                        break;
                    }
                    read += partLength;
                }
                if(check){
                    ROS_INFO("[%s]Timedout while waiting extra packets", this->name.c_str());
                    index = 0;
                    continue;
                }
                partLength = index + pave->header_size+ pave->payload_size;
            }
            //***************************************************************************
            //   After all is correct just fill in encoded image data and publish
            //***************************************************************************
            message->data.assign(part+index+pave->header_size, part+index+pave->header_size+pave->payload_size);
            this->pub.publish(message);
            //***************************************************************************
            //  If the buffer contains more than the payload set up the index to point
            //  at the end of this packet (potentially start of next)
            //***************************************************************************
            if(partLength - index - pave->header_size > pave->payload_size)
                index += pave->header_size + pave->payload_size;
            else
                index = 0;
        }
        ROS_INFO("[%s]Closing socket.", this->name.c_str());//, socketNumber, flag, ros::ok());
        close(socketNumber);
    }
}

<commit_msg>Patch for video node compatibility with OS X<commit_after>#include <ar2mav/ar2mav.h>
#include <arpa/inet.h>
#include <x264_image_transport/x264Packet.h>
#include <sys/socket.h>

// Patch for platforms without GNU TEMP_FAILURE_RETRY macro
// (Notably BSD/OSX)
#ifndef TEMP_FAILURE_RETRY
#define TEMP_FAILURE_RETRY(expr) \
    ({ long int _res; \
        do _res = (long int) (expr); \
        while (_res == -1L && errno == EINTR); \
        _res; })
#endif

typedef boost::shared_ptr<x264_image_transport::x264Packet> x264PacketPtr;

/**
 * The following structures are all written as in the ARDrone SDK 2.0
 */
typedef struct { //PaVE
    char signiture[4]; // "PaVE" - used to identify the start of frame
    uint8_t version; // Version code
    uint8_t video_codec; // Codec of the following frame
    uint16_t header_size; // Size of the parrot_video_encapsulation_t
    uint32_t payload_size; // Amount of data following this PaVE
    uint16_t encoded_stream_width; // ex: 640
    uint16_t encoded_stream_height; // ex: 368
    uint16_t display_width; // ex: 640
    uint16_t display_height; // ex: 360
    uint32_t frame_number; // Frame position inside the current stream
    uint32_t timestamp; // In milliseconds
    uint8_t total_chuncks; // Number of UDP packets containing the current decodable payload - currently unused
    uint8_t chunck_index; // Position of the packet - first chunk is #0 - currenty unused
    uint8_t frame_type; // I-frame, P-frame - parrot_video_encapsulation_frametypes_t
    uint8_t control; // Special commands like end-of-stream or advertised frames
    uint32_t stream_byte_position_lw; // Byte position of the current payload in the encoded stream - lower 32-bit word
    uint32_t stream_byte_position_uw; // Byte position of the current payload in the encoded stream - upper 32-bit word
    uint16_t stream_id; // This ID indentifies packets that should be recorded together
    uint8_t total_slices; // number of slices composing the current frame
    uint8_t slice_index; // position of the current slice in the frame
    uint8_t header1_size; // H.264 only : size of SPS inside payload - no SPS present if value is zero
    uint8_t header2_size; // H.264 only : size of PPS inside payload - no PPS present if value is zero
    uint8_t reserved2[2]; // Padding to align on 48 bytes
    uint32_t advertised_size; // Size of frames announced as advertised frames
    uint8_t reserved3[12]; // Padding to align on 64 bytes
    uint8_t reserved4[4]; // padding -- added b/c it was in the KIPR library code
} __attribute__ ((packed)) parrot_video_encapsulation_t;

typedef enum {
    CODEC_UNKNNOWN = 0,
    CODEC_VLIB,
    CODEC_P264,
    CODEC_MPEG4_VISUAL,
    CODEC_MPEG4_AVC
} parrot_video_encapsulation_codecs_t;

typedef enum {
    FRAME_TYPE_UNKNNOWN = 0, FRAME_TYPE_IDR_FRAME,
    FRAME_TYPE_I_FRAME, FRAME_TYPE_P_FRAME, FRAME_TYPE_HEADERS
} parrot_video_encapsulation_frametypes_t;

/**
 * @brief prints most significant parts of a PaVE packet
 * @param[in] PaVE - the PaVE to be printed
 */
void printPaVE(parrot_video_encapsulation_t* PaVE) {
        printf("\n---------------------------\n");

        printf("Codec : %s\n",
                        (PaVE->video_codec == CODEC_MPEG4_VISUAL) ?
                                        "MP4" :
                                        ((PaVE->video_codec == CODEC_MPEG4_AVC) ? "H264" : "Unknown"));

        printf("StreamID : %d \n", PaVE->stream_id);
        printf("Timestamp : %d ms\n", PaVE->timestamp);
        printf("Encoded dims : %d x %d\n", PaVE->encoded_stream_width,
                        PaVE->encoded_stream_height);
        printf("Display dims : %d x %d\n", PaVE->display_width, PaVE->display_height);
        ////printf ("Header size  : %d (PaVE size : %d)\n", PaVE->header_size, sizeof (parrot_video_encapsulation_t));
        printf("Header size : %d\n", PaVE->header_size);
        printf("Payload size : %d\n", PaVE->payload_size);
        printf("Size of SPS inside payload : %d\n", PaVE->header1_size);
        printf("Size of PPS inside payload : %d\n", PaVE->header2_size);
        printf("Slices in the frame : %d\n", PaVE->total_slices);
        printf("Frame Type / Number : %s : %d : slide %d/%d\n",
                        (PaVE->frame_type == FRAME_TYPE_P_FRAME) ?
                                        "P-Frame" :
                                        ((PaVE->frame_type == FRAME_TYPE_I_FRAME) ?
                                                        "I-Frame" : "IDR-Frame"), PaVE->frame_number,
                        PaVE->slice_index + 1, PaVE->total_slices);

        printf("---------------------------\n\n");
}

/**
 * @brief Sets up a socket connection on which to receive data
 * @param[in] name String representing the name of the drone, for logging purposes
 * @param[in] myAddr strucutre representing the host ip address
 * @param[in] droneAddr sturcture representing the drone ip address
 * @param[in] timeout timeval sturcture to set up reconnection timeouts
 * @returns the socketNumber assigned
 */
int establish_socket(const std::string* name, sockaddr_in* myAddr, sockaddr_in* droneAddr, const struct timeval* timeout){
    const int one = 1;
    int socketNumber = socket(AF_INET, SOCK_STREAM, 0);
    while(ros::ok() && connect(socketNumber, (sockaddr*) droneAddr, sizeof(sockaddr_in)) != 0) {
        ROS_INFO("[%s]Did not manage to establish connection", (*name).c_str());
        ros::Duration((*timeout).tv_sec + (*timeout).tv_usec / 1000000.0).sleep();
    }
    setsockopt(socketNumber, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
    setsockopt(socketNumber, SOL_SOCKET, SO_RCVTIMEO, (char *)timeout,sizeof(struct timeval));
    return socketNumber;
}

namespace ar2mav{
    /**
     * See header file
     */
    ARDroneVideo::ARDroneVideo(ros::NodeHandle nh){
        int temp;
        nh.param<int>("buffer_size", this->buffer_size, 65536);
        nh.param<int>("drone_port", this->drone_port, 5555);
        nh.param<int>("timeout", temp, 1000);
        this->timeout.tv_sec = temp / 1000;
        this->timeout.tv_usec = (temp - timeout.tv_sec) * 1000;
        nh.param<std::string>("name", this->name, "drone");
        this->active = false;
        this->drone_ip = "";
        std::vector<std::string> active;
        if(ros::param::get("/drones_active", active))
            for(int i=0;i<active.size();i++)
                if(active[i].compare(name) == 0)
                    this->active = true;
        if(this->active){
            nh.getParam("/drones/" + this->name + "/ip", this->drone_ip);
            if(this->drone_ip.compare("") == 0){
                //ROS_INFO("[%s]Did not found IP in the parameter server, switchin to args for IP", this->name.c_str());
                nh.param<std::string>("drone_ip", this->drone_ip, "192.168.1.1");
            }
            this->pub = nh.advertise<x264_image_transport::x264Packet>("/" + this->name + "/video/x264", 1000);
        }
    }

    /**
     * See header file
     */
    void ARDroneVideo::fetch_video(){
        if(!this->active)
            return;
        //***************************************************************************
        //   Socket Addresses
        //***************************************************************************
        sockaddr_in myAddr;
        sockaddr_in droneAddr;
        bzero(&myAddr, sizeof(myAddr));
        bzero(&droneAddr, sizeof(droneAddr));
        myAddr.sin_family = AF_INET;
        myAddr.sin_addr.s_addr = INADDR_ANY;
        droneAddr.sin_family = AF_INET;
        droneAddr.sin_addr.s_addr = inet_addr(this->drone_ip.c_str());
        droneAddr.sin_port = htons(this->drone_port);
        //***************************************************************************
        //   Helper variables
        //***************************************************************************
        int index, read, i;
        unsigned char part[buffer_size];
        int partLength;
        bool check;
        x264PacketPtr message;
        parrot_video_encapsulation_t* pave;
        index = 0;
        int errorCount = 0;
        //***************************************************************************
        //   Initialise connection
        //***************************************************************************
        int socketNumber = establish_socket(&this->name, &myAddr, &droneAddr, &this->timeout);
        //***************************************************************************
        //   Decode PaVE packet and send the encoded video stream
        //***************************************************************************
        ROS_INFO("[%s]***** START VIDEO STREAM *****", this->name.c_str());
        while (ros::ok() && this->active) {
            if(index == 0) {
                partLength = TEMP_FAILURE_RETRY(recv(socketNumber, part, this->buffer_size,0));
                if (partLength <= 0) {
                    ROS_INFO("[%s][%d]Did not receive video data, trying to recover", this->name.c_str(), partLength);
                    if(errorCount > 5){
                        close(socketNumber);
                        ros::Duration(this->timeout.tv_sec + this->timeout.tv_usec / 1000000.0).sleep();
                    }
                    socketNumber = establish_socket(&this->name, &myAddr, &droneAddr, &this->timeout);
                    errorCount++;
                    index = 0;
                    continue;
                }
                errorCount = 0;
            }
            pave = (parrot_video_encapsulation_t *) (part+index);
            //***************************************************************************
            //   Verify that we have aligned correctly the PaVE packet
            //   If not try to seek its signiture in the buffer
            //***************************************************************************
            if (strncmp(pave->signiture,"PaVE", 4) != 0) {
                ROS_INFO("[%s]PaVE not synchronized, trying to rebind", this->name.c_str());
                for(i = 0;i<this->buffer_size-index-3;i++)
                    if(strncmp((const char*) (part+index+i),"PaVE", 4) == 0){
                        index += i;
                        break;
                    }
                if(i == this->buffer_size-index-3)
                    index = 0;
                continue;
            }
            //***************************************************************************
            //   When packet is aligned fill in the image meta data into the message
            //***************************************************************************
            message = x264PacketPtr(new x264_image_transport::x264Packet());
            message->img_width = pave->display_width;
            message->img_height = pave->display_height;
            message->header.stamp.fromSec(pave->timestamp / 1000.0);
            message->codec = pave->video_codec == CODEC_MPEG4_AVC ? x264_image_transport::x264Packet::CODEC_H264 :
                    pave->video_codec == CODEC_MPEG4_VISUAL ? x264_image_transport::x264Packet::CODEC_MPEG4 : -1;
            if(index + pave->header_size + pave->payload_size > this->buffer_size){
                ROS_INFO("[%s]Too big payload, skipping frame.(ADVICE: Increase buffer_size)", this->name.c_str());
                index = 0;
                continue;
            }
            //***************************************************************************
            //   If the packet did not contain all the payload have to wait for the rest
            //   to arrive
            //***************************************************************************
            if(partLength - index -  pave->header_size < pave->payload_size) {
                read = partLength - index - pave->header_size;
                check = false;
                while (read < pave->payload_size) {
                    partLength = TEMP_FAILURE_RETRY(recv(socketNumber, part+index+pave->header_size+read, pave->payload_size - read,0));
                    if(partLength <= 0){
                        check = true;
                        break;
                    }
                    read += partLength;
                }
                if(check){
                    ROS_INFO("[%s]Timedout while waiting extra packets", this->name.c_str());
                    index = 0;
                    continue;
                }
                partLength = index + pave->header_size+ pave->payload_size;
            }
            //***************************************************************************
            //   After all is correct just fill in encoded image data and publish
            //***************************************************************************
            message->data.assign(part+index+pave->header_size, part+index+pave->header_size+pave->payload_size);
            this->pub.publish(message);
            //***************************************************************************
            //  If the buffer contains more than the payload set up the index to point
            //  at the end of this packet (potentially start of next)
            //***************************************************************************
            if(partLength - index - pave->header_size > pave->payload_size)
                index += pave->header_size + pave->payload_size;
            else
                index = 0;
        }
        ROS_INFO("[%s]Closing socket.", this->name.c_str());//, socketNumber, flag, ros::ok());
        close(socketNumber);
    }
}

<|endoftext|>


<commit_before>#include "Geometry.h"
#include <math.h>

inline bool siteToLeft(Site* s1, Site* s2){
	if (s1->p[0] < s2->p[0] ||
		(s1->p[0] == s2->p[0] && s1->p[1] < s2->p[1]))
		return true;
	return false;
}

Point2 circumcenter(Point2 A, Point2 B, Point2 C){
	double dA = A.distanceFromOriginSquared();
	double dB = B.distanceFromOriginSquared();
	double dC = C.distanceFromOriginSquared();

	double denom = 2.0 * (A[0]*(C[1] - B[1]) + B[0]*(A[1] - C[1]) + C[0]*(B[1] - A[1]));

	Point2 center;
	center[0] = (dA*(C[1] - B[1]) + dB*(A[1] - C[1]) + dC*(B[1] - A[1])) / denom;
	center[1] = -(dA*(C[0] - B[0]) + dB*(A[0] - C[0]) + dC*(B[0] - A[0])) / denom;

	return center;
}

void findParabolaIntersections(Point2& focus1, Point2& focus2, double directrixHeight,
	Point2& intersection1, Point2& intersection2){

	double bmc1 = focus1[1] - directrixHeight;
	double a1 = 1 / (2.0*bmc1);
	double b1 = -focus1[0] / bmc1;
	double c1 = (focus1[0]*focus1[0] + focus1[1]*focus1[1] - directrixHeight*directrixHeight) / (2.0*bmc1);

	double bmc2 = focus2[1] - directrixHeight;
	double a2 = 1 / (2.0*bmc2);
	double b2 = -focus2[0] / bmc2;
	double c2 = (focus2[0]*focus2[0] + focus2[1]*focus2[1] - directrixHeight*directrixHeight) / (2.0*bmc2);

	double a = a2 - a1;
	double b = b2 - b1;
	double c = c2 - c1;

	if (bmc1 == 0.0){
		double x = focus1[0];
		intersection1[0] = intersection2[0] = x;
		intersection1[1] = intersection2[1] = a2*x*x + b2*x + c2;
	}
	else if (bmc2 == 0.0){
		double x = focus2[0];
		intersection1[0] = intersection2[0] = focus2[0];
		intersection1[1] = intersection2[1] = a1*x*x + b1*x + c1;
	}
	else{
		intersection1[0] = (-b - sqrt(b*b - 4.0*a*c)) / (2.0*a);
		intersection2[0] = (-b + sqrt(b*b - 4.0*a*c)) / (2.0*a);

		intersection1[1] = a1*intersection1[0] * intersection1[0] + b1*intersection1[0] + c1;
		intersection2[1] = a2*intersection2[0] * intersection2[0] + b2*intersection2[0] + c2;
	}
}<commit_msg>testing ssh keys<commit_after>#include "Geometry.h"
#include <math.h>

inline bool siteToLeft(Site* s1, Site* s2){
	if (s1->p[0] < s2->p[0] ||
		(s1->p[0] == s2->p[0] && s1->p[1] < s2->p[1]))
		return true;
	return false;
}

Point2 circumcenter(Point2 A, Point2 B, Point2 C){
	double dA = A.distanceFromOriginSquared();
	double dB = B.distanceFromOriginSquared();
	double dC = C.distanceFromOriginSquared();

	double denom = 2.0 * (A[0]*(C[1] - B[1]) + B[0]*(A[1] - C[1]) + C[0]*(B[1] - A[1]));

	Point2 center;
	center[0] = (dA*(C[1] - B[1]) + dB*(A[1] - C[1]) + dC*(B[1] - A[1])) / denom;
	center[1] = -(dA*(C[0] - B[0]) + dB*(A[0] - C[0]) + dC*(B[0] - A[0])) / denom;

	return center;
}

void findParabolaIntersections(Point2& focus1, Point2& focus2, double directrixHeight,
	Point2& intersection1, Point2& intersection2){

	double bmc1 = focus1[1] - directrixHeight;
	double a1 = 1 / (2.0*bmc1);
	double b1 = -focus1[0] / bmc1;
	double c1 = (focus1[0]*focus1[0] + focus1[1]*focus1[1] - directrixHeight*directrixHeight) / (2.0*bmc1);

	double bmc2 = focus2[1] - directrixHeight;
	double a2 = 1 / (2.0*bmc2);
	double b2 = -focus2[0] / bmc2;
	double c2 = (focus2[0]*focus2[0] + focus2[1]*focus2[1] - directrixHeight*directrixHeight) / (2.0*bmc2);

	double a = a2 - a1;
	double b = b2 - b1;
	double c = c2 - c1;

	if (bmc1 == 0.0){
		double x = focus1[0];
		intersection1[0] = intersection2[0] = x;
		intersection1[1] = intersection2[1] = a2*x*x + b2*x + c2;
	}
	else if (bmc2 == 0.0){
		double x = focus2[0];
		intersection1[0] = intersection2[0] = focus2[0];
		intersection1[1] = intersection2[1] = a1*x*x + b1*x + c1;
	}
	else{
		intersection1[0] = (-b - sqrt(b*b - 4.0*a*c)) / (2.0*a);
		intersection2[0] = (-b + sqrt(b*b - 4.0*a*c)) / (2.0*a);

		intersection1[1] = a1*intersection1[0] * intersection1[0] + b1*intersection1[0] + c1;
		intersection2[1] = a2*intersection2[0] * intersection2[0] + b2*intersection2[0] + c2;
	}
}
<|endoftext|>


<commit_before>#include "gamecontrol.h"

#include <core/eventsmanager.h>
#include <core/joystickevent.h>
#include <core/keyboardevent.h>

#include "ui.h"
#include "inti.h"
#include "killa.h"

GameControl::GameControl(Object* parent, ObjectID id)
	: Object(parent,id), m_inti(nullptr),m_killa(nullptr)
{
	m_inti = new Inti(this,"inti");
    m_killa = new Killa(this,"killa");

    m_killa->set_active(false);

	m_inti->set_position(0,0);
    m_killa->set_position(0,0);

    Interface *ui = new Interface(nullptr,"ui",this);

    add_child(ui);
	add_child(m_inti);
	add_child(m_killa);
    Environment *env = Environment::get_instance();
    env->events_manager->register_listener(this);
}

GameControl::~GameControl()
{
    delete m_inti;
    delete m_killa;
    Environment *env = Environment::get_instance();
    env->events_manager->unregister_listener(this);
}

Object*
GameControl::get_main_char()
{
    if (m_inti->active())
        return m_inti;
	return m_killa;
}

void
GameControl::swap_char(){
    if (m_inti->active())
    {
        m_inti->set_active(false);
        m_killa->set_active(true);
    }
    else
    {
        m_inti->set_active(true);
        m_killa->set_active(false);
    }
}

void
GameControl::draw_self()
{
}

void
GameControl::update_self(unsigned long elapsed)
{
}

bool
GameControl::on_event(const KeyboardEvent& event)
{
	switch (event.state())
	{
	case KeyboardEvent::PRESSED:
		switch (event.key())
		{
		default:
			break;
		}
		break;

	case KeyboardEvent::RELEASED:
		switch (event.key())
		{
		case KeyboardEvent::C:
			swap_char();
			return true;
		default:
			break;
		}
		break;
	}
	return false;
}

bool
GameControl::on_event(const JoyStickEvent& event)
{
	return false;
}
<commit_msg>Adicionando controle para trocar de personagem<commit_after>#include "gamecontrol.h"

#include <core/eventsmanager.h>
#include <core/joystickevent.h>
#include <core/keyboardevent.h>

#include "ui.h"
#include "inti.h"
#include "killa.h"

GameControl::GameControl(Object* parent, ObjectID id)
	: Object(parent,id), m_inti(nullptr),m_killa(nullptr)
{
	m_inti = new Inti(this,"inti");
    m_killa = new Killa(this,"killa");

    m_killa->set_active(false);

	m_inti->set_position(0,0);
    m_killa->set_position(0,0);

    Interface *ui = new Interface(nullptr,"ui",this);

    add_child(ui);
	add_child(m_inti);
	add_child(m_killa);
    Environment *env = Environment::get_instance();
    env->events_manager->register_listener(this);
}

GameControl::~GameControl()
{
    delete m_inti;
    delete m_killa;
    Environment *env = Environment::get_instance();
    env->events_manager->unregister_listener(this);
}

Object*
GameControl::get_main_char()
{
    if (m_inti->active())
        return m_inti;
	return m_killa;
}

void
GameControl::swap_char(){
    if (m_inti->active())
    {
        m_inti->set_active(false);
        m_killa->set_active(true);
    }
    else
    {
        m_inti->set_active(true);
        m_killa->set_active(false);
    }
}

void
GameControl::draw_self()
{
}

void
GameControl::update_self(unsigned long elapsed)
{
}

bool
GameControl::on_event(const KeyboardEvent& event)
{
	switch (event.state())
	{
	case KeyboardEvent::PRESSED:
		switch (event.key())
		{
		default:
			break;
		}
		break;

	case KeyboardEvent::RELEASED:
		switch (event.key())
		{
		case KeyboardEvent::C:
			swap_char();
			return true;
		default:
			break;
		}
		break;
	}
	return false;
}

bool
GameControl::on_event(const JoyStickEvent& event)
{
	switch (event.state())
	{
	case JoyStickEvent::PRESSED:
		switch (event.button())
		{
		default:
			break;
		}
		break;

	case JoyStickEvent::RELEASED:
		switch (event.button())
		{
		case JoyStickEvent::TRIANGLE:
			swap_char();
			return true;
		default:
			break;
		}
		break;
	}
	return false;
}
<|endoftext|>


<commit_before>#include "system/state.hh"
#include <iostream>
#include <fstream>
#include "common/array.hh"

using namespace divine;

namespace divine {

    class succ_container_t: public divine::array_t<state_t>
    {
    public:
	//!A constructor (only calls a constructor of array_t<state_t> with
	//! parameters 4096 (preallocation) and 16 (allocation step).
    succ_container_t(): array_t<state_t>(4096, 16) {}
	//!A destructor.
	~succ_container_t() {}
    };
};

// added interface functions
bool        (*lib_system_with_property)();
size_t      (*lib_get_state_variable_count)();
const char* (*lib_get_state_variable_name)(int var);
size_t      (*lib_get_state_variable_type_count)();
const char* (*lib_get_state_variable_type_name)(int type);
const int   (*lib_get_state_variable_type)(int var);
size_t      (*lib_get_state_variable_type_value_count)(int type);
const char* (*lib_get_state_variable_type_value)(int type, int value);
void        (*lib_project_state_to_int_array)(state_t state, int* proj);
void        (*lib_project_int_array_to_state)(int* proj, state_t state);
int*        (*lib_get_transition_proj)(int trans);
int         (*lib_get_transition_succ)(size_int_t transition, state_t state, succ_container_t & succ_container);
int         (*lib_get_transition_count)();
divine::state_t (*lib_new_state)();

// original interface functions
int         (*lib_get_succ)(state_t, succ_container_t &);
bool        (*lib_is_accepting)(state_t);
divine::state_t (*lib_get_initial_state)();
void        (*lib_print_state)(state_t, std::ostream & );
bool        (*lib_is_in_accepting_component)(state_t state);

extern "C" {

#include "runtime.h"
#include "dve-greybox.h"
#include "dm/dm.h"
#include "chunk_support.h"
#include <dlfcn.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

static void dve_popt(poptContext con,
               enum poptCallbackReason reason,
                            const struct poptOption * opt,
                             const char * arg, void * data){
	(void)con;(void)opt;(void)arg;(void)data;
	switch(reason){
	case POPT_CALLBACK_REASON_PRE:
		break;
	case POPT_CALLBACK_REASON_POST:
		GBregisterLoader("dve", DVEcompileGreyboxModel);
		GBregisterLoader("dveC",DVEloadGreyboxModel);
		Warning(info,"Precompiled divine module initialized");
		return;
	case POPT_CALLBACK_REASON_OPTION:
		break;
	}
	Fatal(1,error,"unexpected call to dve_popt");
}

struct poptOption dve_options[]= {
	{ NULL, 0 , POPT_ARG_CALLBACK|POPT_CBFLAG_POST|POPT_CBFLAG_SKIPOPTION , (void*)&dve_popt, 0 , NULL , NULL },
	POPT_TABLEEND
};

typedef struct grey_box_context {
    int todo;
} *gb_context_t;

static void divine_get_initial_state(int* state)
{
    divine::state_t s = lib_get_initial_state();
    lib_project_state_to_int_array(s, state);
}

static lts_type_t ltstype;
static matrix_t dm_info;
static matrix_t sl_info;
static divine::succ_container_t cb_cont;
static void* dlHandle = NULL;
static char templatename[] = "/tmp/ltsmin-XXXXXX";

static int
succ_callback(TransitionCB cb, void* context)
{
    int dummy = 42; // dummy to work with --cache
    int result = cb_cont.size();
    for(size_t i=0; i < (size_t)result;++i)
    {
        int dst[lib_get_state_variable_count()];
        lib_project_state_to_int_array(cb_cont[i], dst);
        cb(context, &dummy, dst);
    }
    cb_cont.clear();
    return result;
}

static int
divine_get_transitions_all(model_t self, int*src, TransitionCB cb, void*context)
{
    (void)self;
    divine::state_t s = lib_new_state();
    lib_project_int_array_to_state(src, s);
    lib_get_succ(s, cb_cont);
    return succ_callback(cb, context);
}

static int
divine_get_transitions_long(model_t self, int group, int*src, TransitionCB cb, void*context)
{
    (void)self;
    divine::state_t s = lib_new_state();
    lib_project_int_array_to_state(src, s);
    lib_get_transition_succ(group, s, cb_cont);
    return succ_callback(cb, context);
}

void DVEexit()
{
    // close dveC library
    if (dlHandle != NULL)
    {
        dlclose(dlHandle);

        char rmcmd[4096];
        if (snprintf(rmcmd, sizeof rmcmd, "rm -rf %s", templatename) < (ssize_t)sizeof rmcmd)
        {
            // remove!
            system(rmcmd);
        }
    }
}

void DVEcompileGreyboxModel(model_t model, const char *filename){
    // check file exists
    struct stat st;
    if (stat(filename, &st) != 0)
        FatalCall (1, error, "File not found: %s ", filename);

    // check /tmp
    if (stat("/tmp", &st))
        FatalCall (1, error, "Can't access /tmp for temporary compilation");

    // get temporary directory
    char* tmpdir = mkdtemp(templatename);
    if (!tmpdir)
        FatalCall (1, error, "Can't create temporary directory for compilation");

    char command[4096];
    if (snprintf(command, sizeof command, "cp %s %s", filename, tmpdir) < (ssize_t)sizeof command)
    {
        system(command);

        // compile the dve model
        if (snprintf(command, sizeof command, "divine.precompile %s/%s", tmpdir, filename) < (ssize_t)sizeof command)
        {
            system(command);

            // check existence dveC model
            snprintf(command, sizeof command, "%s/%sC", tmpdir, filename);
            if (stat(command, &st) != 0)
            {
                FatalCall (1, error, "Something went wrong with creation of %s ", command);
            }

            // all good, continue
            atexit(DVEexit); // hopefully this works :), if not, keep garbage

            DVEloadGreyboxModel(model, command);
            return;
        } else {
            FatalCall (1, error, "Problems occured when compiling %s/%s", tmpdir, filename);
        }
    }
    FatalCall (1, error, "Can't copy, paths too long ");
}

void DVEloadGreyboxModel(model_t model, const char *filename){
	gb_context_t ctx=(gb_context_t)RTmalloc(sizeof(struct grey_box_context));
	GBsetContext(model,ctx);

    // Open dveC file
    char* abs_filename = realpath(filename, NULL);
    if (abs_filename) {
        dlHandle = dlopen(abs_filename, RTLD_LAZY);
        free(abs_filename);
        if (dlHandle == NULL)
        {
            FatalCall (1, error, "%s, Library \"%s\" is not reachable", dlerror(), filename);
            return;
        }
    } else {
        FatalCall (1, error, "%s, Library \"%s\" is not found", dlerror(), filename);
    }

    // get functions
    lib_get_succ = (int(*)(divine::state_t, divine::succ_container_t &))
	dlsym( dlHandle, "lib_get_succ");
    lib_is_accepting = (bool(*)(divine::state_t))
	dlsym( dlHandle, "lib_is_accepting");
    lib_is_in_accepting_component = (bool(*)(divine::state_t))
	dlsym( dlHandle, "lib_is_in_accepting_component");
    lib_get_initial_state = (divine::state_t(*)())
	dlsym( dlHandle, "lib_get_initial_state");
    lib_print_state = (void(*)(divine::state_t, std::ostream &))
	dlsym( dlHandle, "lib_print_state");

    if (lib_get_succ == NULL || lib_is_accepting == NULL ||
        lib_is_in_accepting_component == NULL || lib_get_initial_state == NULL ||
        lib_print_state == NULL) {
        FatalCall (1, error, "Library \"%s\" doesn't export the required functions", filename);
    }

    // added interface functions
    lib_system_with_property = (bool (*)())
        RTdlsym (filename, dlHandle, "lib_system_with_property");
    lib_get_state_variable_count = (size_t (*)())
        RTdlsym (filename, dlHandle, "lib_get_state_variable_count");
    lib_get_state_variable_name = (const char* (*)(int var))
        RTdlsym (filename, dlHandle, "lib_get_state_variable_name" );
    lib_get_state_variable_type_count = (size_t (*)())
        RTdlsym (filename, dlHandle, "lib_get_state_variable_type_count");
    lib_get_state_variable_type_name = (const char* (*)(int type))
        RTdlsym (filename, dlHandle, "lib_get_state_variable_type_name");
    lib_get_state_variable_type  = (const int (*)(int var))
        RTdlsym (filename, dlHandle, "lib_get_state_variable_type");
    lib_get_state_variable_type_value_count = (size_t (*)(int))
        RTdlsym (filename, dlHandle, "lib_get_state_variable_type_value_count");
    lib_get_state_variable_type_value = (const char* (*)(int type, int value))
        RTdlsym (filename, dlHandle, "lib_get_state_variable_type_value");
    lib_project_state_to_int_array = (void (*)(state_t state, int* proj))
        RTdlsym (filename, dlHandle, "lib_project_state_to_int_array");
    lib_project_int_array_to_state = (void (*)(int* proj, state_t state))
        RTdlsym (filename, dlHandle, "lib_project_int_array_to_state");
    lib_get_transition_proj = (int* (*)(int trans))
        RTdlsym (filename, dlHandle, "lib_get_transition_proj");
    lib_get_transition_succ = (int (*)(size_int_t transition, state_t state, succ_container_t & succ_container))
        RTdlsym (filename, dlHandle, "lib_get_transition_succ");
    lib_get_transition_count = (int (*)())
        RTdlsym (filename, dlHandle, "lib_get_transition_count");
    lib_new_state = (divine::state_t (*)())
        RTdlsym (filename, dlHandle, "lib_new_state");

    // check system_with_property
    if (lib_system_with_property()) {
        Fatal(1,error,"DVE models with properties are currently not supported!");
    }

    // get ltstypes
    int state_length = lib_get_state_variable_count();
    ltstype=lts_type_create();

    // adding types
    int ntypes = lib_get_state_variable_type_count();
    for(int i=0; i < ntypes; i++) {
        const char* type_name = lib_get_state_variable_type_name(i);
        if (lts_type_add_type(ltstype,type_name,NULL) != i) {
            Fatal(1,error,"wrong type number");
        }
    }

    lts_type_set_state_length(ltstype, state_length);

    // set state name & type
    for(int i=0; i < state_length; ++i)
    {
        const char* name = lib_get_state_variable_name(i);
        const int   type = lib_get_state_variable_type(i);
        lts_type_set_state_name(ltstype,i,name);
        lts_type_set_state_typeno(ltstype,i,type);
    }

    GBsetLTStype(model, ltstype);

    // setting values for types
    // chunk_str doesn't work
    for(int i=0; i < ntypes; i++) {
        int type_value_count = lib_get_state_variable_type_value_count(i);
        if (type_value_count > 0) {
            for(int j=0; j < type_value_count; ++j) {
                const char* type_value = lib_get_state_variable_type_value(i, j);
                GBchunkPut(model, i, (chunk){strlen(type_value),(char*)type_value});
            }
        }
    }
    lts_type_validate(ltstype);

    int ngroups = lib_get_transition_count();
	dm_create(&dm_info, ngroups, state_length);
    for(int i=0; i < dm_nrows(&dm_info); i++) {
        int* proj = lib_get_transition_proj(i);
		for(int j=0; j<state_length; j++) {
            if (proj[j]) dm_set(&dm_info, i, j);
        }
    }
    GBsetDMInfo(model, &dm_info);

    // there are no state labels
    dm_create(&sl_info, 0, state_length);
    GBsetStateLabelInfo(model, &sl_info);

    // get initial state
	int state[state_length];
    divine_get_initial_state(state);
    GBsetInitialState(model,state);

    GBsetNextStateAll  (model, divine_get_transitions_all);
    GBsetNextStateLong (model, divine_get_transitions_long);
}

} // extern "C"
<commit_msg>Fixed path errors in dve compilation<commit_after>#include "system/state.hh"
#include <iostream>
#include <fstream>
#include "common/array.hh"

using namespace divine;

namespace divine {

    class succ_container_t: public divine::array_t<state_t>
    {
    public:
	//!A constructor (only calls a constructor of array_t<state_t> with
	//! parameters 4096 (preallocation) and 16 (allocation step).
    succ_container_t(): array_t<state_t>(4096, 16) {}
	//!A destructor.
	~succ_container_t() {}
    };
};

// added interface functions
bool        (*lib_system_with_property)();
size_t      (*lib_get_state_variable_count)();
const char* (*lib_get_state_variable_name)(int var);
size_t      (*lib_get_state_variable_type_count)();
const char* (*lib_get_state_variable_type_name)(int type);
const int   (*lib_get_state_variable_type)(int var);
size_t      (*lib_get_state_variable_type_value_count)(int type);
const char* (*lib_get_state_variable_type_value)(int type, int value);
void        (*lib_project_state_to_int_array)(state_t state, int* proj);
void        (*lib_project_int_array_to_state)(int* proj, state_t state);
int*        (*lib_get_transition_proj)(int trans);
int         (*lib_get_transition_succ)(size_int_t transition, state_t state, succ_container_t & succ_container);
int         (*lib_get_transition_count)();
divine::state_t (*lib_new_state)();

// original interface functions
int         (*lib_get_succ)(state_t, succ_container_t &);
bool        (*lib_is_accepting)(state_t);
divine::state_t (*lib_get_initial_state)();
void        (*lib_print_state)(state_t, std::ostream & );
bool        (*lib_is_in_accepting_component)(state_t state);

extern "C" {

#include "runtime.h"
#include "dve-greybox.h"
#include "dm/dm.h"
#include "chunk_support.h"
#include <dlfcn.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

static void dve_popt(poptContext con,
               enum poptCallbackReason reason,
                            const struct poptOption * opt,
                             const char * arg, void * data){
	(void)con;(void)opt;(void)arg;(void)data;
	switch(reason){
	case POPT_CALLBACK_REASON_PRE:
		break;
	case POPT_CALLBACK_REASON_POST:
		GBregisterLoader("dve", DVEcompileGreyboxModel);
		GBregisterLoader("dveC",DVEloadGreyboxModel);
		Warning(info,"Precompiled divine module initialized");
		return;
	case POPT_CALLBACK_REASON_OPTION:
		break;
	}
	Fatal(1,error,"unexpected call to dve_popt");
}

struct poptOption dve_options[]= {
	{ NULL, 0 , POPT_ARG_CALLBACK|POPT_CBFLAG_POST|POPT_CBFLAG_SKIPOPTION , (void*)&dve_popt, 0 , NULL , NULL },
	POPT_TABLEEND
};

typedef struct grey_box_context {
    int todo;
} *gb_context_t;

static void divine_get_initial_state(int* state)
{
    divine::state_t s = lib_get_initial_state();
    lib_project_state_to_int_array(s, state);
}

static lts_type_t ltstype;
static matrix_t dm_info;
static matrix_t sl_info;
static divine::succ_container_t cb_cont;
static void* dlHandle = NULL;
static char templatename[4096];

static int
succ_callback(TransitionCB cb, void* context)
{
    int dummy = 42; // dummy to work with --cache
    int result = cb_cont.size();
    for(size_t i=0; i < (size_t)result;++i)
    {
        int dst[lib_get_state_variable_count()];
        lib_project_state_to_int_array(cb_cont[i], dst);
        cb(context, &dummy, dst);
    }
    cb_cont.clear();
    return result;
}

static int
divine_get_transitions_all(model_t self, int*src, TransitionCB cb, void*context)
{
    (void)self;
    divine::state_t s = lib_new_state();
    lib_project_int_array_to_state(src, s);
    lib_get_succ(s, cb_cont);
    return succ_callback(cb, context);
}

static int
divine_get_transitions_long(model_t self, int group, int*src, TransitionCB cb, void*context)
{
    (void)self;
    divine::state_t s = lib_new_state();
    lib_project_int_array_to_state(src, s);
    lib_get_transition_succ(group, s, cb_cont);
    return succ_callback(cb, context);
}

void DVEexit()
{
    // close dveC library
    if (dlHandle == NULL)
        return;
    dlclose(dlHandle);

    if (strlen (templatename) == 0)
        return;

    char rmcmd[4096];
    if (snprintf(rmcmd, sizeof rmcmd, "rm -rf %s", templatename) < (ssize_t)sizeof rmcmd) {
        // remove!
        system(rmcmd);
    }
}

#define SYSFAIL(cond,...)                                               \
    do { if (cond) FatalCall(__VA_ARGS__) Fatal(__VA_ARGS__); } while (0)
void DVEcompileGreyboxModel(model_t model, const char *filename){
    struct stat st;
    int ret;
    // check file exists
    if ((ret = stat (filename, &st)) != 0)
        FatalCall (1, error, "%s", filename);

    char *abs_filename = realpath (filename, NULL);
    if (abs_filename == NULL)
        FatalCall (1, error, "Cannot determine absolute path of %s", filename);

    // get temporary directory
    const char *tmpdir = getenv("TMPDIR");
    if (tmpdir == NULL)
        tmpdir = "/tmp";

    if ((ret = stat (tmpdir, &st)) != 0)
        FatalCall(1, error, "Cannot access `%s' for temporary compilation",
                  tmpdir);

    if (snprintf (templatename, sizeof templatename, "%s/ltsmin-XXXXXX", tmpdir) >= (ssize_t)sizeof templatename)
        Fatal (1, error, "Path too long: %s", tmpdir);

    atexit (DVEexit);                   // cleanup
    if ((tmpdir = mkdtemp(templatename)) == NULL)
        FatalCall(1, error, "Cannot create temporary directory for compilation: %s", tmpdir);

    // copy
    char command[4096];
    // XXX shell escape filename
    if (snprintf (command, sizeof command, "cp '%s' '%s'", abs_filename, tmpdir) >= (ssize_t)sizeof command)
        Fatal (1, error, "Paths to long: cannot copy `%s' to `%s'", abs_filename, tmpdir);

    if ((ret = system (command)) != 0)
        SYSFAIL(ret < 0, 1, error, "Command failed with exit code %d: %s", ret, command);

    // compile dve model
    char *basename = strrchr (abs_filename, '/');
    if (basename == NULL)
        Fatal (1, error, "Could not extract basename of file: %s", abs_filename);
    ++basename;                         // skip '/'

    if (snprintf(command, sizeof command, "divine.precompile '%s/%s'", tmpdir, basename) >= (ssize_t)sizeof command)
        Fatal (1, error, "Cannot copy `%s' to `%s', paths too long", abs_filename, tmpdir);

    if ((ret = system(command)) != 0)
        SYSFAIL(ret < 0, 1, error, "Command failed with exit code %d: %s", ret, command);

    // check existence of dveC file
    char dveC_fname[4096];
    if (snprintf (dveC_fname, sizeof dveC_fname, "%s/%sC", tmpdir, basename) >= (ssize_t)sizeof dveC_fname)
        Fatal (1, error, "Path too long: %s", tmpdir);

    if ((ret = stat (dveC_fname, &st)) != 0)
        SYSFAIL(ret < 0, 1, error, "File not found: %s", dveC_fname);

    DVEloadGreyboxModel(model, dveC_fname);
}
#undef SYSFAIL

void DVEloadGreyboxModel(model_t model, const char *filename){
	gb_context_t ctx=(gb_context_t)RTmalloc(sizeof(struct grey_box_context));
	GBsetContext(model,ctx);

    // Open dveC file
    char* abs_filename = realpath(filename, NULL);
    if (abs_filename) {
        dlHandle = dlopen(abs_filename, RTLD_LAZY);
        free(abs_filename);
        if (dlHandle == NULL)
        {
            Fatal (1, error, "%s, Library \"%s\" is not reachable", dlerror(), filename);
            return;
        }
    } else {
        Fatal (1, error, "%s, Library \"%s\" is not found", dlerror(), filename);
    }

    // get functions
    lib_get_succ = (int(*)(divine::state_t, divine::succ_container_t &))
	dlsym( dlHandle, "lib_get_succ");
    lib_is_accepting = (bool(*)(divine::state_t))
	dlsym( dlHandle, "lib_is_accepting");
    lib_is_in_accepting_component = (bool(*)(divine::state_t))
	dlsym( dlHandle, "lib_is_in_accepting_component");
    lib_get_initial_state = (divine::state_t(*)())
	dlsym( dlHandle, "lib_get_initial_state");
    lib_print_state = (void(*)(divine::state_t, std::ostream &))
	dlsym( dlHandle, "lib_print_state");

    if (lib_get_succ == NULL || lib_is_accepting == NULL ||
        lib_is_in_accepting_component == NULL || lib_get_initial_state == NULL ||
        lib_print_state == NULL) {
        Fatal (1, error, "Library \"%s\" doesn't export the required functions", filename);
    }

    // added interface functions
    lib_system_with_property = (bool (*)())
        RTdlsym (filename, dlHandle, "lib_system_with_property");
    lib_get_state_variable_count = (size_t (*)())
        RTdlsym (filename, dlHandle, "lib_get_state_variable_count");
    lib_get_state_variable_name = (const char* (*)(int var))
        RTdlsym (filename, dlHandle, "lib_get_state_variable_name" );
    lib_get_state_variable_type_count = (size_t (*)())
        RTdlsym (filename, dlHandle, "lib_get_state_variable_type_count");
    lib_get_state_variable_type_name = (const char* (*)(int type))
        RTdlsym (filename, dlHandle, "lib_get_state_variable_type_name");
    lib_get_state_variable_type  = (const int (*)(int var))
        RTdlsym (filename, dlHandle, "lib_get_state_variable_type");
    lib_get_state_variable_type_value_count = (size_t (*)(int))
        RTdlsym (filename, dlHandle, "lib_get_state_variable_type_value_count");
    lib_get_state_variable_type_value = (const char* (*)(int type, int value))
        RTdlsym (filename, dlHandle, "lib_get_state_variable_type_value");
    lib_project_state_to_int_array = (void (*)(state_t state, int* proj))
        RTdlsym (filename, dlHandle, "lib_project_state_to_int_array");
    lib_project_int_array_to_state = (void (*)(int* proj, state_t state))
        RTdlsym (filename, dlHandle, "lib_project_int_array_to_state");
    lib_get_transition_proj = (int* (*)(int trans))
        RTdlsym (filename, dlHandle, "lib_get_transition_proj");
    lib_get_transition_succ = (int (*)(size_int_t transition, state_t state, succ_container_t & succ_container))
        RTdlsym (filename, dlHandle, "lib_get_transition_succ");
    lib_get_transition_count = (int (*)())
        RTdlsym (filename, dlHandle, "lib_get_transition_count");
    lib_new_state = (divine::state_t (*)())
        RTdlsym (filename, dlHandle, "lib_new_state");

    // check system_with_property
    if (lib_system_with_property()) {
        Fatal(1,error,"DVE models with properties are currently not supported!");
    }

    // get ltstypes
    int state_length = lib_get_state_variable_count();
    ltstype=lts_type_create();

    // adding types
    int ntypes = lib_get_state_variable_type_count();
    for(int i=0; i < ntypes; i++) {
        const char* type_name = lib_get_state_variable_type_name(i);
        if (lts_type_add_type(ltstype,type_name,NULL) != i) {
            Fatal(1,error,"wrong type number");
        }
    }

    lts_type_set_state_length(ltstype, state_length);

    // set state name & type
    for(int i=0; i < state_length; ++i)
    {
        const char* name = lib_get_state_variable_name(i);
        const int   type = lib_get_state_variable_type(i);
        lts_type_set_state_name(ltstype,i,name);
        lts_type_set_state_typeno(ltstype,i,type);
    }

    GBsetLTStype(model, ltstype);

    // setting values for types
    // chunk_str doesn't work
    for(int i=0; i < ntypes; i++) {
        int type_value_count = lib_get_state_variable_type_value_count(i);
        if (type_value_count > 0) {
            for(int j=0; j < type_value_count; ++j) {
                const char* type_value = lib_get_state_variable_type_value(i, j);
                GBchunkPut(model, i, (chunk){strlen(type_value),(char*)type_value});
            }
        }
    }
    lts_type_validate(ltstype);

    int ngroups = lib_get_transition_count();
	dm_create(&dm_info, ngroups, state_length);
    for(int i=0; i < dm_nrows(&dm_info); i++) {
        int* proj = lib_get_transition_proj(i);
		for(int j=0; j<state_length; j++) {
            if (proj[j]) dm_set(&dm_info, i, j);
        }
    }
    GBsetDMInfo(model, &dm_info);

    // there are no state labels
    dm_create(&sl_info, 0, state_length);
    GBsetStateLabelInfo(model, &sl_info);

    // get initial state
	int state[state_length];
    divine_get_initial_state(state);
    GBsetInitialState(model,state);

    GBsetNextStateAll  (model, divine_get_transitions_all);
    GBsetNextStateLong (model, divine_get_transitions_long);
}

} // extern "C"
<|endoftext|>