<commit_before>/*
 * Copyright (C) 2015 Incognito
 *
 * 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 "core.h"

#include <boost/intrusive_ptr.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/unordered_map.hpp>

#include <set>

PLUGIN_EXPORT bool PLUGIN_CALL OnPlayerConnect(int playerid)
{
	if (playerid >= 0 && playerid < MAX_PLAYERS)
	{
		boost::unordered_map<int, Player>::iterator p = core->getData()->players.find(playerid);
		if (p == core->getData()->players.end())
		{
			Player player(playerid);
			core->getData()->players.insert(std::make_pair(playerid, player));
		}
	}
	return true;
}

PLUGIN_EXPORT bool PLUGIN_CALL OnPlayerDisconnect(int playerid, int reason)
{
	core->getData()->players.erase(playerid);
	return true;
}

PLUGIN_EXPORT bool PLUGIN_CALL OnPlayerEnterCheckpoint(int playerid)
{
	boost::unordered_map<int, Player>::iterator p = core->getData()->players.find(playerid);
	if (p != core->getData()->players.end())
	{
		if (p->second.activeCheckpoint != p->second.visibleCheckpoint)
		{
			int checkpointid = p->second.visibleCheckpoint;
			p->second.activeCheckpoint = checkpointid;
			for (std::set<AMX*>::iterator a = core->getData()->interfaces.begin(); a != core->getData()->interfaces.end(); ++a)
			{
				int amxIndex = 0;
				if (!amx_FindPublic(*a, "OnPlayerEnterDynamicCP", &amxIndex))
				{
					amx_Push(*a, static_cast<cell>(checkpointid));
					amx_Push(*a, static_cast<cell>(playerid));
					amx_Exec(*a, NULL, amxIndex);
				}
			}
		}
	}
	return true;
}

PLUGIN_EXPORT bool PLUGIN_CALL OnPlayerLeaveCheckpoint(int playerid)
{
	boost::unordered_map<int, Player>::iterator p = core->getData()->players.find(playerid);
	if (p != core->getData()->players.end())
	{
		if (p->second.activeCheckpoint == p->second.visibleCheckpoint)
		{
			int checkpointid = p->second.activeCheckpoint;
			p->second.activeCheckpoint = 0;
			for (std::set<AMX*>::iterator a = core->getData()->interfaces.begin(); a != core->getData()->interfaces.end(); ++a)
			{
				int amxIndex = 0;
				if (!amx_FindPublic(*a, "OnPlayerLeaveDynamicCP", &amxIndex))
				{
					amx_Push(*a, static_cast<cell>(checkpointid));
					amx_Push(*a, static_cast<cell>(playerid));
					amx_Exec(*a, NULL, amxIndex);
				}
			}
		}
	}
	return true;
}

PLUGIN_EXPORT bool PLUGIN_CALL OnPlayerEnterRaceCheckpoint(int playerid)
{
	boost::unordered_map<int, Player>::iterator p = core->getData()->players.find(playerid);
	if (p != core->getData()->players.end())
	{
		if (p->second.activeRaceCheckpoint != p->second.visibleRaceCheckpoint)
		{
			int checkpointid = p->second.visibleRaceCheckpoint;
			p->second.activeRaceCheckpoint = checkpointid;
			for (std::set<AMX*>::iterator a = core->getData()->interfaces.begin(); a != core->getData()->interfaces.end(); ++a)
			{
				int amxIndex = 0;
				if (!amx_FindPublic(*a, "OnPlayerEnterDynamicRaceCP", &amxIndex))
				{
					amx_Push(*a, static_cast<cell>(checkpointid));
					amx_Push(*a, static_cast<cell>(playerid));
					amx_Exec(*a, NULL, amxIndex);
				}
			}
		}
	}
	return true;
}

PLUGIN_EXPORT bool PLUGIN_CALL OnPlayerLeaveRaceCheckpoint(int playerid)
{
	boost::unordered_map<int, Player>::iterator p = core->getData()->players.find(playerid);
	if (p != core->getData()->players.end())
	{
		if (p->second.activeRaceCheckpoint == p->second.visibleRaceCheckpoint)
		{
			int checkpointid = p->second.activeRaceCheckpoint;
			p->second.activeRaceCheckpoint = 0;
			for (std::set<AMX*>::iterator a = core->getData()->interfaces.begin(); a != core->getData()->interfaces.end(); ++a)
			{
				int amxIndex = 0;
				if (!amx_FindPublic(*a, "OnPlayerLeaveDynamicRaceCP", &amxIndex))
				{
					amx_Push(*a, static_cast<cell>(checkpointid));
					amx_Push(*a, static_cast<cell>(playerid));
					amx_Exec(*a, NULL, amxIndex);
				}
			}
		}
	}
	return true;
}

PLUGIN_EXPORT bool PLUGIN_CALL OnPlayerPickUpPickup(int playerid, int pickupid)
{
	for (boost::unordered_map<int, int>::iterator i = core->getData()->internalPickups.begin(); i != core->getData()->internalPickups.end(); ++i)
	{
		if (i->second == pickupid)
		{
			int pickupid = i->first;
			for (std::set<AMX*>::iterator a = core->getData()->interfaces.begin(); a != core->getData()->interfaces.end(); ++a)
			{
				int amxIndex = 0;
				if (!amx_FindPublic(*a, "OnPlayerPickUpDynamicPickup", &amxIndex))
				{
					amx_Push(*a, static_cast<cell>(pickupid));
					amx_Push(*a, static_cast<cell>(playerid));
					amx_Exec(*a, NULL, amxIndex);
				}
			}
			break;
		}
	}
	return true;
}

PLUGIN_EXPORT bool PLUGIN_CALL OnPlayerEditObject(int playerid, bool playerobject, int objectid, int response, float fX, float fY, float fZ, float fRotX, float fRotY, float fRotZ)
{
	if (playerobject)
	{
		boost::unordered_map<int, Player>::iterator p = core->getData()->players.find(playerid);
		if (p != core->getData()->players.end())
		{
			for (boost::unordered_map<int, int>::iterator i = p->second.internalObjects.begin(); i != p->second.internalObjects.end(); ++i)
			{
				if (i->second == objectid)
				{
					int objectid = i->first;
					for (std::set<AMX*>::iterator a = core->getData()->interfaces.begin(); a != core->getData()->interfaces.end(); ++a)
					{
						int amxIndex = 0;
						if (!amx_FindPublic(*a, "OnPlayerEditDynamicObject", &amxIndex))
						{
							amx_Push(*a, amx_ftoc(fRotZ));
							amx_Push(*a, amx_ftoc(fRotY));
							amx_Push(*a, amx_ftoc(fRotX));
							amx_Push(*a, amx_ftoc(fZ));
							amx_Push(*a, amx_ftoc(fY));
							amx_Push(*a, amx_ftoc(fX));
							amx_Push(*a, static_cast<cell>(response));
							amx_Push(*a, static_cast<cell>(objectid));
							amx_Push(*a, static_cast<cell>(playerid));
							amx_Exec(*a, NULL, amxIndex);
						}
					}
					break;
				}
			}
		}
	}
	return false;
}

PLUGIN_EXPORT bool PLUGIN_CALL OnPlayerSelectObject(int playerid, int type, int objectid, int modelid, float x, float y, float z)
{
	if (type == SELECT_OBJECT_PLAYER_OBJECT)
	{
		boost::unordered_map<int, Player>::iterator p = core->getData()->players.find(playerid);
		if (p != core->getData()->players.end())
		{
			for (boost::unordered_map<int, int>::iterator i = p->second.internalObjects.begin(); i != p->second.internalObjects.end(); ++i)
			{
				if (i->second == objectid)
				{
					int objectid = i->first;
					for (std::set<AMX*>::iterator a = core->getData()->interfaces.begin(); a != core->getData()->interfaces.end(); ++a)
					{
						int amxIndex = 0;
						if (!amx_FindPublic(*a, "OnPlayerSelectDynamicObject", &amxIndex))
						{
							amx_Push(*a, amx_ftoc(z));
							amx_Push(*a, amx_ftoc(y));
							amx_Push(*a, amx_ftoc(x));
							amx_Push(*a, static_cast<cell>(modelid));
							amx_Push(*a, static_cast<cell>(objectid));
							amx_Push(*a, static_cast<cell>(playerid));
							amx_Exec(*a, NULL, amxIndex);
						}
					}
					break;
				}
			}
		}
	}
	return false;
}

PLUGIN_EXPORT bool PLUGIN_CALL OnPlayerWeaponShot(int playerid, int weaponid, int hittype, int hitid, float x, float y, float z)
{
	if (hittype == BULLET_HIT_TYPE_PLAYER_OBJECT)
	{
		boost::unordered_map<int, Player>::iterator p = core->getData()->players.find(playerid);
		if (p != core->getData()->players.end())
		{
			for (boost::unordered_map<int, int>::iterator i = p->second.internalObjects.begin(); i != p->second.internalObjects.end(); ++i)
			{
				if (i->second == hitid)
				{
					int objectid = i->first;
					for (std::set<AMX*>::iterator a = core->getData()->interfaces.begin(); a != core->getData()->interfaces.end(); ++a)
					{
						int amxIndex = 0;
						if (!amx_FindPublic(*a, "OnPlayerShootDynamicObject", &amxIndex))
						{
							amx_Push(*a, amx_ftoc(z));
							amx_Push(*a, amx_ftoc(y));
							amx_Push(*a, amx_ftoc(x));
							amx_Push(*a, static_cast<cell>(objectid));
							amx_Push(*a, static_cast<cell>(weaponid));
							amx_Push(*a, static_cast<cell>(playerid));
							amx_Exec(*a, NULL, amxIndex);
						}
					}
					break;
				}
			}
		}
	}
	return true;
}
<commit_msg>Handle OnPlayerShootDynamicObject return values<commit_after>/*
 * Copyright (C) 2015 Incognito
 *
 * 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 "core.h"

#include <boost/intrusive_ptr.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/unordered_map.hpp>

#include <set>

PLUGIN_EXPORT bool PLUGIN_CALL OnPlayerConnect(int playerid)
{
	if (playerid >= 0 && playerid < MAX_PLAYERS)
	{
		boost::unordered_map<int, Player>::iterator p = core->getData()->players.find(playerid);
		if (p == core->getData()->players.end())
		{
			Player player(playerid);
			core->getData()->players.insert(std::make_pair(playerid, player));
		}
	}
	return true;
}

PLUGIN_EXPORT bool PLUGIN_CALL OnPlayerDisconnect(int playerid, int reason)
{
	core->getData()->players.erase(playerid);
	return true;
}

PLUGIN_EXPORT bool PLUGIN_CALL OnPlayerEnterCheckpoint(int playerid)
{
	boost::unordered_map<int, Player>::iterator p = core->getData()->players.find(playerid);
	if (p != core->getData()->players.end())
	{
		if (p->second.activeCheckpoint != p->second.visibleCheckpoint)
		{
			int checkpointid = p->second.visibleCheckpoint;
			p->second.activeCheckpoint = checkpointid;
			for (std::set<AMX*>::iterator a = core->getData()->interfaces.begin(); a != core->getData()->interfaces.end(); ++a)
			{
				int amxIndex = 0;
				if (!amx_FindPublic(*a, "OnPlayerEnterDynamicCP", &amxIndex))
				{
					amx_Push(*a, static_cast<cell>(checkpointid));
					amx_Push(*a, static_cast<cell>(playerid));
					amx_Exec(*a, NULL, amxIndex);
				}
			}
		}
	}
	return true;
}

PLUGIN_EXPORT bool PLUGIN_CALL OnPlayerLeaveCheckpoint(int playerid)
{
	boost::unordered_map<int, Player>::iterator p = core->getData()->players.find(playerid);
	if (p != core->getData()->players.end())
	{
		if (p->second.activeCheckpoint == p->second.visibleCheckpoint)
		{
			int checkpointid = p->second.activeCheckpoint;
			p->second.activeCheckpoint = 0;
			for (std::set<AMX*>::iterator a = core->getData()->interfaces.begin(); a != core->getData()->interfaces.end(); ++a)
			{
				int amxIndex = 0;
				if (!amx_FindPublic(*a, "OnPlayerLeaveDynamicCP", &amxIndex))
				{
					amx_Push(*a, static_cast<cell>(checkpointid));
					amx_Push(*a, static_cast<cell>(playerid));
					amx_Exec(*a, NULL, amxIndex);
				}
			}
		}
	}
	return true;
}

PLUGIN_EXPORT bool PLUGIN_CALL OnPlayerEnterRaceCheckpoint(int playerid)
{
	boost::unordered_map<int, Player>::iterator p = core->getData()->players.find(playerid);
	if (p != core->getData()->players.end())
	{
		if (p->second.activeRaceCheckpoint != p->second.visibleRaceCheckpoint)
		{
			int checkpointid = p->second.visibleRaceCheckpoint;
			p->second.activeRaceCheckpoint = checkpointid;
			for (std::set<AMX*>::iterator a = core->getData()->interfaces.begin(); a != core->getData()->interfaces.end(); ++a)
			{
				int amxIndex = 0;
				if (!amx_FindPublic(*a, "OnPlayerEnterDynamicRaceCP", &amxIndex))
				{
					amx_Push(*a, static_cast<cell>(checkpointid));
					amx_Push(*a, static_cast<cell>(playerid));
					amx_Exec(*a, NULL, amxIndex);
				}
			}
		}
	}
	return true;
}

PLUGIN_EXPORT bool PLUGIN_CALL OnPlayerLeaveRaceCheckpoint(int playerid)
{
	boost::unordered_map<int, Player>::iterator p = core->getData()->players.find(playerid);
	if (p != core->getData()->players.end())
	{
		if (p->second.activeRaceCheckpoint == p->second.visibleRaceCheckpoint)
		{
			int checkpointid = p->second.activeRaceCheckpoint;
			p->second.activeRaceCheckpoint = 0;
			for (std::set<AMX*>::iterator a = core->getData()->interfaces.begin(); a != core->getData()->interfaces.end(); ++a)
			{
				int amxIndex = 0;
				if (!amx_FindPublic(*a, "OnPlayerLeaveDynamicRaceCP", &amxIndex))
				{
					amx_Push(*a, static_cast<cell>(checkpointid));
					amx_Push(*a, static_cast<cell>(playerid));
					amx_Exec(*a, NULL, amxIndex);
				}
			}
		}
	}
	return true;
}

PLUGIN_EXPORT bool PLUGIN_CALL OnPlayerPickUpPickup(int playerid, int pickupid)
{
	for (boost::unordered_map<int, int>::iterator i = core->getData()->internalPickups.begin(); i != core->getData()->internalPickups.end(); ++i)
	{
		if (i->second == pickupid)
		{
			int pickupid = i->first;
			for (std::set<AMX*>::iterator a = core->getData()->interfaces.begin(); a != core->getData()->interfaces.end(); ++a)
			{
				int amxIndex = 0;
				if (!amx_FindPublic(*a, "OnPlayerPickUpDynamicPickup", &amxIndex))
				{
					amx_Push(*a, static_cast<cell>(pickupid));
					amx_Push(*a, static_cast<cell>(playerid));
					amx_Exec(*a, NULL, amxIndex);
				}
			}
			break;
		}
	}
	return true;
}

PLUGIN_EXPORT bool PLUGIN_CALL OnPlayerEditObject(int playerid, bool playerobject, int objectid, int response, float fX, float fY, float fZ, float fRotX, float fRotY, float fRotZ)
{
	if (playerobject)
	{
		boost::unordered_map<int, Player>::iterator p = core->getData()->players.find(playerid);
		if (p != core->getData()->players.end())
		{
			for (boost::unordered_map<int, int>::iterator i = p->second.internalObjects.begin(); i != p->second.internalObjects.end(); ++i)
			{
				if (i->second == objectid)
				{
					int objectid = i->first;
					for (std::set<AMX*>::iterator a = core->getData()->interfaces.begin(); a != core->getData()->interfaces.end(); ++a)
					{
						int amxIndex = 0;
						if (!amx_FindPublic(*a, "OnPlayerEditDynamicObject", &amxIndex))
						{
							amx_Push(*a, amx_ftoc(fRotZ));
							amx_Push(*a, amx_ftoc(fRotY));
							amx_Push(*a, amx_ftoc(fRotX));
							amx_Push(*a, amx_ftoc(fZ));
							amx_Push(*a, amx_ftoc(fY));
							amx_Push(*a, amx_ftoc(fX));
							amx_Push(*a, static_cast<cell>(response));
							amx_Push(*a, static_cast<cell>(objectid));
							amx_Push(*a, static_cast<cell>(playerid));
							amx_Exec(*a, NULL, amxIndex);
						}
					}
					break;
				}
			}
		}
	}
	return false;
}

PLUGIN_EXPORT bool PLUGIN_CALL OnPlayerSelectObject(int playerid, int type, int objectid, int modelid, float x, float y, float z)
{
	if (type == SELECT_OBJECT_PLAYER_OBJECT)
	{
		boost::unordered_map<int, Player>::iterator p = core->getData()->players.find(playerid);
		if (p != core->getData()->players.end())
		{
			for (boost::unordered_map<int, int>::iterator i = p->second.internalObjects.begin(); i != p->second.internalObjects.end(); ++i)
			{
				if (i->second == objectid)
				{
					int objectid = i->first;
					for (std::set<AMX*>::iterator a = core->getData()->interfaces.begin(); a != core->getData()->interfaces.end(); ++a)
					{
						int amxIndex = 0;
						if (!amx_FindPublic(*a, "OnPlayerSelectDynamicObject", &amxIndex))
						{
							amx_Push(*a, amx_ftoc(z));
							amx_Push(*a, amx_ftoc(y));
							amx_Push(*a, amx_ftoc(x));
							amx_Push(*a, static_cast<cell>(modelid));
							amx_Push(*a, static_cast<cell>(objectid));
							amx_Push(*a, static_cast<cell>(playerid));
							amx_Exec(*a, NULL, amxIndex);
						}
					}
					break;
				}
			}
		}
	}
	return false;
}

PLUGIN_EXPORT bool PLUGIN_CALL OnPlayerWeaponShot(int playerid, int weaponid, int hittype, int hitid, float x, float y, float z)
{
	bool retVal = true;
	if (hittype == BULLET_HIT_TYPE_PLAYER_OBJECT)
	{
		boost::unordered_map<int, Player>::iterator p = core->getData()->players.find(playerid);
		if (p != core->getData()->players.end())
		{
			for (boost::unordered_map<int, int>::iterator i = p->second.internalObjects.begin(); i != p->second.internalObjects.end(); ++i)
			{
				if (i->second == hitid)
				{
					int objectid = i->first;
					for (std::set<AMX*>::iterator a = core->getData()->interfaces.begin(); a != core->getData()->interfaces.end(); ++a)
					{
						int amxIndex = 0;
						cell amxRetVal = 0;
						if (!amx_FindPublic(*a, "OnPlayerShootDynamicObject", &amxIndex))
						{
							amx_Push(*a, amx_ftoc(z));
							amx_Push(*a, amx_ftoc(y));
							amx_Push(*a, amx_ftoc(x));
							amx_Push(*a, static_cast<cell>(objectid));
							amx_Push(*a, static_cast<cell>(weaponid));
							amx_Push(*a, static_cast<cell>(playerid));
							amx_Exec(*a, &amxRetVal, amxIndex);
							if (!amxRetVal)
							{
								retVal = false;
							}
						}
					}
					break;
				}
			}
		}
	}
	return retVal;
}
<|endoftext|>


<commit_before>// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "views/focus/focus_manager.h"

#include "base/logging.h"

namespace views {

void FocusManager::ClearNativeFocus() {
  NOTIMPLEMENTED();
}

void FocusManager::FocusNativeView(gfx::NativeView native_view) {
  NOTIMPLEMENTED();
}

 // static
FocusManager* FocusManager::GetFocusManagerForNativeView(
    gfx::NativeView native_view) {
  NOTIMPLEMENTED();
}

}  // namespace views
<commit_msg>Fix compilation error in the focus manager by returning NULL from unimplemented function.<commit_after>// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "views/focus/focus_manager.h"

#include "base/logging.h"

namespace views {

void FocusManager::ClearNativeFocus() {
  NOTIMPLEMENTED();
}

void FocusManager::FocusNativeView(gfx::NativeView native_view) {
  NOTIMPLEMENTED();
}

 // static
FocusManager* FocusManager::GetFocusManagerForNativeView(
    gfx::NativeView native_view) {
  NOTIMPLEMENTED();
  return NULL;
}

}  // namespace views
<|endoftext|>


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

#include <pcl/visualization/interactor.h>
#include <vtkCommand.h>

namespace pcl
{
  namespace visualization
  {
    // Standard VTK macro for *New ()
    vtkStandardNewMacro (PCLVisualizerInteractor);

/*    void
    PCLVisualizerInteractor::TerminateApp ()
    {
      stopped = true;
    }
*/
    //////////////////////////////////////////////////////////////////////////
    void
    PCLVisualizerInteractor::stopLoop ()
    {
#if defined _WIN32 || defined VTK_USE_CARBON || defined VTK_USE_CARBON
      BreakLoopFlagOn ();
      // Send a VTK_BreakWin32Loop ClientMessage event to be sure we pop out of the
      // event loop.  This "wakes up" the event loop.  Otherwise, it might sit idle
      // waiting for an event before realizing an exit was requested.
      SendMessage (this->WindowId, RegisterWindowMessage (TEXT ("VTK_BreakWin32Loop")), 0, 0);
#else
      BreakLoopFlagOn ();
/*      XClientMessageEvent client;
      memset (&client, 0, sizeof (client));
      client.type = ClientMessage;
      client.display = DisplayId;
      client.window = WindowId;
      client.message_type = XInternAtom (client.display, "spinOnce exit", false);
      client.format = 32; // indicates size of data chunks: 8, 16 or 32 bits...
      XSendEvent (client.display, client.window, True, NoEventMask, reinterpret_cast<XEvent *>(&client));
      XFlush (client.display);*/
#endif
    }

#if defined _WIN32 || defined VTK_USE_CARBON || defined VTK_USE_CARBON
    //////////////////////////////////////////////////////////////////////////
    void
    PCLVisualizerInteractor::Start ()
    {
      // Let the compositing handle the event loop if it wants to.
      if (this->HasObserver(vtkCommand::StartEvent) && !this->HandleEventLoop)
      {
        this->InvokeEvent (vtkCommand::StartEvent, NULL);
        return;
      }

      // No need to do anything if this is a 'mapped' interactor
      if (!this->Enabled || !this->InstallMessageProc)
        return;

      this->StartedMessageLoop = 1;

      MSG msg;
      this->BreakLoopFlag=0;

      while (GetMessage (&msg, NULL, 0, 0) && this->BreakLoopFlag == 0)
      {
        TranslateMessage (&msg);
        DispatchMessage (&msg);
      }
    }

    //////////////////////////////////////////////////////////////////////////
    void
    PCLVisualizerInteractor::SetBreakLoopFlag (int f)
    {
      if (f)
        this->BreakLoopFlagOn ();
      else
        this->BreakLoopFlagOff ();
    }

    //////////////////////////////////////////////////////////////////////////
    void
    PCLVisualizerInteractor::BreakLoopFlagOff ()
    {
      this->BreakLoopFlag = 0;
      this->Modified ();
    }

    //////////////////////////////////////////////////////////////////////////
    void
    PCLVisualizerInteractor::BreakLoopFlagOn ()
    {
      this->BreakLoopFlag = 1;
      this->Modified ();
    }
#endif
  }
}

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

#include <pcl/visualization/interactor.h>
#include <vtkCommand.h>

namespace pcl
{
  namespace visualization
  {
    // Standard VTK macro for *New ()
    vtkStandardNewMacro (PCLVisualizerInteractor);

/*    void
    PCLVisualizerInteractor::TerminateApp ()
    {
      stopped = true;
    }
*/
    //////////////////////////////////////////////////////////////////////////
    void
    PCLVisualizerInteractor::stopLoop ()
    {
#if defined _WIN32 || defined VTK_USE_CARBON || defined VTK_USE_CARBON
      BreakLoopFlagOn ();
      // Send a VTK_BreakWin32Loop ClientMessage event to be sure we pop out of the
      // event loop.  This "wakes up" the event loop.  Otherwise, it might sit idle
      // waiting for an event before realizing an exit was requested.
      SendMessage (this->WindowId, RegisterWindowMessage (TEXT ("VTK_BreakWin32Loop")), 0, 0);
#else
      BreakLoopFlagOn ();
      XClientMessageEvent client;
      memset (&client, 0, sizeof (client));
      client.type = ClientMessage;
      client.display = DisplayId;
      client.window = WindowId;
      client.message_type = XInternAtom (client.display, "spinOnce exit", false);
      client.format = 32; // indicates size of data chunks: 8, 16 or 32 bits...
      XSendEvent (client.display, client.window, True, NoEventMask, reinterpret_cast<XEvent *>(&client));
      XFlush (client.display);
#endif
    }

#if defined _WIN32 || defined VTK_USE_CARBON || defined VTK_USE_CARBON
    //////////////////////////////////////////////////////////////////////////
    void
    PCLVisualizerInteractor::Start ()
    {
      // Let the compositing handle the event loop if it wants to.
      if (this->HasObserver(vtkCommand::StartEvent) && !this->HandleEventLoop)
      {
        this->InvokeEvent (vtkCommand::StartEvent, NULL);
        return;
      }

      // No need to do anything if this is a 'mapped' interactor
      if (!this->Enabled || !this->InstallMessageProc)
        return;

      this->StartedMessageLoop = 1;

      MSG msg;
      this->BreakLoopFlag=0;

      while (GetMessage (&msg, NULL, 0, 0) && this->BreakLoopFlag == 0)
      {
        TranslateMessage (&msg);
        DispatchMessage (&msg);
      }
    }

    //////////////////////////////////////////////////////////////////////////
    void
    PCLVisualizerInteractor::SetBreakLoopFlag (int f)
    {
      if (f)
        this->BreakLoopFlagOn ();
      else
        this->BreakLoopFlagOff ();
    }

    //////////////////////////////////////////////////////////////////////////
    void
    PCLVisualizerInteractor::BreakLoopFlagOff ()
    {
      this->BreakLoopFlag = 0;
      this->Modified ();
    }

    //////////////////////////////////////////////////////////////////////////
    void
    PCLVisualizerInteractor::BreakLoopFlagOn ()
    {
      this->BreakLoopFlag = 1;
      this->Modified ();
    }
#endif
  }
}

<|endoftext|>


<commit_before>/*
 * Copyright 2015 Georgia Institute of Technology
 *
 * 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    clear_cache.cpp
 * @ingroup
 * @author  tpan
 * @brief   clears cache on a linux system
 * @details for use before doing file io benchmark.
 *
 * Copyright (c) 2016 Georgia Institute of Technology.  All Rights Reserved.
 *
 * TODO add License
 */

#include "utils/memory_usage.hpp"

/**
 * @brief  clear the disk cache in linux by allocating a bunch of memory.
 * @details  in 1MB chunks to workaround memory fragmentation preventing allocation.
 *           can potentially use swap, or if there is not enough physical + swap, be killed.
 *
 */
void clear_cache() {
  size_t avail = MemUsage::get_usable_mem();
  size_t rem = avail;

  size_t minchunk = 1 << 23;
  size_t chunk = minchunk;

  while (chunk < (avail >> 4)) chunk <<= 1;   // keep increasing chunks until larger than 1/16 of avail.

  std::vector<size_t *> dummy;

  size_t nchunks;
  size_t i;
  size_t *ptr;
  size_t j = 0;

  printf("begin clearing %lu bytes\n", avail);

  while ((chunk >= minchunk) && (rem > chunk)) {
    nchunks = rem / chunk;

    for (i = 0; i < nchunks; ++i, ++j) {
      if ((j % 16) == 0) {
        printf("%lu ", j);  // 16 outputs.
        fflush(stdout);
      }

      // (c|m)alloc/free seems to be optimized out.  using new works.
      ptr = new size_t[(chunk / sizeof(size_t))];

      rem -= chunk;
      memset(ptr, 0, chunk);
      ptr[0] = i;

      dummy.push_back(ptr);
    }

    //    // check for available memory, every 64 MBs
    //    if ((i % 64) == 0) {
    //      avail = MemUsage::get_usable_mem();
    //      if (avail < (64 << 20)) break;   // less than 64MB available.
    //    }

    // reduce the size of the chunk by 4
    chunk >>= 2;
  }
  printf("\n");
  printf("attempting to allocate %lu bytes\n", avail - rem);
  fflush(stdout);

  size_t sum = 0;
  size_t ii = 0;
  for (; ii < dummy.size(); ++ii) {
    ptr = dummy[ii];

    if (ptr != nullptr) {
      if ((ii % 16) == 0) {
        printf("%lu ", ii);  // 16 outputs.
        fflush(stdout);
      }
      sum += ptr[ii >> 10];
      delete [] ptr;
      //free(ptr);
      dummy[ii] = nullptr;
    } else {
      break;
    }
  }
  printf("\n");
  printf("disk cache cleared (dummy %lu). %lu blocks %lu bytes\n", sum, j, avail - rem);
}

int main(int argc, char** argv) {

  clear_cache();

  return 0;
}
<commit_msg>WIP: further testing on large memory machine<commit_after>/*
 * Copyright 2015 Georgia Institute of Technology
 *
 * 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    clear_cache.cpp
 * @ingroup
 * @author  tpan
 * @brief   clears cache on a linux system
 * @details for use before doing file io benchmark.
 *
 * Copyright (c) 2016 Georgia Institute of Technology.  All Rights Reserved.
 *
 * TODO add License
 */

#include "utils/memory_usage.hpp"

/**
 * @brief  clear the disk cache in linux by allocating a bunch of memory.
 * @details  in 1MB chunks to workaround memory fragmentation preventing allocation.
 *           can potentially use swap, or if there is not enough physical + swap, be killed.
 *
 */
void clear_cache() {
  size_t avail = MemUsage::get_usable_mem();
  size_t rem = avail;

  size_t minchunk = 1UL << 24;    // 16MB chunks
  size_t chunk = minchunk;

  size_t maxchunk = std::min(1UL << 30, (avail >> 4));
  for ( ;chunk < maxchunk; chunk <<= 1) ;   // keep increasing chunks until larger than 1/16 of avail, or until 1GB.

  std::vector<size_t *> dummy;

  size_t nchunks;
  size_t i;
  size_t *ptr;
  size_t j = 0;

  printf("begin clearing %lu bytes\n", avail);
  size_t iter_cleared = 0;

  while ((chunk >= minchunk) && (rem > minchunk)) {
    nchunks = rem / chunk;
    iter_cleared = 0;

    for (i = 0; i < nchunks; ++i, ++j) {
//      if ((j % 16) == 0) {
//        printf("%lu ", j);  // 16 outputs.
//        fflush(stdout);
//      }

      // (c|m)alloc/free seems to be optimized out.  using new works.
      ptr = new size_t[(chunk / sizeof(size_t))];

      iter_cleared += chunk;
      memset(ptr, 0, chunk);
      ptr[0] = i;

      dummy.push_back(ptr);
    }

    //    // check for available memory, every 64 MBs
    //    if ((i % 64) == 0) {
    //      avail = MemUsage::get_usable_mem();
    //      if (avail < (64 << 20)) break;   // less than 64MB available.
    //    }
    rem -= iter_cleared;

    printf("cleared %lu bytes using %lu chunk %lu bytes. total cleared %lu bytes, rem %lu bytes \n", iter_cleared, i, chunk, avail - rem, rem);
    fflush(stdout);

    // reduce the size of the chunk by 4
    chunk >>= 2;

  }
  printf("finished clearing %lu/%lu bytes with %lu remaining\n", avail - rem, avail, rem);
  fflush(stdout);

  size_t sum = 0;
  size_t ii = 0;
  for (; ii < dummy.size(); ++ii) {
    ptr = dummy[ii];

    if (ptr != nullptr) {
//      if ((ii % 16) == 0) {
//        printf("%lu ", ii);  // 16 outputs.
//        fflush(stdout);
//      }
      sum += ptr[ii >> 10];
      delete [] ptr;
      //free(ptr);
      dummy[ii] = nullptr;
    } else {
      break;
    }
  }
  printf("\n");
  printf("disk cache cleared (dummy %lu). %lu blocks %lu bytes\n", sum, j, avail - rem);
}

int main(int argc, char** argv) {

  clear_cache();

  return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) , Arm Limited and affiliates.
 * SPDX-License-Identifier: Apache-2.0
 *
 * 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 "rtos/ThisThread.h"

namespace rtos {

void ThisThread::sleep_until(uint64_t millisec)
{
}

void ThisThread::sleep_for(uint32_t millisec)
{
}

}
<commit_msg>Add ThisThread Chrono stubs<commit_after>/*
 * Copyright (c) , Arm Limited and affiliates.
 * SPDX-License-Identifier: Apache-2.0
 *
 * 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 "rtos/ThisThread.h"

namespace rtos {

void ThisThread::sleep_until(uint64_t millisec)
{
}

void ThisThread::sleep_until(Kernel::Clock::time_point abs_time)
{
}

void ThisThread::sleep_for(uint32_t millisec)
{
}

void ThisThread::sleep_for(Kernel::Clock::duration_u32 rel_time)
{
}

}
<|endoftext|>


<commit_before>#include <chat/chat.hpp>
#include <hash.hpp>
#include <packet.hpp>
#include <server.hpp>
#include <singleton.hpp>
#include <algorithm>
#include <limits>
#include <unordered_map>
#include <unordered_set>
#include <utility>

using namespace MCPP;

namespace MCPP {

	static const String name("Chat Support");
	static const Word priority=1;
	static const String mods_dir("chat_mods");
	static const String log_prepend("Chat Support: ");
	static const String protocol_error("Protocol error");

	const String & Chat::Name () const noexcept {

		return name;

	}

	Word Chat::Priority () const noexcept {

		return priority;

	}

	//	Maximum depth to which incoming JSON
	//	messages will be parsed
	static const Word max_depth=5;

	void Chat::Install () {

		auto & server=Server::Get();

		//	Incoming packet type
		typedef Packets::Play::Serverbound::ChatMessage type;

		//	Handle incoming chat messages
		server.Router(
			type::PacketID,
			ProtocolState::Play
		)=[this] (PacketEvent event) mutable {

			//	If there's no installed handler,
			//	abort at once
			if (!Chat) return;

			auto & packet=event.Data.Get<type>();

			ChatEvent dispatch;
			dispatch.From=event.From;
			dispatch.Body=std::move(packet.Value);

			Chat(std::move(dispatch));

		};

		//	Make sure that we don't keep
		//	module assets after the server
		//	is shutdown
		server.OnShutdown.Add([this] () mutable {	Chat=ChatHandler();	});

	}

	typedef Packets::Play::Clientbound::ChatMessage packet_type;

	static ChatMessage copy (const ChatMessage & message, const Vector<ChatStyle> & stack) {

		//	Copy everything except the actual
		//	body of the message
		ChatMessage retr;
		retr.From=message.From;
		retr.To=message.To;
		retr.Recipients=message.Recipients;
		retr.Echo=message.Echo;

		for (auto s : stack) retr << s;

		return retr;

	}

	static Vector<String> get_lines (const String & str) {

		Vector<String> retr;

		Vector<CodePoint> curr;
		bool trailing=false;
		for (auto cp : str.CodePoints()) {

			//	The "trailing" variable monitors
			//	for a trailing newline, which requires
			//	the insertion of an empty string at
			//	the end
			//
			//	Since another iteration of the loop implies
			//	that there's a character after the newline,
			//	we reset the variable to false on each
			//	iteration
			trailing=false;

			//	Skip carriage returns
			if (cp=='\r') continue;

			//	Append on newline
			if (cp=='\n') {

				retr.EmplaceBack(std::move(curr));

				trailing=true;

				continue;

			}

			//	Otherwise just add code point
			//	and move on
			curr.Add(cp);

		}

		//	Append last if necessary
		if (
			(curr.Count()!=0) ||
			trailing
		) retr.EmplaceBack(std::move(curr));

		return retr;

	}

	static Vector<packet_type> preprocess (const ChatMessage & message) {

		//	Maintain our own stack
		Vector<ChatStyle> stack;

		//	Chat messages we've split this chat
		//	message into
		Vector<ChatMessage> messages;
		//	Start with one message
		messages.Add(copy(message,stack));

		//	Loop over each element in the
		//	message we were passed in
		for (auto & token : message.Message) {

			switch (token.Type) {

				//	Maintain our own stack by intercepting
				//	push and pop commands
				case ChatFormat::Push:
					stack.Add(token.Style);
					break;
				case ChatFormat::Pop:
					if (stack.Count()!=0) stack.Delete(stack.Count()-1);
					break;
				//	Check segments for new lines, and create
				//	new messages for each newline
				case ChatFormat::Segment:{

					auto lines=get_lines(token.Segment);

					for (Word i=0;i<lines.Count();++i) {

						//	If this isn't the first line, create a
						//	new message
						if (i!=0) messages.Add(copy(message,stack));

						//	Skip empty strings
						if (lines[i].Size()==0) continue;

						messages[messages.Count()-1] << lines[i];

					}

				}continue;
				default:break;

			}

			messages[messages.Count()-1] << token;

		}

		//	Parse messages into packets
		Vector<packet_type> retr;
		for (auto & m : messages) {

			packet_type packet;
			packet.Value=Chat::Format(m);

			retr.Add(std::move(packet));

		}

		return retr;

	}

	static void send (SmartPointer<Client> client, const Vector<packet_type> & packets) {

		if (!client.IsNull()) client->Atomic([&] () mutable {	for (auto & packet : packets) client->Send(packet);	});

	}

	static const String server_username("SERVER");

	Vector<String> Chat::Send (const ChatMessage & message) {

		//	As of 1.7.2 Mojang has broken the client's
		//	rendering of newline characters.  The client
		//	now renders them as "LF" in a box, rather
		//	than actually inserting a line break.
		//
		//	Therefore a workaround is necessary.  This
		//	preprocess method takes and breaks a single
		//	ChatMessage into many ChatMessages, each one
		//	containing a single line.  It then creates
		//	a packet from each of these ChatMessages.
		//
		//	By using the Atomic method on the Client
		//	object, we're able to send all these packets
		//	without any risk of other packets being sent
		//	in between.
		//
		//	It's objectively bad design, but it's not
		//	my fault -- I'm just working around Mojang's
		//	poor design decisions.
		auto packets=preprocess(message);

		//	List of clients to whom the message
		//	could not be delivered
		Vector<String> retr;

		//	Return to sender if this is
		//	an echo message
		if (message.Echo && !message.From.IsNull()) {

			send(message.From,packets);

			return retr;

		}

		auto & server=Server::Get();

		//	If this is a broadcast, simply send to everyone
		if (
			(message.To.Count()==0) &&
			(message.Recipients.Count()==0)
		) {

			for (auto & client : server.Clients) send(client,packets);

			Log(message);

			return retr;

		}

		//	Create two lookup tables for recipients
		//	whose handles we have -- one which relates
		//	the handle to the normalized username of
		//	that user, another which can simply be used
		//	to lookup the handle.
		std::unordered_map<String,SmartPointer<Client>> names;
		std::unordered_set<SmartPointer<Client>> handles;
		for (const auto & c : message.Recipients) {

			String lowercase;

			//	Special case for the server
			if (c.IsNull()) {

				handles.emplace(c);

				lowercase=server_username;

			//	Skip clients who are not in the
			//	appropriate state
			} else if (c->GetState()==ProtocolState::Play) {

				handles.emplace(c);

				lowercase=c->GetUsername().ToLower();

			} else {

				continue;

			}

			names.emplace(
				std::move(lowercase),
				c
			);

		}

		//	Rearrange the clients we're delivering
		//	to by name into a hash table, which maps
		//	their normalized (i.e. lowercased) username
		//	to the actual username that was used for
		//	them.
		//
		//	This will greatly reduce the overhead of
		//	tracking the recipients to whom we could
		//	or could not deliver
		std::unordered_map<String,const String *> to;
		for (const auto & s : message.To) {

			String lowercase(s);
			//	There's a special case for
			//	the server -- that username
			//	is always uppercase
			if (s!=server_username) lowercase.ToLower();

			//	If this user is also being delivered
			//	to by handle, ignore
			if (names.count(s)!=0) continue;

			to.emplace(
				std::move(lowercase),
				&s
			);

		}

		//	Scan connected users to find users
		//	with the usernames of our recipients
		if (to.size()!=0) for (auto & client : server.Clients) {

			//	We're only interested in clients
			//	in game
			if (client->GetState()!=ProtocolState::Play) continue;

			//	Check to see if we're sending to
			//	this user by name
			auto iter=to.find(client->GetUsername().ToLower());
			if (iter!=to.end()) {

				//	YES

				//	Send
				send(client,packets);

				//	Remove from collection
				//
				//	The users left in the collection
				//	will be those users to whom
				//	we could not deliver
				to.erase(iter);

			}

		}

		//	Deliver to users we're delivering to
		//	by handle
		for (auto & client : message.Recipients) send(client,packets);

		//	Build the list of recipients who could
		//	not be found/delivered to
		for (const auto & pair : to) retr.Add(*pair.second);

		//	Log
		Log(message,retr);

		return retr;

	}

	static Singleton<Chat> singleton;

	Chat & Chat::Get () noexcept {

		return singleton.Get();

	}

}

extern "C" {

	Module * Load () {

		return &(Chat::Get());

	}

	void Unload () {

		singleton.Destroy();

	}

}
<commit_msg>Chat Fix<commit_after>#include <chat/chat.hpp>
#include <hash.hpp>
#include <packet.hpp>
#include <server.hpp>
#include <singleton.hpp>
#include <algorithm>
#include <limits>
#include <unordered_map>
#include <unordered_set>
#include <utility>

using namespace MCPP;

namespace MCPP {

	static const String name("Chat Support");
	static const Word priority=1;
	static const String mods_dir("chat_mods");
	static const String log_prepend("Chat Support: ");
	static const String protocol_error("Protocol error");

	const String & Chat::Name () const noexcept {

		return name;

	}

	Word Chat::Priority () const noexcept {

		return priority;

	}

	//	Maximum depth to which incoming JSON
	//	messages will be parsed
	static const Word max_depth=5;

	void Chat::Install () {

		auto & server=Server::Get();

		//	Incoming packet type
		typedef Packets::Play::Serverbound::ChatMessage type;

		//	Handle incoming chat messages
		server.Router(
			type::PacketID,
			ProtocolState::Play
		)=[this] (PacketEvent event) mutable {

			//	If there's no installed handler,
			//	abort at once
			if (!Chat) return;

			auto & packet=event.Data.Get<type>();

			ChatEvent dispatch;
			dispatch.From=event.From;
			dispatch.Body=std::move(packet.Value);

			Chat(std::move(dispatch));

		};

		//	Make sure that we don't keep
		//	module assets after the server
		//	is shutdown
		server.OnShutdown.Add([this] () mutable {	Chat=ChatHandler();	});

	}

	typedef Packets::Play::Clientbound::ChatMessage packet_type;

	static ChatMessage copy (const ChatMessage & message, const Vector<ChatStyle> & stack) {

		//	Copy everything except the actual
		//	body of the message
		ChatMessage retr;
		retr.From=message.From;
		retr.To=message.To;
		retr.Recipients=message.Recipients;
		retr.Echo=message.Echo;

		for (auto s : stack) retr << s;

		return retr;

	}

	static Vector<String> get_lines (const String & str) {

		Vector<String> retr;

		Vector<CodePoint> curr;
		bool trailing=false;
		for (auto cp : str.CodePoints()) {

			//	The "trailing" variable monitors
			//	for a trailing newline, which requires
			//	the insertion of an empty string at
			//	the end
			//
			//	Since another iteration of the loop implies
			//	that there's a character after the newline,
			//	we reset the variable to false on each
			//	iteration
			trailing=false;

			//	Skip carriage returns
			if (cp=='\r') continue;

			//	Append on newline
			if (cp=='\n') {

				retr.EmplaceBack(std::move(curr));

				trailing=true;

				continue;

			}

			//	Otherwise just add code point
			//	and move on
			curr.Add(cp);

		}

		//	Append last if necessary
		if (
			(curr.Count()!=0) ||
			trailing
		) retr.EmplaceBack(std::move(curr));

		return retr;

	}

	static Vector<packet_type> preprocess (const ChatMessage & message) {

		//	Maintain our own stack
		Vector<ChatStyle> stack;

		//	Chat messages we've split this chat
		//	message into
		Vector<ChatMessage> messages;
		//	Start with one message
		messages.Add(copy(message,stack));

		//	Loop over each element in the
		//	message we were passed in
		for (auto & token : message.Message) {

			switch (token.Type) {

				//	Maintain our own stack by intercepting
				//	push and pop commands
				case ChatFormat::Push:
					stack.Add(token.Style);
					break;
				case ChatFormat::Pop:
					if (stack.Count()!=0) stack.Delete(stack.Count()-1);
					break;
				//	Check segments for new lines, and create
				//	new messages for each newline
				case ChatFormat::Segment:{

					auto lines=get_lines(token.Segment);

					for (Word i=0;i<lines.Count();++i) {

						//	If this isn't the first line, create a
						//	new message
						if (i!=0) messages.Add(copy(message,stack));

						//	Skip empty strings
						if (lines[i].Size()==0) continue;

						messages[messages.Count()-1] << lines[i];

					}

				}continue;
				default:break;

			}

			messages[messages.Count()-1] << token;

		}

		//	Parse messages into packets
		Vector<packet_type> retr;
		for (auto & m : messages) {

			packet_type packet;
			packet.Value=Chat::Format(m);

			retr.Add(std::move(packet));

		}

		return retr;

	}

	static void send (SmartPointer<Client> client, const Vector<packet_type> & packets) {

		if (!client.IsNull()) client->Atomic([&] () mutable {	for (auto & packet : packets) client->Send(packet);	});

	}

	static const String server_username("SERVER");

	Vector<String> Chat::Send (const ChatMessage & message) {

		//	As of 1.7.2 Mojang has broken the client's
		//	rendering of newline characters.  The client
		//	now renders them as "LF" in a box, rather
		//	than actually inserting a line break.
		//
		//	Therefore a workaround is necessary.  This
		//	preprocess method takes and breaks a single
		//	ChatMessage into many ChatMessages, each one
		//	containing a single line.  It then creates
		//	a packet from each of these ChatMessages.
		//
		//	By using the Atomic method on the Client
		//	object, we're able to send all these packets
		//	without any risk of other packets being sent
		//	in between.
		//
		//	It's objectively bad design, but it's not
		//	my fault -- I'm just working around Mojang's
		//	poor design decisions.
		auto packets=preprocess(message);

		//	List of clients to whom the message
		//	could not be delivered
		Vector<String> retr;

		//	Return to sender if this is
		//	an echo message
		if (message.Echo && !message.From.IsNull()) {

			send(message.From,packets);

			return retr;

		}

		auto & server=Server::Get();

		//	If this is a broadcast, simply send to everyone
		if (
			(message.To.Count()==0) &&
			(message.Recipients.Count()==0)
		) {

			for (auto & client : server.Clients) send(client,packets);

			Log(message);

			return retr;

		}

		//	Create two lookup tables for recipients
		//	whose handles we have -- one which relates
		//	the handle to the normalized username of
		//	that user, another which can simply be used
		//	to lookup the handle.
		std::unordered_map<String,SmartPointer<Client>> names;
		std::unordered_set<SmartPointer<Client>> handles;
		for (const auto & c : message.Recipients) {

			//	Skip the server and clients
			//	who aren't in the appropriate
			//	state for chat messages
			if (
				c.IsNull() ||
				(c->GetState()!=ProtocolState::Play)
			) continue;

			handles.emplace(c);
			names.emplace(
				c->GetUsername().ToLower(),
				c
			);

		}

		//	Rearrange the clients we're delivering
		//	to by name into a hash table, which maps
		//	their normalized (i.e. lowercased) username
		//	to the actual username that was used for
		//	them.
		//
		//	This will greatly reduce the overhead of
		//	tracking the recipients to whom we could
		//	or could not deliver
		std::unordered_map<String,const String *> to;
		for (const auto & s : message.To) {

			//	Skip the server
			if (s==server_username) continue;

			//	Normalize username
			String lowercase(s.ToLower());

			//	Check if this user is already being
			//	delivered to by handle, if so, skip
			if (names.count(lowercase)!=0) continue;

			to.emplace(
				std::move(lowercase),
				&s
			);

		}

		//	Scan connected users to find users
		//	with the usernames of our recipients
		if (to.size()!=0) for (auto & client : server.Clients) {

			//	We're only interested in clients
			//	in game
			if (client->GetState()!=ProtocolState::Play) continue;

			//	Check to see if we're sending to
			//	this user by name
			auto iter=to.find(client->GetUsername().ToLower());
			if (iter!=to.end()) {

				//	YES

				//	Send
				send(client,packets);

				//	Remove from collection
				//
				//	The users left in the collection
				//	will be those users to whom
				//	we could not deliver
				to.erase(iter);

			}

		}

		//	Deliver to users we're delivering to
		//	by handle
		for (auto & client : message.Recipients) send(client,packets);

		//	Build the list of recipients who could
		//	not be found/delivered to
		for (const auto & pair : to) retr.Add(*pair.second);

		//	Log
		Log(message,retr);

		return retr;

	}

	static Singleton<Chat> singleton;

	Chat & Chat::Get () noexcept {

		return singleton.Get();

	}

}

extern "C" {

	Module * Load () {

		return &(Chat::Get());

	}

	void Unload () {

		singleton.Destroy();

	}

}
<|endoftext|>


<commit_before>/*
    This file is part of libkdepim.

    Copyright (c) 2003 Don Sanders <sanders@kde.org>
    Copyright (c) 2005 George Staikos <staikos@kde.org>
    Copyright (c) 2005 Rafal Rzepecki <divide@users.sourceforge.net>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include "maillistdrag.h"
#include "kdepimprotocols.h"
#include <QBuffer>
#include <QDataStream>
#include <QEventLoop>
#include <QProgressBar>
#include <QTextStream>
#include <QDropEvent>
#include <klocale.h>
#include <kprogressdialog.h>
#include <kurl.h>

using namespace KPIM;

MailSummary::MailSummary( quint32 serialNumber, const QString &messageId,
			  const QString &subject, const QString &from, const QString &to,
			  time_t date )
    : mSerialNumber( serialNumber ), mMessageId( messageId ),
      mSubject( subject ), mFrom( from ), mTo( to ), mDate( date )
{}

quint32 MailSummary::serialNumber() const
{
    return mSerialNumber;
}

QString MailSummary::messageId()  const
{
    return mMessageId;
}

QString MailSummary::subject() const
{
    return mSubject;
}

QString MailSummary::from() const
{
    return mFrom;
}

QString MailSummary::to() const
{
    return mTo;
}

time_t MailSummary::date() const
{
    return mDate;
}

void MailSummary::set( quint32 serialNumber, const QString &messageId,
		       const QString &subject, const QString &from, const QString &to, time_t date )
{
    mSerialNumber = serialNumber;
    mMessageId = messageId;
    mSubject = subject;
    mFrom = from;
    mTo = to;
    mDate = date;
}

MailSummary::operator KUrl() const
{
  return KUrl( KDEPIMPROTOCOL_EMAIL + QString::number( serialNumber() ) + '/' + messageId() );
}

QString MailList::mimeDataType()
{
    return "x-kmail-drag/message-list";
}

bool MailList::canDecode( const QMimeData*md )
{
  return md->hasFormat( mimeDataType() );
}

void MailList::populateMimeData( QMimeData*md, MailTextSource *src )
{
  /* We have three different possible mime types: x-kmail-drag/message-list, message/rfc822, and URL
     Add them in this order */

  /* Popuplate the MimeData with the custom streaming x-kmail-drag/message-list mime type */
  if ( count() ) {
    QByteArray array;
    QBuffer buffer( &array, 0 );
    buffer.open( QIODevice::WriteOnly);
    QDataStream stream( &array, QIODevice::WriteOnly );
    stream << this;
    buffer.close();
    md->setData( MailList::mimeDataType(), array );
  }

  /* Popuplate the MimeData with the standard message/rfc822 mime type, only
     possible if we are given a MailTextSource */
  if ( src && count() ) {
    QByteArray rc;
    KProgressDialog *dlg = new KProgressDialog( 0, QString(), i18n("Retrieving and storing messages..."));
    dlg->setWindowModality(Qt::WindowModal);
    dlg->setAllowCancel(true);
    dlg->progressBar()->setMaximum( count());
    int i = 0;
    dlg->progressBar()->setValue(i);
    dlg->show();

    QTextStream *ts = new QTextStream(rc, QIODevice::WriteOnly);
    for ( MailList::ConstIterator it = begin(); it != end(); ++it ) {
      MailSummary mailDrag = *it;
      *ts << src->text(mailDrag.serialNumber());
      if (dlg->wasCancelled()) {
        break;
      }
      dlg->progressBar()->setValue(++i);
#ifdef __GNUC__
      #warning Port me!
#endif
      //kapp->eventLoop()->processEvents(QEventLoop::ExcludeSocketNotifiers);
    }
    delete dlg;
    delete ts;

    md->setData( "message/rfc822", rc );
  }

  /* Popuplate the MimeData with the URLs of the messages */
  KUrl::List urllist;
  QStringList labels;
  for ( MailList::ConstIterator it = begin(); it != end(); ++it ) {
    urllist.append( (*it) );
    labels.append( KUrl::toPercentEncoding( ( *it ).subject() ) );
  }
  QMap<QString,QString> metadata;
  metadata["labels"] = labels.join( ":" );
  urllist.populateMimeData( md, metadata );

}

// Have to define before use
QDataStream& operator<< ( QDataStream &s, const MailSummary &d )
{
    s << d.serialNumber();
    s << d.messageId();
    s << d.subject();
    s << d.from();
    s << d.to();
#ifdef __GNUC__
    #warning Port me!
#endif
//     s << d.date();
    return s;
}

QDataStream& operator>> ( QDataStream &s, MailSummary &d )
{
    quint32 serialNumber;
    QString messageId, subject, from, to;
    time_t date = 0;
    s >> serialNumber;
    s >> messageId;
    s >> subject;
    s >> from;
    s >> to;
#ifdef __GNUC__
    #warning Port me!
#endif
//     s >> date;
    d.set( serialNumber, messageId, subject, from, to, date );
    return s;
}

QDataStream& operator<< ( QDataStream &s, MailList &mailList )
{
    MailList::iterator it;
    for (it = mailList.begin(); it != mailList.end(); ++it) {
	MailSummary mailDrag = *it;
	s << mailDrag;
    }
    return s;
}

QDataStream& operator>> ( QDataStream &s, MailList &mailList )
{
    mailList.clear();
    MailSummary mailDrag;
    while (!s.atEnd()) {
	s >> mailDrag;
	mailList.append( mailDrag );
    }
    return s;
}

MailList MailList::fromMimeData( const QMimeData *md )
{
  if ( canDecode(md) ) {
    return decode( md->data( mimeDataType() ) );
  } else {
    return MailList();
  }
}

MailList MailList::decode( const QByteArray& payload )
{
  MailList mailList;
  // A read-only data stream
  QDataStream stream( payload );
  if ( payload.size() ) {
    stream >> mailList;
  }
  return mailList;
}

QByteArray MailList::serialsFromMimeData( const QMimeData *md )
{
  MailList mailList = fromMimeData( md );
  if ( mailList.count() ) {
    MailList::iterator it;
    QByteArray a;
    QBuffer buffer( &a );
    buffer.open( QIODevice::WriteOnly );
    QDataStream stream( &buffer );
    for (it = mailList.begin(); it != mailList.end(); ++it) {
      MailSummary mailDrag = *it;
      stream << mailDrag.serialNumber();
    }
    buffer.close();
    return a;
  } else {
    return QByteArray();
  }
}

<commit_msg>Fix drag&drop of mails.<commit_after>/*
    This file is part of libkdepim.

    Copyright (c) 2003 Don Sanders <sanders@kde.org>
    Copyright (c) 2005 George Staikos <staikos@kde.org>
    Copyright (c) 2005 Rafal Rzepecki <divide@users.sourceforge.net>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include "maillistdrag.h"
#include "kdepimprotocols.h"
#include <QBuffer>
#include <QDataStream>
#include <QEventLoop>
#include <QProgressBar>
#include <QTextStream>
#include <QDropEvent>
#include <klocale.h>
#include <kprogressdialog.h>
#include <kurl.h>

using namespace KPIM;

// Have to define before use
QDataStream& operator<< ( QDataStream &s, const MailSummary &d )
{
  s << d.serialNumber();
  s << d.messageId();
  s << d.subject();
  s << d.from();
  s << d.to();
#ifdef __GNUC__
#warning Port me!
#endif
  //s << d.date();
  return s;
}

QDataStream& operator>> ( QDataStream &s, MailSummary &d )
{
  quint32 serialNumber;
  QString messageId, subject, from, to;
  time_t date = 0;
  s >> serialNumber;
  s >> messageId;
  s >> subject;
  s >> from;
  s >> to;
#ifdef __GNUC__
#warning Port me!
#endif
  //s >> date;
  d.set( serialNumber, messageId, subject, from, to, date );
  return s;
}

QDataStream& operator<< ( QDataStream &s, const MailList &mailList )
{
  MailList::const_iterator it;
  for (it = mailList.begin(); it != mailList.end(); ++it) {
    MailSummary mailDrag = *it;
    s << mailDrag;
  }
  return s;
}

QDataStream& operator>> ( QDataStream &s, MailList &mailList )
{
  mailList.clear();
  MailSummary mailDrag;
  while (!s.atEnd()) {
    s >> mailDrag;
    mailList.append( mailDrag );
  }
  return s;
}

MailSummary::MailSummary( quint32 serialNumber, const QString &messageId,
			  const QString &subject, const QString &from, const QString &to,
			  time_t date )
    : mSerialNumber( serialNumber ), mMessageId( messageId ),
      mSubject( subject ), mFrom( from ), mTo( to ), mDate( date )
{}

quint32 MailSummary::serialNumber() const
{
    return mSerialNumber;
}

QString MailSummary::messageId()  const
{
    return mMessageId;
}

QString MailSummary::subject() const
{
    return mSubject;
}

QString MailSummary::from() const
{
    return mFrom;
}

QString MailSummary::to() const
{
    return mTo;
}

time_t MailSummary::date() const
{
    return mDate;
}

void MailSummary::set( quint32 serialNumber, const QString &messageId,
		       const QString &subject, const QString &from, const QString &to, time_t date )
{
    mSerialNumber = serialNumber;
    mMessageId = messageId;
    mSubject = subject;
    mFrom = from;
    mTo = to;
    mDate = date;
}

MailSummary::operator KUrl() const
{
  return KUrl( KDEPIMPROTOCOL_EMAIL + QString::number( serialNumber() ) + '/' + messageId() );
}

QString MailList::mimeDataType()
{
    return "x-kmail-drag/message-list";
}

bool MailList::canDecode( const QMimeData*md )
{
  return md->hasFormat( mimeDataType() );
}

void MailList::populateMimeData( QMimeData*md, MailTextSource *src )
{
  /* We have three different possible mime types: x-kmail-drag/message-list, message/rfc822, and URL
     Add them in this order */

  /* Popuplate the MimeData with the custom streaming x-kmail-drag/message-list mime type */
  if ( count() ) {
    QByteArray array;
    QBuffer buffer( &array, 0 );
    buffer.open( QIODevice::WriteOnly);
    QDataStream stream( &array, QIODevice::WriteOnly );
    stream << (*this);
    buffer.close();
    md->setData( MailList::mimeDataType(), array );
  }

  /* Popuplate the MimeData with the standard message/rfc822 mime type, only
     possible if we are given a MailTextSource */
  if ( src && count() ) {
    QByteArray rc;
    KProgressDialog *dlg = new KProgressDialog( 0, QString(), i18n("Retrieving and storing messages..."));
    dlg->setWindowModality(Qt::WindowModal);
    dlg->setAllowCancel(true);
    dlg->progressBar()->setMaximum( count());
    int i = 0;
    dlg->progressBar()->setValue(i);
    dlg->show();

    QTextStream *ts = new QTextStream(rc, QIODevice::WriteOnly);
    for ( MailList::ConstIterator it = begin(); it != end(); ++it ) {
      MailSummary mailDrag = *it;
      *ts << src->text(mailDrag.serialNumber());
      if (dlg->wasCancelled()) {
        break;
      }
      dlg->progressBar()->setValue(++i);
#ifdef __GNUC__
      #warning Port me!
#endif
      //kapp->eventLoop()->processEvents(QEventLoop::ExcludeSocketNotifiers);
    }
    delete dlg;
    delete ts;

    md->setData( "message/rfc822", rc );
  }

  /* Popuplate the MimeData with the URLs of the messages */
  KUrl::List urllist;
  QStringList labels;
  for ( MailList::ConstIterator it = begin(); it != end(); ++it ) {
    urllist.append( (*it) );
    labels.append( KUrl::toPercentEncoding( ( *it ).subject() ) );
  }
  QMap<QString,QString> metadata;
  metadata["labels"] = labels.join( ":" );
  urllist.populateMimeData( md, metadata );

}

MailList MailList::fromMimeData( const QMimeData *md )
{
  if ( canDecode(md) ) {
    return decode( md->data( mimeDataType() ) );
  } else {
    return MailList();
  }
}

MailList MailList::decode( const QByteArray& payload )
{
  MailList mailList;
  // A read-only data stream
  QDataStream stream( payload );
  if ( payload.size() ) {
    stream >> mailList;
  }
  return mailList;
}

QByteArray MailList::serialsFromMimeData( const QMimeData *md )
{
  MailList mailList = fromMimeData( md );
  if ( mailList.count() ) {
    MailList::iterator it;
    QByteArray a;
    QBuffer buffer( &a );
    buffer.open( QIODevice::WriteOnly );
    QDataStream stream( &buffer );
    for (it = mailList.begin(); it != mailList.end(); ++it) {
      MailSummary mailDrag = *it;
      stream << mailDrag.serialNumber();
    }
    buffer.close();
    return a;
  } else {
    return QByteArray();
  }
}

<|endoftext|>


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

#include <geometry_msgs/Twist.h>

#include <tf/transform_broadcaster.h>

#include <boost/bind.hpp>
#include <boost/lambda/lambda.hpp>

#include <sys/time.h>

#include "Comm.h"

#include <sensor_msgs/Imu.h>
#include <std_srvs/Trigger.h>

#include <stdexcept>

class CheckSumError : public std::logic_error {
public:
    CheckSumError(const std::string &data) :
        std::logic_error("Received the Invalid IMU Data: " + data)
    {
    }
};

float deg_to_rad(float deg) {
    return deg / 180.0f * M_PI;
}

float rad_to_deg(float rad){
    return rad * 180.0f / M_PI;
}

template<class T>
bool isInRange(T value, T max, T min){
    return (value >= min) && (value <= max);
}

struct ImuData {
    double angular_deg[3];
		bool flag;

    ImuData(){
        for(int i=0; i < 2; i++){
            angular_deg[i] = 0;
        }
    }
};

// 角度ごとにURGのデータを送信するためのサービス
class IMU {
private:
    ros::Publisher imu_pub_;
    ros::ServiceServer reset_service_;
    ros::ServiceServer carivrate_service_;
    CComm* usb_;
    double gyro_unit_;
    double acc_unit_;
    std::string port_name_, imu_frame_;
    int   baudrate_;
    ros::Rate loop_rate_;
    int  z_axis_dir_;
    int  y_axis_dir_;

    ImuData getImuData(){
        ImuData data;
        char command[2] = {0};
        char command2[50] = {0};
        char temp[6];
        unsigned long int sum = 0;

        const float temp_unit = 0.00565;

        sprintf(command, "o");
        usb_->Send(command, strlen(command));
        ros::Duration(0.03).sleep();

        usb_->Recv(command2, 50);
        ROS_INFO_STREAM("recv = " << command2);

        if (command2[0] == '\0') {
        	data.flag = false;
        	return data;
        }
        data.flag = true;

        memmove(temp,command2,4);
        sum = sum ^ ((short)strtol(temp, NULL, 16));
        data.angular_deg[0] = ((short)strtol(temp, NULL, 16)) * gyro_unit_;
        memmove(temp,command2+4,4);
        sum = sum ^ ((short)strtol(temp, NULL, 16));
        data.angular_deg[1] = std::asin(((short)strtol(temp, NULL, 16)) * acc_unit) * y_axis_dir_;
        memmove(temp,command2+8,4);
        sum = sum ^ ((short)strtol(temp, NULL, 16));
        data.angular_deg[2] = ((short)strtol(temp, NULL, 16)) * gyro_unit_ * z_axis_dir_;

        memmove(temp,command2+12,4);

        if(sum != ((short)strtol(temp, NULL, 16))){
            ROS_ERROR_STREAM("Recv Checksum: " << ((short)strtol(temp, NULL, 16)));
            ROS_ERROR_STREAM("Calculate Checksum: " << sum);
            throw CheckSumError(command2);
        }
        //while(data.angular_deg[2] < -180) data.angular_deg[2] += 180;
        //while(data.angular_deg[2] > 180) data.angular_deg[2] -= 180;

        return data;
    }

public:
    bool resetCallback(std_srvs::Trigger::Request  &req,
            std_srvs::Trigger::Response &res)
    {
        char command[2] = {0};
        sprintf(command, "0");
        usb_->Send(command, strlen(command));
        sleep(1);
        std::cout << "Gyro 0 Reset" << std::endl;
        res.success = true;
        res.message = "Successful reset angle, gyro angle be zero right now.";

        return true;
    }

    bool caribrateCallback(std_srvs::Trigger::Request  &req,
            std_srvs::Trigger::Response &res)
    {
        char command[2] = {0};
        std::cout << "Calibration" << std::endl;
        sprintf(command, "a");
        usb_->Send(command, strlen(command));
        std::cout << "Calibrate start ";
        for(int i=0; i<8; ++i) {
            std::cout << ". ";
            sleep(1);
        }

        res.success = true;
        res.message = "ADIS driver is done with calibration.";
        ROS_INFO_STREAM(res.message);

        return true;
    }

    IMU(ros::NodeHandle node) :
        imu_pub_(node.advertise<sensor_msgs::Imu>("imu", 10)),
        reset_service_(node.advertiseService("imu_reset", &IMU::resetCallback, this)),
        carivrate_service_(node.advertiseService("imu_caribrate", &IMU::caribrateCallback, this)),
        geta(0), gyro_unit(0.00836181640625), acc_unit(0.0008192), init_angle(0.0),
        port_name("/dev/ttyUSB0"), baudrate(115200), loop_rate(50), z_axis_dir_(-1), y_axis_dir_(-1)
    {
        ros::NodeHandle private_nh("~");
        private_nh.getParam("port_name", port_name_);
        private_nh.param<std::string>("imu_frame", imu_frame_, imu_frame_);
        private_nh.param<double>("gyro_unit", gyro_unit_, gyro_unit_);
        private_nh.param<double>("acc_unit", acc_unit_, acc_unit_);
        private_nh.param<int>("baud_rate", baudrate_, baudrate_);
        private_nh.param<int>("z_axis_dir", z_axis_dir_, z_axis_dir_);
        private_nh.param<int>("y_axis_dir", y_axis_dir_, y_axis_dir_);

        usb = new CComm(port_name, baudrate);
    }

    bool init() {
        char command[2] = {0};
        char command2[101] = {0};
        //シリアルポートオープン
        if (!usb_->Open()) {
            std::cerr << "open error" << std::endl;
            return false;
        }
        std::cout << "device open success" << std::endl;
        sleep(1);
        //コンフィギュレーション キャリブレーション
        // if(m_calibration == true){
        std::cout << "Calibration" << std::endl;
        sprintf(command, "a");
        usb_->Send(command, strlen(command));
        std::cout << "send = " << command << std::endl;
        for(int i=0; i<8; ++i) {
            printf(". ");
            sleep(1);
        }
        // }
        //コンフィギュレーション リセット
        // if(m_reset == true){
        sprintf(command, "0");
        usb_->Send(command, strlen(command));        //送信
        std::cout << "send = " << command << std::endl;
        sleep(1);
        std::cout << "Gyro 0 Reset" << std::endl;
        // }
        usb_->Recv(command2, 100);        //空読み バッファクリアが効かない？
        usb_->ClearRecvBuf();                //バッファクリア
        return true;
    }

    void run() {
        double old_angular_z_deg = getImuData().angular_deg[2];
        double angular_z_deg = 0;
        unsigned short abnormal_count = 0;

        while (ros::ok()) {
            tf::Quaternion q;
            sensor_msgs::Imu output_msg;
            try{
                ImuData data = getImuData();
                if (data.flag == false){
                    usb_->Close();
                    if(!usb_->Open()) {
                        std::cerr << "reconnecting" << std::endl;
                    }
                }else{
                    output_msg.header.frame_id = imu_frame_;
                    output_msg.header.stamp = ros::Time::now();

                    // ROS_INFO_STREAM("x_deg = " << data.angular_deg[0]);
                    ROS_INFO_STREAM("y_deg = " << rad_to_deg(data.angular_deg[1]));
                    ROS_INFO_STREAM("z_deg = " << data.angular_deg[2]);

                    if(!isInRange(std::abs(old_angular_z_deg), 180.0, 165.0) && !isInRange(std::abs(data.angular_deg[2]), 180.0, 165.0) &&
                        std::abs(old_angular_z_deg - data.angular_deg[2]) > 40 && abnormal_count < 4){

                        ROS_WARN_STREAM("Angle change too large: z = " << data.angular_deg[2]);
                        ROS_WARN_STREAM("old_z = " << old_angular_z_deg);
                        abnormal_count++;
                        continue;
                    }else{
                        abnormal_count = 0;
                        angular_z_deg = data.angular_deg[2];
                    }

                    q = tf::createQuaternionFromRPY(data.angular_deg[1], 0.0, deg_to_rad(angular_z_deg));
                    tf::quaternionTFToMsg(q, output_msg.orientation);
                    imu_pub_.publish(output_msg);
                    old_angular_z_deg = angular_z_deg;

                }
            }catch(const CheckSumError &e){
                output_msg.header.stamp = ros::Time::now();
                ROS_ERROR_STREAM(e.what());
                continue;
            }

            ros::spinOnce();
            //loop_rate.sleep();
        }
    }
};

int main(int argc, char * argv[])
{
    ros::init(argc, argv, "imu_node");
    ros::NodeHandle node;
    IMU imu(node);
    if(!imu.init()) return 1;
    imu.run();

    return 0;
}
<commit_msg>Fix variable name<commit_after>#include <ros/ros.h>

#include <geometry_msgs/Twist.h>

#include <tf/transform_broadcaster.h>

#include <boost/bind.hpp>
#include <boost/lambda/lambda.hpp>

#include <sys/time.h>

#include "Comm.h"

#include <sensor_msgs/Imu.h>
#include <std_srvs/Trigger.h>

#include <stdexcept>

class CheckSumError : public std::logic_error {
public:
    CheckSumError(const std::string &data) :
        std::logic_error("Received the Invalid IMU Data: " + data)
    {
    }
};

float deg_to_rad(float deg) {
    return deg / 180.0f * M_PI;
}

float rad_to_deg(float rad){
    return rad * 180.0f / M_PI;
}

template<class T>
bool isInRange(T value, T max, T min){
    return (value >= min) && (value <= max);
}

struct ImuData {
    double angular_deg[3];
		bool flag;

    ImuData(){
        for(int i=0; i < 2; i++){
            angular_deg[i] = 0;
        }
    }
};

// 角度ごとにURGのデータを送信するためのサービス
class IMU {
private:
    ros::Publisher imu_pub_;
    ros::ServiceServer reset_service_;
    ros::ServiceServer carivrate_service_;
    CComm* usb_;
    double gyro_unit_;
    double acc_unit_;
    std::string port_name_, imu_frame_;
    int   baudrate_;
    ros::Rate loop_rate_;
    int  z_axis_dir_;
    int  y_axis_dir_;

    ImuData getImuData(){
        ImuData data;
        char command[2] = {0};
        char command2[50] = {0};
        char temp[6];
        unsigned long int sum = 0;

        const float temp_unit = 0.00565;

        sprintf(command, "o");
        usb_->Send(command, strlen(command));
        ros::Duration(0.03).sleep();

        usb_->Recv(command2, 50);
        ROS_INFO_STREAM("recv = " << command2);

        if (command2[0] == '\0') {
        	data.flag = false;
        	return data;
        }
        data.flag = true;

        memmove(temp,command2,4);
        sum = sum ^ ((short)strtol(temp, NULL, 16));
        data.angular_deg[0] = ((short)strtol(temp, NULL, 16)) * gyro_unit_;
        memmove(temp,command2+4,4);
        sum = sum ^ ((short)strtol(temp, NULL, 16));
        data.angular_deg[1] = std::asin(((short)strtol(temp, NULL, 16)) * acc_unit_) * y_axis_dir_;
        memmove(temp,command2+8,4);
        sum = sum ^ ((short)strtol(temp, NULL, 16));
        data.angular_deg[2] = ((short)strtol(temp, NULL, 16)) * gyro_unit_ * z_axis_dir_;

        memmove(temp,command2+12,4);

        if(sum != ((short)strtol(temp, NULL, 16))){
            ROS_ERROR_STREAM("Recv Checksum: " << ((short)strtol(temp, NULL, 16)));
            ROS_ERROR_STREAM("Calculate Checksum: " << sum);
            throw CheckSumError(command2);
        }
        //while(data.angular_deg[2] < -180) data.angular_deg[2] += 180;
        //while(data.angular_deg[2] > 180) data.angular_deg[2] -= 180;

        return data;
    }

public:
    bool resetCallback(std_srvs::Trigger::Request  &req,
            std_srvs::Trigger::Response &res)
    {
        char command[2] = {0};
        sprintf(command, "0");
        usb_->Send(command, strlen(command));
        sleep(1);
        std::cout << "Gyro 0 Reset" << std::endl;
        res.success = true;
        res.message = "Successful reset angle, gyro angle be zero right now.";

        return true;
    }

    bool caribrateCallback(std_srvs::Trigger::Request  &req,
            std_srvs::Trigger::Response &res)
    {
        char command[2] = {0};
        std::cout << "Calibration" << std::endl;
        sprintf(command, "a");
        usb_->Send(command, strlen(command));
        std::cout << "Calibrate start ";
        for(int i=0; i<8; ++i) {
            std::cout << ". ";
            sleep(1);
        }

        res.success = true;
        res.message = "ADIS driver is done with calibration.";
        ROS_INFO_STREAM(res.message);

        return true;
    }

    IMU(ros::NodeHandle node) :
        imu_pub_(node.advertise<sensor_msgs::Imu>("imu", 10)),
        reset_service_(node.advertiseService("imu_reset", &IMU::resetCallback, this)),
        carivrate_service_(node.advertiseService("imu_caribrate", &IMU::caribrateCallback, this)),
        gyro_unit_(0.00836181640625), acc_unit_(0.0008192),
        port_name_("/dev/ttyUSB0"), baudrate_(115200), loop_rate_(50), z_axis_dir_(-1), y_axis_dir_(-1)
    {
        ros::NodeHandle private_nh("~");
        private_nh.getParam("port_name", port_name_);
        private_nh.param<std::string>("imu_frame", imu_frame_, imu_frame_);
        private_nh.param<double>("gyro_unit", gyro_unit_, gyro_unit_);
        private_nh.param<double>("acc_unit", acc_unit_, acc_unit_);
        private_nh.param<int>("baud_rate", baudrate_, baudrate_);
        private_nh.param<int>("z_axis_dir", z_axis_dir_, z_axis_dir_);
        private_nh.param<int>("y_axis_dir", y_axis_dir_, y_axis_dir_);

        usb_ = new CComm(port_name_, baudrate_);
    }

    bool init() {
        char command[2] = {0};
        char command2[101] = {0};
        //シリアルポートオープン
        if (!usb_->Open()) {
            std::cerr << "open error" << std::endl;
            return false;
        }
        std::cout << "device open success" << std::endl;
        sleep(1);
        //コンフィギュレーション キャリブレーション
        // if(m_calibration == true){
        std::cout << "Calibration" << std::endl;
        sprintf(command, "a");
        usb_->Send(command, strlen(command));
        std::cout << "send = " << command << std::endl;
        for(int i=0; i<8; ++i) {
            printf(". ");
            sleep(1);
        }
        // }
        //コンフィギュレーション リセット
        // if(m_reset == true){
        sprintf(command, "0");
        usb_->Send(command, strlen(command));        //送信
        std::cout << "send = " << command << std::endl;
        sleep(1);
        std::cout << "Gyro 0 Reset" << std::endl;
        // }
        usb_->Recv(command2, 100);        //空読み バッファクリアが効かない？
        usb_->ClearRecvBuf();                //バッファクリア
        return true;
    }

    void run() {
        double old_angular_z_deg = getImuData().angular_deg[2];
        double angular_z_deg = 0;
        unsigned short abnormal_count = 0;

        while (ros::ok()) {
            tf::Quaternion q;
            sensor_msgs::Imu output_msg;
            try{
                ImuData data = getImuData();
                if (data.flag == false){
                    usb_->Close();
                    if(!usb_->Open()) {
                        std::cerr << "reconnecting" << std::endl;
                    }
                }else{
                    output_msg.header.frame_id = imu_frame_;
                    output_msg.header.stamp = ros::Time::now();

                    // ROS_INFO_STREAM("x_deg = " << data.angular_deg[0]);
                    ROS_INFO_STREAM("y_deg = " << rad_to_deg(data.angular_deg[1]));
                    ROS_INFO_STREAM("z_deg = " << data.angular_deg[2]);

                    if(!isInRange(std::abs(old_angular_z_deg), 180.0, 165.0) && !isInRange(std::abs(data.angular_deg[2]), 180.0, 165.0) &&
                        std::abs(old_angular_z_deg - data.angular_deg[2]) > 40 && abnormal_count < 4){

                        ROS_WARN_STREAM("Angle change too large: z = " << data.angular_deg[2]);
                        ROS_WARN_STREAM("old_z = " << old_angular_z_deg);
                        abnormal_count++;
                        continue;
                    }else{
                        abnormal_count = 0;
                        angular_z_deg = data.angular_deg[2];
                    }

                    q = tf::createQuaternionFromRPY(data.angular_deg[1], 0.0, deg_to_rad(angular_z_deg));
                    tf::quaternionTFToMsg(q, output_msg.orientation);
                    imu_pub_.publish(output_msg);
                    old_angular_z_deg = angular_z_deg;

                }
            }catch(const CheckSumError &e){
                output_msg.header.stamp = ros::Time::now();
                ROS_ERROR_STREAM(e.what());
                continue;
            }

            ros::spinOnce();
            //loop_rate.sleep();
        }
    }
};

int main(int argc, char * argv[])
{
    ros::init(argc, argv, "imu_node");
    ros::NodeHandle node;
    IMU imu(node);
    if(!imu.init()) return 1;
    imu.run();

    return 0;
}
<|endoftext|>