<commit_before>/******************************************************************************\
* File:          file.cpp
* Purpose:       Implementation of wxWidgets file extension classes
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 1998-2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#ifdef __WXMSW__
#include <io.h> // for chmod
#endif
#include <wx/stdpaths.h> // strangely enough, for wxTheFileIconsTable
#include <wx/generic/dirctrlg.h> // for wxTheFileIconsTable
#include <wx/extension/file.h>
#include <wx/extension/app.h> // for exApp
#include <wx/extension/configdialog.h>
#include <wx/extension/util.h> // for exColourToLong

exFile::exFile()
  : m_FileName()
  , m_Stat()
  , m_Message(_("Select File"))
  , m_Wildcard(wxFileSelectorDefaultWildcardStr)
{
}

exFile::exFile(const wxString& filename, wxFile::OpenMode mode)
  : wxFile(filename, mode)
  , m_FileName(filename)
  , m_Stat(filename)
  , m_Message(_("Select File"))
  , m_Wildcard(wxFileSelectorDefaultWildcardStr)
{
  MakeAbsolute();
}

int exFile::AskFileOpen(wxFileDialog& dlg, bool ask_for_continue)
{
  if (ask_for_continue)
  {
    if (!Continue())
    {
      return wxID_CANCEL;
    }
  }

  // Take care that if current filename exists, we set
  // the directory member and filename, so that is where the dialog will open.
  if (m_FileName.FileExists())
  {
    dlg.SetFilename(m_FileName.GetFullPath());
    dlg.SetDirectory(m_FileName.GetPath());
  }

  m_Message = dlg.GetMessage();
  m_Wildcard = dlg.GetWildcard();

  return dlg.ShowModal();
}

bool exFile::CheckSyncNeeded()
{
  if (IsOpened() ||
     !m_FileName.GetStat().IsOk() ||
     !exApp::GetConfigBool("AllowSync", true))
  {
    return false;
  }

  if (m_FileName.GetStat().st_mtime != GetStat().st_mtime)
  {
    FileSync();
  }

  return true;
}

bool exFile::Continue()
{
  if (GetContentsChanged())
  {
    if (!m_FileName.FileExists())
    {
      switch (wxMessageBox(
        _("Save changes") + "?",
        _("Confirm"),
        wxYES_NO | wxCANCEL | wxICON_QUESTION))
      {
        case wxYES:    if (!FileSaveAs()) return false; break;
        case wxNO:     ResetContentsChanged(); break;
        case wxCANCEL: return false; break;
      }
    }
    else
    {
      switch (wxMessageBox(
        _("Save changes to") + ": " + m_FileName.GetFullPath() + "?",
        _("Confirm"),
        wxYES_NO | wxCANCEL | wxICON_QUESTION))
      {
        case wxYES:    FileSave(); break;
        case wxNO:     ResetContentsChanged(); break;
        case wxCANCEL: return false; break;
      }
    }
  }

  return true;
}

bool exFile::FileNew(const exFileName& filename)
{
  if (!Continue()) return false;

  m_FileName = filename;

  // Do not make it absolute, the specified filename does not need
  // to exist.
  return true;
}

bool exFile::FileOpen(const exFileName& filename)
{
  if (
    !Continue() ||
    !filename.FileExists()) return false;

  m_FileName = filename;

  if (MakeAbsolute())
  {
    return Open(m_FileName.GetFullPath());
  }
  else
  {
    return false;
  }
}

bool exFile::FileSave()
{
  wxFile::Close();

  return MakeAbsolute();
}

bool exFile::FileSaveAs()
{
  wxFileDialog dlg(
    wxTheApp->GetTopWindow(),
    m_Message,
    wxEmptyString,
    wxEmptyString,
    m_Wildcard,
    wxFD_SAVE | wxFD_OVERWRITE_PROMPT);

  if (AskFileOpen(dlg, false) == wxID_CANCEL)
  {
    return false;
  }

  const wxString filename = dlg.GetPath();

  if (!filename.empty())
  {
    m_FileName.Assign(filename);
    m_FileName.SetLexer();
    return FileSave();
  }

  return false;
}

void exFile::FileSync()
{
  if (FileOpen(m_FileName))
  {
    m_FileName.StatusText(STAT_SYNC | STAT_FULLPATH);
  }
}

bool exFile::MakeAbsolute()
{
  if (m_FileName.MakeAbsolute())
  {
    m_FileName.GetStat().Update(m_FileName.GetFullPath());
    m_Stat.Update(m_FileName.GetFullPath());
    return true;
  }
  else
  {
    return false;
  }
}

wxString* exFile::Read(wxFileOffset seek_position)
{
  const wxFileOffset bytes_to_read = Length() - seek_position;

  // Always do a seek, so you can do more Reads on the same object.
  Seek(seek_position);

  wxMemoryBuffer buffer(bytes_to_read);
  buffer.SetDataLen(bytes_to_read);
  if (wxFile::Read(buffer.GetData(), bytes_to_read) == bytes_to_read)
  {
    /// \todo If the last char is a NULL, is not put in the string strangely enough.
    ///       However, it is in the buffer as next message shows.
//wxLogMessage("%d", ((char*)buffer.GetData())[bytes_to_read - 1]);
    return new wxString(buffer, *wxConvCurrent, bytes_to_read);
  }
  else
  {
    wxLogError(FILE_INFO("Read error"));
    return NULL;
  }
}

int exFileName::GetIcon() const
{
  if (GetStat().IsOk())
  {
    if (IsDir() && !FileExists())
    {
      return wxFileIconsTable::folder;
    }
    else if (!GetExt().empty())
    {
      wxTheFileIconsTable->GetIconID(GetExt());
    }
    else return wxFileIconsTable::computer;
  }
  else
  {
    return wxFileIconsTable::computer;
  }
}

void exFileName::SetLexer(
  const wxString& lexer,
  const wxString& text)
{
  // Of course, if the lexers are not yet constructed, skip the rest.
  if (exApp::GetLexers() == NULL) return;

  if (lexer.empty())
  {
    m_Lexer = exApp::GetLexers()->FindByFileName(*this);

    if (m_Lexer.GetScintillaLexer().empty() && !text.empty())
    {
      m_Lexer = exApp::GetLexers()->FindByText(text);
    }
  }
  else
  {
    m_Lexer = exApp::GetLexers()->FindByName(lexer);
  }
}

#if wxUSE_STATUSBAR
void exFileName::StatusText(long flags) const
{
  wxString text; // clear status bar for empty or not existing or not initialized file names

  if (IsOk())
  {
    const wxString path = (flags & STAT_FULLPATH
      ? GetFullPath(): GetFullName());

    text += path;

    if (GetStat().IsOk())
    {
      const wxString what = (flags & STAT_SYNC
        ? _("Synchronized"): _("Modified"));
      const wxString time = (flags & STAT_SYNC
        ? wxDateTime::Now().Format(): GetStat().GetModificationTime());
      text += " " + what + " " + time;
    }
  }

  exFrame::StatusText(text);
}
#endif // wxUSE_STATUSBAR

#if wxUSE_GUI
exConfigDialog* exStat::m_ConfigDialog = NULL;
#endif

wxString exStat::m_ColourGroup = "Colour/";

#if wxUSE_GUI
// This is a static method, cannot use normal members here.
int exStat::ConfigDialog(
  const wxString& title,
  wxWindow* parent,
  wxWindowID id)
{
  std::vector<exConfigItem> items;
  items.push_back(exConfigItem(_("day"), CONFIG_COLOUR));
  items.push_back(exConfigItem(_("week"), CONFIG_COLOUR));
  items.push_back(exConfigItem(_("month"), CONFIG_COLOUR));
  items.push_back(exConfigItem(_("year"), CONFIG_COLOUR));
#ifndef __WXMSW__
  // Links only used on Unix.
  items.push_back(exConfigItem(_("link"), CONFIG_COLOUR));
#endif

  if (m_ConfigDialog == NULL)
  {
    m_ConfigDialog = new exConfigDialog(
      parent,
      exApp::GetConfig(),
      items,
      title,
      m_ColourGroup,
      0, 2,
      wxOK | wxCANCEL | wxAPPLY,
      id);
  }

  return m_ConfigDialog->Show();
}
#endif

const wxColour exStat::GetColour() const
{
  if (IsOk())
  {
    const wxDateTime now = wxDateTime::Now();
    const wxDateTime mtime = wxDateTime(st_mtime);

    // within 1 day (12 hours)
    if (mtime > now - 12 * wxTimeSpan::Hour())
    {
      return exApp::GetConfig(m_ColourGroup + _("day"), exColourToLong(*wxGREEN));
    }
    // within 1 week
    else if (mtime > now - wxDateSpan::Week())
    {
      return exApp::GetConfig(m_ColourGroup + _("week"), exColourToLong(*wxBLUE));
    }
    // within 1 month (default colour is white, so not used)
    else if (mtime > now - wxDateSpan::Month())
    {
      return exApp::GetConfig(m_ColourGroup + _("month"), exColourToLong(*wxWHITE));
    }
    // within 1 year (default colour is white, so not used)
    else if (mtime > now - wxDateSpan::Year())
    {
      return exApp::GetConfig(m_ColourGroup + _("year"), exColourToLong(*wxWHITE));
    }
  }

  return *wxWHITE;
}

const wxColour exStat::GetLinkColour() const
{
  return exApp::GetConfig(m_ColourGroup + _("link"), exColourToLong(*wxRED));
}

const wxString exStat::GetModificationTime(const wxString& format) const
{
#ifdef __WXMSW__
  return wxDateTime(st_mtime).Format(format);
#else
  // TODO: The current locale %c cannot be sorted in the listview,
  // so override format and use this one.
  return wxDateTime(st_mtime).Format("%Y%m%d %H:%M:%S");
#endif
}

bool exStat::IsLink() const
{
#ifdef __UNIX__
  return m_IsOk && (S_ISLNK(st_mode) != 0);
#else // S_ISLNK not known
  return false;
#endif
}

bool exStat::SetReadOnly(const bool read_only)
{
  if (IsOk())
  {
    if (chmod(m_FullPath.c_str(),
          read_only ?
            st_mode & ~wxS_IWUSR:
            st_mode | wxS_IWUSR) == 0)
    {
      Update(m_FullPath);
      return IsOk();
    }
  }

  return false;
}
<commit_msg>now fixed the file icon<commit_after>/******************************************************************************\
* File:          file.cpp
* Purpose:       Implementation of wxWidgets file extension classes
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 1998-2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#ifdef __WXMSW__
#include <io.h> // for chmod
#endif
#include <wx/stdpaths.h> // strangely enough, for wxTheFileIconsTable
#include <wx/generic/dirctrlg.h> // for wxTheFileIconsTable
#include <wx/extension/file.h>
#include <wx/extension/app.h> // for exApp
#include <wx/extension/configdialog.h>
#include <wx/extension/util.h> // for exColourToLong

exFile::exFile()
  : m_FileName()
  , m_Stat()
  , m_Message(_("Select File"))
  , m_Wildcard(wxFileSelectorDefaultWildcardStr)
{
}

exFile::exFile(const wxString& filename, wxFile::OpenMode mode)
  : wxFile(filename, mode)
  , m_FileName(filename)
  , m_Stat(filename)
  , m_Message(_("Select File"))
  , m_Wildcard(wxFileSelectorDefaultWildcardStr)
{
  MakeAbsolute();
}

int exFile::AskFileOpen(wxFileDialog& dlg, bool ask_for_continue)
{
  if (ask_for_continue)
  {
    if (!Continue())
    {
      return wxID_CANCEL;
    }
  }

  // Take care that if current filename exists, we set
  // the directory member and filename, so that is where the dialog will open.
  if (m_FileName.FileExists())
  {
    dlg.SetFilename(m_FileName.GetFullPath());
    dlg.SetDirectory(m_FileName.GetPath());
  }

  m_Message = dlg.GetMessage();
  m_Wildcard = dlg.GetWildcard();

  return dlg.ShowModal();
}

bool exFile::CheckSyncNeeded()
{
  if (IsOpened() ||
     !m_FileName.GetStat().IsOk() ||
     !exApp::GetConfigBool("AllowSync", true))
  {
    return false;
  }

  if (m_FileName.GetStat().st_mtime != GetStat().st_mtime)
  {
    FileSync();
  }

  return true;
}

bool exFile::Continue()
{
  if (GetContentsChanged())
  {
    if (!m_FileName.FileExists())
    {
      switch (wxMessageBox(
        _("Save changes") + "?",
        _("Confirm"),
        wxYES_NO | wxCANCEL | wxICON_QUESTION))
      {
        case wxYES:    if (!FileSaveAs()) return false; break;
        case wxNO:     ResetContentsChanged(); break;
        case wxCANCEL: return false; break;
      }
    }
    else
    {
      switch (wxMessageBox(
        _("Save changes to") + ": " + m_FileName.GetFullPath() + "?",
        _("Confirm"),
        wxYES_NO | wxCANCEL | wxICON_QUESTION))
      {
        case wxYES:    FileSave(); break;
        case wxNO:     ResetContentsChanged(); break;
        case wxCANCEL: return false; break;
      }
    }
  }

  return true;
}

bool exFile::FileNew(const exFileName& filename)
{
  if (!Continue()) return false;

  m_FileName = filename;

  // Do not make it absolute, the specified filename does not need
  // to exist.
  return true;
}

bool exFile::FileOpen(const exFileName& filename)
{
  if (
    !Continue() ||
    !filename.FileExists()) return false;

  m_FileName = filename;

  if (MakeAbsolute())
  {
    return Open(m_FileName.GetFullPath());
  }
  else
  {
    return false;
  }
}

bool exFile::FileSave()
{
  wxFile::Close();

  return MakeAbsolute();
}

bool exFile::FileSaveAs()
{
  wxFileDialog dlg(
    wxTheApp->GetTopWindow(),
    m_Message,
    wxEmptyString,
    wxEmptyString,
    m_Wildcard,
    wxFD_SAVE | wxFD_OVERWRITE_PROMPT);

  if (AskFileOpen(dlg, false) == wxID_CANCEL)
  {
    return false;
  }

  const wxString filename = dlg.GetPath();

  if (!filename.empty())
  {
    m_FileName.Assign(filename);
    m_FileName.SetLexer();
    return FileSave();
  }

  return false;
}

void exFile::FileSync()
{
  if (FileOpen(m_FileName))
  {
    m_FileName.StatusText(STAT_SYNC | STAT_FULLPATH);
  }
}

bool exFile::MakeAbsolute()
{
  if (m_FileName.MakeAbsolute())
  {
    m_FileName.GetStat().Update(m_FileName.GetFullPath());
    m_Stat.Update(m_FileName.GetFullPath());
    return true;
  }
  else
  {
    return false;
  }
}

wxString* exFile::Read(wxFileOffset seek_position)
{
  const wxFileOffset bytes_to_read = Length() - seek_position;

  // Always do a seek, so you can do more Reads on the same object.
  Seek(seek_position);

  wxMemoryBuffer buffer(bytes_to_read);
  buffer.SetDataLen(bytes_to_read);
  if (wxFile::Read(buffer.GetData(), bytes_to_read) == bytes_to_read)
  {
    /// \todo If the last char is a NULL, is not put in the string strangely enough.
    ///       However, it is in the buffer as next message shows.
//wxLogMessage("%d", ((char*)buffer.GetData())[bytes_to_read - 1]);
    return new wxString(buffer, *wxConvCurrent, bytes_to_read);
  }
  else
  {
    wxLogError(FILE_INFO("Read error"));
    return NULL;
  }
}

int exFileName::GetIcon() const
{
  if (GetStat().IsOk())
  {
    if (DirExists(GetFullPath()))
    {
      return wxFileIconsTable::folder;
    }
    else if (!GetExt().empty())
    {
      return wxTheFileIconsTable->GetIconID(GetExt());
    }
    else
    {
      return wxFileIconsTable::computer;
    }
  }
  else
  {
    return wxFileIconsTable::computer;
  }
}

void exFileName::SetLexer(
  const wxString& lexer,
  const wxString& text)
{
  // Of course, if the lexers are not yet constructed, skip the rest.
  if (exApp::GetLexers() == NULL) return;

  if (lexer.empty())
  {
    m_Lexer = exApp::GetLexers()->FindByFileName(*this);

    if (m_Lexer.GetScintillaLexer().empty() && !text.empty())
    {
      m_Lexer = exApp::GetLexers()->FindByText(text);
    }
  }
  else
  {
    m_Lexer = exApp::GetLexers()->FindByName(lexer);
  }
}

#if wxUSE_STATUSBAR
void exFileName::StatusText(long flags) const
{
  wxString text; // clear status bar for empty or not existing or not initialized file names

  if (IsOk())
  {
    const wxString path = (flags & STAT_FULLPATH
      ? GetFullPath(): GetFullName());

    text += path;

    if (GetStat().IsOk())
    {
      const wxString what = (flags & STAT_SYNC
        ? _("Synchronized"): _("Modified"));
      const wxString time = (flags & STAT_SYNC
        ? wxDateTime::Now().Format(): GetStat().GetModificationTime());
      text += " " + what + " " + time;
    }
  }

  exFrame::StatusText(text);
}
#endif // wxUSE_STATUSBAR

#if wxUSE_GUI
exConfigDialog* exStat::m_ConfigDialog = NULL;
#endif

wxString exStat::m_ColourGroup = "Colour/";

#if wxUSE_GUI
// This is a static method, cannot use normal members here.
int exStat::ConfigDialog(
  const wxString& title,
  wxWindow* parent,
  wxWindowID id)
{
  std::vector<exConfigItem> items;
  items.push_back(exConfigItem(_("day"), CONFIG_COLOUR));
  items.push_back(exConfigItem(_("week"), CONFIG_COLOUR));
  items.push_back(exConfigItem(_("month"), CONFIG_COLOUR));
  items.push_back(exConfigItem(_("year"), CONFIG_COLOUR));
#ifndef __WXMSW__
  // Links only used on Unix.
  items.push_back(exConfigItem(_("link"), CONFIG_COLOUR));
#endif

  if (m_ConfigDialog == NULL)
  {
    m_ConfigDialog = new exConfigDialog(
      parent,
      exApp::GetConfig(),
      items,
      title,
      m_ColourGroup,
      0, 2,
      wxOK | wxCANCEL | wxAPPLY,
      id);
  }

  return m_ConfigDialog->Show();
}
#endif

const wxColour exStat::GetColour() const
{
  if (IsOk())
  {
    const wxDateTime now = wxDateTime::Now();
    const wxDateTime mtime = wxDateTime(st_mtime);

    // within 1 day (12 hours)
    if (mtime > now - 12 * wxTimeSpan::Hour())
    {
      return exApp::GetConfig(m_ColourGroup + _("day"), exColourToLong(*wxGREEN));
    }
    // within 1 week
    else if (mtime > now - wxDateSpan::Week())
    {
      return exApp::GetConfig(m_ColourGroup + _("week"), exColourToLong(*wxBLUE));
    }
    // within 1 month (default colour is white, so not used)
    else if (mtime > now - wxDateSpan::Month())
    {
      return exApp::GetConfig(m_ColourGroup + _("month"), exColourToLong(*wxWHITE));
    }
    // within 1 year (default colour is white, so not used)
    else if (mtime > now - wxDateSpan::Year())
    {
      return exApp::GetConfig(m_ColourGroup + _("year"), exColourToLong(*wxWHITE));
    }
  }

  return *wxWHITE;
}

const wxColour exStat::GetLinkColour() const
{
  return exApp::GetConfig(m_ColourGroup + _("link"), exColourToLong(*wxRED));
}

const wxString exStat::GetModificationTime(const wxString& format) const
{
#ifdef __WXMSW__
  return wxDateTime(st_mtime).Format(format);
#else
  // TODO: The current locale %c cannot be sorted in the listview,
  // so override format and use this one.
  return wxDateTime(st_mtime).Format("%Y%m%d %H:%M:%S");
#endif
}

bool exStat::IsLink() const
{
#ifdef __UNIX__
  return m_IsOk && (S_ISLNK(st_mode) != 0);
#else // S_ISLNK not known
  return false;
#endif
}

bool exStat::SetReadOnly(const bool read_only)
{
  if (IsOk())
  {
    if (chmod(m_FullPath.c_str(),
          read_only ?
            st_mode & ~wxS_IWUSR:
            st_mode | wxS_IWUSR) == 0)
    {
      Update(m_FullPath);
      return IsOk();
    }
  }

  return false;
}
<|endoftext|>


<commit_before>#include "breakpoint.h"
#include <windows.h>
#include <tlhelp32.h>
#include <algorithm>
#include <iostream>

HWBreakpoint::HWBreakpoint()
{
	ZeroMemory(m_address, sizeof(m_address));
	m_countActive = 0;

	BuildTrampoline();
	if (!m_trampoline)
		std::cout << "error: failed to build hook function" << std::endl;

	m_workerSignal = CreateEvent(NULL, FALSE, FALSE, NULL);
	m_workerDone = CreateEvent(NULL, FALSE, FALSE, NULL);
	m_workerThread = CreateThread(NULL, 0, WorkerThreadProc, this, 0, NULL);
	WaitForSingleObject(m_workerDone, INFINITE);
}

HWBreakpoint::~HWBreakpoint()
{
	CriticalSection::Scope lock(m_cs);
	{
		ZeroMemory(m_address, sizeof(m_address));
		SetForThreads();
	}

	m_pendingThread.tid = -1;
	SetEvent(m_workerSignal);
	WaitForSingleObject(m_workerThread, INFINITE);
	CloseHandle(m_workerDone);
	CloseHandle(m_workerSignal);
	CloseHandle(m_workerThread);

	if (m_trampoline)
		VirtualFree(m_trampoline, 0, MEM_RELEASE);
}

bool HWBreakpoint::Set(void* address, int len, Condition when)
{
	HWBreakpoint& bp = GetInstance();
	{
		CriticalSection::Scope lock(bp.m_cs);
		for (int index = 0; index < 4; ++index)
			if (bp.m_address[index] == nullptr)
			{
				bp.m_address[index] = address;
				bp.m_len[index] = len;
				bp.m_when[index] = when;
				if (bp.m_countActive++ == 0)
					bp.ToggleThreadHook(true);
				bp.SetForThreads();
				return true;
			}
	}

	return false;
}

bool HWBreakpoint::Clear(void* address)
{
	HWBreakpoint& bp = GetInstance();
	{
		CriticalSection::Scope lock(bp.m_cs);
		for (int index = 0; index < 4; ++index)
			if (bp.m_address[index] == address)
			{
				bp.m_address[index] = nullptr;
				if (--bp.m_countActive == 0)
					bp.ToggleThreadHook(false);
				bp.SetForThreads();
				return true;
			}
	}

	return false;
}

void HWBreakpoint::ToggleThread(DWORD tid, bool enableBP)
{
	HWBreakpoint& bp = GetInstance();
	{
		CriticalSection::Scope lock(bp.m_cs);
		bp.m_pendingThread.tid = tid;
		bp.m_pendingThread.enable = enableBP;
		SetEvent(bp.m_workerSignal);
		WaitForSingleObject(bp.m_workerDone, INFINITE);
	}
}

void HWBreakpoint::BuildTrampoline()
{
	ULONG_PTR* rtlThreadStartAddress = (ULONG_PTR*)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlUserThreadStart");

	SYSTEM_INFO si;
	GetSystemInfo(&si);

#ifdef _WIN64

	// Explanation:
	// the traditional way is to overwite first instructions in the hook target with
	// an relative uncontitional jmp. this works well in x86 becuase that relative jmp takes
	// only 5 bytes of opcode, and its cover all memory space. things is differente in x64 mode,
	// to cover all memory space, one need to use absolute jmp which cost 14 bytes in opcode. this is too
	// long to overwite for very small functions. the solution is to use two steps: the overwite instruction
	// is a 5 byte relative jmp that jump to a trampoline function, allocated not far from 2GB relative to the
	// target hook. and in the trampoline we have space to specify absolute jump to the real hook function.
	// more details in: http://www.codeproject.com/Articles/44326/MinHook-The-Minimalistic-x-x-API-Hooking-Libra

	// search for avalible memory in 2GB boundary to host the tampoline function
	ULONG_PTR gMinAddress = (ULONG_PTR)si.lpMinimumApplicationAddress;
	ULONG_PTR gMaxAddress = (ULONG_PTR)si.lpMaximumApplicationAddress;
	ULONG_PTR minAddr = std::max<ULONG_PTR>(gMinAddress, (ULONG_PTR)rtlThreadStartAddress - 0x20000000);
	ULONG_PTR maxAddr = std::min<ULONG_PTR>(gMaxAddress, (ULONG_PTR)rtlThreadStartAddress + 0x20000000);

	const size_t BlockSize = si.dwPageSize;
	intptr_t min = minAddr / BlockSize;
	intptr_t max = maxAddr / BlockSize;
	int rel = 0;
	m_trampoline = nullptr;
	MEMORY_BASIC_INFORMATION mi = { 0 };
	for (int i = 0; i < (max - min + 1); ++i)
	{
		rel = -rel + (i & 1);
		void* pQuery = reinterpret_cast<void*>(((min + max) / 2 + rel) * BlockSize);
		VirtualQuery(pQuery, &mi, sizeof(mi));
		if (mi.State == MEM_FREE)
		{
			m_trampoline = (unsigned char*)VirtualAlloc(pQuery, BlockSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
			if (m_trampoline != nullptr)
				break;
		}
	}

	if (!m_trampoline)
		return;

	// save prologe hooked function
	*(ULONG_PTR*)m_orgOpcode = *rtlThreadStartAddress;

	*(unsigned char*)	&m_trampoline[0] = 0x51;				// push rcx
	*(unsigned char*)	&m_trampoline[1] = 0x52;				// push rdx
	*(unsigned char*)	&m_trampoline[2] = 0x52;				// push rdx
	*(unsigned short*)	&m_trampoline[3] = 0x15FF;				// call
	*(DWORD*)			&m_trampoline[5] = 0x00000018;			//			ThreadDeutor
	*(unsigned char*)	&m_trampoline[9] = 0x5A;				// pop rdx
	*(unsigned char*)	&m_trampoline[10] = 0x5A;				// pop rdx
	*(unsigned char*)	&m_trampoline[11] = 0x59;				// pop rcx

	*(DWORD*)			&m_trampoline[12] = 0x48EC8348;			// sub rsp, 0x48	(2 instruction from prologe of target hook)
	*(unsigned short*)	&m_trampoline[16] = 0x8B4C;				// mov r9,
	*(unsigned char*)	&m_trampoline[18] = 0xC9;				//			rcx
	*(short*)			&m_trampoline[19] = 0x25FF;				// jmp
	*(DWORD*)			&m_trampoline[21] = 0x00000000;			//		rtlThreadStartAddress + 7

	// address data for call & jump
	*(DWORD64*)			&m_trampoline[25] = (DWORD64)((unsigned char*)rtlThreadStartAddress + 7);
	*(DWORD64*)			&m_trampoline[33] = (DWORD64)ThreadDeutor;

#else

	if (((unsigned char*)rtlThreadStartAddress)[0] != 0x89 || ((unsigned char*)rtlThreadStartAddress)[4] != 0x89 || ((unsigned char*)rtlThreadStartAddress)[8] != 0xE9)
		return;

	m_trampoline = (unsigned char*)VirtualAlloc(NULL, si.dwPageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
	if (!m_trampoline)
		return;

	// save prologe hooked function
	*(ULONG_PTR*)m_orgOpcode = *rtlThreadStartAddress;
	*((ULONG_PTR*)(m_orgOpcode) + 1) = *(rtlThreadStartAddress + 1);

	*(unsigned char*) &m_trampoline[0] = 0x50;														// push eax
	*(unsigned char*) &m_trampoline[1] = 0x53;														// push ebx
	*(unsigned char*) &m_trampoline[2] = 0xE8;														// call
	*(unsigned long*) &m_trampoline[3] = (ULONG_PTR)ThreadDeutor - (ULONG_PTR)m_trampoline - 7;		//		ThreadDeutor
	*(unsigned char*) &m_trampoline[7] = 0x5B;														// pop ebx
	*(unsigned char*) &m_trampoline[8] = 0x58;														// pop eax

	// execute 2 instruction from prologe of hooked function
	*(unsigned long*)&m_trampoline[9] = *rtlThreadStartAddress;
	*(unsigned long*)&m_trampoline[13] = *(rtlThreadStartAddress + 1);
	*(unsigned char*)&m_trampoline[17] = 0xE9;														// jmp
	*(unsigned long*)&m_trampoline[18] = (ULONG_PTR)rtlThreadStartAddress - (ULONG_PTR)m_trampoline - 14; //  rtlThreadStartAddress + 8

#endif
}

void HWBreakpoint::ToggleThreadHook(bool set)
{
	if (!m_trampoline)
		return;

	//TODO: replacing opcode in system dll might be dangeruos because another thread may invokes and run throw the code while we still replacing it.
	//		the right solution is to do it from another process which first suspend the target process, inject the changes to his memory, and resume it.

	DWORD oldProtect;
	ULONG_PTR* rtlThreadStartAddress = (ULONG_PTR*)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlUserThreadStart");

	if (set)
	{
		VirtualProtect(rtlThreadStartAddress, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
		((unsigned char*)rtlThreadStartAddress)[0] = 0xE9;
		*(DWORD*)&(((unsigned char*)rtlThreadStartAddress)[1]) = (DWORD)m_trampoline - (DWORD)rtlThreadStartAddress - 5;

		VirtualProtect(rtlThreadStartAddress, 5, oldProtect, &oldProtect);
	}
	else if (*rtlThreadStartAddress != *(ULONG_PTR*)m_orgOpcode)
	{
		VirtualProtect(rtlThreadStartAddress, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
		*(ULONG64*)rtlThreadStartAddress = *(ULONG64*)m_orgOpcode;
		VirtualProtect(rtlThreadStartAddress, 5, oldProtect, &oldProtect);
	}
}

void HWBreakpoint::ThreadDeutor()
{
	HWBreakpoint& bp = GetInstance();
	{
		CriticalSection::Scope lock(bp.m_cs);
		{
			bp.m_pendingThread.tid = GetCurrentThreadId();
			bp.m_pendingThread.enable = true;
			SetEvent(bp.m_workerSignal);
			WaitForSingleObject(bp.m_workerDone, INFINITE);
		}
	}
}

void HWBreakpoint::SetForThreads()
{
	const DWORD pid = GetCurrentProcessId();

	HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
	THREADENTRY32 te32;
	hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
	if (hThreadSnap == INVALID_HANDLE_VALUE)
		return;

	te32.dwSize = sizeof(THREADENTRY32);
	if(!Thread32First(hThreadSnap, &te32))
	{
		CloseHandle(hThreadSnap);
		return;
	}

	do
	{
		if(te32.th32OwnerProcessID == pid)
		{
			CriticalSection::Scope lock(m_cs);
			{
				m_pendingThread.tid = te32.th32ThreadID;
				m_pendingThread.enable = true;
				SetEvent(m_workerSignal);
				WaitForSingleObject(m_workerDone, INFINITE);
			}
		}
	} while(Thread32Next(hThreadSnap, &te32));
}

void HWBreakpoint::SetThread(DWORD tid, bool enableBP)
{
	// this function supposed to be called only from worker thread
	if (GetCurrentThreadId() == tid)
		return;

	HANDLE hThread = OpenThread(THREAD_GET_CONTEXT | THREAD_SET_CONTEXT |  THREAD_SUSPEND_RESUME, FALSE, tid);
	if (!hThread)
		return;

	CONTEXT cxt;
	cxt.ContextFlags = CONTEXT_DEBUG_REGISTERS;

	if (SuspendThread(hThread) == -1)
		goto Final;

	if (!GetThreadContext(hThread, &cxt))
		goto Final;

	for (int index = 0; index < 4; ++index)
	{
		const bool isSet = m_address[index] != nullptr;
		SetBits(cxt.Dr7, index*2, 1, isSet);

		if (isSet)
		{
			switch (index)
			{
			case 0: cxt.Dr0 = (DWORD_PTR) m_address[index]; break;
			case 1: cxt.Dr1 = (DWORD_PTR) m_address[index]; break;
			case 2: cxt.Dr2 = (DWORD_PTR) m_address[index]; break;
			case 3: cxt.Dr3 = (DWORD_PTR) m_address[index]; break;
			}

			SetBits(cxt.Dr7, 16 + (index*4), 2, m_when[index]);
			SetBits(cxt.Dr7, 18 + (index*4), 2, m_len[index]);
		}
	}

	if (!SetThreadContext(hThread, &cxt))
		goto Final;

	if (ResumeThread(hThread) == -1)
		goto Final;

	std::cout << "Set BP for Thread: " << tid << std::endl;

Final:
	CloseHandle(hThread);
}

DWORD HWBreakpoint::WorkerThreadProc(LPVOID lpParameter)
{
	HWBreakpoint& bp = *(HWBreakpoint*)lpParameter;

	SetEvent(bp.m_workerDone);

	while (WaitForSingleObject(bp.m_workerSignal, INFINITE) == WAIT_OBJECT_0)
	{
		// signal for abort
		if (bp.m_pendingThread.tid == -1)
			return 0;

		bp.SetThread(bp.m_pendingThread.tid, bp.m_pendingThread.enable);
		SetEvent(bp.m_workerDone);
	}

	return 0;
}<commit_msg>more elegant code<commit_after>#include "breakpoint.h"
#include <windows.h>
#include <tlhelp32.h>
#include <algorithm>
#include <iostream>

HWBreakpoint::HWBreakpoint()
{
	ZeroMemory(m_address, sizeof(m_address));
	m_countActive = 0;

	BuildTrampoline();
	if (!m_trampoline)
		std::cout << "error: failed to build hook function" << std::endl;

	m_workerSignal = CreateEvent(NULL, FALSE, FALSE, NULL);
	m_workerDone = CreateEvent(NULL, FALSE, FALSE, NULL);
	m_workerThread = CreateThread(NULL, 0, WorkerThreadProc, this, 0, NULL);
	WaitForSingleObject(m_workerDone, INFINITE);
}

HWBreakpoint::~HWBreakpoint()
{
	CriticalSection::Scope lock(m_cs);
	{
		ZeroMemory(m_address, sizeof(m_address));
		SetForThreads();
	}

	m_pendingThread.tid = -1;
	SetEvent(m_workerSignal);
	WaitForSingleObject(m_workerThread, INFINITE);
	CloseHandle(m_workerDone);
	CloseHandle(m_workerSignal);
	CloseHandle(m_workerThread);

	if (m_trampoline)
		VirtualFree(m_trampoline, 0, MEM_RELEASE);
}

bool HWBreakpoint::Set(void* address, int len, Condition when)
{
	HWBreakpoint& bp = GetInstance();
	{
		CriticalSection::Scope lock(bp.m_cs);
		for (int index = 0; index < 4; ++index)
			if (bp.m_address[index] == nullptr)
			{
				bp.m_address[index] = address;
				bp.m_len[index] = len;
				bp.m_when[index] = when;
				if (bp.m_countActive++ == 0)
					bp.ToggleThreadHook(true);
				bp.SetForThreads();
				return true;
			}
	}

	return false;
}

bool HWBreakpoint::Clear(void* address)
{
	HWBreakpoint& bp = GetInstance();
	{
		CriticalSection::Scope lock(bp.m_cs);
		for (int index = 0; index < 4; ++index)
			if (bp.m_address[index] == address)
			{
				bp.m_address[index] = nullptr;
				if (--bp.m_countActive == 0)
					bp.ToggleThreadHook(false);
				bp.SetForThreads();
				return true;
			}
	}

	return false;
}

void HWBreakpoint::ToggleThread(DWORD tid, bool enableBP)
{
	HWBreakpoint& bp = GetInstance();
	{
		CriticalSection::Scope lock(bp.m_cs);
		bp.m_pendingThread.tid = tid;
		bp.m_pendingThread.enable = enableBP;
		SetEvent(bp.m_workerSignal);
		WaitForSingleObject(bp.m_workerDone, INFINITE);
	}
}

void HWBreakpoint::BuildTrampoline()
{
	ULONG_PTR* rtlThreadStartAddress = (ULONG_PTR*)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlUserThreadStart");

	SYSTEM_INFO si;
	GetSystemInfo(&si);

#ifdef _WIN64

	// Explanation:
	// the traditional way is to overwite first instructions in the hook target with
	// an relative uncontitional jmp. this works well in x86 becuase that relative jmp takes
	// only 5 bytes of opcode, and its cover all memory space. things is differente in x64 mode,
	// to cover all memory space, one need to use absolute jmp which cost 14 bytes in opcode. this is too
	// long to overwite for very small functions. the solution is to use two steps: the overwite instruction
	// is a 5 byte relative jmp that jump to a trampoline function, allocated not far from 2GB relative to the
	// target hook. and in the trampoline we have space to specify absolute jump to the real hook function.
	// more details in: http://www.codeproject.com/Articles/44326/MinHook-The-Minimalistic-x-x-API-Hooking-Libra

	// search for avalible memory in 2GB boundary to host the tampoline function
	ULONG_PTR gMinAddress = (ULONG_PTR)si.lpMinimumApplicationAddress;
	ULONG_PTR gMaxAddress = (ULONG_PTR)si.lpMaximumApplicationAddress;
	ULONG_PTR minAddr = std::max<ULONG_PTR>(gMinAddress, (ULONG_PTR)rtlThreadStartAddress - 0x20000000);
	ULONG_PTR maxAddr = std::min<ULONG_PTR>(gMaxAddress, (ULONG_PTR)rtlThreadStartAddress + 0x20000000);

	const size_t BlockSize = si.dwPageSize;
	intptr_t min = minAddr / BlockSize;
	intptr_t max = maxAddr / BlockSize;
	int rel = 0;
	m_trampoline = nullptr;
	MEMORY_BASIC_INFORMATION mi = { 0 };
	for (int i = 0; i < (max - min + 1); ++i)
	{
		rel = -rel + (i & 1);
		void* pQuery = reinterpret_cast<void*>(((min + max) / 2 + rel) * BlockSize);
		VirtualQuery(pQuery, &mi, sizeof(mi));
		if (mi.State == MEM_FREE)
		{
			m_trampoline = (unsigned char*)VirtualAlloc(pQuery, BlockSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
			if (m_trampoline != nullptr)
				break;
		}
	}

	if (!m_trampoline)
		return;

	// save prologe hooked function
	*(ULONG64*)m_orgOpcode = *(ULONG64*)rtlThreadStartAddress;

	*(unsigned char*)	&m_trampoline[0] = 0x51;				// push rcx
	*(unsigned char*)	&m_trampoline[1] = 0x52;				// push rdx
	*(unsigned char*)	&m_trampoline[2] = 0x52;				// push rdx
	*(unsigned short*)	&m_trampoline[3] = 0x15FF;				// call
	*(DWORD*)			&m_trampoline[5] = 0x00000018;			//			ThreadDeutor
	*(unsigned char*)	&m_trampoline[9] = 0x5A;				// pop rdx
	*(unsigned char*)	&m_trampoline[10] = 0x5A;				// pop rdx
	*(unsigned char*)	&m_trampoline[11] = 0x59;				// pop rcx

	*(DWORD*)			&m_trampoline[12] = 0x48EC8348;			// sub rsp, 0x48	(2 instruction from prologe of target hook)
	*(unsigned short*)	&m_trampoline[16] = 0x8B4C;				// mov r9,
	*(unsigned char*)	&m_trampoline[18] = 0xC9;				//			rcx
	*(short*)			&m_trampoline[19] = 0x25FF;				// jmp
	*(DWORD*)			&m_trampoline[21] = 0x00000000;			//		rtlThreadStartAddress + 7

	// address data for call & jump
	*(DWORD64*)			&m_trampoline[25] = (DWORD64)((unsigned char*)rtlThreadStartAddress + 7);
	*(DWORD64*)			&m_trampoline[33] = (DWORD64)ThreadDeutor;

#else

	if (((unsigned char*)rtlThreadStartAddress)[0] != 0x89 || ((unsigned char*)rtlThreadStartAddress)[4] != 0x89 || ((unsigned char*)rtlThreadStartAddress)[8] != 0xE9)
		return;

	m_trampoline = (unsigned char*)VirtualAlloc(NULL, si.dwPageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
	if (!m_trampoline)
		return;

	// save prologe hooked function
	*(ULONG64*)m_orgOpcode = *(ULONG64*)rtlThreadStartAddress;

	*(unsigned char*) &m_trampoline[0] = 0x50;														// push eax
	*(unsigned char*) &m_trampoline[1] = 0x53;														// push ebx
	*(unsigned char*) &m_trampoline[2] = 0xE8;														// call
	*(unsigned long*) &m_trampoline[3] = (ULONG_PTR)ThreadDeutor - (ULONG_PTR)m_trampoline - 7;		//		ThreadDeutor
	*(unsigned char*) &m_trampoline[7] = 0x5B;														// pop ebx
	*(unsigned char*) &m_trampoline[8] = 0x58;														// pop eax

	// execute 2 instruction from prologe of hooked function
	*(unsigned long*)&m_trampoline[9] = *rtlThreadStartAddress;
	*(unsigned long*)&m_trampoline[13] = *(rtlThreadStartAddress + 1);
	*(unsigned char*)&m_trampoline[17] = 0xE9;														// jmp
	*(unsigned long*)&m_trampoline[18] = (ULONG_PTR)rtlThreadStartAddress - (ULONG_PTR)m_trampoline - 14; //  rtlThreadStartAddress + 8

#endif
}

void HWBreakpoint::ToggleThreadHook(bool set)
{
	if (!m_trampoline)
		return;

	//TODO: replacing opcode in system dll might be dangeruos because another thread may invokes and run throw the code while we still replacing it.
	//		the right solution is to do it from another process which first suspend the target process, inject the changes to his memory, and resume it.

	DWORD oldProtect;
	ULONG_PTR* rtlThreadStartAddress = (ULONG_PTR*)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlUserThreadStart");

	if (set)
	{
		VirtualProtect(rtlThreadStartAddress, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
		((unsigned char*)rtlThreadStartAddress)[0] = 0xE9;
		*(DWORD*)&(((unsigned char*)rtlThreadStartAddress)[1]) = (DWORD)m_trampoline - (DWORD)rtlThreadStartAddress - 5;

		VirtualProtect(rtlThreadStartAddress, 5, oldProtect, &oldProtect);
	}
	else if (*rtlThreadStartAddress != *(ULONG_PTR*)m_orgOpcode)
	{
		VirtualProtect(rtlThreadStartAddress, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
		*(ULONG64*)rtlThreadStartAddress = *(ULONG64*)m_orgOpcode;
		VirtualProtect(rtlThreadStartAddress, 5, oldProtect, &oldProtect);
	}
}

void HWBreakpoint::ThreadDeutor()
{
	HWBreakpoint& bp = GetInstance();
	{
		CriticalSection::Scope lock(bp.m_cs);
		{
			bp.m_pendingThread.tid = GetCurrentThreadId();
			bp.m_pendingThread.enable = true;
			SetEvent(bp.m_workerSignal);
			WaitForSingleObject(bp.m_workerDone, INFINITE);
		}
	}
}

void HWBreakpoint::SetForThreads()
{
	const DWORD pid = GetCurrentProcessId();

	HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
	THREADENTRY32 te32;
	hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
	if (hThreadSnap == INVALID_HANDLE_VALUE)
		return;

	te32.dwSize = sizeof(THREADENTRY32);
	if(!Thread32First(hThreadSnap, &te32))
	{
		CloseHandle(hThreadSnap);
		return;
	}

	do
	{
		if(te32.th32OwnerProcessID == pid)
		{
			CriticalSection::Scope lock(m_cs);
			{
				m_pendingThread.tid = te32.th32ThreadID;
				m_pendingThread.enable = true;
				SetEvent(m_workerSignal);
				WaitForSingleObject(m_workerDone, INFINITE);
			}
		}
	} while(Thread32Next(hThreadSnap, &te32));
}

void HWBreakpoint::SetThread(DWORD tid, bool enableBP)
{
	// this function supposed to be called only from worker thread
	if (GetCurrentThreadId() == tid)
		return;

	HANDLE hThread = OpenThread(THREAD_GET_CONTEXT | THREAD_SET_CONTEXT |  THREAD_SUSPEND_RESUME, FALSE, tid);
	if (!hThread)
		return;

	CONTEXT cxt;
	cxt.ContextFlags = CONTEXT_DEBUG_REGISTERS;

	if (SuspendThread(hThread) == -1)
		goto Final;

	if (!GetThreadContext(hThread, &cxt))
		goto Final;

	for (int index = 0; index < 4; ++index)
	{
		const bool isSet = m_address[index] != nullptr;
		SetBits(cxt.Dr7, index*2, 1, isSet);

		if (isSet)
		{
			switch (index)
			{
			case 0: cxt.Dr0 = (DWORD_PTR) m_address[index]; break;
			case 1: cxt.Dr1 = (DWORD_PTR) m_address[index]; break;
			case 2: cxt.Dr2 = (DWORD_PTR) m_address[index]; break;
			case 3: cxt.Dr3 = (DWORD_PTR) m_address[index]; break;
			}

			SetBits(cxt.Dr7, 16 + (index*4), 2, m_when[index]);
			SetBits(cxt.Dr7, 18 + (index*4), 2, m_len[index]);
		}
	}

	if (!SetThreadContext(hThread, &cxt))
		goto Final;

	if (ResumeThread(hThread) == -1)
		goto Final;

	std::cout << "Set BP for Thread: " << tid << std::endl;

Final:
	CloseHandle(hThread);
}

DWORD HWBreakpoint::WorkerThreadProc(LPVOID lpParameter)
{
	HWBreakpoint& bp = *(HWBreakpoint*)lpParameter;

	SetEvent(bp.m_workerDone);

	while (WaitForSingleObject(bp.m_workerSignal, INFINITE) == WAIT_OBJECT_0)
	{
		// signal for abort
		if (bp.m_pendingThread.tid == -1)
			return 0;

		bp.SetThread(bp.m_pendingThread.tid, bp.m_pendingThread.enable);
		SetEvent(bp.m_workerDone);
	}

	return 0;
}<|endoftext|>


<commit_before>#include "roomview.h"
#include "areawidget.h"

RoomView::RoomView(QWidget *parent) :
    QGraphicsView(parent)
{
    scene = new QGraphicsScene;
    setScene(scene);
    active_room = 0;

    connect(this, SIGNAL(customContextMenuRequested(const QPoint &)),
            this, SLOT(showContextMenu(const QPoint &)));
}

void RoomView::addArea()
{
    world->rooms()->addRoomArea(world->rooms()->at(active_room),
                                QRect(QPoint(20, 20), QSize(64, 64)));
    updateRoomView();
}

void RoomView::showContextMenu(const QPoint &point)
{
    QMenu *menu = new QMenu;
    menu->addAction(tr("Set background"), this, SLOT(setBackground()));
    menu->addSeparator();
    menu->addAction(tr("Add an area"), this, SLOT(addArea()));
    menu->exec(mapToGlobal(point));
}

void RoomView::setBackground()
{
    QString bgFile = QFileDialog::getOpenFileName(this,"Select the background file",
                                                  QDir::currentPath(),
                                                  "Images (*.png *.xpm *.jpg *.gif)");
    QPixmap bg(bgFile);
    bg = bg.scaled(world->getSize());

    world->rooms()->setRoomBackground(world->rooms()->at(active_room), bg);
    updateRoomView();
}

void RoomView::updateRoomView()
{
    scene->clear();
    scene->addPixmap(world->rooms()->at(active_room)->background());
    for (int i = 0; i < world->rooms()->at(active_room)->areas()->count(); i++)
    {
        AreaWidget *widget = new AreaWidget(world->rooms()->at(active_room)->areas()->at(i));
        scene->addWidget(widget, Qt::Dialog);
    }
}

void RoomView::setWorld(World *world)
{
    this->world = world;
}

void RoomView::changeActiveRoom(QModelIndex index)
{
    active_room = index.row();
    updateRoomView();
}
<commit_msg>if no image selected, setBackground() leaves the background unchanged<commit_after>#include "roomview.h"
#include "areawidget.h"

RoomView::RoomView(QWidget *parent) :
    QGraphicsView(parent)
{
    scene = new QGraphicsScene;
    setScene(scene);
    active_room = 0;

    connect(this, SIGNAL(customContextMenuRequested(const QPoint &)),
            this, SLOT(showContextMenu(const QPoint &)));
}

void RoomView::addArea()
{
    world->rooms()->addRoomArea(world->rooms()->at(active_room),
                                QRect(QPoint(20, 20), QSize(64, 64)));
    updateRoomView();
}

void RoomView::showContextMenu(const QPoint &point)
{
    QMenu *menu = new QMenu;
    menu->addAction(tr("Set background"), this, SLOT(setBackground()));
    menu->addSeparator();
    menu->addAction(tr("Add an area"), this, SLOT(addArea()));
    menu->exec(mapToGlobal(point));
}

void RoomView::setBackground()
{
    QString bgFile = QFileDialog::getOpenFileName(this,"Select the background file",
                                                  QDir::currentPath(),
                                                  "Images (*.png *.xpm *.jpg *.gif)");
    QPixmap bg(bgFile);
    if (bg.isNull())
        return;

    bg = bg.scaled(world->getSize());

    world->rooms()->setRoomBackground(world->rooms()->at(active_room), bg);
    updateRoomView();
}

void RoomView::updateRoomView()
{
    scene->clear();
    scene->addPixmap(world->rooms()->at(active_room)->background());
    for (int i = 0; i < world->rooms()->at(active_room)->areas()->count(); i++)
    {
        AreaWidget *widget = new AreaWidget(world->rooms()->at(active_room)->areas()->at(i));
        scene->addWidget(widget, Qt::Dialog);
    }
}

void RoomView::setWorld(World *world)
{
    this->world = world;
}

void RoomView::changeActiveRoom(QModelIndex index)
{
    active_room = index.row();
    updateRoomView();
}
<|endoftext|>


<commit_before>// This file is part of the dune-hdd project:
//   http://users.dune-project.org/projects/dune-hdd
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_HDD_LINEARELLIPTIC_DISCRETIZATIONS_INTERFACES_HH
#define DUNE_HDD_LINEARELLIPTIC_DISCRETIZATIONS_INTERFACES_HH

#include <memory>
#include <type_traits>

#include <dune/grid/common/gridview.hh>

#include <dune/stuff/grid/boundaryinfo.hh>
#include <dune/stuff/common/crtp.hh>
#include <dune/stuff/common/logging.hh>

#include <dune/pymor/parameters/base.hh>
#include <dune/pymor/discretizations/interfaces.hh>

#include "../problems/interfaces.hh"

namespace Dune {
namespace HDD {
namespace LinearElliptic {

template< class Traits >
class DiscretizationInterface
  : public Pymor::StationaryDiscretizationInterface< Traits >
{
  typedef Pymor::StationaryDiscretizationInterface< Traits > BaseType;
public:
  typedef typename Traits::derived_type     derived_type;
  typedef typename Traits::GridViewType     GridViewType;
  typedef typename Traits::TestSpaceType    TestSpaceType;
  typedef typename Traits::AnsatzSpaceType  AnsatzSpaceType;

  typedef typename TestSpaceType::PatternType PatternType;

  typedef typename GridViewType::Grid::template Codim< 0 >::Entity EntityType;

  typedef typename GridViewType::ctype    DomainFieldType;
  static const unsigned int               dimDomain = GridViewType::dimension;
  typedef typename Traits::RangeFieldType RangeFieldType;
  static const unsigned int               dimRange = Traits::dimRange;

  typedef Stuff::Grid::BoundaryInfoInterface< typename GridViewType::Intersection >             BoundaryInfoType;
  typedef ProblemInterface< EntityType, DomainFieldType, dimDomain, RangeFieldType, dimRange >  ProblemType;

private:
  static_assert(std::is_base_of< GridView< typename GridViewType::Traits >, GridViewType >::value,
                "GridViewType has to be derived from GridView!");

public:
  DiscretizationInterface(const Pymor::ParameterType tt = Pymor::ParameterType())
    : BaseType(tt)
  {}

  DiscretizationInterface(const Pymor::Parametric& other)
    : BaseType(other)
  {}

  static const std::string static_id()
  {
    return "hdd.linearelliptic.discretization";
  }

  const std::shared_ptr< const GridViewType >& grid_view() const
  {
    CHECK_CRTP(this->as_imp(*this).grid_view());
    return this->as_imp(*this).grid_view();
  }

  const std::shared_ptr< const TestSpaceType >& test_space() const
  {
    CHECK_CRTP(this->as_imp(*this).test_space());
    return this->as_imp(*this).test_space();
  }

  const std::shared_ptr< const TestSpaceType >& ansatz_space() const
  {
    CHECK_CRTP(this->as_imp(*this).ansatz_space());
    return this->as_imp(*this).ansatz_space();
  }

  const PatternType& pattern() const
  {
    CHECK_CRTP(this->as_imp(*this).pattern());
    return this->as_imp(*this).pattern();
  }

  const Stuff::Common::Configuration& boundary_info_cfg() const
  {
    CHECK_CRTP(this->as_imp(*this).boundary_info_cfg());
    return this->as_imp(*this).boundary_info_cfg();
  }

  const BoundaryInfoType& boundary_info() const
  {
    CHECK_CRTP(this->as_imp(*this).boundary_info());
    return this->as_imp(*this).boundary_info();
  }

  const ProblemType& problem() const
  {
    CHECK_CRTP(this->as_imp(*this).model());
    return this->as_imp(*this).model();
  }

  void init(std::ostream& out = Dune::Stuff::Common::Logger().devnull(), const std::string prefix = "")
  {
    CHECK_AND_CALL_CRTP(this->as_imp(*this).init(out, prefix));
  }
}; // class DiscretizationInterface

} // namespace LinearElliptic
} // namespace HDD
} // namespace Dune

#endif // DUNE_HDD_LINEARELLIPTIC_DISCRETIZATIONS_INTERFACES_HH
<commit_msg>[linearelliptic.discretizations.interfaces] updated CRTP<commit_after>// This file is part of the dune-hdd project:
//   http://users.dune-project.org/projects/dune-hdd
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_HDD_LINEARELLIPTIC_DISCRETIZATIONS_INTERFACES_HH
#define DUNE_HDD_LINEARELLIPTIC_DISCRETIZATIONS_INTERFACES_HH

#include <memory>
#include <type_traits>

#include <dune/grid/common/gridview.hh>

#include <dune/stuff/grid/boundaryinfo.hh>
#include <dune/stuff/common/crtp.hh>
#include <dune/stuff/common/logging.hh>

#include <dune/pymor/parameters/base.hh>
#include <dune/pymor/discretizations/interfaces.hh>

#include "../problems/interfaces.hh"

namespace Dune {
namespace HDD {
namespace LinearElliptic {

template< class Traits >
class DiscretizationInterface
  : public Pymor::StationaryDiscretizationInterface< Traits >
{
  typedef Pymor::StationaryDiscretizationInterface< Traits > BaseType;
public:
  typedef typename Traits::derived_type     derived_type;
  typedef typename Traits::GridViewType     GridViewType;
  typedef typename Traits::TestSpaceType    TestSpaceType;
  typedef typename Traits::AnsatzSpaceType  AnsatzSpaceType;

  typedef typename TestSpaceType::PatternType PatternType;

  typedef typename GridViewType::Grid::template Codim< 0 >::Entity EntityType;

  typedef typename GridViewType::ctype    DomainFieldType;
  static const unsigned int               dimDomain = GridViewType::dimension;
  typedef typename Traits::RangeFieldType RangeFieldType;
  static const unsigned int               dimRange = Traits::dimRange;

  typedef Stuff::Grid::BoundaryInfoInterface< typename GridViewType::Intersection >             BoundaryInfoType;
  typedef ProblemInterface< EntityType, DomainFieldType, dimDomain, RangeFieldType, dimRange >  ProblemType;

private:
  static_assert(std::is_base_of< GridView< typename GridViewType::Traits >, GridViewType >::value,
                "GridViewType has to be derived from GridView!");

public:
  DiscretizationInterface(const Pymor::ParameterType tt = Pymor::ParameterType())
    : BaseType(tt)
  {}

  DiscretizationInterface(const Pymor::Parametric& other)
    : BaseType(other)
  {}

  static const std::string static_id()
  {
    return "hdd.linearelliptic.discretization";
  }

  const std::shared_ptr< const GridViewType >& grid_view() const
  {
    CHECK_CRTP(this->as_imp().grid_view());
    return this->as_imp().grid_view();
  }

  const std::shared_ptr< const TestSpaceType >& test_space() const
  {
    CHECK_CRTP(this->as_imp().test_space());
    return this->as_imp().test_space();
  }

  const std::shared_ptr< const TestSpaceType >& ansatz_space() const
  {
    CHECK_CRTP(this->as_imp().ansatz_space());
    return this->as_imp().ansatz_space();
  }

  const PatternType& pattern() const
  {
    CHECK_CRTP(this->as_imp().pattern());
    return this->as_imp().pattern();
  }

  const Stuff::Common::Configuration& boundary_info_cfg() const
  {
    CHECK_CRTP(this->as_imp().boundary_info_cfg());
    return this->as_imp().boundary_info_cfg();
  }

  const BoundaryInfoType& boundary_info() const
  {
    CHECK_CRTP(this->as_imp().boundary_info());
    return this->as_imp().boundary_info();
  }

  const ProblemType& problem() const
  {
    CHECK_CRTP(this->as_imp().model());
    return this->as_imp().model();
  }

  void init(std::ostream& out = Dune::Stuff::Common::Logger().devnull(), const std::string prefix = "")
  {
    CHECK_AND_CALL_CRTP(this->as_imp().init(out, prefix));
  }
}; // class DiscretizationInterface

} // namespace LinearElliptic
} // namespace HDD
} // namespace Dune

#endif // DUNE_HDD_LINEARELLIPTIC_DISCRETIZATIONS_INTERFACES_HH
<|endoftext|>


<commit_before>#include <stan/math/rev/mat.hpp>
#include <gtest/gtest.h>
#include <stan/math/prim/scal/fun/value_of.hpp>
#include <chrono>

using stan::math::var;
using Eigen::Dynamic;
using Eigen::Matrix;

typedef std::chrono::high_resolution_clock::time_point TimeVar;
#define duration(a) std::chrono::duration_cast<std::chrono::microseconds>(a).count()
#define timeNow() std::chrono::high_resolution_clock::now()

//  We check that the values of the new regression match those of one built
//  from existing primitives.
TEST(ProbDistributionsBernoulliLogitGLM, glm_matches_bernoulli_logit_doubles)
{
  Matrix<int, Dynamic, 1> n(3, 1);
  n << 1, 0, 1;
  Matrix<double, Dynamic, Dynamic> x(3, 2);
  x << -12, 46, -42,
      24, 25, 27;
  Matrix<double, Dynamic, 1> beta(2, 1);
  beta << 0.3, 2;
  double alpha = 0.3;
  Matrix<double, Dynamic,1> alphavec = alpha * Matrix<double, 3, 1>::Ones();
  Matrix<double, Dynamic, 1> theta(3, 1);
  theta = x * beta + alphavec;

  EXPECT_FLOAT_EQ((stan::math::bernoulli_logit_lpmf(n, theta)),
                  (stan::math::bernoulli_logit_glm_lpmf(n, x, beta, alpha)));
  EXPECT_FLOAT_EQ((stan::math::bernoulli_logit_lpmf<true>(n, theta)),
                  (stan::math::bernoulli_logit_glm_lpmf<true>(n, x, beta, alpha)));
  EXPECT_FLOAT_EQ((stan::math::bernoulli_logit_lpmf<false>(n, theta)),
                  (stan::math::bernoulli_logit_glm_lpmf<false>(n, x, beta, alpha)));
  EXPECT_FLOAT_EQ((stan::math::bernoulli_logit_lpmf<true, Matrix<int, Dynamic, 1>>(n, theta)),
                  (stan::math::bernoulli_logit_glm_lpmf<true, Matrix<int, Dynamic, 1>>(n, x, beta, alpha)));
  EXPECT_FLOAT_EQ((stan::math::bernoulli_logit_lpmf<false, Matrix<int, Dynamic, 1>>(n, theta)),
                  (stan::math::bernoulli_logit_glm_lpmf<false, Matrix<int, Dynamic, 1>>(n, x, beta, alpha)));
  EXPECT_FLOAT_EQ((stan::math::bernoulli_logit_lpmf<Matrix<int, Dynamic, 1>>(n, theta)),
                  (stan::math::bernoulli_logit_glm_lpmf<Matrix<int, Dynamic, 1>>(n, x, beta, alpha)));
}

//  We check that the gradients of the new regression match those of one built
//  from existing primitives.
TEST(ProbDistributionsBernoulliLogitGLM, glm_matches_bernoulli_logit_vars)
{

  Matrix<int, Dynamic, 1> n(3, 1);
  n << 1, 0, 1;
  Matrix<var, Dynamic, Dynamic> x(3, 2);
  x << -12, 46, -42,
      24, 25, 27;
  Matrix<var, Dynamic, 1> beta(2, 1);
  beta << 0.3, 2;
  var alpha = 0.3;
  Matrix<var, Dynamic,1> alphavec = alpha * Matrix<double, 3, 1>::Ones();
  Matrix<var, Dynamic, 1> theta(3, 1);
  theta = x * beta + alphavec;

  var lp = stan::math::bernoulli_logit_lpmf(n, theta);
  lp.grad();

  stan::math::recover_memory();

  Matrix<int, Dynamic, 1> n2(3, 1);
  n2 << 1, 0, 1;
  Matrix<var, Dynamic, Dynamic> x2(3, 2);
  x2 << -12, 46, -42,
      24, 25, 27;
  Matrix<var, Dynamic, 1> beta2(2, 1);
  beta2 << 0.3, 2;
  var alpha2 = 0.3;

  var lp2 = stan::math::bernoulli_logit_glm_lpmf(n2, x2, beta2, alpha2);
  lp2.grad();

  EXPECT_FLOAT_EQ(lp.val(),
                  lp2.val());
  for (size_t i = 0; i < 2; i++)
  {
    EXPECT_FLOAT_EQ(beta[i].adj(), beta2[i].adj());
  }
  EXPECT_FLOAT_EQ(alpha.adj(), alpha2.adj());
  for (size_t j = 0; j < 3; j++)
  {
    for (size_t i = 0; i < 2; i++)
    {
      EXPECT_FLOAT_EQ(x(j, i).adj(), x2(j, i).adj());
    }
  }
}

//  Here, we compare the speed of the new regression to that of one built from
//  existing primitives.

TEST(ProbDistributionsBernoulliLogitGLM, glm_matches_bernoulli_logit_speed) {
  const int R = 30000;
  const int C = 1000;

  Matrix<int,Dynamic,1> n(R, 1);
  for (size_t i = 0; i < R; i++) {
    n[i] = rand()%2;
  }

  int T1 = 0;
  int T2 = 0;

  for (size_t testnumber = 0; testnumber < 30; testnumber++){
    Matrix<double, Dynamic, Dynamic> xreal = Matrix<double, Dynamic, Dynamic>::Random(R, C);
    Matrix<double, Dynamic, 1> betareal = Matrix<double, Dynamic, Dynamic>::Random(C, 1);
    Matrix<double, 1, 1> alphareal = Matrix<double, 1, 1>::Random(1, 1);
    Matrix<double, Dynamic, 1> alpharealvec = Matrix<double, R, 1>::Ones() * alphareal;

    Matrix<var, Dynamic, 1> beta = betareal;
    Matrix<var, Dynamic, 1> theta(R, 1);

    TimeVar t1 = timeNow();
    theta = (xreal * beta) + alpharealvec;
    var lp = stan::math::bernoulli_logit_lpmf(n, theta);

    lp.grad();
    TimeVar t2 = timeNow();

    stan::math::recover_memory();

    Matrix<var, Dynamic, 1> beta2 = betareal;

    TimeVar t3 = timeNow();
    var lp2 = stan::math::bernoulli_logit_glm_lpmf(n, xreal, beta2, alphareal[0]);
    lp2.grad();
    TimeVar t4 = timeNow();
    stan::math::recover_memory();
    T1 += duration(t2 - t1);
    T2 += duration(t4 - t3);

  }

  std::cout << "Existing Primitives:" << std::endl << T1 << std::endl  << "New Primitives:" << std::endl << T2 << std::endl;
}

<commit_msg>commented out performance test for Travis<commit_after>#include <stan/math/rev/mat.hpp>
#include <gtest/gtest.h>
#include <stan/math/prim/scal/fun/value_of.hpp>
#include <chrono>

using stan::math::var;
using Eigen::Dynamic;
using Eigen::Matrix;

typedef std::chrono::high_resolution_clock::time_point TimeVar;
#define duration(a) std::chrono::duration_cast<std::chrono::microseconds>(a).count()
#define timeNow() std::chrono::high_resolution_clock::now()

//  We check that the values of the new regression match those of one built
//  from existing primitives.
TEST(ProbDistributionsBernoulliLogitGLM, glm_matches_bernoulli_logit_doubles)
{
  Matrix<int, Dynamic, 1> n(3, 1);
  n << 1, 0, 1;
  Matrix<double, Dynamic, Dynamic> x(3, 2);
  x << -12, 46, -42,
      24, 25, 27;
  Matrix<double, Dynamic, 1> beta(2, 1);
  beta << 0.3, 2;
  double alpha = 0.3;
  Matrix<double, Dynamic,1> alphavec = alpha * Matrix<double, 3, 1>::Ones();
  Matrix<double, Dynamic, 1> theta(3, 1);
  theta = x * beta + alphavec;

  EXPECT_FLOAT_EQ((stan::math::bernoulli_logit_lpmf(n, theta)),
                  (stan::math::bernoulli_logit_glm_lpmf(n, x, beta, alpha)));
  EXPECT_FLOAT_EQ((stan::math::bernoulli_logit_lpmf<true>(n, theta)),
                  (stan::math::bernoulli_logit_glm_lpmf<true>(n, x, beta, alpha)));
  EXPECT_FLOAT_EQ((stan::math::bernoulli_logit_lpmf<false>(n, theta)),
                  (stan::math::bernoulli_logit_glm_lpmf<false>(n, x, beta, alpha)));
  EXPECT_FLOAT_EQ((stan::math::bernoulli_logit_lpmf<true, Matrix<int, Dynamic, 1>>(n, theta)),
                  (stan::math::bernoulli_logit_glm_lpmf<true, Matrix<int, Dynamic, 1>>(n, x, beta, alpha)));
  EXPECT_FLOAT_EQ((stan::math::bernoulli_logit_lpmf<false, Matrix<int, Dynamic, 1>>(n, theta)),
                  (stan::math::bernoulli_logit_glm_lpmf<false, Matrix<int, Dynamic, 1>>(n, x, beta, alpha)));
  EXPECT_FLOAT_EQ((stan::math::bernoulli_logit_lpmf<Matrix<int, Dynamic, 1>>(n, theta)),
                  (stan::math::bernoulli_logit_glm_lpmf<Matrix<int, Dynamic, 1>>(n, x, beta, alpha)));
}

//  We check that the gradients of the new regression match those of one built
//  from existing primitives.
TEST(ProbDistributionsBernoulliLogitGLM, glm_matches_bernoulli_logit_vars)
{

  Matrix<int, Dynamic, 1> n(3, 1);
  n << 1, 0, 1;
  Matrix<var, Dynamic, Dynamic> x(3, 2);
  x << -12, 46, -42,
      24, 25, 27;
  Matrix<var, Dynamic, 1> beta(2, 1);
  beta << 0.3, 2;
  var alpha = 0.3;
  Matrix<var, Dynamic,1> alphavec = alpha * Matrix<double, 3, 1>::Ones();
  Matrix<var, Dynamic, 1> theta(3, 1);
  theta = x * beta + alphavec;

  var lp = stan::math::bernoulli_logit_lpmf(n, theta);
  lp.grad();

  stan::math::recover_memory();

  Matrix<int, Dynamic, 1> n2(3, 1);
  n2 << 1, 0, 1;
  Matrix<var, Dynamic, Dynamic> x2(3, 2);
  x2 << -12, 46, -42,
      24, 25, 27;
  Matrix<var, Dynamic, 1> beta2(2, 1);
  beta2 << 0.3, 2;
  var alpha2 = 0.3;

  var lp2 = stan::math::bernoulli_logit_glm_lpmf(n2, x2, beta2, alpha2);
  lp2.grad();

  EXPECT_FLOAT_EQ(lp.val(),
                  lp2.val());
  for (size_t i = 0; i < 2; i++)
  {
    EXPECT_FLOAT_EQ(beta[i].adj(), beta2[i].adj());
  }
  EXPECT_FLOAT_EQ(alpha.adj(), alpha2.adj());
  for (size_t j = 0; j < 3; j++)
  {
    for (size_t i = 0; i < 2; i++)
    {
      EXPECT_FLOAT_EQ(x(j, i).adj(), x2(j, i).adj());
    }
  }
}

//  Here, we compare the speed of the new regression to that of one built from
//  existing primitives.

/*
TEST(ProbDistributionsBernoulliLogitGLM, glm_matches_bernoulli_logit_speed) {
  const int R = 30000;
  const int C = 1000;

  Matrix<int,Dynamic,1> n(R, 1);
  for (size_t i = 0; i < R; i++) {
    n[i] = rand()%2;
  }

  int T1 = 0;
  int T2 = 0;

  for (size_t testnumber = 0; testnumber < 30; testnumber++){
    Matrix<double, Dynamic, Dynamic> xreal = Matrix<double, Dynamic, Dynamic>::Random(R, C);
    Matrix<double, Dynamic, 1> betareal = Matrix<double, Dynamic, Dynamic>::Random(C, 1);
    Matrix<double, 1, 1> alphareal = Matrix<double, 1, 1>::Random(1, 1);
    Matrix<double, Dynamic, 1> alpharealvec = Matrix<double, R, 1>::Ones() * alphareal;

    Matrix<var, Dynamic, 1> beta = betareal;
    Matrix<var, Dynamic, 1> theta(R, 1);

    TimeVar t1 = timeNow();
    theta = (xreal * beta) + alpharealvec;
    var lp = stan::math::bernoulli_logit_lpmf(n, theta);

    lp.grad();
    TimeVar t2 = timeNow();

    stan::math::recover_memory();

    Matrix<var, Dynamic, 1> beta2 = betareal;

    TimeVar t3 = timeNow();
    var lp2 = stan::math::bernoulli_logit_glm_lpmf(n, xreal, beta2, alphareal[0]);
    lp2.grad();
    TimeVar t4 = timeNow();
    stan::math::recover_memory();
    T1 += duration(t2 - t1);
    T2 += duration(t4 - t3);

  }

  std::cout << "Existing Primitives:" << std::endl << T1 << std::endl  << "New Primitives:" << std::endl << T2 << std::endl;
}
*/
<|endoftext|>


<commit_before>/*
 * MRustC - Rust Compiler
 * - By John Hodge (Mutabah/thePowersGang)
 *
 * mir/mir.hpp
 * - MIR (Middle Intermediate Representation) definitions
 */
#pragma once
#include <tagged_union.hpp>
#include <vector>
#include <string>
#include <hir/type.hpp>

namespace MIR {

typedef unsigned int    RegionId;
typedef unsigned int    BasicBlockId;

// "LVALUE" - Assignable values
TAGGED_UNION_EX(LValue, (), Variable, (
    // User-named variable
    (Variable, unsigned int),
    // Temporary with no user-defined name
    (Temporary, struct {
        unsigned int idx;
        }),
    // Function argument (matters for destructuring)
    (Argument, struct {
        unsigned int idx;
        }),
    // `static` or `static mut`
    (Static, ::HIR::Path),
    // Function return
    (Return, struct{}),
    (Field, struct {
        ::std::unique_ptr<LValue>   val;
        unsigned int    field_index;
        }),
    // Dereference a value
    (Deref, struct {
        ::std::unique_ptr<LValue>   val;
        }),
    // Index an array or slice (typeof(val) == [T; n] or [T])
    (Index, struct {
        ::std::unique_ptr<LValue>   val;
        ::std::unique_ptr<LValue>   idx;
        }),
    (Downcast, struct {
        ::std::unique_ptr<LValue>   val;
        unsigned int    variant_index;
        })
    ), (),(), (
        LValue clone() const;
    )
    );
extern ::std::ostream& operator<<(::std::ostream& os, const LValue& x);

enum class eBinOp
{
    ADD, ADD_OV,
    SUB, SUB_OV,
    MUL, MUL_OV,
    DIV, DIV_OV,
    MOD,// MOD_OV,

    BIT_OR,
    BIT_AND,
    BIT_XOR,

    BIT_SHR,
    BIT_SHL,

    EQ, NE,
    GT, GE,
    LT, LE,
};
enum class eUniOp
{
    INV,
    NEG
};

// Compile-time known values
TAGGED_UNION(Constant, Int,
    (Int, ::std::int64_t),
    (Uint, ::std::uint64_t),
    (Float, double),
    (Bool, bool),
    (Bytes, ::std::vector< ::std::uint8_t>),    // Byte string
    (StaticString, ::std::string),  // String
    (Const, struct { ::HIR::Path p; }),   // `const`
    (ItemAddr, ::HIR::Path) // address of a value
    );
extern ::std::ostream& operator<<(::std::ostream& os, const Constant& v);

TAGGED_UNION(RValue, Use,
    (Use, LValue),
    (Constant, Constant),
    (SizedArray, struct {
        LValue  val;
        unsigned int    count;
        }),
    (Borrow, struct {
        RegionId    region;
        ::HIR::BorrowType   type;
        LValue  val;
        }),
    (Cast, struct {
        LValue  val;
        ::HIR::TypeRef  type;
        }),
    (BinOp, struct {
        LValue  val_l;
        eBinOp  op;
        LValue  val_r;
        }),
    (UniOp, struct {
        LValue  val;
        eUniOp  op;
        }),
    (DstMeta, struct {
        LValue  val;
        }),
    (MakeDst, struct {
        LValue  ptr_val;
        LValue  meta_val;
        }),
    (Tuple, struct {
        ::std::vector<LValue>   vals;
        }),
    (Array, struct {
        ::std::vector<LValue>   vals;
        }),
    (Struct, struct {
        ::HIR::GenericPath  path;
        ::std::vector<LValue>   vals;
        })
);
extern ::std::ostream& operator<<(::std::ostream& os, const RValue& x);

TAGGED_UNION(Terminator, Incomplete,
    (Incomplete, struct {}),    // Block isn't complete (ERROR in output)
    (Return, struct {}),    // Return clealy to caller
    (Diverge, struct {}),   // Continue unwinding up the stack
    (Goto, BasicBlockId),   // Jump to another block
    (Panic, struct { BasicBlockId dst; }),  // ?
    (If, struct {
        LValue cond;
        BasicBlockId    bb0;
        BasicBlockId    bb1;
        }),
    (Switch, struct {
        LValue val;
        ::std::vector<BasicBlockId>  targets;
        }),
    (Call, struct {
        BasicBlockId    ret_block;
        BasicBlockId    panic_block;
        LValue  ret_val;
        LValue  fcn_val;
        ::std::vector<LValue>   args;
        })
    );
extern ::std::ostream& operator<<(::std::ostream& os, const Terminator& x);

enum class eDropKind {
    SHALLOW,
    DEEP,
};
TAGGED_UNION(Statement, Assign,
    (Assign, struct {
        LValue  dst;
        RValue  src;
        }),
    (Drop, struct {
        eDropKind   kind;   // NOTE: For the `box` primitive
        LValue  slot;
        })
    );

struct BasicBlock
{
    ::std::vector<Statement>    statements;
    Terminator  terminator;
};

class Function
{
public:
    ::std::vector< ::HIR::TypeRef>  named_variables;
    ::std::vector< ::HIR::TypeRef>  temporaries;

    ::std::vector<BasicBlock>   blocks;
};

};

<commit_msg>MIR - (minor) commenting<commit_after>/*
 * MRustC - Rust Compiler
 * - By John Hodge (Mutabah/thePowersGang)
 *
 * mir/mir.hpp
 * - MIR (Middle Intermediate Representation) definitions
 */
#pragma once
#include <tagged_union.hpp>
#include <vector>
#include <string>
#include <hir/type.hpp>

namespace MIR {

typedef unsigned int    RegionId;
typedef unsigned int    BasicBlockId;

// "LVALUE" - Assignable values
TAGGED_UNION_EX(LValue, (), Variable, (
    // User-named variable
    (Variable, unsigned int),
    // Temporary with no user-defined name
    (Temporary, struct {
        unsigned int idx;
        }),
    // Function argument (matters for destructuring)
    (Argument, struct {
        unsigned int idx;
        }),
    // `static` or `static mut`
    (Static, ::HIR::Path),
    // Function return
    (Return, struct{}),
    // Field access (tuple, struct, tuple struct, enum field, ...)
    (Field, struct {
        ::std::unique_ptr<LValue>   val;
        unsigned int    field_index;
        }),
    // Dereference a value
    (Deref, struct {
        ::std::unique_ptr<LValue>   val;
        }),
    // Index an array or slice (typeof(val) == [T; n] or [T])
    (Index, struct {
        ::std::unique_ptr<LValue>   val;
        ::std::unique_ptr<LValue>   idx;
        }),
    // Interpret an enum as a particular variant
    (Downcast, struct {
        ::std::unique_ptr<LValue>   val;
        unsigned int    variant_index;
        })
    ), (),(), (
        LValue clone() const;
    )
    );
extern ::std::ostream& operator<<(::std::ostream& os, const LValue& x);

enum class eBinOp
{
    ADD, ADD_OV,
    SUB, SUB_OV,
    MUL, MUL_OV,
    DIV, DIV_OV,
    MOD,// MOD_OV,

    BIT_OR,
    BIT_AND,
    BIT_XOR,

    BIT_SHR,
    BIT_SHL,

    EQ, NE,
    GT, GE,
    LT, LE,
};
enum class eUniOp
{
    INV,
    NEG
};

// Compile-time known values
TAGGED_UNION(Constant, Int,
    (Int, ::std::int64_t),
    (Uint, ::std::uint64_t),
    (Float, double),
    (Bool, bool),
    (Bytes, ::std::vector< ::std::uint8_t>),    // Byte string
    (StaticString, ::std::string),  // String
    (Const, struct { ::HIR::Path p; }),   // `const`
    (ItemAddr, ::HIR::Path) // address of a value
    );
extern ::std::ostream& operator<<(::std::ostream& os, const Constant& v);

TAGGED_UNION(RValue, Use,
    (Use, LValue),
    (Constant, Constant),
    (SizedArray, struct {
        LValue  val;
        unsigned int    count;
        }),
    (Borrow, struct {
        RegionId    region;
        ::HIR::BorrowType   type;
        LValue  val;
        }),
    (Cast, struct {
        LValue  val;
        ::HIR::TypeRef  type;
        }),
    (BinOp, struct {
        LValue  val_l;
        eBinOp  op;
        LValue  val_r;
        }),
    (UniOp, struct {
        LValue  val;
        eUniOp  op;
        }),
    (DstMeta, struct {
        LValue  val;
        }),
    (MakeDst, struct {
        LValue  ptr_val;
        LValue  meta_val;
        }),
    (Tuple, struct {
        ::std::vector<LValue>   vals;
        }),
    (Array, struct {
        ::std::vector<LValue>   vals;
        }),
    (Struct, struct {
        ::HIR::GenericPath  path;
        ::std::vector<LValue>   vals;
        })
);
extern ::std::ostream& operator<<(::std::ostream& os, const RValue& x);

TAGGED_UNION(Terminator, Incomplete,
    (Incomplete, struct {}),    // Block isn't complete (ERROR in output)
    (Return, struct {}),    // Return clealy to caller
    (Diverge, struct {}),   // Continue unwinding up the stack
    (Goto, BasicBlockId),   // Jump to another block
    (Panic, struct { BasicBlockId dst; }),  // ?
    (If, struct {
        LValue cond;
        BasicBlockId    bb0;
        BasicBlockId    bb1;
        }),
    (Switch, struct {
        LValue val;
        ::std::vector<BasicBlockId>  targets;
        }),
    (Call, struct {
        BasicBlockId    ret_block;
        BasicBlockId    panic_block;
        LValue  ret_val;
        LValue  fcn_val;
        ::std::vector<LValue>   args;
        })
    );
extern ::std::ostream& operator<<(::std::ostream& os, const Terminator& x);

enum class eDropKind {
    SHALLOW,
    DEEP,
};
TAGGED_UNION(Statement, Assign,
    (Assign, struct {
        LValue  dst;
        RValue  src;
        }),
    (Drop, struct {
        eDropKind   kind;   // NOTE: For the `box` primitive
        LValue  slot;
        })
    );

struct BasicBlock
{
    ::std::vector<Statement>    statements;
    Terminator  terminator;
};

class Function
{
public:
    ::std::vector< ::HIR::TypeRef>  named_variables;
    ::std::vector< ::HIR::TypeRef>  temporaries;

    ::std::vector<BasicBlock>   blocks;
};

};

<|endoftext|>


<commit_before>#ifndef __STAN__PROB__DISTRIBUTIONS__MULTIVARIATE__CONTINUOUS__DIRICHLET_HPP__
#define __STAN__PROB__DISTRIBUTIONS__MULTIVARIATE__CONTINUOUS__DIRICHLET_HPP__

#include <boost/math/special_functions/gamma.hpp>
#include <boost/random/gamma_distribution.hpp>
#include <boost/random/variate_generator.hpp>

#include <stan/prob/constants.hpp>
#include <stan/math/matrix_error_handling.hpp>
#include <stan/math/error_handling.hpp>
#include <stan/prob/traits.hpp>
#include <stan/math/functions/multiply_log.hpp>

namespace stan {

  namespace prob {

    /**
     * The log of the Dirichlet density for the given theta and
     * a vector of prior sample sizes, alpha.
     * Each element of alpha must be greater than 0.
     * Each element of theta must be greater than or 0.
     * Theta sums to 1.
     *
     * \f{eqnarray*}{
       \theta &\sim& \mbox{\sf{Dirichlet}} (\alpha_1, \ldots, \alpha_k) \\
       \log (p (\theta \,|\, \alpha_1, \ldots, \alpha_k) ) &=& \log \left( \frac{\Gamma(\alpha_1 + \cdots + \alpha_k)}{\Gamma(\alpha_1) \cdots \Gamma(\alpha_k)}
          \theta_1^{\alpha_1 - 1} \cdots \theta_k^{\alpha_k - 1} \right) \\
       &=& \log (\Gamma(\alpha_1 + \cdots + \alpha_k)) - \log(\Gamma(\alpha_1)) - \cdots - \log(\Gamma(\alpha_k)) +
           (\alpha_1 - 1) \log (\theta_1) + \cdots + (\alpha_k - 1) \log (\theta_k)
     \f}
     *
     * @param theta A scalar vector.
     * @param alpha Prior sample sizes.
     * @return The log of the Dirichlet density.
     * @throw std::domain_error if any element of alpha is less than
     * or equal to 0.
     * @throw std::domain_error if any element of theta is less than 0.
     * @throw std::domain_error if the sum of theta is not 1.
     * @tparam T_prob Type of scalar.
     * @tparam T_prior_sample_size Type of prior sample sizes.
     */
    template <bool propto,
              typename T_prob, typename T_prior_sample_size>
    typename boost::math::tools::promote_args<T_prob,T_prior_sample_size>::type
    dirichlet_log(const Eigen::Matrix<T_prob,Eigen::Dynamic,1>& theta,
		  const Eigen::Matrix<T_prior_sample_size,Eigen::Dynamic,1>& alpha) {
      static const char* function = "stan::prob::dirichlet_log(%1%)";
      using boost::math::lgamma;
      using boost::math::tools::promote_args;
      using stan::math::check_consistent_sizes;

      typename promote_args<T_prob,T_prior_sample_size>::type lp(0.0);
      if (!check_consistent_sizes(function,theta,alpha,
				  "probabilities","prior sample sizes",
				  &lp))
	return lp;

      // FIXME: parameter check

      using stan::math::multiply_log;
      if (include_summand<propto,T_prior_sample_size>::value) {
        lp += lgamma(alpha.sum());
        for (int k = 0; k < alpha.rows(); ++k)
          lp -= lgamma(alpha[k]);
      }
      if (include_summand<propto,T_prob,T_prior_sample_size>::value)
        for (int k = 0; k < theta.rows(); ++k)
          lp += multiply_log(alpha[k]-1, theta[k]);
      return lp;
    }

    template <typename T_prob, typename T_prior_sample_size>
    inline
    typename boost::math::tools::promote_args<T_prob,T_prior_sample_size>::type
    dirichlet_log(const Eigen::Matrix<T_prob,Eigen::Dynamic,1>& theta,
            const Eigen::Matrix<T_prior_sample_size,Eigen::Dynamic,1>& alpha) {
      return dirichlet_log<false>(theta,alpha);
    }

    template <class RNG>
    inline Eigen::VectorXd
    dirichlet_rng(const Eigen::Matrix<double,Eigen::Dynamic,1>& alpha,
                     RNG& rng) {
      using boost::variate_generator;
      using boost::gamma_distribution;

      double sum = 0;
      Eigen::VectorXd y(alpha.rows());
      for(int i = 0; i < alpha.rows(); i++) {
        variate_generator<RNG&, gamma_distribution<> >
          gamma_rng(rng, gamma_distribution<>(alpha(i,0),1));
        y(i) = gamma_rng();
        sum += y(i);
        }

      for(int i = 0; i < alpha.rows(); i++)
        y(i) /= sum;
      return y;
    }
  }
}
#endif
<commit_msg>dirichlet: checking for alpha > 0<commit_after>#ifndef __STAN__PROB__DISTRIBUTIONS__MULTIVARIATE__CONTINUOUS__DIRICHLET_HPP__
#define __STAN__PROB__DISTRIBUTIONS__MULTIVARIATE__CONTINUOUS__DIRICHLET_HPP__

#include <boost/math/special_functions/gamma.hpp>
#include <boost/random/gamma_distribution.hpp>
#include <boost/random/variate_generator.hpp>

#include <stan/prob/constants.hpp>
#include <stan/math/matrix_error_handling.hpp>
#include <stan/math/error_handling.hpp>
#include <stan/prob/traits.hpp>
#include <stan/math/functions/multiply_log.hpp>

namespace stan {

  namespace prob {

    /**
     * The log of the Dirichlet density for the given theta and
     * a vector of prior sample sizes, alpha.
     * Each element of alpha must be greater than 0.
     * Each element of theta must be greater than or 0.
     * Theta sums to 1.
     *
     * \f{eqnarray*}{
       \theta &\sim& \mbox{\sf{Dirichlet}} (\alpha_1, \ldots, \alpha_k) \\
       \log (p (\theta \,|\, \alpha_1, \ldots, \alpha_k) ) &=& \log \left( \frac{\Gamma(\alpha_1 + \cdots + \alpha_k)}{\Gamma(\alpha_1) \cdots \Gamma(\alpha_k)}
          \theta_1^{\alpha_1 - 1} \cdots \theta_k^{\alpha_k - 1} \right) \\
       &=& \log (\Gamma(\alpha_1 + \cdots + \alpha_k)) - \log(\Gamma(\alpha_1)) - \cdots - \log(\Gamma(\alpha_k)) +
           (\alpha_1 - 1) \log (\theta_1) + \cdots + (\alpha_k - 1) \log (\theta_k)
     \f}
     *
     * @param theta A scalar vector.
     * @param alpha Prior sample sizes.
     * @return The log of the Dirichlet density.
     * @throw std::domain_error if any element of alpha is less than
     * or equal to 0.
     * @throw std::domain_error if any element of theta is less than 0.
     * @throw std::domain_error if the sum of theta is not 1.
     * @tparam T_prob Type of scalar.
     * @tparam T_prior_sample_size Type of prior sample sizes.
     */
    template <bool propto,
              typename T_prob, typename T_prior_sample_size>
    typename boost::math::tools::promote_args<T_prob,T_prior_sample_size>::type
    dirichlet_log(const Eigen::Matrix<T_prob,Eigen::Dynamic,1>& theta,
		  const Eigen::Matrix<T_prior_sample_size,Eigen::Dynamic,1>& alpha) {
      static const char* function = "stan::prob::dirichlet_log(%1%)";
      using boost::math::lgamma;
      using boost::math::tools::promote_args;
      using stan::math::check_consistent_sizes;
      using stan::math::check_positive;

      typename promote_args<T_prob,T_prior_sample_size>::type lp(0.0);
      if (!check_consistent_sizes(function, theta, alpha,
				  "probabilities", "prior sample sizes",
				  &lp))
	return lp;
      if (!check_positive(function, alpha, "prior sample sizes", &lp))
	return lp;
      // FIXME: parameter check

      using stan::math::multiply_log;
      if (include_summand<propto,T_prior_sample_size>::value) {
        lp += lgamma(alpha.sum());
        for (int k = 0; k < alpha.rows(); ++k)
          lp -= lgamma(alpha[k]);
      }
      if (include_summand<propto,T_prob,T_prior_sample_size>::value)
        for (int k = 0; k < theta.rows(); ++k)
          lp += multiply_log(alpha[k]-1, theta[k]);
      return lp;
    }

    template <typename T_prob, typename T_prior_sample_size>
    inline
    typename boost::math::tools::promote_args<T_prob,T_prior_sample_size>::type
    dirichlet_log(const Eigen::Matrix<T_prob,Eigen::Dynamic,1>& theta,
            const Eigen::Matrix<T_prior_sample_size,Eigen::Dynamic,1>& alpha) {
      return dirichlet_log<false>(theta,alpha);
    }

    template <class RNG>
    inline Eigen::VectorXd
    dirichlet_rng(const Eigen::Matrix<double,Eigen::Dynamic,1>& alpha,
                     RNG& rng) {
      using boost::variate_generator;
      using boost::gamma_distribution;

      double sum = 0;
      Eigen::VectorXd y(alpha.rows());
      for(int i = 0; i < alpha.rows(); i++) {
        variate_generator<RNG&, gamma_distribution<> >
          gamma_rng(rng, gamma_distribution<>(alpha(i,0),1));
        y(i) = gamma_rng();
        sum += y(i);
        }

      for(int i = 0; i < alpha.rows(); i++)
        y(i) /= sum;
      return y;
    }
  }
}
#endif
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 deipi.com LLC and contributors. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "server_binary.h"

#ifdef HAVE_REMOTE_PROTOCOL

#include "binary.h"
#include "client_binary.h"

BinaryServer::BinaryServer(const std::shared_ptr<XapiandServer>& server_, ev::loop_ref *loop_, const std::shared_ptr<Binary> &binary_)
	: BaseServer(server_, loop_, binary_->sock),
	  binary(binary_),
	  async_signal(*loop_)
{
	async_signal.set<BinaryServer, &BinaryServer::async_signal_cb>(this);
	async_signal.start();
	LOG_EV(this, "\tStart binary async signal event\n");

	LOG_EV(this, "Start binary accept event (sock=%d)\n", binary->sock);
	LOG_OBJ(this, "CREATED BINARY SERVER!\n");
}

BinaryServer::~BinaryServer()
{
	LOG_OBJ(this, "DELETED BINARY SERVER!\n");
}

void
BinaryServer::async_signal_cb(ev::async &watcher, int revents)
{
	while (binary->tasks.call(share_this<BinaryServer>())) {}
}

void
BinaryServer::io_accept(ev::io &watcher, int revents)
{
	if (EV_ERROR & revents) {
		LOG_EV(this, "ERROR: got invalid binary event (sock=%d): %s\n", binary->sock, strerror(errno));
		return;
	}

	assert(binary->sock == watcher.fd || binary->sock == -1);

	int client_sock;
	if ((client_sock = binary->accept()) < 0) {
		if (!ignored_errorno(errno, false)) {
			LOG_ERR(this, "ERROR: accept binary error (sock=%d): %s\n", binary->sock, strerror(errno));
		}
	} else {
		Worker::create<BinaryClient>(share_this<BinaryServer>(), loop, client_sock, active_timeout, idle_timeout);
	}
}

bool
BinaryServer::trigger_replication(const Endpoint &src_endpoint, const Endpoint &dst_endpoint)
{
	int client_sock = binary->connection_socket();
	if (client_sock  < 0) {
		return false;
	}

	auto client = Worker::create<BinaryClient>(share_this<BinaryServer>(), loop, client_sock, active_timeout, idle_timeout);

	if (!client->init_replication(src_endpoint, dst_endpoint)) {
		return false;
	}

	INFO(this, "Database being synchronized from %s...\n", src_endpoint.as_string().c_str());

	return true;
}

bool
BinaryServer::store(const Endpoints &endpoints, const Xapian::docid &did, const std::string &filename)
{
	int client_sock = binary->connection_socket();
	if (client_sock < 0) {
		return false;
	}

	auto client = Worker::create<BinaryClient>(share_this<BinaryServer>(), loop, client_sock, active_timeout, idle_timeout);

	if (!client->init_storing(endpoints, did, filename)) {
		return false;
	}

	return true;
}

#endif /* HAVE_REMOTE_PROTOCOL */
<commit_msg>Initialize binary remote protocol<commit_after>/*
 * Copyright (C) 2015 deipi.com LLC and contributors. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "server_binary.h"

#ifdef HAVE_REMOTE_PROTOCOL

#include "binary.h"
#include "client_binary.h"

BinaryServer::BinaryServer(const std::shared_ptr<XapiandServer>& server_, ev::loop_ref *loop_, const std::shared_ptr<Binary> &binary_)
	: BaseServer(server_, loop_, binary_->sock),
	  binary(binary_),
	  async_signal(*loop_)
{
	async_signal.set<BinaryServer, &BinaryServer::async_signal_cb>(this);
	async_signal.start();
	LOG_EV(this, "\tStart binary async signal event\n");

	LOG_EV(this, "Start binary accept event (sock=%d)\n", binary->sock);
	LOG_OBJ(this, "CREATED BINARY SERVER!\n");
}

BinaryServer::~BinaryServer()
{
	LOG_OBJ(this, "DELETED BINARY SERVER!\n");
}

void
BinaryServer::async_signal_cb(ev::async &watcher, int revents)
{
	while (binary->tasks.call(share_this<BinaryServer>())) {}
}

void
BinaryServer::io_accept(ev::io &watcher, int revents)
{
	if (EV_ERROR & revents) {
		LOG_EV(this, "ERROR: got invalid binary event (sock=%d): %s\n", binary->sock, strerror(errno));
		return;
	}

	assert(binary->sock == watcher.fd || binary->sock == -1);

	int client_sock;
	if ((client_sock = binary->accept()) < 0) {
		if (!ignored_errorno(errno, false)) {
			LOG_ERR(this, "ERROR: accept binary error (sock=%d): %s\n", binary->sock, strerror(errno));
		}
	} else {
		auto client = Worker::create<BinaryClient>(share_this<BinaryServer>(), loop, client_sock, active_timeout, idle_timeout);

		if (!client->init_remote()) {
			client->detach();
		}
	}
}

bool
BinaryServer::trigger_replication(const Endpoint &src_endpoint, const Endpoint &dst_endpoint)
{
	int client_sock = binary->connection_socket();
	if (client_sock  < 0) {
		return false;
	}

	auto client = Worker::create<BinaryClient>(share_this<BinaryServer>(), loop, client_sock, active_timeout, idle_timeout);

	if (!client->init_replication(src_endpoint, dst_endpoint)) {
		return false;
	}

	INFO(this, "Database being synchronized from %s...\n", src_endpoint.as_string().c_str());

	return true;
}

bool
BinaryServer::store(const Endpoints &endpoints, const Xapian::docid &did, const std::string &filename)
{
	int client_sock = binary->connection_socket();
	if (client_sock < 0) {
		return false;
	}

	auto client = Worker::create<BinaryClient>(share_this<BinaryServer>(), loop, client_sock, active_timeout, idle_timeout);

	if (!client->init_storing(endpoints, did, filename)) {
		return false;
	}

	return true;
}

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


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/
#include "QmitkStoreSCPLauncher.h"
#include <QMessageBox>
#include <QProcessEnvironment>
#include <mitkLogMacros.h>

#include <fstream>
#include <iostream>
#include <QFile>
#include <QTextStream>
#include <QIODevice>
#include <QDir>
#include <QDirIterator>
#include <QCoreApplication>
#include "org_mitk_gui_qt_dicom_config.h"

QmitkStoreSCPLauncher::QmitkStoreSCPLauncher(QmitkStoreSCPLauncherBuilder* builder)
: m_StoreSCP(new QProcess())
{
    connect( m_StoreSCP, SIGNAL(error(QProcess::ProcessError)),this, SLOT(OnProcessError(QProcess::ProcessError)));
    connect( m_StoreSCP, SIGNAL(stateChanged(QProcess::ProcessState)),this, SLOT(OnStateChanged(QProcess::ProcessState)));
    connect( m_StoreSCP, SIGNAL(readyReadStandardOutput()),this, SLOT(OnReadyProcessOutput()));
    SetArgumentList(builder);
}

QmitkStoreSCPLauncher::~QmitkStoreSCPLauncher()
{
    disconnect( m_StoreSCP, SIGNAL(error(QProcess::ProcessError)),this, SLOT(OnProcessError(QProcess::ProcessError)));
    disconnect( m_StoreSCP, SIGNAL(stateChanged(QProcess::ProcessState)),this, SLOT(OnStateChanged(QProcess::ProcessState)));
    disconnect( m_StoreSCP, SIGNAL(readyReadStandardOutput()),this, SLOT(OnReadyProcessOutput()));
    m_StoreSCP->close();
    m_StoreSCP->waitForFinished(1000);
    delete m_StoreSCP;
}

void QmitkStoreSCPLauncher::StartStoreSCP()
{
    FindPathToStoreSCP();
    m_StoreSCP->start(m_PathToStoreSCP,m_ArgumentList);
}

void QmitkStoreSCPLauncher::FindPathToStoreSCP()
{
    QString appPath= QCoreApplication::applicationDirPath();
    if(m_PathToStoreSCP.isEmpty())
    {
        QString fileName;
#ifdef _WIN32
        fileName = "/storescp.exe";
#else
        fileName = "/storescp";
#endif

        m_PathToStoreSCP = fileName;

        //In developement the storescp isn't copied into bin directory
        if(!QFile::exists(m_PathToStoreSCP))
        {
            m_PathToStoreSCP = static_cast<QString>(DCMTK_STORESCP);
        }
    }
}

void QmitkStoreSCPLauncher::OnReadyProcessOutput()
{
    QString out(m_StoreSCP->readAllStandardOutput());
    QStringList allDataList,importList;

    allDataList = out.split("\n",QString::SkipEmptyParts);
    QStringListIterator it(allDataList);

    while(it.hasNext())
    {
        QString output = it.next();
        if (output.contains("E: "))
        {
            output.replace("E: ","");
            m_ErrorText = output;
            OnProcessError(QProcess::UnknownError);
            return;
        }
        if(output.contains("I: storing DICOM file: "))
        {
            output.replace("I: storing DICOM file: ","");
            importList += output;
        }
    }
    if(!importList.isEmpty())
    {
        emit SignalStartImport(importList);
    }
}

void QmitkStoreSCPLauncher::OnProcessError(QProcess::ProcessError err)
{
    switch(err)
    {
    case QProcess::FailedToStart:
        m_ErrorText.prepend("Failed to start storage provider: ");
        m_ErrorText.append(m_StoreSCP->errorString());
        emit SignalStoreSCPError(m_ErrorText);
        m_ErrorText.clear();
        break;
    case QProcess::Crashed:
        m_ErrorText.prepend("Storage provider closed: ");
        m_ErrorText.append(m_StoreSCP->errorString());
        emit SignalStoreSCPError(m_ErrorText);
        m_ErrorText.clear();
        break;
    case QProcess::Timedout:
        m_ErrorText.prepend("Storage provider timeout: ");
        m_ErrorText.append(m_StoreSCP->errorString());
        emit SignalStoreSCPError(m_ErrorText);
        m_ErrorText.clear();
        break;
    case QProcess::WriteError:
        m_ErrorText.prepend("Storage provider write error: ");
        m_ErrorText.append(m_StoreSCP->errorString());
        emit SignalStoreSCPError(m_ErrorText);
        m_ErrorText.clear();
        break;
    case QProcess::ReadError:
        m_ErrorText.prepend("Storage provider read error: ");
        m_ErrorText.append(m_StoreSCP->errorString());
        emit SignalStoreSCPError(m_ErrorText);
        m_ErrorText.clear();
        break;
    case QProcess::UnknownError:
        m_ErrorText.prepend("Storage provider unknown error: ");
        m_ErrorText.append(m_StoreSCP->errorString());
        emit SignalStoreSCPError(m_ErrorText);
        m_ErrorText.clear();
        break;
    default:
        m_ErrorText.prepend("Storage provider unknown error: ");
        m_ErrorText.append(m_StoreSCP->errorString());
        emit SignalStoreSCPError(m_ErrorText);
        m_ErrorText.clear();
        break;
    }
}

void QmitkStoreSCPLauncher::OnStateChanged(QProcess::ProcessState status)
{
    switch(status)
    {
    case QProcess::NotRunning:
        m_StatusText.prepend("Storage provider not running!");
        emit SignalStatusOfStoreSCP(m_StatusText);
        m_StatusText.clear();
        break;
    case QProcess::Starting:
        m_StatusText.prepend("Starting storage provider!");
        emit SignalStatusOfStoreSCP(m_StatusText);
        m_StatusText.clear();
        break;
    case QProcess::Running:
        m_StatusText.prepend(m_ArgumentList[0]).prepend(" Port: ").prepend(m_ArgumentList[2]).prepend(" AET: ").prepend("Storage provider running! ");
        emit SignalStatusOfStoreSCP(m_StatusText);
        m_StatusText.clear();
        break;
    default:
        m_StatusText.prepend("Storage provider unknown error!");
        emit SignalStatusOfStoreSCP(m_StatusText);
        m_StatusText.clear();
        break;
    }
}

void QmitkStoreSCPLauncher::SetArgumentList(QmitkStoreSCPLauncherBuilder* builder)
{
    m_ArgumentList << *builder->GetPort() << QString("-aet") <<*builder->GetAETitle() << *builder->GetTransferSyntax()
        << *builder->GetOtherNetworkOptions() << *builder->GetMode() << QString("-od") << *builder->GetOutputDirectory();
}

QString QmitkStoreSCPLauncher::ArgumentListToQString()
{
    QString argumentString;
    QStringListIterator argumentIterator(m_ArgumentList);
    while(argumentIterator.hasNext())
    {
        argumentString.append(" ");
        argumentString.append(argumentIterator.next());
    }
    return argumentString;
}
<commit_msg>Worked with and without the change with my system...<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/
#include "QmitkStoreSCPLauncher.h"
#include <QMessageBox>
#include <QProcessEnvironment>
#include <mitkLogMacros.h>

#include <fstream>
#include <iostream>
#include <QFile>
#include <QTextStream>
#include <QIODevice>
#include <QDir>
#include <QDirIterator>
#include <QCoreApplication>
#include "org_mitk_gui_qt_dicom_config.h"

QmitkStoreSCPLauncher::QmitkStoreSCPLauncher(QmitkStoreSCPLauncherBuilder* builder)
: m_StoreSCP(new QProcess())
{
    connect( m_StoreSCP, SIGNAL(error(QProcess::ProcessError)),this, SLOT(OnProcessError(QProcess::ProcessError)));
    connect( m_StoreSCP, SIGNAL(stateChanged(QProcess::ProcessState)),this, SLOT(OnStateChanged(QProcess::ProcessState)));
    connect( m_StoreSCP, SIGNAL(readyReadStandardOutput()),this, SLOT(OnReadyProcessOutput()));
    SetArgumentList(builder);
}

QmitkStoreSCPLauncher::~QmitkStoreSCPLauncher()
{
    disconnect( m_StoreSCP, SIGNAL(error(QProcess::ProcessError)),this, SLOT(OnProcessError(QProcess::ProcessError)));
    disconnect( m_StoreSCP, SIGNAL(stateChanged(QProcess::ProcessState)),this, SLOT(OnStateChanged(QProcess::ProcessState)));
    disconnect( m_StoreSCP, SIGNAL(readyReadStandardOutput()),this, SLOT(OnReadyProcessOutput()));
    m_StoreSCP->close();
    m_StoreSCP->waitForFinished(1000);
    delete m_StoreSCP;
}

void QmitkStoreSCPLauncher::StartStoreSCP()
{
    FindPathToStoreSCP();
    m_StoreSCP->start(m_PathToStoreSCP,m_ArgumentList);
}

void QmitkStoreSCPLauncher::FindPathToStoreSCP()
{
    QString appPath= QCoreApplication::applicationDirPath();
    if(m_PathToStoreSCP.isEmpty())
    {
        QString fileName;
#ifdef _WIN32
        fileName = "/storescp.exe";
#else
        fileName = "/storescp";
#endif

        m_PathToStoreSCP = appPath + fileName;

        //In developement the storescp isn't copied into bin directory
        if(!QFile::exists(m_PathToStoreSCP))
        {
            m_PathToStoreSCP = static_cast<QString>(DCMTK_STORESCP);
        }
    }
}

void QmitkStoreSCPLauncher::OnReadyProcessOutput()
{
    QString out(m_StoreSCP->readAllStandardOutput());
    QStringList allDataList,importList;

    allDataList = out.split("\n",QString::SkipEmptyParts);
    QStringListIterator it(allDataList);

    while(it.hasNext())
    {
        QString output = it.next();
        if (output.contains("E: "))
        {
            output.replace("E: ","");
            m_ErrorText = output;
            OnProcessError(QProcess::UnknownError);
            return;
        }
        if(output.contains("I: storing DICOM file: "))
        {
            output.replace("I: storing DICOM file: ","");
            importList += output;
        }
    }
    if(!importList.isEmpty())
    {
        emit SignalStartImport(importList);
    }
}

void QmitkStoreSCPLauncher::OnProcessError(QProcess::ProcessError err)
{
    switch(err)
    {
    case QProcess::FailedToStart:
        m_ErrorText.prepend("Failed to start storage provider: ");
        m_ErrorText.append(m_StoreSCP->errorString());
        emit SignalStoreSCPError(m_ErrorText);
        m_ErrorText.clear();
        break;
    case QProcess::Crashed:
        m_ErrorText.prepend("Storage provider closed: ");
        m_ErrorText.append(m_StoreSCP->errorString());
        emit SignalStoreSCPError(m_ErrorText);
        m_ErrorText.clear();
        break;
    case QProcess::Timedout:
        m_ErrorText.prepend("Storage provider timeout: ");
        m_ErrorText.append(m_StoreSCP->errorString());
        emit SignalStoreSCPError(m_ErrorText);
        m_ErrorText.clear();
        break;
    case QProcess::WriteError:
        m_ErrorText.prepend("Storage provider write error: ");
        m_ErrorText.append(m_StoreSCP->errorString());
        emit SignalStoreSCPError(m_ErrorText);
        m_ErrorText.clear();
        break;
    case QProcess::ReadError:
        m_ErrorText.prepend("Storage provider read error: ");
        m_ErrorText.append(m_StoreSCP->errorString());
        emit SignalStoreSCPError(m_ErrorText);
        m_ErrorText.clear();
        break;
    case QProcess::UnknownError:
        m_ErrorText.prepend("Storage provider unknown error: ");
        m_ErrorText.append(m_StoreSCP->errorString());
        emit SignalStoreSCPError(m_ErrorText);
        m_ErrorText.clear();
        break;
    default:
        m_ErrorText.prepend("Storage provider unknown error: ");
        m_ErrorText.append(m_StoreSCP->errorString());
        emit SignalStoreSCPError(m_ErrorText);
        m_ErrorText.clear();
        break;
    }
}

void QmitkStoreSCPLauncher::OnStateChanged(QProcess::ProcessState status)
{
    switch(status)
    {
    case QProcess::NotRunning:
        m_StatusText.prepend("Storage provider not running!");
        emit SignalStatusOfStoreSCP(m_StatusText);
        m_StatusText.clear();
        break;
    case QProcess::Starting:
        m_StatusText.prepend("Starting storage provider!");
        emit SignalStatusOfStoreSCP(m_StatusText);
        m_StatusText.clear();
        break;
    case QProcess::Running:
        m_StatusText.prepend(m_ArgumentList[0]).prepend(" Port: ").prepend(m_ArgumentList[2]).prepend(" AET: ").prepend("Storage provider running! ");
        emit SignalStatusOfStoreSCP(m_StatusText);
        m_StatusText.clear();
        break;
    default:
        m_StatusText.prepend("Storage provider unknown error!");
        emit SignalStatusOfStoreSCP(m_StatusText);
        m_StatusText.clear();
        break;
    }
}

void QmitkStoreSCPLauncher::SetArgumentList(QmitkStoreSCPLauncherBuilder* builder)
{
    m_ArgumentList << *builder->GetPort() << QString("-aet") <<*builder->GetAETitle() << *builder->GetTransferSyntax()
        << *builder->GetOtherNetworkOptions() << *builder->GetMode() << QString("-od") << *builder->GetOutputDirectory();
}

QString QmitkStoreSCPLauncher::ArgumentListToQString()
{
    QString argumentString;
    QStringListIterator argumentIterator(m_ArgumentList);
    while(argumentIterator.hasNext())
    {
        argumentString.append(" ");
        argumentString.append(argumentIterator.next());
    }
    return argumentString;
}
<|endoftext|>