<commit_before>// Ouzel by Elviss Strazdins

#ifndef OUZEL_SCENE_CAMERA_HPP
#define OUZEL_SCENE_CAMERA_HPP

#include <memory>
#include "Component.hpp"
#include "../math/Constants.hpp"
#include "../math/Matrix.hpp"
#include "../math/Rect.hpp"
#include "../graphics/DepthStencilState.hpp"
#include "../graphics/RenderTarget.hpp"

namespace ouzel::scene
{
    class Layer;

    class Camera: public Component
    {
        friend Layer;
    public:
        enum class ProjectionMode
        {
            custom,
            orthographic,
            perspective
        };

        enum class ScaleMode
        {
            noScale,
            exactFit,
            noBorder,
            showAll
        };

        explicit Camera(const math::Matrix<float, 4>& initProjection);
        explicit Camera(const math::Size<float, 2>& initTargetContentSize = math::Size<float, 2>{}, ScaleMode initScaleMode = ScaleMode::noScale);
        explicit Camera(float initFov, float initNearPlane = 1.0F, float initFarPlane = 100.0F);
        ~Camera() override;

        [[nodiscard]] auto getProjectionMode() const noexcept { return projectionMode; }
        void setProjectionMode(ProjectionMode newProjectionMode) { projectionMode = newProjectionMode; }

        [[nodiscard]] auto getFov() const noexcept { return fov; }
        void setFov(float newFov) { fov = newFov; }

        [[nodiscard]] auto getNearPlane() const noexcept { return nearPlane; }
        void setNearPlane(float newNearPlane) { nearPlane = newNearPlane; }

        [[nodiscard]] auto getFarPlane() const noexcept { return farPlane; }
        void setFarPlane(float newFarPlane) { farPlane = newFarPlane; }

        [[nodiscard]] auto& getProjection() const noexcept { return projection; }
        void setProjection(const math::Matrix<float, 4>& newProjection) { projection = newProjection; }
        void recalculateProjection();

        const math::Matrix<float, 4>& getViewProjection() const;
        const math::Matrix<float, 4>& getRenderViewProjection() const;
        const math::Matrix<float, 4>& getInverseViewProjection() const;

        math::Vector<float, 3> convertNormalizedToWorld(const math::Vector<float, 2>& normalizedPosition) const;
        math::Vector<float, 2> convertWorldToNormalized(const math::Vector<float, 3>& worldPosition) const;

        bool checkVisibility(const math::Matrix<float, 4>& boxTransform, const math::Box<float, 3>& box) const;

        [[nodiscard]] auto& getViewport() const noexcept { return viewport; }
        [[nodiscard]] auto& getRenderViewport() const noexcept { return renderViewport; }
        void setViewport(const math::Rect<float>& newViewport);

        [[nodiscard]] auto getScaleMode() const noexcept { return scaleMode; }
        void setScaleMode(ScaleMode newScaleMode);

        [[nodiscard]] auto& getTargetContentSize() const noexcept { return targetContentSize; }
        void setTargetContentSize(const math::Size<float, 2>& newTargetContentSize);

        [[nodiscard]] auto& getContentSize() const noexcept { return contentSize; }
        [[nodiscard]] auto& getContentScale() const noexcept { return contentScale; }
        [[nodiscard]] auto& getContentPosition() const noexcept { return contentPosition; }

        [[nodiscard]] auto getRenderTarget() const noexcept { return renderTarget; }
        void setRenderTarget(graphics::RenderTarget* newRenderTarget);

        [[nodiscard]] auto getDepthTest() const noexcept { return depthTest; }
        void setDepthTest(bool newDepthTest);
        [[nodiscard]] auto& getDepthStencilState() const noexcept { return depthStencilState; }

        [[nodiscard]] auto getStencilReferenceValue() const noexcept { return stencilReferenceValue; }
        void setStencilReferenceValue(std::uint32_t newStencilReferenceValue) { stencilReferenceValue = newStencilReferenceValue; }

        [[nodiscard]] auto getWireframe() const noexcept { return wireframe; }
        void setWireframe(bool newWireframe) { wireframe = newWireframe; }

        [[nodiscard]] auto getClearColorBuffer() const noexcept { return clearColorBuffer; }
        void setClearColorBuffer(bool clear) { clearColorBuffer = clear; }

        [[nodiscard]] auto getClearDepthBuffer() const noexcept { return clearDepthBuffer; }
        void setClearDepthBuffer(bool clear) { clearDepthBuffer = clear; }

        [[nodiscard]] auto getClearStencilBuffer() const noexcept { return clearStencilBuffer; }
        void setClearStencilBuffer(bool clear) { clearStencilBuffer = clear; }

        [[nodiscard]] auto getClearColor() const noexcept { return clearColor; }
        void setClearColor(math::Color color) { clearColor = color; }

        [[nodiscard]] auto getClearDepth() const noexcept { return clearDepth; }
        void setClearDepth(float depth) { clearDepth = depth; }

        [[nodiscard]] auto getClearStencil() const noexcept { return clearStencil; }
        void setClearDepth(std::uint32_t stencil) { clearStencil = stencil; }

    private:
        void setActor(Actor* newActor) override;
        void setLayer(Layer* newLayer) override;

        void updateTransform() override;
        void calculateViewProjection() const;

        ProjectionMode projectionMode;
        float fov = math::tau<float> / 6.0F;
        float nearPlane = 1.0F;
        float farPlane = 100.0F;

        math::Matrix<float, 4> projection;

        math::Rect<float> viewport = math::Rect<float>{0.0F, 0.0F, 1.0F, 1.0F};
        math::Rect<float> renderViewport;
        math::Size<float, 2> targetContentSize;

        ScaleMode scaleMode = ScaleMode::noScale;
        math::Size<float, 2> contentSize{};
        math::Vector<float, 2> contentScale{};
        math::Vector<float, 2> contentPosition{};

        bool depthTest = false;
        bool wireframe = false;

        mutable bool viewProjectionDirty = true;
        mutable math::Matrix<float, 4> viewProjection;
        mutable math::Matrix<float, 4> renderViewProjection;

        mutable bool inverseViewProjectionDirty = true;
        mutable math::Matrix<float, 4> inverseViewProjection;

        graphics::RenderTarget* renderTarget = nullptr;
        std::unique_ptr<graphics::DepthStencilState> depthStencilState;
        std::uint32_t stencilReferenceValue = 0;

        bool clearColorBuffer = false;
        bool clearDepthBuffer = false;
        bool clearStencilBuffer = false;
        math::Color clearColor;
        float clearDepth = 1.0F;
        std::uint32_t clearStencil = 0;
    };
}

#endif // OUZEL_SCENE_CAMERA_HPP
<commit_msg>Recalculate projection on projection parameter change<commit_after>// Ouzel by Elviss Strazdins

#ifndef OUZEL_SCENE_CAMERA_HPP
#define OUZEL_SCENE_CAMERA_HPP

#include <memory>
#include "Component.hpp"
#include "../math/Constants.hpp"
#include "../math/Matrix.hpp"
#include "../math/Rect.hpp"
#include "../graphics/DepthStencilState.hpp"
#include "../graphics/RenderTarget.hpp"

namespace ouzel::scene
{
    class Layer;

    class Camera: public Component
    {
        friend Layer;
    public:
        enum class ProjectionMode
        {
            custom,
            orthographic,
            perspective
        };

        enum class ScaleMode
        {
            noScale,
            exactFit,
            noBorder,
            showAll
        };

        explicit Camera(const math::Matrix<float, 4>& initProjection);
        explicit Camera(const math::Size<float, 2>& initTargetContentSize = math::Size<float, 2>{}, ScaleMode initScaleMode = ScaleMode::noScale);
        explicit Camera(float initFov, float initNearPlane = 1.0F, float initFarPlane = 100.0F);
        ~Camera() override;

        [[nodiscard]] auto getProjectionMode() const noexcept { return projectionMode; }
        void setProjectionMode(ProjectionMode newProjectionMode)
        {
            projectionMode = newProjectionMode;
            recalculateProjection();
        }

        [[nodiscard]] auto getFov() const noexcept { return fov; }
        void setFov(float newFov)
        {
            fov = newFov;
            recalculateProjection();
        }

        [[nodiscard]] auto getNearPlane() const noexcept { return nearPlane; }
        void setNearPlane(float newNearPlane)
        {
            nearPlane = newNearPlane;
            recalculateProjection();
        }

        [[nodiscard]] auto getFarPlane() const noexcept { return farPlane; }
        void setFarPlane(float newFarPlane)
        {
            farPlane = newFarPlane;
            recalculateProjection();
        }

        [[nodiscard]] auto& getProjection() const noexcept { return projection; }
        void setProjection(const math::Matrix<float, 4>& newProjection)
        {
            projection = newProjection;
            recalculateProjection();
        }
        void recalculateProjection();

        const math::Matrix<float, 4>& getViewProjection() const;
        const math::Matrix<float, 4>& getRenderViewProjection() const;
        const math::Matrix<float, 4>& getInverseViewProjection() const;

        math::Vector<float, 3> convertNormalizedToWorld(const math::Vector<float, 2>& normalizedPosition) const;
        math::Vector<float, 2> convertWorldToNormalized(const math::Vector<float, 3>& worldPosition) const;

        bool checkVisibility(const math::Matrix<float, 4>& boxTransform, const math::Box<float, 3>& box) const;

        [[nodiscard]] auto& getViewport() const noexcept { return viewport; }
        void setViewport(const math::Rect<float>& newViewport);
        [[nodiscard]] auto& getRenderViewport() const noexcept { return renderViewport; }

        [[nodiscard]] auto getScaleMode() const noexcept { return scaleMode; }
        void setScaleMode(ScaleMode newScaleMode);

        [[nodiscard]] auto& getTargetContentSize() const noexcept { return targetContentSize; }
        void setTargetContentSize(const math::Size<float, 2>& newTargetContentSize);

        [[nodiscard]] auto& getContentSize() const noexcept { return contentSize; }
        [[nodiscard]] auto& getContentScale() const noexcept { return contentScale; }
        [[nodiscard]] auto& getContentPosition() const noexcept { return contentPosition; }

        [[nodiscard]] auto getRenderTarget() const noexcept { return renderTarget; }
        void setRenderTarget(graphics::RenderTarget* newRenderTarget);

        [[nodiscard]] auto getDepthTest() const noexcept { return depthTest; }
        void setDepthTest(bool newDepthTest);
        [[nodiscard]] auto& getDepthStencilState() const noexcept { return depthStencilState; }

        [[nodiscard]] auto getStencilReferenceValue() const noexcept { return stencilReferenceValue; }
        void setStencilReferenceValue(std::uint32_t newStencilReferenceValue) { stencilReferenceValue = newStencilReferenceValue; }

        [[nodiscard]] auto getWireframe() const noexcept { return wireframe; }
        void setWireframe(bool newWireframe) { wireframe = newWireframe; }

        [[nodiscard]] auto getClearColorBuffer() const noexcept { return clearColorBuffer; }
        void setClearColorBuffer(bool clear) { clearColorBuffer = clear; }

        [[nodiscard]] auto getClearDepthBuffer() const noexcept { return clearDepthBuffer; }
        void setClearDepthBuffer(bool clear) { clearDepthBuffer = clear; }

        [[nodiscard]] auto getClearStencilBuffer() const noexcept { return clearStencilBuffer; }
        void setClearStencilBuffer(bool clear) { clearStencilBuffer = clear; }

        [[nodiscard]] auto getClearColor() const noexcept { return clearColor; }
        void setClearColor(math::Color color) { clearColor = color; }

        [[nodiscard]] auto getClearDepth() const noexcept { return clearDepth; }
        void setClearDepth(float depth) { clearDepth = depth; }

        [[nodiscard]] auto getClearStencil() const noexcept { return clearStencil; }
        void setClearDepth(std::uint32_t stencil) { clearStencil = stencil; }

    private:
        void setActor(Actor* newActor) override;
        void setLayer(Layer* newLayer) override;

        void updateTransform() override;
        void calculateViewProjection() const;

        ProjectionMode projectionMode;
        float fov = math::tau<float> / 6.0F;
        float nearPlane = 1.0F;
        float farPlane = 100.0F;

        math::Matrix<float, 4> projection;

        math::Rect<float> viewport = math::Rect<float>{0.0F, 0.0F, 1.0F, 1.0F};
        math::Rect<float> renderViewport;
        math::Size<float, 2> targetContentSize;

        ScaleMode scaleMode = ScaleMode::noScale;
        math::Size<float, 2> contentSize{};
        math::Vector<float, 2> contentScale{};
        math::Vector<float, 2> contentPosition{};

        bool depthTest = false;
        bool wireframe = false;

        mutable bool viewProjectionDirty = true;
        mutable math::Matrix<float, 4> viewProjection;
        mutable math::Matrix<float, 4> renderViewProjection;

        mutable bool inverseViewProjectionDirty = true;
        mutable math::Matrix<float, 4> inverseViewProjection;

        graphics::RenderTarget* renderTarget = nullptr;
        std::unique_ptr<graphics::DepthStencilState> depthStencilState;
        std::uint32_t stencilReferenceValue = 0;

        bool clearColorBuffer = false;
        bool clearDepthBuffer = false;
        bool clearStencilBuffer = false;
        math::Color clearColor;
        float clearDepth = 1.0F;
        std::uint32_t clearStencil = 0;
    };
}

#endif // OUZEL_SCENE_CAMERA_HPP
<|endoftext|>


<commit_before>/*
	Flexisip, a flexible SIP proxy server with media capabilities.
    Copyright (C) 2010  Belledonne Communications SARL.

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

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

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "agent.hh"
#include "mediarelay.hh"

#include <poll.h>

#include <algorithm>
#include <list>

using namespace::std;

int MediaSource::recv(uint8_t *buf, size_t buflen){
	slen=sizeof(ss);
	int err=recvfrom(fd,buf,buflen,0,(struct sockaddr*)&ss,&slen);
	if (err==-1) slen=0;
	return err;
}

int MediaSource::send(uint8_t *buf, size_t buflen){
	int err;
	if (slen>0){
		err=sendto(fd,buf,buflen,0,(struct sockaddr*)&ss,slen);
		return err;
	}
	return 0;
}

RelaySession::RelaySession(const std::string &localip) : mLocalIp(localip){
	mLastActivityTime=0;
	mSession[0]=rtp_session_new(RTP_SESSION_SENDRECV);
	mSession[1]=rtp_session_new(RTP_SESSION_SENDRECV);
	rtp_session_set_local_addr(mSession[0],mLocalIp.c_str(),-1);
	rtp_session_set_local_addr(mSession[1],mLocalIp.c_str(),-1);
	mSources[0].fd=rtp_session_get_rtp_socket(mSession[0]);
	mSources[1].fd=rtp_session_get_rtp_socket(mSession[1]);
	mSources[2].fd=rtp_session_get_rtcp_socket(mSession[0]);
	mSources[3].fd=rtp_session_get_rtcp_socket(mSession[1]);
	mUsed=true;
}

RelaySession::~RelaySession(){
	rtp_session_destroy(mSession[0]);
	rtp_session_destroy(mSession[1]);
}

int RelaySession::getPorts(int ports[2])const{
	ports[0]=rtp_session_get_local_port(mSession[0]);
	ports[1]=rtp_session_get_local_port(mSession[1]);
	if (ports[0]==-1 || ports[1]==-1)
		return -1;
	return 0;
}

const std::string & RelaySession::getAddr()const{
	return mLocalIp;
}

void RelaySession::unuse(){
	mUsed=false;
}

void RelaySession::fillPollFd(struct pollfd *tab){
	int i;
	for(i=0;i<4;++i){
		tab[i].fd=mSources[i].fd;
		tab[i].events=POLLIN;
		tab[i].revents=0;
	}
}

void RelaySession::transfer(time_t curtime, struct pollfd *tab){
	uint8_t buf[1500];
	const int maxsize=sizeof(buf);
	int len;
	int i;

	if (mLastActivityTime==0)
		mLastActivityTime=curtime;

	for (i=0;i<4;i+=2){
		if (tab[i].revents & POLLIN){
			len=mSources[i].recv(buf,maxsize);
			if (len>0)
				mSources[i+1].send(buf,len);
			mLastActivityTime=curtime;
		}
		if (tab[i+1].revents & POLLIN){
			mLastActivityTime=curtime;
			len=mSources[i+1].recv(buf,maxsize);
			if (len>0)
				mSources[i].send(buf,len);
		}
	}
}

MediaRelayServer::MediaRelayServer(const std::string &localip) : mLocalIp(localip){
	mRunning=true;
	if (pipe(mCtlPipe)==-1){
		LOGF("Could not create MediaRelayServer control pipe.");
	}
	pthread_create(&mThread,NULL,&MediaRelayServer::threadFunc,this);
}

MediaRelayServer::~MediaRelayServer(){
	mRunning=false;
	if (write(mCtlPipe[1],"e",1)==-1)
		LOGE("MediaRelayServer: Fail to write to control pipe.");
	pthread_join(mThread,NULL);
	for_each(mSessions.begin(),mSessions.end(),delete_functor<RelaySession>());
	close(mCtlPipe[0]);
	close(mCtlPipe[1]);
}

RelaySession *MediaRelayServer::createSession(){
	RelaySession *s=new RelaySession(mLocalIp);
	int count;
	mMutex.lock();
	mSessions.push_back(s);
	count=mSessions.size();
	mMutex.unlock();
	LOGD("There are now %i relay sessions running.",count);
	/*write to the control pipe to wakeup the server thread */
	if (write(mCtlPipe[1],"e",1)==-1)
		LOGE("MediaRelayServer: fail to write to control pipe.");
	return s;
}

void MediaRelayServer::run(){
	int sessionCount;
	int i;
	struct pollfd *pfds;
	list<RelaySession*>::iterator it;
	int err;

	while(mRunning){
		mMutex.lock();
		sessionCount=mSessions.size();
		mMutex.unlock();
		pfds=(struct pollfd*)alloca((sessionCount*4) + 1);
		for(i=0,it=mSessions.begin();i<sessionCount;++i,++it){
			(*it)->fillPollFd(&pfds[i*4]);
		}

		pfds[sessionCount*4].fd=mCtlPipe[0];
		pfds[sessionCount*4].events=POLLIN;
		pfds[sessionCount*4].revents=0;

		err=poll(pfds,(sessionCount*4 )+ 1,-1);
		if (pfds[sessionCount*4].revents){
			char tmp;
			if (read(mCtlPipe[0],&tmp,1)==-1){
				LOGE("Fail to read from control pipe.");
			}
		}
		time_t curtime=time(NULL);
		for(i=0,it=mSessions.begin();i<sessionCount;++i,++it){
			RelaySession *s=(*it);
			if (s->isUsed()){
				s->transfer(curtime,&pfds[i*4]);
			}
		}
		/*cleanup loop*/
		mMutex.lock();
		for(it=mSessions.begin();it!=mSessions.end();){
			if (!(*it)->isUsed()){
				delete *it;
				it=mSessions.erase(it);
			}else{
				++it;
			}
		}
		mMutex.unlock();
	}
}

void *MediaRelayServer::threadFunc(void *arg){
	MediaRelayServer *zis=(MediaRelayServer*)arg;
	zis->run();
	return NULL;
}
<commit_msg>fix stack overflow<commit_after>/*
	Flexisip, a flexible SIP proxy server with media capabilities.
    Copyright (C) 2010  Belledonne Communications SARL.

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

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

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "agent.hh"
#include "mediarelay.hh"

#include <poll.h>

#include <algorithm>
#include <list>

using namespace::std;

int MediaSource::recv(uint8_t *buf, size_t buflen){
	slen=sizeof(ss);
	int err=recvfrom(fd,buf,buflen,0,(struct sockaddr*)&ss,&slen);
	if (err==-1) slen=0;
	return err;
}

int MediaSource::send(uint8_t *buf, size_t buflen){
	int err;
	if (slen>0){
		err=sendto(fd,buf,buflen,0,(struct sockaddr*)&ss,slen);
		return err;
	}
	return 0;
}

RelaySession::RelaySession(const std::string &localip) : mLocalIp(localip){
	mLastActivityTime=0;
	mSession[0]=rtp_session_new(RTP_SESSION_SENDRECV);
	mSession[1]=rtp_session_new(RTP_SESSION_SENDRECV);
	rtp_session_set_local_addr(mSession[0],mLocalIp.c_str(),-1);
	rtp_session_set_local_addr(mSession[1],mLocalIp.c_str(),-1);
	mSources[0].fd=rtp_session_get_rtp_socket(mSession[0]);
	mSources[1].fd=rtp_session_get_rtp_socket(mSession[1]);
	mSources[2].fd=rtp_session_get_rtcp_socket(mSession[0]);
	mSources[3].fd=rtp_session_get_rtcp_socket(mSession[1]);
	mUsed=true;
}

RelaySession::~RelaySession(){
	rtp_session_destroy(mSession[0]);
	rtp_session_destroy(mSession[1]);
}

int RelaySession::getPorts(int ports[2])const{
	ports[0]=rtp_session_get_local_port(mSession[0]);
	ports[1]=rtp_session_get_local_port(mSession[1]);
	if (ports[0]==-1 || ports[1]==-1)
		return -1;
	return 0;
}

const std::string & RelaySession::getAddr()const{
	return mLocalIp;
}

void RelaySession::unuse(){
	mUsed=false;
}

void RelaySession::fillPollFd(struct pollfd *tab){
	int i;
	for(i=0;i<4;++i){
		tab[i].fd=mSources[i].fd;
		tab[i].events=POLLIN;
		tab[i].revents=0;
	}
}

void RelaySession::transfer(time_t curtime, struct pollfd *tab){
	uint8_t buf[1500];
	const int maxsize=sizeof(buf);
	int len;
	int i;

	if (mLastActivityTime==0)
		mLastActivityTime=curtime;

	for (i=0;i<4;i+=2){
		if (tab[i].revents & POLLIN){
			len=mSources[i].recv(buf,maxsize);
			if (len>0)
				mSources[i+1].send(buf,len);
			mLastActivityTime=curtime;
		}
		if (tab[i+1].revents & POLLIN){
			mLastActivityTime=curtime;
			len=mSources[i+1].recv(buf,maxsize);
			if (len>0)
				mSources[i].send(buf,len);
		}
	}
}

MediaRelayServer::MediaRelayServer(const std::string &localip) : mLocalIp(localip){
	mRunning=true;
	if (pipe(mCtlPipe)==-1){
		LOGF("Could not create MediaRelayServer control pipe.");
	}
	pthread_create(&mThread,NULL,&MediaRelayServer::threadFunc,this);
}

MediaRelayServer::~MediaRelayServer(){
	mRunning=false;
	if (write(mCtlPipe[1],"e",1)==-1)
		LOGE("MediaRelayServer: Fail to write to control pipe.");
	pthread_join(mThread,NULL);
	for_each(mSessions.begin(),mSessions.end(),delete_functor<RelaySession>());
	close(mCtlPipe[0]);
	close(mCtlPipe[1]);
}

RelaySession *MediaRelayServer::createSession(){
	RelaySession *s=new RelaySession(mLocalIp);
	int count;
	mMutex.lock();
	mSessions.push_back(s);
	count=mSessions.size();
	mMutex.unlock();
	LOGD("There are now %i relay sessions running.",count);
	/*write to the control pipe to wakeup the server thread */
	if (write(mCtlPipe[1],"e",1)==-1)
		LOGE("MediaRelayServer: fail to write to control pipe.");
	return s;
}

void MediaRelayServer::run(){
	int sessionCount;
	int i;
	struct pollfd *pfds=NULL;
	list<RelaySession*>::iterator it;
	int err;
	int pfds_size=0,cur_pfds_size=0;

	while(mRunning){
		mMutex.lock();
		sessionCount=mSessions.size();
		mMutex.unlock();
		pfds_size=(sessionCount*4)+1;
		if (pfds_size>cur_pfds_size){
			pfds=(struct pollfd*)realloc(pfds,pfds_size);
			cur_pfds_size=pfds_size;
		}
		for(i=0,it=mSessions.begin();i<sessionCount;++i,++it){
			(*it)->fillPollFd(&pfds[i*4]);
		}

		pfds[sessionCount*4].fd=mCtlPipe[0];
		pfds[sessionCount*4].events=POLLIN;
		pfds[sessionCount*4].revents=0;

		err=poll(pfds,(sessionCount*4 )+ 1,-1);
		if (pfds[sessionCount*4].revents){
			char tmp;
			if (read(mCtlPipe[0],&tmp,1)==-1){
				LOGE("Fail to read from control pipe.");
			}
		}
		time_t curtime=time(NULL);
		for(i=0,it=mSessions.begin();i<sessionCount;++i,++it){
			RelaySession *s=(*it);
			if (s->isUsed()){
				s->transfer(curtime,&pfds[i*4]);
			}
		}
		/*cleanup loop*/
		mMutex.lock();
		for(it=mSessions.begin();it!=mSessions.end();){
			if (!(*it)->isUsed()){
				delete *it;
				it=mSessions.erase(it);
			}else{
				++it;
			}
		}
		mMutex.unlock();
	}
	if (pfds) free(pfds);
}

void *MediaRelayServer::threadFunc(void *arg){
	MediaRelayServer *zis=(MediaRelayServer*)arg;
	zis->run();
	return NULL;
}
<|endoftext|>


<commit_before>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2009 Sage Weil <sage@newdream.net>
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

using namespace std;

#include "common/config.h"
#include "common/strtol.h"

#include "common/ConfUtils.h"
#include "common/ceph_argparse.h"
#include "global/global_context.h"
#include "global/global_init.h"
#include "auth/Crypto.h"
#include "auth/Auth.h"
#include "auth/KeyRing.h"

#include <sstream>

void usage()
{
  cout << "usage: ceph-authtool keyringfile [OPTIONS]...\n"
       << "where the options are:\n"
       << "  -l, --list                    will list all keys and capabilities present in\n"
       << "                                the keyring\n"
       << "  -p, --print                   will print an encoded key for the specified\n"
       << "                                entityname. This is suitable for the\n"
       << "                                'mount -o secret=..' argument\n"
       << "  -C, --create-keyring          will create a new keyring, overwriting any\n"
       << "                                existing keyringfile\n"
       << "  --gen-key                     will generate a new secret key for the\n"
       << "                                specified entityname\n"
       << "  --add-key                     will add an encoded key to the keyring\n"
       << "  --cap subsystem capability    will set the capability for given subsystem\n"
       << "  --caps capsfile               will set all of capabilities associated with a\n"
       << "                                given key, for all subsystems\n"
       << "  -b, --bin                     will create a binary formatted keyring" << std::endl;
  exit(1);
}

int main(int argc, const char **argv)
{
  vector<const char*> args;
  argv_to_vec(argc, argv, args);
  env_to_vec(args);

  bool gen_key = false;
  bool gen_print_key = false;
  std::string add_key;
  bool list = false;
  bool print_key = false;
  bool create_keyring = false;
  std::string caps_fn;
  std::string import_keyring;
  bool set_auid = false;
  uint64_t auid = CEPH_AUTH_UID_DEFAULT;
  map<string,bufferlist> caps;
  bool bin_keyring = false;
  std::string fn;

  global_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY,
	      CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
  std::vector<const char*>::iterator i;
  for (i = args.begin(); i != args.end(); ) {
    std::string val;
    if (ceph_argparse_double_dash(args, i)) {
      break;
    } else if (ceph_argparse_flag(args, i, "-g", "--gen-key", (char*)NULL)) {
      gen_key = true;
    } else if (ceph_argparse_flag(args, i, "--gen-print-key", (char*)NULL)) {
      gen_print_key = true;
    } else if (ceph_argparse_witharg(args, i, &val, "-a", "--add-key", (char*)NULL)) {
      add_key = val;
    } else if (ceph_argparse_flag(args, i, &val, "-l", "--list", (char*)NULL)) {
      list = true;
    } else if (ceph_argparse_witharg(args, i, &val, "--caps", (char*)NULL)) {
      caps_fn = val;
    } else if (ceph_argparse_witharg(args, i, &val, "--cap", (char*)NULL)) {
      std::string my_key = val;
      if (i == args.end()) {
	cerr << "must give two arguments to --cap: key and val." << std::endl;
	exit(1);
      }
      std::string my_val = *i;
      ++i;
      ::encode(my_val, caps[my_key]);
    } else if (ceph_argparse_flag(args, i, "-p", "--print-key", (char*)NULL)) {
      print_key = true;
    } else if (ceph_argparse_flag(args, i, "-C", "--create-keyring", (char*)NULL)) {
      create_keyring = true;
    } else if (ceph_argparse_witharg(args, i, &val, "--import-keyring", (char*)NULL)) {
      import_keyring = val;
    } else if (ceph_argparse_witharg(args, i, &val, "-u", "--set-uid", (char*)NULL)) {
      std::string err;
      auid = strict_strtoll(val.c_str(), 10, &err);
      if (!err.empty()) {
	cerr << "error parsing UID: " << err << std::endl;
	exit(1);
      }
      set_auid = true;
    } else if (ceph_argparse_flag(args, i, "-b", "--bin", (char*)NULL)) {
      bin_keyring = true;
    } else if (fn.empty()) {
      fn = *i++;
    } else {
      usage();
    }
  }
  if (fn.empty() && !gen_print_key) {
    cerr << argv[0] << ": must specify filename" << std::endl;
    usage();
  }
  if (!(gen_key ||
	gen_print_key ||
	!add_key.empty() ||
	list ||
	!caps_fn.empty() ||
	caps.size() ||
	set_auid ||
	print_key ||
	create_keyring ||
	!import_keyring.empty())) {
    cerr << "no command specified" << std::endl;
    usage();
  }
  if (gen_key && (!add_key.empty())) {
    cerr << "can't both gen_key and add_key" << std::endl;
    usage();
  }

  common_init_finish(g_ceph_context);
  EntityName ename(g_conf->name);

  if (gen_print_key) {
    CryptoKey key;
    key.create(g_ceph_context, CEPH_CRYPTO_AES);
    cout << key << std::endl;
    return 0;
  }

  // keyring --------
  bool modified = false;
  KeyRing keyring;

  bufferlist bl;
  int r = 0;
  if (create_keyring) {
    cout << "creating " << fn << std::endl;
    modified = true;
  } else {
    std::string err;
    r = bl.read_file(fn.c_str(), &err);
    if (r >= 0) {
      try {
	bufferlist::iterator iter = bl.begin();
	::decode(keyring, iter);
      } catch (const buffer::error &err) {
	cerr << "error reading file " << fn << std::endl;
	exit(1);
      }
    } else {
      cerr << "can't open " << fn << ": " << err << std::endl;
      exit(1);
    }
  }

  // write commands
  if (!import_keyring.empty()) {
    KeyRing other;
    bufferlist obl;
    std::string err;
    int r = obl.read_file(import_keyring.c_str(), &err);
    if (r >= 0) {
      try {
	bufferlist::iterator iter = obl.begin();
	::decode(other, iter);
      } catch (const buffer::error &err) {
	cerr << "error reading file " << import_keyring << std::endl;
	exit(1);
      }

      cout << "importing contents of " << import_keyring << " into " << fn << std::endl;
      //other.print(cout);
      keyring.import(g_ceph_context, other);
      modified = true;
    } else {
      cerr << "can't open " << import_keyring << ": " << err << std::endl;
      exit(1);
    }
  }
  if (gen_key) {
    EntityAuth eauth;
    eauth.key.create(g_ceph_context, CEPH_CRYPTO_AES);
    keyring.add(ename, eauth);
    modified = true;
  }
  if (!add_key.empty()) {
    EntityAuth eauth;
    try {
      eauth.key.decode_base64(add_key);
    } catch (const buffer::error &err) {
      cerr << "can't decode key '" << add_key << "'" << std::endl;
      exit(1);
    }
    keyring.add(ename, eauth);
    modified = true;
    cout << "added entity " << ename << " auth " << eauth << std::endl;
  }
  if (!caps_fn.empty()) {
    ConfFile cf;
    std::deque<std::string> parse_errors;
    if (cf.parse_file(caps_fn, &parse_errors) != 0) {
      cerr << "could not parse caps file " << caps_fn << std::endl;
      exit(1);
    }
    complain_about_parse_errors(g_ceph_context, &parse_errors);
    map<string, bufferlist> caps;
    const char *key_names[] = { "mon", "osd", "mds", NULL };
    for (int i=0; key_names[i]; i++) {
      std::string val;
      if (cf.read("global", key_names[i], val) == 0) {
        bufferlist bl;
        ::encode(val, bl);
        string s(key_names[i]);
        caps[s] = bl;
      }
    }
    keyring.set_caps(ename, caps);
    modified = true;
  }
  if (caps.size()) {
    keyring.set_caps(ename, caps);
    modified = true;
  }
  if (set_auid) {
    keyring.set_uid(ename, auid);
    modified = true;
  }

  // read commands
  if (list) {
    keyring.print(cout);
  }
  if (print_key) {
    CryptoKey key;
    if (keyring.get_secret(ename, key)) {
      cout << key << std::endl;
    } else {
      cerr << "entity " << ename << " not found" << std::endl;
    }
  }

  // write result?
  if (modified) {
    bufferlist bl;
    if (bin_keyring) {
      ::encode(keyring, bl);
    } else {
      keyring.encode_plaintext(bl);
    }
    r = bl.write_file(fn.c_str(), 0600);
    if (r < 0) {
      cerr << "could not write " << fn << std::endl;
    }
    //cout << "wrote " << bl.length() << " bytes to " << fn << std::endl;
  }

  return 0;
}
<commit_msg>ceph-authtool: make error msg more helpful<commit_after>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2009 Sage Weil <sage@newdream.net>
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

using namespace std;

#include "common/config.h"
#include "common/strtol.h"

#include "common/ConfUtils.h"
#include "common/ceph_argparse.h"
#include "global/global_context.h"
#include "global/global_init.h"
#include "auth/Crypto.h"
#include "auth/Auth.h"
#include "auth/KeyRing.h"

#include <sstream>

void usage()
{
  cout << "usage: ceph-authtool keyringfile [OPTIONS]...\n"
       << "where the options are:\n"
       << "  -l, --list                    will list all keys and capabilities present in\n"
       << "                                the keyring\n"
       << "  -p, --print                   will print an encoded key for the specified\n"
       << "                                entityname. This is suitable for the\n"
       << "                                'mount -o secret=..' argument\n"
       << "  -C, --create-keyring          will create a new keyring, overwriting any\n"
       << "                                existing keyringfile\n"
       << "  --gen-key                     will generate a new secret key for the\n"
       << "                                specified entityname\n"
       << "  --add-key                     will add an encoded key to the keyring\n"
       << "  --cap subsystem capability    will set the capability for given subsystem\n"
       << "  --caps capsfile               will set all of capabilities associated with a\n"
       << "                                given key, for all subsystems\n"
       << "  -b, --bin                     will create a binary formatted keyring" << std::endl;
  exit(1);
}

int main(int argc, const char **argv)
{
  vector<const char*> args;
  argv_to_vec(argc, argv, args);
  env_to_vec(args);

  bool gen_key = false;
  bool gen_print_key = false;
  std::string add_key;
  bool list = false;
  bool print_key = false;
  bool create_keyring = false;
  std::string caps_fn;
  std::string import_keyring;
  bool set_auid = false;
  uint64_t auid = CEPH_AUTH_UID_DEFAULT;
  map<string,bufferlist> caps;
  bool bin_keyring = false;
  std::string fn;

  global_init(args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY,
	      CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
  std::vector<const char*>::iterator i;
  for (i = args.begin(); i != args.end(); ) {
    std::string val;
    if (ceph_argparse_double_dash(args, i)) {
      break;
    } else if (ceph_argparse_flag(args, i, "-g", "--gen-key", (char*)NULL)) {
      gen_key = true;
    } else if (ceph_argparse_flag(args, i, "--gen-print-key", (char*)NULL)) {
      gen_print_key = true;
    } else if (ceph_argparse_witharg(args, i, &val, "-a", "--add-key", (char*)NULL)) {
      add_key = val;
    } else if (ceph_argparse_flag(args, i, &val, "-l", "--list", (char*)NULL)) {
      list = true;
    } else if (ceph_argparse_witharg(args, i, &val, "--caps", (char*)NULL)) {
      caps_fn = val;
    } else if (ceph_argparse_witharg(args, i, &val, "--cap", (char*)NULL)) {
      std::string my_key = val;
      if (i == args.end()) {
	cerr << "must give two arguments to --cap: key and val." << std::endl;
	exit(1);
      }
      std::string my_val = *i;
      ++i;
      ::encode(my_val, caps[my_key]);
    } else if (ceph_argparse_flag(args, i, "-p", "--print-key", (char*)NULL)) {
      print_key = true;
    } else if (ceph_argparse_flag(args, i, "-C", "--create-keyring", (char*)NULL)) {
      create_keyring = true;
    } else if (ceph_argparse_witharg(args, i, &val, "--import-keyring", (char*)NULL)) {
      import_keyring = val;
    } else if (ceph_argparse_witharg(args, i, &val, "-u", "--set-uid", (char*)NULL)) {
      std::string err;
      auid = strict_strtoll(val.c_str(), 10, &err);
      if (!err.empty()) {
	cerr << "error parsing UID: " << err << std::endl;
	exit(1);
      }
      set_auid = true;
    } else if (ceph_argparse_flag(args, i, "-b", "--bin", (char*)NULL)) {
      bin_keyring = true;
    } else if (fn.empty()) {
      fn = *i++;
    } else {
      cerr << argv[0] << ": unexpected '" << *i << "'" << std::endl;
      usage();
    }
  }
  if (fn.empty() && !gen_print_key) {
    cerr << argv[0] << ": must specify filename" << std::endl;
    usage();
  }
  if (!(gen_key ||
	gen_print_key ||
	!add_key.empty() ||
	list ||
	!caps_fn.empty() ||
	caps.size() ||
	set_auid ||
	print_key ||
	create_keyring ||
	!import_keyring.empty())) {
    cerr << "no command specified" << std::endl;
    usage();
  }
  if (gen_key && (!add_key.empty())) {
    cerr << "can't both gen_key and add_key" << std::endl;
    usage();
  }

  common_init_finish(g_ceph_context);
  EntityName ename(g_conf->name);

  if (gen_print_key) {
    CryptoKey key;
    key.create(g_ceph_context, CEPH_CRYPTO_AES);
    cout << key << std::endl;
    return 0;
  }

  // keyring --------
  bool modified = false;
  KeyRing keyring;

  bufferlist bl;
  int r = 0;
  if (create_keyring) {
    cout << "creating " << fn << std::endl;
    modified = true;
  } else {
    std::string err;
    r = bl.read_file(fn.c_str(), &err);
    if (r >= 0) {
      try {
	bufferlist::iterator iter = bl.begin();
	::decode(keyring, iter);
      } catch (const buffer::error &err) {
	cerr << "error reading file " << fn << std::endl;
	exit(1);
      }
    } else {
      cerr << "can't open " << fn << ": " << err << std::endl;
      exit(1);
    }
  }

  // write commands
  if (!import_keyring.empty()) {
    KeyRing other;
    bufferlist obl;
    std::string err;
    int r = obl.read_file(import_keyring.c_str(), &err);
    if (r >= 0) {
      try {
	bufferlist::iterator iter = obl.begin();
	::decode(other, iter);
      } catch (const buffer::error &err) {
	cerr << "error reading file " << import_keyring << std::endl;
	exit(1);
      }

      cout << "importing contents of " << import_keyring << " into " << fn << std::endl;
      //other.print(cout);
      keyring.import(g_ceph_context, other);
      modified = true;
    } else {
      cerr << "can't open " << import_keyring << ": " << err << std::endl;
      exit(1);
    }
  }
  if (gen_key) {
    EntityAuth eauth;
    eauth.key.create(g_ceph_context, CEPH_CRYPTO_AES);
    keyring.add(ename, eauth);
    modified = true;
  }
  if (!add_key.empty()) {
    EntityAuth eauth;
    try {
      eauth.key.decode_base64(add_key);
    } catch (const buffer::error &err) {
      cerr << "can't decode key '" << add_key << "'" << std::endl;
      exit(1);
    }
    keyring.add(ename, eauth);
    modified = true;
    cout << "added entity " << ename << " auth " << eauth << std::endl;
  }
  if (!caps_fn.empty()) {
    ConfFile cf;
    std::deque<std::string> parse_errors;
    if (cf.parse_file(caps_fn, &parse_errors) != 0) {
      cerr << "could not parse caps file " << caps_fn << std::endl;
      exit(1);
    }
    complain_about_parse_errors(g_ceph_context, &parse_errors);
    map<string, bufferlist> caps;
    const char *key_names[] = { "mon", "osd", "mds", NULL };
    for (int i=0; key_names[i]; i++) {
      std::string val;
      if (cf.read("global", key_names[i], val) == 0) {
        bufferlist bl;
        ::encode(val, bl);
        string s(key_names[i]);
        caps[s] = bl;
      }
    }
    keyring.set_caps(ename, caps);
    modified = true;
  }
  if (caps.size()) {
    keyring.set_caps(ename, caps);
    modified = true;
  }
  if (set_auid) {
    keyring.set_uid(ename, auid);
    modified = true;
  }

  // read commands
  if (list) {
    keyring.print(cout);
  }
  if (print_key) {
    CryptoKey key;
    if (keyring.get_secret(ename, key)) {
      cout << key << std::endl;
    } else {
      cerr << "entity " << ename << " not found" << std::endl;
    }
  }

  // write result?
  if (modified) {
    bufferlist bl;
    if (bin_keyring) {
      ::encode(keyring, bl);
    } else {
      keyring.encode_plaintext(bl);
    }
    r = bl.write_file(fn.c_str(), 0600);
    if (r < 0) {
      cerr << "could not write " << fn << std::endl;
    }
    //cout << "wrote " << bl.length() << " bytes to " << fn << std::endl;
  }

  return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2006 The Regents of The University of Michigan
 * Copyright (c) 2010 Advanced Micro Devices, 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 the copyright holders 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.
 *
 * Authors: Ali Saidi
 *          Steve Reinhardt
 */

/**
 * @file
 * Definition of the Packet Class, a packet is a transaction occuring
 * between a single level of the memory heirarchy (ie L1->L2).
 */

#include <cstring>
#include <iostream>

#include "base/cprintf.hh"
#include "base/misc.hh"
#include "base/trace.hh"
#include "mem/packet.hh"

using namespace std;

// The one downside to bitsets is that static initializers can get ugly.
#define SET1(a1)                     (1 << (a1))
#define SET2(a1, a2)                 (SET1(a1) | SET1(a2))
#define SET3(a1, a2, a3)             (SET2(a1, a2) | SET1(a3))
#define SET4(a1, a2, a3, a4)         (SET3(a1, a2, a3) | SET1(a4))
#define SET5(a1, a2, a3, a4, a5)     (SET4(a1, a2, a3, a4) | SET1(a5))
#define SET6(a1, a2, a3, a4, a5, a6) (SET5(a1, a2, a3, a4, a5) | SET1(a6))

const MemCmd::CommandInfo
MemCmd::commandInfo[] =
{
    /* InvalidCmd */
    { 0, InvalidCmd, "InvalidCmd" },
    /* ReadReq */
    { SET3(IsRead, IsRequest, NeedsResponse), ReadResp, "ReadReq" },
    /* ReadResp */
    { SET3(IsRead, IsResponse, HasData), InvalidCmd, "ReadResp" },
    /* ReadRespWithInvalidate */
    { SET4(IsRead, IsResponse, HasData, IsInvalidate),
            InvalidCmd, "ReadRespWithInvalidate" },
    /* WriteReq */
    { SET5(IsWrite, NeedsExclusive, IsRequest, NeedsResponse, HasData),
            WriteResp, "WriteReq" },
    /* WriteResp */
    { SET3(IsWrite, NeedsExclusive, IsResponse), InvalidCmd, "WriteResp" },
    /* Writeback */
    { SET4(IsWrite, NeedsExclusive, IsRequest, HasData),
            InvalidCmd, "Writeback" },
    /* SoftPFReq */
    { SET4(IsRead, IsRequest, IsSWPrefetch, NeedsResponse),
            SoftPFResp, "SoftPFReq" },
    /* HardPFReq */
    { SET4(IsRead, IsRequest, IsHWPrefetch, NeedsResponse),
            HardPFResp, "HardPFReq" },
    /* SoftPFResp */
    { SET4(IsRead, IsResponse, IsSWPrefetch, HasData),
            InvalidCmd, "SoftPFResp" },
    /* HardPFResp */
    { SET4(IsRead, IsResponse, IsHWPrefetch, HasData),
            InvalidCmd, "HardPFResp" },
    /* WriteInvalidateReq */
    { SET6(IsWrite, NeedsExclusive, IsInvalidate,
           IsRequest, HasData, NeedsResponse),
            WriteInvalidateResp, "WriteInvalidateReq" },
    /* WriteInvalidateResp */
    { SET3(IsWrite, NeedsExclusive, IsResponse),
            InvalidCmd, "WriteInvalidateResp" },
    /* UpgradeReq */
    { SET5(IsInvalidate, NeedsExclusive, IsUpgrade, IsRequest, NeedsResponse),
            UpgradeResp, "UpgradeReq" },
    /* SCUpgradeReq: response could be UpgradeResp or UpgradeFailResp */
    { SET6(IsInvalidate, NeedsExclusive, IsUpgrade, IsLlsc,
           IsRequest, NeedsResponse),
            UpgradeResp, "SCUpgradeReq" },
    /* UpgradeResp */
    { SET3(NeedsExclusive, IsUpgrade, IsResponse),
            InvalidCmd, "UpgradeResp" },
    /* SCUpgradeFailReq: generates UpgradeFailResp ASAP */
    { SET5(IsInvalidate, NeedsExclusive, IsLlsc,
           IsRequest, NeedsResponse),
            UpgradeFailResp, "SCUpgradeFailReq" },
    /* UpgradeFailResp */
    { SET2(NeedsExclusive, IsResponse),
            InvalidCmd, "UpgradeFailResp" },
    /* ReadExReq */
    { SET5(IsRead, NeedsExclusive, IsInvalidate, IsRequest, NeedsResponse),
            ReadExResp, "ReadExReq" },
    /* ReadExResp */
    { SET4(IsRead, NeedsExclusive, IsResponse, HasData),
            InvalidCmd, "ReadExResp" },
    /* LoadLockedReq: note that we use plain ReadResp as response, so that
     *                we can also use ReadRespWithInvalidate when needed */
    { SET4(IsRead, IsLlsc, IsRequest, NeedsResponse),
            ReadResp, "LoadLockedReq" },
    /* StoreCondReq */
    { SET6(IsWrite, NeedsExclusive, IsLlsc,
           IsRequest, NeedsResponse, HasData),
            StoreCondResp, "StoreCondReq" },
    /* StoreCondFailReq: generates failing StoreCondResp ASAP */
    { SET6(IsWrite, NeedsExclusive, IsLlsc,
           IsRequest, NeedsResponse, HasData),
            StoreCondResp, "StoreCondFailReq" },
    /* StoreCondResp */
    { SET4(IsWrite, NeedsExclusive, IsLlsc, IsResponse),
            InvalidCmd, "StoreCondResp" },
    /* SwapReq -- for Swap ldstub type operations */
    { SET6(IsRead, IsWrite, NeedsExclusive, IsRequest, HasData, NeedsResponse),
        SwapResp, "SwapReq" },
    /* SwapResp -- for Swap ldstub type operations */
    { SET5(IsRead, IsWrite, NeedsExclusive, IsResponse, HasData),
            InvalidCmd, "SwapResp" },
    /* IntReq -- for interrupts */
    { SET4(IsWrite, IsRequest, NeedsResponse, HasData),
        MessageResp, "MessageReq" },
    /* IntResp -- for interrupts */
    { SET2(IsWrite, IsResponse), InvalidCmd, "MessageResp" },
    /* NetworkNackError  -- nacked at network layer (not by protocol) */
    { SET2(IsResponse, IsError), InvalidCmd, "NetworkNackError" },
    /* InvalidDestError  -- packet dest field invalid */
    { SET2(IsResponse, IsError), InvalidCmd, "InvalidDestError" },
    /* BadAddressError   -- memory address invalid */
    { SET2(IsResponse, IsError), InvalidCmd, "BadAddressError" },
    /* FunctionalReadError */
    { SET3(IsRead, IsResponse, IsError), InvalidCmd, "FunctionalReadError" },
    /* FunctionalWriteError */
    { SET3(IsWrite, IsResponse, IsError), InvalidCmd, "FunctionalWriteError" },
    /* PrintReq */
    { SET2(IsRequest, IsPrint), InvalidCmd, "PrintReq" },
    /* Flush Request */
    { SET3(IsRequest, IsFlush, NeedsExclusive), InvalidCmd, "FlushReq" },
};

bool
Packet::checkFunctional(Printable *obj, Addr addr, int size, uint8_t *data)
{
    Addr func_start = getAddr();
    Addr func_end   = getAddr() + getSize() - 1;
    Addr val_start  = addr;
    Addr val_end    = val_start + size - 1;

    if (func_start > val_end || val_start > func_end) {
        // no intersection
        return false;
    }

    // check print first since it doesn't require data
    if (isPrint()) {
        dynamic_cast<PrintReqState*>(senderState)->printObj(obj);
        return false;
    }

    // if there's no data, there's no need to look further
    if (!data) {
        return false;
    }

    // offset of functional request into supplied value (could be
    // negative if partial overlap)
    int offset = func_start - val_start;

    if (isRead()) {
        if (func_start >= val_start && func_end <= val_end) {
            allocate();
            memcpy(getPtr<uint8_t>(), data + offset, getSize());
            return true;
        } else {
            // Offsets and sizes to copy in case of partial overlap
            int func_offset;
            int val_offset;
            int overlap_size;

            // calculate offsets and copy sizes for the two byte arrays
            if (val_start < func_start && val_end <= func_end) {
                val_offset = func_start - val_start;
                func_offset = 0;
                overlap_size = val_end - func_start;
            } else if (val_start >= func_start && val_end > func_end) {
                val_offset = 0;
                func_offset = val_start - func_start;
                overlap_size = func_end - val_start;
            } else if (val_start >= func_start && val_end <= func_end) {
                val_offset = 0;
                func_offset = val_start - func_start;
                overlap_size = size;
            } else {
                panic("BUG: Missed a case for a partial functional request");
            }

            // Figure out how much of the partial overlap should be copied
            // into the packet and not overwrite previously found bytes.
            if (bytesValidStart == 0 && bytesValidEnd == 0) {
                // No bytes have been copied yet, just set indices
                // to found range
                bytesValidStart = func_offset;
                bytesValidEnd = func_offset + overlap_size;
            } else {
                // Some bytes have already been copied. Use bytesValid
                // indices and offset values to figure out how much data
                // to copy and where to copy it to.

                // Indice overlap conditions to check
                int a = func_offset - bytesValidStart;
                int b = (func_offset + overlap_size) - bytesValidEnd;
                int c = func_offset - bytesValidEnd;
                int d = (func_offset + overlap_size) - bytesValidStart;

                if (a >= 0 && b <= 0) {
                    // bytes already in pkt data array are superset of
                    // found bytes, will not copy any bytes
                    overlap_size = 0;
                } else if (a < 0 && d >= 0 && b <= 0) {
                    // found bytes will move bytesValidStart towards 0
                    overlap_size = bytesValidStart - func_offset;
                    bytesValidStart = func_offset;
                } else if (b > 0 && c <= 0 && a >= 0) {
                    // found bytes will move bytesValidEnd
                    // towards end of pkt data array
                    overlap_size =
                        (func_offset + overlap_size) - bytesValidEnd;
                    val_offset += bytesValidEnd - func_offset;
                    func_offset = bytesValidEnd;
                    bytesValidEnd += overlap_size;
                } else if (a < 0 && b > 0) {
                    // Found bytes are superset of copied range. Will move
                    // bytesValidStart towards 0 and bytesValidEnd towards
                    // end of pkt data array.  Need to break copy into two
                    // pieces so as to not overwrite previously found data.

                    // copy the first half
                    uint8_t *dest = getPtr<uint8_t>() + func_offset;
                    uint8_t *src = data + val_offset;
                    memcpy(dest, src, (bytesValidStart - func_offset));

                    // re-calc the offsets and indices to do the copy
                    // required for the second half
                    val_offset += (bytesValidEnd - func_offset);
                    bytesValidStart = func_offset;
                    overlap_size =
                        (func_offset + overlap_size) - bytesValidEnd;
                    func_offset = bytesValidEnd;
                    bytesValidEnd += overlap_size;
                } else if ((c > 0 && b > 0)
                           || (a < 0 && d < 0)) {
                    // region to be copied is discontiguous! Not supported.
                    panic("BUG: Discontiguous bytes found"
                          "for functional copying!");
                }
            }

            assert((bytesValidStart >= 0) && (bytesValidEnd <= getSize()));

            // copy partial data into the packet's data array
            uint8_t *dest = getPtr<uint8_t>() + func_offset;
            uint8_t *src = data + val_offset;
            memcpy(dest, src, overlap_size);

            // check if we're done filling the functional access
            bool done = (bytesValidStart == 0) && (bytesValidEnd == getSize());
            return done;
        }
    } else if (isWrite()) {
        if (offset >= 0) {
            memcpy(data + offset, getPtr<uint8_t>(),
                   (min(func_end, val_end) - func_start) + 1);
        } else {
            // val_start > func_start
            memcpy(data, getPtr<uint8_t>() - offset,
                   (min(func_end, val_end) - val_start) + 1);
        }
    } else {
        panic("Don't know how to handle command %s\n", cmdString());
    }

    // keep going with request by default
    return false;
}

void
Packet::print(ostream &o, const int verbosity, const string &prefix) const
{
    ccprintf(o, "%s[%x:%x] %s\n", prefix,
             getAddr(), getAddr() + getSize() - 1, cmdString());
}

Packet::PrintReqState::PrintReqState(ostream &_os, int _verbosity)
    : curPrefixPtr(new string("")), os(_os), verbosity(_verbosity)
{
    labelStack.push_back(LabelStackEntry("", curPrefixPtr));
}

Packet::PrintReqState::~PrintReqState()
{
    labelStack.pop_back();
    assert(labelStack.empty());
    delete curPrefixPtr;
}

Packet::PrintReqState::
LabelStackEntry::LabelStackEntry(const string &_label, string *_prefix)
    : label(_label), prefix(_prefix), labelPrinted(false)
{
}

void
Packet::PrintReqState::pushLabel(const string &lbl, const string &prefix)
{
    labelStack.push_back(LabelStackEntry(lbl, curPrefixPtr));
    curPrefixPtr = new string(*curPrefixPtr);
    *curPrefixPtr += prefix;
}

void
Packet::PrintReqState::popLabel()
{
    delete curPrefixPtr;
    curPrefixPtr = labelStack.back().prefix;
    labelStack.pop_back();
    assert(!labelStack.empty());
}

void
Packet::PrintReqState::printLabels()
{
    if (!labelStack.back().labelPrinted) {
        LabelStack::iterator i = labelStack.begin();
        LabelStack::iterator end = labelStack.end();
        while (i != end) {
            if (!i->labelPrinted) {
                ccprintf(os, "%s%s\n", *(i->prefix), i->label);
                i->labelPrinted = true;
            }
            i++;
        }
    }
}

void
Packet::PrintReqState::printObj(Printable *obj)
{
    printLabels();
    obj->print(os, verbosity, curPrefix());
}
<commit_msg>Packet: Remove meaningless assert statement<commit_after>/*
 * Copyright (c) 2011 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2006 The Regents of The University of Michigan
 * Copyright (c) 2010 Advanced Micro Devices, 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 the copyright holders 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.
 *
 * Authors: Ali Saidi
 *          Steve Reinhardt
 */

/**
 * @file
 * Definition of the Packet Class, a packet is a transaction occuring
 * between a single level of the memory heirarchy (ie L1->L2).
 */

#include <cstring>
#include <iostream>

#include "base/cprintf.hh"
#include "base/misc.hh"
#include "base/trace.hh"
#include "mem/packet.hh"

using namespace std;

// The one downside to bitsets is that static initializers can get ugly.
#define SET1(a1)                     (1 << (a1))
#define SET2(a1, a2)                 (SET1(a1) | SET1(a2))
#define SET3(a1, a2, a3)             (SET2(a1, a2) | SET1(a3))
#define SET4(a1, a2, a3, a4)         (SET3(a1, a2, a3) | SET1(a4))
#define SET5(a1, a2, a3, a4, a5)     (SET4(a1, a2, a3, a4) | SET1(a5))
#define SET6(a1, a2, a3, a4, a5, a6) (SET5(a1, a2, a3, a4, a5) | SET1(a6))

const MemCmd::CommandInfo
MemCmd::commandInfo[] =
{
    /* InvalidCmd */
    { 0, InvalidCmd, "InvalidCmd" },
    /* ReadReq */
    { SET3(IsRead, IsRequest, NeedsResponse), ReadResp, "ReadReq" },
    /* ReadResp */
    { SET3(IsRead, IsResponse, HasData), InvalidCmd, "ReadResp" },
    /* ReadRespWithInvalidate */
    { SET4(IsRead, IsResponse, HasData, IsInvalidate),
            InvalidCmd, "ReadRespWithInvalidate" },
    /* WriteReq */
    { SET5(IsWrite, NeedsExclusive, IsRequest, NeedsResponse, HasData),
            WriteResp, "WriteReq" },
    /* WriteResp */
    { SET3(IsWrite, NeedsExclusive, IsResponse), InvalidCmd, "WriteResp" },
    /* Writeback */
    { SET4(IsWrite, NeedsExclusive, IsRequest, HasData),
            InvalidCmd, "Writeback" },
    /* SoftPFReq */
    { SET4(IsRead, IsRequest, IsSWPrefetch, NeedsResponse),
            SoftPFResp, "SoftPFReq" },
    /* HardPFReq */
    { SET4(IsRead, IsRequest, IsHWPrefetch, NeedsResponse),
            HardPFResp, "HardPFReq" },
    /* SoftPFResp */
    { SET4(IsRead, IsResponse, IsSWPrefetch, HasData),
            InvalidCmd, "SoftPFResp" },
    /* HardPFResp */
    { SET4(IsRead, IsResponse, IsHWPrefetch, HasData),
            InvalidCmd, "HardPFResp" },
    /* WriteInvalidateReq */
    { SET6(IsWrite, NeedsExclusive, IsInvalidate,
           IsRequest, HasData, NeedsResponse),
            WriteInvalidateResp, "WriteInvalidateReq" },
    /* WriteInvalidateResp */
    { SET3(IsWrite, NeedsExclusive, IsResponse),
            InvalidCmd, "WriteInvalidateResp" },
    /* UpgradeReq */
    { SET5(IsInvalidate, NeedsExclusive, IsUpgrade, IsRequest, NeedsResponse),
            UpgradeResp, "UpgradeReq" },
    /* SCUpgradeReq: response could be UpgradeResp or UpgradeFailResp */
    { SET6(IsInvalidate, NeedsExclusive, IsUpgrade, IsLlsc,
           IsRequest, NeedsResponse),
            UpgradeResp, "SCUpgradeReq" },
    /* UpgradeResp */
    { SET3(NeedsExclusive, IsUpgrade, IsResponse),
            InvalidCmd, "UpgradeResp" },
    /* SCUpgradeFailReq: generates UpgradeFailResp ASAP */
    { SET5(IsInvalidate, NeedsExclusive, IsLlsc,
           IsRequest, NeedsResponse),
            UpgradeFailResp, "SCUpgradeFailReq" },
    /* UpgradeFailResp */
    { SET2(NeedsExclusive, IsResponse),
            InvalidCmd, "UpgradeFailResp" },
    /* ReadExReq */
    { SET5(IsRead, NeedsExclusive, IsInvalidate, IsRequest, NeedsResponse),
            ReadExResp, "ReadExReq" },
    /* ReadExResp */
    { SET4(IsRead, NeedsExclusive, IsResponse, HasData),
            InvalidCmd, "ReadExResp" },
    /* LoadLockedReq: note that we use plain ReadResp as response, so that
     *                we can also use ReadRespWithInvalidate when needed */
    { SET4(IsRead, IsLlsc, IsRequest, NeedsResponse),
            ReadResp, "LoadLockedReq" },
    /* StoreCondReq */
    { SET6(IsWrite, NeedsExclusive, IsLlsc,
           IsRequest, NeedsResponse, HasData),
            StoreCondResp, "StoreCondReq" },
    /* StoreCondFailReq: generates failing StoreCondResp ASAP */
    { SET6(IsWrite, NeedsExclusive, IsLlsc,
           IsRequest, NeedsResponse, HasData),
            StoreCondResp, "StoreCondFailReq" },
    /* StoreCondResp */
    { SET4(IsWrite, NeedsExclusive, IsLlsc, IsResponse),
            InvalidCmd, "StoreCondResp" },
    /* SwapReq -- for Swap ldstub type operations */
    { SET6(IsRead, IsWrite, NeedsExclusive, IsRequest, HasData, NeedsResponse),
        SwapResp, "SwapReq" },
    /* SwapResp -- for Swap ldstub type operations */
    { SET5(IsRead, IsWrite, NeedsExclusive, IsResponse, HasData),
            InvalidCmd, "SwapResp" },
    /* IntReq -- for interrupts */
    { SET4(IsWrite, IsRequest, NeedsResponse, HasData),
        MessageResp, "MessageReq" },
    /* IntResp -- for interrupts */
    { SET2(IsWrite, IsResponse), InvalidCmd, "MessageResp" },
    /* NetworkNackError  -- nacked at network layer (not by protocol) */
    { SET2(IsResponse, IsError), InvalidCmd, "NetworkNackError" },
    /* InvalidDestError  -- packet dest field invalid */
    { SET2(IsResponse, IsError), InvalidCmd, "InvalidDestError" },
    /* BadAddressError   -- memory address invalid */
    { SET2(IsResponse, IsError), InvalidCmd, "BadAddressError" },
    /* FunctionalReadError */
    { SET3(IsRead, IsResponse, IsError), InvalidCmd, "FunctionalReadError" },
    /* FunctionalWriteError */
    { SET3(IsWrite, IsResponse, IsError), InvalidCmd, "FunctionalWriteError" },
    /* PrintReq */
    { SET2(IsRequest, IsPrint), InvalidCmd, "PrintReq" },
    /* Flush Request */
    { SET3(IsRequest, IsFlush, NeedsExclusive), InvalidCmd, "FlushReq" },
};

bool
Packet::checkFunctional(Printable *obj, Addr addr, int size, uint8_t *data)
{
    Addr func_start = getAddr();
    Addr func_end   = getAddr() + getSize() - 1;
    Addr val_start  = addr;
    Addr val_end    = val_start + size - 1;

    if (func_start > val_end || val_start > func_end) {
        // no intersection
        return false;
    }

    // check print first since it doesn't require data
    if (isPrint()) {
        dynamic_cast<PrintReqState*>(senderState)->printObj(obj);
        return false;
    }

    // if there's no data, there's no need to look further
    if (!data) {
        return false;
    }

    // offset of functional request into supplied value (could be
    // negative if partial overlap)
    int offset = func_start - val_start;

    if (isRead()) {
        if (func_start >= val_start && func_end <= val_end) {
            allocate();
            memcpy(getPtr<uint8_t>(), data + offset, getSize());
            return true;
        } else {
            // Offsets and sizes to copy in case of partial overlap
            int func_offset;
            int val_offset;
            int overlap_size;

            // calculate offsets and copy sizes for the two byte arrays
            if (val_start < func_start && val_end <= func_end) {
                val_offset = func_start - val_start;
                func_offset = 0;
                overlap_size = val_end - func_start;
            } else if (val_start >= func_start && val_end > func_end) {
                val_offset = 0;
                func_offset = val_start - func_start;
                overlap_size = func_end - val_start;
            } else if (val_start >= func_start && val_end <= func_end) {
                val_offset = 0;
                func_offset = val_start - func_start;
                overlap_size = size;
            } else {
                panic("BUG: Missed a case for a partial functional request");
            }

            // Figure out how much of the partial overlap should be copied
            // into the packet and not overwrite previously found bytes.
            if (bytesValidStart == 0 && bytesValidEnd == 0) {
                // No bytes have been copied yet, just set indices
                // to found range
                bytesValidStart = func_offset;
                bytesValidEnd = func_offset + overlap_size;
            } else {
                // Some bytes have already been copied. Use bytesValid
                // indices and offset values to figure out how much data
                // to copy and where to copy it to.

                // Indice overlap conditions to check
                int a = func_offset - bytesValidStart;
                int b = (func_offset + overlap_size) - bytesValidEnd;
                int c = func_offset - bytesValidEnd;
                int d = (func_offset + overlap_size) - bytesValidStart;

                if (a >= 0 && b <= 0) {
                    // bytes already in pkt data array are superset of
                    // found bytes, will not copy any bytes
                    overlap_size = 0;
                } else if (a < 0 && d >= 0 && b <= 0) {
                    // found bytes will move bytesValidStart towards 0
                    overlap_size = bytesValidStart - func_offset;
                    bytesValidStart = func_offset;
                } else if (b > 0 && c <= 0 && a >= 0) {
                    // found bytes will move bytesValidEnd
                    // towards end of pkt data array
                    overlap_size =
                        (func_offset + overlap_size) - bytesValidEnd;
                    val_offset += bytesValidEnd - func_offset;
                    func_offset = bytesValidEnd;
                    bytesValidEnd += overlap_size;
                } else if (a < 0 && b > 0) {
                    // Found bytes are superset of copied range. Will move
                    // bytesValidStart towards 0 and bytesValidEnd towards
                    // end of pkt data array.  Need to break copy into two
                    // pieces so as to not overwrite previously found data.

                    // copy the first half
                    uint8_t *dest = getPtr<uint8_t>() + func_offset;
                    uint8_t *src = data + val_offset;
                    memcpy(dest, src, (bytesValidStart - func_offset));

                    // re-calc the offsets and indices to do the copy
                    // required for the second half
                    val_offset += (bytesValidEnd - func_offset);
                    bytesValidStart = func_offset;
                    overlap_size =
                        (func_offset + overlap_size) - bytesValidEnd;
                    func_offset = bytesValidEnd;
                    bytesValidEnd += overlap_size;
                } else if ((c > 0 && b > 0)
                           || (a < 0 && d < 0)) {
                    // region to be copied is discontiguous! Not supported.
                    panic("BUG: Discontiguous bytes found"
                          "for functional copying!");
                }
            }

            // copy partial data into the packet's data array
            uint8_t *dest = getPtr<uint8_t>() + func_offset;
            uint8_t *src = data + val_offset;
            memcpy(dest, src, overlap_size);

            // check if we're done filling the functional access
            bool done = (bytesValidStart == 0) && (bytesValidEnd == getSize());
            return done;
        }
    } else if (isWrite()) {
        if (offset >= 0) {
            memcpy(data + offset, getPtr<uint8_t>(),
                   (min(func_end, val_end) - func_start) + 1);
        } else {
            // val_start > func_start
            memcpy(data, getPtr<uint8_t>() - offset,
                   (min(func_end, val_end) - val_start) + 1);
        }
    } else {
        panic("Don't know how to handle command %s\n", cmdString());
    }

    // keep going with request by default
    return false;
}

void
Packet::print(ostream &o, const int verbosity, const string &prefix) const
{
    ccprintf(o, "%s[%x:%x] %s\n", prefix,
             getAddr(), getAddr() + getSize() - 1, cmdString());
}

Packet::PrintReqState::PrintReqState(ostream &_os, int _verbosity)
    : curPrefixPtr(new string("")), os(_os), verbosity(_verbosity)
{
    labelStack.push_back(LabelStackEntry("", curPrefixPtr));
}

Packet::PrintReqState::~PrintReqState()
{
    labelStack.pop_back();
    assert(labelStack.empty());
    delete curPrefixPtr;
}

Packet::PrintReqState::
LabelStackEntry::LabelStackEntry(const string &_label, string *_prefix)
    : label(_label), prefix(_prefix), labelPrinted(false)
{
}

void
Packet::PrintReqState::pushLabel(const string &lbl, const string &prefix)
{
    labelStack.push_back(LabelStackEntry(lbl, curPrefixPtr));
    curPrefixPtr = new string(*curPrefixPtr);
    *curPrefixPtr += prefix;
}

void
Packet::PrintReqState::popLabel()
{
    delete curPrefixPtr;
    curPrefixPtr = labelStack.back().prefix;
    labelStack.pop_back();
    assert(!labelStack.empty());
}

void
Packet::PrintReqState::printLabels()
{
    if (!labelStack.back().labelPrinted) {
        LabelStack::iterator i = labelStack.begin();
        LabelStack::iterator end = labelStack.end();
        while (i != end) {
            if (!i->labelPrinted) {
                ccprintf(os, "%s%s\n", *(i->prefix), i->label);
                i->labelPrinted = true;
            }
            i++;
        }
    }
}

void
Packet::PrintReqState::printObj(Printable *obj)
{
    printLabels();
    obj->print(os, verbosity, curPrefix());
}
<|endoftext|>


<commit_before>namespace factor
{
    void abort();
}

#ifdef FACTOR_DEBUG
#define FACTOR_ASSERT(condition) ((condition) \
    ? (void)0 \
    : ( \
        ::fprintf(stderr, "assertion \"%s\" failed: file \"%s\", line %d\n", \
            #condition, __FILE__, __LINE__), \
        ::factor::abort() \
    ))
#else
#define FACTOR_ASSERT(condition) ((void)0)
#endif
<commit_msg>VM: Refactor assert.hpp to Factor style<commit_after>namespace factor { void abort(); }

#ifdef FACTOR_DEBUG
#define FACTOR_ASSERT(condition)                                               \
  ((condition)                                                                 \
       ? (void) 0                                                              \
       : (::fprintf(stderr, "assertion \"%s\" failed: file \"%s\", line %d\n", \
                    #condition, __FILE__, __LINE__),                           \
          ::factor::abort()))
#else
#define FACTOR_ASSERT(condition) ((void) 0)
#endif
<|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS aw024 (1.51.50); FILE MERGED 2006/09/08 18:50:33 aw 1.51.50.4: RESYNC: (1.53-1.54); FILE MERGED 2006/05/12 21:09:28 aw 1.51.50.3: RESYNC: (1.52-1.53); FILE MERGED 2005/09/17 17:01:00 aw 1.51.50.2: RESYNC: (1.51-1.52); FILE MERGED 2005/05/19 12:15:13 aw 1.51.50.1: #i39529#<commit_after><|endoftext|>


<commit_before>#include "menu/menu.h"
#include "menu/menu_option.h"
#include "util/bitmap.h"
#include "util/funcs.h"
#include "util/keyboard.h"
#include "util/sound.h"
#include "util/token.h"
#include "util/tokenreader.h"
#include "globals.h"
#include "init.h"
#include "music.h"

#include <queue>

Bitmap *Menu::work = Bitmap::Screen;

static std::string lastPlayed = "";

static std::queue<MenuOption *> backgrounds;

Menu::Menu() : music("")
{
}

void Menu::load(Token *token)throw( LoadException )
{
	try
	{
		if ( *token != "menu" )
			throw LoadException("Not a menu");

		while ( token->hasTokens() )
		{

			Token * tok;
			*token >> tok;
			if ( *tok == "music" )
			{
				// Set music
				*tok >> music;
			}
			else if ( *tok == "background" )
			{
				// Create new background and push onto the stack
				//background = new obj() <-- D:

				backgrounds.push(background);
			}
			else if ( *tok == "menu" )
			{
				// Create a menu option ie options, controller config, adventure, versus, credits, etc
			}
			else
			{
				cout<<"Unhandled menu attribute: "<<endl;
				tok->print(" ");
			}
		}

	}
	catch ( const TokenException & ex )
	{
		// delete current;
		string m( "Menu parse error: " );
		m += ex.getReason();
		throw LoadException( m );
	}
	catch ( const LoadException & ex )
	{
		// delete current;
		throw ex;
	}

	if(backgrounds.empty())throw LoadException("There should be at least one background in the entire menu!");

}

void Menu::load(const std::string &filename)throw( LoadException )
{
	// Must check for initial token, menu
	TokenReader tr( filename );

	// Token * current = tr.readToken();
	Token * token = tr.readToken();
	load(token);
}

void Menu::run() throw(ReturnException)
{

	Keyboard key;

	Bitmap screen_buffer( 320, 240 );
	bool done = false;
	bool endGame = false;

	if(menuOptions.empty())throw ReturnException();
	selectedOption = menuOptions.begin();

	while( !endGame )
	{
		Global::speed_counter = 0;
		Global::second_counter = 0;
		int game_time = 100;

		if(music != "" && music != lastPlayed)
		{
			Music::pause();
			Music::fadeIn( 0.3 );
			Music::loadSong( Util::getDataPath() + music );
			Music::play();
			lastPlayed = music;
		}
		while ( ! done && (*selectedOption)->getState() != MenuOption::Run ){

			bool draw = false;
			key.poll();

			if ( Global::speed_counter > 0 )
			{
				draw = true;
				// Keys

				// Logic
				std::vector <MenuOption *>::iterator b = menuOptions.begin();
				std::vector <MenuOption *>::iterator e = menuOptions.end();
				for(;b!=e;++b)
				{
					(*b)->logic();
				}

				Global::speed_counter = 0;
			}

			while ( Global::second_counter > 0 )
			{
				game_time--;
				Global::second_counter--;
				if ( game_time < 0 )
					game_time = 0;
			}

			if ( draw )
			{
				// Draw
				std::vector <MenuOption *>::iterator b = menuOptions.begin();
				std::vector <MenuOption *>::iterator e = menuOptions.end();
				for(;b!=e;++b)
				{
					(*b)->draw(work);
				}
			}

			while ( Global::speed_counter < 1 )
			{
				Util::rest( 1 );
				key.poll();
			}

			done |= key[ Keyboard::Key_ESC ];
		}

		// do we got an option to run, lets do it
		if((*selectedOption)->getState() == MenuOption::Run)
		{
			(*selectedOption)->run(endGame);
			// Reset it's state
			(*selectedOption)->setState(MenuOption::Selected);
			//  pop out any backgrounds pushed onto the stack reseting it to the old one if applicable
			if(backgrounds.size() >= 2)
			{
				delete backgrounds.front();
				backgrounds.pop();
				background = backgrounds.front();
			}
		}
	}
}

void Menu::setBitmap(Bitmap *bmp)
{
	work = bmp;
}

Menu::~Menu()
{
	// cleanup
	std::vector <MenuOption *>::iterator b = menuOptions.begin();
	std::vector <MenuOption *>::iterator e = menuOptions.end();
	for(;b!=e;++b)
	{
		if((*b))delete (*b);
	}
}

<commit_msg>menu backgrounds<commit_after>#include "menu/menu.h"
#include "menu/menu_option.h"
#include "util/bitmap.h"
#include "util/funcs.h"
#include "util/keyboard.h"
#include "util/sound.h"
#include "util/token.h"
#include "util/tokenreader.h"
#include "globals.h"
#include "init.h"
#include "music.h"

#include <queue>

Bitmap *Menu::work = Bitmap::Screen;

static std::string lastPlayed = "";

static std::queue<MenuOption *> backgrounds;

Menu::Menu() : music("")
{
}

void Menu::load(Token *token)throw( LoadException )
{
	try
	{
		if ( *token != "menu" )
			throw LoadException("Not a menu");

		while ( token->hasTokens() )
		{

			Token * tok;
			*token >> tok;
			if ( *tok == "music" )
			{
				// Set music
				*tok >> music;
			}
			else if ( *tok == "background" )
			{
				// Create new background and push onto the stack
				//background = new obj() <-- D:

				backgrounds.push(background);
			}
			else if ( *tok == "menu" )
			{
				// Create a menu option ie options, controller config, adventure, versus, credits, etc
			}
			else
			{
				cout<<"Unhandled menu attribute: "<<endl;
				tok->print(" ");
			}
		}

	}
	catch ( const TokenException & ex )
	{
		// delete current;
		string m( "Menu parse error: " );
		m += ex.getReason();
		throw LoadException( m );
	}
	catch ( const LoadException & ex )
	{
		// delete current;
		throw ex;
	}

	if(backgrounds.empty())throw LoadException("There should be at least one background in the entire menu!");

}

void Menu::load(const std::string &filename)throw( LoadException )
{
	// Must check for initial token, menu
	TokenReader tr( filename );

	// Token * current = tr.readToken();
	Token * token = tr.readToken();
	load(token);
}

void Menu::run() throw(ReturnException)
{

	Keyboard key;

	Bitmap screen_buffer( 320, 240 );
	bool done = false;
	bool endGame = false;

	if(menuOptions.empty())throw ReturnException();
	selectedOption = menuOptions.begin();

	while( !endGame )
	{
		Global::speed_counter = 0;
		Global::second_counter = 0;
		int game_time = 100;

		if(music != "" && music != lastPlayed)
		{
			Music::pause();
			Music::fadeIn( 0.3 );
			Music::loadSong( Util::getDataPath() + music );
			Music::play();
			lastPlayed = music;
		}
		while ( ! done && (*selectedOption)->getState() != MenuOption::Run ){

			bool draw = false;
			key.poll();

			if ( Global::speed_counter > 0 )
			{
				draw = true;
				// Keys

				// Logic
				background->logic();

				std::vector <MenuOption *>::iterator b = menuOptions.begin();
				std::vector <MenuOption *>::iterator e = menuOptions.end();
				for(;b!=e;++b)
				{
					(*b)->logic();
				}

				Global::speed_counter = 0;
			}

			while ( Global::second_counter > 0 )
			{
				game_time--;
				Global::second_counter--;
				if ( game_time < 0 )
					game_time = 0;
			}

			if ( draw )
			{
				// Draw
				background->draw(work);

				std::vector <MenuOption *>::iterator b = menuOptions.begin();
				std::vector <MenuOption *>::iterator e = menuOptions.end();
				for(;b!=e;++b)
				{
					(*b)->draw(work);
				}
			}

			while ( Global::speed_counter < 1 )
			{
				Util::rest( 1 );
				key.poll();
			}

			done |= key[ Keyboard::Key_ESC ];
		}

		// do we got an option to run, lets do it
		if((*selectedOption)->getState() == MenuOption::Run)
		{
			(*selectedOption)->run(endGame);
			// Reset it's state
			(*selectedOption)->setState(MenuOption::Selected);
			//  pop out any backgrounds pushed onto the stack reseting it to the old one if applicable
			if(backgrounds.size() >= 2)
			{
				delete backgrounds.front();
				backgrounds.pop();
				background = backgrounds.front();
			}
		}
	}
}

void Menu::setBitmap(Bitmap *bmp)
{
	work = bmp;
}

Menu::~Menu()
{
	// cleanup
	std::vector <MenuOption *>::iterator b = menuOptions.begin();
	std::vector <MenuOption *>::iterator e = menuOptions.end();
	for(;b!=e;++b)
	{
		if((*b))delete (*b);
	}

	while(!backgrounds.empty())
	{
		delete backgrounds.front();
		backgrounds.pop();
	}
}

<|endoftext|>


<commit_before>#include "unsafearea.hpp"

#include <QDebug>

UnsafeArea::UnsafeArea(QObject *parent) :
    QObject(parent), mUnsafeTopMargin(0), mUnsafeBottomMargin(0), mUnsafeLeftMargin(0), mUnsafeRightMargin(0), mMyDevice(MyDevice::OTHER)
{

}

// https://bugreports.qt.io/browse/QTBUG-64574
// I O S sizes to detect the device type
// https://stackoverflow.com/questions/46192280/detect-if-the-device-is-iphone-x
// 1136 iPhone 5, 5S, 5C
// 1334 iPhone 6/6S/7/8
// 1920,2208 iPhone 6+/6S+/7+/8+
// 2436 iPhone X, Xs
// 2688 iPhone Xs Max
// 1792 iPhone Xr
// https://developer.apple.com/library/archive/documentation/DeviceInformation/Reference/iOSDeviceCompatibility/Displays/Displays.html
void UnsafeArea::configureDevice(int height, int width, int devicePixelRatio)
{
    qDebug() << "UNSAFE AREAS ? configureDevice - height: " << height << " width: " << width << " devicePixelRatio: " << devicePixelRatio;
    int portraitHeightPixel = 0;
    if(height > width) {
        portraitHeightPixel = height*devicePixelRatio;
    } else {
        portraitHeightPixel = width*devicePixelRatio;
    }
    switch (portraitHeightPixel) {
    case 1136:
        mMyDevice = MyDevice::IPHONE_5_5S_5C;
        qDebug() << "Device detected: " << "IPHONE_5_5S_5C";
        break;
    case 1334:
        mMyDevice = MyDevice::IPHONE_6_6S_7_8;
        qDebug() << "Device detected: " << "IPHONE_6_6S_7_8";
        break;
    case 1920:
    case 2208:
        mMyDevice = MyDevice::IPHONE_6PLUS_6SPLUS_7PLUS_8PLUS;
        qDebug() << "Device detected: " << "IPHONE_6PLUS_6SPLUS_7PLUS_8PLUS";
        break;
    case 2436:
        mMyDevice = MyDevice::IPHONE_X_XS;
        qDebug() << "Device detected: " << "IPHONE_X_XS";
        break;
    case 2688:
        mMyDevice = MyDevice::IPHONE_XSMAX;
        qDebug() << "Device detected: " << "IPHONE_XSMAX";
        break;
    case 1792:
        mMyDevice = MyDevice::IPHONE_XR;
        qDebug() << "Device detected: " << "IPHONE_XR";
        break;
    case 2732:
        mMyDevice = MyDevice::IPADPRO_129;
        qDebug() << "Device detected: " << "IPADPRO 12.9";
        break;
    case 2224:
        mMyDevice = MyDevice::IPADPRO_105;
        qDebug() << "Device detected: " << "IPADPRO 10.5";
        break;
    case 2048:
        mMyDevice = MyDevice::IPADPRO_97_AIR_MINI;
        qDebug() << "Device detected: " << "IPADPRO 9.7, Air 2, Mini4";
        break;
    default:
        mMyDevice = MyDevice::OTHER;
        qDebug() << "Device detected: " << "OTHER";
    }
}

bool UnsafeArea::isKnownIPhone() {
    switch (mMyDevice) {
    case MyDevice::IPHONE_X_XS:
    case MyDevice::IPHONE_XSMAX:
    case MyDevice::IPHONE_XR:
    case MyDevice::IPHONE_5_5S_5C:
    case MyDevice::IPHONE_6_6S_7_8:
    case MyDevice::IPHONE_6PLUS_6SPLUS_7PLUS_8PLUS:
        qDebug() << "isKnownIPhone";
        return true;
    default:
        break;
    }
    return false;
}

bool UnsafeArea::isKnownIPad() {
    switch (mMyDevice) {
    case MyDevice::IPADPRO_97_AIR_MINI:
    case MyDevice::IPADPRO_105:
    case MyDevice::IPADPRO_129:
        qDebug() << "isKnownIPad";
        return true;
    default:
        break;
    }
    return false;
}

void UnsafeArea::orientationChanged(int orientation)
{
    qDebug() << "orientationChanged: " << orientation;
    if(orientation == 1) {
        qDebug() << "PORTRAIT";
        portrait();
    } else if(orientation == 2) {
        qDebug() << "LANDSCAPE LEFT (HomeButton right)";
        landscapeLeft();
    } else if(orientation == 8) {
        qDebug() << "LANDSCAPE RIGHT (HomeButton left)";
        landscapeRight();
    } else {
        qWarning() << "unsupported Orientation: " << orientation;
    }
}

void UnsafeArea::portrait()
{
    switch (mMyDevice) {
    case MyDevice::IPHONE_X_XS:
    case MyDevice::IPHONE_XSMAX:
    case MyDevice::IPHONE_XR:
        setUnsafeTopMargin(24);
        setUnsafeBottomMargin(8);
        setUnsafeLeftMargin(0);
        setUnsafeRightMargin(0);
        break;
    case MyDevice::IPHONE_5_5S_5C:
    case MyDevice::IPHONE_6_6S_7_8:
    case MyDevice::IPHONE_6PLUS_6SPLUS_7PLUS_8PLUS:
        setUnsafeTopMargin(16);
        setUnsafeBottomMargin(0);
        setUnsafeLeftMargin(0);
        setUnsafeRightMargin(0);
        break;
    case MyDevice::IPADPRO_97_AIR_MINI:
    case MyDevice::IPADPRO_105:
    case MyDevice::IPADPRO_129:
        setUnsafeTopMargin(16);
        setUnsafeBottomMargin(0);
        setUnsafeLeftMargin(0);
        setUnsafeRightMargin(0);
        break;
    default:
        break;
    }
}

// HomeButton right
void UnsafeArea::landscapeLeft()
{
    switch (mMyDevice) {
    case MyDevice::IPHONE_X_XS:
    case MyDevice::IPHONE_XSMAX:
    case MyDevice::IPHONE_XR:
        setUnsafeTopMargin(0);
        setUnsafeBottomMargin(8);
        setUnsafeLeftMargin(30);
        setUnsafeRightMargin(0);
        break;
    case MyDevice::IPHONE_5_5S_5C:
    case MyDevice::IPHONE_6_6S_7_8:
    case MyDevice::IPHONE_6PLUS_6SPLUS_7PLUS_8PLUS:
        setUnsafeTopMargin(10);
        setUnsafeBottomMargin(0);
        setUnsafeLeftMargin(0);
        setUnsafeRightMargin(0);
        break;
    case MyDevice::IPADPRO_97_AIR_MINI:
    case MyDevice::IPADPRO_105:
    case MyDevice::IPADPRO_129:
        setUnsafeTopMargin(10);
        setUnsafeBottomMargin(0);
        setUnsafeLeftMargin(0);
        setUnsafeRightMargin(0);
        break;
    default:
        break;
    }
}

// HomeButton left
void UnsafeArea::landscapeRight()
{
    switch (mMyDevice) {
    case MyDevice::IPHONE_X_XS:
    case MyDevice::IPHONE_XSMAX:
    case MyDevice::IPHONE_XR:
        setUnsafeTopMargin(0);
        setUnsafeBottomMargin(8);
        setUnsafeLeftMargin(0);
        setUnsafeRightMargin(30);
        break;
    case MyDevice::IPHONE_5_5S_5C:
    case MyDevice::IPHONE_6_6S_7_8:
    case MyDevice::IPHONE_6PLUS_6SPLUS_7PLUS_8PLUS:
        setUnsafeTopMargin(10);
        setUnsafeBottomMargin(0);
        setUnsafeLeftMargin(0);
        setUnsafeRightMargin(0);
        break;
    case MyDevice::IPADPRO_97_AIR_MINI:
    case MyDevice::IPADPRO_105:
    case MyDevice::IPADPRO_129:
        setUnsafeTopMargin(10);
        setUnsafeBottomMargin(0);
        setUnsafeLeftMargin(0);
        setUnsafeRightMargin(0);
        break;
    default:
        break;
    }
}

int UnsafeArea::unsafeTopMargin() const
{
    return mUnsafeTopMargin;
}

int UnsafeArea::unsafeBottomMargin() const
{
    return mUnsafeBottomMargin;
}

int UnsafeArea::unsafeLeftMargin() const
{
    return mUnsafeLeftMargin;
}

int UnsafeArea::unsafeRightMargin() const
{
    return mUnsafeRightMargin;
}

void UnsafeArea::setUnsafeTopMargin(int unsafeTopMargin)
{
    if (mUnsafeTopMargin == unsafeTopMargin)
        return;
    mUnsafeTopMargin = unsafeTopMargin;
    emit unsafeTopMarginChanged(mUnsafeTopMargin);
}
void UnsafeArea::setUnsafeBottomMargin(int unsafeBottomMargin)
{
    if (mUnsafeBottomMargin == unsafeBottomMargin)
        return;
    mUnsafeBottomMargin = unsafeBottomMargin;
    emit unsafeBottomMarginChanged(mUnsafeBottomMargin);
}
void UnsafeArea::setUnsafeLeftMargin(int unsafeLeftMargin)
{
    if (mUnsafeLeftMargin == unsafeLeftMargin)
        return;
    mUnsafeLeftMargin = unsafeLeftMargin;
    emit unsafeLeftMarginChanged(mUnsafeLeftMargin);
}
void UnsafeArea::setUnsafeRightMargin(int unsafeRightMargin)
{
    if (mUnsafeRightMargin == unsafeRightMargin)
        return;
    mUnsafeRightMargin = unsafeRightMargin;
    emit unsafeRightMarginChanged(mUnsafeRightMargin);
}

UnsafeArea::~UnsafeArea()
{
    // place cleanUp code here
}
<commit_msg>comment<commit_after>#include "unsafearea.hpp"

#include <QDebug>

UnsafeArea::UnsafeArea(QObject *parent) :
    QObject(parent), mUnsafeTopMargin(0), mUnsafeBottomMargin(0), mUnsafeLeftMargin(0), mUnsafeRightMargin(0), mMyDevice(MyDevice::OTHER)
{

}

// https://bugreports.qt.io/browse/QTBUG-64574
// I O S sizes to detect the device type
// https://stackoverflow.com/questions/46192280/detect-if-the-device-is-iphone-x
// 1136 iPhone 5, 5S, 5C
// 1334 iPhone 6/6S/7/8
// 1920,2208 iPhone 6+/6S+/7+/8+
// 2436 iPhone X, Xs
// 2688 iPhone Xs Max
// 1792 iPhone Xr
// https://developer.apple.com/library/archive/documentation/DeviceInformation/Reference/iOSDeviceCompatibility/Displays/Displays.html
// attention: all sizes are UIKIT SIZES not NATIVE PIXEL
void UnsafeArea::configureDevice(int height, int width, int devicePixelRatio)
{
    qDebug() << "UNSAFE AREAS ? configureDevice - height: " << height << " width: " << width << " devicePixelRatio: " << devicePixelRatio;
    int portraitHeightPixel = 0;
    if(height > width) {
        portraitHeightPixel = height*devicePixelRatio;
    } else {
        portraitHeightPixel = width*devicePixelRatio;
    }
    switch (portraitHeightPixel) {
    case 1136:
        mMyDevice = MyDevice::IPHONE_5_5S_5C;
        qDebug() << "Device detected: " << "IPHONE_5_5S_5C";
        break;
    case 1334:
        mMyDevice = MyDevice::IPHONE_6_6S_7_8;
        qDebug() << "Device detected: " << "IPHONE_6_6S_7_8";
        break;
    case 1920:
    case 2208:
        mMyDevice = MyDevice::IPHONE_6PLUS_6SPLUS_7PLUS_8PLUS;
        qDebug() << "Device detected: " << "IPHONE_6PLUS_6SPLUS_7PLUS_8PLUS";
        break;
    case 2436:
        mMyDevice = MyDevice::IPHONE_X_XS;
        qDebug() << "Device detected: " << "IPHONE_X_XS";
        break;
    case 2688:
        mMyDevice = MyDevice::IPHONE_XSMAX;
        qDebug() << "Device detected: " << "IPHONE_XSMAX";
        break;
    case 1792:
        mMyDevice = MyDevice::IPHONE_XR;
        qDebug() << "Device detected: " << "IPHONE_XR";
        break;
    case 2732:
        mMyDevice = MyDevice::IPADPRO_129;
        qDebug() << "Device detected: " << "IPADPRO 12.9";
        break;
    case 2224:
        mMyDevice = MyDevice::IPADPRO_105;
        qDebug() << "Device detected: " << "IPADPRO 10.5";
        break;
    case 2048:
        mMyDevice = MyDevice::IPADPRO_97_AIR_MINI;
        qDebug() << "Device detected: " << "IPADPRO 9.7, Air 2, Mini4";
        break;
    default:
        mMyDevice = MyDevice::OTHER;
        qDebug() << "Device detected: " << "OTHER";
    }
}

bool UnsafeArea::isKnownIPhone() {
    switch (mMyDevice) {
    case MyDevice::IPHONE_X_XS:
    case MyDevice::IPHONE_XSMAX:
    case MyDevice::IPHONE_XR:
    case MyDevice::IPHONE_5_5S_5C:
    case MyDevice::IPHONE_6_6S_7_8:
    case MyDevice::IPHONE_6PLUS_6SPLUS_7PLUS_8PLUS:
        qDebug() << "isKnownIPhone";
        return true;
    default:
        break;
    }
    return false;
}

bool UnsafeArea::isKnownIPad() {
    switch (mMyDevice) {
    case MyDevice::IPADPRO_97_AIR_MINI:
    case MyDevice::IPADPRO_105:
    case MyDevice::IPADPRO_129:
        qDebug() << "isKnownIPad";
        return true;
    default:
        break;
    }
    return false;
}

void UnsafeArea::orientationChanged(int orientation)
{
    qDebug() << "orientationChanged: " << orientation;
    if(orientation == 1) {
        qDebug() << "PORTRAIT";
        portrait();
    } else if(orientation == 2) {
        qDebug() << "LANDSCAPE LEFT (HomeButton right)";
        landscapeLeft();
    } else if(orientation == 8) {
        qDebug() << "LANDSCAPE RIGHT (HomeButton left)";
        landscapeRight();
    } else {
        qWarning() << "unsupported Orientation: " << orientation;
    }
}

void UnsafeArea::portrait()
{
    switch (mMyDevice) {
    case MyDevice::IPHONE_X_XS:
    case MyDevice::IPHONE_XSMAX:
    case MyDevice::IPHONE_XR:
        setUnsafeTopMargin(24);
        setUnsafeBottomMargin(8);
        setUnsafeLeftMargin(0);
        setUnsafeRightMargin(0);
        break;
    case MyDevice::IPHONE_5_5S_5C:
    case MyDevice::IPHONE_6_6S_7_8:
    case MyDevice::IPHONE_6PLUS_6SPLUS_7PLUS_8PLUS:
        setUnsafeTopMargin(16);
        setUnsafeBottomMargin(0);
        setUnsafeLeftMargin(0);
        setUnsafeRightMargin(0);
        break;
    case MyDevice::IPADPRO_97_AIR_MINI:
    case MyDevice::IPADPRO_105:
    case MyDevice::IPADPRO_129:
        setUnsafeTopMargin(16);
        setUnsafeBottomMargin(0);
        setUnsafeLeftMargin(0);
        setUnsafeRightMargin(0);
        break;
    default:
        break;
    }
}

// HomeButton right
void UnsafeArea::landscapeLeft()
{
    switch (mMyDevice) {
    case MyDevice::IPHONE_X_XS:
    case MyDevice::IPHONE_XSMAX:
    case MyDevice::IPHONE_XR:
        setUnsafeTopMargin(0);
        setUnsafeBottomMargin(8);
        setUnsafeLeftMargin(30);
        setUnsafeRightMargin(0);
        break;
    case MyDevice::IPHONE_5_5S_5C:
    case MyDevice::IPHONE_6_6S_7_8:
    case MyDevice::IPHONE_6PLUS_6SPLUS_7PLUS_8PLUS:
        setUnsafeTopMargin(10);
        setUnsafeBottomMargin(0);
        setUnsafeLeftMargin(0);
        setUnsafeRightMargin(0);
        break;
    case MyDevice::IPADPRO_97_AIR_MINI:
    case MyDevice::IPADPRO_105:
    case MyDevice::IPADPRO_129:
        setUnsafeTopMargin(10);
        setUnsafeBottomMargin(0);
        setUnsafeLeftMargin(0);
        setUnsafeRightMargin(0);
        break;
    default:
        break;
    }
}

// HomeButton left
void UnsafeArea::landscapeRight()
{
    switch (mMyDevice) {
    case MyDevice::IPHONE_X_XS:
    case MyDevice::IPHONE_XSMAX:
    case MyDevice::IPHONE_XR:
        setUnsafeTopMargin(0);
        setUnsafeBottomMargin(8);
        setUnsafeLeftMargin(0);
        setUnsafeRightMargin(30);
        break;
    case MyDevice::IPHONE_5_5S_5C:
    case MyDevice::IPHONE_6_6S_7_8:
    case MyDevice::IPHONE_6PLUS_6SPLUS_7PLUS_8PLUS:
        setUnsafeTopMargin(10);
        setUnsafeBottomMargin(0);
        setUnsafeLeftMargin(0);
        setUnsafeRightMargin(0);
        break;
    case MyDevice::IPADPRO_97_AIR_MINI:
    case MyDevice::IPADPRO_105:
    case MyDevice::IPADPRO_129:
        setUnsafeTopMargin(10);
        setUnsafeBottomMargin(0);
        setUnsafeLeftMargin(0);
        setUnsafeRightMargin(0);
        break;
    default:
        break;
    }
}

int UnsafeArea::unsafeTopMargin() const
{
    return mUnsafeTopMargin;
}

int UnsafeArea::unsafeBottomMargin() const
{
    return mUnsafeBottomMargin;
}

int UnsafeArea::unsafeLeftMargin() const
{
    return mUnsafeLeftMargin;
}

int UnsafeArea::unsafeRightMargin() const
{
    return mUnsafeRightMargin;
}

void UnsafeArea::setUnsafeTopMargin(int unsafeTopMargin)
{
    if (mUnsafeTopMargin == unsafeTopMargin)
        return;
    mUnsafeTopMargin = unsafeTopMargin;
    emit unsafeTopMarginChanged(mUnsafeTopMargin);
}
void UnsafeArea::setUnsafeBottomMargin(int unsafeBottomMargin)
{
    if (mUnsafeBottomMargin == unsafeBottomMargin)
        return;
    mUnsafeBottomMargin = unsafeBottomMargin;
    emit unsafeBottomMarginChanged(mUnsafeBottomMargin);
}
void UnsafeArea::setUnsafeLeftMargin(int unsafeLeftMargin)
{
    if (mUnsafeLeftMargin == unsafeLeftMargin)
        return;
    mUnsafeLeftMargin = unsafeLeftMargin;
    emit unsafeLeftMarginChanged(mUnsafeLeftMargin);
}
void UnsafeArea::setUnsafeRightMargin(int unsafeRightMargin)
{
    if (mUnsafeRightMargin == unsafeRightMargin)
        return;
    mUnsafeRightMargin = unsafeRightMargin;
    emit unsafeRightMarginChanged(mUnsafeRightMargin);
}

UnsafeArea::~UnsafeArea()
{
    // place cleanUp code here
}
<|endoftext|>