<commit_before>//===- LazyLiveness.cpp - Lazy, CFG-invariant liveness information --------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass implements a lazy liveness analysis as per "Fast Liveness Checking
// for SSA-form Programs," by Boissinot, et al.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "lazyliveness"
#include "llvm/CodeGen/LazyLiveness.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/PostOrderIterator.h"
using namespace llvm;

char LazyLiveness::ID = 0;
static RegisterPass<LazyLiveness> X("lazy-liveness", "Lazy Liveness Analysis");

void LazyLiveness::computeBackedgeChain(MachineFunction& mf,
                                        MachineBasicBlock* MBB) {
  SparseBitVector<128> tmp = rv[MBB];
  tmp.set(preorder[MBB]);
  tmp &= backedge_source;
  calculated.set(preorder[MBB]);

  for (SparseBitVector<128>::iterator I = tmp.begin(); I != tmp.end(); ++I) {
    assert(rev_preorder.size() > *I && "Unknown block!");

    MachineBasicBlock* SrcMBB = rev_preorder[*I];

    for (MachineBasicBlock::succ_iterator SI = SrcMBB->succ_begin(),
         SE = SrcMBB->succ_end(); SI != SE; ++SI) {
      MachineBasicBlock* TgtMBB = *SI;

      if (backedges.count(std::make_pair(SrcMBB, TgtMBB)) &&
          !rv[MBB].test(preorder[TgtMBB])) {
        if (!calculated.test(preorder[TgtMBB]))
          computeBackedgeChain(mf, TgtMBB);

        tv[MBB].set(preorder[TgtMBB]);
        SparseBitVector<128> right = tv[TgtMBB];
        tv[MBB] |= right;
      }
    }

    tv[MBB].reset(preorder[MBB]);
  }
}

bool LazyLiveness::runOnMachineFunction(MachineFunction &mf) {
  rv.clear();
  tv.clear();
  backedges.clear();
  backedge_source.clear();
  backedge_target.clear();
  calculated.clear();
  preorder.clear();
  rev_preorder.clear();

  rv.resize(mf.size());
  tv.resize(mf.size());
  preorder.resize(mf.size());
  rev_preorder.reserve(mf.size());

  MRI = &mf.getRegInfo();
  MachineDominatorTree& MDT = getAnalysis<MachineDominatorTree>();

  // Step 0: Compute preorder numbering for all MBBs.
  unsigned num = 0;
  for (df_iterator<MachineDomTreeNode*> DI = df_begin(MDT.getRootNode()),
       DE = df_end(MDT.getRootNode()); DI != DE; ++DI) {
    preorder[(*DI)->getBlock()] = num++;
    rev_preorder.push_back((*DI)->getBlock());
  }

  // Step 1: Compute the transitive closure of the CFG, ignoring backedges.
  for (po_iterator<MachineBasicBlock*> POI = po_begin(&*mf.begin()),
       POE = po_end(&*mf.begin()); POI != POE; ++POI) {
    MachineBasicBlock* MBB = *POI;
    SparseBitVector<128>& entry = rv[MBB];
    entry.set(preorder[MBB]);

    for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(),
         SE = MBB->succ_end(); SI != SE; ++SI) {
      DenseMap<MachineBasicBlock*, SparseBitVector<128> >::iterator SII =
                                                         rv.find(*SI);

      // Because we're iterating in postorder, any successor that does not yet
      // have an rv entry must be on a backedge.
      if (SII != rv.end()) {
        entry |= SII->second;
      } else {
        backedges.insert(std::make_pair(MBB, *SI));
        backedge_source.set(preorder[MBB]);
        backedge_target.set(preorder[*SI]);
      }
    }
  }

  for (SparseBitVector<128>::iterator I = backedge_source.begin();
       I != backedge_source.end(); ++I)
    computeBackedgeChain(mf, rev_preorder[*I]);

  for (po_iterator<MachineBasicBlock*> POI = po_begin(&*mf.begin()),
       POE = po_end(&*mf.begin()); POI != POE; ++POI)
    if (!backedge_target.test(preorder[*POI]))
      for (MachineBasicBlock::succ_iterator SI = (*POI)->succ_begin(),
           SE = (*POI)->succ_end(); SI != SE; ++SI)
        if (!backedges.count(std::make_pair(*POI, *SI)) && tv.count(*SI)) {
          SparseBitVector<128> right = tv[*SI];
          tv[*POI] |= right;
        }

  for (po_iterator<MachineBasicBlock*> POI = po_begin(&*mf.begin()),
       POE = po_end(&*mf.begin()); POI != POE; ++POI)
    tv[*POI].set(preorder[*POI]);

  return false;
}

bool LazyLiveness::vregLiveIntoMBB(unsigned vreg, MachineBasicBlock* MBB) {
  MachineDominatorTree& MDT = getAnalysis<MachineDominatorTree>();

  MachineBasicBlock* DefMBB = MRI->def_begin(vreg)->getParent();
  unsigned def = preorder[DefMBB];
  unsigned max_dom = 0;
  for (df_iterator<MachineDomTreeNode*> DI = df_begin(MDT[DefMBB]),
       DE = df_end(MDT[DefMBB]); DI != DE; ++DI) {
    if (preorder[DI->getBlock()] > max_dom) {
      max_dom = preorder[(*DI)->getBlock()];
    }
  }

  if (preorder[MBB] <= def || max_dom < preorder[MBB])
    return false;

  SparseBitVector<128>::iterator I = tv[MBB].begin();
  while (I != tv[MBB].end() && *I <= def) ++I;
  while (I != tv[MBB].end() && *I < max_dom) {
    for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(vreg),
         UE = MachineRegisterInfo::use_end(); UI != UE; ++UI) {
      MachineBasicBlock* UseMBB = UI->getParent();
      if (rv[rev_preorder[*I]].test(preorder[UseMBB]))
        return true;

      unsigned t_dom = 0;
      for (df_iterator<MachineDomTreeNode*> DI =
           df_begin(MDT[rev_preorder[*I]]), DE = df_end(MDT[rev_preorder[*I]]);
           DI != DE; ++DI)
        if (preorder[DI->getBlock()] > t_dom) {
          max_dom = preorder[(*DI)->getBlock()];
        }
      I = tv[MBB].begin();
      while (I != tv[MBB].end() && *I < t_dom) ++I;
    }
  }

  return false;
}
<commit_msg>Remove LazyLiveness from the tree.  It doesn't work right now, and I'm not going to have the time to finish it any time soon.  If someone's interested it, they can resurrect it from SVN history.<commit_after><|endoftext|>


<commit_before>//
// Copyright 2016 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "FirebaseArduino.h"

// This is needed to compile std::string on esp8266.
template class std::basic_string<char>;

void FirebaseArduino::begin(const String& host, const String& auth) {
  host_ = host.c_str();
  auth_ = auth.c_str();
}

void FirebaseArduino::initStream() {
  if (stream_http_.get() == nullptr) {
    stream_http_.reset(FirebaseHttpClient::create());
    stream_http_->setReuseConnection(true);
    stream_.reset(new FirebaseStream(stream_http_));
  }
}

void FirebaseArduino::initRequest() {
  if (req_http_.get() == nullptr) {
    req_http_.reset(FirebaseHttpClient::create());
    req_http_->setReuseConnection(true);
    req_.reset(new FirebaseRequest(req_http_));
  }
}

String FirebaseArduino::pushInt(const String& path, int value) {
  return push(path, value);
}

String FirebaseArduino::pushFloat(const String& path, float value) {
  return push(path, value);
}

String FirebaseArduino::pushBool(const String& path, bool value) {
  return push(path, value);
}

String FirebaseArduino::pushString(const String& path, const String& value) {
  JsonVariant json(value.c_str());
  return push(path, json);
}

String FirebaseArduino::push(const String& path, const JsonVariant& value) {
  int size = value.measureLength()+1;
  char * buf = new char[size];
  value.printTo(buf, size);
  initRequest();
  int status = req_.get()->sendRequest(host_, auth_, "POST", path.c_str(), buf);
  error_ = req_.get()->error();
  const char* name = req_.get()->json()["name"].as<const char*>();
  delete buf;
  return name;
}

void FirebaseArduino::setInt(const String& path, int value) {
  set(path, value);
}

void FirebaseArduino::setFloat(const String& path, float value) {
  set(path, value);
}

void FirebaseArduino::setBool(const String& path, bool value) {
  set(path, value);
}

void FirebaseArduino::setString(const String& path, const String& value) {
  JsonVariant json(value.c_str());
  set(path, json);
}

void FirebaseArduino::set(const String& path, const JsonVariant& value) {
  int size = value.measureLength()+1;
  char* buf= new char[size];
  value.printTo(buf, size);
  initRequest();
  req_.get()->sendRequest(host_, auth_, "PUT", path.c_str(), buf);
  error_ = req_.get()->error();
  delete buf;
}

void FirebaseArduino::getRequest(const String& path) {
  initRequest();
  req_.get()->sendRequest(host_, auth_, "GET", path.c_str());
  error_ = req_.get()->error();
}

FirebaseObject FirebaseArduino::get(const String& path) {
  getRequest(path);
  if (failed()) {
    return FirebaseObject{""};
  }
  return FirebaseObject(req_.get()->response().c_str());
}

int FirebaseArduino::getInt(const String& path) {
  getRequest(path);
  if (failed()) {
    return 0;
  }
  return FirebaseObject(req_.get()->response().c_str()).getInt();
}

float FirebaseArduino::getFloat(const String& path) {
  getRequest(path);
  if (failed()) {
    return 0.0f;
  }
  return FirebaseObject(req_.get()->response().c_str()).getFloat();
}

String FirebaseArduino::getString(const String& path) {
  getRequest(path);
  if (failed()) {
    return "";
  }
  return FirebaseObject(req_.get()->response().c_str()).getString();
}

bool FirebaseArduino::getBool(const String& path) {
  getRequest(path);
  if (failed()) {
    return "";
  }
  return FirebaseObject(req_.get()->response().c_str()).getBool();
}
void FirebaseArduino::remove(const String& path) {
  initRequest();
  req_.get()->sendRequest(host_, auth_, "DELETE", path.c_str());
  error_ = req_.get()->error();
}

void FirebaseArduino::stream(const String& path) {
  initStream();
  stream_.get()->startStreaming(host_, auth_, path.c_str());
  error_ = stream_.get()->error();
}

bool FirebaseArduino::available() {
  if (stream_http_.get() == nullptr) {
    error_ = FirebaseError(FIREBASE_ERROR_CODES::STREAM_NOT_INITIALIZED, "HTTP stream is not initialized");
    return 0;
  }
  if (!stream_http_.get()->connected()) {
    error_ = FirebaseError(FIREBASE_ERROR_CODES::HTTP_CONNECTION_LOST, "Connection Lost");
    return 0;
  }
  auto client = stream_http_.get()->getStreamPtr();
  return (client == nullptr) ? false : client->available();
}

FirebaseObject FirebaseArduino::readEvent() {
  if (stream_http_.get() == nullptr) {
    return FirebaseObject("");
  }
  auto client = stream_http_.get()->getStreamPtr();
  if (client == nullptr) {
      return FirebaseObject("");
  }
  String type = client->readStringUntil('\n').substring(7);;
  String event = client->readStringUntil('\n').substring(6);
  client->readStringUntil('\n'); // consume separator
  FirebaseObject obj = FirebaseObject(event.c_str());
  obj.getJsonVariant().as<JsonObject&>().set("type", type);
  return obj;
}

bool FirebaseArduino::success() {
  return error_.code() == 0;
}

bool FirebaseArduino::failed() {
  return error_.code() != 0;
}

const String& FirebaseArduino::error() {
  return error_.message().c_str();
}

FirebaseArduino Firebase;
<commit_msg>Fixed!<commit_after>//
// Copyright 2016 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "FirebaseArduino.h"

// This is needed to compile std::string on esp8266.
template class std::basic_string<char>;

void FirebaseArduino::begin(const String& host, const String& auth) {
  host_ = host.c_str();
  auth_ = auth.c_str();
}

void FirebaseArduino::initStream() {
  if (stream_http_.get() == nullptr) {
    stream_http_.reset(FirebaseHttpClient::create());
    stream_http_->setReuseConnection(true);
    stream_.reset(new FirebaseStream(stream_http_));
  }
}

void FirebaseArduino::initRequest() {
  if (req_http_.get() == nullptr) {
    req_http_.reset(FirebaseHttpClient::create());
    req_http_->setReuseConnection(true);
    req_.reset(new FirebaseRequest(req_http_));
  }
}

String FirebaseArduino::pushInt(const String& path, int value) {
  return push(path, value);
}

String FirebaseArduino::pushFloat(const String& path, float value) {
  return push(path, value);
}

String FirebaseArduino::pushBool(const String& path, bool value) {
  return push(path, value);
}

String FirebaseArduino::pushString(const String& path, const String& value) {
  JsonVariant json(value.c_str());
  return push(path, json);
}

String FirebaseArduino::push(const String& path, const JsonVariant& value) {
  int size = value.measureLength()+1;
  char * buf = new char[size];
  value.printTo(buf, size);
  initRequest();
  int status = req_.get()->sendRequest(host_, auth_, "POST", path.c_str(), buf);
  error_ = req_.get()->error();
  const char* name = req_.get()->json()["name"].as<const char*>();
  delete buf;
  return name;
}

void FirebaseArduino::setInt(const String& path, int value) {
  set(path, value);
}

void FirebaseArduino::setFloat(const String& path, float value) {
  set(path, value);
}

void FirebaseArduino::setBool(const String& path, bool value) {
  set(path, value);
}

void FirebaseArduino::setString(const String& path, const String& value) {
  JsonVariant json(value.c_str());
  set(path, json);
}

void FirebaseArduino::set(const String& path, const JsonVariant& value) {
  int size = value.measureLength()+1;
  char* buf= new char[size];
  value.printTo(buf, size);
  initRequest();
  req_.get()->sendRequest(host_, auth_, "PUT", path.c_str(), buf);
  error_ = req_.get()->error();
  delete buf;
}

void FirebaseArduino::getRequest(const String& path) {
  initRequest();
  req_.get()->sendRequest(host_, auth_, "GET", path.c_str());
  error_ = req_.get()->error();
}

FirebaseObject FirebaseArduino::get(const String& path) {
  getRequest(path);
  if (failed()) {
    return FirebaseObject{""};
  }
  return FirebaseObject(req_.get()->response().c_str());
}

int FirebaseArduino::getInt(const String& path) {
  getRequest(path);
  if (failed()) {
    return 0;
  }
  return FirebaseObject(req_.get()->response().c_str()).getInt();
}

float FirebaseArduino::getFloat(const String& path) {
  getRequest(path);
  if (failed()) {
    return 0.0f;
  }
  return FirebaseObject(req_.get()->response().c_str()).getFloat();
}

String FirebaseArduino::getString(const String& path) {
  getRequest(path);
  if (failed()) {
    return "";
  }
  return FirebaseObject(req_.get()->response().c_str()).getString();
}

bool FirebaseArduino::getBool(const String& path) {
  getRequest(path);
  if (failed()) {
    return "";
  }
  return FirebaseObject(req_.get()->response().c_str()).getBool();
}
void FirebaseArduino::remove(const String& path) {
  initRequest();
  req_.get()->sendRequest(host_, auth_, "DELETE", path.c_str());
  error_ = req_.get()->error();
}

void FirebaseArduino::stream(const String& path) {
  initStream();
  stream_.get()->startStreaming(host_, auth_, path.c_str());
  error_ = stream_.get()->error();
}

bool FirebaseArduino::available() {
  if (stream_http_.get() == nullptr) {
    error_ = FirebaseError(FIREBASE_ERROR_CODES::STREAM_NOT_INITIALIZED, "HTTP stream is not initialized");
    return 0;
  }
  if (!stream_http_.get()->connected()) {
    error_ = FirebaseError(FIREBASE_ERROR_CODES::HTTP_CONNECTION_LOST, "Connection Lost");
    return 0;
  }
  auto client = stream_http_.get()->getStreamPtr();
  return (client == nullptr) ? false : client->available();
}

FirebaseObject FirebaseArduino::readEvent() {
  if (stream_http_.get() == nullptr) {
    return FirebaseObject("");
  }
  auto client = stream_http_.get()->getStreamPtr();
  if (client == nullptr) {
      return FirebaseObject("");
  }
  String type = client->readStringUntil('\n').substring(7);;
  String event = client->readStringUntil('\n').substring(6);
  client->readStringUntil('\n'); // consume separator
  FirebaseObject obj = FirebaseObject(event.c_str());

  // required to have a copy of the string but use a char[] format which is
  // the only supported format for JsonObject#set (it does not like the std::string of the test env)
  char *cstr = new char[type.length() + 1];
  strcpy(cstr, type.c_str());
  obj.getJsonVariant().as<JsonObject&>().set("type", cstr);
  return obj;
}

bool FirebaseArduino::success() {
  return error_.code() == 0;
}

bool FirebaseArduino::failed() {
  return error_.code() != 0;
}

const String& FirebaseArduino::error() {
  return error_.message().c_str();
}

FirebaseArduino Firebase;
<|endoftext|>


<commit_before>/**
 * Appcelerator Titanium - licensed under the Apache Public License 2
 * see LICENSE in the root folder for details on the license.
 * Copyright (c) 2009 Appcelerator, Inc. All Rights Reserved.
 */
#include "../ui_module.h"

using std::vector;
using std::map;
namespace ti
{
	Win32MenuItem::Win32MenuItem(MenuItemType type) :
		MenuItem(type),
		oldSubmenu(0),
		wideOldLabel(::UTF8ToWide(label))
	{
	}

	Win32MenuItem::~Win32MenuItem()
	{
	}

	void Win32MenuItem::SetLabelImpl(std::string newLabel)
	{
		if (!this->IsSeparator())
		{
			this->wideOldLabel = ::UTF8ToWide(newLabel);;
			this->RecreateAllNativeItems();
		}

		if (this->nativeItems.size() > 0)
		{
			Win32UserWindow::RedrawAllMenus();
		}
	}

	void Win32MenuItem::SetIconImpl(std::string newIconPath)
	{
		this->iconPath = newIconPath;

		if (!this->IsCheck() && !this->IsSeparator())
		{
			this->RecreateAllNativeItems();
		}

		if (this->nativeItems.size() > 0)
		{
			Win32UserWindow::RedrawAllMenus();
		}
	}

	void Win32MenuItem::SetStateImpl(bool newState)
	{
		if (this->IsCheck())
		{
			this->RecreateAllNativeItems();
		}

		if (this->nativeItems.size() > 0)
		{
			Win32UserWindow::RedrawAllMenus();
		}
	}

	void Win32MenuItem::SetSubmenuImpl(AutoMenu newSubmenu)
	{
		if (!this->IsSeparator())
		{
			this->RecreateAllNativeItems();
			this->oldSubmenu = newSubmenu.cast<Win32Menu>();
		}

		if (this->nativeItems.size() > 0)
		{
			Win32UserWindow::RedrawAllMenus();
		}
	}

	void Win32MenuItem::SetEnabledImpl(bool enabled)
	{
		if (!this->IsSeparator())
		{
			this->RecreateAllNativeItems();
		}

		if (this->nativeItems.size() > 0)
		{
			Win32UserWindow::RedrawAllMenus();
		}
	}

	void Win32MenuItem::RecreateAllNativeItems()
	{
		std::vector<NativeItemBits*>::iterator i = this->nativeItems.begin();
		while (i != this->nativeItems.end())
		{
			NativeItemBits* bits = (*i++);
			this->RecreateMenuItem(bits);
		}
	}

	void Win32MenuItem::RecreateMenuItem(NativeItemBits* bits)
	{
		int nativePosition = GetNativeMenuItemPosition(bits);
		Win32Menu::RemoveItemAtFromNativeMenu(this, bits->parentMenu, nativePosition);
		Win32Menu::InsertItemIntoNativeMenu(this, bits->parentMenu, true, nativePosition);
	}

	void Win32MenuItem::CreateNative(
		LPMENUITEMINFO itemInfo, HMENU nativeParentMenu, bool registerNative)
	{
		ZeroMemory(itemInfo, sizeof(MENUITEMINFO));
		itemInfo->cbSize = sizeof(MENUITEMINFO);
		itemInfo->wID = ++Win32UIBinding::nextItemId;
		itemInfo->dwItemData = (ULONG_PTR) this;
		itemInfo->fMask = MIIM_ID | MIIM_FTYPE | MIIM_DATA;

		HMENU nativeSubmenu = 0;
		if (this->IsSeparator())
		{
			itemInfo->fType = MFT_SEPARATOR;
		}
		else
		{
			itemInfo->fMask = itemInfo->fMask | MIIM_STRING | MIIM_SUBMENU | MIIM_STATE;
			itemInfo->fType = MFT_STRING;
			itemInfo->fState = this->IsEnabled() ? MFS_ENABLED : MFS_DISABLED;
			itemInfo->dwTypeData = (LPWSTR) this->wideOldLabel.c_str();

			AutoPtr<Win32Menu> wsubmenu = this->submenu.cast<Win32Menu>();
			if (!wsubmenu.isNull())
				nativeSubmenu = wsubmenu->CreateNative(registerNative);

			itemInfo->hSubMenu = nativeSubmenu;

			if (this->IsCheck())
			{
				itemInfo->fState |= this->GetState() ? MFS_CHECKED : MFS_UNCHECKED;
			}
			else if (!this->iconPath.empty())
			{
				HBITMAP bitmap = Win32UIBinding::LoadImageAsBitmap(iconPath, 0, 0);
				if (bitmap)
				{
					itemInfo->fMask = itemInfo->fMask | MIIM_BITMAP;
					itemInfo->hbmpItem = bitmap;
				}
				else
				{
					std::string error = Win32Utils::QuickFormatMessage(GetLastError());
					Logger::Get("UI.MenuItem")->Error("Could not load icon (%s): %s",
						iconPath.c_str(), error.c_str());
				}
			}
		}

		if (registerNative)
		{
			NativeItemBits* bits = new NativeItemBits;
			bits->id = itemInfo->wID;
			bits->parentMenu = nativeParentMenu;
			bits->submenu = nativeSubmenu;
			this->nativeItems.push_back(bits);
		}
	}

	void Win32MenuItem::DestroyNative(NativeItemBits* bits)
	{
		// Erase the reference to this item in our registry
		vector<NativeItemBits*>::iterator i = nativeItems.begin();
		while (i != nativeItems.end())
		{
			if (*i == bits)
				i = nativeItems.erase(i);
			else
				i++;
		}

		if (bits->submenu)
		{
			this->oldSubmenu->DestroyNative(bits->submenu);
		}

		delete bits;
	}

	void Win32MenuItem::DestroyNative(HMENU nativeParent, int position)
	{
		UINT nativeId = GetMenuItemID(nativeParent, position);
		HMENU submenu = GetSubMenu(nativeParent, position);

		vector<NativeItemBits*>::iterator i = nativeItems.begin();
		while (i != nativeItems.end())
		{
			NativeItemBits* b = *i++;

			if ((b->submenu && submenu) ||
				(!b->submenu && b->id == nativeId))
			{
				this->DestroyNative(b);
				return;
			}
		}
	}

	/*static*/
	int Win32MenuItem::GetNativeMenuItemPosition(NativeItemBits* bits)
	{
		int count = GetMenuItemCount(bits->parentMenu);
		for (int i = 0; i < count; i++)
		{

			if ((bits->submenu && GetSubMenu(bits->parentMenu, i) == bits->submenu) ||
				(bits->id == GetMenuItemID(bits->parentMenu, i)))
				return i;
		}

		throw ValueException::FromString("Could not find native item index in native menu.");
	}

	/*static*/
	bool Win32MenuItem::HandleClickEvent(HMENU nativeMenu, UINT position)
	{
		MENUITEMINFO itemInfo;
		ZeroMemory(&itemInfo, sizeof(MENUITEMINFO));
		itemInfo.cbSize = sizeof(MENUITEMINFO);
		itemInfo.fMask = MIIM_DATA;
		GetMenuItemInfo(nativeMenu, position, TRUE, &itemInfo);

		if (itemInfo.dwItemData)
		{
			MenuItem* item = (MenuItem*) itemInfo.dwItemData;
			item->HandleClickEvent(NULL);
			return true;
		}

		return false;
	}
}

<commit_msg>Fix loading menu icons in Win32.<commit_after>/**
 * Appcelerator Titanium - licensed under the Apache Public License 2
 * see LICENSE in the root folder for details on the license.
 * Copyright (c) 2009 Appcelerator, Inc. All Rights Reserved.
 */
#include "../ui_module.h"

using std::vector;
using std::map;
namespace ti
{
	Win32MenuItem::Win32MenuItem(MenuItemType type) :
		MenuItem(type),
		oldSubmenu(0),
		wideOldLabel(::UTF8ToWide(label))
	{
	}

	Win32MenuItem::~Win32MenuItem()
	{
	}

	void Win32MenuItem::SetLabelImpl(std::string newLabel)
	{
		if (!this->IsSeparator())
		{
			this->wideOldLabel = ::UTF8ToWide(newLabel);;
			this->RecreateAllNativeItems();
		}

		if (this->nativeItems.size() > 0)
		{
			Win32UserWindow::RedrawAllMenus();
		}
	}

	void Win32MenuItem::SetIconImpl(std::string newIconPath)
	{
		this->iconPath = newIconPath;

		if (!this->IsCheck() && !this->IsSeparator())
		{
			this->RecreateAllNativeItems();
		}

		if (this->nativeItems.size() > 0)
		{
			Win32UserWindow::RedrawAllMenus();
		}
	}

	void Win32MenuItem::SetStateImpl(bool newState)
	{
		if (this->IsCheck())
		{
			this->RecreateAllNativeItems();
		}

		if (this->nativeItems.size() > 0)
		{
			Win32UserWindow::RedrawAllMenus();
		}
	}

	void Win32MenuItem::SetSubmenuImpl(AutoMenu newSubmenu)
	{
		if (!this->IsSeparator())
		{
			this->RecreateAllNativeItems();
			this->oldSubmenu = newSubmenu.cast<Win32Menu>();
		}

		if (this->nativeItems.size() > 0)
		{
			Win32UserWindow::RedrawAllMenus();
		}
	}

	void Win32MenuItem::SetEnabledImpl(bool enabled)
	{
		if (!this->IsSeparator())
		{
			this->RecreateAllNativeItems();
		}

		if (this->nativeItems.size() > 0)
		{
			Win32UserWindow::RedrawAllMenus();
		}
	}

	void Win32MenuItem::RecreateAllNativeItems()
	{
		std::vector<NativeItemBits*>::iterator i = this->nativeItems.begin();
		while (i != this->nativeItems.end())
		{
			NativeItemBits* bits = (*i++);
			this->RecreateMenuItem(bits);
		}
	}

	void Win32MenuItem::RecreateMenuItem(NativeItemBits* bits)
	{
		int nativePosition = GetNativeMenuItemPosition(bits);
		Win32Menu::RemoveItemAtFromNativeMenu(this, bits->parentMenu, nativePosition);
		Win32Menu::InsertItemIntoNativeMenu(this, bits->parentMenu, true, nativePosition);
	}

	void Win32MenuItem::CreateNative(
		LPMENUITEMINFO itemInfo, HMENU nativeParentMenu, bool registerNative)
	{
		ZeroMemory(itemInfo, sizeof(MENUITEMINFO));
		itemInfo->cbSize = sizeof(MENUITEMINFO);
		itemInfo->wID = ++Win32UIBinding::nextItemId;
		itemInfo->dwItemData = (ULONG_PTR) this;
		itemInfo->fMask = MIIM_ID | MIIM_FTYPE | MIIM_DATA;

		HMENU nativeSubmenu = 0;
		if (this->IsSeparator())
		{
			itemInfo->fType = MFT_SEPARATOR;
		}
		else
		{
			itemInfo->fMask = itemInfo->fMask | MIIM_STRING | MIIM_SUBMENU | MIIM_STATE;
			itemInfo->fType = MFT_STRING;
			itemInfo->fState = this->IsEnabled() ? MFS_ENABLED : MFS_DISABLED;
			itemInfo->dwTypeData = (LPWSTR) this->wideOldLabel.c_str();

			AutoPtr<Win32Menu> wsubmenu = this->submenu.cast<Win32Menu>();
			if (!wsubmenu.isNull())
				nativeSubmenu = wsubmenu->CreateNative(registerNative);

			itemInfo->hSubMenu = nativeSubmenu;

			if (this->IsCheck())
			{
				itemInfo->fState |= this->GetState() ? MFS_CHECKED : MFS_UNCHECKED;
			}
			else if (!this->iconPath.empty())
			{
				HBITMAP bitmap = Win32UIBinding::LoadImageAsBitmap(iconPath,
					GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
				if (bitmap)
				{
					itemInfo->fMask = itemInfo->fMask | MIIM_BITMAP;
					itemInfo->hbmpItem = bitmap;
				}
				else
				{
					std::string error = Win32Utils::QuickFormatMessage(GetLastError());
					Logger::Get("UI.MenuItem")->Error("Could not load icon (%s): %s",
						iconPath.c_str(), error.c_str());
				}
			}
		}

		if (registerNative)
		{
			NativeItemBits* bits = new NativeItemBits;
			bits->id = itemInfo->wID;
			bits->parentMenu = nativeParentMenu;
			bits->submenu = nativeSubmenu;
			this->nativeItems.push_back(bits);
		}
	}

	void Win32MenuItem::DestroyNative(NativeItemBits* bits)
	{
		// Erase the reference to this item in our registry
		vector<NativeItemBits*>::iterator i = nativeItems.begin();
		while (i != nativeItems.end())
		{
			if (*i == bits)
				i = nativeItems.erase(i);
			else
				i++;
		}

		if (bits->submenu)
		{
			this->oldSubmenu->DestroyNative(bits->submenu);
		}

		delete bits;
	}

	void Win32MenuItem::DestroyNative(HMENU nativeParent, int position)
	{
		UINT nativeId = GetMenuItemID(nativeParent, position);
		HMENU submenu = GetSubMenu(nativeParent, position);

		vector<NativeItemBits*>::iterator i = nativeItems.begin();
		while (i != nativeItems.end())
		{
			NativeItemBits* b = *i++;

			if ((b->submenu && submenu) ||
				(!b->submenu && b->id == nativeId))
			{
				this->DestroyNative(b);
				return;
			}
		}
	}

	/*static*/
	int Win32MenuItem::GetNativeMenuItemPosition(NativeItemBits* bits)
	{
		int count = GetMenuItemCount(bits->parentMenu);
		for (int i = 0; i < count; i++)
		{

			if ((bits->submenu && GetSubMenu(bits->parentMenu, i) == bits->submenu) ||
				(bits->id == GetMenuItemID(bits->parentMenu, i)))
				return i;
		}

		throw ValueException::FromString("Could not find native item index in native menu.");
	}

	/*static*/
	bool Win32MenuItem::HandleClickEvent(HMENU nativeMenu, UINT position)
	{
		MENUITEMINFO itemInfo;
		ZeroMemory(&itemInfo, sizeof(MENUITEMINFO));
		itemInfo.cbSize = sizeof(MENUITEMINFO);
		itemInfo.fMask = MIIM_DATA;
		GetMenuItemInfo(nativeMenu, position, TRUE, &itemInfo);

		if (itemInfo.dwItemData)
		{
			MenuItem* item = (MenuItem*) itemInfo.dwItemData;
			item->HandleClickEvent(NULL);
			return true;
		}

		return false;
	}
}

<|endoftext|>


<commit_before>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/** @file
 * Tests for the SixenseDevice and SixenseManager classes.
 */

#include <memory>
#include <string>
#include <boost/thread.hpp>
#include <boost/chrono.hpp>
#include <gtest/gtest.h>
#include "SurgSim/Devices/Sixense/SixenseDevice.h"
#include "SurgSim/Devices/Sixense/SixenseManager.h"
#include "SurgSim/DataStructures/DataGroup.h"
#include "SurgSim/Input/InputConsumerInterface.h"
#include "SurgSim/Input/OutputProducerInterface.h"
#include "SurgSim/Math/RigidTransform.h"
#include "SurgSim/Math/Matrix.h"

using SurgSim::Device::SixenseDevice;
using SurgSim::Device::SixenseManager;
using SurgSim::DataStructures::DataGroup;
using SurgSim::Input::InputConsumerInterface;
using SurgSim::Input::OutputProducerInterface;
using SurgSim::Math::RigidTransform3d;
using SurgSim::Math::Matrix44d;

struct TestListener : public InputConsumerInterface, public OutputProducerInterface
{
public:
	TestListener() :
		m_numTimesReceivedInput(0),
		m_numTimesRequestedOutput(0)
	{
	}

	virtual void handleInput(const std::string& device, const DataGroup& inputData);
	virtual bool requestOutput(const std::string& device, DataGroup* outputData);

	int m_numTimesReceivedInput;
	int m_numTimesRequestedOutput;
	DataGroup m_lastReceivedInput;
};

void TestListener::handleInput(const std::string& device, const DataGroup& inputData)
{
	++m_numTimesReceivedInput;
	m_lastReceivedInput = inputData;
}

bool TestListener::requestOutput(const std::string& device, DataGroup* outputData)
{
	++m_numTimesRequestedOutput;
	return false;
}

TEST(SixenseDeviceTest, CanConstructManager)
{
	ASSERT_NO_THROW({SixenseManager manager;});
}

TEST(SixenseDeviceTest, CreateAndReleaseDevice)
{
	SixenseManager manager;
	std::shared_ptr<SixenseDevice> device = manager.createDevice("TestSixense");
	ASSERT_TRUE(device != nullptr) << "Initialization failed.  Is a Sixense/Hydra device plugged in?";
	manager.releaseDevice(device);
}

TEST(SixenseDeviceTest, DestroyManagerWithRunningDevice)
{
	SixenseManager manager;
	std::shared_ptr<SixenseDevice> device = manager.createDevice("TestSixense");
	ASSERT_TRUE(device != nullptr) << "Initialization failed.  Is a Sixense/Hydra device plugged in?";

	// NB: device NOT released here!
}

TEST(SixenseDeviceTest, Name)
{
	SixenseManager manager;
	std::shared_ptr<SixenseDevice> device = manager.createDevice("TestSixense");
	ASSERT_TRUE(device != nullptr) << "Initialization failed.  Is a Sixense/Hydra device plugged in?";
	EXPECT_EQ("TestSixense", device->getName());
}

TEST(SixenseDeviceTest, CreateDeviceTwice)
{
	SixenseManager manager;
	{
		std::shared_ptr<SixenseDevice> device = manager.createDevice("TestSixense");
		ASSERT_TRUE(device != nullptr) << "Initialization failed.  Is a Sixense/Hydra device plugged in?";
		manager.releaseDevice(device);
	}
	{
		std::shared_ptr<SixenseDevice> device = manager.createDevice("TestSixense");
		ASSERT_TRUE(device != nullptr) << "Initialization failed.  Is a Sixense/Hydra device plugged in?";
		manager.releaseDevice(device);
	}
}

TEST(SixenseDeviceTest, CreateTwoDevices)
{
	SixenseManager manager;

	std::shared_ptr<SixenseDevice> device1 = manager.createDevice("Sixense1");
	ASSERT_TRUE(device1 != nullptr) << "Initialization failed.  Is a Sixense/Hydra device plugged in?";

	std::shared_ptr<SixenseDevice> device2 = manager.createDevice("Sixense2");
	ASSERT_TRUE(device2 != nullptr) << "Initialization failed for second controller." <<
		"  Is only one controller plugged in?";

	std::shared_ptr<SixenseDevice> device3 = manager.createDevice("Sixense3");
	if (! device3)
	{
		std::cerr << "[Warning: third Sixense/Hydra controller not actually created; is it plugged in?]" << std::endl;
	}
}

TEST(SixenseDeviceTest, InputConsumer)
{
	SixenseManager manager;
	std::shared_ptr<SixenseDevice> device = manager.createDevice("TestSixense");
	ASSERT_TRUE(device != nullptr) << "Initialization failed.  Is a Sixense/Hydra device plugged in?";

	std::shared_ptr<TestListener> consumer = std::make_shared<TestListener>();
	EXPECT_EQ(0, consumer->m_numTimesReceivedInput);

	EXPECT_FALSE(device->removeInputConsumer(consumer));
	EXPECT_EQ(0, consumer->m_numTimesReceivedInput);

	EXPECT_TRUE(device->addInputConsumer(consumer));

	// Adding the same input consumer again should fail.
	EXPECT_FALSE(device->addInputConsumer(consumer));

	// Sleep for a second, to see how many times the consumer is invoked.
	// (A Sixense device updates internally at 60Hz, but our code currently runs at 120Hz to reduce latency.)
	boost::this_thread::sleep_until(boost::chrono::steady_clock::now() + boost::chrono::milliseconds(1000));

	EXPECT_TRUE(device->removeInputConsumer(consumer));

	// Removing the same input consumer again should fail.
	EXPECT_FALSE(device->removeInputConsumer(consumer));

	// Check the number of invocations.
	EXPECT_GE(consumer->m_numTimesReceivedInput, 100);
	EXPECT_LE(consumer->m_numTimesReceivedInput, 140);

	EXPECT_TRUE(consumer->m_lastReceivedInput.poses().hasCurrentData("pose"));
	EXPECT_TRUE(consumer->m_lastReceivedInput.scalars().hasCurrentData("trigger"));
	EXPECT_TRUE(consumer->m_lastReceivedInput.scalars().hasCurrentData("joystickX"));
	EXPECT_TRUE(consumer->m_lastReceivedInput.scalars().hasCurrentData("joystickY"));
	EXPECT_TRUE(consumer->m_lastReceivedInput.booleans().hasCurrentData("buttonTrigger"));
	EXPECT_TRUE(consumer->m_lastReceivedInput.booleans().hasCurrentData("buttonBumper"));
	EXPECT_TRUE(consumer->m_lastReceivedInput.booleans().hasCurrentData("button1"));
	EXPECT_TRUE(consumer->m_lastReceivedInput.booleans().hasCurrentData("button2"));
	EXPECT_TRUE(consumer->m_lastReceivedInput.booleans().hasCurrentData("button3"));
	EXPECT_TRUE(consumer->m_lastReceivedInput.booleans().hasCurrentData("button4"));
	EXPECT_TRUE(consumer->m_lastReceivedInput.booleans().hasCurrentData("buttonStart"));
	EXPECT_TRUE(consumer->m_lastReceivedInput.booleans().hasCurrentData("buttonJoystick"));
}

TEST(SixenseDeviceTest, OutputProducer)
{
	SixenseManager manager;
	std::shared_ptr<SixenseDevice> device = manager.createDevice("TestSixense");
	ASSERT_TRUE(device != nullptr) << "Initialization failed.  Is a Sixense/Hydra device plugged in?";

	std::shared_ptr<TestListener> producer = std::make_shared<TestListener>();
	EXPECT_EQ(0, producer->m_numTimesRequestedOutput);

	EXPECT_FALSE(device->removeOutputProducer(producer));
	EXPECT_EQ(0, producer->m_numTimesRequestedOutput);

	EXPECT_TRUE(device->setOutputProducer(producer));

	// Sleep for a second, to see how many times the producer is invoked.
	// (A Sixense device is does not request any output.)
	boost::this_thread::sleep_until(boost::chrono::steady_clock::now() + boost::chrono::milliseconds(1000));

	EXPECT_TRUE(device->removeOutputProducer(producer));

	// Removing the same input producer again should fail.
	EXPECT_FALSE(device->removeOutputProducer(producer));

	// Check the number of invocations.
	EXPECT_EQ(0, producer->m_numTimesRequestedOutput);
}
<commit_msg>Fix SixenseDeviceTest file comment.<commit_after>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/// \file
/// Tests for the SixenseDevice and SixenseManager classes.

#include <memory>
#include <string>
#include <boost/thread.hpp>
#include <boost/chrono.hpp>
#include <gtest/gtest.h>
#include "SurgSim/Devices/Sixense/SixenseDevice.h"
#include "SurgSim/Devices/Sixense/SixenseManager.h"
#include "SurgSim/DataStructures/DataGroup.h"
#include "SurgSim/Input/InputConsumerInterface.h"
#include "SurgSim/Input/OutputProducerInterface.h"
#include "SurgSim/Math/RigidTransform.h"
#include "SurgSim/Math/Matrix.h"

using SurgSim::Device::SixenseDevice;
using SurgSim::Device::SixenseManager;
using SurgSim::DataStructures::DataGroup;
using SurgSim::Input::InputConsumerInterface;
using SurgSim::Input::OutputProducerInterface;
using SurgSim::Math::RigidTransform3d;
using SurgSim::Math::Matrix44d;

struct TestListener : public InputConsumerInterface, public OutputProducerInterface
{
public:
	TestListener() :
		m_numTimesReceivedInput(0),
		m_numTimesRequestedOutput(0)
	{
	}

	virtual void handleInput(const std::string& device, const DataGroup& inputData);
	virtual bool requestOutput(const std::string& device, DataGroup* outputData);

	int m_numTimesReceivedInput;
	int m_numTimesRequestedOutput;
	DataGroup m_lastReceivedInput;
};

void TestListener::handleInput(const std::string& device, const DataGroup& inputData)
{
	++m_numTimesReceivedInput;
	m_lastReceivedInput = inputData;
}

bool TestListener::requestOutput(const std::string& device, DataGroup* outputData)
{
	++m_numTimesRequestedOutput;
	return false;
}

TEST(SixenseDeviceTest, CanConstructManager)
{
	ASSERT_NO_THROW({SixenseManager manager;});
}

TEST(SixenseDeviceTest, CreateAndReleaseDevice)
{
	SixenseManager manager;
	std::shared_ptr<SixenseDevice> device = manager.createDevice("TestSixense");
	ASSERT_TRUE(device != nullptr) << "Initialization failed.  Is a Sixense/Hydra device plugged in?";
	manager.releaseDevice(device);
}

TEST(SixenseDeviceTest, DestroyManagerWithRunningDevice)
{
	SixenseManager manager;
	std::shared_ptr<SixenseDevice> device = manager.createDevice("TestSixense");
	ASSERT_TRUE(device != nullptr) << "Initialization failed.  Is a Sixense/Hydra device plugged in?";

	// NB: device NOT released here!
}

TEST(SixenseDeviceTest, Name)
{
	SixenseManager manager;
	std::shared_ptr<SixenseDevice> device = manager.createDevice("TestSixense");
	ASSERT_TRUE(device != nullptr) << "Initialization failed.  Is a Sixense/Hydra device plugged in?";
	EXPECT_EQ("TestSixense", device->getName());
}

TEST(SixenseDeviceTest, CreateDeviceTwice)
{
	SixenseManager manager;
	{
		std::shared_ptr<SixenseDevice> device = manager.createDevice("TestSixense");
		ASSERT_TRUE(device != nullptr) << "Initialization failed.  Is a Sixense/Hydra device plugged in?";
		manager.releaseDevice(device);
	}
	{
		std::shared_ptr<SixenseDevice> device = manager.createDevice("TestSixense");
		ASSERT_TRUE(device != nullptr) << "Initialization failed.  Is a Sixense/Hydra device plugged in?";
		manager.releaseDevice(device);
	}
}

TEST(SixenseDeviceTest, CreateTwoDevices)
{
	SixenseManager manager;

	std::shared_ptr<SixenseDevice> device1 = manager.createDevice("Sixense1");
	ASSERT_TRUE(device1 != nullptr) << "Initialization failed.  Is a Sixense/Hydra device plugged in?";

	std::shared_ptr<SixenseDevice> device2 = manager.createDevice("Sixense2");
	ASSERT_TRUE(device2 != nullptr) << "Initialization failed for second controller." <<
		"  Is only one controller plugged in?";

	std::shared_ptr<SixenseDevice> device3 = manager.createDevice("Sixense3");
	if (! device3)
	{
		std::cerr << "[Warning: third Sixense/Hydra controller not actually created; is it plugged in?]" << std::endl;
	}
}

TEST(SixenseDeviceTest, InputConsumer)
{
	SixenseManager manager;
	std::shared_ptr<SixenseDevice> device = manager.createDevice("TestSixense");
	ASSERT_TRUE(device != nullptr) << "Initialization failed.  Is a Sixense/Hydra device plugged in?";

	std::shared_ptr<TestListener> consumer = std::make_shared<TestListener>();
	EXPECT_EQ(0, consumer->m_numTimesReceivedInput);

	EXPECT_FALSE(device->removeInputConsumer(consumer));
	EXPECT_EQ(0, consumer->m_numTimesReceivedInput);

	EXPECT_TRUE(device->addInputConsumer(consumer));

	// Adding the same input consumer again should fail.
	EXPECT_FALSE(device->addInputConsumer(consumer));

	// Sleep for a second, to see how many times the consumer is invoked.
	// (A Sixense device updates internally at 60Hz, but our code currently runs at 120Hz to reduce latency.)
	boost::this_thread::sleep_until(boost::chrono::steady_clock::now() + boost::chrono::milliseconds(1000));

	EXPECT_TRUE(device->removeInputConsumer(consumer));

	// Removing the same input consumer again should fail.
	EXPECT_FALSE(device->removeInputConsumer(consumer));

	// Check the number of invocations.
	EXPECT_GE(consumer->m_numTimesReceivedInput, 100);
	EXPECT_LE(consumer->m_numTimesReceivedInput, 140);

	EXPECT_TRUE(consumer->m_lastReceivedInput.poses().hasCurrentData("pose"));
	EXPECT_TRUE(consumer->m_lastReceivedInput.scalars().hasCurrentData("trigger"));
	EXPECT_TRUE(consumer->m_lastReceivedInput.scalars().hasCurrentData("joystickX"));
	EXPECT_TRUE(consumer->m_lastReceivedInput.scalars().hasCurrentData("joystickY"));
	EXPECT_TRUE(consumer->m_lastReceivedInput.booleans().hasCurrentData("buttonTrigger"));
	EXPECT_TRUE(consumer->m_lastReceivedInput.booleans().hasCurrentData("buttonBumper"));
	EXPECT_TRUE(consumer->m_lastReceivedInput.booleans().hasCurrentData("button1"));
	EXPECT_TRUE(consumer->m_lastReceivedInput.booleans().hasCurrentData("button2"));
	EXPECT_TRUE(consumer->m_lastReceivedInput.booleans().hasCurrentData("button3"));
	EXPECT_TRUE(consumer->m_lastReceivedInput.booleans().hasCurrentData("button4"));
	EXPECT_TRUE(consumer->m_lastReceivedInput.booleans().hasCurrentData("buttonStart"));
	EXPECT_TRUE(consumer->m_lastReceivedInput.booleans().hasCurrentData("buttonJoystick"));
}

TEST(SixenseDeviceTest, OutputProducer)
{
	SixenseManager manager;
	std::shared_ptr<SixenseDevice> device = manager.createDevice("TestSixense");
	ASSERT_TRUE(device != nullptr) << "Initialization failed.  Is a Sixense/Hydra device plugged in?";

	std::shared_ptr<TestListener> producer = std::make_shared<TestListener>();
	EXPECT_EQ(0, producer->m_numTimesRequestedOutput);

	EXPECT_FALSE(device->removeOutputProducer(producer));
	EXPECT_EQ(0, producer->m_numTimesRequestedOutput);

	EXPECT_TRUE(device->setOutputProducer(producer));

	// Sleep for a second, to see how many times the producer is invoked.
	// (A Sixense device is does not request any output.)
	boost::this_thread::sleep_until(boost::chrono::steady_clock::now() + boost::chrono::milliseconds(1000));

	EXPECT_TRUE(device->removeOutputProducer(producer));

	// Removing the same input producer again should fail.
	EXPECT_FALSE(device->removeOutputProducer(producer));

	// Check the number of invocations.
	EXPECT_EQ(0, producer->m_numTimesRequestedOutput);
}
<|endoftext|>


<commit_before>/*!
  \copyright (c) RDO-Team, 2011
  \file      calc_array.cpp
  \author
  \date      02.05.2011
  \brief        -
  \indent    4T
*/

// ---------------------------------------------------------------------------- PCH
#include "simulator/runtime/pch.h"
// ----------------------------------------------------------------------- INCLUDES
// ----------------------------------------------------------------------- SYNOPSIS
#include "simulator/runtime/calc/calc_array.h"
#include "simulator/runtime/rdo_array.h"
// --------------------------------------------------------------------------------

OPEN_RDO_RUNTIME_NAMESPACE

// --------------------------------------------------------------------------------
// -------------------- RDOCalcArraySize
// --------------------------------------------------------------------------------
RDOCalcArraySize::RDOCalcArraySize(CREF(LPRDOCalc) pCalc)
	: m_pCalc(pCalc)
{}

REF(RDOValue) RDOCalcArraySize::doCalc(CREF(LPRDORuntime) pRuntime)
{
	REF(RDOValue) value = m_pCalc->calcValue(pRuntime);
	LPRDOArrayType pArrayType = value.type().object_dynamic_cast<RDOArrayType>();
	ASSERT(pArrayType);
	CREF(LPRDOArrayValue) pArrayValue = value.getPointer<RDOArrayValue>();
	ASSERT(pArrayValue);
	m_value = RDOValue(pArrayValue->size());
	return m_value;
}

// --------------------------------------------------------------------------------
// -------------------- RDOCalcArrayItem
// --------------------------------------------------------------------------------
RDOCalcArrayItem::RDOCalcArrayItem(CREF(LPRDOCalc) pArray, CREF(LPRDOCalc) pArrayInd)
	: m_pArray   (pArray   )
	, m_pArrayInd(pArrayInd)
{}

REF(RDOValue) RDOCalcArrayItem::doCalc(CREF(LPRDORuntime) pRuntime)
{
	REF(RDOValue) value = m_pArray->calcValue(pRuntime);

	CREF(LPRDOArrayValue) pArrayValue = value.getPointerSafety<RDOArrayType>();
	ASSERT(pArrayValue);

	m_value = pArrayValue->getItem(m_pArrayInd->calcValue(pRuntime),this->srcInfo(),pRuntime);
	return m_value;
}

// --------------------------------------------------------------------------------
// -------------------- RDOCalcSetArrayItem
// --------------------------------------------------------------------------------
RDOCalcSetArrayItem::RDOCalcSetArrayItem(CREF(LPRDOCalc) pArray, CREF(LPRDOCalc) pArrayInd, CREF(LPRDOCalc) pSetItem)
	: m_pArray   (pArray   )
	, m_pArrayInd(pArrayInd)
	, m_pSetItem (pSetItem )
{}

REF(RDOValue) RDOCalcSetArrayItem::doCalc(CREF(LPRDORuntime) pRuntime)
{
	m_value = m_pArray->calcValue(pRuntime);

	CREF(LPRDOArrayValue) pArrayValue = m_value.getPointerSafety<RDOArrayType>();
	ASSERT(pArrayValue);
	pArrayValue->setItem(m_pArrayInd->calcValue(pRuntime), m_pSetItem->calcValue(pRuntime),this->srcInfo(),pRuntime);

	return m_value;
}

CLOSE_RDO_RUNTIME_NAMESPACE
<commit_msg> - srcInfo калка для работы с элементами массива настроено на индекс элемента.Форматирование.<commit_after>/*!
  \copyright (c) RDO-Team, 2011
  \file      calc_array.cpp
  \author
  \date      02.05.2011
  \brief        -
  \indent    4T
*/

// ---------------------------------------------------------------------------- PCH
#include "simulator/runtime/pch.h"
// ----------------------------------------------------------------------- INCLUDES
// ----------------------------------------------------------------------- SYNOPSIS
#include "simulator/runtime/calc/calc_array.h"
#include "simulator/runtime/rdo_array.h"
// --------------------------------------------------------------------------------

OPEN_RDO_RUNTIME_NAMESPACE

// --------------------------------------------------------------------------------
// -------------------- RDOCalcArraySize
// --------------------------------------------------------------------------------
RDOCalcArraySize::RDOCalcArraySize(CREF(LPRDOCalc) pCalc)
	: m_pCalc(pCalc)
{}

REF(RDOValue) RDOCalcArraySize::doCalc(CREF(LPRDORuntime) pRuntime)
{
	REF(RDOValue) value = m_pCalc->calcValue(pRuntime);
	LPRDOArrayType pArrayType = value.type().object_dynamic_cast<RDOArrayType>();
	ASSERT(pArrayType);
	CREF(LPRDOArrayValue) pArrayValue = value.getPointer<RDOArrayValue>();
	ASSERT(pArrayValue);
	m_value = RDOValue(pArrayValue->size());
	return m_value;
}

// --------------------------------------------------------------------------------
// -------------------- RDOCalcArrayItem
// --------------------------------------------------------------------------------
RDOCalcArrayItem::RDOCalcArrayItem(CREF(LPRDOCalc) pArray, CREF(LPRDOCalc) pArrayInd)
	: m_pArray   (pArray   )
	, m_pArrayInd(pArrayInd)
{}

REF(RDOValue) RDOCalcArrayItem::doCalc(CREF(LPRDORuntime) pRuntime)
{
	setSrcInfo(m_pArrayInd->srcInfo());
	REF(RDOValue) value = m_pArray->calcValue(pRuntime);

	CREF(LPRDOArrayValue) pArrayValue = value.getPointerSafety<RDOArrayType>();
	ASSERT(pArrayValue);

	m_value = pArrayValue->getItem(m_pArrayInd->calcValue(pRuntime), srcInfo(), pRuntime);
	return m_value;
}

// --------------------------------------------------------------------------------
// -------------------- RDOCalcSetArrayItem
// --------------------------------------------------------------------------------
RDOCalcSetArrayItem::RDOCalcSetArrayItem(CREF(LPRDOCalc) pArray, CREF(LPRDOCalc) pArrayInd, CREF(LPRDOCalc) pSetItem)
	: m_pArray   (pArray   )
	, m_pArrayInd(pArrayInd)
	, m_pSetItem (pSetItem )
{}

REF(RDOValue) RDOCalcSetArrayItem::doCalc(CREF(LPRDORuntime) pRuntime)
{
	m_value = m_pArray->calcValue(pRuntime);
	setSrcInfo(m_pArrayInd->srcInfo());

	CREF(LPRDOArrayValue) pArrayValue = m_value.getPointerSafety<RDOArrayType>();
	ASSERT(pArrayValue);
	pArrayValue->setItem(m_pArrayInd->calcValue(pRuntime), m_pSetItem->calcValue(pRuntime), srcInfo(), pRuntime);

	return m_value;
}

CLOSE_RDO_RUNTIME_NAMESPACE
<|endoftext|>


<commit_before>/*
 * This file is part of TelepathyLoggerQt4
 *
 * Copyright (C) 2011 Collabora Ltd. <http://www.collabora.co.uk/>
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <TelepathyLoggerQt4/Models/LoggerConversationModel>

#include "TelepathyLoggerQt4/Models/_gen/logger-conversation-model.moc.hpp"

#include <QtCore/QDebug>
#include <TelepathyQt4/Account>
#include <TelepathyQt4/Contact>
#include <TelepathyQt4/ContactManager>
#include <TelepathyQt4/Connection>
#include <TelepathyLoggerQt4/Entity>
#include <TelepathyLoggerQt4/TextEvent>
#include <TelepathyLoggerQt4/CallEvent>
#include <TelepathyLoggerQt4/LogManager>
#include <TelepathyLoggerQt4/PendingDates>
#include <TelepathyLoggerQt4/PendingEvents>
#include <TelepathyQt4Yell/Models/TextEventItem>
#include <TelepathyQt4Yell/Models/CallEventItem>

#define MAX_ITEMS 1000

using namespace Tpl;

struct TELEPATHY_LOGGER_QT4_MODELS_NO_EXPORT LoggerConversationModel::Private
{
    Private(const Tp::AccountPtr &account, const Tp::ContactPtr &contact);
    void setup() const;
    void fetchDate(const QDate &date) const;

    Tp::AccountPtr mAccount;
    Tp::ContactPtr mContact;
    Tpl::EntityPtr mEntity;
    Tpl::QDateList mDates;
    bool mBackFetching;
};

LoggerConversationModel::Private::Private(const Tp::AccountPtr &account, const Tp::ContactPtr &contact)
    : mAccount(account),
      mContact(contact),
      mBackFetching(false)
{
    mEntity = Tpl::Entity::create(mContact, Tpl::EntityTypeContact);
    if (mEntity.isNull()) {
        return;
    }
}

LoggerConversationModel::LoggerConversationModel(const Tp::AccountPtr &account, const Tp::ContactPtr &contact, QObject *parent)
    : Tpy::AbstractConversationModel(parent),
      mPriv(new Private(account, contact))
{
    qDebug() << "LoggerConversationModel::LoggerConversationModel";
    setup();
}

LoggerConversationModel::~LoggerConversationModel()
{
    delete mPriv;
}

void LoggerConversationModel::setup() const
{
    if (mPriv->mAccount.isNull()) {
        return;
    }

    if (mPriv->mContact.isNull()) {
        return;
    }

    if (mPriv->mEntity.isNull()) {
        return;
    }

    Tpl::LogManagerPtr manager = Tpl::LogManager::instance();
    if (manager.isNull()) {
        return;
    }

    Tpl::PendingDates *pendingDates = manager->queryDates(mPriv->mAccount, mPriv->mEntity, Tpl::EventTypeMaskAny);
    if (!pendingDates) {
        return;
    }
    connect(pendingDates,
            SIGNAL(finished(Tpl::PendingOperation*)),
            SLOT(onPendingDatesFinished(Tpl::PendingOperation*)));
}

void LoggerConversationModel::onPendingDatesFinished(Tpl::PendingOperation *op)
{
    Tpl::PendingDates *pendingDates = static_cast<Tpl::PendingDates*> (op);
    if (!pendingDates || pendingDates->isError()) {
        return;
    }

    mPriv->mDates = pendingDates->dates();

    Q_EMIT backFetchable();
}

bool LoggerConversationModel::canFetchMoreBack() const
{
    qDebug() << "LoggerConversationModel::canFetchMoreBack";
    return (mPriv->mDates.size() > 0);
}

void LoggerConversationModel::fetchMoreBack()
{
    qDebug() << "LoggerConversationModel::fetchMoreBack";

    if (mPriv->mBackFetching) {
        qWarning() << "LoggerConversationModel::fetchMoreBack: already fetching";
        return;
    }

    if (mPriv->mDates.size() <= 0) {
        return;
    }

    QDate date = mPriv->mDates.last();
    mPriv->mDates.pop_back();
    fetchDate(date);
}

bool LoggerConversationModel::canFetchMore(const QModelIndex & index) const
{
    return false;
}

void LoggerConversationModel::fetchMore(const QModelIndex & index)
{
}

void LoggerConversationModel::fetchDate(const QDate &date) const
{
    if (mPriv->mBackFetching) {
        qWarning() << "LoggerConversationModel::fetchDate: already fetching";
        return;
    }

    if (mPriv->mAccount.isNull()) {
        return;
    }

    if (mPriv->mContact.isNull()) {
        return;
    }

    if (mPriv->mEntity.isNull()) {
        return;
    }

    Tpl::LogManagerPtr manager = Tpl::LogManager::instance();
    if (manager.isNull()) {
        return;
    }

    Tpl::PendingEvents *pendingEvents = manager->queryEvents(mPriv->mAccount, mPriv->mEntity, Tpl::EventTypeMaskAny, date);
    if (!pendingEvents) {
        return;
    }
    mPriv->mBackFetching = true;
    Q_EMIT backFetchingChanged();
    connect(pendingEvents, SIGNAL(finished(Tpl::PendingOperation*)), SLOT(onPendingEventsFinished(Tpl::PendingOperation*)));
}

void LoggerConversationModel::onPendingEventsFinished(Tpl::PendingOperation *op)
{
    qDebug() << "LoggerConversationModel::onPendingEventsFinished";

    Tpl::PendingEvents *pendingEvents = static_cast<Tpl::PendingEvents*> (op);
    if (!pendingEvents || pendingEvents->isError()) {
        mPriv->mBackFetching = false;
        Q_EMIT backFetchingChanged();
        return;
    }

    Tpl::EventPtrList eventList = pendingEvents->events();
    Tpl::EventPtr event;

    QList<const Tpy::EventItem *> items;

    beginInsertRows(QModelIndex(), 0, eventList.size() - 1);

    Q_FOREACH(event, eventList) {
        qDebug() << "LoggerConversationModel::onPendingEventsFinished: event added";
        Tpl::TextEventPtr textEvent = event.dynamicCast<Tpl::TextEvent>();
        Tpl::CallEventPtr callEvent = event.dynamicCast<Tpl::CallEvent>();

        Tp::ContactPtr sender;
        if (!event->sender().isNull()) {
            if (event->sender()->identifier() == mPriv->mContact->id()) {
                sender = mPriv->mContact;
            } else if (event->sender()->identifier() == mPriv->mContact->manager()->connection()->selfContact()->id()) {
                sender = mPriv->mContact->manager()->connection()->selfContact();
            }
            if (sender.isNull()) {
                qDebug() << "LoggerConversationModel::onPendingEventsFinished: unknown sender " << event->sender()->identifier();
            }
        }

        Tp::ContactPtr receiver;
        if (!event->receiver().isNull()) {
            if (event->receiver()->identifier() == mPriv->mContact->id()) {
                receiver = mPriv->mContact;
            } else if (event->receiver()->identifier() == mPriv->mContact->manager()->connection()->selfContact()->id()) {
                receiver = mPriv->mContact->manager()->connection()->selfContact();
            }
            if (receiver.isNull()) {
                qDebug() << "LoggerConversationModel::onPendingEventsFinished: unknown receiver " << event->receiver()->identifier();
            }
        }

        if (!textEvent.isNull()) {
            Tpy::TextEventItem::MessageOrigin messageOrigin;
            if (textEvent->sender()->identifier() == mPriv->mContact->id()) {
                messageOrigin = Tpy::TextEventItem::MessageOriginIncoming;
            } else {
                messageOrigin = Tpy::TextEventItem::MessageOriginOutgoing;
                //contact = mPriv->mContact->manager()->connection()->selfContact();
            }
            Tpy::TextEventItem *item = new Tpy::TextEventItem(
                sender, receiver, textEvent->timestamp(), textEvent->message(),
                messageOrigin, textEvent->messageType(), this);
            items.append(item);
        } else if (!callEvent.isNull()) {
            // convert from Tpl::CallEndReason to Tpy::CallStateChangeReason (very similar)
            Tpy::CallStateChangeReason stateChangeReason = Tpy::CallStateChangeReasonUnknown;
            Tpl::CallEndReason endReason = callEvent->endReason();
            if (endReason == Tpl::CallEndReasonNoAnswer) {
                stateChangeReason = Tpy::CallStateChangeReasonNoAnswer;
            } else if (endReason == Tpl::CallEndReasonUserRequested) {
                stateChangeReason = Tpy::CallStateChangeReasonUserRequested;
            } if (endReason == Tpl::CallEndReasonUnknown) {
                stateChangeReason = Tpy::CallStateChangeReasonUnknown;
            } else {
                // Unknown Tpl::CallEndReason enum
                Q_ASSERT(true);
            }

            Tp::ContactPtr endActor;
            if (!callEvent->endActor().isNull()) {
                if (callEvent->endActor()->identifier() == mPriv->mContact->id()) {
                    endActor = mPriv->mContact;
                } else if (callEvent->endActor()->identifier() == mPriv->mContact->manager()->connection()->selfContact()->id()) {
                    endActor = mPriv->mContact->manager()->connection()->selfContact();
                }
                if (receiver.isNull()) {
                    qDebug() << "LoggerConversationModel::onPendingEventsFinished: unknown endActor " << callEvent->endActor()->identifier();
                }
            }

            Tpy::CallEventItem *item = new Tpy::CallEventItem(
                sender, receiver, callEvent->timestamp(), callEvent->duration(),
                endActor, stateChangeReason, callEvent->detailedEndReason(), this);
            items.append(item);
        }
    }

    if (items.size() > 0) {
        this->insertItems(items);
    }

    endInsertRows();

    mPriv->mBackFetching = false;
    Q_EMIT backFetchingChanged();
    Q_EMIT backFetched(items.size());
}

bool LoggerConversationModel::backFetching() const
{
    return mPriv->mBackFetching;
}
<commit_msg>Models: message origin removed<commit_after>/*
 * This file is part of TelepathyLoggerQt4
 *
 * Copyright (C) 2011 Collabora Ltd. <http://www.collabora.co.uk/>
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <TelepathyLoggerQt4/Models/LoggerConversationModel>

#include "TelepathyLoggerQt4/Models/_gen/logger-conversation-model.moc.hpp"

#include <QtCore/QDebug>
#include <TelepathyQt4/Account>
#include <TelepathyQt4/Contact>
#include <TelepathyQt4/ContactManager>
#include <TelepathyQt4/Connection>
#include <TelepathyLoggerQt4/Entity>
#include <TelepathyLoggerQt4/TextEvent>
#include <TelepathyLoggerQt4/CallEvent>
#include <TelepathyLoggerQt4/LogManager>
#include <TelepathyLoggerQt4/PendingDates>
#include <TelepathyLoggerQt4/PendingEvents>
#include <TelepathyQt4Yell/Models/TextEventItem>
#include <TelepathyQt4Yell/Models/CallEventItem>

#define MAX_ITEMS 1000

using namespace Tpl;

struct TELEPATHY_LOGGER_QT4_MODELS_NO_EXPORT LoggerConversationModel::Private
{
    Private(const Tp::AccountPtr &account, const Tp::ContactPtr &contact);
    void setup() const;
    void fetchDate(const QDate &date) const;

    Tp::AccountPtr mAccount;
    Tp::ContactPtr mContact;
    Tpl::EntityPtr mEntity;
    Tpl::QDateList mDates;
    bool mBackFetching;
};

LoggerConversationModel::Private::Private(const Tp::AccountPtr &account, const Tp::ContactPtr &contact)
    : mAccount(account),
      mContact(contact),
      mBackFetching(false)
{
    mEntity = Tpl::Entity::create(mContact, Tpl::EntityTypeContact);
    if (mEntity.isNull()) {
        return;
    }
}

LoggerConversationModel::LoggerConversationModel(const Tp::AccountPtr &account, const Tp::ContactPtr &contact, QObject *parent)
    : Tpy::AbstractConversationModel(parent),
      mPriv(new Private(account, contact))
{
    qDebug() << "LoggerConversationModel::LoggerConversationModel";
    setup();
}

LoggerConversationModel::~LoggerConversationModel()
{
    delete mPriv;
}

void LoggerConversationModel::setup() const
{
    if (mPriv->mAccount.isNull()) {
        return;
    }

    if (mPriv->mContact.isNull()) {
        return;
    }

    if (mPriv->mEntity.isNull()) {
        return;
    }

    Tpl::LogManagerPtr manager = Tpl::LogManager::instance();
    if (manager.isNull()) {
        return;
    }

    Tpl::PendingDates *pendingDates = manager->queryDates(mPriv->mAccount, mPriv->mEntity, Tpl::EventTypeMaskAny);
    if (!pendingDates) {
        return;
    }
    connect(pendingDates,
            SIGNAL(finished(Tpl::PendingOperation*)),
            SLOT(onPendingDatesFinished(Tpl::PendingOperation*)));
}

void LoggerConversationModel::onPendingDatesFinished(Tpl::PendingOperation *op)
{
    Tpl::PendingDates *pendingDates = static_cast<Tpl::PendingDates*> (op);
    if (!pendingDates || pendingDates->isError()) {
        return;
    }

    mPriv->mDates = pendingDates->dates();

    Q_EMIT backFetchable();
}

bool LoggerConversationModel::canFetchMoreBack() const
{
    qDebug() << "LoggerConversationModel::canFetchMoreBack";
    return (mPriv->mDates.size() > 0);
}

void LoggerConversationModel::fetchMoreBack()
{
    qDebug() << "LoggerConversationModel::fetchMoreBack";

    if (mPriv->mBackFetching) {
        qWarning() << "LoggerConversationModel::fetchMoreBack: already fetching";
        return;
    }

    if (mPriv->mDates.size() <= 0) {
        return;
    }

    QDate date = mPriv->mDates.last();
    mPriv->mDates.pop_back();
    fetchDate(date);
}

bool LoggerConversationModel::canFetchMore(const QModelIndex & index) const
{
    return false;
}

void LoggerConversationModel::fetchMore(const QModelIndex & index)
{
}

void LoggerConversationModel::fetchDate(const QDate &date) const
{
    if (mPriv->mBackFetching) {
        qWarning() << "LoggerConversationModel::fetchDate: already fetching";
        return;
    }

    if (mPriv->mAccount.isNull()) {
        return;
    }

    if (mPriv->mContact.isNull()) {
        return;
    }

    if (mPriv->mEntity.isNull()) {
        return;
    }

    Tpl::LogManagerPtr manager = Tpl::LogManager::instance();
    if (manager.isNull()) {
        return;
    }

    Tpl::PendingEvents *pendingEvents = manager->queryEvents(mPriv->mAccount, mPriv->mEntity, Tpl::EventTypeMaskAny, date);
    if (!pendingEvents) {
        return;
    }
    mPriv->mBackFetching = true;
    Q_EMIT backFetchingChanged();
    connect(pendingEvents, SIGNAL(finished(Tpl::PendingOperation*)), SLOT(onPendingEventsFinished(Tpl::PendingOperation*)));
}

void LoggerConversationModel::onPendingEventsFinished(Tpl::PendingOperation *op)
{
    qDebug() << "LoggerConversationModel::onPendingEventsFinished";

    Tpl::PendingEvents *pendingEvents = static_cast<Tpl::PendingEvents*> (op);
    if (!pendingEvents || pendingEvents->isError()) {
        mPriv->mBackFetching = false;
        Q_EMIT backFetchingChanged();
        return;
    }

    Tpl::EventPtrList eventList = pendingEvents->events();
    Tpl::EventPtr event;

    QList<const Tpy::EventItem *> items;

    beginInsertRows(QModelIndex(), 0, eventList.size() - 1);

    Q_FOREACH(event, eventList) {
        qDebug() << "LoggerConversationModel::onPendingEventsFinished: event added";
        Tpl::TextEventPtr textEvent = event.dynamicCast<Tpl::TextEvent>();
        Tpl::CallEventPtr callEvent = event.dynamicCast<Tpl::CallEvent>();

        Tp::ContactPtr sender;
        if (!event->sender().isNull()) {
            if (event->sender()->identifier() == mPriv->mContact->id()) {
                sender = mPriv->mContact;
            } else if (event->sender()->identifier() == mPriv->mContact->manager()->connection()->selfContact()->id()) {
                sender = mPriv->mContact->manager()->connection()->selfContact();
            }
            if (sender.isNull()) {
                qDebug() << "LoggerConversationModel::onPendingEventsFinished: unknown sender " << event->sender()->identifier();
            }
        }

        Tp::ContactPtr receiver;
        if (!event->receiver().isNull()) {
            if (event->receiver()->identifier() == mPriv->mContact->id()) {
                receiver = mPriv->mContact;
            } else if (event->receiver()->identifier() == mPriv->mContact->manager()->connection()->selfContact()->id()) {
                receiver = mPriv->mContact->manager()->connection()->selfContact();
            }
            if (receiver.isNull()) {
                qDebug() << "LoggerConversationModel::onPendingEventsFinished: unknown receiver " << event->receiver()->identifier();
            }
        }

        if (!textEvent.isNull()) {
            Tpy::TextEventItem *item = new Tpy::TextEventItem(
                sender, receiver, textEvent->timestamp(), textEvent->message(),
                textEvent->messageType(), this);
            items.append(item);
        } else if (!callEvent.isNull()) {
            // convert from Tpl::CallEndReason to Tpy::CallStateChangeReason (very similar)
            Tpy::CallStateChangeReason stateChangeReason = Tpy::CallStateChangeReasonUnknown;
            Tpl::CallEndReason endReason = callEvent->endReason();
            if (endReason == Tpl::CallEndReasonNoAnswer) {
                stateChangeReason = Tpy::CallStateChangeReasonNoAnswer;
            } else if (endReason == Tpl::CallEndReasonUserRequested) {
                stateChangeReason = Tpy::CallStateChangeReasonUserRequested;
            } if (endReason == Tpl::CallEndReasonUnknown) {
                stateChangeReason = Tpy::CallStateChangeReasonUnknown;
            } else {
                // Unknown Tpl::CallEndReason enum
                Q_ASSERT(true);
            }

            Tp::ContactPtr endActor;
            if (!callEvent->endActor().isNull()) {
                if (callEvent->endActor()->identifier() == mPriv->mContact->id()) {
                    endActor = mPriv->mContact;
                } else if (callEvent->endActor()->identifier() == mPriv->mContact->manager()->connection()->selfContact()->id()) {
                    endActor = mPriv->mContact->manager()->connection()->selfContact();
                }
                if (receiver.isNull()) {
                    qDebug() << "LoggerConversationModel::onPendingEventsFinished: unknown endActor " << callEvent->endActor()->identifier();
                }
            }

            Tpy::CallEventItem *item = new Tpy::CallEventItem(
                sender, receiver, callEvent->timestamp(), callEvent->duration(),
                endActor, stateChangeReason, callEvent->detailedEndReason(), this);
            items.append(item);
        }
    }

    if (items.size() > 0) {
        this->insertItems(items);
    }

    endInsertRows();

    mPriv->mBackFetching = false;
    Q_EMIT backFetchingChanged();
    Q_EMIT backFetched(items.size());
}

bool LoggerConversationModel::backFetching() const
{
    return mPriv->mBackFetching;
}
<|endoftext|>


<commit_before>#include <silicium/config.hpp>
#include <silicium/bounded_int.hpp>
#include <silicium/variant.hpp>
#include <silicium/arithmetic/add.hpp>
#include <boost/test/unit_test.hpp>

namespace Si
{
	namespace m2
	{
		using std::size_t;
		using std::move;

		struct empty_t
		{
		};

		static BOOST_CONSTEXPR_OR_CONST empty_t empty;

		struct out_of_memory
		{
		};

		struct piece_of_memory
		{
			void *begin;

			piece_of_memory()
			    : begin(nullptr)
			{
			}

			explicit piece_of_memory(void *begin)
			    : begin(begin)
			{
			}
		};

		struct standard_allocator
		{
			variant<piece_of_memory, out_of_memory> allocate(size_t size)
			{
				void *memory = std::malloc(size);
				if (memory)
				{
					return piece_of_memory{memory};
				}
				return out_of_memory();
			}

			variant<piece_of_memory, out_of_memory> reallocate(piece_of_memory existing_allocation, size_t new_size)
			{
				void *new_allocation = std::realloc(existing_allocation.begin, new_size);
				if (new_allocation)
				{
					return piece_of_memory{new_allocation};
				}
				return out_of_memory();
			}

			void deallocate(piece_of_memory existing_allocation)
			{
				std::free(existing_allocation.begin);
			}
		};

		enum class resize_result
		{
			success,
			out_of_memory
		};

		template <class T, class Length, class Allocator>
		struct dynamic_storage : private Allocator
		{
			typedef T element_type;
			typedef Length length_type;

			dynamic_storage(empty_t, Allocator allocator = Allocator())
			    : Allocator(move(allocator))
			    , m_begin()
			    , m_length(length_type::template literal<0>())
			{
			}

			~dynamic_storage()
			{
				Allocator::deallocate(m_begin);
			}

			length_type length() const
			{
				return m_length;
			}

			resize_result resize(length_type new_length)
			{
				// TODO: handle overflow
				size_t const size_in_bytes = new_length.value() * sizeof(element_type);
				return visit<resize_result>(Allocator::reallocate(m_begin, size_in_bytes),
				                            [this, new_length](piece_of_memory const reallocated)
				                            {
					                            m_begin = reallocated;
					                            m_length = new_length;
					                            return resize_result::success;
					                        },
				                            [](out_of_memory)
				                            {
					                            return resize_result::out_of_memory;
					                        });
			}

			T &data() const
			{
				return *begin();
			}

			dynamic_storage(dynamic_storage &&other) BOOST_NOEXCEPT : Allocator(move(other)),
			                                                          m_begin(other.m_begin),
			                                                          m_length(other.m_length)
			{
			}

			dynamic_storage &operator=(dynamic_storage &&other) BOOST_NOEXCEPT
			{
				std::memcpy(this, &other, sizeof(other));
				return *this;
			}

			SILICIUM_DISABLE_COPY(dynamic_storage)

		private:
			piece_of_memory m_begin;
			length_type m_length;

			T *begin() const
			{
				return static_cast<T *>(m_begin.begin);
			}
		};

		enum class emplace_back_result
		{
			success,
			out_of_memory,
			full
		};

		template <class DynamicStorage>
		struct basic_vector
		{
			typedef typename DynamicStorage::element_type element_type;
			typedef typename DynamicStorage::length_type length_type;

			basic_vector(empty_t, DynamicStorage storage)
			    : m_storage(move(storage))
			    , m_used(length_type::template literal<0>())
			{
			}

			length_type capacity() const
			{
				return m_storage.length();
			}

			length_type length() const
			{
				return m_used;
			}

			template <class... Args>
			emplace_back_result emplace_back(Args &&... args)
			{
				overflow_or<typename length_type::value_type> const maybe_new_size =
				    checked_add<typename length_type::value_type>(capacity().value(), 1);
				if (maybe_new_size.is_overflow())
				{
					return emplace_back_result::full;
				}
				length_type const new_size = *length_type::create(*maybe_new_size.value());
				if (m_storage.length() < new_size)
				{
					// TODO: exponential growth
					switch (m_storage.resize(new_size))
					{
					case resize_result::success:
						break;

					case resize_result::out_of_memory:
						return emplace_back_result::out_of_memory;
					}
				}
				new (&m_storage.data()) element_type{std::forward<Args>(args)...};
				m_used = new_size;
				return emplace_back_result::success;
			}

			basic_vector(basic_vector &&other) BOOST_NOEXCEPT : m_storage(other.m_storage), m_used(other.m_used)
			{
			}

			basic_vector &operator=(basic_vector &&other) BOOST_NOEXCEPT
			{
				std::memcpy(this, &other, sizeof(other));
				return *this;
			}

			SILICIUM_DISABLE_COPY(basic_vector)

		private:
			DynamicStorage m_storage;
			length_type m_used;
		};

		template <class T, class Length>
		using vector = basic_vector<dynamic_storage<T, Length, standard_allocator>>;
	}
}

BOOST_AUTO_TEST_CASE(move2_vector_emplace_back)
{
	Si::m2::vector<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>> v{
	    Si::m2::empty,
	    Si::m2::dynamic_storage<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>, Si::m2::standard_allocator>{
	        Si::m2::empty}};
	BOOST_REQUIRE_EQUAL(0u, v.length().value());
	BOOST_REQUIRE_EQUAL(0u, v.capacity().value());
	BOOST_REQUIRE(Si::m2::emplace_back_result::success == v.emplace_back(12u));
	BOOST_REQUIRE_EQUAL(1u, v.length().value());
	BOOST_REQUIRE_EQUAL(1u, v.capacity().value());
	BOOST_REQUIRE(Si::m2::emplace_back_result::success == v.emplace_back(13u));
	BOOST_REQUIRE_EQUAL(2u, v.length().value());
	BOOST_REQUIRE_EQUAL(2u, v.capacity().value());
}
<commit_msg>working move operations<commit_after>#include <silicium/config.hpp>
#include <silicium/bounded_int.hpp>
#include <silicium/variant.hpp>
#include <silicium/arithmetic/add.hpp>
#include <boost/test/unit_test.hpp>

namespace Si
{
	namespace m2
	{
		using std::size_t;
		using std::move;

		struct empty_t
		{
		};

		static BOOST_CONSTEXPR_OR_CONST empty_t empty;

		struct out_of_memory
		{
		};

		struct piece_of_memory
		{
			void *begin;

			piece_of_memory()
			    : begin(nullptr)
			{
			}

			explicit piece_of_memory(void *begin)
			    : begin(begin)
			{
			}
		};

		struct standard_allocator
		{
			variant<piece_of_memory, out_of_memory> allocate(size_t size)
			{
				void *memory = std::malloc(size);
				if (memory)
				{
					return piece_of_memory{memory};
				}
				return out_of_memory();
			}

			variant<piece_of_memory, out_of_memory> reallocate(piece_of_memory existing_allocation, size_t new_size)
			{
				void *new_allocation = std::realloc(existing_allocation.begin, new_size);
				if (new_allocation)
				{
					return piece_of_memory{new_allocation};
				}
				return out_of_memory();
			}

			void deallocate(piece_of_memory existing_allocation)
			{
				std::free(existing_allocation.begin);
			}
		};

		enum class resize_result
		{
			success,
			out_of_memory
		};

		template <class T, class Length, class Allocator>
		struct dynamic_storage : private Allocator
		{
			typedef T element_type;
			typedef Length length_type;

			dynamic_storage(empty_t, Allocator allocator = Allocator())
			    : Allocator(move(allocator))
			    , m_begin()
			    , m_length(length_type::template literal<0>())
			{
			}

			~dynamic_storage()
			{
				Allocator::deallocate(m_begin);
			}

			length_type length() const
			{
				return m_length;
			}

			resize_result resize(length_type new_length)
			{
				// TODO: handle overflow
				size_t const size_in_bytes = new_length.value() * sizeof(element_type);
				return visit<resize_result>(Allocator::reallocate(m_begin, size_in_bytes),
				                            [this, new_length](piece_of_memory const reallocated)
				                            {
					                            m_begin = reallocated;
					                            m_length = new_length;
					                            return resize_result::success;
					                        },
				                            [](out_of_memory)
				                            {
					                            return resize_result::out_of_memory;
					                        });
			}

			T &data() const
			{
				return *begin();
			}

			dynamic_storage(dynamic_storage &&other) BOOST_NOEXCEPT : Allocator(move(other)),
			                                                          m_begin(other.m_begin),
			                                                          m_length(other.m_length)
			{
				other.m_begin = piece_of_memory();
				other.m_length = length_type::template literal<0>();
			}

			dynamic_storage &operator=(dynamic_storage &&other) BOOST_NOEXCEPT
			{
				using std::swap;
				swap(static_cast<Allocator &>(*this), static_cast<Allocator &>(other));
				swap(m_begin, other.m_begin);
				swap(m_length, other.m_length);
				return *this;
			}

			SILICIUM_DISABLE_COPY(dynamic_storage)

		private:
			piece_of_memory m_begin;
			length_type m_length;

			T *begin() const
			{
				return static_cast<T *>(m_begin.begin);
			}
		};

		enum class emplace_back_result
		{
			success,
			out_of_memory,
			full
		};

		template <class DynamicStorage>
		struct basic_vector
		{
			typedef typename DynamicStorage::element_type element_type;
			typedef typename DynamicStorage::length_type length_type;

			basic_vector(empty_t, DynamicStorage storage)
			    : m_storage(move(storage))
			    , m_used(length_type::template literal<0>())
			{
			}

			length_type capacity() const
			{
				return m_storage.length();
			}

			length_type length() const
			{
				return m_used;
			}

			template <class... Args>
			emplace_back_result emplace_back(Args &&... args)
			{
				overflow_or<typename length_type::value_type> const maybe_new_size =
				    checked_add<typename length_type::value_type>(capacity().value(), 1);
				if (maybe_new_size.is_overflow())
				{
					return emplace_back_result::full;
				}
				length_type const new_size = *length_type::create(*maybe_new_size.value());
				if (m_storage.length() < new_size)
				{
					// TODO: exponential growth
					switch (m_storage.resize(new_size))
					{
					case resize_result::success:
						break;

					case resize_result::out_of_memory:
						return emplace_back_result::out_of_memory;
					}
				}
				new (&m_storage.data()) element_type{std::forward<Args>(args)...};
				m_used = new_size;
				return emplace_back_result::success;
			}

			basic_vector(basic_vector &&other) BOOST_NOEXCEPT : m_storage(move(other.m_storage)), m_used(other.m_used)
			{
				// TODO: solve more generically
				other.m_used = length_type::template literal<0>();
			}

			basic_vector &operator=(basic_vector &&other) BOOST_NOEXCEPT
			{
				m_storage = move(other.m_storage);
				m_used = other.m_used;
				// TODO: solve more generically
				other.m_used = length_type::template literal<0>();
				return *this;
			}

			SILICIUM_DISABLE_COPY(basic_vector)

		private:
			DynamicStorage m_storage;
			length_type m_used;
		};

		template <class T, class Length>
		using vector = basic_vector<dynamic_storage<T, Length, standard_allocator>>;
	}
}

BOOST_AUTO_TEST_CASE(move2_vector_emplace_back)
{
	Si::m2::vector<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>> v{
	    Si::m2::empty,
	    Si::m2::dynamic_storage<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>, Si::m2::standard_allocator>{
	        Si::m2::empty}};
	BOOST_REQUIRE_EQUAL(0u, v.length().value());
	BOOST_REQUIRE_EQUAL(0u, v.capacity().value());
	BOOST_REQUIRE(Si::m2::emplace_back_result::success == v.emplace_back(12u));
	BOOST_REQUIRE_EQUAL(1u, v.length().value());
	BOOST_REQUIRE_EQUAL(1u, v.capacity().value());
	BOOST_REQUIRE(Si::m2::emplace_back_result::success == v.emplace_back(13u));
	BOOST_REQUIRE_EQUAL(2u, v.length().value());
	BOOST_REQUIRE_EQUAL(2u, v.capacity().value());
}

BOOST_AUTO_TEST_CASE(move2_vector_move_construct)
{
	Si::m2::vector<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>> v{
	    Si::m2::empty,
	    Si::m2::dynamic_storage<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>, Si::m2::standard_allocator>{
	        Si::m2::empty}};
	BOOST_REQUIRE(Si::m2::emplace_back_result::success == v.emplace_back(12u));
	Si::m2::vector<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>> w{std::move(v)};
	BOOST_REQUIRE_EQUAL(0u, v.length().value());
	BOOST_REQUIRE_EQUAL(1u, w.length().value());
}

BOOST_AUTO_TEST_CASE(move2_vector_move_assign)
{
	Si::m2::vector<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>> v{
	    Si::m2::empty,
	    Si::m2::dynamic_storage<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>, Si::m2::standard_allocator>{
	        Si::m2::empty}};
	BOOST_REQUIRE(Si::m2::emplace_back_result::success == v.emplace_back(12u));
	Si::m2::vector<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>> w{
	    Si::m2::empty,
	    Si::m2::dynamic_storage<std::uint64_t, Si::bounded_int<std::size_t, 0, 10>, Si::m2::standard_allocator>{
	        Si::m2::empty}};
	w = std::move(v);
	BOOST_REQUIRE_EQUAL(0u, v.length().value());
	BOOST_REQUIRE_EQUAL(1u, w.length().value());
}
<|endoftext|>