<commit_before>
#include <string.h>
#include <math.h>

#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
#include <windows.h>

#include "GUI.h"

using namespace System;
using namespace System::Runtime::InteropServices;
using namespace Microsoft::Win32;

using namespace ExtIO_RedPitaya_TRX;

//---------------------------------------------------------------------------

#define EXTIO_API __declspec(dllexport) __stdcall

#define TCP_PORT 1001
#define TCP_ADDR "192.168.1.100"

SOCKET gSock[2] = {-1, -1};

char gBuffer[8192];

UInt32 gRate = 100000;
Int32 gCorr = 0;

UInt32 gFreq = 600000;
UInt32 gFreqMin = 100000;
UInt32 gFreqMax = 60000000;

bool gInitHW = false;

bool gExitThread = false;
bool gThreadRunning = false;

//---------------------------------------------------------------------------

ref class ManagedGlobals
{
  public:
    static GUI ^gGUI = nullptr;
    static RegistryKey ^gKey = nullptr;
};

//---------------------------------------------------------------------------

void (*ExtIOCallback)(int, int, float, void *) = 0;

static void SetRate(UInt32);
static void UpdateRate(UInt32);
static void SetCorr(Int32);

//---------------------------------------------------------------------------

DWORD WINAPI GeneratorThreadProc(__in LPVOID lpParameter)
{
  unsigned long size = 0;

  while(!gExitThread)
  {
    SleepEx(1, FALSE);
    if(gExitThread) break;

    ioctlsocket(gSock[1], FIONREAD, &size);

    while(size >= 8192)
    {
      recv(gSock[1], gBuffer, 8192, 0);

      if(ExtIOCallback) (*ExtIOCallback)(1024, 0, 0.0, gBuffer);

      ioctlsocket(gSock[1], FIONREAD, &size);
    }
  }
  gExitThread = false;
  gThreadRunning = false;
  return 0;
}

//---------------------------------------------------------------------------

static void StopThread()
{
  if(gThreadRunning)
  {
    gExitThread = true;
    while(gThreadRunning)
    {
      SleepEx(10, FALSE);
    }
  }
}

//---------------------------------------------------------------------------

static void StartThread()
{
  gExitThread = false;
  gThreadRunning = true;
  CreateThread(NULL, (SIZE_T)(64 * 1024), GeneratorThreadProc, NULL, 0, NULL);
}

//---------------------------------------------------------------------------

extern "C" int EXTIO_API SetHWLO(long LOfreq);

//---------------------------------------------------------------------------

extern "C"
bool EXTIO_API InitHW(char *name, char *model, int &type)
{
  String ^addrString;
  UInt32 rateIndex = 2;
  Int32 corr = 0;

  type = 7;

  strcpy(name, "Red Pitaya SDR TRX");
  strcpy(model, "");

  if(!gInitHW)
  {
    ManagedGlobals::gKey = Registry::CurrentUser->OpenSubKey("Software\\ExtIO_RedPitaya_TRX", true);
    if(!ManagedGlobals::gKey)
    {
      ManagedGlobals::gKey = Registry::CurrentUser->CreateSubKey("Software\\ExtIO_RedPitaya_TRX");
      ManagedGlobals::gKey->SetValue("IP Address", TCP_ADDR);
      ManagedGlobals::gKey->SetValue("Sample Rate", rateIndex);
      ManagedGlobals::gKey->SetValue("Freq. Corr.", corr);
    }

    ManagedGlobals::gGUI = gcnew GUI;
    addrString = ManagedGlobals::gKey->GetValue("IP Address")->ToString();
    ManagedGlobals::gGUI->addrValue->Text = addrString;

    rateIndex = Convert::ToUInt32(ManagedGlobals::gKey->GetValue("Sample Rate", 1));
    if(rateIndex < 0 || rateIndex > 5) rateIndex = 2;
    ManagedGlobals::gGUI->rateValue->SelectedIndex = rateIndex;
    ManagedGlobals::gGUI->rateCallback = UpdateRate;

    corr = Convert::ToInt32(ManagedGlobals::gKey->GetValue("Freq. Corr.", 0));
    if(corr < -100 || corr > 100) corr = 0;
    ManagedGlobals::gGUI->corrValue->Value = corr;
    ManagedGlobals::gGUI->corrCallback = SetCorr;

    SetRate(rateIndex);
    SetCorr(corr);

    gInitHW = true;
  }

  return gInitHW;
}

//---------------------------------------------------------------------------

extern "C"
bool EXTIO_API OpenHW()
{
  return gInitHW;
}

//---------------------------------------------------------------------------

extern "C"
int EXTIO_API StartHW(long LOfreq)
{
  WSADATA wsaData;
  struct sockaddr_in addr;
  String ^addrString;
  char *buffer;
  UInt32 command;
  int i;

  if(!gInitHW) return 0;

  WSAStartup(MAKEWORD(2, 2), &wsaData);

  addrString = ManagedGlobals::gGUI->addrValue->Text;
  ManagedGlobals::gKey->SetValue("IP Address", addrString);

  buffer = (char*)Marshal::StringToHGlobalAnsi(addrString).ToPointer();

  for(i = 0; i < 2; ++i)
  {
    gSock[i] = socket(AF_INET, SOCK_STREAM, 0);

    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(buffer);
    addr.sin_port = htons(TCP_PORT);

    connect(gSock[i], (struct sockaddr *)&addr, sizeof(addr));

    command = i;
    send(gSock[i], (char *)&command, 4, 0);
  }

  Marshal::FreeHGlobal(IntPtr(buffer));

  StopThread();
  gFreq = LOfreq;
  SetRate(ManagedGlobals::gGUI->rateValue->SelectedIndex);
  StartThread();

  return 1024;
}

//---------------------------------------------------------------------------

extern "C"
void EXTIO_API StopHW()
{
  StopThread();

  closesocket(gSock[1]);
  closesocket(gSock[0]);

  gSock[1] = -1;
  gSock[0] = -1;

  WSACleanup();
}

//---------------------------------------------------------------------------

extern "C"
void EXTIO_API CloseHW()
{
  gInitHW = false;
}

//---------------------------------------------------------------------------

extern "C"
void EXTIO_API SetCallback(void (*callback)(int, int, float, void *))
{
  ExtIOCallback = callback;
}

//---------------------------------------------------------------------------

extern "C"
int EXTIO_API SetHWLO(long LOfreq)
{
  int rc = 0;
  UInt32 buffer = 0;

  gFreq = LOfreq;

  // check limits
  if(gFreq < gFreqMin)
  {
    gFreq = gFreqMin;
    rc = -gFreqMin;
  }
  else if(gFreq > gFreqMax)
  {
    gFreq = gFreqMax;
    rc = gFreqMax;
  }

  if(gFreq != LOfreq && ExtIOCallback) (*ExtIOCallback)(-1, 101, 0.0, 0);

  buffer = (long)floor(gFreq*(1.0 + gCorr*1.0e-6) + 0.5);
  if(gSock[0] > 0) send(gSock[0], (char *)&buffer, 4, 0);

  return rc;
}

//---------------------------------------------------------------------------

static void SetRate(UInt32 rateIndex)
{
  switch(rateIndex)
  {
    case 0: gRate = 20000; gFreqMin = 10000; break;
    case 1: gRate = 50000; gFreqMin = 25000; break;
    case 2: gRate = 100000; gFreqMin = 50000; break;
    case 3: gRate = 250000; gFreqMin = 125000; break;
    case 4: gRate = 500000; gFreqMin = 250000; break;
    case 5: gRate = 1250000; gFreqMin = 625000; break;
  }

  if(ManagedGlobals::gKey) ManagedGlobals::gKey->SetValue("Sample Rate", rateIndex);

  rateIndex |= 1<<28;
  if(gSock[0] > 0) send(gSock[0], (char *)&rateIndex, 4, 0);

  SetHWLO(gFreq);
}

//---------------------------------------------------------------------------

static void UpdateRate(UInt32 rateIndex)
{
  SetRate(rateIndex);
  if(ExtIOCallback) (*ExtIOCallback)(-1, 100, 0.0, 0);
}

//---------------------------------------------------------------------------

static void SetCorr(Int32 corr)
{
  gCorr = corr;
  if(ManagedGlobals::gKey) ManagedGlobals::gKey->SetValue("Freq. Corr.", corr);
  SetHWLO(gFreq);
}

//---------------------------------------------------------------------------

extern "C"
long EXTIO_API GetHWLO()
{
  return gFreq;
}

//---------------------------------------------------------------------------

extern "C"
long EXTIO_API GetHWSR()
{
  return gRate;
}

//---------------------------------------------------------------------------

extern "C"
int EXTIO_API GetStatus()
{
  return 0;
}

//---------------------------------------------------------------------------

extern "C"
void EXTIO_API ShowGUI()
{
  if(ManagedGlobals::gGUI) ManagedGlobals::gGUI->ShowDialog();
}
<commit_msg>fix initial gFreqMin value in ExtIO_RedPitaya_TRX.cpp<commit_after>
#include <string.h>
#include <math.h>

#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
#include <windows.h>

#include "GUI.h"

using namespace System;
using namespace System::Runtime::InteropServices;
using namespace Microsoft::Win32;

using namespace ExtIO_RedPitaya_TRX;

//---------------------------------------------------------------------------

#define EXTIO_API __declspec(dllexport) __stdcall

#define TCP_PORT 1001
#define TCP_ADDR "192.168.1.100"

SOCKET gSock[2] = {-1, -1};

char gBuffer[8192];

UInt32 gRate = 100000;
Int32 gCorr = 0;

UInt32 gFreq = 600000;
UInt32 gFreqMin = 50000;
UInt32 gFreqMax = 60000000;

bool gInitHW = false;

bool gExitThread = false;
bool gThreadRunning = false;

//---------------------------------------------------------------------------

ref class ManagedGlobals
{
  public:
    static GUI ^gGUI = nullptr;
    static RegistryKey ^gKey = nullptr;
};

//---------------------------------------------------------------------------

void (*ExtIOCallback)(int, int, float, void *) = 0;

static void SetRate(UInt32);
static void UpdateRate(UInt32);
static void SetCorr(Int32);

//---------------------------------------------------------------------------

DWORD WINAPI GeneratorThreadProc(__in LPVOID lpParameter)
{
  unsigned long size = 0;

  while(!gExitThread)
  {
    SleepEx(1, FALSE);
    if(gExitThread) break;

    ioctlsocket(gSock[1], FIONREAD, &size);

    while(size >= 8192)
    {
      recv(gSock[1], gBuffer, 8192, 0);

      if(ExtIOCallback) (*ExtIOCallback)(1024, 0, 0.0, gBuffer);

      ioctlsocket(gSock[1], FIONREAD, &size);
    }
  }
  gExitThread = false;
  gThreadRunning = false;
  return 0;
}

//---------------------------------------------------------------------------

static void StopThread()
{
  if(gThreadRunning)
  {
    gExitThread = true;
    while(gThreadRunning)
    {
      SleepEx(10, FALSE);
    }
  }
}

//---------------------------------------------------------------------------

static void StartThread()
{
  gExitThread = false;
  gThreadRunning = true;
  CreateThread(NULL, (SIZE_T)(64 * 1024), GeneratorThreadProc, NULL, 0, NULL);
}

//---------------------------------------------------------------------------

extern "C" int EXTIO_API SetHWLO(long LOfreq);

//---------------------------------------------------------------------------

extern "C"
bool EXTIO_API InitHW(char *name, char *model, int &type)
{
  String ^addrString;
  UInt32 rateIndex = 2;
  Int32 corr = 0;

  type = 7;

  strcpy(name, "Red Pitaya SDR TRX");
  strcpy(model, "");

  if(!gInitHW)
  {
    ManagedGlobals::gKey = Registry::CurrentUser->OpenSubKey("Software\\ExtIO_RedPitaya_TRX", true);
    if(!ManagedGlobals::gKey)
    {
      ManagedGlobals::gKey = Registry::CurrentUser->CreateSubKey("Software\\ExtIO_RedPitaya_TRX");
      ManagedGlobals::gKey->SetValue("IP Address", TCP_ADDR);
      ManagedGlobals::gKey->SetValue("Sample Rate", rateIndex);
      ManagedGlobals::gKey->SetValue("Freq. Corr.", corr);
    }

    ManagedGlobals::gGUI = gcnew GUI;
    addrString = ManagedGlobals::gKey->GetValue("IP Address")->ToString();
    ManagedGlobals::gGUI->addrValue->Text = addrString;

    rateIndex = Convert::ToUInt32(ManagedGlobals::gKey->GetValue("Sample Rate", 1));
    if(rateIndex < 0 || rateIndex > 5) rateIndex = 2;
    ManagedGlobals::gGUI->rateValue->SelectedIndex = rateIndex;
    ManagedGlobals::gGUI->rateCallback = UpdateRate;

    corr = Convert::ToInt32(ManagedGlobals::gKey->GetValue("Freq. Corr.", 0));
    if(corr < -100 || corr > 100) corr = 0;
    ManagedGlobals::gGUI->corrValue->Value = corr;
    ManagedGlobals::gGUI->corrCallback = SetCorr;

    SetRate(rateIndex);
    SetCorr(corr);

    gInitHW = true;
  }

  return gInitHW;
}

//---------------------------------------------------------------------------

extern "C"
bool EXTIO_API OpenHW()
{
  return gInitHW;
}

//---------------------------------------------------------------------------

extern "C"
int EXTIO_API StartHW(long LOfreq)
{
  WSADATA wsaData;
  struct sockaddr_in addr;
  String ^addrString;
  char *buffer;
  UInt32 command;
  int i;

  if(!gInitHW) return 0;

  WSAStartup(MAKEWORD(2, 2), &wsaData);

  addrString = ManagedGlobals::gGUI->addrValue->Text;
  ManagedGlobals::gKey->SetValue("IP Address", addrString);

  buffer = (char*)Marshal::StringToHGlobalAnsi(addrString).ToPointer();

  for(i = 0; i < 2; ++i)
  {
    gSock[i] = socket(AF_INET, SOCK_STREAM, 0);

    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(buffer);
    addr.sin_port = htons(TCP_PORT);

    connect(gSock[i], (struct sockaddr *)&addr, sizeof(addr));

    command = i;
    send(gSock[i], (char *)&command, 4, 0);
  }

  Marshal::FreeHGlobal(IntPtr(buffer));

  StopThread();
  gFreq = LOfreq;
  SetRate(ManagedGlobals::gGUI->rateValue->SelectedIndex);
  StartThread();

  return 1024;
}

//---------------------------------------------------------------------------

extern "C"
void EXTIO_API StopHW()
{
  StopThread();

  closesocket(gSock[1]);
  closesocket(gSock[0]);

  gSock[1] = -1;
  gSock[0] = -1;

  WSACleanup();
}

//---------------------------------------------------------------------------

extern "C"
void EXTIO_API CloseHW()
{
  gInitHW = false;
}

//---------------------------------------------------------------------------

extern "C"
void EXTIO_API SetCallback(void (*callback)(int, int, float, void *))
{
  ExtIOCallback = callback;
}

//---------------------------------------------------------------------------

extern "C"
int EXTIO_API SetHWLO(long LOfreq)
{
  int rc = 0;
  UInt32 buffer = 0;

  gFreq = LOfreq;

  // check limits
  if(gFreq < gFreqMin)
  {
    gFreq = gFreqMin;
    rc = -gFreqMin;
  }
  else if(gFreq > gFreqMax)
  {
    gFreq = gFreqMax;
    rc = gFreqMax;
  }

  if(gFreq != LOfreq && ExtIOCallback) (*ExtIOCallback)(-1, 101, 0.0, 0);

  buffer = (long)floor(gFreq*(1.0 + gCorr*1.0e-6) + 0.5);
  if(gSock[0] > 0) send(gSock[0], (char *)&buffer, 4, 0);

  return rc;
}

//---------------------------------------------------------------------------

static void SetRate(UInt32 rateIndex)
{
  switch(rateIndex)
  {
    case 0: gRate = 20000; gFreqMin = 10000; break;
    case 1: gRate = 50000; gFreqMin = 25000; break;
    case 2: gRate = 100000; gFreqMin = 50000; break;
    case 3: gRate = 250000; gFreqMin = 125000; break;
    case 4: gRate = 500000; gFreqMin = 250000; break;
    case 5: gRate = 1250000; gFreqMin = 625000; break;
  }

  if(ManagedGlobals::gKey) ManagedGlobals::gKey->SetValue("Sample Rate", rateIndex);

  rateIndex |= 1<<28;
  if(gSock[0] > 0) send(gSock[0], (char *)&rateIndex, 4, 0);

  SetHWLO(gFreq);
}

//---------------------------------------------------------------------------

static void UpdateRate(UInt32 rateIndex)
{
  SetRate(rateIndex);
  if(ExtIOCallback) (*ExtIOCallback)(-1, 100, 0.0, 0);
}

//---------------------------------------------------------------------------

static void SetCorr(Int32 corr)
{
  gCorr = corr;
  if(ManagedGlobals::gKey) ManagedGlobals::gKey->SetValue("Freq. Corr.", corr);
  SetHWLO(gFreq);
}

//---------------------------------------------------------------------------

extern "C"
long EXTIO_API GetHWLO()
{
  return gFreq;
}

//---------------------------------------------------------------------------

extern "C"
long EXTIO_API GetHWSR()
{
  return gRate;
}

//---------------------------------------------------------------------------

extern "C"
int EXTIO_API GetStatus()
{
  return 0;
}

//---------------------------------------------------------------------------

extern "C"
void EXTIO_API ShowGUI()
{
  if(ManagedGlobals::gGUI) ManagedGlobals::gGUI->ShowDialog();
}
<|endoftext|>


<commit_before>/*************************************************************************
*    UrBackup - Client/Server backup system
*    Copyright (C) 2011-2014 Martin Raiber
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program 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 General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/

#include "vld.h"
#include <stdlib.h>
#include "SessionMgr.h"
#include "Server.h"
#include "stringtools.h"

CSessionMgr::CSessionMgr(void)
{
	sess_mutex=Server->createMutex();

	wait_cond=Server->createCondition();
	wait_mutex=Server->createMutex();

	stop_mutex=Server->createMutex();
	stop_cond=Server->createCondition();

	SESSIONID_LEN=30;//Server->Settings->getValue("SESSIONID_LEN",15);
	SESSION_TIMEOUT_S=1800;//Server->Settings->getValue("SESSION_TIMEOUT_S",600);

	for(unsigned char i=48;i<58;++i)
		Pool.push_back(i);
	for(unsigned char i=65;i<91;++i)
		Pool.push_back(i);
	for(unsigned char i=97;i<122;++i)
		Pool.push_back(i);

	run=false;
}

CSessionMgr::~CSessionMgr()
{
	{
	  IScopedLock lock( sess_mutex );
	  Server->Log("removing sessions...");
	  if(!mSessions.empty() )
	  {
		  std::vector<std::wstring> sesids;
		  for(std::map<std::wstring, SUser*>::iterator i=mSessions.begin();i!=mSessions.end();++i)
		  {
			  sesids.push_back(i->first);
		  }

		  lock.relock(NULL);

		  for(size_t i=0;i<sesids.size();++i)
		  {
			  RemoveSession(sesids[i]);
		  }
	  }
	  Server->Log("done.");
	}
  if(run)
  {
    IScopedLock slock(stop_mutex);
    Server->Log("waiting for sessionmgr...");
    run=false;
    wait_cond->notify_all();
    stop_cond->wait(&slock);
    Server->Log("done.");
  }
  Server->destroy(sess_mutex);
  Server->destroy(wait_mutex);
  Server->destroy(stop_mutex);

  Server->destroy(wait_cond);
  Server->destroy(stop_cond);
}

void CSessionMgr::startTimeoutSessionThread()
{
    run=true;
    Server->createThread(this);
}

std::wstring CSessionMgr::GenerateSessionIDWithUser(const std::wstring &pUsername, const std::wstring &pIdentData, bool update_user)
{
	std::wstring ret;
	ret.resize(SESSIONID_LEN);
	std::vector<unsigned int> rnd_n=Server->getSecureRandomNumbers(SESSIONID_LEN);
	for(int i=0;i<SESSIONID_LEN;++i)
		ret[i]+=Pool[rnd_n[i]%Pool.size()];

	IScopedLock lock( sess_mutex );
	if(update_user)
	{
		std::vector<std::wstring> to_remove;
		for(std::map<std::wstring, SUser*>::iterator i=mSessions.begin();i!=mSessions.end();++i)
		{
			if( i->second->username==pUsername )
			{
				to_remove.push_back(i->first);
			}
		}

		lock.relock(NULL);

		for(size_t i=0;i<to_remove.size();++i)
		{
			RemoveSession(to_remove[i]);
		}

		lock.relock(sess_mutex);
	}

	SUser *user=new SUser;
	user->username=pUsername;
	user->session=ret;
	user->mutex=Server->createMutex();
	user->lock=NULL;
	user->ident_data=pIdentData;
	user->id=-1;
	user->lastused=Server->getTimeMS();
	mSessions.insert(std::pair<std::wstring, SUser*>(ret, user) );

	return ret;
}

SUser *CSessionMgr::getUser(const std::wstring &pSID, const std::wstring &pIdentData, bool update)
{
	IScopedLock lock( sess_mutex );
	std::map<std::wstring, SUser*>::iterator i=mSessions.find(pSID);
	if( i!=mSessions.end() )
	{
		if( i->second->ident_data!=pIdentData )
			return NULL;

		lock.relock(NULL);

		ILock *lock=((IMutex*)i->second->mutex)->Lock2();
		i->second->lock=lock;
		if( update==true )
			i->second->lastused=Server->getTimeMS();
		return i->second;
	}
	else
		return NULL;
}

void CSessionMgr::releaseUser(SUser *user)
{
	if( user!=NULL )
	{
		((ILock*)user->lock)->Remove();
	}
}

void CSessionMgr::lockUser(SUser *user)
{
	if( user!=NULL )
	{
		ILock *lock=((IMutex*)user->mutex)->Lock2();
		user->lock=lock;
	}
}

bool CSessionMgr::RemoveSession(const std::wstring &pSID)
{
	IScopedLock lock( sess_mutex );
	std::map<std::wstring, SUser*>::iterator i=mSessions.find(pSID);
	if( i!=mSessions.end() )
	{
		SUser* user=i->second;
		mSessions.erase(i);

		lock.relock(NULL);

		IScopedLock *lock=new IScopedLock(((IMutex*)user->mutex));
		delete lock;

		Server->destroy((IMutex*)user->mutex);

		for(std::map<std::string, IObject* >::iterator iter=user->mCustom.begin();
			iter!=user->mCustom.end();++iter)
		{
			iter->second->Remove();
		}

		delete user;

		return true;
	}
	else
		return false;
}

unsigned int CSessionMgr::TimeoutSessions(void)
{
	if(Server!=NULL)
		Server->Log("Looking for old Sessions... "+nconvert(mSessions.size())+" sessions", LL_INFO);
	unsigned int ret=0;
	IScopedLock lock( sess_mutex );
	int64 ttime=Server->getTimeMS();
	std::vector<std::wstring> to_timeout;
	for(std::map<std::wstring, SUser*>::iterator i=mSessions.begin();i!=mSessions.end();++i)
	{
		int64 diff=ttime-i->second->lastused;
		if( diff > (unsigned int)(SESSION_TIMEOUT_S)*1000 )
		{
			Server->Log(L"Session timeout: Session "+i->first, LL_INFO);
			to_timeout.push_back(i->first);
			return 0;
		}
		else
		{
		    ret=static_cast<unsigned int>((std::max)(diff, static_cast<int64>(ret)));
		}
	}

	lock.relock(NULL);

	for(size_t i=0;i<to_timeout.size();++i)
	{
		RemoveSession(to_timeout[i]);
	}

	return (unsigned int)((SESSION_TIMEOUT_S)*1000)-ret+1000;
}

void CSessionMgr::operator()(void)
{
    {
		IScopedLock lock( wait_mutex );
		while(run)
		{
			unsigned int wtime=TimeoutSessions();
			wait_cond->wait(&lock, wtime);
		}
    }
    IScopedLock slock(stop_mutex);
    stop_cond->notify_one();
}
<commit_msg>Properly timeout sessions<commit_after>/*************************************************************************
*    UrBackup - Client/Server backup system
*    Copyright (C) 2011-2014 Martin Raiber
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program 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 General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/

#include "vld.h"
#include <stdlib.h>
#include "SessionMgr.h"
#include "Server.h"
#include "stringtools.h"

CSessionMgr::CSessionMgr(void)
{
	sess_mutex=Server->createMutex();

	wait_cond=Server->createCondition();
	wait_mutex=Server->createMutex();

	stop_mutex=Server->createMutex();
	stop_cond=Server->createCondition();

	SESSIONID_LEN=30;//Server->Settings->getValue("SESSIONID_LEN",15);
	SESSION_TIMEOUT_S=1800;//Server->Settings->getValue("SESSION_TIMEOUT_S",600);

	for(unsigned char i=48;i<58;++i)
		Pool.push_back(i);
	for(unsigned char i=65;i<91;++i)
		Pool.push_back(i);
	for(unsigned char i=97;i<122;++i)
		Pool.push_back(i);

	run=false;
}

CSessionMgr::~CSessionMgr()
{
	{
	  IScopedLock lock( sess_mutex );
	  Server->Log("removing sessions...");
	  if(!mSessions.empty() )
	  {
		  std::vector<std::wstring> sesids;
		  for(std::map<std::wstring, SUser*>::iterator i=mSessions.begin();i!=mSessions.end();++i)
		  {
			  sesids.push_back(i->first);
		  }

		  lock.relock(NULL);

		  for(size_t i=0;i<sesids.size();++i)
		  {
			  RemoveSession(sesids[i]);
		  }
	  }
	  Server->Log("done.");
	}
  if(run)
  {
    IScopedLock slock(stop_mutex);
    Server->Log("waiting for sessionmgr...");
    run=false;
    wait_cond->notify_all();
    stop_cond->wait(&slock);
    Server->Log("done.");
  }
  Server->destroy(sess_mutex);
  Server->destroy(wait_mutex);
  Server->destroy(stop_mutex);

  Server->destroy(wait_cond);
  Server->destroy(stop_cond);
}

void CSessionMgr::startTimeoutSessionThread()
{
    run=true;
    Server->createThread(this);
}

std::wstring CSessionMgr::GenerateSessionIDWithUser(const std::wstring &pUsername, const std::wstring &pIdentData, bool update_user)
{
	std::wstring ret;
	ret.resize(SESSIONID_LEN);
	std::vector<unsigned int> rnd_n=Server->getSecureRandomNumbers(SESSIONID_LEN);
	for(int i=0;i<SESSIONID_LEN;++i)
		ret[i]+=Pool[rnd_n[i]%Pool.size()];

	IScopedLock lock( sess_mutex );
	if(update_user)
	{
		std::vector<std::wstring> to_remove;
		for(std::map<std::wstring, SUser*>::iterator i=mSessions.begin();i!=mSessions.end();++i)
		{
			if( i->second->username==pUsername )
			{
				to_remove.push_back(i->first);
			}
		}

		lock.relock(NULL);

		for(size_t i=0;i<to_remove.size();++i)
		{
			RemoveSession(to_remove[i]);
		}

		lock.relock(sess_mutex);
	}

	SUser *user=new SUser;
	user->username=pUsername;
	user->session=ret;
	user->mutex=Server->createMutex();
	user->lock=NULL;
	user->ident_data=pIdentData;
	user->id=-1;
	user->lastused=Server->getTimeMS();
	mSessions.insert(std::pair<std::wstring, SUser*>(ret, user) );

	return ret;
}

SUser *CSessionMgr::getUser(const std::wstring &pSID, const std::wstring &pIdentData, bool update)
{
	IScopedLock lock( sess_mutex );
	std::map<std::wstring, SUser*>::iterator i=mSessions.find(pSID);
	if( i!=mSessions.end() )
	{
		if( i->second->ident_data!=pIdentData )
			return NULL;

		lock.relock(NULL);

		ILock *lock=((IMutex*)i->second->mutex)->Lock2();
		i->second->lock=lock;
		if( update==true )
			i->second->lastused=Server->getTimeMS();
		return i->second;
	}
	else
		return NULL;
}

void CSessionMgr::releaseUser(SUser *user)
{
	if( user!=NULL )
	{
		((ILock*)user->lock)->Remove();
	}
}

void CSessionMgr::lockUser(SUser *user)
{
	if( user!=NULL )
	{
		ILock *lock=((IMutex*)user->mutex)->Lock2();
		user->lock=lock;
	}
}

bool CSessionMgr::RemoveSession(const std::wstring &pSID)
{
	IScopedLock lock( sess_mutex );
	std::map<std::wstring, SUser*>::iterator i=mSessions.find(pSID);
	if( i!=mSessions.end() )
	{
		SUser* user=i->second;
		mSessions.erase(i);

		lock.relock(NULL);

		IScopedLock *lock=new IScopedLock(((IMutex*)user->mutex));
		delete lock;

		Server->destroy((IMutex*)user->mutex);

		for(std::map<std::string, IObject* >::iterator iter=user->mCustom.begin();
			iter!=user->mCustom.end();++iter)
		{
			iter->second->Remove();
		}

		delete user;

		return true;
	}
	else
		return false;
}

unsigned int CSessionMgr::TimeoutSessions(void)
{
	if(Server!=NULL)
		Server->Log("Looking for old Sessions... "+nconvert(mSessions.size())+" sessions", LL_INFO);
	unsigned int ret=0;
	IScopedLock lock( sess_mutex );
	int64 ttime=Server->getTimeMS();
	std::vector<std::wstring> to_timeout;
	for(std::map<std::wstring, SUser*>::iterator i=mSessions.begin();i!=mSessions.end();++i)
	{
		int64 diff=ttime-i->second->lastused;
		if( diff > (unsigned int)(SESSION_TIMEOUT_S)*1000 )
		{
			Server->Log(L"Session timeout: Session "+i->first, LL_INFO);
			to_timeout.push_back(i->first);
		}
		else
		{
		    ret=static_cast<unsigned int>((std::max)(diff, static_cast<int64>(ret)));
		}
	}

	lock.relock(NULL);

	for(size_t i=0;i<to_timeout.size();++i)
	{
		RemoveSession(to_timeout[i]);
	}

	return (unsigned int)((SESSION_TIMEOUT_S)*1000)-ret+1000;
}

void CSessionMgr::operator()(void)
{
    {
		IScopedLock lock( wait_mutex );
		while(run)
		{
			unsigned int wtime=TimeoutSessions();
			wait_cond->wait(&lock, wtime);
		}
    }
    IScopedLock slock(stop_mutex);
    stop_cond->notify_one();
}
<|endoftext|>


<commit_before>#include "stdafx.h"

#include "Core/WindowsApplication.h"

#include "Sources/External/IMGUI/imgui_impl_win32.h"

#include <functional>
#include <Strsafe.h>

#include "Core/CoreTypes.h"
#include "Core/Input/Input.h"

#include "Render/RenderSettings.h"

namespace Kioto
{
namespace KiotoCore
{
void Init();
void Update();
void Shutdown();
void ChangeFullscreenMode(bool fullScreen);
void Resize(uint16 width, uint16 height, bool minimized);
Kioto::RenderSettings& GetRenderSettings();
}

namespace WindowsApplication
{
namespace
{
const UINT WindowStyle = WS_OVERLAPPEDWINDOW;
RECT WindowRect = {};
std::wstring WindowCaption;
bool IsFullscreen = false;
HWND Hwnd;
}

void MessageError(LPTSTR lpszFunction);
LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

bool Init(HINSTANCE hInstance, int32 nCmdShow, std::wstring caption)
{
    // TODO: create mutex to check if another instance exist.
    IsFullscreen = false;
    WindowCaption = caption;

    WNDCLASSEX windowClass = {};
    windowClass.cbSize = sizeof(WNDCLASSEX);
    windowClass.style = CS_HREDRAW | CS_VREDRAW;
    windowClass.lpfnWndProc = WindowProc;
    windowClass.hInstance = hInstance;
    windowClass.hCursor = LoadCursor(nullptr, IDC_ARROW);
    windowClass.lpszClassName = caption.c_str();
    RegisterClassEx(&windowClass);

    Vector2i resolution = KiotoCore::GetRenderSettings().Resolution;
    RECT windowRect = { 0, 0, resolution.x, resolution.y };
    if (!AdjustWindowRect(&windowRect, WS_OVERLAPPEDWINDOW, FALSE))
        return false;

    Hwnd = CreateWindow(windowClass.lpszClassName,
        WindowCaption.c_str(),
        WindowStyle,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        windowRect.right - windowRect.left,
        windowRect.bottom - windowRect.top,
        nullptr,
        nullptr,
        hInstance,
        nullptr);

    if (Hwnd == nullptr)
    {
        MessageError(TEXT("Create window"));
        return false;
    }

    ShowWindow(Hwnd, nCmdShow);

    return true;
}

int64 Run()
{
    MSG msg = {};
    while (msg.message != WM_QUIT)
    {
        if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            KiotoCore::Update(); // [a_vorontcov] TODO: If app minimized go to sleep.
        }
    }
    Shutdown();

    return static_cast<int64>(msg.wParam);
}

void Shutdown()
{
    KiotoCore::Shutdown();
}

void ChangeFullscreenMode(bool fullScreen)
{
    if (fullScreen == IsFullscreen)
        return;

    IsFullscreen = fullScreen;
    if (!IsFullscreen)
    {
        SetWindowLong(Hwnd, GWL_STYLE, WindowStyle);

        SetWindowPos(
            Hwnd,
            HWND_NOTOPMOST,
            WindowRect.left,
            WindowRect.top,
            WindowRect.right - WindowRect.left,
            WindowRect.bottom - WindowRect.top,
            SWP_FRAMECHANGED | SWP_NOACTIVATE);

        ShowWindow(Hwnd, SW_NORMAL);
        return;
    }
    GetWindowRect(Hwnd, &WindowRect);

    UINT fullScreenWindowStyle = WindowStyle & ~(WS_CAPTION | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SYSMENU | WS_THICKFRAME);
    SetWindowLong(Hwnd, GWL_STYLE, fullScreenWindowStyle);

    DEVMODE devMode = {};
    devMode.dmSize = sizeof(DEVMODE);
    EnumDisplaySettings(nullptr, ENUM_CURRENT_SETTINGS, &devMode);

    SetWindowPos(
        Hwnd,
        HWND_TOPMOST,
        devMode.dmPosition.x,
        devMode.dmPosition.y,
        devMode.dmPosition.x + devMode.dmPelsWidth,
        devMode.dmPosition.y + devMode.dmPelsHeight,
        SWP_FRAMECHANGED | SWP_NOACTIVATE);

    ShowWindow(Hwnd, SW_MAXIMIZE);
}

HWND GetHWND()
{
    return Hwnd;
}

LRESULT WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    ImGui::ImplWinWndProcHandler(hwnd, message, wParam, lParam);

    switch (message)
    {
    case WM_CREATE:
    {
        LPCREATESTRUCT pCreateStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);
        SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pCreateStruct->lpCreateParams));

        // [a_vorontcov] For now only keyboard, joystick and mouse.
        RAWINPUTDEVICE rid[3];

        rid[0].usUsagePage = 0x01;
        rid[0].usUsage = 0x02; // [a_vorontcov] Mouse.
        rid[0].dwFlags = 0;
        rid[0].hwndTarget = hwnd;

        rid[1].usUsagePage = 0x01;
        rid[1].usUsage = 0x06; // [a_vorontcov] Keyboard.
        rid[1].dwFlags = 0;
        rid[1].hwndTarget = hwnd;

        rid[2].usUsagePage = 0x01;
        rid[2].usUsage = 0x04; // [a_vorontcov] Joystic.
        rid[2].dwFlags = 0;
        rid[2].hwndTarget = hwnd;

        if (!RegisterRawInputDevices(rid, 3, sizeof(rid[0])))
            assert(false && "Couldn't register input devices");
        return 0;
    }

    case WM_INPUT:
    {
        if (ImGui::IsAnyWindowFocused())
            return 0;
        // [a_vorontcov] Explanation of what's going on here - https://docs.microsoft.com/en-us/windows/desktop/inputdev/using-raw-input

        UINT dwSize;
        GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));
        LPBYTE lpb = new BYTE[dwSize]; // [a_vorontcov] TODO: Remove every frame reallocation here.
        if (lpb == NULL)
            return 0;

        if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize)
            OutputDebugString(TEXT("GetRawInputData doesn't return correct size! \n"));
        RAWINPUT* raw = (RAWINPUT*)lpb;

        if (raw->header.dwType == RIM_TYPEKEYBOARD)
        {
            if ((raw->data.keyboard.Flags & RI_KEY_BREAK) != 0)
                Input::SetButtonUp(static_cast<uint32>(raw->data.keyboard.VKey));
            else if (raw->data.keyboard.Flags == RI_KEY_MAKE)
                Input::SetButtonDown(static_cast<uint32>(raw->data.keyboard.VKey));
        }
        else if (raw->header.dwType == RIM_TYPEMOUSE)
        {
            Input::SetMouseMoveRelated(raw->data.mouse.lLastX, raw->data.mouse.lLastY);

            if (raw->data.mouse.usButtonFlags & RI_MOUSE_WHEEL)
                Input::SetMouseWheel(raw->data.mouse.usButtonData);

            if (static_cast<uint32>(raw->data.mouse.usButtonFlags) != 0)
                Input::SetMouseFlags(static_cast<uint32>(raw->data.mouse.usButtonFlags));
        }
        SafeDeleteArray(lpb);
        return 0;
    }

    case WM_KEYDOWN:
        return 0;

    case WM_KEYUP:
        return 0;

    case WM_SYSKEYDOWN:
        if ((wParam == VK_RETURN) && (lParam & (1 << 29))) // [a_vorontcov] Handle Alt+Enter.
        {
            KiotoCore::ChangeFullscreenMode(!IsFullscreen);
        }
        return 0;

    case WM_EXITSIZEMOVE:
    {
        RECT clientRect = {};
        GetClientRect(Hwnd, &clientRect);
        KiotoCore::Resize(static_cast<uint16>(clientRect.right - clientRect.left), static_cast<uint16>(clientRect.bottom - clientRect.top), wParam == SIZE_MINIMIZED);
    }
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;

    default:
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

void MessageError(LPTSTR lpszFunction)
{
    LPVOID messageBuffer;
    LPVOID displayBuffer;
    DWORD dw = GetLastError();

    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        nullptr,
        dw,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR)&messageBuffer,
        0, nullptr);

    displayBuffer = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
        (lstrlen((LPCTSTR)messageBuffer) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
    StringCchPrintf((LPTSTR)displayBuffer,
        LocalSize(displayBuffer) / sizeof(TCHAR),
        TEXT("%s failed with error %d: %s"),
        lpszFunction, dw, messageBuffer);
    MessageBox(nullptr, (LPCTSTR)displayBuffer, TEXT("Error"), MB_OK);

    LocalFree(messageBuffer);
    LocalFree(displayBuffer);
}
}
}<commit_msg>Fixed lptstr conversion<commit_after>#include "stdafx.h"

#include "Core/WindowsApplication.h"

#include "Sources/External/IMGUI/imgui_impl_win32.h"

#include <functional>
#include <Strsafe.h>

#include "Core/CoreTypes.h"
#include "Core/Input/Input.h"

#include "Render/RenderSettings.h"

namespace Kioto
{
namespace KiotoCore
{
void Init();
void Update();
void Shutdown();
void ChangeFullscreenMode(bool fullScreen);
void Resize(uint16 width, uint16 height, bool minimized);
Kioto::RenderSettings& GetRenderSettings();
}

namespace WindowsApplication
{
namespace
{
const UINT WindowStyle = WS_OVERLAPPEDWINDOW;
RECT WindowRect = {};
std::wstring WindowCaption;
bool IsFullscreen = false;
HWND Hwnd;
}

void MessageError(LPTSTR lpszFunction);
LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

bool Init(HINSTANCE hInstance, int32 nCmdShow, std::wstring caption)
{
    // TODO: create mutex to check if another instance exist.
    IsFullscreen = false;
    WindowCaption = caption;

    WNDCLASSEX windowClass = {};
    windowClass.cbSize = sizeof(WNDCLASSEX);
    windowClass.style = CS_HREDRAW | CS_VREDRAW;
    windowClass.lpfnWndProc = WindowProc;
    windowClass.hInstance = hInstance;
    windowClass.hCursor = LoadCursor(nullptr, IDC_ARROW);
    windowClass.lpszClassName = caption.c_str();
    RegisterClassEx(&windowClass);

    Vector2i resolution = KiotoCore::GetRenderSettings().Resolution;
    RECT windowRect = { 0, 0, resolution.x, resolution.y };
    if (!AdjustWindowRect(&windowRect, WS_OVERLAPPEDWINDOW, FALSE))
        return false;

    Hwnd = CreateWindow(windowClass.lpszClassName,
        WindowCaption.c_str(),
        WindowStyle,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        windowRect.right - windowRect.left,
        windowRect.bottom - windowRect.top,
        nullptr,
        nullptr,
        hInstance,
        nullptr);

    if (Hwnd == nullptr)
    {
        MessageError(const_cast<wchar_t*>(TEXT("Create window")));
        return false;
    }

    ShowWindow(Hwnd, nCmdShow);

    return true;
}

int64 Run()
{
    MSG msg = {};
    while (msg.message != WM_QUIT)
    {
        if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            KiotoCore::Update(); // [a_vorontcov] TODO: If app minimized go to sleep.
        }
    }
    Shutdown();

    return static_cast<int64>(msg.wParam);
}

void Shutdown()
{
    KiotoCore::Shutdown();
}

void ChangeFullscreenMode(bool fullScreen)
{
    if (fullScreen == IsFullscreen)
        return;

    IsFullscreen = fullScreen;
    if (!IsFullscreen)
    {
        SetWindowLong(Hwnd, GWL_STYLE, WindowStyle);

        SetWindowPos(
            Hwnd,
            HWND_NOTOPMOST,
            WindowRect.left,
            WindowRect.top,
            WindowRect.right - WindowRect.left,
            WindowRect.bottom - WindowRect.top,
            SWP_FRAMECHANGED | SWP_NOACTIVATE);

        ShowWindow(Hwnd, SW_NORMAL);
        return;
    }
    GetWindowRect(Hwnd, &WindowRect);

    UINT fullScreenWindowStyle = WindowStyle & ~(WS_CAPTION | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SYSMENU | WS_THICKFRAME);
    SetWindowLong(Hwnd, GWL_STYLE, fullScreenWindowStyle);

    DEVMODE devMode = {};
    devMode.dmSize = sizeof(DEVMODE);
    EnumDisplaySettings(nullptr, ENUM_CURRENT_SETTINGS, &devMode);

    SetWindowPos(
        Hwnd,
        HWND_TOPMOST,
        devMode.dmPosition.x,
        devMode.dmPosition.y,
        devMode.dmPosition.x + devMode.dmPelsWidth,
        devMode.dmPosition.y + devMode.dmPelsHeight,
        SWP_FRAMECHANGED | SWP_NOACTIVATE);

    ShowWindow(Hwnd, SW_MAXIMIZE);
}

HWND GetHWND()
{
    return Hwnd;
}

LRESULT WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    ImGui::ImplWinWndProcHandler(hwnd, message, wParam, lParam);

    switch (message)
    {
    case WM_CREATE:
    {
        LPCREATESTRUCT pCreateStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);
        SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pCreateStruct->lpCreateParams));

        // [a_vorontcov] For now only keyboard, joystick and mouse.
        RAWINPUTDEVICE rid[3];

        rid[0].usUsagePage = 0x01;
        rid[0].usUsage = 0x02; // [a_vorontcov] Mouse.
        rid[0].dwFlags = 0;
        rid[0].hwndTarget = hwnd;

        rid[1].usUsagePage = 0x01;
        rid[1].usUsage = 0x06; // [a_vorontcov] Keyboard.
        rid[1].dwFlags = 0;
        rid[1].hwndTarget = hwnd;

        rid[2].usUsagePage = 0x01;
        rid[2].usUsage = 0x04; // [a_vorontcov] Joystic.
        rid[2].dwFlags = 0;
        rid[2].hwndTarget = hwnd;

        if (!RegisterRawInputDevices(rid, 3, sizeof(rid[0])))
            assert(false && "Couldn't register input devices");
        return 0;
    }

    case WM_INPUT:
    {
        if (ImGui::IsAnyWindowFocused())
            return 0;
        // [a_vorontcov] Explanation of what's going on here - https://docs.microsoft.com/en-us/windows/desktop/inputdev/using-raw-input

        UINT dwSize;
        GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));
        LPBYTE lpb = new BYTE[dwSize]; // [a_vorontcov] TODO: Remove every frame reallocation here.
        if (lpb == NULL)
            return 0;

        if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize)
            OutputDebugString(TEXT("GetRawInputData doesn't return correct size! \n"));
        RAWINPUT* raw = (RAWINPUT*)lpb;

        if (raw->header.dwType == RIM_TYPEKEYBOARD)
        {
            if ((raw->data.keyboard.Flags & RI_KEY_BREAK) != 0)
                Input::SetButtonUp(static_cast<uint32>(raw->data.keyboard.VKey));
            else if (raw->data.keyboard.Flags == RI_KEY_MAKE)
                Input::SetButtonDown(static_cast<uint32>(raw->data.keyboard.VKey));
        }
        else if (raw->header.dwType == RIM_TYPEMOUSE)
        {
            Input::SetMouseMoveRelated(raw->data.mouse.lLastX, raw->data.mouse.lLastY);

            if (raw->data.mouse.usButtonFlags & RI_MOUSE_WHEEL)
                Input::SetMouseWheel(raw->data.mouse.usButtonData);

            if (static_cast<uint32>(raw->data.mouse.usButtonFlags) != 0)
                Input::SetMouseFlags(static_cast<uint32>(raw->data.mouse.usButtonFlags));
        }
        SafeDeleteArray(lpb);
        return 0;
    }

    case WM_KEYDOWN:
        return 0;

    case WM_KEYUP:
        return 0;

    case WM_SYSKEYDOWN:
        if ((wParam == VK_RETURN) && (lParam & (1 << 29))) // [a_vorontcov] Handle Alt+Enter.
        {
            KiotoCore::ChangeFullscreenMode(!IsFullscreen);
        }
        return 0;

    case WM_EXITSIZEMOVE:
    {
        RECT clientRect = {};
        GetClientRect(Hwnd, &clientRect);
        KiotoCore::Resize(static_cast<uint16>(clientRect.right - clientRect.left), static_cast<uint16>(clientRect.bottom - clientRect.top), wParam == SIZE_MINIMIZED);
    }
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;

    default:
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

void MessageError(LPTSTR lpszFunction)
{
    LPVOID messageBuffer;
    LPVOID displayBuffer;
    DWORD dw = GetLastError();

    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        nullptr,
        dw,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR)&messageBuffer,
        0, nullptr);

    displayBuffer = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
        (lstrlen((LPCTSTR)messageBuffer) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
    StringCchPrintf((LPTSTR)displayBuffer,
        LocalSize(displayBuffer) / sizeof(TCHAR),
        TEXT("%s failed with error %d: %s"),
        lpszFunction, dw, messageBuffer);
    MessageBox(nullptr, (LPCTSTR)displayBuffer, TEXT("Error"), MB_OK);

    LocalFree(messageBuffer);
    LocalFree(displayBuffer);
}
}
}<|endoftext|>


<commit_before>#include <iomanip>

#include <Castro.H>
#include <Castro_F.H>
#include <Geometry.H>

void
Castro::sum_integrated_quantities ()
{
    int finest_level  = parent->finestLevel();
    Real time         = state[State_Type].curTime();
    Real mass         = 0.0;
    Real momentum[3]  = { 0.0 };
    Real rho_E        = 0.0;
    Real rho_e        = 0.0;
    Real rho_phi      = 0.0;

    Real gravitational_energy = 0.0;
    Real kinetic_energy       = 0.0;
    Real internal_energy      = 0.0;
    Real total_energy         = 0.0;

    Real angular_momentum[3]     = { 0.0 };
    Real moment_of_inertia[3][3] = { 0.0 };
    Real m_r_squared[3]          = { 0.0 };

    Real omega[3]     = { 0.0, 0.0, 2.0*3.14159265358979*rotational_frequency };
    Real L_grid[3]    = { 0.0 };

    Real mass_left    = 0.0;
    Real mass_right   = 0.0;

    Real com[3]       = { 0.0 };
    Real com_l[3]     = { 0.0 };
    Real com_r[3]     = { 0.0 };
    Real delta_com[3] = { 0.0 };

    Real com_vel[3]   = { 0.0 };
    Real com_vel_l[3] = { 0.0 };
    Real com_vel_r[3] = { 0.0 };

    std::string name1;
    std::string name2;

    int index1;
    int index2;

    int datawidth     =  14;
    int dataprecision =   6;

    for (int lev = 0; lev <= finest_level; lev++)
    {

      // Get the current level from Castro

      Castro& ca_lev = getLevel(lev);

      // Calculate center of mass quantities.

      mass_left    += ca_lev.volWgtSumOneSide("density", time, 0, 0);
      mass_right   += ca_lev.volWgtSumOneSide("density", time, 1, 0);

      for ( int i = 0; i <= BL_SPACEDIM-1; i++ ) {
        switch ( i ) {
	  case 0 :
            name1 = "xmom"; break;
          case 1 :
            name1 = "ymom"; break;
          case 2 :
            name1 = "zmom"; break;
	}

        delta_com[i]  = ca_lev.locWgtSum("density", time, i);
        com[i]       += delta_com[i];

        com_l[i]     += ca_lev.locWgtSumOneSide("density", time, i, 0, 0);
        com_r[i]     += ca_lev.locWgtSumOneSide("density", time, i, 1, 0);
        com_vel_l[i] += ca_lev.volWgtSumOneSide(name1,    time, 0, 0);
        com_vel_r[i] += ca_lev.volWgtSumOneSide(name1,    time, 1, 0);
      }

      // Calculate total mass, momentum and energy of system.

      mass     += ca_lev.volWgtSum("density", time);

      momentum[0]     += ca_lev.volWgtSum("xmom", time);
      momentum[1]     += ca_lev.volWgtSum("ymom", time);
#if (BL_SPACEDIM == 3)
      momentum[2]     += ca_lev.volWgtSum("zmom", time);
#endif

      rho_E    += ca_lev.volWgtSum("rho_E", time);
      rho_e    += ca_lev.volWgtSum("rho_e", time);

#ifdef GRAVITY
      if ( do_grav ) {
        rho_phi  += ca_lev.volProductSum("density", "phi", time);
      }
#endif

      // Calculate total angular momentum on the grid using L = r x p

#if (BL_SPACEDIM == 3)
      for ( int i = 0; i <= 2; i++ ) {

        index1 = (i+1) % 3;
        index2 = (i+2) % 3;

        switch (i) {
          case 0 :
            name1 = "ymom"; name2 = "zmom"; break;
          case 1 :
            name1 = "zmom"; name2 = "xmom"; break;
          case 2 :
            name1 = "xmom"; name2 = "ymom"; break;
        }

        L_grid[i] = ca_lev.locWgtSum(name2, time, index1) - ca_lev.locWgtSum(name1, time, index2);

        angular_momentum[i]  += L_grid[i];

      }
#elif (BL_SPACEDIM == 2)
	L_grid[2] = ca_lev.locWgtSum("ymom", time, 0) - ca_lev.locWgtSum("xmom", time, 1);
#endif

      // Add rotation source terms

      if ( do_rotation ) {

        // Construct (symmetric) moment of inertia tensor

	for ( int i = 0; i <= BL_SPACEDIM-1; i++ ) {
          m_r_squared[i] = ca_lev.locWgtSum2D("density", time, i, i);
        }

        for ( int i = 0; i <= 2; i++ ) {
	  for ( int j = 0; j <= 2; j++ ) {
            if ( i <= j ) {
              if ( i != j )  {
                if ( ( i < BL_SPACEDIM ) && ( j < BL_SPACEDIM ) ) // Protect against computing z direction sum in 2D
                  moment_of_inertia[i][j] = -ca_lev.locWgtSum2D("density", time, i, j);
              }
              else
                moment_of_inertia[i][j] = m_r_squared[(i+1)%3] + m_r_squared[(i+2)%3];
            }
	    else
              moment_of_inertia[i][j] = moment_of_inertia[j][i];
          }
        }

        for ( int i = 0; i <= 2; i++ ) {

	  // Momentum source from motion IN rotating frame == omega x (rho * r)

          momentum[i] += omega[(i+1)%3]*delta_com[(i+2)%3] - omega[(i+2)%3]*delta_com[(i+1)%3];

          // Rotational energy from motion IN rotating frame == omega dot L_grid

          kinetic_energy     += omega[i] * L_grid[i];

	  // Now add quantities due to motion OF rotating frame

	  for ( int j = 0; j <=2; j++ ) {
            angular_momentum[i] += moment_of_inertia[i][j] * omega[j];

            kinetic_energy += (1.0/2.0) * omega[i] * moment_of_inertia[i][j] * omega[j];
          }

        }
      }

    }

    // Complete calculations for COM quantities

    Real center = 0.0;

    for ( int i = 0; i <= 2; i++ ) {
      center = 0.5*(Geometry::ProbLo(i) + Geometry::ProbHi(i));
      com[i]       = com[i] / mass + center;
      com_l[i]     = com_l[i] / mass_left + center;
      com_r[i]     = com_r[i] / mass_right + center;
      com_vel_l[i] = com_vel_l[i] / mass_left;
      com_vel_r[i] = com_vel_r[i] / mass_right;
      com_vel[i]   = momentum[i] / mass;
    }

    const Real* ml = &mass_left;
    const Real* mr = &mass_right;
    const Real* cxl = &com_l[0];
    const Real* cxr = &com_r[0];
    const Real* cyl = &com_l[1];
    const Real* cyr = &com_r[1];
    const Real* czl = &com_l[2];
    const Real* czr = &com_r[2];

    BL_FORT_PROC_CALL(COM_SAVE,com_save)
      (ml, mr, cxl, cxr, cyl, cyr, czl, czr);

    // Complete calculations for energy

    gravitational_energy = (-1.0/2.0) * rho_phi; // avoids double counting; CASTRO uses positive phi
    internal_energy = rho_e;
    kinetic_energy += rho_E - rho_e;
    total_energy = gravitational_energy + internal_energy + kinetic_energy;

    // Write data out to the log.

    if ( ParallelDescriptor::IOProcessor() )
    {

      std::ostream& data_log1 = parent->DataLog(0);
      if ( data_log1.good() ) {

        // Write header row

        if (time == 0.0) {
          data_log1 << std::setw(datawidth) << "#    TIME    ";
          data_log1 << std::setw(datawidth) << " MASS        ";
          data_log1 << std::setw(datawidth) << " XMOM        ";
          data_log1 << std::setw(datawidth) << " YMOM        ";
          data_log1 << std::setw(datawidth) << " ZMOM        ";
          data_log1 << std::setw(datawidth) << " KIN. ENERGY ";
          data_log1 << std::setw(datawidth) << " GRAV. ENERGY";
          data_log1 << std::setw(datawidth) << " INT. ENERGY ";
          data_log1 << std::setw(datawidth) << " TOTAL ENERGY";
          data_log1 << std::setw(datawidth) << " ANG. MOM. X ";
          data_log1 << std::setw(datawidth) << " ANG. MOM. Y ";
          data_log1 << std::setw(datawidth) << " ANG. MOM. Z ";
          data_log1 << std::setw(datawidth) << "  X COM       ";
          data_log1 << std::setw(datawidth) << "  Y COM       ";
          data_log1 << std::setw(datawidth) << "  Z COM       ";
          data_log1 << std::setw(datawidth) << "  LEFT MASS   ";
          data_log1 << std::setw(datawidth) << "  RIGHT MASS  ";
          data_log1 << std::setw(datawidth) << "  LEFT X COM  ";
          data_log1 << std::setw(datawidth) << "  RIGHT X COM ";
          data_log1 << std::setw(datawidth) << "  LEFT Y COM  ";
          data_log1 << std::setw(datawidth) << "  RIGHT Y COM ";
          data_log1 << std::setw(datawidth) << "  LEFT Z COM  ";
          data_log1 << std::setw(datawidth) << "  RIGHT Z COM ";
          data_log1 << std::setw(datawidth) << "  X VEL       ";
          data_log1 << std::setw(datawidth) << "  Y VEL       ";
          data_log1 << std::setw(datawidth) << "  Z VEL       ";
          data_log1 << std::setw(datawidth) << "  LEFT X VEL  ";
          data_log1 << std::setw(datawidth) << "  RIGHT X VEL ";
          data_log1 << std::setw(datawidth) << "  LEFT Y VEL  ";
          data_log1 << std::setw(datawidth) << "  RIGHT Y VEL ";
          data_log1 << std::setw(datawidth) << "  LEFT Z VEL  ";
          data_log1 << std::setw(datawidth) << "  RIGHT Z VEL ";

          data_log1 << std::endl;
        }

        // Write data for the present time

	  data_log1 << std::fixed;

	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << time;

	  data_log1 << std::scientific;

	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << mass;
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << momentum[0];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << momentum[1];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << momentum[2];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << kinetic_energy;
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << gravitational_energy;
          data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << internal_energy;
          data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << total_energy;
          data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << angular_momentum[0];
          data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << angular_momentum[1];
          data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << angular_momentum[2];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com[0];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com[1];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com[2];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << mass_left;
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << mass_right;
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_l[0];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_r[0];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_l[1];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_r[1];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_l[2];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_r[2];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_vel[0];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_vel[1];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_vel[2];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_vel_l[0];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_vel_r[0];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_vel_l[1];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_vel_r[1];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_vel_l[2];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_vel_r[2];

	  data_log1 << std::endl;

      }
    }
}

<commit_msg>Added explanatory comment regarding previous parallel output fix.<commit_after>#include <iomanip>

#include <Castro.H>
#include <Castro_F.H>
#include <Geometry.H>

void
Castro::sum_integrated_quantities ()
{
    int finest_level  = parent->finestLevel();
    Real time         = state[State_Type].curTime();
    Real mass         = 0.0;
    Real momentum[3]  = { 0.0 };
    Real rho_E        = 0.0;
    Real rho_e        = 0.0;
    Real rho_phi      = 0.0;

    Real gravitational_energy = 0.0;
    Real kinetic_energy       = 0.0;
    Real internal_energy      = 0.0;
    Real total_energy         = 0.0;

    Real angular_momentum[3]     = { 0.0 };
    Real moment_of_inertia[3][3] = { 0.0 };
    Real m_r_squared[3]          = { 0.0 };

    Real omega[3]     = { 0.0, 0.0, 2.0*3.14159265358979*rotational_frequency };
    Real L_grid[3]    = { 0.0 };

    Real mass_left    = 0.0;
    Real mass_right   = 0.0;

    Real com[3]       = { 0.0 };
    Real com_l[3]     = { 0.0 };
    Real com_r[3]     = { 0.0 };
    Real delta_com[3] = { 0.0 };

    Real com_vel[3]   = { 0.0 };
    Real com_vel_l[3] = { 0.0 };
    Real com_vel_r[3] = { 0.0 };

    std::string name1;
    std::string name2;

    int index1;
    int index2;

    int datawidth     =  14;
    int dataprecision =   6;

    for (int lev = 0; lev <= finest_level; lev++)
    {

      // Get the current level from Castro

      Castro& ca_lev = getLevel(lev);

      // Calculate center of mass quantities.

      mass_left    += ca_lev.volWgtSumOneSide("density", time, 0, 0);
      mass_right   += ca_lev.volWgtSumOneSide("density", time, 1, 0);

      for ( int i = 0; i <= BL_SPACEDIM-1; i++ ) {
        switch ( i ) {
	  case 0 :
            name1 = "xmom"; break;
          case 1 :
            name1 = "ymom"; break;
          case 2 :
            name1 = "zmom"; break;
	}

        delta_com[i]  = ca_lev.locWgtSum("density", time, i);
        com[i]       += delta_com[i];

        com_l[i]     += ca_lev.locWgtSumOneSide("density", time, i, 0, 0);
        com_r[i]     += ca_lev.locWgtSumOneSide("density", time, i, 1, 0);
        com_vel_l[i] += ca_lev.volWgtSumOneSide(name1,    time, 0, 0);
        com_vel_r[i] += ca_lev.volWgtSumOneSide(name1,    time, 1, 0);
      }

      // Calculate total mass, momentum and energy of system.

      mass     += ca_lev.volWgtSum("density", time);

      momentum[0]     += ca_lev.volWgtSum("xmom", time);
      momentum[1]     += ca_lev.volWgtSum("ymom", time);
#if (BL_SPACEDIM == 3)
      momentum[2]     += ca_lev.volWgtSum("zmom", time);
#endif

      rho_E    += ca_lev.volWgtSum("rho_E", time);
      rho_e    += ca_lev.volWgtSum("rho_e", time);

#ifdef GRAVITY
      if ( do_grav ) {
        rho_phi  += ca_lev.volProductSum("density", "phi", time);
      }
#endif

      // Calculate total angular momentum on the grid using L = r x p

#if (BL_SPACEDIM == 3)
      for ( int i = 0; i <= 2; i++ ) {

        index1 = (i+1) % 3;
        index2 = (i+2) % 3;

        switch (i) {
          case 0 :
            name1 = "ymom"; name2 = "zmom"; break;
          case 1 :
            name1 = "zmom"; name2 = "xmom"; break;
          case 2 :
            name1 = "xmom"; name2 = "ymom"; break;
        }

        L_grid[i] = ca_lev.locWgtSum(name2, time, index1) - ca_lev.locWgtSum(name1, time, index2);

        angular_momentum[i]  += L_grid[i];

      }
#elif (BL_SPACEDIM == 2)
	L_grid[2] = ca_lev.locWgtSum("ymom", time, 0) - ca_lev.locWgtSum("xmom", time, 1);
#endif

      // Add rotation source terms

      if ( do_rotation ) {

        // Construct (symmetric) moment of inertia tensor

	for ( int i = 0; i <= BL_SPACEDIM-1; i++ ) {
          m_r_squared[i] = ca_lev.locWgtSum2D("density", time, i, i);
        }

        for ( int i = 0; i <= 2; i++ ) {
	  for ( int j = 0; j <= 2; j++ ) {
            if ( i <= j ) {
              if ( i != j )  {
                if ( ( i < BL_SPACEDIM ) && ( j < BL_SPACEDIM ) ) // Protect against computing z direction sum in 2D
                  moment_of_inertia[i][j] = -ca_lev.locWgtSum2D("density", time, i, j);
              }
              else
                moment_of_inertia[i][j] = m_r_squared[(i+1)%3] + m_r_squared[(i+2)%3];
            }
	    else
              moment_of_inertia[i][j] = moment_of_inertia[j][i];
          }
        }

        for ( int i = 0; i <= 2; i++ ) {

	  // Momentum source from motion IN rotating frame == omega x (rho * r)

          momentum[i] += omega[(i+1)%3]*delta_com[(i+2)%3] - omega[(i+2)%3]*delta_com[(i+1)%3];

          // Rotational energy from motion IN rotating frame == omega dot L_grid

          kinetic_energy     += omega[i] * L_grid[i];

	  // Now add quantities due to motion OF rotating frame

	  for ( int j = 0; j <=2; j++ ) {
            angular_momentum[i] += moment_of_inertia[i][j] * omega[j];

            kinetic_energy += (1.0/2.0) * omega[i] * moment_of_inertia[i][j] * omega[j];
          }

        }
      }

    }

    // Complete calculations for COM quantities

    Real center = 0.0;

    for ( int i = 0; i <= 2; i++ ) {
      center = 0.5*(Geometry::ProbLo(i) + Geometry::ProbHi(i));
      com[i]       = com[i] / mass + center;
      com_l[i]     = com_l[i] / mass_left + center;
      com_r[i]     = com_r[i] / mass_right + center;
      com_vel_l[i] = com_vel_l[i] / mass_left;
      com_vel_r[i] = com_vel_r[i] / mass_right;
      com_vel[i]   = momentum[i] / mass;
    }

    const Real* ml = &mass_left;
    const Real* mr = &mass_right;
    const Real* cxl = &com_l[0];
    const Real* cxr = &com_r[0];
    const Real* cyl = &com_l[1];
    const Real* cyr = &com_r[1];
    const Real* czl = &com_l[2];
    const Real* czr = &com_r[2];

    BL_FORT_PROC_CALL(COM_SAVE,com_save)
      (ml, mr, cxl, cxr, cyl, cyr, czl, czr);

    // Complete calculations for energy

    gravitational_energy = (-1.0/2.0) * rho_phi; // avoids double counting; CASTRO uses positive phi
    internal_energy = rho_e;
    kinetic_energy += rho_E - rho_e;
    total_energy = gravitational_energy + internal_energy + kinetic_energy;

    // Write data out to the log.

    if ( ParallelDescriptor::IOProcessor() )
    {

      // The data log is only defined on the IO processor
      // for parallel runs, so the stream should only be opened inside.

      std::ostream& data_log1 = parent->DataLog(0);
      if ( data_log1.good() ) {

        // Write header row

        if (time == 0.0) {
          data_log1 << std::setw(datawidth) << "#    TIME    ";
          data_log1 << std::setw(datawidth) << " MASS        ";
          data_log1 << std::setw(datawidth) << " XMOM        ";
          data_log1 << std::setw(datawidth) << " YMOM        ";
          data_log1 << std::setw(datawidth) << " ZMOM        ";
          data_log1 << std::setw(datawidth) << " KIN. ENERGY ";
          data_log1 << std::setw(datawidth) << " GRAV. ENERGY";
          data_log1 << std::setw(datawidth) << " INT. ENERGY ";
          data_log1 << std::setw(datawidth) << " TOTAL ENERGY";
          data_log1 << std::setw(datawidth) << " ANG. MOM. X ";
          data_log1 << std::setw(datawidth) << " ANG. MOM. Y ";
          data_log1 << std::setw(datawidth) << " ANG. MOM. Z ";
          data_log1 << std::setw(datawidth) << "  X COM       ";
          data_log1 << std::setw(datawidth) << "  Y COM       ";
          data_log1 << std::setw(datawidth) << "  Z COM       ";
          data_log1 << std::setw(datawidth) << "  LEFT MASS   ";
          data_log1 << std::setw(datawidth) << "  RIGHT MASS  ";
          data_log1 << std::setw(datawidth) << "  LEFT X COM  ";
          data_log1 << std::setw(datawidth) << "  RIGHT X COM ";
          data_log1 << std::setw(datawidth) << "  LEFT Y COM  ";
          data_log1 << std::setw(datawidth) << "  RIGHT Y COM ";
          data_log1 << std::setw(datawidth) << "  LEFT Z COM  ";
          data_log1 << std::setw(datawidth) << "  RIGHT Z COM ";
          data_log1 << std::setw(datawidth) << "  X VEL       ";
          data_log1 << std::setw(datawidth) << "  Y VEL       ";
          data_log1 << std::setw(datawidth) << "  Z VEL       ";
          data_log1 << std::setw(datawidth) << "  LEFT X VEL  ";
          data_log1 << std::setw(datawidth) << "  RIGHT X VEL ";
          data_log1 << std::setw(datawidth) << "  LEFT Y VEL  ";
          data_log1 << std::setw(datawidth) << "  RIGHT Y VEL ";
          data_log1 << std::setw(datawidth) << "  LEFT Z VEL  ";
          data_log1 << std::setw(datawidth) << "  RIGHT Z VEL ";

          data_log1 << std::endl;
        }

        // Write data for the present time

	  data_log1 << std::fixed;

	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << time;

	  data_log1 << std::scientific;

	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << mass;
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << momentum[0];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << momentum[1];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << momentum[2];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << kinetic_energy;
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << gravitational_energy;
          data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << internal_energy;
          data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << total_energy;
          data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << angular_momentum[0];
          data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << angular_momentum[1];
          data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << angular_momentum[2];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com[0];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com[1];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com[2];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << mass_left;
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << mass_right;
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_l[0];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_r[0];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_l[1];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_r[1];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_l[2];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_r[2];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_vel[0];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_vel[1];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_vel[2];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_vel_l[0];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_vel_r[0];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_vel_l[1];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_vel_r[1];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_vel_l[2];
	  data_log1 << std::setw(datawidth) << std::setprecision(dataprecision) << com_vel_r[2];

	  data_log1 << std::endl;

      }
    }
}

<|endoftext|>


<commit_before>#include "fetchers.hh"
#include "store-api.hh"
#include <filesystem>
#include "archive.hh"

namespace nix::fetchers {

struct PathInputScheme : InputScheme
{
    std::optional<Input> inputFromURL(const ParsedURL & url) override
    {
        if (url.scheme != "path") return {};

        if (url.authority && *url.authority != "")
            throw Error("path URL '%s' should not have an authority ('%s')", url.url, *url.authority);

        Input input;
        input.attrs.insert_or_assign("type", "path");
        input.attrs.insert_or_assign("path", url.path);

        for (auto & [name, value] : url.query)
            if (name == "rev" || name == "narHash")
                input.attrs.insert_or_assign(name, value);
            else if (name == "revCount" || name == "lastModified") {
                if (auto n = string2Int<uint64_t>(value))
                    input.attrs.insert_or_assign(name, *n);
                else
                    throw Error("path URL '%s' has invalid parameter '%s'", url.to_string(), name);
            }
            else
                throw Error("path URL '%s' has unsupported parameter '%s'", url.to_string(), name);

        return input;
    }

    std::optional<Input> inputFromAttrs(const Attrs & attrs) override
    {
        if (maybeGetStrAttr(attrs, "type") != "path") return {};

        getStrAttr(attrs, "path");

        for (auto & [name, value] : attrs)
            /* Allow the user to pass in "fake" tree info
               attributes. This is useful for making a pinned tree
               work the same as the repository from which is exported
               (e.g. path:/nix/store/...-source?lastModified=1585388205&rev=b0c285...). */
            if (name == "type" || name == "rev" || name == "revCount" || name == "lastModified" || name == "narHash" || name == "path")
                // checked in Input::fromAttrs
                ;
            else
                throw Error("unsupported path input attribute '%s'", name);

        Input input;
        input.attrs = attrs;
        return input;
    }

    ParsedURL toURL(const Input & input) override
    {
        auto query = attrsToQuery(input.attrs);
        query.erase("path");
        query.erase("type");
        return ParsedURL {
            .scheme = "path",
            .path = getStrAttr(input.attrs, "path"),
            .query = query,
        };
    }

    bool hasAllInfo(const Input & input) override
    {
        return true;
    }

    std::optional<Path> getSourcePath(const Input & input) override
    {
        return getStrAttr(input.attrs, "path");
    }

    void markChangedFile(const Input & input, std::string_view file, std::optional<std::string> commitMsg) override
    {
        // nothing to do
    }

    std::pair<StorePath, Input> fetch(ref<Store> store, const Input & _input) override
    {
        Input input(_input);
        std::string absPath;
        auto path = getStrAttr(input.attrs, "path");

        if (path[0] != '/') {
            if (!input.parent)
                throw Error("cannot fetch input '%s' because it uses a relative path", input.to_string());

            auto parent = canonPath(*input.parent);

            // the path isn't relative, prefix it
            absPath = nix::absPath(path, parent);

            // for security, ensure that if the parent is a store path, it's inside it
            if (store->isInStore(parent)) {
                auto storePath = store->printStorePath(store->toStorePath(parent).first);
                if (!isDirOrInDir(absPath, storePath))
                    throw BadStorePath("relative path '%s' points outside of its parent's store path '%s'", path, storePath);
            }
        } else
            absPath = path;

        Activity act(*logger, lvlTalkative, actUnknown, fmt("copying '%s'", absPath));

        // FIXME: check whether access to 'path' is allowed.
        auto storePath = store->maybeParseStorePath(absPath);

        if (storePath)
            store->addTempRoot(*storePath);

        time_t mtime = 0;
        if (!storePath || storePath->name() != "source" || !store->isValidPath(*storePath)) {
            // FIXME: try to substitute storePath.
            auto src = sinkToSource([&](Sink & sink) {
                mtime = dumpPathAndGetMtime(absPath, sink, defaultPathFilter);
            });
            storePath = store->addToStoreFromDump(*src, "source");
        }
        input.attrs.insert_or_assign("lastModified", uint64_t(mtime));

        return {std::move(*storePath), input};
    }
};

static auto rPathInputScheme = OnStartup([] { registerInputScheme(std::make_unique<PathInputScheme>()); });

}
<commit_msg>libfetchers: remove obsolete filesystem #include<commit_after>#include "fetchers.hh"
#include "store-api.hh"
#include "archive.hh"

namespace nix::fetchers {

struct PathInputScheme : InputScheme
{
    std::optional<Input> inputFromURL(const ParsedURL & url) override
    {
        if (url.scheme != "path") return {};

        if (url.authority && *url.authority != "")
            throw Error("path URL '%s' should not have an authority ('%s')", url.url, *url.authority);

        Input input;
        input.attrs.insert_or_assign("type", "path");
        input.attrs.insert_or_assign("path", url.path);

        for (auto & [name, value] : url.query)
            if (name == "rev" || name == "narHash")
                input.attrs.insert_or_assign(name, value);
            else if (name == "revCount" || name == "lastModified") {
                if (auto n = string2Int<uint64_t>(value))
                    input.attrs.insert_or_assign(name, *n);
                else
                    throw Error("path URL '%s' has invalid parameter '%s'", url.to_string(), name);
            }
            else
                throw Error("path URL '%s' has unsupported parameter '%s'", url.to_string(), name);

        return input;
    }

    std::optional<Input> inputFromAttrs(const Attrs & attrs) override
    {
        if (maybeGetStrAttr(attrs, "type") != "path") return {};

        getStrAttr(attrs, "path");

        for (auto & [name, value] : attrs)
            /* Allow the user to pass in "fake" tree info
               attributes. This is useful for making a pinned tree
               work the same as the repository from which is exported
               (e.g. path:/nix/store/...-source?lastModified=1585388205&rev=b0c285...). */
            if (name == "type" || name == "rev" || name == "revCount" || name == "lastModified" || name == "narHash" || name == "path")
                // checked in Input::fromAttrs
                ;
            else
                throw Error("unsupported path input attribute '%s'", name);

        Input input;
        input.attrs = attrs;
        return input;
    }

    ParsedURL toURL(const Input & input) override
    {
        auto query = attrsToQuery(input.attrs);
        query.erase("path");
        query.erase("type");
        return ParsedURL {
            .scheme = "path",
            .path = getStrAttr(input.attrs, "path"),
            .query = query,
        };
    }

    bool hasAllInfo(const Input & input) override
    {
        return true;
    }

    std::optional<Path> getSourcePath(const Input & input) override
    {
        return getStrAttr(input.attrs, "path");
    }

    void markChangedFile(const Input & input, std::string_view file, std::optional<std::string> commitMsg) override
    {
        // nothing to do
    }

    std::pair<StorePath, Input> fetch(ref<Store> store, const Input & _input) override
    {
        Input input(_input);
        std::string absPath;
        auto path = getStrAttr(input.attrs, "path");

        if (path[0] != '/') {
            if (!input.parent)
                throw Error("cannot fetch input '%s' because it uses a relative path", input.to_string());

            auto parent = canonPath(*input.parent);

            // the path isn't relative, prefix it
            absPath = nix::absPath(path, parent);

            // for security, ensure that if the parent is a store path, it's inside it
            if (store->isInStore(parent)) {
                auto storePath = store->printStorePath(store->toStorePath(parent).first);
                if (!isDirOrInDir(absPath, storePath))
                    throw BadStorePath("relative path '%s' points outside of its parent's store path '%s'", path, storePath);
            }
        } else
            absPath = path;

        Activity act(*logger, lvlTalkative, actUnknown, fmt("copying '%s'", absPath));

        // FIXME: check whether access to 'path' is allowed.
        auto storePath = store->maybeParseStorePath(absPath);

        if (storePath)
            store->addTempRoot(*storePath);

        time_t mtime = 0;
        if (!storePath || storePath->name() != "source" || !store->isValidPath(*storePath)) {
            // FIXME: try to substitute storePath.
            auto src = sinkToSource([&](Sink & sink) {
                mtime = dumpPathAndGetMtime(absPath, sink, defaultPathFilter);
            });
            storePath = store->addToStoreFromDump(*src, "source");
        }
        input.attrs.insert_or_assign("lastModified", uint64_t(mtime));

        return {std::move(*storePath), input};
    }
};

static auto rPathInputScheme = OnStartup([] { registerInputScheme(std::make_unique<PathInputScheme>()); });

}
<|endoftext|>


<commit_before>//
//  src/macho/container.cc
//  tbd
//
//  Created by inoahdev on 4/24/17.
//  Copyright © 2017 inoahdev. All rights reserved.
//

#include "header/symbol_table.h"
#include "container.h"

namespace macho {
    container::container(FILE *file, long base)
    : file_(file), base_(base) {
        const auto position = ftell(file);
        fseek(file, 0, SEEK_END);

        this->size_ = ftell(file);

        fseek(file, position, SEEK_SET);
        this->validate();
    }

    container::container(FILE *file, long base, size_t size)
    : file_(file), base_(base), size_(size) {
        this->validate();
    }

    container::~container() {
        auto &cached = cached_;
        if (cached) {
            delete[] cached;
        }

        auto &string_table = string_table_;
        if (string_table) {
            delete[] string_table;
        }
    }

    void container::validate() {
        auto &base = base_;
        auto &file = file_;

        auto &header = header_;
        auto &magic = header.magic;

        const auto is_big_endian = this->is_big_endian();
        const auto position = ftell(file);

        fseek(file, base, SEEK_SET);
        fread(&magic, sizeof(uint32_t), 1, file);

        const auto macho_file_is_regular = magic_is_thin(magic);
        if (macho_file_is_regular) {
            fread(&header.cputype, sizeof(header) - sizeof(uint32_t), 1, file);

            if (is_big_endian) {
                swap_mach_header(&header);
            }
        } else {
            const auto macho_file_is_fat = magic_is_fat(magic);
            if (macho_file_is_fat) {
                fprintf(stderr, "Architecture at location (0x%.8lX) cannot be a fat mach-o file itself\n", base);
                exit(1);
            } else {
                fprintf(stderr, "Architecture at location (0x%.8lX) is not a valid mach-o base\n", base);
                exit(1);
            }
        }

        fseek(file, position, SEEK_SET);
    }

    void container::iterate_load_commands(const std::function<bool (const struct load_command *)> &callback) {
        const auto &base = base_;
        const auto &file = file_;

        const auto &header = header_;
        const auto is_big_endian = this->is_big_endian();

        const auto &ncmds = header.ncmds;
        const auto &sizeofcmds = header.sizeofcmds;

        auto &cached = cached_;
        auto created_cache = false;

        if (!cached) {
            cached = new char[sizeofcmds];
            created_cache = true;

            auto load_command_base = base + sizeof(header);
            if (this->is_64_bit()) {
                load_command_base += sizeof(uint32_t);
            }

            const auto position = ftell(file);

            fseek(file, load_command_base, SEEK_SET);
            fread(cached, sizeofcmds, 1, file);

            fseek(file, position, SEEK_SET);
        }

        auto size_used = 0;
        auto cached_index = 0;

        auto should_callback = true;
        for (auto i = 0; i < ncmds; i++) {
            auto load_cmd = (struct load_command *)&cached[cached_index];
            const auto &cmdsize = load_cmd->cmdsize;

            if (created_cache) {
                if (is_big_endian) {
                    swap_load_command(load_cmd);
                }

                if (cmdsize < sizeof(struct load_command)) {
                    fprintf(stderr, "Load-command (at index %d) of mach-o container (at base 0x%.8lX) is too small to be valid\n", i, base);
                    exit(1);
                }

                if (cmdsize >= sizeofcmds) {
                    fprintf(stderr, "Load-command (at index %d) of mach-o container (at base 0x%.8lX) is larger than/or equal to entire area allocated for load-commands\n", i, base);
                    exit(1);
                }

                size_used += cmdsize;
                if (size_used > sizeofcmds) {
                    fprintf(stderr, "Load-command (at index %d) of mach-o container (at base 0x%.8lX) goes past end of area allocated for load-commands\n", i, base);
                    exit(1);
                } else if (size_used == sizeofcmds && i != ncmds - 1) {
                    fprintf(stderr, "Load-command (at index %d) of mach-o container (at base 0x%.8lX) takes up all of the remaining space allocated for load-commands\n", i, base);
                    exit(1);
                }
            }

            if (should_callback) {
                auto result = callback(load_cmd);
                if (!result) {
                    should_callback = false;
                }
            }

            if (!should_callback && !created_cache) {
                break;
            }

            cached_index += cmdsize;
        }
    }

    void container::iterate_symbols(const std::function<bool (const struct nlist_64 &, const char *)> &callback) {
        auto &base = base_;
        auto &file = file_;

        const auto is_big_endian = this->is_big_endian();
        const auto position = ftell(file);

        struct symtab_command *symtab_command = nullptr;
        iterate_load_commands([&](const struct load_command *load_cmd) {
            if (load_cmd->cmd != load_commands::symbol_table) {
                return true;
            }

            symtab_command = (struct symtab_command *)load_cmd;
            if (is_big_endian) {
                swap_symtab_command(symtab_command);
            }

            return false;
        });

        if (!symtab_command) {
            fprintf(stderr, "Mach-o container (at base 0x%.8lX) does not have a symbol-table\n", base);
            exit(1);
        }

        const auto &string_table_location = symtab_command->stroff;
        if (string_table_location > size_) {
            fprintf(stderr, "Mach-o container (at base 0x%.8lX) has a string-table outside of its container\n", base);
            exit(1);
        }

        const auto &string_table_size = symtab_command->strsize;
        if (string_table_size > size_) {
            fprintf(stderr, "Mach-o container (at base 0x%.8lX) has a string-table with a size larger than that of itself\n", base);
            exit(1);
        }

        const auto string_table_end = string_table_location + string_table_size;
        if (string_table_end > size_) {
            fprintf(stderr, "Mach-o container (at base 0x%.8lX) has a string-table that goes outside of its container\n", base);
            exit(1);
        }

        const auto &symbol_table_location = symtab_command->symoff;
        if (symbol_table_location > size_) {
            fprintf(stderr, "Mach-o container (at base 0x%.8lX) has a symbol-table that is outside of its container\n", base);
            exit(1);
        }

        auto &string_table = string_table_;
        if (!string_table) {
            string_table = new char[string_table_size];

            fseek(file, base + string_table_location, SEEK_SET);
            fread(string_table, string_table_size, 1, file);
        }

        const auto &symbol_table_count = symtab_command->nsyms;
        const auto string_table_max_index = string_table_size - 1;

        fseek(file, base + symbol_table_location, SEEK_SET);

        const auto is_64_bit = this->is_64_bit();
        if (is_64_bit) {
            const auto symbol_table_size = sizeof(struct nlist_64) * symbol_table_count;
            if (symbol_table_size > size_) {
                fprintf(stderr, "Mach-o container (at base 0x%.8lX) has a symbol-table with a size larger than itself\n", base);
                exit(1);
            }

            const auto symbol_table_end = symbol_table_location + symbol_table_size;
            if (symbol_table_end > size_) {
                fprintf(stderr, "Mach-o container (at base 0x%.8lX) has a symbol-table that goes outside of its boundaries\n", base);
                exit(1);
            }

            const auto symbol_table = new struct nlist_64[symbol_table_count];
            fread(symbol_table, symbol_table_size, 1, file);

            if (is_big_endian) {
                swap_nlist_64(symbol_table, symbol_table_count);
            }

            for (auto i = 0; i < symbol_table_count; i++) {
                const auto &symbol_table_entry = symbol_table[i];
                const auto &symbol_table_entry_string_table_index = symbol_table_entry.n_un.n_strx;

                if (symbol_table_entry_string_table_index > string_table_max_index) {
                    fprintf(stderr, "Symbol-table entry (at index %d) has symbol-string past end of string-table of mach-o container (at base 0x%.8lX)\n", i, base);
                    exit(1);
                }

                const auto symbol_table_string_table_string = &string_table[symbol_table_entry_string_table_index];
                const auto result = callback(symbol_table_entry, symbol_table_string_table_string);

                if (!result) {
                    break;
                }
            }

            delete[] symbol_table;
        } else {
            const auto symbol_table_size = sizeof(struct nlist) * symbol_table_count;
            if (symbol_table_size > size_) {
                fprintf(stderr, "Mach-o container (at base 0x%.8lX) has a symbol-table with a size larger than itself\n", base);
                exit(1);
            }

            const auto symbol_table_end = symbol_table_location + symbol_table_size;
            if (symbol_table_end > size_) {
                fprintf(stderr, "Mach-o container (at base 0x%.8lX) has a symbol-table that goes outside of its boundaries\n", base);
                exit(1);
            }

            const auto symbol_table = new struct nlist[symbol_table_count];
            fread(symbol_table, symbol_table_size, 1, file);

            if (is_big_endian) {
                swap_nlist(symbol_table, symbol_table_count);
            }

            for (auto i = 0; i < symbol_table_count; i++) {
                const auto &symbol_table_entry = symbol_table[i];
                const auto &symbol_table_entry_string_table_index = symbol_table_entry.n_un.n_strx;

                if (i == 10956) {
                    printf("");
                }

                if (symbol_table_entry_string_table_index > string_table_max_index) {
                    fprintf(stderr, "Symbol-table entry (at index %d) has symbol-string past end of string-table of mach-o container (at base 0x%.8lX)\n", i, base);
                    exit(1);
                }

                const struct nlist_64 symbol_table_entry_64 = { { symbol_table_entry.n_un.n_strx }, symbol_table_entry.n_type, symbol_table_entry.n_sect, (uint16_t)symbol_table_entry.n_desc, symbol_table_entry.n_value };

                const auto symbol_table_string_table_string = &string_table[symbol_table_entry_string_table_index];
                const auto result = callback(symbol_table_entry_64, symbol_table_string_table_string);

                if (!result) {
                    break;
                }
            }

            delete[] symbol_table;
        }

        fseek(file, position, SEEK_SET);
    }
}
<commit_msg>Fix spaces/tabs in container.cc<commit_after>//
//  src/macho/container.cc
//  tbd
//
//  Created by inoahdev on 4/24/17.
//  Copyright © 2017 inoahdev. All rights reserved.
//

#include "header/symbol_table.h"
#include "container.h"

namespace macho {
    container::container(FILE *file, long base)
    : file_(file), base_(base) {
        const auto position = ftell(file);
        fseek(file, 0, SEEK_END);

        this->size_ = ftell(file);

        fseek(file, position, SEEK_SET);
        this->validate();
    }

    container::container(FILE *file, long base, size_t size)
    : file_(file), base_(base), size_(size) {
        this->validate();
    }

    container::~container() {
        auto &cached = cached_;
        if (cached) {
            delete[] cached;
        }

        auto &string_table = string_table_;
        if (string_table) {
            delete[] string_table;
        }
    }

    void container::validate() {
        auto &base = base_;
        auto &file = file_;

        auto &header = header_;
        auto &magic = header.magic;

        const auto is_big_endian = this->is_big_endian();
        const auto position = ftell(file);

        fseek(file, base, SEEK_SET);
        fread(&magic, sizeof(uint32_t), 1, file);

        const auto macho_file_is_regular = magic_is_thin(magic);
        if (macho_file_is_regular) {
            fread(&header.cputype, sizeof(header) - sizeof(uint32_t), 1, file);

            if (is_big_endian) {
                swap_mach_header(&header);
            }
        } else {
            const auto macho_file_is_fat = magic_is_fat(magic);
            if (macho_file_is_fat) {
                fprintf(stderr, "Architecture at location (0x%.8lX) cannot be a fat mach-o file itself\n", base);
                exit(1);
            } else {
                fprintf(stderr, "Architecture at location (0x%.8lX) is not a valid mach-o base\n", base);
                exit(1);
            }
        }

        fseek(file, position, SEEK_SET);
    }

    void container::iterate_load_commands(const std::function<bool (const struct load_command *)> &callback) {
        const auto &base = base_;
        const auto &file = file_;

        const auto &header = header_;
        const auto is_big_endian = this->is_big_endian();

        const auto &ncmds = header.ncmds;
        const auto &sizeofcmds = header.sizeofcmds;

        auto &cached = cached_;
        auto created_cache = false;

        if (!cached) {
            cached = new char[sizeofcmds];
            created_cache = true;

            auto load_command_base = base + sizeof(header);
            if (this->is_64_bit()) {
                load_command_base += sizeof(uint32_t);
            }

            const auto position = ftell(file);

            fseek(file, load_command_base, SEEK_SET);
            fread(cached, sizeofcmds, 1, file);

            fseek(file, position, SEEK_SET);
        }

        auto size_used = 0;
        auto cached_index = 0;

        auto should_callback = true;
        for (auto i = 0; i < ncmds; i++) {
            auto load_cmd = (struct load_command *)&cached[cached_index];
            const auto &cmdsize = load_cmd->cmdsize;

            if (created_cache) {
                if (is_big_endian) {
                    swap_load_command(load_cmd);
                }

                if (cmdsize < sizeof(struct load_command)) {
                    fprintf(stderr, "Load-command (at index %d) of mach-o container (at base 0x%.8lX) is too small to be valid\n", i, base);
                    exit(1);
                }

                if (cmdsize >= sizeofcmds) {
                    fprintf(stderr, "Load-command (at index %d) of mach-o container (at base 0x%.8lX) is larger than/or equal to entire area allocated for load-commands\n", i, base);
                    exit(1);
                }

                size_used += cmdsize;
                if (size_used > sizeofcmds) {
                    fprintf(stderr, "Load-command (at index %d) of mach-o container (at base 0x%.8lX) goes past end of area allocated for load-commands\n", i, base);
                    exit(1);
                } else if (size_used == sizeofcmds && i != ncmds - 1) {
                    fprintf(stderr, "Load-command (at index %d) of mach-o container (at base 0x%.8lX) takes up all of the remaining space allocated for load-commands\n", i, base);
                    exit(1);
                }
            }

            if (should_callback) {
                auto result = callback(load_cmd);
                if (!result) {
                    should_callback = false;
                }
            }

            if (!should_callback && !created_cache) {
                break;
            }

            cached_index += cmdsize;
        }
    }

    void container::iterate_symbols(const std::function<bool (const struct nlist_64 &, const char *)> &callback) {
        auto &base = base_;
        auto &file = file_;

        const auto is_big_endian = this->is_big_endian();
        const auto position = ftell(file);

        struct symtab_command *symtab_command = nullptr;
        iterate_load_commands([&](const struct load_command *load_cmd) {
            if (load_cmd->cmd != load_commands::symbol_table) {
                return true;
            }

            symtab_command = (struct symtab_command *)load_cmd;
            if (is_big_endian) {
                swap_symtab_command(symtab_command);
            }

            return false;
        });

        if (!symtab_command) {
            fprintf(stderr, "Mach-o container (at base 0x%.8lX) does not have a symbol-table\n", base);
            exit(1);
        }

        const auto &string_table_location = symtab_command->stroff;
        if (string_table_location > size_) {
            fprintf(stderr, "Mach-o container (at base 0x%.8lX) has a string-table outside of its container\n", base);
            exit(1);
        }

        const auto &string_table_size = symtab_command->strsize;
        if (string_table_size > size_) {
            fprintf(stderr, "Mach-o container (at base 0x%.8lX) has a string-table with a size larger than that of itself\n", base);
            exit(1);
        }

        const auto string_table_end = string_table_location + string_table_size;
        if (string_table_end > size_) {
            fprintf(stderr, "Mach-o container (at base 0x%.8lX) has a string-table that goes outside of its container\n", base);
            exit(1);
        }

        const auto &symbol_table_location = symtab_command->symoff;
        if (symbol_table_location > size_) {
            fprintf(stderr, "Mach-o container (at base 0x%.8lX) has a symbol-table that is outside of its container\n", base);
            exit(1);
        }

        auto &string_table = string_table_;
        if (!string_table) {
            string_table = new char[string_table_size];

            fseek(file, base + string_table_location, SEEK_SET);
            fread(string_table, string_table_size, 1, file);
        }

        const auto &symbol_table_count = symtab_command->nsyms;
        const auto string_table_max_index = string_table_size - 1;

        fseek(file, base + symbol_table_location, SEEK_SET);

        const auto is_64_bit = this->is_64_bit();
        if (is_64_bit) {
            const auto symbol_table_size = sizeof(struct nlist_64) * symbol_table_count;
            if (symbol_table_size > size_) {
                fprintf(stderr, "Mach-o container (at base 0x%.8lX) has a symbol-table with a size larger than itself\n", base);
                exit(1);
            }

            const auto symbol_table_end = symbol_table_location + symbol_table_size;
            if (symbol_table_end > size_) {
                fprintf(stderr, "Mach-o container (at base 0x%.8lX) has a symbol-table that goes outside of its boundaries\n", base);
                exit(1);
            }

            const auto symbol_table = new struct nlist_64[symbol_table_count];
            fread(symbol_table, symbol_table_size, 1, file);

            if (is_big_endian) {
                swap_nlist_64(symbol_table, symbol_table_count);
            }

            for (auto i = 0; i < symbol_table_count; i++) {
                const auto &symbol_table_entry = symbol_table[i];
                const auto &symbol_table_entry_string_table_index = symbol_table_entry.n_un.n_strx;

                if (symbol_table_entry_string_table_index > string_table_max_index) {
                    fprintf(stderr, "Symbol-table entry (at index %d) has symbol-string past end of string-table of mach-o container (at base 0x%.8lX)\n", i, base);
                    exit(1);
                }

                const auto symbol_table_string_table_string = &string_table[symbol_table_entry_string_table_index];
                const auto result = callback(symbol_table_entry, symbol_table_string_table_string);

                if (!result) {
                    break;
                }
            }

            delete[] symbol_table;
        } else {
            const auto symbol_table_size = sizeof(struct nlist) * symbol_table_count;
            if (symbol_table_size > size_) {
                fprintf(stderr, "Mach-o container (at base 0x%.8lX) has a symbol-table with a size larger than itself\n", base);
                exit(1);
            }

            const auto symbol_table_end = symbol_table_location + symbol_table_size;
            if (symbol_table_end > size_) {
                fprintf(stderr, "Mach-o container (at base 0x%.8lX) has a symbol-table that goes outside of its boundaries\n", base);
                exit(1);
            }

            const auto symbol_table = new struct nlist[symbol_table_count];
            fread(symbol_table, symbol_table_size, 1, file);

            if (is_big_endian) {
                swap_nlist(symbol_table, symbol_table_count);
            }

            for (auto i = 0; i < symbol_table_count; i++) {
                const auto &symbol_table_entry = symbol_table[i];
                const auto &symbol_table_entry_string_table_index = symbol_table_entry.n_un.n_strx;

                if (i == 10956) {
                    printf("");
                }

                if (symbol_table_entry_string_table_index > string_table_max_index) {
                    fprintf(stderr, "Symbol-table entry (at index %d) has symbol-string past end of string-table of mach-o container (at base 0x%.8lX)\n", i, base);
                    exit(1);
                }

                const struct nlist_64 symbol_table_entry_64 = { { symbol_table_entry.n_un.n_strx }, symbol_table_entry.n_type, symbol_table_entry.n_sect, (uint16_t)symbol_table_entry.n_desc, symbol_table_entry.n_value };

                const auto symbol_table_string_table_string = &string_table[symbol_table_entry_string_table_index];
                const auto result = callback(symbol_table_entry_64, symbol_table_string_table_string);

                if (!result) {
                    break;
                }
            }

            delete[] symbol_table;
        }

        fseek(file, position, SEEK_SET);
    }
}
<|endoftext|>